Add new VideoConference module for muting mic/cam (#11798)
* add new VideoConference module for muting mic/cam Co-authored-by: PrzemyslawTusinski <61138537+PrzemyslawTusinski@users.noreply.github.com> Co-authored-by: Niels Laute <niels.laute@live.nl>
150
.github/actions/spell-check/expect.txt
vendored
@ -46,6 +46,7 @@ Aissue
|
|||||||
akamaihd
|
akamaihd
|
||||||
ALarger
|
ALarger
|
||||||
alekhyareddy
|
alekhyareddy
|
||||||
|
alignas
|
||||||
ALIGNLEFT
|
ALIGNLEFT
|
||||||
ALLAPPS
|
ALLAPPS
|
||||||
Alloc
|
Alloc
|
||||||
@ -142,9 +143,11 @@ autoplay
|
|||||||
Autorun
|
Autorun
|
||||||
AUTOSIZECOLUMNS
|
AUTOSIZECOLUMNS
|
||||||
autoupdate
|
autoupdate
|
||||||
awakeversion
|
|
||||||
AValid
|
AValid
|
||||||
|
avialable
|
||||||
|
awakeversion
|
||||||
AWAYMODE
|
AWAYMODE
|
||||||
|
AYUV
|
||||||
azurecr
|
azurecr
|
||||||
azurewebsites
|
azurewebsites
|
||||||
backend
|
backend
|
||||||
@ -185,6 +188,7 @@ bms
|
|||||||
BNumber
|
BNumber
|
||||||
Bokm
|
Bokm
|
||||||
BOKMAL
|
BOKMAL
|
||||||
|
boolalpha
|
||||||
Bools
|
Bools
|
||||||
bootstrapper
|
bootstrapper
|
||||||
Bopomofo
|
Bopomofo
|
||||||
@ -213,6 +217,7 @@ BValue
|
|||||||
bytearray
|
bytearray
|
||||||
callbackptr
|
callbackptr
|
||||||
callhistory
|
callhistory
|
||||||
|
Camer
|
||||||
Cangjie
|
Cangjie
|
||||||
cangjieime
|
cangjieime
|
||||||
CANRENAME
|
CANRENAME
|
||||||
@ -285,6 +290,7 @@ CMock
|
|||||||
CMONITORS
|
CMONITORS
|
||||||
cmyk
|
cmyk
|
||||||
cnt
|
cnt
|
||||||
|
coc
|
||||||
coclass
|
coclass
|
||||||
codebase
|
codebase
|
||||||
codecvt
|
codecvt
|
||||||
@ -293,9 +299,10 @@ codereview
|
|||||||
Codespaces
|
Codespaces
|
||||||
COINIT
|
COINIT
|
||||||
colorconv
|
colorconv
|
||||||
|
colorfilter
|
||||||
colorhistory
|
colorhistory
|
||||||
colorhistorylimit
|
colorhistorylimit
|
||||||
colorfilter
|
COLORKEY
|
||||||
colorpicker
|
colorpicker
|
||||||
COLORREF
|
COLORREF
|
||||||
colorscheme
|
colorscheme
|
||||||
@ -429,6 +436,7 @@ dcomp
|
|||||||
DComposition
|
DComposition
|
||||||
ddd
|
ddd
|
||||||
ddee
|
ddee
|
||||||
|
ddf
|
||||||
Deact
|
Deact
|
||||||
declspec
|
declspec
|
||||||
decltype
|
decltype
|
||||||
@ -472,11 +480,14 @@ devenum
|
|||||||
deviceencryption
|
deviceencryption
|
||||||
devicemanagenent
|
devicemanagenent
|
||||||
DEVMON
|
DEVMON
|
||||||
|
devpkey
|
||||||
|
DEVSOURCE
|
||||||
DFactory
|
DFactory
|
||||||
DHCP
|
DHCP
|
||||||
Dialpad
|
Dialpad
|
||||||
diffing
|
diffing
|
||||||
difftime
|
difftime
|
||||||
|
DIIRFLAG
|
||||||
dimm
|
dimm
|
||||||
directaccess
|
directaccess
|
||||||
dirname
|
dirname
|
||||||
@ -489,6 +500,7 @@ Displayandhidethedesktop
|
|||||||
DISPLAYCHANGE
|
DISPLAYCHANGE
|
||||||
displayname
|
displayname
|
||||||
divyan
|
divyan
|
||||||
|
djsoref
|
||||||
DLACTIVEXCTLS
|
DLACTIVEXCTLS
|
||||||
DLCONTROL
|
DLCONTROL
|
||||||
dlg
|
dlg
|
||||||
@ -501,9 +513,10 @@ dllexport
|
|||||||
dllhost
|
dllhost
|
||||||
dllmain
|
dllmain
|
||||||
DNLEN
|
DNLEN
|
||||||
docsmsft
|
|
||||||
Dns
|
Dns
|
||||||
|
docsmsft
|
||||||
doctype
|
doctype
|
||||||
|
dogancelik
|
||||||
domainlexicon
|
domainlexicon
|
||||||
DONTVALIDATEPATH
|
DONTVALIDATEPATH
|
||||||
dotnet
|
dotnet
|
||||||
@ -531,7 +544,11 @@ dupenv
|
|||||||
dutil
|
dutil
|
||||||
DVASPECT
|
DVASPECT
|
||||||
DVASPECTINFO
|
DVASPECTINFO
|
||||||
|
DVH
|
||||||
|
DVHD
|
||||||
DVR
|
DVR
|
||||||
|
DVSD
|
||||||
|
DVSL
|
||||||
DVTARGETDEVICE
|
DVTARGETDEVICE
|
||||||
DWindow
|
DWindow
|
||||||
DWINRT
|
DWINRT
|
||||||
@ -550,6 +567,8 @@ dword
|
|||||||
dworigin
|
dworigin
|
||||||
dwrite
|
dwrite
|
||||||
dxgi
|
dxgi
|
||||||
|
dxgiformat
|
||||||
|
dxguid
|
||||||
dynamiclock
|
dynamiclock
|
||||||
EABF
|
EABF
|
||||||
EAC
|
EAC
|
||||||
@ -602,6 +621,7 @@ efa
|
|||||||
efgh
|
efgh
|
||||||
EFile
|
EFile
|
||||||
egistry
|
egistry
|
||||||
|
elif
|
||||||
elseif
|
elseif
|
||||||
emailandaccounts
|
emailandaccounts
|
||||||
Emoji
|
Emoji
|
||||||
@ -610,6 +630,7 @@ ENABLEDPOPUP
|
|||||||
endforeach
|
endforeach
|
||||||
endif
|
endif
|
||||||
endl
|
endl
|
||||||
|
endpointvolume
|
||||||
endregion
|
endregion
|
||||||
Enque
|
Enque
|
||||||
ENTERSIZEMOVE
|
ENTERSIZEMOVE
|
||||||
@ -662,7 +683,7 @@ exlist
|
|||||||
EXPCMDFLAGS
|
EXPCMDFLAGS
|
||||||
EXPCMDSTATE
|
EXPCMDSTATE
|
||||||
explr
|
explr
|
||||||
Expr
|
expr
|
||||||
exsb
|
exsb
|
||||||
EXSEL
|
EXSEL
|
||||||
exstyle
|
exstyle
|
||||||
@ -679,6 +700,7 @@ FANCYZONESDRAWLAYOUTTEST
|
|||||||
FANCYZONESEDITOR
|
FANCYZONESEDITOR
|
||||||
Farbraum
|
Farbraum
|
||||||
FARPROC
|
FARPROC
|
||||||
|
fdw
|
||||||
feimage
|
feimage
|
||||||
ffcd
|
ffcd
|
||||||
FFDDDDDD
|
FFDDDDDD
|
||||||
@ -690,13 +712,16 @@ FILEFLAGS
|
|||||||
FILEFLAGSMASK
|
FILEFLAGSMASK
|
||||||
FILEOP
|
FILEOP
|
||||||
FILEOS
|
FILEOS
|
||||||
|
filepath
|
||||||
FILESUBTYPE
|
FILESUBTYPE
|
||||||
FILESYSPATH
|
FILESYSPATH
|
||||||
filesystem
|
filesystem
|
||||||
FILETIME
|
FILETIME
|
||||||
FILETYPE
|
FILETYPE
|
||||||
FILEVERSION
|
FILEVERSION
|
||||||
|
Filtergraph
|
||||||
Filterkeyboard
|
Filterkeyboard
|
||||||
|
Filterx
|
||||||
finalizer
|
finalizer
|
||||||
findfast
|
findfast
|
||||||
findmydevice
|
findmydevice
|
||||||
@ -705,6 +730,7 @@ FIXEDFILEINFO
|
|||||||
FLASHZONES
|
FLASHZONES
|
||||||
FLASHZONESONQUICKSWITCH
|
FLASHZONESONQUICKSWITCH
|
||||||
Fle
|
Fle
|
||||||
|
flt
|
||||||
fluentui
|
fluentui
|
||||||
flyout
|
flyout
|
||||||
fmtlib
|
fmtlib
|
||||||
@ -726,6 +752,7 @@ FTYPE
|
|||||||
FULLNAME
|
FULLNAME
|
||||||
fullscreen
|
fullscreen
|
||||||
func
|
func
|
||||||
|
Functiondiscoverykeys
|
||||||
fwlink
|
fwlink
|
||||||
fwrite
|
fwrite
|
||||||
fxcop
|
fxcop
|
||||||
@ -736,6 +763,7 @@ Gamebar
|
|||||||
gamedvr
|
gamedvr
|
||||||
gamemode
|
gamemode
|
||||||
GBs
|
GBs
|
||||||
|
GCLP
|
||||||
gcnew
|
gcnew
|
||||||
gdi
|
gdi
|
||||||
gdiplus
|
gdiplus
|
||||||
@ -778,8 +806,10 @@ Hashset
|
|||||||
hbitmap
|
hbitmap
|
||||||
hbmp
|
hbmp
|
||||||
hbr
|
hbr
|
||||||
|
HBRBACKGROUND
|
||||||
HBRUSH
|
HBRUSH
|
||||||
hcblack
|
hcblack
|
||||||
|
HCERTSTORE
|
||||||
hcwhite
|
hcwhite
|
||||||
hdc
|
hdc
|
||||||
HDF
|
HDF
|
||||||
@ -791,6 +821,8 @@ hdrop
|
|||||||
HDS
|
HDS
|
||||||
HEB
|
HEB
|
||||||
helptext
|
helptext
|
||||||
|
HEVC
|
||||||
|
hfile
|
||||||
HGLOBAL
|
HGLOBAL
|
||||||
hhk
|
hhk
|
||||||
HHmmss
|
HHmmss
|
||||||
@ -865,11 +897,13 @@ IApp
|
|||||||
IApplication
|
IApplication
|
||||||
IAppx
|
IAppx
|
||||||
IAsync
|
IAsync
|
||||||
|
IAudio
|
||||||
IAuto
|
IAuto
|
||||||
IBackground
|
IBackground
|
||||||
IBase
|
IBase
|
||||||
IBeam
|
IBeam
|
||||||
IBind
|
IBind
|
||||||
|
ICapture
|
||||||
icase
|
icase
|
||||||
iccex
|
iccex
|
||||||
ICEBLUE
|
ICEBLUE
|
||||||
@ -922,9 +956,11 @@ IFancy
|
|||||||
ifdef
|
ifdef
|
||||||
IFeatures
|
IFeatures
|
||||||
IFile
|
IFile
|
||||||
|
IFilter
|
||||||
ifndef
|
ifndef
|
||||||
IFolder
|
IFolder
|
||||||
ifstream
|
ifstream
|
||||||
|
IGraph
|
||||||
iid
|
iid
|
||||||
IImage
|
IImage
|
||||||
Iindex
|
Iindex
|
||||||
@ -944,8 +980,11 @@ imagingdevices
|
|||||||
IMain
|
IMain
|
||||||
IMarkdown
|
IMarkdown
|
||||||
ime
|
ime
|
||||||
|
IMedia
|
||||||
|
IMem
|
||||||
imeutil
|
imeutil
|
||||||
img
|
img
|
||||||
|
iminstall
|
||||||
IMoniker
|
IMoniker
|
||||||
IMonitor
|
IMonitor
|
||||||
IMouse
|
IMouse
|
||||||
@ -1002,6 +1041,7 @@ IObject
|
|||||||
iobjectwithsitesetsite
|
iobjectwithsitesetsite
|
||||||
IOle
|
IOle
|
||||||
iolewindowcontextsensitivehelp
|
iolewindowcontextsensitivehelp
|
||||||
|
iomanip
|
||||||
iostream
|
iostream
|
||||||
IPackage
|
IPackage
|
||||||
IPath
|
IPath
|
||||||
@ -1023,6 +1063,7 @@ IProperty
|
|||||||
IPublic
|
IPublic
|
||||||
IQuery
|
IQuery
|
||||||
IRead
|
IRead
|
||||||
|
IReference
|
||||||
IReflect
|
IReflect
|
||||||
IRegistered
|
IRegistered
|
||||||
IRegistration
|
IRegistration
|
||||||
@ -1055,6 +1096,7 @@ ith
|
|||||||
IThrottled
|
IThrottled
|
||||||
IThumbnail
|
IThumbnail
|
||||||
ITrigger
|
ITrigger
|
||||||
|
itsme
|
||||||
IUI
|
IUI
|
||||||
IUnknown
|
IUnknown
|
||||||
IUri
|
IUri
|
||||||
@ -1065,9 +1107,11 @@ IVector
|
|||||||
IView
|
IView
|
||||||
IVirtual
|
IVirtual
|
||||||
IWeb
|
IWeb
|
||||||
IXml
|
IWIC
|
||||||
IWindows
|
IWindows
|
||||||
|
IXml
|
||||||
ixx
|
ixx
|
||||||
|
IYUV
|
||||||
IZone
|
IZone
|
||||||
IZoom
|
IZoom
|
||||||
JArray
|
JArray
|
||||||
@ -1116,17 +1160,17 @@ Keytool
|
|||||||
keyup
|
keyup
|
||||||
KILLFOCUS
|
KILLFOCUS
|
||||||
Knownfolders
|
Knownfolders
|
||||||
|
KSPROPERTY
|
||||||
Kybd
|
Kybd
|
||||||
LAlt
|
LAlt
|
||||||
Lambson
|
Lambson
|
||||||
lamotile
|
lamotile
|
||||||
langword
|
langword
|
||||||
langword
|
|
||||||
Lastdevice
|
Lastdevice
|
||||||
LASTEXITCODE
|
LASTEXITCODE
|
||||||
Laute
|
|
||||||
launchfaceenrollment
|
launchfaceenrollment
|
||||||
launchfingerprintenrollment
|
launchfingerprintenrollment
|
||||||
|
Laute
|
||||||
laute
|
laute
|
||||||
laviusmotileng
|
laviusmotileng
|
||||||
LAYOUTRTL
|
LAYOUTRTL
|
||||||
@ -1140,9 +1184,11 @@ Lclean
|
|||||||
LCONTROL
|
LCONTROL
|
||||||
LCtrl
|
LCtrl
|
||||||
Ldone
|
Ldone
|
||||||
|
ldx
|
||||||
LEFTSCROLLBAR
|
LEFTSCROLLBAR
|
||||||
lego
|
lego
|
||||||
len
|
len
|
||||||
|
LEQ
|
||||||
LError
|
LError
|
||||||
Lessthan
|
Lessthan
|
||||||
LEVELID
|
LEVELID
|
||||||
@ -1166,6 +1212,7 @@ LINQTo
|
|||||||
Linux
|
Linux
|
||||||
listbox
|
listbox
|
||||||
listview
|
listview
|
||||||
|
lld
|
||||||
llkhf
|
llkhf
|
||||||
Llvm
|
Llvm
|
||||||
lmcons
|
lmcons
|
||||||
@ -1246,6 +1293,7 @@ MAINICON
|
|||||||
Mainwindow
|
Mainwindow
|
||||||
majortype
|
majortype
|
||||||
makeappx
|
makeappx
|
||||||
|
makecab
|
||||||
MAKEINTRESOURCE
|
MAKEINTRESOURCE
|
||||||
MAKEINTRESOURCEW
|
MAKEINTRESOURCEW
|
||||||
MAKELPARAM
|
MAKELPARAM
|
||||||
@ -1264,6 +1312,7 @@ MATCHMODE
|
|||||||
MAXIMIZEBOX
|
MAXIMIZEBOX
|
||||||
MAXSHORTCUTSIZE
|
MAXSHORTCUTSIZE
|
||||||
maxversiontested
|
maxversiontested
|
||||||
|
MBs
|
||||||
MBUTTON
|
MBUTTON
|
||||||
MBUTTONDBLCLK
|
MBUTTONDBLCLK
|
||||||
MBUTTONDOWN
|
MBUTTONDOWN
|
||||||
@ -1273,7 +1322,7 @@ MDICHILD
|
|||||||
MDL
|
MDL
|
||||||
mdpreviewhandler
|
mdpreviewhandler
|
||||||
MEDIASUBTYPE
|
MEDIASUBTYPE
|
||||||
MEDIATYPE
|
mediatype
|
||||||
Melman
|
Melman
|
||||||
memcpy
|
memcpy
|
||||||
memset
|
memset
|
||||||
@ -1285,8 +1334,17 @@ messageboxes
|
|||||||
METACHARSET
|
METACHARSET
|
||||||
metadata
|
metadata
|
||||||
metafile
|
metafile
|
||||||
|
mfapi
|
||||||
mfc
|
mfc
|
||||||
mfcribbon
|
mfcribbon
|
||||||
|
mfidl
|
||||||
|
mfobjects
|
||||||
|
mfplat
|
||||||
|
mfreadwrite
|
||||||
|
Mfsensorgroup
|
||||||
|
mftransform
|
||||||
|
mfuuid
|
||||||
|
mic
|
||||||
microsoft
|
microsoft
|
||||||
Midl
|
Midl
|
||||||
mii
|
mii
|
||||||
@ -1299,10 +1357,12 @@ miniz
|
|||||||
minlevel
|
minlevel
|
||||||
MINMAXINFO
|
MINMAXINFO
|
||||||
Miracast
|
Miracast
|
||||||
|
mirophone
|
||||||
MJPG
|
MJPG
|
||||||
mkdir
|
mkdir
|
||||||
Mlcfg
|
Mlcfg
|
||||||
MLogo
|
MLogo
|
||||||
|
mmdeviceapi
|
||||||
MMI
|
MMI
|
||||||
Mmsys
|
Mmsys
|
||||||
mobilehotspot
|
mobilehotspot
|
||||||
@ -1369,6 +1429,7 @@ mutex
|
|||||||
mutexes
|
mutexes
|
||||||
muxc
|
muxc
|
||||||
mvvm
|
mvvm
|
||||||
|
myfile
|
||||||
MYICON
|
MYICON
|
||||||
NAMECHANGE
|
NAMECHANGE
|
||||||
nameof
|
nameof
|
||||||
@ -1412,6 +1473,7 @@ netsh
|
|||||||
netstandard
|
netstandard
|
||||||
Neue
|
Neue
|
||||||
newcolor
|
newcolor
|
||||||
|
newdev
|
||||||
newitem
|
newitem
|
||||||
newpath
|
newpath
|
||||||
newrow
|
newrow
|
||||||
@ -1421,6 +1483,7 @@ niels
|
|||||||
nielslaute
|
nielslaute
|
||||||
NIF
|
NIF
|
||||||
nightlight
|
nightlight
|
||||||
|
nitroin
|
||||||
NLD
|
NLD
|
||||||
nlog
|
nlog
|
||||||
NLSTEXT
|
NLSTEXT
|
||||||
@ -1438,6 +1501,7 @@ nodoc
|
|||||||
noexcept
|
noexcept
|
||||||
NOFRAMES
|
NOFRAMES
|
||||||
NOINHERITLAYOUT
|
NOINHERITLAYOUT
|
||||||
|
NOINTERFACE
|
||||||
NOLINKINFO
|
NOLINKINFO
|
||||||
NOMINMAX
|
NOMINMAX
|
||||||
NOMOVE
|
NOMOVE
|
||||||
@ -1521,6 +1585,7 @@ OPTIMIZEFORINVOKE
|
|||||||
optin
|
optin
|
||||||
optionalfeatures
|
optionalfeatures
|
||||||
OPTIONSGROUP
|
OPTIONSGROUP
|
||||||
|
ORAW
|
||||||
ORPHANEDDIALOGTITLE
|
ORPHANEDDIALOGTITLE
|
||||||
oss
|
oss
|
||||||
ostr
|
ostr
|
||||||
@ -1532,6 +1597,7 @@ otheroptions
|
|||||||
otherusers
|
otherusers
|
||||||
OUTOFCONTEXT
|
OUTOFCONTEXT
|
||||||
OUTOFMEMORY
|
OUTOFMEMORY
|
||||||
|
outpin
|
||||||
Outptr
|
Outptr
|
||||||
outputtype
|
outputtype
|
||||||
outro
|
outro
|
||||||
@ -1553,6 +1619,7 @@ PARENTRELATIVEPARSING
|
|||||||
parray
|
parray
|
||||||
PARTIALCONFIRMATIONDIALOGTITLE
|
PARTIALCONFIRMATIONDIALOGTITLE
|
||||||
pathcch
|
pathcch
|
||||||
|
PAUDIO
|
||||||
pbc
|
pbc
|
||||||
Pbgra
|
Pbgra
|
||||||
pcb
|
pcb
|
||||||
@ -1593,6 +1660,7 @@ Pipelinhttps
|
|||||||
pipename
|
pipename
|
||||||
pitem
|
pitem
|
||||||
PKBDLLHOOKSTRUCT
|
PKBDLLHOOKSTRUCT
|
||||||
|
PKEY
|
||||||
placeholders
|
placeholders
|
||||||
plib
|
plib
|
||||||
PLK
|
PLK
|
||||||
@ -1611,6 +1679,7 @@ popd
|
|||||||
popup
|
popup
|
||||||
POPUPWINDOW
|
POPUPWINDOW
|
||||||
posix
|
posix
|
||||||
|
Postion
|
||||||
powerappscds
|
powerappscds
|
||||||
powercfg
|
powercfg
|
||||||
powerlauncher
|
powerlauncher
|
||||||
@ -1626,6 +1695,7 @@ powertoyswiki
|
|||||||
Powrprof
|
Powrprof
|
||||||
ppenum
|
ppenum
|
||||||
ppidl
|
ppidl
|
||||||
|
ppmt
|
||||||
pprm
|
pprm
|
||||||
pproc
|
pproc
|
||||||
ppsi
|
ppsi
|
||||||
@ -1643,11 +1713,13 @@ Prefixer
|
|||||||
Preinstalled
|
Preinstalled
|
||||||
preload
|
preload
|
||||||
PREMULTIPLIED
|
PREMULTIPLIED
|
||||||
|
preperty
|
||||||
prevhost
|
prevhost
|
||||||
previewer
|
previewer
|
||||||
PREVIEWGROUP
|
PREVIEWGROUP
|
||||||
PREVIEWHANDLERFRAMEINFO
|
PREVIEWHANDLERFRAMEINFO
|
||||||
previewpane
|
previewpane
|
||||||
|
previouscamera
|
||||||
PREVIOUSVERSIONSINSTALLED
|
PREVIOUSVERSIONSINSTALLED
|
||||||
prevpane
|
prevpane
|
||||||
prgms
|
prgms
|
||||||
@ -1664,6 +1736,7 @@ PROGRAMFILES
|
|||||||
progressbar
|
progressbar
|
||||||
Proj
|
Proj
|
||||||
projectname
|
projectname
|
||||||
|
PROPBAG
|
||||||
propkey
|
propkey
|
||||||
propvarutil
|
propvarutil
|
||||||
prpui
|
prpui
|
||||||
@ -1676,6 +1749,7 @@ psfgao
|
|||||||
Psr
|
Psr
|
||||||
psrm
|
psrm
|
||||||
psrree
|
psrree
|
||||||
|
pstr
|
||||||
pstream
|
pstream
|
||||||
pstrm
|
pstrm
|
||||||
psz
|
psz
|
||||||
@ -1693,6 +1767,7 @@ PVOID
|
|||||||
pwa
|
pwa
|
||||||
pwcs
|
pwcs
|
||||||
PWSTR
|
PWSTR
|
||||||
|
pwsz
|
||||||
pwtd
|
pwtd
|
||||||
qianlifeng
|
qianlifeng
|
||||||
qit
|
qit
|
||||||
@ -1738,20 +1813,27 @@ rectp
|
|||||||
rects
|
rects
|
||||||
recyclebin
|
recyclebin
|
||||||
redirectedfrom
|
redirectedfrom
|
||||||
|
reencode
|
||||||
|
reencoded
|
||||||
refactor
|
refactor
|
||||||
refactoring
|
refactoring
|
||||||
REFCLSID
|
REFCLSID
|
||||||
refcount
|
refcount
|
||||||
|
REFGUID
|
||||||
REFIID
|
REFIID
|
||||||
REGCLS
|
REGCLS
|
||||||
regedit
|
regedit
|
||||||
regex
|
regex
|
||||||
|
REGFILTER
|
||||||
|
REGFILTERPINS
|
||||||
regionformatting
|
regionformatting
|
||||||
regionlanguage
|
regionlanguage
|
||||||
REGISTERCLASSFAILED
|
REGISTERCLASSFAILED
|
||||||
Registery
|
Registery
|
||||||
registrypath
|
registrypath
|
||||||
regkey
|
regkey
|
||||||
|
REGPINTYPES
|
||||||
|
regsvr
|
||||||
reimplementing
|
reimplementing
|
||||||
reloadable
|
reloadable
|
||||||
Remapper
|
Remapper
|
||||||
@ -1803,13 +1885,14 @@ RKey
|
|||||||
RMENU
|
RMENU
|
||||||
RNumber
|
RNumber
|
||||||
roadmap
|
roadmap
|
||||||
|
robocopy
|
||||||
Roboto
|
Roboto
|
||||||
roslyn
|
roslyn
|
||||||
royvou
|
royvou
|
||||||
Rpc
|
Rpc
|
||||||
RRF
|
RRF
|
||||||
rshift
|
|
||||||
RSHIFT
|
RSHIFT
|
||||||
|
rshift
|
||||||
Rsp
|
Rsp
|
||||||
rst
|
rst
|
||||||
Rstrtmgr
|
Rstrtmgr
|
||||||
@ -1859,6 +1942,7 @@ SEARCHFOR
|
|||||||
SEARCHREPLACEGROUP
|
SEARCHREPLACEGROUP
|
||||||
searchterm
|
searchterm
|
||||||
Secur
|
Secur
|
||||||
|
seekg
|
||||||
Segoe
|
Segoe
|
||||||
Sekan
|
Sekan
|
||||||
SENDCHANGE
|
SENDCHANGE
|
||||||
@ -1904,8 +1988,8 @@ Shl
|
|||||||
shldisp
|
shldisp
|
||||||
shlobj
|
shlobj
|
||||||
shlwapi
|
shlwapi
|
||||||
|
shmem
|
||||||
shobjidl
|
shobjidl
|
||||||
shortsplit
|
|
||||||
SHORTCUTATLEAST
|
SHORTCUTATLEAST
|
||||||
shortcutcontrol
|
shortcutcontrol
|
||||||
Shortcutguide
|
Shortcutguide
|
||||||
@ -1917,6 +2001,7 @@ SHORTCUTSTARTWITHMODIFIER
|
|||||||
Shortcuttool
|
Shortcuttool
|
||||||
shortdate
|
shortdate
|
||||||
SHORTPATH
|
SHORTPATH
|
||||||
|
shortsplit
|
||||||
showcolorname
|
showcolorname
|
||||||
SHOWDEFAULT
|
SHOWDEFAULT
|
||||||
SHOWELEVATIONPROMPT
|
SHOWELEVATIONPROMPT
|
||||||
@ -1945,6 +2030,7 @@ SIZENESW
|
|||||||
SIZENS
|
SIZENS
|
||||||
SIZENWSE
|
SIZENWSE
|
||||||
sizeof
|
sizeof
|
||||||
|
sizeread
|
||||||
SIZEWE
|
SIZEWE
|
||||||
sketchapp
|
sketchapp
|
||||||
SKIPOWNPROCESS
|
SKIPOWNPROCESS
|
||||||
@ -1974,6 +2060,7 @@ spesi
|
|||||||
splitwstring
|
splitwstring
|
||||||
sppd
|
sppd
|
||||||
sppre
|
sppre
|
||||||
|
sprintf
|
||||||
spsi
|
spsi
|
||||||
spsia
|
spsia
|
||||||
spsrif
|
spsrif
|
||||||
@ -2031,6 +2118,7 @@ storagesense
|
|||||||
stoul
|
stoul
|
||||||
stoull
|
stoull
|
||||||
strcmp
|
strcmp
|
||||||
|
streampos
|
||||||
strftime
|
strftime
|
||||||
Stringified
|
Stringified
|
||||||
Stringify
|
Stringify
|
||||||
@ -2057,8 +2145,8 @@ surfacehub
|
|||||||
sut
|
sut
|
||||||
SVE
|
SVE
|
||||||
svg
|
svg
|
||||||
SVGIO
|
|
||||||
SVGIn
|
SVGIn
|
||||||
|
SVGIO
|
||||||
svgpreviewhandler
|
svgpreviewhandler
|
||||||
SWC
|
SWC
|
||||||
SWFO
|
SWFO
|
||||||
@ -2068,6 +2156,7 @@ swprintf
|
|||||||
SWRESTORE
|
SWRESTORE
|
||||||
SYMED
|
SYMED
|
||||||
SYMOPT
|
SYMOPT
|
||||||
|
SYNCMFT
|
||||||
SYNCPAINT
|
SYNCPAINT
|
||||||
sys
|
sys
|
||||||
SYSCHAR
|
SYSCHAR
|
||||||
@ -2083,9 +2172,9 @@ syslog
|
|||||||
SYSMENU
|
SYSMENU
|
||||||
systemd
|
systemd
|
||||||
SYSTEMTIME
|
SYSTEMTIME
|
||||||
Tadele
|
|
||||||
sz
|
sz
|
||||||
tabletmode
|
tabletmode
|
||||||
|
Tadele
|
||||||
tadele
|
tadele
|
||||||
Tahoma
|
Tahoma
|
||||||
talenthrcore
|
talenthrcore
|
||||||
@ -2111,6 +2200,7 @@ tchar
|
|||||||
tcscpy
|
tcscpy
|
||||||
TCustom
|
TCustom
|
||||||
TDevice
|
TDevice
|
||||||
|
tellg
|
||||||
Templated
|
Templated
|
||||||
templatenamespace
|
templatenamespace
|
||||||
Temporarilypeekatthedesktop
|
Temporarilypeekatthedesktop
|
||||||
@ -2132,8 +2222,8 @@ THISCOMPONENT
|
|||||||
thre
|
thre
|
||||||
tif
|
tif
|
||||||
TILEDWINDOW
|
TILEDWINDOW
|
||||||
timediff
|
|
||||||
timedate
|
timedate
|
||||||
|
timediff
|
||||||
Timeline
|
Timeline
|
||||||
TIMERID
|
TIMERID
|
||||||
timeunion
|
timeunion
|
||||||
@ -2143,6 +2233,7 @@ TLayout
|
|||||||
tlb
|
tlb
|
||||||
tlbimp
|
tlbimp
|
||||||
tmp
|
tmp
|
||||||
|
TMPVAR
|
||||||
TNP
|
TNP
|
||||||
todo
|
todo
|
||||||
toggleswitch
|
toggleswitch
|
||||||
@ -2161,12 +2252,15 @@ towlower
|
|||||||
towupper
|
towupper
|
||||||
tracelogging
|
tracelogging
|
||||||
traies
|
traies
|
||||||
|
transcoded
|
||||||
|
transparrent
|
||||||
TRAYMOUSEMESSAGE
|
TRAYMOUSEMESSAGE
|
||||||
TRK
|
TRK
|
||||||
trl
|
trl
|
||||||
trueplay
|
trueplay
|
||||||
truetype
|
truetype
|
||||||
trunc
|
trunc
|
||||||
|
tspan
|
||||||
TStr
|
TStr
|
||||||
tsx
|
tsx
|
||||||
TYMED
|
TYMED
|
||||||
@ -2192,8 +2286,10 @@ UIPI
|
|||||||
UIs
|
UIs
|
||||||
UITo
|
UITo
|
||||||
ULARGE
|
ULARGE
|
||||||
|
ulazy
|
||||||
ULLONG
|
ULLONG
|
||||||
ulong
|
ulong
|
||||||
|
ULONGLONG
|
||||||
umd
|
umd
|
||||||
unchecks
|
unchecks
|
||||||
uncomment
|
uncomment
|
||||||
@ -2222,6 +2318,7 @@ unknwn
|
|||||||
UNLEN
|
UNLEN
|
||||||
unlicense
|
unlicense
|
||||||
Unmap
|
Unmap
|
||||||
|
unmute
|
||||||
UNORM
|
UNORM
|
||||||
unregister
|
unregister
|
||||||
unregistering
|
unregistering
|
||||||
@ -2256,16 +2353,20 @@ uuidof
|
|||||||
uwp
|
uwp
|
||||||
UWPUI
|
UWPUI
|
||||||
uxtheme
|
uxtheme
|
||||||
|
UYVY
|
||||||
validmodulename
|
validmodulename
|
||||||
vcamp
|
vcamp
|
||||||
vccorlib
|
vccorlib
|
||||||
|
vcdl
|
||||||
VCINSTALLDIR
|
VCINSTALLDIR
|
||||||
|
vcm
|
||||||
vcomp
|
vcomp
|
||||||
vcredist
|
vcredist
|
||||||
VCRT
|
VCRT
|
||||||
vcruntime
|
vcruntime
|
||||||
vcvars
|
vcvars
|
||||||
vcxproj
|
vcxproj
|
||||||
|
vdi
|
||||||
VDId
|
VDId
|
||||||
vec
|
vec
|
||||||
VERBSONLY
|
VERBSONLY
|
||||||
@ -2275,10 +2376,14 @@ VERSIONINFO
|
|||||||
Versioning
|
Versioning
|
||||||
VFT
|
VFT
|
||||||
vid
|
vid
|
||||||
|
VIDCAP
|
||||||
|
videoconference
|
||||||
|
videoconferencevirtualdriver
|
||||||
VIDEOINFOHEADER
|
VIDEOINFOHEADER
|
||||||
videoplayback
|
videoplayback
|
||||||
viewbox
|
viewbox
|
||||||
viewmodel
|
viewmodel
|
||||||
|
vih
|
||||||
virtualization
|
virtualization
|
||||||
visiblecolorformats
|
visiblecolorformats
|
||||||
Visibletrue
|
Visibletrue
|
||||||
@ -2298,6 +2403,7 @@ VSCBD
|
|||||||
vscode
|
vscode
|
||||||
VSCROLL
|
VSCROLL
|
||||||
vse
|
vse
|
||||||
|
vsix
|
||||||
vsonline
|
vsonline
|
||||||
vstemplate
|
vstemplate
|
||||||
VSTHRD
|
VSTHRD
|
||||||
@ -2320,6 +2426,9 @@ wcscpy
|
|||||||
wcslen
|
wcslen
|
||||||
wcsncmp
|
wcsncmp
|
||||||
wcsnicmp
|
wcsnicmp
|
||||||
|
WDK
|
||||||
|
wdksetup
|
||||||
|
wdkvsix
|
||||||
wdp
|
wdp
|
||||||
wdupenv
|
wdupenv
|
||||||
We'd
|
We'd
|
||||||
@ -2346,6 +2455,8 @@ wikipedia
|
|||||||
wil
|
wil
|
||||||
wildcards
|
wildcards
|
||||||
winapi
|
winapi
|
||||||
|
wincodec
|
||||||
|
Wincodecsdk
|
||||||
wincolor
|
wincolor
|
||||||
windef
|
windef
|
||||||
windevbuildagents
|
windevbuildagents
|
||||||
@ -2401,6 +2512,7 @@ WMKEYUP
|
|||||||
wmp
|
wmp
|
||||||
WMSYSKEYDOWN
|
WMSYSKEYDOWN
|
||||||
WMSYSKEYUP
|
WMSYSKEYUP
|
||||||
|
WMV
|
||||||
wnd
|
wnd
|
||||||
WNDCLASS
|
WNDCLASS
|
||||||
WNDCLASSEX
|
WNDCLASSEX
|
||||||
@ -2431,9 +2543,11 @@ wstringstream
|
|||||||
wsz
|
wsz
|
||||||
wtoi
|
wtoi
|
||||||
WTS
|
WTS
|
||||||
|
wtsapi
|
||||||
WTSAT
|
WTSAT
|
||||||
wu
|
wu
|
||||||
wubi
|
wubi
|
||||||
|
WVC
|
||||||
Wwan
|
Wwan
|
||||||
www
|
www
|
||||||
wxs
|
wxs
|
||||||
@ -2448,6 +2562,7 @@ XBUTTON
|
|||||||
XBUTTONDBLCLK
|
XBUTTONDBLCLK
|
||||||
XBUTTONDOWN
|
XBUTTONDOWN
|
||||||
XBUTTONUP
|
XBUTTONUP
|
||||||
|
xcopy
|
||||||
XDiff
|
XDiff
|
||||||
XDocument
|
XDocument
|
||||||
XElement
|
XElement
|
||||||
@ -2479,7 +2594,10 @@ yourinfo
|
|||||||
YourUserName
|
YourUserName
|
||||||
YStr
|
YStr
|
||||||
YUY
|
YUY
|
||||||
|
yuyoyuppe
|
||||||
YUYV
|
YUYV
|
||||||
|
YVU
|
||||||
|
YVYU
|
||||||
ZEROINIT
|
ZEROINIT
|
||||||
ZIndex
|
ZIndex
|
||||||
zipfolder
|
zipfolder
|
||||||
@ -2491,9 +2609,3 @@ ZONESETCHANGE
|
|||||||
Zoneszonabletester
|
Zoneszonabletester
|
||||||
Zoomusingmagnifier
|
Zoomusingmagnifier
|
||||||
zzz
|
zzz
|
||||||
coc
|
|
||||||
djsoref
|
|
||||||
dogancelik
|
|
||||||
itsme
|
|
||||||
nitroin
|
|
||||||
ulazy
|
|
||||||
|
@ -7,3 +7,5 @@ set SolutionDir=%cd%
|
|||||||
popd
|
popd
|
||||||
SET IsPipeline=1
|
SET IsPipeline=1
|
||||||
call msbuild ../tools/BugReportTool/BugReportTool.sln /p:Configuration=Release /p:Platform=x64 /p:CIBuild=true || exit /b 1
|
call msbuild ../tools/BugReportTool/BugReportTool.sln /p:Configuration=Release /p:Platform=x64 /p:CIBuild=true || exit /b 1
|
||||||
|
call msbuild ../tools/WebcamReportTool/WebcamReportTool.sln /p:Configuration=Release /p:Platform=x64 /p:CIBuild=true || exit /b 1
|
||||||
|
|
||||||
|
@ -61,6 +61,11 @@ build:
|
|||||||
- 'x64/**/*.pdb'
|
- 'x64/**/*.pdb'
|
||||||
exclude:
|
exclude:
|
||||||
- 'x64/Release/obj/**/*.pdb'
|
- 'x64/Release/obj/**/*.pdb'
|
||||||
|
# TODO(yuyoyuppe): uncomment when VCM should be enabled
|
||||||
|
#- from: 'x86/Release'
|
||||||
|
# to: 'Build_Output'
|
||||||
|
# include:
|
||||||
|
# - 'modules\VideoConference\VideoConferenceProxyFilter_x86.dll'
|
||||||
- from: 'x64/Release'
|
- from: 'x64/Release'
|
||||||
to: 'Build_Output'
|
to: 'Build_Output'
|
||||||
include:
|
include:
|
||||||
@ -159,6 +164,9 @@ build:
|
|||||||
- 'modules\PowerRename\PowerRenameExt.dll'
|
- 'modules\PowerRename\PowerRenameExt.dll'
|
||||||
- 'modules\ShortcutGuide\ShortcutGuide\PowerToys.ShortcutGuide.exe'
|
- 'modules\ShortcutGuide\ShortcutGuide\PowerToys.ShortcutGuide.exe'
|
||||||
- 'modules\ShortcutGuide\ShortcutGuideModuleInterface\ShortcutGuideModuleInterface.dll'
|
- 'modules\ShortcutGuide\ShortcutGuideModuleInterface\ShortcutGuideModuleInterface.dll'
|
||||||
|
# TODO(yuyoyuppe): uncomment when VCM should be enabled
|
||||||
|
#- 'modules\VideoConference\VideoConferenceModule.dll'
|
||||||
|
#- 'modules\VideoConference\VideoConferenceProxyFilter_x64.dll'
|
||||||
- 'Settings\ManagedTelemetry.dll'
|
- 'Settings\ManagedTelemetry.dll'
|
||||||
- 'Settings\Microsoft.PowerToys.Settings.UI.exe'
|
- 'Settings\Microsoft.PowerToys.Settings.UI.exe'
|
||||||
- 'Settings\Microsoft.PowerToys.Settings.UI.Lib.dll'
|
- 'Settings\Microsoft.PowerToys.Settings.UI.Lib.dll'
|
||||||
@ -177,6 +185,7 @@ build:
|
|||||||
to: 'Build_Output'
|
to: 'Build_Output'
|
||||||
include:
|
include:
|
||||||
- 'BugReportTool\BugReportTool.exe'
|
- 'BugReportTool\BugReportTool.exe'
|
||||||
|
- 'WebcamReportTool\WebcamReportTool.exe'
|
||||||
signing_options:
|
signing_options:
|
||||||
sign_inline: true # This does signing a soon as this command completes
|
sign_inline: true # This does signing a soon as this command completes
|
||||||
- !!buildcommand
|
- !!buildcommand
|
||||||
@ -237,4 +246,3 @@ static_analysis_options:
|
|||||||
files_to_scan:
|
files_to_scan:
|
||||||
- exclude:
|
- exclude:
|
||||||
- '**/*.lcl'
|
- '**/*.lcl'
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
cd /D "%~dp0"
|
cd /D "%~dp0"
|
||||||
|
|
||||||
nuget restore ../tools/BugReportTool/BugReportTool.sln || exit /b 1
|
nuget restore ../tools/BugReportTool/BugReportTool.sln || exit /b 1
|
||||||
|
nuget restore ../tools/WebcamReportTool/WebcamReportTool.sln || exit /b 1
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
cd /D "%~dp0"
|
cd /D "%~dp0"
|
||||||
|
|
||||||
nuget restore ../PowerToys.sln || exit /b 1
|
nuget restore ../PowerToys.sln || exit /b 1
|
||||||
|
|
||||||
|
powershell.exe -Command "Invoke-WebRequest -OutFile %tmp%\wdksetup.exe https://go.microsoft.com/fwlink/p/?linkid=2085767"
|
||||||
|
%tmp%\wdksetup.exe /q
|
||||||
|
|
||||||
|
copy "C:\Program Files (x86)\Windows Kits\10\Vsix\VS2019\WDK.vsix" %tmp%\wdkvsix.zip
|
||||||
|
powershell Expand-Archive %tmp%\wdkvsix.zip -DestinationPath %tmp%\wdkvsix -Force
|
||||||
|
|
||||||
|
robocopy /e %tmp%\wdkvsix\$MSBuild\Microsoft\VC\v160 "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VC\v160" || IF %ERRORLEVEL% LEQ 7 EXIT 0
|
||||||
|
robocopy /e %tmp%\wdkvsix\$VCTargets "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\VC\VCTargets" || IF %ERRORLEVEL% LEQ 7 EXIT 0
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
|
|
||||||
<!-- Props that are constant for both Debug and Release configurations -->
|
<!-- Props that are constant for both Debug and Release configurations -->
|
||||||
<PropertyGroup Label="Configuration">
|
<PropertyGroup Label="Configuration">
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
<PlatformToolset Condition="'$(OverridePlatformToolset)'!='True'">v142</PlatformToolset>
|
||||||
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\</IntDir>
|
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\</IntDir>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
<SpectreMitigation>Spectre</SpectreMitigation>
|
<SpectreMitigation>Spectre</SpectreMitigation>
|
||||||
|
258
PowerToys.sln
@ -333,7 +333,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Community.PowerToys.Run.Plu
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Community.PowerToys.Run.Plugin.UnitConverter.UnitTest", "src\modules\launcher\Plugins\Community.PowerToys.Run.Plugin.UnitConverter.UnitTest\Community.PowerToys.Run.Plugin.UnitConverter.UnitTest.csproj", "{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Community.PowerToys.Run.Plugin.UnitConverter.UnitTest", "src\modules\launcher\Plugins\Community.PowerToys.Run.Plugin.UnitConverter.UnitTest\Community.PowerToys.Run.Plugin.UnitConverter.UnitTest.csproj", "{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}"
|
||||||
EndProject
|
EndProject
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shortcutguide", "shortcutguide", "{106CBECA-0701-4FC3-838C-9DF816A19AE2}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shortcutguide", "shortcutguide", "{106CBECA-0701-4FC3-838C-9DF816A19AE2}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShortcutGuideModuleInterface", "src\modules\ShortcutGuide\ShortcutGuideModuleInterface\ShortcutGuideModuleInterface.vcxproj", "{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShortcutGuideModuleInterface", "src\modules\ShortcutGuide\ShortcutGuideModuleInterface\ShortcutGuideModuleInterface.vcxproj", "{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}"
|
||||||
@ -342,376 +341,597 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShortcutGuide", "src\module
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZonesModuleInterface", "src\modules\fancyzones\FancyZonesModuleInterface\FancyZonesModuleInterface.vcxproj", "{48804216-2A0E-4168-A6D8-9CD068D14227}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZonesModuleInterface", "src\modules\fancyzones\FancyZonesModuleInterface\FancyZonesModuleInterface.vcxproj", "{48804216-2A0E-4168-A6D8-9CD068D14227}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZones", "src\modules\fancyzones\FancyZones\FancyZones.vcxproj", "{390AE700-B55F-4202-91EA-A822EB75B9BD}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZones", "src\modules\fancyzones\FancyZones\FancyZones.vcxproj", "{FF1D7936-842A-4BBB-8BEA-E9FE796DE700}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToys.Update", "src\Update\PowerToys.Update.vcxproj", "{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToys.Update", "src\Update\PowerToys.Update.vcxproj", "{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.WindowsSettings", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\Microsoft.PowerToys.Run.Plugin.WindowsSettings.csproj", "{5043CECE-E6A7-4867-9CBE-02D27D83747A}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.WindowsSettings", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\Microsoft.PowerToys.Run.Plugin.WindowsSettings.csproj", "{5043CECE-E6A7-4867-9CBE-02D27D83747A}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoConferenceShared", "src\modules\videoconference\VideoConferenceShared\VideoConferenceShared.vcxproj", "{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoConferenceModule", "src\modules\videoconference\VideoConferenceModule\Video Conference.vcxproj", "{5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoConferenceProxyFilter", "src\modules\videoconference\VideoConferenceProxyFilter\VideoConferenceProxyFilter.vcxproj", "{AC2857B4-103D-4D6D-9740-926EBF785042}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A} = {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "VideoConference", "VideoConference", "{470FBAF9-E1F8-4F3E-8786-198A1C81C8A8}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
Release|x64 = Release|x64
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Debug|x64.ActiveCfg = Debug|x64
|
{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Debug|x64.Build.0 = Debug|x64
|
{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Release|x64.ActiveCfg = Release|x64
|
{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Release|x64.ActiveCfg = Release|x64
|
||||||
{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Release|x64.Build.0 = Release|x64
|
{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Release|x64.Build.0 = Release|x64
|
||||||
|
{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Release|x86.ActiveCfg = Release|x64
|
||||||
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Debug|x64.ActiveCfg = Debug|x64
|
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Debug|x64.Build.0 = Debug|x64
|
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Release|x64.ActiveCfg = Release|x64
|
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Release|x64.ActiveCfg = Release|x64
|
||||||
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Release|x64.Build.0 = Release|x64
|
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Release|x64.Build.0 = Release|x64
|
||||||
|
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Release|x86.ActiveCfg = Release|x64
|
||||||
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Debug|x64.ActiveCfg = Debug|x64
|
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Debug|x64.Build.0 = Debug|x64
|
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Release|x64.ActiveCfg = Release|x64
|
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Release|x64.ActiveCfg = Release|x64
|
||||||
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Release|x64.Build.0 = Release|x64
|
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Release|x64.Build.0 = Release|x64
|
||||||
|
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Release|x86.ActiveCfg = Release|x64
|
||||||
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Debug|x64.ActiveCfg = Debug|x64
|
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Debug|x64.Build.0 = Debug|x64
|
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Release|x64.ActiveCfg = Release|x64
|
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Release|x64.ActiveCfg = Release|x64
|
||||||
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Release|x64.Build.0 = Release|x64
|
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Release|x64.Build.0 = Release|x64
|
||||||
|
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Release|x86.ActiveCfg = Release|x64
|
||||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|x64.ActiveCfg = Debug|x64
|
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|x64.Build.0 = Debug|x64
|
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|x64.ActiveCfg = Release|x64
|
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|x64.ActiveCfg = Release|x64
|
||||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|x64.Build.0 = Release|x64
|
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|x64.Build.0 = Release|x64
|
||||||
|
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|x86.ActiveCfg = Release|x64
|
||||||
{B25AC7A5-FB9F-4789-B392-D5C85E948670}.Debug|x64.ActiveCfg = Debug|x64
|
{B25AC7A5-FB9F-4789-B392-D5C85E948670}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{B25AC7A5-FB9F-4789-B392-D5C85E948670}.Debug|x64.Build.0 = Debug|x64
|
{B25AC7A5-FB9F-4789-B392-D5C85E948670}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{B25AC7A5-FB9F-4789-B392-D5C85E948670}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{B25AC7A5-FB9F-4789-B392-D5C85E948670}.Release|x64.ActiveCfg = Release|x64
|
{B25AC7A5-FB9F-4789-B392-D5C85E948670}.Release|x64.ActiveCfg = Release|x64
|
||||||
{B25AC7A5-FB9F-4789-B392-D5C85E948670}.Release|x64.Build.0 = Release|x64
|
{B25AC7A5-FB9F-4789-B392-D5C85E948670}.Release|x64.Build.0 = Release|x64
|
||||||
|
{B25AC7A5-FB9F-4789-B392-D5C85E948670}.Release|x86.ActiveCfg = Release|x64
|
||||||
{51920F1F-C28C-4ADF-8660-4238766796C2}.Debug|x64.ActiveCfg = Debug|x64
|
{51920F1F-C28C-4ADF-8660-4238766796C2}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{51920F1F-C28C-4ADF-8660-4238766796C2}.Debug|x64.Build.0 = Debug|x64
|
{51920F1F-C28C-4ADF-8660-4238766796C2}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{51920F1F-C28C-4ADF-8660-4238766796C2}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x64.ActiveCfg = Release|x64
|
{51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x64.ActiveCfg = Release|x64
|
||||||
{51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x64.Build.0 = Release|x64
|
{51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x64.Build.0 = Release|x64
|
||||||
|
{51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x86.ActiveCfg = Release|x64
|
||||||
{0E072714-D127-460B-AFAD-B4C40B412798}.Debug|x64.ActiveCfg = Debug|x64
|
{0E072714-D127-460B-AFAD-B4C40B412798}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{0E072714-D127-460B-AFAD-B4C40B412798}.Debug|x64.Build.0 = Debug|x64
|
{0E072714-D127-460B-AFAD-B4C40B412798}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{0E072714-D127-460B-AFAD-B4C40B412798}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{0E072714-D127-460B-AFAD-B4C40B412798}.Release|x64.ActiveCfg = Release|x64
|
{0E072714-D127-460B-AFAD-B4C40B412798}.Release|x64.ActiveCfg = Release|x64
|
||||||
{0E072714-D127-460B-AFAD-B4C40B412798}.Release|x64.Build.0 = Release|x64
|
{0E072714-D127-460B-AFAD-B4C40B412798}.Release|x64.Build.0 = Release|x64
|
||||||
|
{0E072714-D127-460B-AFAD-B4C40B412798}.Release|x86.ActiveCfg = Release|x64
|
||||||
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x64.ActiveCfg = Debug|x64
|
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x64.Build.0 = Debug|x64
|
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Release|x64.ActiveCfg = Release|x64
|
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Release|x64.ActiveCfg = Release|x64
|
||||||
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Release|x64.Build.0 = Release|x64
|
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Release|x64.Build.0 = Release|x64
|
||||||
|
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Release|x86.ActiveCfg = Release|x64
|
||||||
{2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Debug|x64.ActiveCfg = Debug|x64
|
{2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Debug|x64.Build.0 = Debug|x64
|
{2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Release|x64.ActiveCfg = Release|x64
|
{2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Release|x64.ActiveCfg = Release|x64
|
||||||
{2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Release|x64.Build.0 = Release|x64
|
{2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Release|x64.Build.0 = Release|x64
|
||||||
|
{2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Release|x86.ActiveCfg = Release|x64
|
||||||
{64A80062-4D8B-4229-8A38-DFA1D7497749}.Debug|x64.ActiveCfg = Debug|x64
|
{64A80062-4D8B-4229-8A38-DFA1D7497749}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{64A80062-4D8B-4229-8A38-DFA1D7497749}.Debug|x64.Build.0 = Debug|x64
|
{64A80062-4D8B-4229-8A38-DFA1D7497749}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{64A80062-4D8B-4229-8A38-DFA1D7497749}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{64A80062-4D8B-4229-8A38-DFA1D7497749}.Release|x64.ActiveCfg = Release|x64
|
{64A80062-4D8B-4229-8A38-DFA1D7497749}.Release|x64.ActiveCfg = Release|x64
|
||||||
{64A80062-4D8B-4229-8A38-DFA1D7497749}.Release|x64.Build.0 = Release|x64
|
{64A80062-4D8B-4229-8A38-DFA1D7497749}.Release|x64.Build.0 = Release|x64
|
||||||
|
{64A80062-4D8B-4229-8A38-DFA1D7497749}.Release|x86.ActiveCfg = Release|x64
|
||||||
{0485F45C-EA7A-4BB5-804B-3E8D14699387}.Debug|x64.ActiveCfg = Debug|x64
|
{0485F45C-EA7A-4BB5-804B-3E8D14699387}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{0485F45C-EA7A-4BB5-804B-3E8D14699387}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{0485F45C-EA7A-4BB5-804B-3E8D14699387}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{0485F45C-EA7A-4BB5-804B-3E8D14699387}.Release|x64.ActiveCfg = Release|x64
|
{0485F45C-EA7A-4BB5-804B-3E8D14699387}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{0485F45C-EA7A-4BB5-804B-3E8D14699387}.Release|x64.Build.0 = Release|x64
|
||||||
|
{0485F45C-EA7A-4BB5-804B-3E8D14699387}.Release|x86.ActiveCfg = Release|x64
|
||||||
{89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Debug|x64.ActiveCfg = Debug|x64
|
{89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Debug|x64.Build.0 = Debug|x64
|
{89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Release|x64.ActiveCfg = Release|x64
|
{89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Release|x64.ActiveCfg = Release|x64
|
||||||
{89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Release|x64.Build.0 = Release|x64
|
{89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Release|x64.Build.0 = Release|x64
|
||||||
|
{89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Release|x86.ActiveCfg = Release|x64
|
||||||
{2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Debug|x64.ActiveCfg = Debug|x64
|
{2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Debug|x64.Build.0 = Debug|x64
|
{2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Release|x64.ActiveCfg = Release|x64
|
{2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Release|x64.ActiveCfg = Release|x64
|
||||||
{2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Release|x64.Build.0 = Release|x64
|
{2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Release|x64.Build.0 = Release|x64
|
||||||
|
{2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Release|x86.ActiveCfg = Release|x64
|
||||||
{0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Debug|x64.ActiveCfg = Debug|x64
|
{0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Debug|x64.Build.0 = Debug|x64
|
{0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Release|x64.ActiveCfg = Release|x64
|
{0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Release|x64.ActiveCfg = Release|x64
|
||||||
{0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Release|x64.Build.0 = Release|x64
|
{0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Release|x64.Build.0 = Release|x64
|
||||||
|
{0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Release|x86.ActiveCfg = Release|x64
|
||||||
{E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Debug|x64.ActiveCfg = Debug|x64
|
{E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Debug|x64.Build.0 = Debug|x64
|
{E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Release|x64.ActiveCfg = Release|x64
|
{E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Release|x64.ActiveCfg = Release|x64
|
||||||
{E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Release|x64.Build.0 = Release|x64
|
{E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Release|x64.Build.0 = Release|x64
|
||||||
|
{E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Release|x86.ActiveCfg = Release|x64
|
||||||
{D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Debug|x64.ActiveCfg = Debug|x64
|
{D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Debug|x64.Build.0 = Debug|x64
|
{D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Release|x64.ActiveCfg = Release|x64
|
{D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Release|x64.ActiveCfg = Release|x64
|
||||||
{D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Release|x64.Build.0 = Release|x64
|
{D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Release|x64.Build.0 = Release|x64
|
||||||
|
{D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Release|x86.ActiveCfg = Release|x64
|
||||||
{17DA04DF-E393-4397-9CF0-84DABE11032E}.Debug|x64.ActiveCfg = Debug|x64
|
{17DA04DF-E393-4397-9CF0-84DABE11032E}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{17DA04DF-E393-4397-9CF0-84DABE11032E}.Debug|x64.Build.0 = Debug|x64
|
{17DA04DF-E393-4397-9CF0-84DABE11032E}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{17DA04DF-E393-4397-9CF0-84DABE11032E}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{17DA04DF-E393-4397-9CF0-84DABE11032E}.Release|x64.ActiveCfg = Release|x64
|
{17DA04DF-E393-4397-9CF0-84DABE11032E}.Release|x64.ActiveCfg = Release|x64
|
||||||
{17DA04DF-E393-4397-9CF0-84DABE11032E}.Release|x64.Build.0 = Release|x64
|
{17DA04DF-E393-4397-9CF0-84DABE11032E}.Release|x64.Build.0 = Release|x64
|
||||||
|
{17DA04DF-E393-4397-9CF0-84DABE11032E}.Release|x86.ActiveCfg = Release|x64
|
||||||
{8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Debug|x64.ActiveCfg = Debug|x64
|
{8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Debug|x64.Build.0 = Debug|x64
|
{8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Release|x64.ActiveCfg = Release|x64
|
{8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Release|x64.ActiveCfg = Release|x64
|
||||||
{8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Release|x64.Build.0 = Release|x64
|
{8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Release|x64.Build.0 = Release|x64
|
||||||
|
{8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Release|x86.ActiveCfg = Release|x64
|
||||||
{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Debug|x64.ActiveCfg = Debug|x64
|
{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Debug|x64.Build.0 = Debug|x64
|
{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Release|x64.ActiveCfg = Release|x64
|
{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Release|x64.ActiveCfg = Release|x64
|
||||||
{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Release|x64.Build.0 = Release|x64
|
{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Release|x64.Build.0 = Release|x64
|
||||||
|
{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Release|x86.ActiveCfg = Release|x64
|
||||||
{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Debug|x64.ActiveCfg = Debug|x64
|
{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Debug|x64.Build.0 = Debug|x64
|
{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Release|x64.ActiveCfg = Release|x64
|
{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Release|x64.ActiveCfg = Release|x64
|
||||||
{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Release|x64.Build.0 = Release|x64
|
{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Release|x64.Build.0 = Release|x64
|
||||||
|
{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Release|x86.ActiveCfg = Release|x64
|
||||||
{FF742965-9A80-41A5-B042-D6C7D3A21708}.Debug|x64.ActiveCfg = Debug|x64
|
{FF742965-9A80-41A5-B042-D6C7D3A21708}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{FF742965-9A80-41A5-B042-D6C7D3A21708}.Debug|x64.Build.0 = Debug|x64
|
{FF742965-9A80-41A5-B042-D6C7D3A21708}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{FF742965-9A80-41A5-B042-D6C7D3A21708}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{FF742965-9A80-41A5-B042-D6C7D3A21708}.Release|x64.ActiveCfg = Release|x64
|
{FF742965-9A80-41A5-B042-D6C7D3A21708}.Release|x64.ActiveCfg = Release|x64
|
||||||
{FF742965-9A80-41A5-B042-D6C7D3A21708}.Release|x64.Build.0 = Release|x64
|
{FF742965-9A80-41A5-B042-D6C7D3A21708}.Release|x64.Build.0 = Release|x64
|
||||||
|
{FF742965-9A80-41A5-B042-D6C7D3A21708}.Release|x86.ActiveCfg = Release|x64
|
||||||
{59BD9891-3837-438A-958D-ADC7F91F6F7E}.Debug|x64.ActiveCfg = Debug|x64
|
{59BD9891-3837-438A-958D-ADC7F91F6F7E}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{59BD9891-3837-438A-958D-ADC7F91F6F7E}.Debug|x64.Build.0 = Debug|x64
|
{59BD9891-3837-438A-958D-ADC7F91F6F7E}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{59BD9891-3837-438A-958D-ADC7F91F6F7E}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{59BD9891-3837-438A-958D-ADC7F91F6F7E}.Release|x64.ActiveCfg = Release|x64
|
{59BD9891-3837-438A-958D-ADC7F91F6F7E}.Release|x64.ActiveCfg = Release|x64
|
||||||
{59BD9891-3837-438A-958D-ADC7F91F6F7E}.Release|x64.Build.0 = Release|x64
|
{59BD9891-3837-438A-958D-ADC7F91F6F7E}.Release|x64.Build.0 = Release|x64
|
||||||
|
{59BD9891-3837-438A-958D-ADC7F91F6F7E}.Release|x86.ActiveCfg = Release|x64
|
||||||
{4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Debug|x64.ActiveCfg = Debug|x64
|
{4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Debug|x64.Build.0 = Debug|x64
|
{4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Release|x64.ActiveCfg = Release|x64
|
{4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Release|x64.ActiveCfg = Release|x64
|
||||||
{4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Release|x64.Build.0 = Release|x64
|
{4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Release|x64.Build.0 = Release|x64
|
||||||
|
{4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Release|x86.ActiveCfg = Release|x64
|
||||||
{74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Debug|x64.ActiveCfg = Debug|x64
|
{74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Debug|x64.Build.0 = Debug|x64
|
{74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Release|x64.ActiveCfg = Release|x64
|
{74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Release|x64.ActiveCfg = Release|x64
|
||||||
{74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Release|x64.Build.0 = Release|x64
|
{74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Release|x64.Build.0 = Release|x64
|
||||||
|
{74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Release|x86.ActiveCfg = Release|x64
|
||||||
{FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Debug|x64.ActiveCfg = Debug|x64
|
{FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Debug|x64.Build.0 = Debug|x64
|
{FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Release|x64.ActiveCfg = Release|x64
|
{FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Release|x64.ActiveCfg = Release|x64
|
||||||
{FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Release|x64.Build.0 = Release|x64
|
{FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Release|x64.Build.0 = Release|x64
|
||||||
|
{FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Release|x86.ActiveCfg = Release|x64
|
||||||
{C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Debug|x64.ActiveCfg = Debug|x64
|
{C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Debug|x64.Build.0 = Debug|x64
|
{C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Release|x64.ActiveCfg = Release|x64
|
{C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Release|x64.ActiveCfg = Release|x64
|
||||||
{C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Release|x64.Build.0 = Release|x64
|
{C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Release|x64.Build.0 = Release|x64
|
||||||
|
{C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Release|x86.ActiveCfg = Release|x64
|
||||||
{F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Debug|x64.ActiveCfg = Debug|x64
|
{F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Debug|x64.Build.0 = Debug|x64
|
{F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Release|x64.ActiveCfg = Release|x64
|
{F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Release|x64.ActiveCfg = Release|x64
|
||||||
{F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Release|x64.Build.0 = Release|x64
|
{F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Release|x64.Build.0 = Release|x64
|
||||||
|
{F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Release|x86.ActiveCfg = Release|x64
|
||||||
{E364F67B-BB12-4E91-B639-355866EBCD8B}.Debug|x64.ActiveCfg = Debug|x64
|
{E364F67B-BB12-4E91-B639-355866EBCD8B}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{E364F67B-BB12-4E91-B639-355866EBCD8B}.Debug|x64.Build.0 = Debug|x64
|
{E364F67B-BB12-4E91-B639-355866EBCD8B}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{E364F67B-BB12-4E91-B639-355866EBCD8B}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{E364F67B-BB12-4E91-B639-355866EBCD8B}.Release|x64.ActiveCfg = Release|x64
|
{E364F67B-BB12-4E91-B639-355866EBCD8B}.Release|x64.ActiveCfg = Release|x64
|
||||||
{E364F67B-BB12-4E91-B639-355866EBCD8B}.Release|x64.Build.0 = Release|x64
|
{E364F67B-BB12-4E91-B639-355866EBCD8B}.Release|x64.Build.0 = Release|x64
|
||||||
|
{E364F67B-BB12-4E91-B639-355866EBCD8B}.Release|x86.ActiveCfg = Release|x64
|
||||||
{F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Debug|x64.ActiveCfg = Debug|x64
|
{F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Debug|x64.Build.0 = Debug|x64
|
{F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Release|x64.ActiveCfg = Release|x64
|
{F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Release|x64.ActiveCfg = Release|x64
|
||||||
{F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Release|x64.Build.0 = Release|x64
|
{F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Release|x64.Build.0 = Release|x64
|
||||||
|
{F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Release|x86.ActiveCfg = Release|x64
|
||||||
{AF2349B8-E5B6-4004-9502-687C1C7730B1}.Debug|x64.ActiveCfg = Debug|x64
|
{AF2349B8-E5B6-4004-9502-687C1C7730B1}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{AF2349B8-E5B6-4004-9502-687C1C7730B1}.Debug|x64.Build.0 = Debug|x64
|
{AF2349B8-E5B6-4004-9502-687C1C7730B1}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{AF2349B8-E5B6-4004-9502-687C1C7730B1}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{AF2349B8-E5B6-4004-9502-687C1C7730B1}.Release|x64.ActiveCfg = Release|x64
|
{AF2349B8-E5B6-4004-9502-687C1C7730B1}.Release|x64.ActiveCfg = Release|x64
|
||||||
{AF2349B8-E5B6-4004-9502-687C1C7730B1}.Release|x64.Build.0 = Release|x64
|
{AF2349B8-E5B6-4004-9502-687C1C7730B1}.Release|x64.Build.0 = Release|x64
|
||||||
|
{AF2349B8-E5B6-4004-9502-687C1C7730B1}.Release|x86.ActiveCfg = Release|x64
|
||||||
{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Debug|x64.ActiveCfg = Debug|x64
|
{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Debug|x64.Build.0 = Debug|x64
|
{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Release|x64.ActiveCfg = Release|x64
|
{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Release|x64.ActiveCfg = Release|x64
|
||||||
{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Release|x64.Build.0 = Release|x64
|
{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Release|x64.Build.0 = Release|x64
|
||||||
|
{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Release|x86.ActiveCfg = Release|x64
|
||||||
{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Debug|x64.ActiveCfg = Debug|x64
|
{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Debug|x64.Build.0 = Debug|x64
|
{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Release|x64.ActiveCfg = Release|x64
|
{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Release|x64.ActiveCfg = Release|x64
|
||||||
{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Release|x64.Build.0 = Release|x64
|
{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Release|x64.Build.0 = Release|x64
|
||||||
|
{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Release|x86.ActiveCfg = Release|x64
|
||||||
{DA425894-6E13-404F-8DCB-78584EC0557A}.Debug|x64.ActiveCfg = Debug|x64
|
{DA425894-6E13-404F-8DCB-78584EC0557A}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{DA425894-6E13-404F-8DCB-78584EC0557A}.Debug|x64.Build.0 = Debug|x64
|
{DA425894-6E13-404F-8DCB-78584EC0557A}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{DA425894-6E13-404F-8DCB-78584EC0557A}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{DA425894-6E13-404F-8DCB-78584EC0557A}.Release|x64.ActiveCfg = Release|x64
|
{DA425894-6E13-404F-8DCB-78584EC0557A}.Release|x64.ActiveCfg = Release|x64
|
||||||
{DA425894-6E13-404F-8DCB-78584EC0557A}.Release|x64.Build.0 = Release|x64
|
{DA425894-6E13-404F-8DCB-78584EC0557A}.Release|x64.Build.0 = Release|x64
|
||||||
|
{DA425894-6E13-404F-8DCB-78584EC0557A}.Release|x86.ActiveCfg = Release|x64
|
||||||
{060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Debug|x64.ActiveCfg = Debug|x64
|
{060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Debug|x64.Build.0 = Debug|x64
|
{060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Release|x64.ActiveCfg = Release|x64
|
{060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Release|x64.ActiveCfg = Release|x64
|
||||||
{060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Release|x64.Build.0 = Release|x64
|
{060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Release|x64.Build.0 = Release|x64
|
||||||
|
{060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Release|x86.ActiveCfg = Release|x64
|
||||||
{748417CA-F17E-487F-9411-CAFB6D3F4877}.Debug|x64.ActiveCfg = Debug|x64
|
{748417CA-F17E-487F-9411-CAFB6D3F4877}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{748417CA-F17E-487F-9411-CAFB6D3F4877}.Debug|x64.Build.0 = Debug|x64
|
{748417CA-F17E-487F-9411-CAFB6D3F4877}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{748417CA-F17E-487F-9411-CAFB6D3F4877}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{748417CA-F17E-487F-9411-CAFB6D3F4877}.Release|x64.ActiveCfg = Release|x64
|
{748417CA-F17E-487F-9411-CAFB6D3F4877}.Release|x64.ActiveCfg = Release|x64
|
||||||
{748417CA-F17E-487F-9411-CAFB6D3F4877}.Release|x64.Build.0 = Release|x64
|
{748417CA-F17E-487F-9411-CAFB6D3F4877}.Release|x64.Build.0 = Release|x64
|
||||||
|
{748417CA-F17E-487F-9411-CAFB6D3F4877}.Release|x86.ActiveCfg = Release|x64
|
||||||
{217DF501-135C-4E38-BFC8-99D4821032EA}.Debug|x64.ActiveCfg = Debug|x64
|
{217DF501-135C-4E38-BFC8-99D4821032EA}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{217DF501-135C-4E38-BFC8-99D4821032EA}.Debug|x64.Build.0 = Debug|x64
|
{217DF501-135C-4E38-BFC8-99D4821032EA}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{217DF501-135C-4E38-BFC8-99D4821032EA}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{217DF501-135C-4E38-BFC8-99D4821032EA}.Release|x64.ActiveCfg = Release|x64
|
{217DF501-135C-4E38-BFC8-99D4821032EA}.Release|x64.ActiveCfg = Release|x64
|
||||||
{217DF501-135C-4E38-BFC8-99D4821032EA}.Release|x64.Build.0 = Release|x64
|
{217DF501-135C-4E38-BFC8-99D4821032EA}.Release|x64.Build.0 = Release|x64
|
||||||
|
{217DF501-135C-4E38-BFC8-99D4821032EA}.Release|x86.ActiveCfg = Release|x64
|
||||||
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Debug|x64.ActiveCfg = Debug|x64
|
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Debug|x64.Build.0 = Debug|x64
|
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Release|x64.ActiveCfg = Release|x64
|
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Release|x64.ActiveCfg = Release|x64
|
||||||
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Release|x64.Build.0 = Release|x64
|
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Release|x64.Build.0 = Release|x64
|
||||||
|
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Release|x86.ActiveCfg = Release|x64
|
||||||
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Debug|x64.ActiveCfg = Debug|x64
|
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Debug|x64.Build.0 = Debug|x64
|
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Debug|x86.Deploy.0 = Debug|Win32
|
||||||
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Release|x64.ActiveCfg = Release|x64
|
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Release|x64.ActiveCfg = Release|x64
|
||||||
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Release|x64.Build.0 = Release|x64
|
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Release|x64.Build.0 = Release|x64
|
||||||
|
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Release|x86.Deploy.0 = Release|Win32
|
||||||
{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Debug|x64.ActiveCfg = Debug|x64
|
{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Debug|x64.Build.0 = Debug|x64
|
{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Release|x64.ActiveCfg = Release|x64
|
{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Release|x64.ActiveCfg = Release|x64
|
||||||
{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Release|x64.Build.0 = Release|x64
|
{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Release|x64.Build.0 = Release|x64
|
||||||
|
{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Release|x86.ActiveCfg = Release|x64
|
||||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Debug|x64.ActiveCfg = Debug|x64
|
{F055103B-F80B-4D0C-BF48-057C55620033}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Debug|x64.Build.0 = Debug|x64
|
{F055103B-F80B-4D0C-BF48-057C55620033}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{F055103B-F80B-4D0C-BF48-057C55620033}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|x64.ActiveCfg = Release|x64
|
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|x64.ActiveCfg = Release|x64
|
||||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|x64.Build.0 = Release|x64
|
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|x64.Build.0 = Release|x64
|
||||||
|
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|x86.ActiveCfg = Release|x64
|
||||||
{787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Debug|x64.ActiveCfg = Debug|x64
|
{787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Debug|x64.Build.0 = Debug|x64
|
{787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Release|x64.ActiveCfg = Release|x64
|
{787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Release|x64.ActiveCfg = Release|x64
|
||||||
{787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Release|x64.Build.0 = Release|x64
|
{787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Release|x64.Build.0 = Release|x64
|
||||||
|
{787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Release|x86.ActiveCfg = Release|x64
|
||||||
{08C8C05F-0362-41BC-818C-724572DF8B06}.Debug|x64.ActiveCfg = Debug|x64
|
{08C8C05F-0362-41BC-818C-724572DF8B06}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{08C8C05F-0362-41BC-818C-724572DF8B06}.Debug|x64.Build.0 = Debug|x64
|
{08C8C05F-0362-41BC-818C-724572DF8B06}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{08C8C05F-0362-41BC-818C-724572DF8B06}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{08C8C05F-0362-41BC-818C-724572DF8B06}.Release|x64.ActiveCfg = Release|x64
|
{08C8C05F-0362-41BC-818C-724572DF8B06}.Release|x64.ActiveCfg = Release|x64
|
||||||
{08C8C05F-0362-41BC-818C-724572DF8B06}.Release|x64.Build.0 = Release|x64
|
{08C8C05F-0362-41BC-818C-724572DF8B06}.Release|x64.Build.0 = Release|x64
|
||||||
|
{08C8C05F-0362-41BC-818C-724572DF8B06}.Release|x86.ActiveCfg = Release|x64
|
||||||
{5D00D290-4016-4CFE-9E41-1E7C724509BA}.Debug|x64.ActiveCfg = Debug|x64
|
{5D00D290-4016-4CFE-9E41-1E7C724509BA}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{5D00D290-4016-4CFE-9E41-1E7C724509BA}.Debug|x64.Build.0 = Debug|x64
|
{5D00D290-4016-4CFE-9E41-1E7C724509BA}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{5D00D290-4016-4CFE-9E41-1E7C724509BA}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{5D00D290-4016-4CFE-9E41-1E7C724509BA}.Release|x64.ActiveCfg = Release|x64
|
{5D00D290-4016-4CFE-9E41-1E7C724509BA}.Release|x64.ActiveCfg = Release|x64
|
||||||
{5D00D290-4016-4CFE-9E41-1E7C724509BA}.Release|x64.Build.0 = Release|x64
|
{5D00D290-4016-4CFE-9E41-1E7C724509BA}.Release|x64.Build.0 = Release|x64
|
||||||
|
{5D00D290-4016-4CFE-9E41-1E7C724509BA}.Release|x86.ActiveCfg = Release|x64
|
||||||
{4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Debug|x64.ActiveCfg = Debug|x64
|
{4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Debug|x64.Build.0 = Debug|x64
|
{4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Release|x64.ActiveCfg = Release|x64
|
{4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Release|x64.ActiveCfg = Release|x64
|
||||||
{4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Release|x64.Build.0 = Release|x64
|
{4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Release|x64.Build.0 = Release|x64
|
||||||
|
{4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Release|x86.ActiveCfg = Release|x64
|
||||||
{42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Debug|x64.ActiveCfg = Debug|x64
|
{42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Debug|x64.Build.0 = Debug|x64
|
{42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Release|x64.ActiveCfg = Release|x64
|
{42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Release|x64.ActiveCfg = Release|x64
|
||||||
{42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Release|x64.Build.0 = Release|x64
|
{42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Release|x64.Build.0 = Release|x64
|
||||||
|
{42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Release|x86.ActiveCfg = Release|x64
|
||||||
{1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Debug|x64.ActiveCfg = Debug|x64
|
{1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Debug|x64.Build.0 = Debug|x64
|
{1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Release|x64.ActiveCfg = Release|x64
|
{1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Release|x64.ActiveCfg = Release|x64
|
||||||
{1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Release|x64.Build.0 = Release|x64
|
{1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Release|x64.Build.0 = Release|x64
|
||||||
|
{1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Release|x86.ActiveCfg = Release|x64
|
||||||
{8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Debug|x64.ActiveCfg = Debug|x64
|
{8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Debug|x64.Build.0 = Debug|x64
|
{8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Release|x64.ActiveCfg = Release|x64
|
{8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Release|x64.ActiveCfg = Release|x64
|
||||||
{8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Release|x64.Build.0 = Release|x64
|
{8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Release|x64.Build.0 = Release|x64
|
||||||
|
{8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Release|x86.ActiveCfg = Release|x64
|
||||||
{655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Debug|x64.ActiveCfg = Debug|x64
|
{655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Debug|x64.Build.0 = Debug|x64
|
{655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Release|x64.ActiveCfg = Release|x64
|
{655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Release|x64.ActiveCfg = Release|x64
|
||||||
{655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Release|x64.Build.0 = Release|x64
|
{655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Release|x64.Build.0 = Release|x64
|
||||||
|
{655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Release|x86.ActiveCfg = Release|x64
|
||||||
{BA58206B-1493-4C75-BFEA-A85768A1E156}.Debug|x64.ActiveCfg = Debug|x64
|
{BA58206B-1493-4C75-BFEA-A85768A1E156}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{BA58206B-1493-4C75-BFEA-A85768A1E156}.Debug|x64.Build.0 = Debug|x64
|
{BA58206B-1493-4C75-BFEA-A85768A1E156}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{BA58206B-1493-4C75-BFEA-A85768A1E156}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{BA58206B-1493-4C75-BFEA-A85768A1E156}.Release|x64.ActiveCfg = Release|x64
|
{BA58206B-1493-4C75-BFEA-A85768A1E156}.Release|x64.ActiveCfg = Release|x64
|
||||||
{BA58206B-1493-4C75-BFEA-A85768A1E156}.Release|x64.Build.0 = Release|x64
|
{BA58206B-1493-4C75-BFEA-A85768A1E156}.Release|x64.Build.0 = Release|x64
|
||||||
|
{BA58206B-1493-4C75-BFEA-A85768A1E156}.Release|x86.ActiveCfg = Release|x64
|
||||||
{03276A39-D4E9-417C-8FFD-200B0EE5E871}.Debug|x64.ActiveCfg = Debug|x64
|
{03276A39-D4E9-417C-8FFD-200B0EE5E871}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{03276A39-D4E9-417C-8FFD-200B0EE5E871}.Debug|x64.Build.0 = Debug|x64
|
{03276A39-D4E9-417C-8FFD-200B0EE5E871}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{03276A39-D4E9-417C-8FFD-200B0EE5E871}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{03276A39-D4E9-417C-8FFD-200B0EE5E871}.Release|x64.ActiveCfg = Release|x64
|
{03276A39-D4E9-417C-8FFD-200B0EE5E871}.Release|x64.ActiveCfg = Release|x64
|
||||||
{03276A39-D4E9-417C-8FFD-200B0EE5E871}.Release|x64.Build.0 = Release|x64
|
{03276A39-D4E9-417C-8FFD-200B0EE5E871}.Release|x64.Build.0 = Release|x64
|
||||||
|
{03276A39-D4E9-417C-8FFD-200B0EE5E871}.Release|x86.ActiveCfg = Release|x64
|
||||||
{B81FB7B6-D30E-428F-908A-41422EFC1172}.Debug|x64.ActiveCfg = Debug|x64
|
{B81FB7B6-D30E-428F-908A-41422EFC1172}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{B81FB7B6-D30E-428F-908A-41422EFC1172}.Debug|x64.Build.0 = Debug|x64
|
{B81FB7B6-D30E-428F-908A-41422EFC1172}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{B81FB7B6-D30E-428F-908A-41422EFC1172}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{B81FB7B6-D30E-428F-908A-41422EFC1172}.Release|x64.ActiveCfg = Release|x64
|
{B81FB7B6-D30E-428F-908A-41422EFC1172}.Release|x64.ActiveCfg = Release|x64
|
||||||
{B81FB7B6-D30E-428F-908A-41422EFC1172}.Release|x64.Build.0 = Release|x64
|
{B81FB7B6-D30E-428F-908A-41422EFC1172}.Release|x64.Build.0 = Release|x64
|
||||||
|
{B81FB7B6-D30E-428F-908A-41422EFC1172}.Release|x86.ActiveCfg = Release|x64
|
||||||
{0F85E674-34AE-443D-954C-8321EB8B93B1}.Debug|x64.ActiveCfg = Debug|x64
|
{0F85E674-34AE-443D-954C-8321EB8B93B1}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{0F85E674-34AE-443D-954C-8321EB8B93B1}.Debug|x64.Build.0 = Debug|x64
|
{0F85E674-34AE-443D-954C-8321EB8B93B1}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{0F85E674-34AE-443D-954C-8321EB8B93B1}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{0F85E674-34AE-443D-954C-8321EB8B93B1}.Release|x64.ActiveCfg = Release|x64
|
{0F85E674-34AE-443D-954C-8321EB8B93B1}.Release|x64.ActiveCfg = Release|x64
|
||||||
{0F85E674-34AE-443D-954C-8321EB8B93B1}.Release|x64.Build.0 = Release|x64
|
{0F85E674-34AE-443D-954C-8321EB8B93B1}.Release|x64.Build.0 = Release|x64
|
||||||
|
{0F85E674-34AE-443D-954C-8321EB8B93B1}.Release|x86.ActiveCfg = Release|x64
|
||||||
{632BBE62-5421-49EA-835A-7FFA4F499BD6}.Debug|x64.ActiveCfg = Debug|x64
|
{632BBE62-5421-49EA-835A-7FFA4F499BD6}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{632BBE62-5421-49EA-835A-7FFA4F499BD6}.Debug|x64.Build.0 = Debug|x64
|
{632BBE62-5421-49EA-835A-7FFA4F499BD6}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{632BBE62-5421-49EA-835A-7FFA4F499BD6}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{632BBE62-5421-49EA-835A-7FFA4F499BD6}.Release|x64.ActiveCfg = Release|x64
|
{632BBE62-5421-49EA-835A-7FFA4F499BD6}.Release|x64.ActiveCfg = Release|x64
|
||||||
{632BBE62-5421-49EA-835A-7FFA4F499BD6}.Release|x64.Build.0 = Release|x64
|
{632BBE62-5421-49EA-835A-7FFA4F499BD6}.Release|x64.Build.0 = Release|x64
|
||||||
|
{632BBE62-5421-49EA-835A-7FFA4F499BD6}.Release|x86.ActiveCfg = Release|x64
|
||||||
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Debug|x64.ActiveCfg = Debug|x64
|
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Debug|x64.Build.0 = Debug|x64
|
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Release|x64.ActiveCfg = Release|x64
|
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Release|x64.ActiveCfg = Release|x64
|
||||||
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Release|x64.Build.0 = Release|x64
|
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Release|x64.Build.0 = Release|x64
|
||||||
|
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Release|x86.ActiveCfg = Release|x64
|
||||||
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Debug|x64.ActiveCfg = Debug|x64
|
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Debug|x64.Build.0 = Debug|x64
|
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Release|x64.ActiveCfg = Release|x64
|
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Release|x64.ActiveCfg = Release|x64
|
||||||
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Release|x64.Build.0 = Release|x64
|
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Release|x64.Build.0 = Release|x64
|
||||||
|
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Release|x86.ActiveCfg = Release|x64
|
||||||
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.ActiveCfg = Debug|x64
|
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.Build.0 = Debug|x64
|
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.ActiveCfg = Release|x64
|
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.ActiveCfg = Release|x64
|
||||||
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.Build.0 = Release|x64
|
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.Build.0 = Release|x64
|
||||||
|
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x86.ActiveCfg = Release|x64
|
||||||
{FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Debug|x64.ActiveCfg = Debug|x64
|
{FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Debug|x64.Build.0 = Debug|x64
|
{FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Release|x64.ActiveCfg = Release|x64
|
{FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Release|x64.ActiveCfg = Release|x64
|
||||||
{FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Release|x64.Build.0 = Release|x64
|
{FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Release|x64.Build.0 = Release|x64
|
||||||
|
{FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Release|x86.ActiveCfg = Release|x64
|
||||||
{DA5A6FE9-0040-40CC-83CC-764AE5306590}.Debug|x64.ActiveCfg = Debug|x64
|
{DA5A6FE9-0040-40CC-83CC-764AE5306590}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{DA5A6FE9-0040-40CC-83CC-764AE5306590}.Debug|x64.Build.0 = Debug|x64
|
{DA5A6FE9-0040-40CC-83CC-764AE5306590}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{DA5A6FE9-0040-40CC-83CC-764AE5306590}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{DA5A6FE9-0040-40CC-83CC-764AE5306590}.Release|x64.ActiveCfg = Release|x64
|
{DA5A6FE9-0040-40CC-83CC-764AE5306590}.Release|x64.ActiveCfg = Release|x64
|
||||||
{DA5A6FE9-0040-40CC-83CC-764AE5306590}.Release|x64.Build.0 = Release|x64
|
{DA5A6FE9-0040-40CC-83CC-764AE5306590}.Release|x64.Build.0 = Release|x64
|
||||||
|
{DA5A6FE9-0040-40CC-83CC-764AE5306590}.Release|x86.ActiveCfg = Release|x64
|
||||||
{0351ADA4-0C32-4652-9BA0-41F7B602372B}.Debug|x64.ActiveCfg = Debug|x64
|
{0351ADA4-0C32-4652-9BA0-41F7B602372B}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{0351ADA4-0C32-4652-9BA0-41F7B602372B}.Debug|x64.Build.0 = Debug|x64
|
{0351ADA4-0C32-4652-9BA0-41F7B602372B}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{0351ADA4-0C32-4652-9BA0-41F7B602372B}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{0351ADA4-0C32-4652-9BA0-41F7B602372B}.Release|x64.ActiveCfg = Release|x64
|
{0351ADA4-0C32-4652-9BA0-41F7B602372B}.Release|x64.ActiveCfg = Release|x64
|
||||||
{0351ADA4-0C32-4652-9BA0-41F7B602372B}.Release|x64.Build.0 = Release|x64
|
{0351ADA4-0C32-4652-9BA0-41F7B602372B}.Release|x64.Build.0 = Release|x64
|
||||||
|
{0351ADA4-0C32-4652-9BA0-41F7B602372B}.Release|x86.ActiveCfg = Release|x64
|
||||||
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.ActiveCfg = Debug|x64
|
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.Build.0 = Debug|x64
|
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.ActiveCfg = Release|x64
|
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.ActiveCfg = Release|x64
|
||||||
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.Build.0 = Release|x64
|
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.Build.0 = Release|x64
|
||||||
|
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x86.ActiveCfg = Release|x64
|
||||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|x64.ActiveCfg = Debug|x64
|
{6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|x64.Build.0 = Debug|x64
|
{6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Release|x64.ActiveCfg = Release|x64
|
{6955446D-23F7-4023-9BB3-8657F904AF99}.Release|x64.ActiveCfg = Release|x64
|
||||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Release|x64.Build.0 = Release|x64
|
{6955446D-23F7-4023-9BB3-8657F904AF99}.Release|x64.Build.0 = Release|x64
|
||||||
|
{6955446D-23F7-4023-9BB3-8657F904AF99}.Release|x86.ActiveCfg = Release|x64
|
||||||
{58736667-1027-4AD7-BFDF-7A3A6474103A}.Debug|x64.ActiveCfg = Debug|x64
|
{58736667-1027-4AD7-BFDF-7A3A6474103A}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{58736667-1027-4AD7-BFDF-7A3A6474103A}.Debug|x64.Build.0 = Debug|x64
|
{58736667-1027-4AD7-BFDF-7A3A6474103A}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{58736667-1027-4AD7-BFDF-7A3A6474103A}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{58736667-1027-4AD7-BFDF-7A3A6474103A}.Release|x64.ActiveCfg = Release|x64
|
{58736667-1027-4AD7-BFDF-7A3A6474103A}.Release|x64.ActiveCfg = Release|x64
|
||||||
{58736667-1027-4AD7-BFDF-7A3A6474103A}.Release|x64.Build.0 = Release|x64
|
{58736667-1027-4AD7-BFDF-7A3A6474103A}.Release|x64.Build.0 = Release|x64
|
||||||
|
{58736667-1027-4AD7-BFDF-7A3A6474103A}.Release|x86.ActiveCfg = Release|x64
|
||||||
{1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Debug|x64.ActiveCfg = Debug|x64
|
{1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Debug|x64.Build.0 = Debug|x64
|
{1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Release|x64.ActiveCfg = Release|x64
|
{1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Release|x64.ActiveCfg = Release|x64
|
||||||
{1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Release|x64.Build.0 = Release|x64
|
{1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Release|x64.Build.0 = Release|x64
|
||||||
|
{1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Release|x86.ActiveCfg = Release|x64
|
||||||
{031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Debug|x64.ActiveCfg = Debug|x64
|
{031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Debug|x64.Build.0 = Debug|x64
|
{031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Release|x64.ActiveCfg = Release|x64
|
{031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Release|x64.ActiveCfg = Release|x64
|
||||||
{031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Release|x64.Build.0 = Release|x64
|
{031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Release|x64.Build.0 = Release|x64
|
||||||
|
{031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Release|x86.ActiveCfg = Release|x64
|
||||||
{0B593A6C-4143-4337-860E-DB5710FB87DB}.Debug|x64.ActiveCfg = Debug|x64
|
{0B593A6C-4143-4337-860E-DB5710FB87DB}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{0B593A6C-4143-4337-860E-DB5710FB87DB}.Debug|x64.Build.0 = Debug|x64
|
{0B593A6C-4143-4337-860E-DB5710FB87DB}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{0B593A6C-4143-4337-860E-DB5710FB87DB}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{0B593A6C-4143-4337-860E-DB5710FB87DB}.Release|x64.ActiveCfg = Release|x64
|
{0B593A6C-4143-4337-860E-DB5710FB87DB}.Release|x64.ActiveCfg = Release|x64
|
||||||
{0B593A6C-4143-4337-860E-DB5710FB87DB}.Release|x64.Build.0 = Release|x64
|
{0B593A6C-4143-4337-860E-DB5710FB87DB}.Release|x64.Build.0 = Release|x64
|
||||||
|
{0B593A6C-4143-4337-860E-DB5710FB87DB}.Release|x86.ActiveCfg = Release|x64
|
||||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.ActiveCfg = Debug|x64
|
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.Build.0 = Debug|x64
|
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.ActiveCfg = Release|x64
|
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.ActiveCfg = Release|x64
|
||||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.Build.0 = Release|x64
|
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.Build.0 = Release|x64
|
||||||
|
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x86.ActiveCfg = Release|x64
|
||||||
{7319089E-46D6-4400-BC65-E39BDF1416EE}.Debug|x64.ActiveCfg = Debug|x64
|
{7319089E-46D6-4400-BC65-E39BDF1416EE}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{7319089E-46D6-4400-BC65-E39BDF1416EE}.Debug|x64.Build.0 = Debug|x64
|
{7319089E-46D6-4400-BC65-E39BDF1416EE}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{7319089E-46D6-4400-BC65-E39BDF1416EE}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{7319089E-46D6-4400-BC65-E39BDF1416EE}.Release|x64.ActiveCfg = Release|x64
|
{7319089E-46D6-4400-BC65-E39BDF1416EE}.Release|x64.ActiveCfg = Release|x64
|
||||||
{7319089E-46D6-4400-BC65-E39BDF1416EE}.Release|x64.Build.0 = Release|x64
|
{7319089E-46D6-4400-BC65-E39BDF1416EE}.Release|x64.Build.0 = Release|x64
|
||||||
|
{7319089E-46D6-4400-BC65-E39BDF1416EE}.Release|x86.ActiveCfg = Release|x64
|
||||||
{CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Debug|x64.ActiveCfg = Debug|x64
|
{CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Debug|x64.Build.0 = Debug|x64
|
{CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Release|x64.ActiveCfg = Release|x64
|
{CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Release|x64.ActiveCfg = Release|x64
|
||||||
{CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Release|x64.Build.0 = Release|x64
|
{CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Release|x64.Build.0 = Release|x64
|
||||||
|
{CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Release|x86.ActiveCfg = Release|x64
|
||||||
{98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Debug|x64.ActiveCfg = Debug|x64
|
{98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Debug|x64.Build.0 = Debug|x64
|
{98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Release|x64.ActiveCfg = Release|x64
|
{98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Release|x64.ActiveCfg = Release|x64
|
||||||
{98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Release|x64.Build.0 = Release|x64
|
{98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Release|x64.Build.0 = Release|x64
|
||||||
|
{98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Release|x86.ActiveCfg = Release|x64
|
||||||
{C3A17DCA-217B-462C-BB0C-BE086AF80081}.Debug|x64.ActiveCfg = Debug|x64
|
{C3A17DCA-217B-462C-BB0C-BE086AF80081}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{C3A17DCA-217B-462C-BB0C-BE086AF80081}.Debug|x64.Build.0 = Debug|x64
|
{C3A17DCA-217B-462C-BB0C-BE086AF80081}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{C3A17DCA-217B-462C-BB0C-BE086AF80081}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{C3A17DCA-217B-462C-BB0C-BE086AF80081}.Release|x64.ActiveCfg = Release|x64
|
{C3A17DCA-217B-462C-BB0C-BE086AF80081}.Release|x64.ActiveCfg = Release|x64
|
||||||
{C3A17DCA-217B-462C-BB0C-BE086AF80081}.Release|x64.Build.0 = Release|x64
|
{C3A17DCA-217B-462C-BB0C-BE086AF80081}.Release|x64.Build.0 = Release|x64
|
||||||
|
{C3A17DCA-217B-462C-BB0C-BE086AF80081}.Release|x86.ActiveCfg = Release|x64
|
||||||
{4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Debug|x64.ActiveCfg = Debug|x64
|
{4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Debug|x64.Build.0 = Debug|x64
|
{4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Release|x64.ActiveCfg = Release|x64
|
{4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Release|x64.ActiveCfg = Release|x64
|
||||||
{4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Release|x64.Build.0 = Release|x64
|
{4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Release|x64.Build.0 = Release|x64
|
||||||
|
{4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Release|x86.ActiveCfg = Release|x64
|
||||||
{0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Debug|x64.ActiveCfg = Debug|x64
|
{0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Debug|x64.Build.0 = Debug|x64
|
{0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Release|x64.ActiveCfg = Release|x64
|
{0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Release|x64.ActiveCfg = Release|x64
|
||||||
{0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Release|x64.Build.0 = Release|x64
|
{0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Release|x64.Build.0 = Release|x64
|
||||||
|
{0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Release|x86.ActiveCfg = Release|x64
|
||||||
{6ED2F4FC-E122-4CEE-90F1-97E4CCC8BC7A}.Debug|x64.ActiveCfg = Debug|x64
|
{6ED2F4FC-E122-4CEE-90F1-97E4CCC8BC7A}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{6ED2F4FC-E122-4CEE-90F1-97E4CCC8BC7A}.Debug|x64.Build.0 = Debug|x64
|
{6ED2F4FC-E122-4CEE-90F1-97E4CCC8BC7A}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{6ED2F4FC-E122-4CEE-90F1-97E4CCC8BC7A}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{6ED2F4FC-E122-4CEE-90F1-97E4CCC8BC7A}.Release|x64.ActiveCfg = Release|x64
|
{6ED2F4FC-E122-4CEE-90F1-97E4CCC8BC7A}.Release|x64.ActiveCfg = Release|x64
|
||||||
{6ED2F4FC-E122-4CEE-90F1-97E4CCC8BC7A}.Release|x64.Build.0 = Release|x64
|
{6ED2F4FC-E122-4CEE-90F1-97E4CCC8BC7A}.Release|x64.Build.0 = Release|x64
|
||||||
|
{6ED2F4FC-E122-4CEE-90F1-97E4CCC8BC7A}.Release|x86.ActiveCfg = Release|x64
|
||||||
{BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Debug|x64.ActiveCfg = Debug|x64
|
{BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Debug|x64.Build.0 = Debug|x64
|
{BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Release|x64.ActiveCfg = Release|x64
|
{BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Release|x64.ActiveCfg = Release|x64
|
||||||
{BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Release|x64.Build.0 = Release|x64
|
{BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Release|x64.Build.0 = Release|x64
|
||||||
|
{BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Release|x86.ActiveCfg = Release|x64
|
||||||
{E496B7FC-1E99-4BAB-849B-0E8367040B02}.Debug|x64.ActiveCfg = Debug|x64
|
{E496B7FC-1E99-4BAB-849B-0E8367040B02}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{E496B7FC-1E99-4BAB-849B-0E8367040B02}.Debug|x64.Build.0 = Debug|x64
|
{E496B7FC-1E99-4BAB-849B-0E8367040B02}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{E496B7FC-1E99-4BAB-849B-0E8367040B02}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{E496B7FC-1E99-4BAB-849B-0E8367040B02}.Release|x64.ActiveCfg = Release|x64
|
{E496B7FC-1E99-4BAB-849B-0E8367040B02}.Release|x64.ActiveCfg = Release|x64
|
||||||
{E496B7FC-1E99-4BAB-849B-0E8367040B02}.Release|x64.Build.0 = Release|x64
|
{E496B7FC-1E99-4BAB-849B-0E8367040B02}.Release|x64.Build.0 = Release|x64
|
||||||
|
{E496B7FC-1E99-4BAB-849B-0E8367040B02}.Release|x86.ActiveCfg = Release|x64
|
||||||
{7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Debug|x64.ActiveCfg = Debug|x64
|
{7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Debug|x64.Build.0 = Debug|x64
|
{7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Release|x64.ActiveCfg = Release|x64
|
{7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Release|x64.ActiveCfg = Release|x64
|
||||||
{7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Release|x64.Build.0 = Release|x64
|
{7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Release|x64.Build.0 = Release|x64
|
||||||
|
{7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Release|x86.ActiveCfg = Release|x64
|
||||||
{8DF78B53-200E-451F-9328-01EB907193AE}.Debug|x64.ActiveCfg = Debug|x64
|
{8DF78B53-200E-451F-9328-01EB907193AE}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{8DF78B53-200E-451F-9328-01EB907193AE}.Debug|x64.Build.0 = Debug|x64
|
{8DF78B53-200E-451F-9328-01EB907193AE}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{8DF78B53-200E-451F-9328-01EB907193AE}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{8DF78B53-200E-451F-9328-01EB907193AE}.Release|x64.ActiveCfg = Release|x64
|
{8DF78B53-200E-451F-9328-01EB907193AE}.Release|x64.ActiveCfg = Release|x64
|
||||||
{8DF78B53-200E-451F-9328-01EB907193AE}.Release|x64.Build.0 = Release|x64
|
{8DF78B53-200E-451F-9328-01EB907193AE}.Release|x64.Build.0 = Release|x64
|
||||||
|
{8DF78B53-200E-451F-9328-01EB907193AE}.Release|x86.ActiveCfg = Release|x64
|
||||||
{23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Debug|x64.ActiveCfg = Debug|x64
|
{23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Debug|x64.Build.0 = Debug|x64
|
{23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Release|x64.ActiveCfg = Release|x64
|
{23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Release|x64.ActiveCfg = Release|x64
|
||||||
{23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Release|x64.Build.0 = Release|x64
|
{23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Release|x64.Build.0 = Release|x64
|
||||||
|
{23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Release|x86.ActiveCfg = Release|x64
|
||||||
{62173D9A-6724-4C00-A1C8-FB646480A9EC}.Debug|x64.ActiveCfg = Debug|x64
|
{62173D9A-6724-4C00-A1C8-FB646480A9EC}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{62173D9A-6724-4C00-A1C8-FB646480A9EC}.Debug|x64.Build.0 = Debug|x64
|
{62173D9A-6724-4C00-A1C8-FB646480A9EC}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{62173D9A-6724-4C00-A1C8-FB646480A9EC}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{62173D9A-6724-4C00-A1C8-FB646480A9EC}.Release|x64.ActiveCfg = Release|x64
|
{62173D9A-6724-4C00-A1C8-FB646480A9EC}.Release|x64.ActiveCfg = Release|x64
|
||||||
{62173D9A-6724-4C00-A1C8-FB646480A9EC}.Release|x64.Build.0 = Release|x64
|
{62173D9A-6724-4C00-A1C8-FB646480A9EC}.Release|x64.Build.0 = Release|x64
|
||||||
{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Debug|x64.ActiveCfg = Debug|x64
|
{62173D9A-6724-4C00-A1C8-FB646480A9EC}.Release|x86.ActiveCfg = Release|x64
|
||||||
{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Release|x64.Build.0 = Release|x64
|
|
||||||
{5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Debug|x64.ActiveCfg = Debug|x64
|
{5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Debug|x64.Build.0 = Debug|x64
|
{5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Release|x64.ActiveCfg = Release|x64
|
{5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Release|x64.ActiveCfg = Release|x64
|
||||||
{5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Release|x64.Build.0 = Release|x64
|
{5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Release|x64.Build.0 = Release|x64
|
||||||
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Debug|x64.ActiveCfg = Debug|x64
|
{5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Release|x86.ActiveCfg = Release|x64
|
||||||
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Release|x64.Build.0 = Release|x64
|
|
||||||
{D940E07F-532C-4FF3-883F-790DA014F19A}.Debug|x64.ActiveCfg = Debug|x64
|
{D940E07F-532C-4FF3-883F-790DA014F19A}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{D940E07F-532C-4FF3-883F-790DA014F19A}.Debug|x64.Build.0 = Debug|x64
|
{D940E07F-532C-4FF3-883F-790DA014F19A}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{D940E07F-532C-4FF3-883F-790DA014F19A}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{D940E07F-532C-4FF3-883F-790DA014F19A}.Release|x64.ActiveCfg = Release|x64
|
{D940E07F-532C-4FF3-883F-790DA014F19A}.Release|x64.ActiveCfg = Release|x64
|
||||||
{D940E07F-532C-4FF3-883F-790DA014F19A}.Release|x64.Build.0 = Release|x64
|
{D940E07F-532C-4FF3-883F-790DA014F19A}.Release|x64.Build.0 = Release|x64
|
||||||
|
{D940E07F-532C-4FF3-883F-790DA014F19A}.Release|x86.ActiveCfg = Release|x64
|
||||||
|
{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
|
{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Release|x64.Build.0 = Release|x64
|
||||||
|
{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Release|x86.ActiveCfg = Release|x64
|
||||||
|
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
|
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Release|x64.Build.0 = Release|x64
|
||||||
|
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Release|x86.ActiveCfg = Release|x64
|
||||||
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Debug|x64.ActiveCfg = Debug|x64
|
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Debug|x64.Build.0 = Debug|x64
|
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|x64.ActiveCfg = Release|x64
|
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|x64.ActiveCfg = Release|x64
|
||||||
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|x64.Build.0 = Release|x64
|
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|x64.Build.0 = Release|x64
|
||||||
|
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|x86.ActiveCfg = Release|x64
|
||||||
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|x64.ActiveCfg = Debug|x64
|
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|x64.Build.0 = Debug|x64
|
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|x64.ActiveCfg = Release|x64
|
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|x64.ActiveCfg = Release|x64
|
||||||
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|x64.Build.0 = Release|x64
|
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|x64.Build.0 = Release|x64
|
||||||
|
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|x86.ActiveCfg = Release|x64
|
||||||
{48804216-2A0E-4168-A6D8-9CD068D14227}.Debug|x64.ActiveCfg = Debug|x64
|
{48804216-2A0E-4168-A6D8-9CD068D14227}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{48804216-2A0E-4168-A6D8-9CD068D14227}.Debug|x64.Build.0 = Debug|x64
|
{48804216-2A0E-4168-A6D8-9CD068D14227}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{48804216-2A0E-4168-A6D8-9CD068D14227}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{48804216-2A0E-4168-A6D8-9CD068D14227}.Release|x64.ActiveCfg = Release|x64
|
{48804216-2A0E-4168-A6D8-9CD068D14227}.Release|x64.ActiveCfg = Release|x64
|
||||||
{48804216-2A0E-4168-A6D8-9CD068D14227}.Release|x64.Build.0 = Release|x64
|
{48804216-2A0E-4168-A6D8-9CD068D14227}.Release|x64.Build.0 = Release|x64
|
||||||
{390AE700-B55F-4202-91EA-A822EB75B9BD}.Debug|x64.ActiveCfg = Debug|x64
|
{48804216-2A0E-4168-A6D8-9CD068D14227}.Release|x86.ActiveCfg = Release|x64
|
||||||
{390AE700-B55F-4202-91EA-A822EB75B9BD}.Debug|x64.Build.0 = Debug|x64
|
{FF1D7936-842A-4BBB-8BEA-E9FE796DE700}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{390AE700-B55F-4202-91EA-A822EB75B9BD}.Release|x64.ActiveCfg = Release|x64
|
{FF1D7936-842A-4BBB-8BEA-E9FE796DE700}.Debug|x64.Build.0 = Debug|x64
|
||||||
{390AE700-B55F-4202-91EA-A822EB75B9BD}.Release|x64.Build.0 = Release|x64
|
{FF1D7936-842A-4BBB-8BEA-E9FE796DE700}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
|
{FF1D7936-842A-4BBB-8BEA-E9FE796DE700}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{FF1D7936-842A-4BBB-8BEA-E9FE796DE700}.Release|x64.Build.0 = Release|x64
|
||||||
|
{FF1D7936-842A-4BBB-8BEA-E9FE796DE700}.Release|x86.ActiveCfg = Release|x64
|
||||||
{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Debug|x64.ActiveCfg = Debug|x64
|
{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Debug|x64.Build.0 = Debug|x64
|
{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Release|x64.ActiveCfg = Release|x64
|
{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Release|x64.ActiveCfg = Release|x64
|
||||||
{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Release|x64.Build.0 = Release|x64
|
{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Release|x64.Build.0 = Release|x64
|
||||||
|
{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Release|x86.ActiveCfg = Release|x64
|
||||||
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x64.ActiveCfg = Debug|x64
|
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x64.Build.0 = Debug|x64
|
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x64.ActiveCfg = Release|x64
|
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x64.ActiveCfg = Release|x64
|
||||||
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x64.Build.0 = Release|x64
|
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x64.Build.0 = Release|x64
|
||||||
|
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x86.ActiveCfg = Release|x64
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|x64.Build.0 = Release|x64
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
|
{5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Release|x64.Build.0 = Release|x64
|
||||||
|
{5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Release|x86.ActiveCfg = Release|x64
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x64.Build.0 = Release|x64
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x86.Build.0 = Release|Win32
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -809,16 +1029,20 @@ Global
|
|||||||
{23D2070D-E4AD-4ADD-85A7-083D9C76AD49} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
|
{23D2070D-E4AD-4ADD-85A7-083D9C76AD49} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
|
||||||
{62173D9A-6724-4C00-A1C8-FB646480A9EC} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
|
{62173D9A-6724-4C00-A1C8-FB646480A9EC} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
|
||||||
{127F38E0-40AA-4594-B955-5616BF206882} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
{127F38E0-40AA-4594-B955-5616BF206882} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||||
{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
|
|
||||||
{5E7360A8-D048-4ED3-8F09-0BFD64C5529A} = {127F38E0-40AA-4594-B955-5616BF206882}
|
{5E7360A8-D048-4ED3-8F09-0BFD64C5529A} = {127F38E0-40AA-4594-B955-5616BF206882}
|
||||||
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
|
|
||||||
{D940E07F-532C-4FF3-883F-790DA014F19A} = {127F38E0-40AA-4594-B955-5616BF206882}
|
{D940E07F-532C-4FF3-883F-790DA014F19A} = {127F38E0-40AA-4594-B955-5616BF206882}
|
||||||
|
{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
|
||||||
|
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
|
||||||
{106CBECA-0701-4FC3-838C-9DF816A19AE2} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
{106CBECA-0701-4FC3-838C-9DF816A19AE2} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||||
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81} = {106CBECA-0701-4FC3-838C-9DF816A19AE2}
|
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81} = {106CBECA-0701-4FC3-838C-9DF816A19AE2}
|
||||||
{2EDB3EB4-FA92-4BFF-B2D8-566584837231} = {106CBECA-0701-4FC3-838C-9DF816A19AE2}
|
{2EDB3EB4-FA92-4BFF-B2D8-566584837231} = {106CBECA-0701-4FC3-838C-9DF816A19AE2}
|
||||||
{48804216-2A0E-4168-A6D8-9CD068D14227} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
|
{48804216-2A0E-4168-A6D8-9CD068D14227} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
|
||||||
{390AE700-B55F-4202-91EA-A822EB75B9BD} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
|
{FF1D7936-842A-4BBB-8BEA-E9FE796DE700} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
|
||||||
{5043CECE-E6A7-4867-9CBE-02D27D83747A} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
|
{5043CECE-E6A7-4867-9CBE-02D27D83747A} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A} = {470FBAF9-E1F8-4F3E-8786-198A1C81C8A8}
|
||||||
|
{5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB} = {470FBAF9-E1F8-4F3E-8786-198A1C81C8A8}
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042} = {470FBAF9-E1F8-4F3E-8786-198A1C81C8A8}
|
||||||
|
{470FBAF9-E1F8-4F3E-8786-198A1C81C8A8} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
||||||
|
@ -66,7 +66,12 @@ Various tools used by PowerToys. Includes the Visual Studio 2019 project templat
|
|||||||
2. Visual Studio Community/Professional/Enterprise 2019
|
2. Visual Studio Community/Professional/Enterprise 2019
|
||||||
3. Once you've cloned and started the `PowerToys.sln`, in the solution explorer, if you see a dialog that says `install extra components`, click `install`
|
3. Once you've cloned and started the `PowerToys.sln`, in the solution explorer, if you see a dialog that says `install extra components`, click `install`
|
||||||
|
|
||||||
### Compile source code
|
**Optional step:**<br/>
|
||||||
|
4. to build the Video Conference module, install the [WDK version 1903](https://docs.microsoft.com/en-us/windows-hardware/drivers/other-wdk-downloads) ([direct download link](https://go.microsoft.com/fwlink/?linkid=2085767))<br />
|
||||||
|
During the installation, make sure that, when prompted, the `Install Windows Driver Kit Visual Studio extension` option is checked.
|
||||||
|
|
||||||
|
|
||||||
|
### Compiling Source Code
|
||||||
|
|
||||||
- Open `PowerToys.sln` in Visual Studio, in the `Solutions Configuration` drop-down menu select `Release` or `Debug`, from the `Build` menu choose `Build Solution`.
|
- Open `PowerToys.sln` in Visual Studio, in the `Solutions Configuration` drop-down menu select `Release` or `Debug`, from the `Build` menu choose `Build Solution`.
|
||||||
- The PowerToys binaries will be in your repo under `x64\Release\`.
|
- The PowerToys binaries will be in your repo under `x64\Release\`.
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<Import Project="..\packages\WiX.3.11.2\build\wix.props" Condition="Exists('..\packages\WiX.3.11.2\build\wix.props')" />
|
<Import Project="..\packages\WiX.3.11.2\build\wix.props" Condition="Exists('..\packages\WiX.3.11.2\build\wix.props')" />
|
||||||
<Import Project="..\..\src\Version.props" />
|
<Import Project="..\..\src\Version.props" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<DefineConstants>Version=$(Version);</DefineConstants>
|
<DefineConstants>Version=$(Version)</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
|
||||||
@ -74,7 +74,6 @@
|
|||||||
</Target>
|
</Target>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PreBuildEvent>IF NOT DEFINED IsPipeline (
|
<PreBuildEvent>IF NOT DEFINED IsPipeline (
|
||||||
|
|
||||||
call "$([MSBuild]::GetVsInstallRoot())\Common7\Tools\VsDevCmd.bat" -arch=amd64 -host_arch=amd64 -winsdk=10.0.18362.0
|
call "$([MSBuild]::GetVsInstallRoot())\Common7\Tools\VsDevCmd.bat" -arch=amd64 -host_arch=amd64 -winsdk=10.0.18362.0
|
||||||
SET PTRoot=..\..\..\..
|
SET PTRoot=..\..\..\..
|
||||||
call "..\..\publish.cmd"
|
call "..\..\publish.cmd"
|
||||||
|
@ -8,9 +8,11 @@
|
|||||||
<?define KeyboardManagerProjectName="KeyboardManager"?>
|
<?define KeyboardManagerProjectName="KeyboardManager"?>
|
||||||
<?define PowerRenameProjectName="PowerRename"?>
|
<?define PowerRenameProjectName="PowerRename"?>
|
||||||
<?define ColorPickerProjectName="ColorPicker"?>
|
<?define ColorPickerProjectName="ColorPicker"?>
|
||||||
|
<?define VideoConferenceProjectName="VideoConference"?>
|
||||||
<?define AwakeProjectName="Awake"?>
|
<?define AwakeProjectName="Awake"?>
|
||||||
|
|
||||||
<?define RepoDir="$(var.ProjectDir)..\..\" ?>
|
<?define RepoDir="$(var.ProjectDir)..\..\" ?>
|
||||||
|
<?define BinX32Dir="$(var.RepoDir)x86\$(var.Configuration)\" ?>
|
||||||
<?define BinX64Dir="$(var.RepoDir)x64\$(var.Configuration)\" ?>
|
<?define BinX64Dir="$(var.RepoDir)x64\$(var.Configuration)\" ?>
|
||||||
<?define ShortcutGuideExecutable=$(var.BinX64Dir)\modules\ShortcutGuide\ShortcutGuide?>
|
<?define ShortcutGuideExecutable=$(var.BinX64Dir)\modules\ShortcutGuide\ShortcutGuide?>
|
||||||
<?define ShortcutGuideModuleInterface=$(var.BinX64Dir)\modules\ShortcutGuide\ShortcutGuideModuleInterface?>
|
<?define ShortcutGuideModuleInterface=$(var.BinX64Dir)\modules\ShortcutGuide\ShortcutGuideModuleInterface?>
|
||||||
@ -218,6 +220,10 @@
|
|||||||
</Directory>
|
</Directory>
|
||||||
<Directory Id="ShortcutGuideModuleInterfaceInstallFolder" Name="ShortcutGuideModuleInterface"/>
|
<Directory Id="ShortcutGuideModuleInterfaceInstallFolder" Name="ShortcutGuideModuleInterface"/>
|
||||||
</Directory>
|
</Directory>
|
||||||
|
<!-- TODO(yuyoyuppe): uncomment when VCM should be enabled -->
|
||||||
|
<!-- <Directory Id="VideoConferenceInstallFolder" Name="$(var.VideoConferenceProjectName)">
|
||||||
|
<Directory Id="VideoConferenceIconsFolder" Name="Icons" />
|
||||||
|
</Directory> -->
|
||||||
<Directory Id="FileExplorerPreviewInstallFolder" Name="FileExplorerPreview" />
|
<Directory Id="FileExplorerPreviewInstallFolder" Name="FileExplorerPreview" />
|
||||||
<Directory Id="FancyZonesInstallFolder" Name="$(var.FancyZonesProjectName)" />
|
<Directory Id="FancyZonesInstallFolder" Name="$(var.FancyZonesProjectName)" />
|
||||||
<Directory Id="AwakeInstallFolder" Name="$(var.AwakeProjectName)">
|
<Directory Id="AwakeInstallFolder" Name="$(var.AwakeProjectName)">
|
||||||
@ -442,6 +448,9 @@
|
|||||||
<Component Id="BugReportTool_exe" Guid="0F8E3E9F-2E86-4660-A3BF-AE4DD431B93C" Win64="yes">
|
<Component Id="BugReportTool_exe" Guid="0F8E3E9F-2E86-4660-A3BF-AE4DD431B93C" Win64="yes">
|
||||||
<File Source="$(var.BinX64Dir)BugReportTool\BugReportTool.exe" Id="BugReportTool.exe" KeyPath="yes" Checksum="yes" />
|
<File Source="$(var.BinX64Dir)BugReportTool\BugReportTool.exe" Id="BugReportTool.exe" KeyPath="yes" Checksum="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component Id="WebcamReportTool_exe" Guid="B6005DAC-8C26-4865-91B3-99F098422C13" Win64="yes">
|
||||||
|
<File Source="$(var.BinX64Dir)WebcamReportTool\WebcamReportTool.exe" Id="WebcamReportTool.exe" Checksum="yes" />
|
||||||
|
</Component>
|
||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
|
|
||||||
<DirectoryRef Id="ModulesInstallFolder" FileSource="$(var.BinX64Dir)modules\">
|
<DirectoryRef Id="ModulesInstallFolder" FileSource="$(var.BinX64Dir)modules\">
|
||||||
@ -637,6 +646,37 @@
|
|||||||
</Component>
|
</Component>
|
||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
|
|
||||||
|
<!-- TODO(yuyoyuppe): uncomment when VCM should be enabled -->
|
||||||
|
<!-- <DirectoryRef Id="VideoConferenceInstallFolder" FileSource="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\">
|
||||||
|
<Component Id="Module_VideoConference" Guid="5996527a-40fc-432e-b3ac-abc0b4bd3887" Win64="yes">
|
||||||
|
<Condition>WINDOWSBUILDNUMBER >= 18362</Condition>
|
||||||
|
<File SelfRegCost="1" Source="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\VideoConferenceProxyFilter_x64.dll" KeyPath="yes">
|
||||||
|
<Class Id="{31AD75E9-8C3A-49C8-B9ED-5880D6B4A764}" Context="InprocServer32" ThreadingModel="apartment" Description="PowerToys VideoConference Mute" />
|
||||||
|
</File>
|
||||||
|
<File SelfRegCost="1" Source="$(var.BinX32Dir)modules\$(var.VideoConferenceProjectName)\VideoConferenceProxyFilter_x86.dll">
|
||||||
|
<Class Id="{31AD75E9-8C3A-49C8-B9ED-5880D6B4A732}" Context="InprocServer32" ThreadingModel="apartment" Description="PowerToys VideoConference Mute" />
|
||||||
|
</File>
|
||||||
|
<File Source="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\VideoConferenceModule.dll" />
|
||||||
|
</Component>
|
||||||
|
</DirectoryRef>
|
||||||
|
<DirectoryRef Id="VideoConferenceIconsFolder" FileSource="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\Icons">
|
||||||
|
<Component Id="Module_VideoConferenceIcons" Guid="5996527a-40fc-432e-b34c-abc0b4bd3887" Win64="yes">
|
||||||
|
<Condition>WINDOWSBUILDNUMBER >= 18362</Condition>
|
||||||
|
<File Source="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\Icons\Off-NotInUse Dark.png" />
|
||||||
|
<File Source="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\Icons\Off-NotInUse Light.png" />
|
||||||
|
<File Source="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\Icons\Off-Off Dark.png" />
|
||||||
|
<File Source="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\Icons\Off-Off Light.png" />
|
||||||
|
<File Source="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\Icons\Off-On Dark.png" />
|
||||||
|
<File Source="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\Icons\Off-On Light.png" />
|
||||||
|
<File Source="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\Icons\On-NotInUse Dark.png" />
|
||||||
|
<File Source="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\Icons\On-NotInUse Light.png" />
|
||||||
|
<File Source="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\Icons\On-Off Light.png" />
|
||||||
|
<File Source="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\Icons\On-Off Dark.png" />
|
||||||
|
<File Source="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\Icons\On-On Dark.png" />
|
||||||
|
<File Source="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\Icons\On-On Light.png" />
|
||||||
|
</Component>
|
||||||
|
</DirectoryRef> -->
|
||||||
|
|
||||||
<DirectoryRef Id="ShortcutGuideExecutableInstallFolder" FileSource="$(var.ShortcutGuideExecutable)">
|
<DirectoryRef Id="ShortcutGuideExecutableInstallFolder" FileSource="$(var.ShortcutGuideExecutable)">
|
||||||
<Component Id="Module_ShortcutGuideExecutable" Guid="DA6E5710-F1DF-44EB-A316-300FA39544E9" Win64="yes">
|
<Component Id="Module_ShortcutGuideExecutable" Guid="DA6E5710-F1DF-44EB-A316-300FA39544E9" Win64="yes">
|
||||||
<File Source="$(var.ShortcutGuideExecutable)\PowerToys.ShortcutGuide.exe" KeyPath="yes" />
|
<File Source="$(var.ShortcutGuideExecutable)\PowerToys.ShortcutGuide.exe" KeyPath="yes" />
|
||||||
@ -751,7 +791,7 @@
|
|||||||
<File Source="$(var.BinX64Dir)Settings\PowerToys.Settings.exe"/>
|
<File Source="$(var.BinX64Dir)Settings\PowerToys.Settings.exe"/>
|
||||||
<File Source="$(var.BinX64Dir)Settings\Microsoft.PowerToys.Settings.UI.exe"/>
|
<File Source="$(var.BinX64Dir)Settings\Microsoft.PowerToys.Settings.UI.exe"/>
|
||||||
<!-- dll -->
|
<!-- dll -->
|
||||||
<?foreach File in concrt140_app.dll;Microsoft.Bcl.AsyncInterfaces.dll;System.IO.Abstractions.dll;Microsoft.PowerToys.Settings.UI.Lib.dll;PowerToys.Settings.dll;Microsoft.Toolkit.dll;Microsoft.Toolkit.Uwp.dll;Microsoft.Toolkit.Uwp.UI.dll;Microsoft.Toolkit.Win32.UI.XamlHost.dll;Microsoft.Toolkit.Win32.UI.XamlHost.Managed.dll;Microsoft.Toolkit.Wpf.UI.Controls.dll;Microsoft.Toolkit.Wpf.UI.XamlHost.dll;Microsoft.UI.Xaml.dll;Microsoft.Xaml.Interactions.dll;Microsoft.Xaml.Interactivity.dll;msvcp140_1_app.dll;msvcp140_2_app.dll;msvcp140_app.dll;Newtonsoft.Json.dll;PowerToysInterop.dll;System.Runtime.CompilerServices.Unsafe.dll;System.Text.Encodings.Web.dll;System.Text.Json.dll;vcamp140_app.dll;vccorlib140_app.dll;vcomp140_app.dll;vcruntime140_1_app.dll;vcruntime140_app.dll;ManagedTelemetry.dll;ManagedCommon.dll;ColorCode.Core.dll;ColorCode.UWP.dll;Microsoft.Graphics.Canvas.winmd;Microsoft.Toolkit.Parsers.dll;Microsoft.Toolkit.Uwp.UI.Animations.dll;Microsoft.Toolkit.Uwp.UI.Controls.dll?>
|
<?foreach File in concrt140_app.dll;Microsoft.Bcl.AsyncInterfaces.dll;System.IO.Abstractions.dll;Microsoft.PowerToys.Settings.UI.Lib.dll;PowerToys.Settings.dll;Microsoft.Toolkit.dll;Microsoft.Toolkit.Uwp.dll;Microsoft.Toolkit.Uwp.UI.dll;Microsoft.Toolkit.Win32.UI.XamlHost.dll;Microsoft.Toolkit.Win32.UI.XamlHost.Managed.dll;Microsoft.Toolkit.Wpf.UI.Controls.dll;Microsoft.Toolkit.Wpf.UI.XamlHost.dll;Microsoft.UI.Xaml.dll;Microsoft.Xaml.Interactions.dll;Microsoft.Xaml.Interactivity.dll;msvcp140_1_app.dll;msvcp140_2_app.dll;msvcp140_app.dll;Newtonsoft.Json.dll;PowerToysInterop.dll;System.Runtime.CompilerServices.Unsafe.dll;System.Text.Encodings.Web.dll;System.Text.Json.dll;vcamp140_app.dll;vccorlib140_app.dll;vcomp140_app.dll;vcruntime140_1_app.dll;vcruntime140_app.dll;ManagedTelemetry.dll;ManagedCommon.dll;ColorCode.Core.dll;ColorCode.UWP.dll;Microsoft.Graphics.Canvas.winmd;Microsoft.Toolkit.Parsers.dll;Microsoft.Toolkit.Uwp.UI.Animations.dll;Microsoft.Toolkit.Uwp.UI.Controls.dll;System.Deployment.dll;System.Windows.Forms.dll;System.Runtime.Serialization.Formatters.Soap.dll?>
|
||||||
<File Id="SettingsV2_$(var.File)" Source="$(var.BinX64Dir)Settings\$(var.File)" />
|
<File Id="SettingsV2_$(var.File)" Source="$(var.BinX64Dir)Settings\$(var.File)" />
|
||||||
<?endforeach?>
|
<?endforeach?>
|
||||||
<!-- json -->
|
<!-- json -->
|
||||||
@ -791,7 +831,7 @@
|
|||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
<DirectoryRef Id="SettingsV2AssetsModulesInstallFolder" FileSource="$(var.BinX64Dir)Settings\Assets\Modules">
|
<DirectoryRef Id="SettingsV2AssetsModulesInstallFolder" FileSource="$(var.BinX64Dir)Settings\Assets\Modules">
|
||||||
<Component Id="SettingsV2AssetsModules" Guid="A0B961A9-77D0-4223-88A9-E3B41BD9C329" Win64="yes">
|
<Component Id="SettingsV2AssetsModules" Guid="A0B961A9-77D0-4223-88A9-E3B41BD9C329" Win64="yes">
|
||||||
<?foreach File in ColorPicker.png;FancyZones.png;Awake.png;ImageResizer.png;KBM.png;PowerLauncher.png;PowerPreview.png;PowerRename.png;PT.png;ShortcutGuide.png?>
|
<?foreach File in ColorPicker.png;FancyZones.png;Awake.png;ImageResizer.png;KBM.png;PowerLauncher.png;PowerPreview.png;PowerRename.png;PT.png;ShortcutGuide.png;VideoConference.png?>
|
||||||
<File Id="SettingsV2AssetsModules_$(var.File)" Source="$(var.BinX64Dir)Settings\Assets\Modules\$(var.File)" />
|
<File Id="SettingsV2AssetsModules_$(var.File)" Source="$(var.BinX64Dir)Settings\Assets\Modules\$(var.File)" />
|
||||||
<?endforeach?>
|
<?endforeach?>
|
||||||
</Component>
|
</Component>
|
||||||
@ -882,6 +922,9 @@
|
|||||||
<ComponentRef Id="ShortcutGuideSvgs" />
|
<ComponentRef Id="ShortcutGuideSvgs" />
|
||||||
<ComponentRef Id="Module_ShortcutGuideModuleInterface" />
|
<ComponentRef Id="Module_ShortcutGuideModuleInterface" />
|
||||||
<ComponentRef Id="Module_ShortcutGuideExecutable" />
|
<ComponentRef Id="Module_ShortcutGuideExecutable" />
|
||||||
|
<!-- TODO(yuyoyuppe): uncomment when VCM should be enabled -->
|
||||||
|
<!-- <ComponentRef Id="Module_VideoConference" />
|
||||||
|
<ComponentRef Id="Module_VideoConferenceIcons" /> -->
|
||||||
<ComponentRef Id="Module_FancyZones" />
|
<ComponentRef Id="Module_FancyZones" />
|
||||||
<ComponentRef Id="DesktopShortcut" />
|
<ComponentRef Id="DesktopShortcut" />
|
||||||
<ComponentRef Id="Module_PowerRename" />
|
<ComponentRef Id="Module_PowerRename" />
|
||||||
@ -911,6 +954,7 @@
|
|||||||
</ComponentGroup>
|
</ComponentGroup>
|
||||||
<ComponentGroup Id="ToolComponents" Directory="ToolsFolder">
|
<ComponentGroup Id="ToolComponents" Directory="ToolsFolder">
|
||||||
<ComponentRef Id="BugReportTool_exe" />
|
<ComponentRef Id="BugReportTool_exe" />
|
||||||
|
<ComponentRef Id="WebcamReportTool_exe" />
|
||||||
</ComponentGroup>
|
</ComponentGroup>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ TRACELOGGING_DEFINE_PROVIDER(
|
|||||||
const DWORD USERNAME_DOMAIN_LEN = DNLEN + UNLEN + 2; // Domain Name + '\' + User Name + '\0'
|
const DWORD USERNAME_DOMAIN_LEN = DNLEN + UNLEN + 2; // Domain Name + '\' + User Name + '\0'
|
||||||
const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0'
|
const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0'
|
||||||
|
|
||||||
|
static const wchar_t* POWERTOYS_EXE_COMPONENT = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}";
|
||||||
static const wchar_t* POWERTOYS_UPGRADE_CODE = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}";
|
static const wchar_t* POWERTOYS_UPGRADE_CODE = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}";
|
||||||
|
|
||||||
// Creates a Scheduled Task to run at logon for the current user.
|
// Creates a Scheduled Task to run at logon for the current user.
|
||||||
@ -596,6 +597,165 @@ UINT __stdcall DetectPrevInstallPathCA(MSIHANDLE hInstall)
|
|||||||
return WcaFinalize(er);
|
return WcaFinalize(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT __stdcall CertifyVirtualCameraDriverCA(MSIHANDLE hInstall)
|
||||||
|
{
|
||||||
|
#ifdef CIBuild // On pipeline we are using microsoft certification
|
||||||
|
WcaInitialize(hInstall, "CertifyVirtualCameraDriverCA");
|
||||||
|
return WcaFinalize(ERROR_SUCCESS);
|
||||||
|
#else
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
UINT er = ERROR_SUCCESS;
|
||||||
|
LPWSTR certificatePath = nullptr;
|
||||||
|
HCERTSTORE hCertStore = nullptr;
|
||||||
|
HANDLE hfile = nullptr;
|
||||||
|
DWORD size = INVALID_FILE_SIZE;
|
||||||
|
char * pFileContent = nullptr;
|
||||||
|
|
||||||
|
hr = WcaInitialize(hInstall, "CertifyVirtualCameraDriverCA");
|
||||||
|
ExitOnFailure(hr, "Failed to initialize", hr);
|
||||||
|
|
||||||
|
hr = WcaGetProperty(L"CustomActionData", &certificatePath);
|
||||||
|
ExitOnFailure(hr, "Failed to get install preperty", hr);
|
||||||
|
|
||||||
|
hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"AuthRoot");
|
||||||
|
if (!hCertStore)
|
||||||
|
{
|
||||||
|
hr = GetLastError();
|
||||||
|
ExitOnFailure(hr, "Cannot put principal run level: %x", hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
hfile = CreateFile(certificatePath, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
if (hfile == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
hr = GetLastError();
|
||||||
|
ExitOnFailure(hr, "Certificate file open failed", hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
size = GetFileSize(hfile, nullptr);
|
||||||
|
if (size == INVALID_FILE_SIZE)
|
||||||
|
{
|
||||||
|
hr = GetLastError();
|
||||||
|
ExitOnFailure(hr, "Certificate file size not valid", hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
pFileContent = (char*)malloc(size);
|
||||||
|
|
||||||
|
DWORD sizeread;
|
||||||
|
if (!ReadFile(hfile, pFileContent, size, &sizeread, nullptr))
|
||||||
|
{
|
||||||
|
hr = GetLastError();
|
||||||
|
ExitOnFailure(hr, "Certificate file read failed", hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CertAddEncodedCertificateToStore(hCertStore,
|
||||||
|
X509_ASN_ENCODING,
|
||||||
|
(const BYTE*)pFileContent,
|
||||||
|
size,
|
||||||
|
CERT_STORE_ADD_ALWAYS,
|
||||||
|
nullptr))
|
||||||
|
{
|
||||||
|
hr = GetLastError();
|
||||||
|
ExitOnFailure(hr, "Adding certificate failed", hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(pFileContent);
|
||||||
|
|
||||||
|
LExit:
|
||||||
|
ReleaseStr(certificatePath);
|
||||||
|
if (hCertStore)
|
||||||
|
{
|
||||||
|
CertCloseStore(hCertStore, 0);
|
||||||
|
}
|
||||||
|
if (hfile)
|
||||||
|
{
|
||||||
|
CloseHandle(hfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
PMSIHANDLE hRecord = MsiCreateRecord(0);
|
||||||
|
MsiRecordSetString(hRecord, 0, TEXT("Failed to add certificate to store"));
|
||||||
|
MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_WARNING + MB_OK), hRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||||
|
return WcaFinalize(er);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UINT __stdcall InstallVirtualCameraDriverCA(MSIHANDLE hInstall)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
UINT er = ERROR_SUCCESS;
|
||||||
|
LPWSTR driverPath = nullptr;
|
||||||
|
|
||||||
|
hr = WcaInitialize(hInstall, "InstallVirtualCameraDriverCA");
|
||||||
|
ExitOnFailure(hr, "Failed to initialize");
|
||||||
|
|
||||||
|
hr = WcaGetProperty(L"CustomActionData", &driverPath);
|
||||||
|
ExitOnFailure(hr, "Failed to get install preperty");
|
||||||
|
|
||||||
|
BOOL requiresReboot;
|
||||||
|
DiInstallDriverW(GetConsoleWindow(), driverPath, DIIRFLAG_FORCE_INF, &requiresReboot);
|
||||||
|
|
||||||
|
hr = GetLastError();
|
||||||
|
ExitOnFailure(hr, "Failed to install driver");
|
||||||
|
|
||||||
|
LExit:
|
||||||
|
|
||||||
|
if (!SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
PMSIHANDLE hRecord = MsiCreateRecord(0);
|
||||||
|
MsiRecordSetString(hRecord, 0, TEXT("Failed to install virtual camera driver"));
|
||||||
|
MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_WARNING + MB_OK), hRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||||
|
return WcaFinalize(er);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT __stdcall UninstallVirtualCameraDriverCA(MSIHANDLE hInstall)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
UINT er = ERROR_SUCCESS;
|
||||||
|
LPWSTR driverPath = nullptr;
|
||||||
|
|
||||||
|
hr = WcaInitialize(hInstall, "UninstallVirtualCameraDriverCA");
|
||||||
|
ExitOnFailure(hr, "Failed to initialize");
|
||||||
|
|
||||||
|
hr = WcaGetProperty(L"CustomActionData", &driverPath);
|
||||||
|
ExitOnFailure(hr, "Failed to get uninstall preperty");
|
||||||
|
|
||||||
|
BOOL requiresReboot;
|
||||||
|
DiUninstallDriverW(GetConsoleWindow(), driverPath, 0, &requiresReboot);
|
||||||
|
|
||||||
|
switch (GetLastError())
|
||||||
|
{
|
||||||
|
case ERROR_ACCESS_DENIED:
|
||||||
|
case ERROR_FILE_NOT_FOUND:
|
||||||
|
case ERROR_INVALID_FLAGS:
|
||||||
|
case ERROR_IN_WOW64:
|
||||||
|
{
|
||||||
|
hr = GetLastError();
|
||||||
|
ExitOnFailure(hr, "Failed to uninstall driver");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LExit:
|
||||||
|
|
||||||
|
if (!SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
PMSIHANDLE hRecord = MsiCreateRecord(0);
|
||||||
|
MsiRecordSetString(hRecord, 0, TEXT("Filed to iminstall virtual camera driver"));
|
||||||
|
MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_WARNING + MB_OK), hRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||||
|
return WcaFinalize(er);
|
||||||
|
}
|
||||||
|
|
||||||
UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||||
{
|
{
|
||||||
|
@ -13,3 +13,7 @@ EXPORTS
|
|||||||
TelemetryLogRepairCancelCA
|
TelemetryLogRepairCancelCA
|
||||||
TelemetryLogRepairFailCA
|
TelemetryLogRepairFailCA
|
||||||
TerminateProcessesCA
|
TerminateProcessesCA
|
||||||
|
TerminateProcessesCA
|
||||||
|
CertifyVirtualCameraDriverCA
|
||||||
|
InstallVirtualCameraDriverCA
|
||||||
|
UninstallVirtualCameraDriverCA
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalLibraryDirectories>$(WIX)sdk\$(WixPlatformToolset)\lib\x64;$(SolutionDir)\packages\WiX.3.11.2\tools\sdk\vs2017\lib\x64;..\..\$(PlatformShortName)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(WIX)sdk\$(WixPlatformToolset)\lib\x64;$(SolutionDir)\packages\WiX.3.11.2\tools\sdk\vs2017\lib\x64;..\..\$(PlatformShortName)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>msi.lib;wcautil.lib;Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;ApplicationUpdate.lib;Notifications.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Newdev.lib;Crypt32.lib;msi.lib;wcautil.lib;Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;ApplicationUpdate.lib;Notifications.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#define DPSAPI_VERSION 1
|
#define DPSAPI_VERSION 1
|
||||||
// Windows Header Files:
|
// Windows Header Files:
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <newdev.h>
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
#include <msiquery.h>
|
#include <msiquery.h>
|
||||||
#include <Msi.h>
|
#include <Msi.h>
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "pch.h"
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#define NOMINMAX
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
class FileWatcher
|
class FileWatcher
|
||||||
{
|
{
|
@ -28,10 +28,12 @@
|
|||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
<ClInclude Include="settings_helpers.h" />
|
<ClInclude Include="settings_helpers.h" />
|
||||||
<ClInclude Include="settings_objects.h" />
|
<ClInclude Include="settings_objects.h" />
|
||||||
|
<ClInclude Include="FileWatcher.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="settings_helpers.cpp" />
|
<ClCompile Include="settings_helpers.cpp" />
|
||||||
<ClCompile Include="settings_objects.cpp" />
|
<ClCompile Include="settings_objects.cpp" />
|
||||||
|
<ClCompile Include="FileWatcher.cpp" />
|
||||||
<ClCompile Include="pch.cpp">
|
<ClCompile Include="pch.cpp">
|
||||||
<PrecompiledHeader Condition="'$(CIBuild)'!='true'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(CIBuild)'!='true'">Create</PrecompiledHeader>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -8,6 +8,7 @@ namespace PTSettingsHelper
|
|||||||
{
|
{
|
||||||
constexpr inline const wchar_t* log_settings_filename = L"log_settings.json";
|
constexpr inline const wchar_t* log_settings_filename = L"log_settings.json";
|
||||||
|
|
||||||
|
std::wstring get_powertoys_general_save_file_location();
|
||||||
std::wstring get_module_save_file_location(std::wstring_view powertoy_key);
|
std::wstring get_module_save_file_location(std::wstring_view powertoy_key);
|
||||||
std::wstring get_module_save_folder_location(std::wstring_view powertoy_name);
|
std::wstring get_module_save_folder_location(std::wstring_view powertoy_name);
|
||||||
std::wstring get_root_save_folder_location();
|
std::wstring get_root_save_folder_location();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <TraceLoggingProvider.h>
|
#include "TraceLoggingProvider.h"
|
||||||
#include <TraceLoggingDefines.h>
|
#include "TraceLoggingDefines.h"
|
||||||
|
|
||||||
TRACELOGGING_DECLARE_PROVIDER(g_hProvider);
|
TRACELOGGING_DECLARE_PROVIDER(g_hProvider);
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup>
|
<ItemDefinitionGroup>
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
|
<PreprocessorDefinitions>PowerToysInterop;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)src\common\interop;../../;../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)src\common\interop;../../;../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<OmitDefaultLibName>false</OmitDefaultLibName>
|
<OmitDefaultLibName>false</OmitDefaultLibName>
|
||||||
@ -54,7 +55,7 @@
|
|||||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Mf.lib;WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -83,6 +84,8 @@
|
|||||||
<WriteLinesToFile File="Generated Files\AssemblyInfo.cpp" Lines="@(HeaderLines)" Overwrite="true" Encoding="Unicode" WriteOnlyWhenDifferent="true" />
|
<WriteLinesToFile File="Generated Files\AssemblyInfo.cpp" Lines="@(HeaderLines)" Overwrite="true" Encoding="Unicode" WriteOnlyWhenDifferent="true" />
|
||||||
</Target>
|
</Target>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\modules\videoconference\VideoConferenceShared\MicrophoneDevice.h" />
|
||||||
|
<ClInclude Include="..\..\modules\videoconference\VideoConferenceShared\VideoCaptureDeviceList.h" />
|
||||||
<ClInclude Include="HotkeyManager.h" />
|
<ClInclude Include="HotkeyManager.h" />
|
||||||
<ClInclude Include="KeyboardHook.h" />
|
<ClInclude Include="KeyboardHook.h" />
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
@ -90,6 +93,12 @@
|
|||||||
<ClInclude Include="shared_constants.h" />
|
<ClInclude Include="shared_constants.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\modules\videoconference\VideoConferenceShared\MicrophoneDevice.cpp">
|
||||||
|
<CompileAsManaged>false</CompileAsManaged>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\modules\videoconference\VideoConferenceShared\VideoCaptureDeviceList.cpp">
|
||||||
|
<CompileAsManaged>false</CompileAsManaged>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="Generated Files\AssemblyInfo.cpp" />
|
<ClCompile Include="Generated Files\AssemblyInfo.cpp" />
|
||||||
<ClCompile Include="HotkeyManager.cpp" />
|
<ClCompile Include="HotkeyManager.cpp" />
|
||||||
<ClCompile Include="interop.cpp" />
|
<ClCompile Include="interop.cpp" />
|
||||||
@ -109,6 +118,12 @@
|
|||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||||
|
</ImportGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
@ -27,6 +27,12 @@
|
|||||||
<ClInclude Include="resource.h">
|
<ClInclude Include="resource.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\modules\videoconference\VideoConferenceShared\MicrophoneDevice.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\modules\videoconference\VideoConferenceShared\VideoCaptureDeviceList.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="shared_constants.h">
|
<ClInclude Include="shared_constants.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -50,6 +56,12 @@
|
|||||||
<ClCompile Include="keyboard_layout.cpp">
|
<ClCompile Include="keyboard_layout.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\modules\videoconference\VideoConferenceShared\MicrophoneDevice.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\modules\videoconference\VideoConferenceShared\VideoCaptureDeviceList.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="interop.rc">
|
<ResourceCompile Include="interop.rc">
|
||||||
|
@ -13,12 +13,17 @@
|
|||||||
// Therefore the simplest way is to compile these functions as native using the pragmas below.
|
// Therefore the simplest way is to compile these functions as native using the pragmas below.
|
||||||
#pragma managed(push, off)
|
#pragma managed(push, off)
|
||||||
#include "../utils/os-detect.h"
|
#include "../utils/os-detect.h"
|
||||||
|
// TODO: move to a separate library in common
|
||||||
|
#include "../../modules/videoconference/VideoConferenceShared/MicrophoneDevice.h"
|
||||||
|
#include "../../modules/videoconference/VideoConferenceShared/VideoCaptureDeviceList.h"
|
||||||
#pragma managed(pop)
|
#pragma managed(pop)
|
||||||
|
|
||||||
#include <common/version/version.h>
|
#include <common/version/version.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace System;
|
using namespace System;
|
||||||
using namespace System::Runtime::InteropServices;
|
using namespace System::Runtime::InteropServices;
|
||||||
|
using System::Collections::Generic::List;
|
||||||
|
|
||||||
// https://docs.microsoft.com/en-us/cpp/dotnet/how-to-wrap-native-class-for-use-by-csharp?view=vs-2019
|
// https://docs.microsoft.com/en-us/cpp/dotnet/how-to-wrap-native-class-for-use-by-csharp?view=vs-2019
|
||||||
namespace interop
|
namespace interop
|
||||||
@ -122,6 +127,32 @@ public
|
|||||||
static String ^ GetProductVersion() {
|
static String ^ GetProductVersion() {
|
||||||
return gcnew String(get_product_version().c_str());
|
return gcnew String(get_product_version().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static List<String ^> ^ GetAllActiveMicrophoneDeviceNames() {
|
||||||
|
auto names = gcnew List<String ^>();
|
||||||
|
for (const auto& device : MicrophoneDevice::getAllActive())
|
||||||
|
{
|
||||||
|
names->Add(gcnew String(device.name().data()));
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<String ^> ^
|
||||||
|
GetAllVideoCaptureDeviceNames() {
|
||||||
|
auto names = gcnew List<String ^>();
|
||||||
|
VideoCaptureDeviceList vcdl;
|
||||||
|
vcdl.EnumerateDevices();
|
||||||
|
|
||||||
|
for (UINT32 i = 0; i < vcdl.Count(); ++i)
|
||||||
|
{
|
||||||
|
auto name = gcnew String(vcdl.GetDeviceName(i).data());
|
||||||
|
if (name != L"PowerToys VideoConference Mute")
|
||||||
|
{
|
||||||
|
names->Add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public
|
public
|
||||||
|
4
src/common/interop/packages.config
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.200902.2" targetFramework="native" />
|
||||||
|
</packages>
|
@ -7,13 +7,13 @@
|
|||||||
#include <common/utils/resources.h>
|
#include <common/utils/resources.h>
|
||||||
#include <common/utils/winapi_error.h>
|
#include <common/utils/winapi_error.h>
|
||||||
#include <common/utils/window.h>
|
#include <common/utils/window.h>
|
||||||
|
#include <common/SettingsAPI/FileWatcher.h>
|
||||||
|
|
||||||
#include "FancyZones.h"
|
#include "FancyZones.h"
|
||||||
#include "FancyZonesLib/Settings.h"
|
#include "FancyZonesLib/Settings.h"
|
||||||
#include "FancyZonesLib/ZoneWindow.h"
|
#include "FancyZonesLib/ZoneWindow.h"
|
||||||
#include "FancyZonesLib/FancyZonesData.h"
|
#include "FancyZonesLib/FancyZonesData.h"
|
||||||
#include "FancyZonesLib/ZoneSet.h"
|
#include "FancyZonesLib/ZoneSet.h"
|
||||||
#include "FancyZonesLib/FileWatcher.h"
|
|
||||||
#include "FancyZonesLib/WindowMoveHandler.h"
|
#include "FancyZonesLib/WindowMoveHandler.h"
|
||||||
#include "FancyZonesLib/FancyZonesWinHookEventIDs.h"
|
#include "FancyZonesLib/FancyZonesWinHookEventIDs.h"
|
||||||
#include "FancyZonesLib/util.h"
|
#include "FancyZonesLib/util.h"
|
||||||
|
@ -41,7 +41,6 @@
|
|||||||
<ClInclude Include="FancyZones.h" />
|
<ClInclude Include="FancyZones.h" />
|
||||||
<ClInclude Include="FancyZonesDataTypes.h" />
|
<ClInclude Include="FancyZonesDataTypes.h" />
|
||||||
<ClInclude Include="FancyZonesWinHookEventIDs.h" />
|
<ClInclude Include="FancyZonesWinHookEventIDs.h" />
|
||||||
<ClInclude Include="FileWatcher.h" />
|
|
||||||
<ClInclude Include="GenericKeyHook.h" />
|
<ClInclude Include="GenericKeyHook.h" />
|
||||||
<ClInclude Include="FancyZonesData.h" />
|
<ClInclude Include="FancyZonesData.h" />
|
||||||
<ClInclude Include="JsonHelpers.h" />
|
<ClInclude Include="JsonHelpers.h" />
|
||||||
@ -67,7 +66,6 @@
|
|||||||
<ClCompile Include="FancyZonesDataTypes.cpp" />
|
<ClCompile Include="FancyZonesDataTypes.cpp" />
|
||||||
<ClCompile Include="FancyZonesWinHookEventIDs.cpp" />
|
<ClCompile Include="FancyZonesWinHookEventIDs.cpp" />
|
||||||
<ClCompile Include="FancyZonesData.cpp" />
|
<ClCompile Include="FancyZonesData.cpp" />
|
||||||
<ClCompile Include="FileWatcher.cpp" />
|
|
||||||
<ClCompile Include="JsonHelpers.cpp" />
|
<ClCompile Include="JsonHelpers.cpp" />
|
||||||
<ClCompile Include="MonitorWorkAreaHandler.cpp" />
|
<ClCompile Include="MonitorWorkAreaHandler.cpp" />
|
||||||
<ClCompile Include="OnThreadExecutor.cpp" />
|
<ClCompile Include="OnThreadExecutor.cpp" />
|
||||||
|
@ -78,9 +78,6 @@
|
|||||||
<ClInclude Include="ZoneWindowDrawing.h">
|
<ClInclude Include="ZoneWindowDrawing.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="FileWatcher.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="CallTracer.h">
|
<ClInclude Include="CallTracer.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -140,9 +137,6 @@
|
|||||||
<ClCompile Include="OnThreadExecutor.cpp">
|
<ClCompile Include="OnThreadExecutor.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="FileWatcher.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="CallTracer.cpp">
|
<ClCompile Include="CallTracer.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
After Width: | Height: | Size: 3.9 KiB |
@ -0,0 +1,19 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="322" height="44" viewBox="0 0 322 44">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip-Off-Disabled">
|
||||||
|
<rect width="322" height="44"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<g id="Off-Disabled" clip-path="url(#clip-Off-Disabled)">
|
||||||
|
<rect width="322" height="44" fill="#f1f1f1"/>
|
||||||
|
<g id="Background" fill="#1f1f1f">
|
||||||
|
<path d="M 321.5 43.5 L 0.5 43.5 L 0.5 0.5 L 321.5 0.5 L 321.5 43.5 Z" stroke="none"/>
|
||||||
|
<path d="M 1 1 L 1 43 L 321 43 L 321 1 L 1 1 M 0 0 L 322 0 L 322 44 L 0 44 L 0 0 Z" stroke="none" fill="#313131"/>
|
||||||
|
</g>
|
||||||
|
<rect id="Divider" width="1" height="24" transform="translate(161 10)" fill="#313131"/>
|
||||||
|
<text id="Camera_label" data-name="Camera label" transform="translate(200 13)" fill="#585858" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Camera not in use</tspan></text>
|
||||||
|
<path id="Camera_disabled_icon" data-name="Camera disabled icon" d="M12.5,509.031a3.408,3.408,0,0,1,1.359.272,3.634,3.634,0,0,1,1.117.745,3.348,3.348,0,0,1,.75,1.1A3.555,3.555,0,0,1,16,512.508a3.35,3.35,0,0,1-.273,1.351,3.608,3.608,0,0,1-.75,1.11,3.371,3.371,0,0,1-1.109.745,3.617,3.617,0,0,1-1.367.272,3.407,3.407,0,0,1-1.359-.272,3.634,3.634,0,0,1-1.117-.745,3.347,3.347,0,0,1-.75-1.1A3.555,3.555,0,0,1,9,512.508a3.351,3.351,0,0,1,.273-1.351,3.608,3.608,0,0,1,.75-1.11,3.371,3.371,0,0,1,1.109-.745A3.616,3.616,0,0,1,12.5,509.031ZM10,512.508a2.393,2.393,0,0,0,.2.963,2.585,2.585,0,0,0,.531.792,2.423,2.423,0,0,0,.8.536,2.491,2.491,0,0,0,.977.194,2.591,2.591,0,0,0,.719-.1,2.241,2.241,0,0,0,.656-.31l-3.461-3.439a2.334,2.334,0,0,0-.3.652A2.76,2.76,0,0,0,10,512.508Zm4.586,1.366a2.333,2.333,0,0,0,.3-.652,2.759,2.759,0,0,0,.109-.714,2.393,2.393,0,0,0-.2-.963,2.428,2.428,0,0,0-.539-.784,2.725,2.725,0,0,0-.8-.536,2.353,2.353,0,0,0-.969-.2,2.593,2.593,0,0,0-.719.1,2.245,2.245,0,0,0-.656.311ZM16,504v5.326a4.453,4.453,0,0,0-1-.823v-2.9l-3,1.5v.714a4.157,4.157,0,0,0-.508.078,4.1,4.1,0,0,0-.492.14v-2.981H1v5.962H8a4.038,4.038,0,0,0-.219.994H0v-7.95H12v1.925Z" transform="translate(171 -486)" fill="#585858"/>
|
||||||
|
<path id="Mic_off_icon" data-name="Mic off icon" d="M23.943,2.531l-1.019-1V1.5a1.448,1.448,0,0,1,.119-.586A1.5,1.5,0,0,1,23.37.437,1.538,1.538,0,0,1,24.453,0h4.076a1.538,1.538,0,0,1,1.083.437,1.5,1.5,0,0,1,.326.477,1.448,1.448,0,0,1,.119.586V8.531l-1.019-1V1.5a.472.472,0,0,0-.143-.352A.529.529,0,0,0,28.528,1H24.453a.491.491,0,0,0-.358.141.509.509,0,0,0-.151.359ZM32.095,8v2.523l-1.019-.992V8ZM35,15.148l-.716.7-3-2.945a3.218,3.218,0,0,1-1.106.8A3.388,3.388,0,0,1,28.831,14H27v1h2.038v1H23.943V15h2.038V14H24.15a3.206,3.206,0,0,1-1.266-.25,3.307,3.307,0,0,1-1.035-.687,3.239,3.239,0,0,1-.7-1.016,3.16,3.16,0,0,1-.263-1.25V8h1.019v2.8a2.093,2.093,0,0,0,.175.852,2.238,2.238,0,0,0,.486.7,2.2,2.2,0,0,0,.708.469,2.493,2.493,0,0,0,.876.18h4.681a2.187,2.187,0,0,0,.947-.211,2.427,2.427,0,0,0,.78-.586l-.812-.8a1.486,1.486,0,0,1-.533.438,1.613,1.613,0,0,1-.685.164H24.453a1.538,1.538,0,0,1-1.083-.437,1.5,1.5,0,0,1-.326-.477,1.448,1.448,0,0,1-.119-.586V4.711L19,.852l.716-.7ZM28.528,11a.5.5,0,0,0,.287-.086.526.526,0,0,0,.191-.234L23.943,5.711V10.5a.472.472,0,0,0,.143.352.529.529,0,0,0,.366.148Z" transform="translate(-9 14)" fill="#fff"/>
|
||||||
|
<text id="Mic_label" data-name="Mic label" transform="translate(38 13)" fill="#fff" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Microphone off</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.8 KiB |
@ -0,0 +1,19 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="322" height="44" viewBox="0 0 322 44">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip-Off-Disabled_Light">
|
||||||
|
<rect width="322" height="44"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<g id="Off-Disabled_Light" data-name="Off-Disabled Light" clip-path="url(#clip-Off-Disabled_Light)">
|
||||||
|
<rect width="322" height="44" fill="#f1f1f1"/>
|
||||||
|
<g id="Background" fill="#f1f1f1">
|
||||||
|
<path d="M 321.5 43.5 L 0.5 43.5 L 0.5 0.5 L 321.5 0.5 L 321.5 43.5 Z" stroke="none"/>
|
||||||
|
<path d="M 1 1 L 1 43 L 321 43 L 321 1 L 1 1 M 0 0 L 322 0 L 322 44 L 0 44 L 0 0 Z" stroke="none" fill="#dbdbdb"/>
|
||||||
|
</g>
|
||||||
|
<rect id="Divider" width="1" height="24" transform="translate(161 10)" fill="#dbdbdb"/>
|
||||||
|
<text id="Camera_label" data-name="Camera label" transform="translate(200 13)" fill="#c1c1c1" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Camera not in use</tspan></text>
|
||||||
|
<path id="Camera_disabled_icon" data-name="Camera disabled icon" d="M12.5,509.031a3.408,3.408,0,0,1,1.359.272,3.634,3.634,0,0,1,1.117.745,3.348,3.348,0,0,1,.75,1.1A3.555,3.555,0,0,1,16,512.508a3.35,3.35,0,0,1-.273,1.351,3.608,3.608,0,0,1-.75,1.11,3.371,3.371,0,0,1-1.109.745,3.617,3.617,0,0,1-1.367.272,3.407,3.407,0,0,1-1.359-.272,3.634,3.634,0,0,1-1.117-.745,3.347,3.347,0,0,1-.75-1.1A3.555,3.555,0,0,1,9,512.508a3.351,3.351,0,0,1,.273-1.351,3.608,3.608,0,0,1,.75-1.11,3.371,3.371,0,0,1,1.109-.745A3.616,3.616,0,0,1,12.5,509.031ZM10,512.508a2.393,2.393,0,0,0,.2.963,2.585,2.585,0,0,0,.531.792,2.423,2.423,0,0,0,.8.536,2.491,2.491,0,0,0,.977.194,2.591,2.591,0,0,0,.719-.1,2.241,2.241,0,0,0,.656-.31l-3.461-3.439a2.334,2.334,0,0,0-.3.652A2.76,2.76,0,0,0,10,512.508Zm4.586,1.366a2.333,2.333,0,0,0,.3-.652,2.759,2.759,0,0,0,.109-.714,2.393,2.393,0,0,0-.2-.963,2.428,2.428,0,0,0-.539-.784,2.725,2.725,0,0,0-.8-.536,2.353,2.353,0,0,0-.969-.2,2.593,2.593,0,0,0-.719.1,2.245,2.245,0,0,0-.656.311ZM16,504v5.326a4.453,4.453,0,0,0-1-.823v-2.9l-3,1.5v.714a4.157,4.157,0,0,0-.508.078,4.1,4.1,0,0,0-.492.14v-2.981H1v5.962H8a4.038,4.038,0,0,0-.219.994H0v-7.95H12v1.925Z" transform="translate(171 -486)" fill="#c1c1c1"/>
|
||||||
|
<path id="Mic_off_icon" data-name="Mic off icon" d="M23.943,2.531l-1.019-1V1.5a1.448,1.448,0,0,1,.119-.586A1.5,1.5,0,0,1,23.37.437,1.538,1.538,0,0,1,24.453,0h4.076a1.538,1.538,0,0,1,1.083.437,1.5,1.5,0,0,1,.326.477,1.448,1.448,0,0,1,.119.586V8.531l-1.019-1V1.5a.472.472,0,0,0-.143-.352A.529.529,0,0,0,28.528,1H24.453a.491.491,0,0,0-.358.141.509.509,0,0,0-.151.359ZM32.095,8v2.523l-1.019-.992V8ZM35,15.148l-.716.7-3-2.945a3.218,3.218,0,0,1-1.106.8A3.388,3.388,0,0,1,28.831,14H27v1h2.038v1H23.943V15h2.038V14H24.15a3.206,3.206,0,0,1-1.266-.25,3.307,3.307,0,0,1-1.035-.687,3.239,3.239,0,0,1-.7-1.016,3.16,3.16,0,0,1-.263-1.25V8h1.019v2.8a2.093,2.093,0,0,0,.175.852,2.238,2.238,0,0,0,.486.7,2.2,2.2,0,0,0,.708.469,2.493,2.493,0,0,0,.876.18h4.681a2.187,2.187,0,0,0,.947-.211,2.427,2.427,0,0,0,.78-.586l-.812-.8a1.486,1.486,0,0,1-.533.438,1.613,1.613,0,0,1-.685.164H24.453a1.538,1.538,0,0,1-1.083-.437,1.5,1.5,0,0,1-.326-.477,1.448,1.448,0,0,1-.119-.586V4.711L19,.852l.716-.7ZM28.528,11a.5.5,0,0,0,.287-.086.526.526,0,0,0,.191-.234L23.943,5.711V10.5a.472.472,0,0,0,.143.352.529.529,0,0,0,.366.148Z" transform="translate(-9 14)"/>
|
||||||
|
<text id="Mic_label" data-name="Mic label" transform="translate(38 13)" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Microphone off</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.7 KiB |
@ -0,0 +1,19 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="322" height="44" viewBox="0 0 322 44">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip-Off-Off_Dark">
|
||||||
|
<rect width="322" height="44"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<g id="Off-Off_Dark" data-name="Off-Off Dark" clip-path="url(#clip-Off-Off_Dark)">
|
||||||
|
<rect width="322" height="44" fill="#f1f1f1"/>
|
||||||
|
<g id="Background" fill="#1f1f1f">
|
||||||
|
<path d="M 321.5 43.5 L 0.5 43.5 L 0.5 0.5 L 321.5 0.5 L 321.5 43.5 Z" stroke="none"/>
|
||||||
|
<path d="M 1 1 L 1 43 L 321 43 L 321 1 L 1 1 M 0 0 L 322 0 L 322 44 L 0 44 L 0 0 Z" stroke="none" fill="#313131"/>
|
||||||
|
</g>
|
||||||
|
<rect id="Divider" width="1" height="24" transform="translate(161 10)" fill="#313131"/>
|
||||||
|
<text id="Camera_label" data-name="Camera label" transform="translate(200 13)" fill="#fff" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Camera off</tspan></text>
|
||||||
|
<path id="Camera_off_icon" data-name="Camera off icon" d="M12,24.9l4-2.038v8.279l-1.953-1q-.141-.072-.258-.119t-.242-.1a1.825,1.825,0,0,1-.227-.119l-.25-.159a1.726,1.726,0,0,1-.2-.159,1.556,1.556,0,0,1-.156-.167q-.07-.088-.148-.175l-.18-.2L11,27.533v-3.59H7.477l-1-1.019H12Zm3,4.593V24.508l-3,1.536v1.91ZM.148,19.716.852,19l15,15.284-.7.716-3.859-3.924H0V22.924H3.289ZM1,30.057h9.289l-6-6.113H1Z" transform="translate(171 -5)" fill="#fff"/>
|
||||||
|
<path id="Mic_off_icon" data-name="Mic off icon" d="M23.943,2.531l-1.019-1V1.5a1.448,1.448,0,0,1,.119-.586A1.5,1.5,0,0,1,23.37.437,1.538,1.538,0,0,1,24.453,0h4.076a1.538,1.538,0,0,1,1.083.437,1.5,1.5,0,0,1,.326.477,1.448,1.448,0,0,1,.119.586V8.531l-1.019-1V1.5a.472.472,0,0,0-.143-.352A.529.529,0,0,0,28.528,1H24.453a.491.491,0,0,0-.358.141.509.509,0,0,0-.151.359ZM32.095,8v2.523l-1.019-.992V8ZM35,15.148l-.716.7-3-2.945a3.218,3.218,0,0,1-1.106.8A3.388,3.388,0,0,1,28.831,14H27v1h2.038v1H23.943V15h2.038V14H24.15a3.206,3.206,0,0,1-1.266-.25,3.307,3.307,0,0,1-1.035-.687,3.239,3.239,0,0,1-.7-1.016,3.16,3.16,0,0,1-.263-1.25V8h1.019v2.8a2.093,2.093,0,0,0,.175.852,2.238,2.238,0,0,0,.486.7,2.2,2.2,0,0,0,.708.469,2.493,2.493,0,0,0,.876.18h4.681a2.187,2.187,0,0,0,.947-.211,2.427,2.427,0,0,0,.78-.586l-.812-.8a1.486,1.486,0,0,1-.533.438,1.613,1.613,0,0,1-.685.164H24.453a1.538,1.538,0,0,1-1.083-.437,1.5,1.5,0,0,1-.326-.477,1.448,1.448,0,0,1-.119-.586V4.711L19,.852l.716-.7ZM28.528,11a.5.5,0,0,0,.287-.086.526.526,0,0,0,.191-.234L23.943,5.711V10.5a.472.472,0,0,0,.143.352.529.529,0,0,0,.366.148Z" transform="translate(-9 14)" fill="#fff"/>
|
||||||
|
<text id="Mic_label" data-name="Mic label" transform="translate(38 13)" fill="#fff" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Microphone off</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 3.8 KiB |
@ -0,0 +1,19 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="322" height="44" viewBox="0 0 322 44">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip-Off-Off_Light">
|
||||||
|
<rect width="322" height="44"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<g id="Off-Off_Light" data-name="Off-Off Light" clip-path="url(#clip-Off-Off_Light)">
|
||||||
|
<rect width="322" height="44" fill="#f1f1f1"/>
|
||||||
|
<g id="Background" fill="#f1f1f1">
|
||||||
|
<path d="M 321.5 43.5 L 0.5 43.5 L 0.5 0.5 L 321.5 0.5 L 321.5 43.5 Z" stroke="none"/>
|
||||||
|
<path d="M 1 1 L 1 43 L 321 43 L 321 1 L 1 1 M 0 0 L 322 0 L 322 44 L 0 44 L 0 0 Z" stroke="none" fill="#dbdbdb"/>
|
||||||
|
</g>
|
||||||
|
<rect id="Divider" width="1" height="24" transform="translate(161 10)" fill="#dbdbdb"/>
|
||||||
|
<text id="Camera_label" data-name="Camera label" transform="translate(200 13)" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Camera off</tspan></text>
|
||||||
|
<path id="Camera_off_icon" data-name="Camera off icon" d="M12,24.9l4-2.038v8.279l-1.953-1q-.141-.072-.258-.119t-.242-.1a1.825,1.825,0,0,1-.227-.119l-.25-.159a1.726,1.726,0,0,1-.2-.159,1.556,1.556,0,0,1-.156-.167q-.07-.088-.148-.175l-.18-.2L11,27.533v-3.59H7.477l-1-1.019H12Zm3,4.593V24.508l-3,1.536v1.91ZM.148,19.716.852,19l15,15.284-.7.716-3.859-3.924H0V22.924H3.289ZM1,30.057h9.289l-6-6.113H1Z" transform="translate(171 -5)"/>
|
||||||
|
<path id="Mic_off_icon" data-name="Mic off icon" d="M23.943,2.531l-1.019-1V1.5a1.448,1.448,0,0,1,.119-.586A1.5,1.5,0,0,1,23.37.437,1.538,1.538,0,0,1,24.453,0h4.076a1.538,1.538,0,0,1,1.083.437,1.5,1.5,0,0,1,.326.477,1.448,1.448,0,0,1,.119.586V8.531l-1.019-1V1.5a.472.472,0,0,0-.143-.352A.529.529,0,0,0,28.528,1H24.453a.491.491,0,0,0-.358.141.509.509,0,0,0-.151.359ZM32.095,8v2.523l-1.019-.992V8ZM35,15.148l-.716.7-3-2.945a3.218,3.218,0,0,1-1.106.8A3.388,3.388,0,0,1,28.831,14H27v1h2.038v1H23.943V15h2.038V14H24.15a3.206,3.206,0,0,1-1.266-.25,3.307,3.307,0,0,1-1.035-.687,3.239,3.239,0,0,1-.7-1.016,3.16,3.16,0,0,1-.263-1.25V8h1.019v2.8a2.093,2.093,0,0,0,.175.852,2.238,2.238,0,0,0,.486.7,2.2,2.2,0,0,0,.708.469,2.493,2.493,0,0,0,.876.18h4.681a2.187,2.187,0,0,0,.947-.211,2.427,2.427,0,0,0,.78-.586l-.812-.8a1.486,1.486,0,0,1-.533.438,1.613,1.613,0,0,1-.685.164H24.453a1.538,1.538,0,0,1-1.083-.437,1.5,1.5,0,0,1-.326-.477,1.448,1.448,0,0,1-.119-.586V4.711L19,.852l.716-.7ZM28.528,11a.5.5,0,0,0,.287-.086.526.526,0,0,0,.191-.234L23.943,5.711V10.5a.472.472,0,0,0,.143.352.529.529,0,0,0,.366.148Z" transform="translate(-9 14)"/>
|
||||||
|
<text id="Mic_label" data-name="Mic label" transform="translate(38 13)" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Microphone off</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 3.4 KiB |
@ -0,0 +1,19 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="322" height="44" viewBox="0 0 322 44">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip-Off-On_Dark">
|
||||||
|
<rect width="322" height="44"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<g id="Off-On_Dark" data-name="Off-On Dark" clip-path="url(#clip-Off-On_Dark)">
|
||||||
|
<rect width="322" height="44" fill="#f1f1f1"/>
|
||||||
|
<g id="Background" fill="#1f1f1f">
|
||||||
|
<path d="M 321.5 43.5 L 0.5 43.5 L 0.5 0.5 L 321.5 0.5 L 321.5 43.5 Z" stroke="none"/>
|
||||||
|
<path d="M 1 1 L 1 43 L 321 43 L 321 1 L 1 1 M 0 0 L 322 0 L 322 44 L 0 44 L 0 0 Z" stroke="none" fill="#313131"/>
|
||||||
|
</g>
|
||||||
|
<rect id="Divider" width="1" height="24" transform="translate(161 10)" fill="#313131"/>
|
||||||
|
<text id="Camera_label" data-name="Camera label" transform="translate(200 13)" fill="#fff" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Camera on</tspan></text>
|
||||||
|
<path id="Mic_off_icon" data-name="Mic off icon" d="M23.943,2.531l-1.019-1V1.5a1.448,1.448,0,0,1,.119-.586A1.5,1.5,0,0,1,23.37.437,1.538,1.538,0,0,1,24.453,0h4.076a1.538,1.538,0,0,1,1.083.437,1.5,1.5,0,0,1,.326.477,1.448,1.448,0,0,1,.119.586V8.531l-1.019-1V1.5a.472.472,0,0,0-.143-.352A.529.529,0,0,0,28.528,1H24.453a.491.491,0,0,0-.358.141.509.509,0,0,0-.151.359ZM32.095,8v2.523l-1.019-.992V8ZM35,15.148l-.716.7-3-2.945a3.218,3.218,0,0,1-1.106.8A3.388,3.388,0,0,1,28.831,14H27v1h2.038v1H23.943V15h2.038V14H24.15a3.206,3.206,0,0,1-1.266-.25,3.307,3.307,0,0,1-1.035-.687,3.239,3.239,0,0,1-.7-1.016,3.16,3.16,0,0,1-.263-1.25V8h1.019v2.8a2.093,2.093,0,0,0,.175.852,2.238,2.238,0,0,0,.486.7,2.2,2.2,0,0,0,.708.469,2.493,2.493,0,0,0,.876.18h4.681a2.187,2.187,0,0,0,.947-.211,2.427,2.427,0,0,0,.78-.586l-.812-.8a1.486,1.486,0,0,1-.533.438,1.613,1.613,0,0,1-.685.164H24.453a1.538,1.538,0,0,1-1.083-.437,1.5,1.5,0,0,1-.326-.477,1.448,1.448,0,0,1-.119-.586V4.711L19,.852l.716-.7ZM28.528,11a.5.5,0,0,0,.287-.086.526.526,0,0,0,.191-.234L23.943,5.711V10.5a.472.472,0,0,0,.143.352.529.529,0,0,0,.366.148Z" transform="translate(-9 14)" fill="#fff"/>
|
||||||
|
<text id="Mic_label" data-name="Mic label" transform="translate(38 13)" fill="#fff" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Microphone off</tspan></text>
|
||||||
|
<path id="Camera_on_icon" data-name="Camera on icon" d="M16,512.359,12,510.3V512.3H0v-8.231H12v1.993L16,504Zm-5-7.266H1v6.173H11Zm4,.571-3,1.551v1.929l3,1.551Z" transform="translate(171 -486)" fill="#fff"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 3.5 KiB |
@ -0,0 +1,19 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="322" height="44" viewBox="0 0 322 44">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip-Off-On_Light">
|
||||||
|
<rect width="322" height="44"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<g id="Off-On_Light" data-name="Off-On Light" clip-path="url(#clip-Off-On_Light)">
|
||||||
|
<rect width="322" height="44" fill="#f1f1f1"/>
|
||||||
|
<g id="Background" fill="#f1f1f1">
|
||||||
|
<path d="M 321.5 43.5 L 0.5 43.5 L 0.5 0.5 L 321.5 0.5 L 321.5 43.5 Z" stroke="none"/>
|
||||||
|
<path d="M 1 1 L 1 43 L 321 43 L 321 1 L 1 1 M 0 0 L 322 0 L 322 44 L 0 44 L 0 0 Z" stroke="none" fill="#dbdbdb"/>
|
||||||
|
</g>
|
||||||
|
<rect id="Divider" width="1" height="24" transform="translate(161 10)" fill="#dbdbdb"/>
|
||||||
|
<text id="Camera_label" data-name="Camera label" transform="translate(200 13)" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Camera on</tspan></text>
|
||||||
|
<path id="Mic_off_icon" data-name="Mic off icon" d="M23.943,2.531l-1.019-1V1.5a1.448,1.448,0,0,1,.119-.586A1.5,1.5,0,0,1,23.37.437,1.538,1.538,0,0,1,24.453,0h4.076a1.538,1.538,0,0,1,1.083.437,1.5,1.5,0,0,1,.326.477,1.448,1.448,0,0,1,.119.586V8.531l-1.019-1V1.5a.472.472,0,0,0-.143-.352A.529.529,0,0,0,28.528,1H24.453a.491.491,0,0,0-.358.141.509.509,0,0,0-.151.359ZM32.095,8v2.523l-1.019-.992V8ZM35,15.148l-.716.7-3-2.945a3.218,3.218,0,0,1-1.106.8A3.388,3.388,0,0,1,28.831,14H27v1h2.038v1H23.943V15h2.038V14H24.15a3.206,3.206,0,0,1-1.266-.25,3.307,3.307,0,0,1-1.035-.687,3.239,3.239,0,0,1-.7-1.016,3.16,3.16,0,0,1-.263-1.25V8h1.019v2.8a2.093,2.093,0,0,0,.175.852,2.238,2.238,0,0,0,.486.7,2.2,2.2,0,0,0,.708.469,2.493,2.493,0,0,0,.876.18h4.681a2.187,2.187,0,0,0,.947-.211,2.427,2.427,0,0,0,.78-.586l-.812-.8a1.486,1.486,0,0,1-.533.438,1.613,1.613,0,0,1-.685.164H24.453a1.538,1.538,0,0,1-1.083-.437,1.5,1.5,0,0,1-.326-.477,1.448,1.448,0,0,1-.119-.586V4.711L19,.852l.716-.7ZM28.528,11a.5.5,0,0,0,.287-.086.526.526,0,0,0,.191-.234L23.943,5.711V10.5a.472.472,0,0,0,.143.352.529.529,0,0,0,.366.148Z" transform="translate(-9 14)"/>
|
||||||
|
<text id="Mic_label" data-name="Mic label" transform="translate(38 13)" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Microphone off</tspan></text>
|
||||||
|
<path id="Camera_on_icon" data-name="Camera on icon" d="M16,512.359,12,510.3V512.3H0v-8.231H12v1.993L16,504Zm-5-7.266H1v6.173H11Zm4,.571-3,1.551v1.929l3,1.551Z" transform="translate(171 -486)"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 3.6 KiB |
@ -0,0 +1,19 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="322" height="44" viewBox="0 0 322 44">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip-On-Disabled">
|
||||||
|
<rect width="322" height="44"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<g id="On-Disabled" clip-path="url(#clip-On-Disabled)">
|
||||||
|
<rect width="322" height="44" fill="#f1f1f1"/>
|
||||||
|
<g id="Background" fill="#1f1f1f">
|
||||||
|
<path d="M 321.5 43.5 L 0.5 43.5 L 0.5 0.5 L 321.5 0.5 L 321.5 43.5 Z" stroke="none"/>
|
||||||
|
<path d="M 1 1 L 1 43 L 321 43 L 321 1 L 1 1 M 0 0 L 322 0 L 322 44 L 0 44 L 0 0 Z" stroke="none" fill="#1f1f1f"/>
|
||||||
|
</g>
|
||||||
|
<rect id="Divider" width="1" height="24" transform="translate(161 10)" fill="#313131"/>
|
||||||
|
<text id="Camera_label" data-name="Camera label" transform="translate(200 13)" fill="#585858" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Camera not in use</tspan></text>
|
||||||
|
<path id="Camer_disabled_icon" data-name="Camer disabled icon" d="M12.5,509.031a3.408,3.408,0,0,1,1.359.272,3.634,3.634,0,0,1,1.117.745,3.348,3.348,0,0,1,.75,1.1A3.555,3.555,0,0,1,16,512.508a3.35,3.35,0,0,1-.273,1.351,3.608,3.608,0,0,1-.75,1.11,3.371,3.371,0,0,1-1.109.745,3.617,3.617,0,0,1-1.367.272,3.407,3.407,0,0,1-1.359-.272,3.634,3.634,0,0,1-1.117-.745,3.347,3.347,0,0,1-.75-1.1A3.555,3.555,0,0,1,9,512.508a3.351,3.351,0,0,1,.273-1.351,3.608,3.608,0,0,1,.75-1.11,3.371,3.371,0,0,1,1.109-.745A3.616,3.616,0,0,1,12.5,509.031ZM10,512.508a2.393,2.393,0,0,0,.2.963,2.585,2.585,0,0,0,.531.792,2.423,2.423,0,0,0,.8.536,2.491,2.491,0,0,0,.977.194,2.591,2.591,0,0,0,.719-.1,2.241,2.241,0,0,0,.656-.31l-3.461-3.439a2.334,2.334,0,0,0-.3.652A2.76,2.76,0,0,0,10,512.508Zm4.586,1.366a2.333,2.333,0,0,0,.3-.652,2.759,2.759,0,0,0,.109-.714,2.393,2.393,0,0,0-.2-.963,2.428,2.428,0,0,0-.539-.784,2.725,2.725,0,0,0-.8-.536,2.353,2.353,0,0,0-.969-.2,2.593,2.593,0,0,0-.719.1,2.245,2.245,0,0,0-.656.311ZM16,504v5.326a4.453,4.453,0,0,0-1-.823v-2.9l-3,1.5v.714a4.157,4.157,0,0,0-.508.078,4.1,4.1,0,0,0-.492.14v-2.981H1v5.962H8a4.038,4.038,0,0,0-.219.994H0v-7.95H12v1.925Z" transform="translate(171 -486)" fill="#585858"/>
|
||||||
|
<text id="Mic_label" data-name="Mic label" transform="translate(38 13)" fill="#fff" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Microphone on</tspan></text>
|
||||||
|
<path id="Mic_on_icon" data-name="Mic on icon" d="M259.518,12.092a1.476,1.476,0,0,1-.589-.118,1.5,1.5,0,0,1-.8-.8,1.486,1.486,0,0,1-.118-.59V1.511a1.486,1.486,0,0,1,.118-.59,1.5,1.5,0,0,1,.8-.8A1.476,1.476,0,0,1,259.518,0h4.02a1.476,1.476,0,0,1,.589.118,1.5,1.5,0,0,1,.8.8,1.487,1.487,0,0,1,.118.59V10.58a1.487,1.487,0,0,1-.118.59,1.5,1.5,0,0,1-.8.8,1.476,1.476,0,0,1-.589.118Zm-.5-1.511a.51.51,0,0,0,.5.5h4.02a.51.51,0,0,0,.5-.5V1.511a.485.485,0,0,0-.149-.354.482.482,0,0,0-.353-.15h-4.02a.482.482,0,0,0-.353.15.485.485,0,0,0-.149.354Zm8.04-2.519v2.85a3.106,3.106,0,0,1-.251,1.244,3.2,3.2,0,0,1-1.7,1.7,3.085,3.085,0,0,1-1.241.252H262.03v1.008h2.01v1.008h-5.025V15.115h2.01V14.107h-1.837a3.085,3.085,0,0,1-1.241-.252,3.2,3.2,0,0,1-1.7-1.7A3.107,3.107,0,0,1,256,10.911V8.061h1.005v2.85a2.128,2.128,0,0,0,.173.85,2.2,2.2,0,0,0,.463.693,2.281,2.281,0,0,0,.7.472,1.981,1.981,0,0,0,.848.173h4.68a2.113,2.113,0,0,0,.848-.173,2.195,2.195,0,0,0,.691-.464,2.288,2.288,0,0,0,.471-.7,2,2,0,0,0,.173-.85V8.061Z" transform="translate(-244.073 14)" fill="#fff"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 3.5 KiB |
@ -0,0 +1,19 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="322" height="44" viewBox="0 0 322 44">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip-On-Disabled_Light">
|
||||||
|
<rect width="322" height="44"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<g id="On-Disabled_Light" data-name="On-Disabled Light" clip-path="url(#clip-On-Disabled_Light)">
|
||||||
|
<rect width="322" height="44" fill="#f1f1f1"/>
|
||||||
|
<g id="Background" fill="#f1f1f1">
|
||||||
|
<path d="M 321.5 43.5 L 0.5 43.5 L 0.5 0.5 L 321.5 0.5 L 321.5 43.5 Z" stroke="none"/>
|
||||||
|
<path d="M 1 1 L 1 43 L 321 43 L 321 1 L 1 1 M 0 0 L 322 0 L 322 44 L 0 44 L 0 0 Z" stroke="none" fill="#dbdbdb"/>
|
||||||
|
</g>
|
||||||
|
<rect id="Divider" width="1" height="24" transform="translate(161 10)" fill="#dbdbdb"/>
|
||||||
|
<text id="Camera_label" data-name="Camera label" transform="translate(200 13)" fill="#c1c1c1" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Camera not in use</tspan></text>
|
||||||
|
<path id="Camer_disabled_icon" data-name="Camer disabled icon" d="M12.5,509.031a3.408,3.408,0,0,1,1.359.272,3.634,3.634,0,0,1,1.117.745,3.348,3.348,0,0,1,.75,1.1A3.555,3.555,0,0,1,16,512.508a3.35,3.35,0,0,1-.273,1.351,3.608,3.608,0,0,1-.75,1.11,3.371,3.371,0,0,1-1.109.745,3.617,3.617,0,0,1-1.367.272,3.407,3.407,0,0,1-1.359-.272,3.634,3.634,0,0,1-1.117-.745,3.347,3.347,0,0,1-.75-1.1A3.555,3.555,0,0,1,9,512.508a3.351,3.351,0,0,1,.273-1.351,3.608,3.608,0,0,1,.75-1.11,3.371,3.371,0,0,1,1.109-.745A3.616,3.616,0,0,1,12.5,509.031ZM10,512.508a2.393,2.393,0,0,0,.2.963,2.585,2.585,0,0,0,.531.792,2.423,2.423,0,0,0,.8.536,2.491,2.491,0,0,0,.977.194,2.591,2.591,0,0,0,.719-.1,2.241,2.241,0,0,0,.656-.31l-3.461-3.439a2.334,2.334,0,0,0-.3.652A2.76,2.76,0,0,0,10,512.508Zm4.586,1.366a2.333,2.333,0,0,0,.3-.652,2.759,2.759,0,0,0,.109-.714,2.393,2.393,0,0,0-.2-.963,2.428,2.428,0,0,0-.539-.784,2.725,2.725,0,0,0-.8-.536,2.353,2.353,0,0,0-.969-.2,2.593,2.593,0,0,0-.719.1,2.245,2.245,0,0,0-.656.311ZM16,504v5.326a4.453,4.453,0,0,0-1-.823v-2.9l-3,1.5v.714a4.157,4.157,0,0,0-.508.078,4.1,4.1,0,0,0-.492.14v-2.981H1v5.962H8a4.038,4.038,0,0,0-.219.994H0v-7.95H12v1.925Z" transform="translate(171 -486)" fill="#c1c1c1"/>
|
||||||
|
<text id="Mic_label" data-name="Mic label" transform="translate(38 13)" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Microphone on</tspan></text>
|
||||||
|
<path id="Mic_on_icon" data-name="Mic on icon" d="M259.518,12.092a1.476,1.476,0,0,1-.589-.118,1.5,1.5,0,0,1-.8-.8,1.486,1.486,0,0,1-.118-.59V1.511a1.486,1.486,0,0,1,.118-.59,1.5,1.5,0,0,1,.8-.8A1.476,1.476,0,0,1,259.518,0h4.02a1.476,1.476,0,0,1,.589.118,1.5,1.5,0,0,1,.8.8,1.487,1.487,0,0,1,.118.59V10.58a1.487,1.487,0,0,1-.118.59,1.5,1.5,0,0,1-.8.8,1.476,1.476,0,0,1-.589.118Zm-.5-1.511a.51.51,0,0,0,.5.5h4.02a.51.51,0,0,0,.5-.5V1.511a.485.485,0,0,0-.149-.354.482.482,0,0,0-.353-.15h-4.02a.482.482,0,0,0-.353.15.485.485,0,0,0-.149.354Zm8.04-2.519v2.85a3.106,3.106,0,0,1-.251,1.244,3.2,3.2,0,0,1-1.7,1.7,3.085,3.085,0,0,1-1.241.252H262.03v1.008h2.01v1.008h-5.025V15.115h2.01V14.107h-1.837a3.085,3.085,0,0,1-1.241-.252,3.2,3.2,0,0,1-1.7-1.7A3.107,3.107,0,0,1,256,10.911V8.061h1.005v2.85a2.128,2.128,0,0,0,.173.85,2.2,2.2,0,0,0,.463.693,2.281,2.281,0,0,0,.7.472,1.981,1.981,0,0,0,.848.173h4.68a2.113,2.113,0,0,0,.848-.173,2.195,2.195,0,0,0,.691-.464,2.288,2.288,0,0,0,.471-.7,2,2,0,0,0,.173-.85V8.061Z" transform="translate(-244.073 14)"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 3.5 KiB |
@ -0,0 +1,19 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="322" height="44" viewBox="0 0 322 44">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip-On-Off_Dark">
|
||||||
|
<rect width="322" height="44"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<g id="On-Off_Dark" data-name="On-Off Dark" clip-path="url(#clip-On-Off_Dark)">
|
||||||
|
<rect width="322" height="44" fill="#f1f1f1"/>
|
||||||
|
<g id="Background" fill="#1f1f1f">
|
||||||
|
<path d="M 321.5 43.5 L 0.5 43.5 L 0.5 0.5 L 321.5 0.5 L 321.5 43.5 Z" stroke="none"/>
|
||||||
|
<path d="M 1 1 L 1 43 L 321 43 L 321 1 L 1 1 M 0 0 L 322 0 L 322 44 L 0 44 L 0 0 Z" stroke="none" fill="#313131"/>
|
||||||
|
</g>
|
||||||
|
<rect id="Divider" width="1" height="24" transform="translate(161 10)" fill="#313131"/>
|
||||||
|
<text id="Camera_label" data-name="Camera label" transform="translate(200 13)" fill="#fff" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Camera off</tspan></text>
|
||||||
|
<path id="Camera_off_icon" data-name="Camera off icon" d="M12,24.9l4-2.038v8.279l-1.953-1q-.141-.072-.258-.119t-.242-.1a1.825,1.825,0,0,1-.227-.119l-.25-.159a1.726,1.726,0,0,1-.2-.159,1.556,1.556,0,0,1-.156-.167q-.07-.088-.148-.175l-.18-.2L11,27.533v-3.59H7.477l-1-1.019H12Zm3,4.593V24.508l-3,1.536v1.91ZM.148,19.716.852,19l15,15.284-.7.716-3.859-3.924H0V22.924H3.289ZM1,30.057h9.289l-6-6.113H1Z" transform="translate(171 -5)" fill="#fff"/>
|
||||||
|
<text id="Mic_label" data-name="Mic label" transform="translate(38 13)" fill="#fff" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Microphone on</tspan></text>
|
||||||
|
<path id="Mic_on_icon" data-name="Mic on icon" d="M259.518,12.092a1.476,1.476,0,0,1-.589-.118,1.5,1.5,0,0,1-.8-.8,1.486,1.486,0,0,1-.118-.59V1.511a1.486,1.486,0,0,1,.118-.59,1.5,1.5,0,0,1,.8-.8A1.476,1.476,0,0,1,259.518,0h4.02a1.476,1.476,0,0,1,.589.118,1.5,1.5,0,0,1,.8.8,1.487,1.487,0,0,1,.118.59V10.58a1.487,1.487,0,0,1-.118.59,1.5,1.5,0,0,1-.8.8,1.476,1.476,0,0,1-.589.118Zm-.5-1.511a.51.51,0,0,0,.5.5h4.02a.51.51,0,0,0,.5-.5V1.511a.485.485,0,0,0-.149-.354.482.482,0,0,0-.353-.15h-4.02a.482.482,0,0,0-.353.15.485.485,0,0,0-.149.354Zm8.04-2.519v2.85a3.106,3.106,0,0,1-.251,1.244,3.2,3.2,0,0,1-1.7,1.7,3.085,3.085,0,0,1-1.241.252H262.03v1.008h2.01v1.008h-5.025V15.115h2.01V14.107h-1.837a3.085,3.085,0,0,1-1.241-.252,3.2,3.2,0,0,1-1.7-1.7A3.107,3.107,0,0,1,256,10.911V8.061h1.005v2.85a2.128,2.128,0,0,0,.173.85,2.2,2.2,0,0,0,.463.693,2.281,2.281,0,0,0,.7.472,1.981,1.981,0,0,0,.848.173h4.68a2.113,2.113,0,0,0,.848-.173,2.195,2.195,0,0,0,.691-.464,2.288,2.288,0,0,0,.471-.7,2,2,0,0,0,.173-.85V8.061Z" transform="translate(-244.073 14)" fill="#fff"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 3.5 KiB |
@ -0,0 +1,19 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="322" height="44" viewBox="0 0 322 44">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip-On-Off_Light">
|
||||||
|
<rect width="322" height="44"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<g id="On-Off_Light" data-name="On-Off Light" clip-path="url(#clip-On-Off_Light)">
|
||||||
|
<rect width="322" height="44" fill="#f1f1f1"/>
|
||||||
|
<g id="Background" fill="#f1f1f1">
|
||||||
|
<path d="M 321.5 43.5 L 0.5 43.5 L 0.5 0.5 L 321.5 0.5 L 321.5 43.5 Z" stroke="none"/>
|
||||||
|
<path d="M 1 1 L 1 43 L 321 43 L 321 1 L 1 1 M 0 0 L 322 0 L 322 44 L 0 44 L 0 0 Z" stroke="none" fill="#dbdbdb"/>
|
||||||
|
</g>
|
||||||
|
<rect id="Divider" width="1" height="24" transform="translate(161 10)" fill="#dbdbdb"/>
|
||||||
|
<text id="Camera_label" data-name="Camera label" transform="translate(200 13)" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Camera off</tspan></text>
|
||||||
|
<path id="Camera_off_icon" data-name="Camera off icon" d="M12,24.9l4-2.038v8.279l-1.953-1q-.141-.072-.258-.119t-.242-.1a1.825,1.825,0,0,1-.227-.119l-.25-.159a1.726,1.726,0,0,1-.2-.159,1.556,1.556,0,0,1-.156-.167q-.07-.088-.148-.175l-.18-.2L11,27.533v-3.59H7.477l-1-1.019H12Zm3,4.593V24.508l-3,1.536v1.91ZM.148,19.716.852,19l15,15.284-.7.716-3.859-3.924H0V22.924H3.289ZM1,30.057h9.289l-6-6.113H1Z" transform="translate(171 -5)"/>
|
||||||
|
<text id="Mic_label" data-name="Mic label" transform="translate(38 13)" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Microphone on</tspan></text>
|
||||||
|
<path id="Mic_on_icon" data-name="Mic on icon" d="M259.518,12.092a1.476,1.476,0,0,1-.589-.118,1.5,1.5,0,0,1-.8-.8,1.486,1.486,0,0,1-.118-.59V1.511a1.486,1.486,0,0,1,.118-.59,1.5,1.5,0,0,1,.8-.8A1.476,1.476,0,0,1,259.518,0h4.02a1.476,1.476,0,0,1,.589.118,1.5,1.5,0,0,1,.8.8,1.487,1.487,0,0,1,.118.59V10.58a1.487,1.487,0,0,1-.118.59,1.5,1.5,0,0,1-.8.8,1.476,1.476,0,0,1-.589.118Zm-.5-1.511a.51.51,0,0,0,.5.5h4.02a.51.51,0,0,0,.5-.5V1.511a.485.485,0,0,0-.149-.354.482.482,0,0,0-.353-.15h-4.02a.482.482,0,0,0-.353.15.485.485,0,0,0-.149.354Zm8.04-2.519v2.85a3.106,3.106,0,0,1-.251,1.244,3.2,3.2,0,0,1-1.7,1.7,3.085,3.085,0,0,1-1.241.252H262.03v1.008h2.01v1.008h-5.025V15.115h2.01V14.107h-1.837a3.085,3.085,0,0,1-1.241-.252,3.2,3.2,0,0,1-1.7-1.7A3.107,3.107,0,0,1,256,10.911V8.061h1.005v2.85a2.128,2.128,0,0,0,.173.85,2.2,2.2,0,0,0,.463.693,2.281,2.281,0,0,0,.7.472,1.981,1.981,0,0,0,.848.173h4.68a2.113,2.113,0,0,0,.848-.173,2.195,2.195,0,0,0,.691-.464,2.288,2.288,0,0,0,.471-.7,2,2,0,0,0,.173-.85V8.061Z" transform="translate(-244.073 14)"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 3.2 KiB |
@ -0,0 +1,19 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="322" height="44" viewBox="0 0 322 44">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip-On-On_Dark">
|
||||||
|
<rect width="322" height="44"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<g id="On-On_Dark" data-name="On-On Dark" clip-path="url(#clip-On-On_Dark)">
|
||||||
|
<rect width="322" height="44" fill="#f1f1f1"/>
|
||||||
|
<g id="Background" fill="#1f1f1f">
|
||||||
|
<path d="M 321.5 43.5 L 0.5 43.5 L 0.5 0.5 L 321.5 0.5 L 321.5 43.5 Z" stroke="none"/>
|
||||||
|
<path d="M 1 1 L 1 43 L 321 43 L 321 1 L 1 1 M 0 0 L 322 0 L 322 44 L 0 44 L 0 0 Z" stroke="none" fill="#313131"/>
|
||||||
|
</g>
|
||||||
|
<rect id="Divider" width="1" height="24" transform="translate(161 10)" fill="#313131"/>
|
||||||
|
<text id="Camera_label" data-name="Camera label" transform="translate(200 13)" fill="#fff" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Camera on</tspan></text>
|
||||||
|
<path id="Camera_on_icon" data-name="Camera on icon" d="M16,512.359,12,510.3V512.3H0v-8.231H12v1.993L16,504Zm-5-7.266H1v6.173H11Zm4,.571-3,1.551v1.929l3,1.551Z" transform="translate(171 -486)" fill="#fff"/>
|
||||||
|
<text id="Mic_label" data-name="Mic label" transform="translate(38 13)" fill="#fff" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Microphone on</tspan></text>
|
||||||
|
<path id="Mic_on_icon" data-name="Mic on icon" d="M259.518,12.092a1.476,1.476,0,0,1-.589-.118,1.5,1.5,0,0,1-.8-.8,1.486,1.486,0,0,1-.118-.59V1.511a1.486,1.486,0,0,1,.118-.59,1.5,1.5,0,0,1,.8-.8A1.476,1.476,0,0,1,259.518,0h4.02a1.476,1.476,0,0,1,.589.118,1.5,1.5,0,0,1,.8.8,1.487,1.487,0,0,1,.118.59V10.58a1.487,1.487,0,0,1-.118.59,1.5,1.5,0,0,1-.8.8,1.476,1.476,0,0,1-.589.118Zm-.5-1.511a.51.51,0,0,0,.5.5h4.02a.51.51,0,0,0,.5-.5V1.511a.485.485,0,0,0-.149-.354.482.482,0,0,0-.353-.15h-4.02a.482.482,0,0,0-.353.15.485.485,0,0,0-.149.354Zm8.04-2.519v2.85a3.106,3.106,0,0,1-.251,1.244,3.2,3.2,0,0,1-1.7,1.7,3.085,3.085,0,0,1-1.241.252H262.03v1.008h2.01v1.008h-5.025V15.115h2.01V14.107h-1.837a3.085,3.085,0,0,1-1.241-.252,3.2,3.2,0,0,1-1.7-1.7A3.107,3.107,0,0,1,256,10.911V8.061h1.005v2.85a2.128,2.128,0,0,0,.173.85,2.2,2.2,0,0,0,.463.693,2.281,2.281,0,0,0,.7.472,1.981,1.981,0,0,0,.848.173h4.68a2.113,2.113,0,0,0,.848-.173,2.195,2.195,0,0,0,.691-.464,2.288,2.288,0,0,0,.471-.7,2,2,0,0,0,.173-.85V8.061Z" transform="translate(-244.073 14)" fill="#fff"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 3.2 KiB |
@ -0,0 +1,19 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="322" height="44" viewBox="0 0 322 44">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip-On-On_Light">
|
||||||
|
<rect width="322" height="44"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<g id="On-On_Light" data-name="On-On Light" clip-path="url(#clip-On-On_Light)">
|
||||||
|
<rect width="322" height="44" fill="#f1f1f1"/>
|
||||||
|
<g id="Background" fill="#f1f1f1">
|
||||||
|
<path d="M 321.5 43.5 L 0.5 43.5 L 0.5 0.5 L 321.5 0.5 L 321.5 43.5 Z" stroke="none"/>
|
||||||
|
<path d="M 1 1 L 1 43 L 321 43 L 321 1 L 1 1 M 0 0 L 322 0 L 322 44 L 0 44 L 0 0 Z" stroke="none" fill="#dbdbdb"/>
|
||||||
|
</g>
|
||||||
|
<rect id="Divider" width="1" height="24" transform="translate(161 10)" fill="#dbdbdb"/>
|
||||||
|
<text id="Camera_label" data-name="Camera label" transform="translate(200 13)" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Camera on</tspan></text>
|
||||||
|
<path id="Camera_on_icon" data-name="Camera on icon" d="M16,512.359,12,510.3V512.3H0v-8.231H12v1.993L16,504Zm-5-7.266H1v6.173H11Zm4,.571-3,1.551v1.929l3,1.551Z" transform="translate(171 -486)"/>
|
||||||
|
<text id="Mic_label" data-name="Mic label" transform="translate(38 13)" font-size="12" font-family="SegoeUI, Segoe UI"><tspan x="0" y="13">Microphone on</tspan></text>
|
||||||
|
<path id="Mic_on_icon" data-name="Mic on icon" d="M259.518,12.092a1.476,1.476,0,0,1-.589-.118,1.5,1.5,0,0,1-.8-.8,1.486,1.486,0,0,1-.118-.59V1.511a1.486,1.486,0,0,1,.118-.59,1.5,1.5,0,0,1,.8-.8A1.476,1.476,0,0,1,259.518,0h4.02a1.476,1.476,0,0,1,.589.118,1.5,1.5,0,0,1,.8.8,1.487,1.487,0,0,1,.118.59V10.58a1.487,1.487,0,0,1-.118.59,1.5,1.5,0,0,1-.8.8,1.476,1.476,0,0,1-.589.118Zm-.5-1.511a.51.51,0,0,0,.5.5h4.02a.51.51,0,0,0,.5-.5V1.511a.485.485,0,0,0-.149-.354.482.482,0,0,0-.353-.15h-4.02a.482.482,0,0,0-.353.15.485.485,0,0,0-.149.354Zm8.04-2.519v2.85a3.106,3.106,0,0,1-.251,1.244,3.2,3.2,0,0,1-1.7,1.7,3.085,3.085,0,0,1-1.241.252H262.03v1.008h2.01v1.008h-5.025V15.115h2.01V14.107h-1.837a3.085,3.085,0,0,1-1.241-.252,3.2,3.2,0,0,1-1.7-1.7A3.107,3.107,0,0,1,256,10.911V8.061h1.005v2.85a2.128,2.128,0,0,0,.173.85,2.2,2.2,0,0,0,.463.693,2.281,2.281,0,0,0,.7.472,1.981,1.981,0,0,0,.848.173h4.68a2.113,2.113,0,0,0,.848-.173,2.195,2.195,0,0,0,.691-.464,2.288,2.288,0,0,0,.471-.7,2,2,0,0,0,.173-.85V8.061Z" transform="translate(-244.073 14)"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
14
src/modules/videoconference/VideoConferenceModule/README.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Video Conference Mute
|
||||||
|
|
||||||
|
# Introduction
|
||||||
|
The Video Conference Mute module allows muting microphone and/or web camera video stream during video calls or other activity.
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
If you'd like to mute your web camera, please select "PowerToys VideoConference Mute" device in your web camera-using app, then restart it.
|
||||||
|
|
||||||
|
During a video call, you can use default shortcuts to mute microphone, web camera or both. You'll see a toolbar indicating corresponding mute statuses.
|
||||||
|
|
||||||
|
# Options
|
||||||
|
You can tweak the toolbar position on the screen as well as set web camera overlay image during muting.
|
||||||
|
|
||||||
|
# Backlog
|
335
src/modules/videoconference/VideoConferenceModule/Toolbar.cpp
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "Toolbar.h"
|
||||||
|
|
||||||
|
#include <windowsx.h>
|
||||||
|
|
||||||
|
#include <common/Themes/windows_colors.h>
|
||||||
|
|
||||||
|
#include "Logging.h"
|
||||||
|
#include "VideoConferenceModule.h"
|
||||||
|
|
||||||
|
Toolbar* toolbar = nullptr;
|
||||||
|
|
||||||
|
const int REFRESH_RATE = 100;
|
||||||
|
const int OVERLAY_SHOW_TIME = 500;
|
||||||
|
const int BORDER_OFFSET = 12;
|
||||||
|
|
||||||
|
Toolbar::Toolbar()
|
||||||
|
{
|
||||||
|
toolbar = this;
|
||||||
|
darkImages.camOnMicOn = Gdiplus::Image::FromFile(L"modules/VideoConference/Icons/On-On Dark.png");
|
||||||
|
darkImages.camOffMicOn = Gdiplus::Image::FromFile(L"modules/VideoConference/Icons/On-Off Dark.png");
|
||||||
|
darkImages.camOnMicOff = Gdiplus::Image::FromFile(L"modules/VideoConference/Icons/Off-On Dark.png");
|
||||||
|
darkImages.camOffMicOff = Gdiplus::Image::FromFile(L"modules/VideoConference/Icons/Off-Off Dark.png");
|
||||||
|
darkImages.camUnusedMicOn = Gdiplus::Image::FromFile(L"modules/VideoConference/Icons/On-NotInUse Dark.png");
|
||||||
|
darkImages.camUnusedMicOff = Gdiplus::Image::FromFile(L"modules/VideoConference/Icons/Off-NotInUse Dark.png");
|
||||||
|
|
||||||
|
lightImages.camOnMicOn = Gdiplus::Image::FromFile(L"modules/VideoConference/Icons/On-On Light.png");
|
||||||
|
lightImages.camOffMicOn = Gdiplus::Image::FromFile(L"modules/VideoConference/Icons/On-Off Light.png");
|
||||||
|
lightImages.camOnMicOff = Gdiplus::Image::FromFile(L"modules/VideoConference/Icons/Off-On Light.png");
|
||||||
|
lightImages.camOffMicOff = Gdiplus::Image::FromFile(L"modules/VideoConference/Icons/Off-Off Light.png");
|
||||||
|
lightImages.camUnusedMicOn = Gdiplus::Image::FromFile(L"modules/VideoConference/Icons/On-NotInUse Light.png");
|
||||||
|
lightImages.camUnusedMicOff = Gdiplus::Image::FromFile(L"modules/VideoConference/Icons/Off-NotInUse Light.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toolbar::scheduleModuleSettingsUpdate()
|
||||||
|
{
|
||||||
|
moduleSettingsUpdateScheduled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toolbar::scheduleGeneralSettingsUpdate()
|
||||||
|
{
|
||||||
|
generalSettingsUpdateScheduled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT Toolbar::WindowProcessMessages(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||||
|
{
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_DESTROY:
|
||||||
|
return 0;
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
{
|
||||||
|
int x = GET_X_LPARAM(lparam);
|
||||||
|
int y = GET_Y_LPARAM(lparam);
|
||||||
|
|
||||||
|
if (x < 322 / 2)
|
||||||
|
{
|
||||||
|
VideoConferenceModule::reverseMicrophoneMute();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VideoConferenceModule::reverseVirtualCameraMuteState();
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
case WM_CREATE:
|
||||||
|
case WM_PAINT:
|
||||||
|
{
|
||||||
|
PAINTSTRUCT ps;
|
||||||
|
HDC hdc;
|
||||||
|
|
||||||
|
hdc = BeginPaint(hwnd, &ps);
|
||||||
|
|
||||||
|
Gdiplus::Graphics graphic(hdc);
|
||||||
|
|
||||||
|
ToolbarImages* themeImages = &toolbar->darkImages;
|
||||||
|
|
||||||
|
if (toolbar->theme == L"light" || (toolbar->theme == L"system" && !WindowsColors::is_dark_mode()))
|
||||||
|
{
|
||||||
|
themeImages = &toolbar->lightImages;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
themeImages = &toolbar->darkImages;
|
||||||
|
}
|
||||||
|
Gdiplus::Image* toolbarImage = nullptr;
|
||||||
|
if (!toolbar->cameraInUse)
|
||||||
|
{
|
||||||
|
if (toolbar->microphoneMuted)
|
||||||
|
{
|
||||||
|
toolbarImage = themeImages->camUnusedMicOff;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toolbarImage = themeImages->camUnusedMicOn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (toolbar->microphoneMuted)
|
||||||
|
{
|
||||||
|
if (toolbar->cameraMuted)
|
||||||
|
{
|
||||||
|
toolbarImage = themeImages->camOffMicOff;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toolbarImage = themeImages->camOnMicOff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (toolbar->cameraMuted)
|
||||||
|
{
|
||||||
|
toolbarImage = themeImages->camOffMicOn;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toolbarImage = themeImages->camOnMicOn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
graphic.DrawImage(toolbarImage, 0, 0, toolbarImage->GetWidth(), toolbarImage->GetHeight());
|
||||||
|
|
||||||
|
EndPaint(hwnd, &ps);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_TIMER:
|
||||||
|
{
|
||||||
|
if (toolbar->generalSettingsUpdateScheduled)
|
||||||
|
{
|
||||||
|
instance->onGeneralSettingsChanged();
|
||||||
|
toolbar->generalSettingsUpdateScheduled = false;
|
||||||
|
}
|
||||||
|
if (toolbar->moduleSettingsUpdateScheduled)
|
||||||
|
{
|
||||||
|
instance->onModuleSettingsChanged();
|
||||||
|
toolbar->moduleSettingsUpdateScheduled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
toolbar->cameraInUse = VideoConferenceModule::getVirtualCameraInUse();
|
||||||
|
|
||||||
|
InvalidateRect(hwnd, NULL, NULL);
|
||||||
|
|
||||||
|
using namespace std::chrono;
|
||||||
|
const auto nowMillis = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
|
||||||
|
const bool showOverlayTimeout = nowMillis - toolbar->lastTimeCamOrMicMuteStateChanged > OVERLAY_SHOW_TIME;
|
||||||
|
|
||||||
|
static bool previousShow = false;
|
||||||
|
bool show = false;
|
||||||
|
|
||||||
|
if (toolbar->cameraInUse)
|
||||||
|
{
|
||||||
|
show = toolbar->HideToolbarWhenUnmuted ? toolbar->microphoneMuted || toolbar->cameraMuted : true;
|
||||||
|
}
|
||||||
|
else if (toolbar->previouscameraInUse)
|
||||||
|
{
|
||||||
|
VideoConferenceModule::unmuteAll();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
show = toolbar->microphoneMuted;
|
||||||
|
}
|
||||||
|
show = show || !showOverlayTimeout;
|
||||||
|
if (show)
|
||||||
|
{
|
||||||
|
ShowWindow(hwnd, SW_SHOW);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ShowWindow(hwnd, SW_HIDE);
|
||||||
|
}
|
||||||
|
if (previousShow != show)
|
||||||
|
{
|
||||||
|
previousShow = show;
|
||||||
|
LOG(show ? "Toolbar visibility changed to shown" : "Toolbar visibility changed to hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
KillTimer(hwnd, toolbar->nTimerId);
|
||||||
|
toolbar->previouscameraInUse = toolbar->cameraInUse;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
|
toolbar->nTimerId = SetTimer(hwnd, 101, REFRESH_RATE, nullptr);
|
||||||
|
|
||||||
|
return DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toolbar::show(std::wstring position, std::wstring monitorString)
|
||||||
|
{
|
||||||
|
for (auto& hwnd : hwnds)
|
||||||
|
{
|
||||||
|
PostMessageW(hwnd, WM_CLOSE, 0, 0);
|
||||||
|
}
|
||||||
|
hwnds.clear();
|
||||||
|
|
||||||
|
int overlayWidth = darkImages.camOffMicOff->GetWidth();
|
||||||
|
int overlayHeight = darkImages.camOffMicOff->GetHeight();
|
||||||
|
|
||||||
|
// Register the window class
|
||||||
|
LPCWSTR CLASS_NAME = L"MuteNotificationWindowClass";
|
||||||
|
WNDCLASS wc{};
|
||||||
|
wc.hInstance = GetModuleHandleW(nullptr);
|
||||||
|
wc.lpszClassName = CLASS_NAME;
|
||||||
|
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||||
|
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
|
||||||
|
wc.lpfnWndProc = WindowProcessMessages;
|
||||||
|
RegisterClassW(&wc);
|
||||||
|
|
||||||
|
// Create the window
|
||||||
|
DWORD dwExtStyle = 0;
|
||||||
|
DWORD dwStyle = WS_POPUPWINDOW;
|
||||||
|
|
||||||
|
std::vector<MonitorInfo> monitorInfos;
|
||||||
|
|
||||||
|
if (monitorString == L"All monitors")
|
||||||
|
{
|
||||||
|
monitorInfos = MonitorInfo::GetMonitors(false);
|
||||||
|
}
|
||||||
|
else //"Main monitor" or non-present
|
||||||
|
{
|
||||||
|
monitorInfos.push_back(MonitorInfo::GetPrimaryMonitor());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& monitorInfo : monitorInfos)
|
||||||
|
{
|
||||||
|
int positionX = 0;
|
||||||
|
int positionY = 0;
|
||||||
|
|
||||||
|
if (position == L"Top left corner")
|
||||||
|
{
|
||||||
|
positionX = monitorInfo.left() + BORDER_OFFSET;
|
||||||
|
positionY = monitorInfo.top() + BORDER_OFFSET;
|
||||||
|
}
|
||||||
|
else if (position == L"Top center")
|
||||||
|
{
|
||||||
|
positionX = monitorInfo.middle().x - overlayWidth / 2;
|
||||||
|
positionY = monitorInfo.top() + BORDER_OFFSET;
|
||||||
|
}
|
||||||
|
else if (position == L"Bottom left corner")
|
||||||
|
{
|
||||||
|
positionX = monitorInfo.left() + BORDER_OFFSET;
|
||||||
|
positionY = monitorInfo.bottom() - overlayHeight - BORDER_OFFSET;
|
||||||
|
}
|
||||||
|
else if (position == L"Bottom center")
|
||||||
|
{
|
||||||
|
positionX = monitorInfo.middle().x - overlayWidth / 2;
|
||||||
|
positionY = monitorInfo.bottom() - overlayHeight - BORDER_OFFSET;
|
||||||
|
}
|
||||||
|
else if (position == L"Bottom right corner")
|
||||||
|
{
|
||||||
|
positionX = monitorInfo.right() - overlayWidth - BORDER_OFFSET;
|
||||||
|
positionY = monitorInfo.bottom() - overlayHeight - BORDER_OFFSET;
|
||||||
|
}
|
||||||
|
else //"Top right corner" or non-present
|
||||||
|
{
|
||||||
|
positionX = monitorInfo.right() - overlayWidth - BORDER_OFFSET;
|
||||||
|
positionY = monitorInfo.top() + BORDER_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND hwnd;
|
||||||
|
hwnd = CreateWindowExW(
|
||||||
|
WS_EX_TOOLWINDOW | WS_EX_LAYERED,
|
||||||
|
CLASS_NAME,
|
||||||
|
CLASS_NAME,
|
||||||
|
WS_POPUP,
|
||||||
|
positionX,
|
||||||
|
positionY,
|
||||||
|
overlayWidth,
|
||||||
|
overlayHeight,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
GetModuleHandleW(nullptr),
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
auto transparrentColorKey = RGB(0, 0, 255);
|
||||||
|
HBRUSH brush = CreateSolidBrush(transparrentColorKey);
|
||||||
|
SetClassLongPtr(hwnd, GCLP_HBRBACKGROUND, (LONG_PTR)brush);
|
||||||
|
|
||||||
|
SetLayeredWindowAttributes(hwnd, transparrentColorKey, 0, LWA_COLORKEY);
|
||||||
|
|
||||||
|
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||||
|
|
||||||
|
hwnds.push_back(hwnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toolbar::hide()
|
||||||
|
{
|
||||||
|
for (auto& hwnd : hwnds)
|
||||||
|
{
|
||||||
|
PostMessage(hwnd, WM_CLOSE, 0, 0);
|
||||||
|
}
|
||||||
|
hwnds.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Toolbar::getCameraMute()
|
||||||
|
{
|
||||||
|
return cameraMuted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toolbar::setCameraMute(bool mute)
|
||||||
|
{
|
||||||
|
if (mute != cameraMuted)
|
||||||
|
{
|
||||||
|
lastTimeCamOrMicMuteStateChanged = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||||
|
}
|
||||||
|
cameraMuted = mute;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Toolbar::getMicrophoneMute()
|
||||||
|
{
|
||||||
|
return microphoneMuted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toolbar::setMicrophoneMute(bool mute)
|
||||||
|
{
|
||||||
|
if (mute != microphoneMuted)
|
||||||
|
{
|
||||||
|
lastTimeCamOrMicMuteStateChanged = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
microphoneMuted = mute;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toolbar::setHideToolbarWhenUnmuted(bool hide)
|
||||||
|
{
|
||||||
|
HideToolbarWhenUnmuted = hide;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toolbar::setTheme(std::wstring theme)
|
||||||
|
{
|
||||||
|
Toolbar::theme = theme;
|
||||||
|
}
|
61
src/modules/videoconference/VideoConferenceModule/Toolbar.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <gdiplus.h>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
#include <common/Display/monitors.h>
|
||||||
|
|
||||||
|
struct ToolbarImages
|
||||||
|
{
|
||||||
|
Gdiplus::Image* camOnMicOn = nullptr;
|
||||||
|
Gdiplus::Image* camOffMicOn = nullptr;
|
||||||
|
Gdiplus::Image* camOnMicOff = nullptr;
|
||||||
|
Gdiplus::Image* camOffMicOff = nullptr;
|
||||||
|
Gdiplus::Image* camUnusedMicOn = nullptr;
|
||||||
|
Gdiplus::Image* camUnusedMicOff = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Toolbar
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Toolbar();
|
||||||
|
|
||||||
|
void scheduleModuleSettingsUpdate();
|
||||||
|
void scheduleGeneralSettingsUpdate();
|
||||||
|
|
||||||
|
void show(std::wstring position, std::wstring monitorString);
|
||||||
|
void hide();
|
||||||
|
|
||||||
|
bool getCameraMute();
|
||||||
|
void setCameraMute(bool mute);
|
||||||
|
bool getMicrophoneMute();
|
||||||
|
void setMicrophoneMute(bool mute);
|
||||||
|
|
||||||
|
void setTheme(std::wstring theme);
|
||||||
|
void setHideToolbarWhenUnmuted(bool hide);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static LRESULT CALLBACK WindowProcessMessages(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||||
|
|
||||||
|
// Window callback can't be non-static so this members can't as well
|
||||||
|
std::vector<HWND> hwnds;
|
||||||
|
|
||||||
|
ToolbarImages darkImages;
|
||||||
|
ToolbarImages lightImages;
|
||||||
|
|
||||||
|
bool cameraMuted = false;
|
||||||
|
bool cameraInUse = false;
|
||||||
|
bool previouscameraInUse = false;
|
||||||
|
bool microphoneMuted = false;
|
||||||
|
|
||||||
|
std::wstring theme = L"system";
|
||||||
|
|
||||||
|
bool HideToolbarWhenUnmuted = true;
|
||||||
|
|
||||||
|
uint64_t lastTimeCamOrMicMuteStateChanged;
|
||||||
|
|
||||||
|
std::atomic_bool moduleSettingsUpdateScheduled = false;
|
||||||
|
std::atomic_bool generalSettingsUpdateScheduled = false;
|
||||||
|
UINT_PTR nTimerId;
|
||||||
|
};
|
@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="pch.cpp" />
|
||||||
|
<ClCompile Include="dllmain.cpp" />
|
||||||
|
<ClCompile Include="keyboard_state.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="shortcut_guide.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="target_state.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="overlay_window.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="trace.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="pch.h" />
|
||||||
|
<ClInclude Include="keyboard_state.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="shortcut_guide.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="target_state.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="overlay_window.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="trace.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{2c7c97f7-0d87-4230-a4b2-baf2cfc35d58}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{aa4b6713-589d-42ef-804d-3a045833f83f}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="shortcut_guide.rc" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,183 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>overlaywindow</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||||
|
<ProjectName>VideoConferenceModule</ProjectName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<SpectreMitigation>Spectre</SpectreMitigation>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<SpectreMitigation>Spectre</SpectreMitigation>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200519.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200519.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||||
|
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\VideoConference\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\VideoConference\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;OVERLAYWINDOW_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\;..\..\;..\VideoConferenceShared\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||||
|
<AdditionalDependencies>mfplat.lib;mf.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;gdiplus.lib;dwmapi.lib;uxtheme.lib;shcore.lib;Wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>xcopy /y /I "$(ProjectDir)Icons\*" "$(OutDir)Icons"
|
||||||
|
xcopy /y /I "$(ProjectDir)black.bmp*" "$(OutDir)"</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;OVERLAYWINDOW_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\common\inc;..\..\..\common\Telemetry;..\..\..\;..\..\;..\VideoConferenceShared\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||||
|
<AdditionalDependencies>mfplat.lib;mf.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;gdiplus.lib;dwmapi.lib;uxtheme.lib;shcore.lib;Wtsapi32.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>xcopy /y /I "$(ProjectDir)Icons\*" "$(OutDir)Icons"
|
||||||
|
xcopy /y /I "$(ProjectDir)black.bmp*" "$(OutDir)"</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="framework.h" />
|
||||||
|
<ClInclude Include="Toolbar.h" />
|
||||||
|
<ClInclude Include="pch.h" />
|
||||||
|
<ClInclude Include="trace.h" />
|
||||||
|
<ClInclude Include="VideoConferenceModule.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="dllmain.cpp" />
|
||||||
|
<ClCompile Include="trace.cpp" />
|
||||||
|
<ClCompile Include="Toolbar.cpp" />
|
||||||
|
<ClCompile Include="pch.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="VideoConferenceModule.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\VideoConferenceShared\VideoConferenceShared.vcxproj">
|
||||||
|
<Project>{459e0768-7ebd-4c41-bba1-6db3b3815e0a}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="Icons\Off-NotInUse Dark.svg" />
|
||||||
|
<None Include="Icons\Off-NotInUse Light.svg" />
|
||||||
|
<None Include="Icons\Off-Off Dark.svg" />
|
||||||
|
<None Include="Icons\Off-Off Light.svg" />
|
||||||
|
<None Include="Icons\Off-On Dark.svg" />
|
||||||
|
<None Include="Icons\Off-On Light.svg" />
|
||||||
|
<None Include="Icons\On-NotInUse Dark.svg" />
|
||||||
|
<None Include="Icons\On-NotInUse Light.svg" />
|
||||||
|
<None Include="Icons\On-Off Dark.svg" />
|
||||||
|
<None Include="Icons\On-Off Light.svg" />
|
||||||
|
<None Include="Icons\On-On Dark.svg" />
|
||||||
|
<None Include="Icons\On-On Light.svg" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Image Include="black.bmp" />
|
||||||
|
<Image Include="Icons\Off-NotInUse Dark.png" />
|
||||||
|
<Image Include="Icons\Off-NotInUse Light.png" />
|
||||||
|
<Image Include="Icons\Off-Off Dark.png" />
|
||||||
|
<Image Include="Icons\Off-Off Light.png" />
|
||||||
|
<Image Include="Icons\Off-On Dark.png" />
|
||||||
|
<Image Include="Icons\Off-On Light.png" />
|
||||||
|
<Image Include="Icons\On-NotInUse Dark.png" />
|
||||||
|
<Image Include="Icons\On-NotInUse Light.png" />
|
||||||
|
<Image Include="Icons\On-Off Dark.png" />
|
||||||
|
<Image Include="Icons\On-Off Light.png" />
|
||||||
|
<Image Include="Icons\On-On Dark.png" />
|
||||||
|
<Image Include="Icons\On-On Light.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200519.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200519.2\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||||
|
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||||
|
</Target>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\common\Display\Display.vcxproj">
|
||||||
|
<Project>{caba8dfb-823b-4bf2-93ac-3f31984150d9}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\..\common\SettingsAPI\SetttingsAPI.vcxproj">
|
||||||
|
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\..\common\Themes\Themes.vcxproj">
|
||||||
|
<Project>{98537082-0fdb-40de-abd8-0dc5a4269bab}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,100 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="dllmain.cpp" />
|
||||||
|
<ClCompile Include="Toolbar.cpp" />
|
||||||
|
<ClCompile Include="pch.cpp" />
|
||||||
|
<ClCompile Include="VideoConferenceModule.cpp" />
|
||||||
|
<ClCompile Include="trace.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="framework.h" />
|
||||||
|
<ClInclude Include="Toolbar.h" />
|
||||||
|
<ClInclude Include="pch.h" />
|
||||||
|
<ClInclude Include="VideoConferenceModule.h" />
|
||||||
|
<ClInclude Include="trace.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Image Include="black.bmp" />
|
||||||
|
<Image Include="Icons\Off-NotInUse Dark.png">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</Image>
|
||||||
|
<Image Include="Icons\Off-NotInUse Light.png">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</Image>
|
||||||
|
<Image Include="Icons\Off-Off Dark.png">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</Image>
|
||||||
|
<Image Include="Icons\Off-Off Light.png">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</Image>
|
||||||
|
<Image Include="Icons\Off-On Dark.png">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</Image>
|
||||||
|
<Image Include="Icons\Off-On Light.png">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</Image>
|
||||||
|
<Image Include="Icons\On-NotInUse Dark.png">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</Image>
|
||||||
|
<Image Include="Icons\On-NotInUse Light.png">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</Image>
|
||||||
|
<Image Include="Icons\On-Off Dark.png">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</Image>
|
||||||
|
<Image Include="Icons\On-Off Light.png">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</Image>
|
||||||
|
<Image Include="Icons\On-On Dark.png">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</Image>
|
||||||
|
<Image Include="Icons\On-On Light.png">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</Image>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
<None Include="Icons\Off-NotInUse Dark.svg">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Icons\Off-NotInUse Light.svg">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Icons\Off-Off Dark.svg">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Icons\Off-Off Light.svg">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Icons\Off-On Dark.svg">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Icons\Off-On Light.svg">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Icons\On-NotInUse Dark.svg">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Icons\On-NotInUse Light.svg">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Icons\On-Off Dark.svg">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Icons\On-Off Light.svg">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Icons\On-On Dark.svg">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="Icons\On-On Light.svg">
|
||||||
|
<Filter>Icons</Filter>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Icons">
|
||||||
|
<UniqueIdentifier>{735361e2-82fa-4034-b9c9-cd6aa099eaa5}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,568 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "VideoConferenceModule.h"
|
||||||
|
|
||||||
|
#include <WinUser.h>
|
||||||
|
|
||||||
|
#include <gdiplus.h>
|
||||||
|
#include <shellapi.h>
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include <common/debug_control.h>
|
||||||
|
#include <common/SettingsAPI/settings_helpers.h>
|
||||||
|
#include <common/utils/elevation.h>
|
||||||
|
#include <common/utils/process_path.h>
|
||||||
|
|
||||||
|
#include <CameraStateUpdateChannels.h>
|
||||||
|
|
||||||
|
#include "logging.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
|
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||||
|
|
||||||
|
VideoConferenceModule* instance = nullptr;
|
||||||
|
|
||||||
|
VideoConferenceSettings VideoConferenceModule::settings;
|
||||||
|
Toolbar VideoConferenceModule::toolbar;
|
||||||
|
|
||||||
|
HHOOK VideoConferenceModule::hook_handle;
|
||||||
|
|
||||||
|
IAudioEndpointVolume* endpointVolume = NULL;
|
||||||
|
|
||||||
|
bool VideoConferenceModule::isKeyPressed(unsigned int keyCode)
|
||||||
|
{
|
||||||
|
return (GetKeyState(keyCode) & 0x8000);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
bool VideoConferenceModule::isHotkeyPressed(DWORD code, PowerToysSettings::HotkeyObject& hotkey)
|
||||||
|
{
|
||||||
|
return code == hotkey.get_code() &&
|
||||||
|
isKeyPressed(VK_SHIFT) == hotkey.shift_pressed() &&
|
||||||
|
isKeyPressed(VK_CONTROL) == hotkey.ctrl_pressed() &&
|
||||||
|
isKeyPressed(VK_LWIN) == hotkey.win_pressed() &&
|
||||||
|
(isKeyPressed(VK_LMENU)) == hotkey.alt_pressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoConferenceModule::reverseMicrophoneMute()
|
||||||
|
{
|
||||||
|
bool muted = false;
|
||||||
|
for (auto& controlledMic : instance->_controlledMicrophones)
|
||||||
|
{
|
||||||
|
const bool was_muted = controlledMic.muted();
|
||||||
|
controlledMic.toggle_muted();
|
||||||
|
muted = muted || !was_muted;
|
||||||
|
}
|
||||||
|
if (muted)
|
||||||
|
{
|
||||||
|
Trace::MicrophoneMuted();
|
||||||
|
}
|
||||||
|
toolbar.setMicrophoneMute(muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoConferenceModule::getMicrophoneMuteState()
|
||||||
|
{
|
||||||
|
return instance->_microphoneTrackedInUI ? instance->_microphoneTrackedInUI->muted() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoConferenceModule::reverseVirtualCameraMuteState()
|
||||||
|
{
|
||||||
|
bool muted = false;
|
||||||
|
if (!instance->_settingsUpdateChannel.has_value())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->_settingsUpdateChannel->access([&muted](auto settingsMemory) {
|
||||||
|
auto settings = reinterpret_cast<CameraSettingsUpdateChannel*>(settingsMemory._data);
|
||||||
|
settings->useOverlayImage = !settings->useOverlayImage;
|
||||||
|
muted = settings->useOverlayImage;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (muted)
|
||||||
|
{
|
||||||
|
Trace::CameraMuted();
|
||||||
|
}
|
||||||
|
toolbar.setCameraMute(muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoConferenceModule::getVirtualCameraMuteState()
|
||||||
|
{
|
||||||
|
bool disabled = false;
|
||||||
|
if (!instance->_settingsUpdateChannel.has_value())
|
||||||
|
{
|
||||||
|
return disabled;
|
||||||
|
}
|
||||||
|
instance->_settingsUpdateChannel->access([&disabled](auto settingsMemory) {
|
||||||
|
auto settings = reinterpret_cast<CameraSettingsUpdateChannel*>(settingsMemory._data);
|
||||||
|
disabled = settings->useOverlayImage;
|
||||||
|
});
|
||||||
|
return disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoConferenceModule::getVirtualCameraInUse()
|
||||||
|
{
|
||||||
|
if (!instance->_settingsUpdateChannel.has_value())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool inUse = false;
|
||||||
|
instance->_settingsUpdateChannel->access([&inUse](auto settingsMemory) {
|
||||||
|
auto settings = reinterpret_cast<CameraSettingsUpdateChannel*>(settingsMemory._data);
|
||||||
|
inUse = settings->cameraInUse;
|
||||||
|
});
|
||||||
|
return inUse;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK VideoConferenceModule::LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (nCode == HC_ACTION)
|
||||||
|
{
|
||||||
|
switch (wParam)
|
||||||
|
{
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
KBDLLHOOKSTRUCT* kbd = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
|
||||||
|
|
||||||
|
if (isHotkeyPressed(kbd->vkCode, settings.cameraAndMicrophoneMuteHotkey))
|
||||||
|
{
|
||||||
|
const bool cameraInUse = getVirtualCameraInUse();
|
||||||
|
const bool microphoneIsMuted = getMicrophoneMuteState();
|
||||||
|
const bool cameraIsMuted = cameraInUse && getVirtualCameraMuteState();
|
||||||
|
if (cameraInUse)
|
||||||
|
{
|
||||||
|
// we're likely on a video call, so we must mute the unmuted cam/mic or reverse the mute state
|
||||||
|
// of everything, if cam and mic mute states are the same
|
||||||
|
if (microphoneIsMuted == cameraIsMuted)
|
||||||
|
{
|
||||||
|
reverseMicrophoneMute();
|
||||||
|
reverseVirtualCameraMuteState();
|
||||||
|
}
|
||||||
|
else if (cameraIsMuted)
|
||||||
|
{
|
||||||
|
reverseMicrophoneMute();
|
||||||
|
}
|
||||||
|
else if (microphoneIsMuted)
|
||||||
|
{
|
||||||
|
reverseVirtualCameraMuteState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if the camera is not in use, we just mute/unmute the mic
|
||||||
|
reverseMicrophoneMute();
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (isHotkeyPressed(kbd->vkCode, settings.microphoneMuteHotkey))
|
||||||
|
{
|
||||||
|
reverseMicrophoneMute();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (isHotkeyPressed(kbd->vkCode, settings.cameraMuteHotkey))
|
||||||
|
{
|
||||||
|
reverseVirtualCameraMuteState();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CallNextHookEx(hook_handle, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoConferenceModule::onGeneralSettingsChanged()
|
||||||
|
{
|
||||||
|
auto settings = PTSettingsHelper::load_general_settings();
|
||||||
|
bool enabled = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (json::has(settings, L"enabled"))
|
||||||
|
{
|
||||||
|
for (const auto& mod : settings.GetNamedObject(L"enabled"))
|
||||||
|
{
|
||||||
|
const auto value = mod.Value();
|
||||||
|
if (value.ValueType() != json::JsonValueType::Boolean)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (mod.Key() == get_key())
|
||||||
|
{
|
||||||
|
enabled = value.GetBoolean();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
LOG("Couldn't get enabled state");
|
||||||
|
}
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
enable();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoConferenceModule::onModuleSettingsChanged()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PowerToysSettings::PowerToyValues values = PowerToysSettings::PowerToyValues::load_from_settings_file(get_key());
|
||||||
|
//Trace::SettingsChanged(pressTime.value, overlayOpacity.value, theme.value);
|
||||||
|
|
||||||
|
if (_enabled)
|
||||||
|
{
|
||||||
|
if (const auto val = values.get_json(L"mute_camera_and_microphone_hotkey"))
|
||||||
|
{
|
||||||
|
settings.cameraAndMicrophoneMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
|
||||||
|
}
|
||||||
|
if (const auto val = values.get_json(L"mute_microphone_hotkey"))
|
||||||
|
{
|
||||||
|
settings.microphoneMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
|
||||||
|
}
|
||||||
|
if (const auto val = values.get_json(L"mute_camera_hotkey"))
|
||||||
|
{
|
||||||
|
settings.cameraMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
|
||||||
|
}
|
||||||
|
if (const auto val = values.get_string_value(L"toolbar_position"))
|
||||||
|
{
|
||||||
|
settings.toolbarPositionString = val.value();
|
||||||
|
}
|
||||||
|
if (const auto val = values.get_string_value(L"toolbar_monitor"))
|
||||||
|
{
|
||||||
|
settings.toolbarMonitorString = val.value();
|
||||||
|
}
|
||||||
|
if (const auto val = values.get_string_value(L"selected_camera"); val && val != settings.selectedCamera)
|
||||||
|
{
|
||||||
|
settings.selectedCamera = val.value();
|
||||||
|
sendSourceCameraNameUpdate();
|
||||||
|
}
|
||||||
|
if (const auto val = values.get_string_value(L"camera_overlay_image_path"); val && val != settings.imageOverlayPath)
|
||||||
|
{
|
||||||
|
settings.imageOverlayPath = val.value();
|
||||||
|
sendOverlayImageUpdate();
|
||||||
|
}
|
||||||
|
if (const auto val = values.get_bool_value(L"hide_toolbar_when_unmuted"))
|
||||||
|
{
|
||||||
|
toolbar.setHideToolbarWhenUnmuted(val.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto selectedMic = values.get_string_value(L"selected_mic");
|
||||||
|
if (selectedMic && selectedMic != settings.selectedMicrophone)
|
||||||
|
{
|
||||||
|
settings.selectedMicrophone = *selectedMic;
|
||||||
|
updateControlledMicrophones(settings.selectedMicrophone);
|
||||||
|
}
|
||||||
|
|
||||||
|
toolbar.show(settings.toolbarPositionString, settings.toolbarMonitorString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
LOG("onModuleSettingsChanged encountered an exception");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoConferenceModule::VideoConferenceModule() :
|
||||||
|
_generalSettingsWatcher{ PTSettingsHelper::get_powertoys_general_save_file_location(), [this] {
|
||||||
|
toolbar.scheduleGeneralSettingsUpdate();
|
||||||
|
} },
|
||||||
|
_moduleSettingsWatcher{ PTSettingsHelper::get_module_save_file_location(get_key()), [this] { toolbar.scheduleModuleSettingsUpdate(); } }
|
||||||
|
{
|
||||||
|
init_settings();
|
||||||
|
_settingsUpdateChannel =
|
||||||
|
SerializedSharedMemory::create(CameraSettingsUpdateChannel::endpoint(), sizeof(CameraSettingsUpdateChannel), false);
|
||||||
|
if (_settingsUpdateChannel)
|
||||||
|
{
|
||||||
|
_settingsUpdateChannel->access([](auto memory) {
|
||||||
|
auto updatesChannel = new (memory._data) CameraSettingsUpdateChannel{};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
sendSourceCameraNameUpdate();
|
||||||
|
sendOverlayImageUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline VideoConferenceModule::~VideoConferenceModule()
|
||||||
|
{
|
||||||
|
instance->unmuteAll();
|
||||||
|
toolbar.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
const wchar_t* VideoConferenceModule::get_name()
|
||||||
|
{
|
||||||
|
return L"Video Conference";
|
||||||
|
}
|
||||||
|
|
||||||
|
const wchar_t* VideoConferenceModule::get_key()
|
||||||
|
{
|
||||||
|
return L"Video Conference";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoConferenceModule::get_config(wchar_t* buffer, int* buffer_size)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoConferenceModule::set_config(const wchar_t* config)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PowerToysSettings::PowerToyValues values = PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
|
||||||
|
values.save_to_settings_file();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
LOG("VideoConferenceModule::set_config: exception during saving new settings values");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoConferenceModule::init_settings()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PowerToysSettings::PowerToyValues powerToysSettings = PowerToysSettings::PowerToyValues::load_from_settings_file(L"Video Conference");
|
||||||
|
|
||||||
|
if (const auto val = powerToysSettings.get_json(L"mute_camera_and_microphone_hotkey"))
|
||||||
|
{
|
||||||
|
settings.cameraAndMicrophoneMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
|
||||||
|
}
|
||||||
|
if (const auto val = powerToysSettings.get_json(L"mute_microphone_hotkey"))
|
||||||
|
{
|
||||||
|
settings.microphoneMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
|
||||||
|
}
|
||||||
|
if (const auto val = powerToysSettings.get_json(L"mute_camera_hotkey"))
|
||||||
|
{
|
||||||
|
settings.cameraMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
|
||||||
|
}
|
||||||
|
if (const auto val = powerToysSettings.get_string_value(L"toolbar_position"))
|
||||||
|
{
|
||||||
|
settings.toolbarPositionString = val.value();
|
||||||
|
}
|
||||||
|
if (const auto val = powerToysSettings.get_string_value(L"toolbar_monitor"))
|
||||||
|
{
|
||||||
|
settings.toolbarMonitorString = val.value();
|
||||||
|
}
|
||||||
|
if (const auto val = powerToysSettings.get_string_value(L"selected_camera"))
|
||||||
|
{
|
||||||
|
settings.selectedCamera = val.value();
|
||||||
|
}
|
||||||
|
if (const auto val = powerToysSettings.get_string_value(L"camera_overlay_image_path"))
|
||||||
|
{
|
||||||
|
settings.imageOverlayPath = val.value();
|
||||||
|
}
|
||||||
|
if (const auto val = powerToysSettings.get_bool_value(L"hide_toolbar_when_unmuted"))
|
||||||
|
{
|
||||||
|
toolbar.setHideToolbarWhenUnmuted(val.value());
|
||||||
|
}
|
||||||
|
if (const auto val = powerToysSettings.get_string_value(L"selected_mic"); val && *val != settings.selectedMicrophone)
|
||||||
|
{
|
||||||
|
settings.selectedMicrophone = *val;
|
||||||
|
updateControlledMicrophones(settings.selectedMicrophone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception&)
|
||||||
|
{
|
||||||
|
// Error while loading from the settings file. Just let default values stay as they are.
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto loaded = PTSettingsHelper::load_general_settings();
|
||||||
|
std::wstring settings_theme{ static_cast<std::wstring_view>(loaded.GetNamedString(L"theme", L"system")) };
|
||||||
|
if (settings_theme != L"dark" && settings_theme != L"light")
|
||||||
|
{
|
||||||
|
settings_theme = L"system";
|
||||||
|
}
|
||||||
|
toolbar.setTheme(settings_theme);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoConferenceModule::updateControlledMicrophones(const std::wstring_view new_mic)
|
||||||
|
{
|
||||||
|
for (auto& controlledMic : _controlledMicrophones)
|
||||||
|
{
|
||||||
|
controlledMic.set_muted(false);
|
||||||
|
}
|
||||||
|
_controlledMicrophones.clear();
|
||||||
|
_microphoneTrackedInUI = nullptr;
|
||||||
|
auto allMics = MicrophoneDevice::getAllActive();
|
||||||
|
if (new_mic == L"[All]")
|
||||||
|
{
|
||||||
|
_controlledMicrophones = std::move(allMics);
|
||||||
|
if (auto defaultMic = MicrophoneDevice::getDefault())
|
||||||
|
{
|
||||||
|
for (auto& controlledMic : _controlledMicrophones)
|
||||||
|
{
|
||||||
|
if (controlledMic.id() == defaultMic->id())
|
||||||
|
{
|
||||||
|
_microphoneTrackedInUI = &controlledMic;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto& controlledMic : allMics)
|
||||||
|
{
|
||||||
|
if (controlledMic.name() == new_mic)
|
||||||
|
{
|
||||||
|
_controlledMicrophones.emplace_back(std::move(controlledMic));
|
||||||
|
_microphoneTrackedInUI = &_controlledMicrophones[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_microphoneTrackedInUI)
|
||||||
|
{
|
||||||
|
_microphoneTrackedInUI->set_mute_changed_callback([&](const bool muted) {
|
||||||
|
toolbar.setMicrophoneMute(muted);
|
||||||
|
});
|
||||||
|
toolbar.setMicrophoneMute(_microphoneTrackedInUI->muted());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleProxyCamRegistration(const bool enable)
|
||||||
|
{
|
||||||
|
if (!is_process_elevated())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto vcmRoot = fs::path{ get_module_folderpath() } / "modules";
|
||||||
|
vcmRoot /= "VideoConference";
|
||||||
|
|
||||||
|
std::array<fs::path, 2> proxyFilters = { vcmRoot / "VideoConferenceProxyFilter_x64.dll", vcmRoot / "VideoConferenceProxyFilter_x86.dll" };
|
||||||
|
for (const auto filter : proxyFilters)
|
||||||
|
{
|
||||||
|
std::wstring params{ L"/s " };
|
||||||
|
if (!enable)
|
||||||
|
{
|
||||||
|
params += L"/u ";
|
||||||
|
}
|
||||||
|
params += '"';
|
||||||
|
params += filter;
|
||||||
|
params += '"';
|
||||||
|
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||||
|
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC };
|
||||||
|
sei.lpFile = L"regsvr32";
|
||||||
|
sei.lpParameters = params.c_str();
|
||||||
|
sei.nShow = SW_SHOWNORMAL;
|
||||||
|
ShellExecuteExW(&sei);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoConferenceModule::enable()
|
||||||
|
{
|
||||||
|
if (!_enabled)
|
||||||
|
{
|
||||||
|
toggleProxyCamRegistration(true);
|
||||||
|
toolbar.setMicrophoneMute(getMicrophoneMuteState());
|
||||||
|
toolbar.setCameraMute(getVirtualCameraMuteState());
|
||||||
|
|
||||||
|
toolbar.show(settings.toolbarPositionString, settings.toolbarMonitorString);
|
||||||
|
|
||||||
|
_enabled = true;
|
||||||
|
|
||||||
|
#if defined(DISABLE_LOWLEVEL_HOOKS_WHEN_DEBUGGED)
|
||||||
|
if (IsDebuggerPresent())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoConferenceModule::unmuteAll()
|
||||||
|
{
|
||||||
|
if (getVirtualCameraMuteState())
|
||||||
|
{
|
||||||
|
reverseVirtualCameraMuteState();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getMicrophoneMuteState())
|
||||||
|
{
|
||||||
|
reverseMicrophoneMute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoConferenceModule::disable()
|
||||||
|
{
|
||||||
|
if (_enabled)
|
||||||
|
{
|
||||||
|
toggleProxyCamRegistration(false);
|
||||||
|
if (hook_handle)
|
||||||
|
{
|
||||||
|
bool success = UnhookWindowsHookEx(hook_handle);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
hook_handle = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->unmuteAll();
|
||||||
|
toolbar.hide();
|
||||||
|
|
||||||
|
_enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoConferenceModule::is_enabled()
|
||||||
|
{
|
||||||
|
return _enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoConferenceModule::destroy()
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
instance = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoConferenceModule::sendSourceCameraNameUpdate()
|
||||||
|
{
|
||||||
|
if (!_settingsUpdateChannel.has_value() || settings.selectedCamera.empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_settingsUpdateChannel->access([](auto memory) {
|
||||||
|
auto updatesChannel = reinterpret_cast<CameraSettingsUpdateChannel*>(memory._data);
|
||||||
|
updatesChannel->sourceCameraName.emplace();
|
||||||
|
std::copy(begin(settings.selectedCamera), end(settings.selectedCamera), begin(*updatesChannel->sourceCameraName));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoConferenceModule::sendOverlayImageUpdate()
|
||||||
|
{
|
||||||
|
if (!_settingsUpdateChannel.has_value())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_imageOverlayChannel.reset();
|
||||||
|
|
||||||
|
wchar_t powertoysDirectory[MAX_PATH + 1];
|
||||||
|
|
||||||
|
DWORD length = GetModuleFileNameW(nullptr, powertoysDirectory, MAX_PATH);
|
||||||
|
PathRemoveFileSpecW(powertoysDirectory);
|
||||||
|
|
||||||
|
std::wstring blankImagePath(powertoysDirectory);
|
||||||
|
blankImagePath += L"\\modules\\VideoConference\\black.bmp";
|
||||||
|
|
||||||
|
_imageOverlayChannel = SerializedSharedMemory::create_readonly(CameraOverlayImageChannel::endpoint(),
|
||||||
|
settings.imageOverlayPath != L"" ? settings.imageOverlayPath : blankImagePath);
|
||||||
|
|
||||||
|
const auto imageSize = static_cast<uint32_t>(_imageOverlayChannel->size());
|
||||||
|
_settingsUpdateChannel->access([imageSize](auto memory) {
|
||||||
|
auto updatesChannel = reinterpret_cast<CameraSettingsUpdateChannel*>(memory._data);
|
||||||
|
updatesChannel->overlayImageSize.emplace(imageSize);
|
||||||
|
updatesChannel->newOverlayImagePosted = true;
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <common/SettingsAPI/FileWatcher.h>
|
||||||
|
|
||||||
|
#include <mmdeviceapi.h>
|
||||||
|
#include <endpointvolume.h>
|
||||||
|
|
||||||
|
#include <interface/powertoy_module_interface.h>
|
||||||
|
|
||||||
|
#include <common/SettingsAPI/settings_objects.h>
|
||||||
|
#include <MicrophoneDevice.h>
|
||||||
|
|
||||||
|
#include "Toolbar.h"
|
||||||
|
|
||||||
|
#include <SerializedSharedMemory.h>
|
||||||
|
|
||||||
|
extern class VideoConferenceModule* instance;
|
||||||
|
|
||||||
|
struct VideoConferenceSettings
|
||||||
|
{
|
||||||
|
PowerToysSettings::HotkeyObject cameraAndMicrophoneMuteHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, false, 78);
|
||||||
|
PowerToysSettings::HotkeyObject microphoneMuteHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, true, 65);
|
||||||
|
PowerToysSettings::HotkeyObject cameraMuteHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, true, 79);
|
||||||
|
|
||||||
|
std::wstring toolbarPositionString;
|
||||||
|
std::wstring toolbarMonitorString;
|
||||||
|
|
||||||
|
std::wstring selectedCamera;
|
||||||
|
std::wstring imageOverlayPath;
|
||||||
|
std::wstring selectedMicrophone;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VideoConferenceModule : public PowertoyModuleIface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VideoConferenceModule();
|
||||||
|
~VideoConferenceModule();
|
||||||
|
virtual const wchar_t* get_name() override;
|
||||||
|
|
||||||
|
virtual bool get_config(wchar_t* buffer, int* buffer_size) override;
|
||||||
|
|
||||||
|
virtual void set_config(const wchar_t* config) override;
|
||||||
|
|
||||||
|
virtual void enable() override;
|
||||||
|
virtual void disable() override;
|
||||||
|
virtual bool is_enabled() override;
|
||||||
|
virtual void destroy() override;
|
||||||
|
|
||||||
|
virtual const wchar_t * get_key() override;
|
||||||
|
|
||||||
|
void sendSourceCameraNameUpdate();
|
||||||
|
void sendOverlayImageUpdate();
|
||||||
|
|
||||||
|
static void unmuteAll();
|
||||||
|
static void reverseMicrophoneMute();
|
||||||
|
static bool getMicrophoneMuteState();
|
||||||
|
static void reverseVirtualCameraMuteState();
|
||||||
|
static bool getVirtualCameraMuteState();
|
||||||
|
static bool getVirtualCameraInUse();
|
||||||
|
|
||||||
|
void onGeneralSettingsChanged();
|
||||||
|
void onModuleSettingsChanged();
|
||||||
|
private:
|
||||||
|
|
||||||
|
void init_settings();
|
||||||
|
void updateControlledMicrophones(const std::wstring_view new_mic);
|
||||||
|
// all callback methods and used by callback have to be static
|
||||||
|
static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||||
|
static bool isKeyPressed(unsigned int keyCode);
|
||||||
|
static bool isHotkeyPressed(DWORD code, PowerToysSettings::HotkeyObject& hotkey);
|
||||||
|
|
||||||
|
static HHOOK hook_handle;
|
||||||
|
bool _enabled = false;
|
||||||
|
|
||||||
|
std::vector<MicrophoneDevice> _controlledMicrophones;
|
||||||
|
MicrophoneDevice* _microphoneTrackedInUI = nullptr;
|
||||||
|
|
||||||
|
std::optional<SerializedSharedMemory> _imageOverlayChannel;
|
||||||
|
std::optional<SerializedSharedMemory> _settingsUpdateChannel;
|
||||||
|
|
||||||
|
FileWatcher _generalSettingsWatcher;
|
||||||
|
FileWatcher _moduleSettingsWatcher;
|
||||||
|
|
||||||
|
static VideoConferenceSettings settings;
|
||||||
|
static Toolbar toolbar;
|
||||||
|
};
|
BIN
src/modules/videoconference/VideoConferenceModule/black.bmp
Normal file
After Width: | Height: | Size: 822 B |
@ -0,0 +1,35 @@
|
|||||||
|
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||||
|
#include "pch.h"
|
||||||
|
#include <interface/powertoy_module_interface.h>
|
||||||
|
#include "trace.h"
|
||||||
|
#include "VideoConferenceModule.h"
|
||||||
|
|
||||||
|
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||||
|
{
|
||||||
|
switch (ul_reason_for_call)
|
||||||
|
{
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
Trace::RegisterProvider();
|
||||||
|
break;
|
||||||
|
case DLL_THREAD_ATTACH:
|
||||||
|
case DLL_THREAD_DETACH:
|
||||||
|
break;
|
||||||
|
case DLL_PROCESS_DETACH:
|
||||||
|
Trace::UnregisterProvider();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
|
||||||
|
{
|
||||||
|
if (!instance)
|
||||||
|
{
|
||||||
|
instance = new VideoConferenceModule();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||||
|
// Windows Header Files
|
||||||
|
#include <windows.h>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.Windows.CppWinRT" version="2.0.200729.8" targetFramework="native" />
|
||||||
|
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.200519.2" targetFramework="native" />
|
||||||
|
</packages>
|
@ -0,0 +1,5 @@
|
|||||||
|
// pch.cpp: source file corresponding to the pre-compiled header
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
|
24
src/modules/videoconference/VideoConferenceModule/pch.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <Unknwn.h>
|
||||||
|
|
||||||
|
#include <winrt/base.h>
|
||||||
|
#include <winrt/Windows.Foundation.h>
|
||||||
|
#include <winrt/Windows.Foundation.Collections.h>
|
||||||
|
|
||||||
|
#include <wil/resource.h>
|
||||||
|
#include <wil/com.h>
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
#include <optional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <Shobjidl.h>
|
||||||
|
#include <Shlwapi.h>
|
||||||
|
|
||||||
|
#include <common/Telemetry/ProjectTelemetry.h>
|
57
src/modules/videoconference/VideoConferenceModule/trace.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
|
TRACELOGGING_DEFINE_PROVIDER(
|
||||||
|
g_hProvider,
|
||||||
|
"Microsoft.PowerToys",
|
||||||
|
// {38e8889b-9731-53f5-e901-e8a7c1753074}
|
||||||
|
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
|
||||||
|
TraceLoggingOptionProjectTelemetry());
|
||||||
|
|
||||||
|
void Trace::RegisterProvider() noexcept
|
||||||
|
{
|
||||||
|
TraceLoggingRegister(g_hProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Trace::UnregisterProvider() noexcept
|
||||||
|
{
|
||||||
|
TraceLoggingUnregister(g_hProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Trace::SettingsChanged(const struct VideoConferenceSettings& settings) noexcept
|
||||||
|
{
|
||||||
|
bool CustomOverlayImage = (settings.imageOverlayPath.length() > 0);
|
||||||
|
|
||||||
|
TraceLoggingWrite(
|
||||||
|
g_hProvider,
|
||||||
|
"VideoConference_SettingsChanged",
|
||||||
|
TraceLoggingWideString(settings.toolbarPositionString.c_str(), "ToolbarPosition"),
|
||||||
|
TraceLoggingWideString(settings.toolbarMonitorString.c_str(), "ToolbarMonitorSelection"),
|
||||||
|
TraceLoggingBool(CustomOverlayImage, "CustomImageOverlayUsed"),
|
||||||
|
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||||
|
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
|
||||||
|
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Trace::MicrophoneMuted() noexcept
|
||||||
|
{
|
||||||
|
TraceLoggingWrite(
|
||||||
|
g_hProvider,
|
||||||
|
"VideoConference_MicrophoneMuted",
|
||||||
|
TraceLoggingBoolean(true, "MicrophoneMuted"),
|
||||||
|
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||||
|
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
|
||||||
|
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Trace::CameraMuted() noexcept
|
||||||
|
{
|
||||||
|
TraceLoggingWrite(
|
||||||
|
g_hProvider,
|
||||||
|
"VideoConference_CameraMuted",
|
||||||
|
TraceLoggingBoolean(true, "CameraMuted"),
|
||||||
|
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||||
|
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
|
||||||
|
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||||
|
}
|
12
src/modules/videoconference/VideoConferenceModule/trace.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "VideoConferenceModule.h"
|
||||||
|
|
||||||
|
class Trace
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void RegisterProvider() noexcept;
|
||||||
|
static void UnregisterProvider() noexcept;
|
||||||
|
static void SettingsChanged(const struct VideoConferenceSettings &settings) noexcept;
|
||||||
|
static void MicrophoneMuted() noexcept;
|
||||||
|
static void CameraMuted() noexcept;
|
||||||
|
};
|
@ -0,0 +1,118 @@
|
|||||||
|
#include "DirectShowUtils.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
unique_media_type_ptr CopyMediaType(const AM_MEDIA_TYPE* source)
|
||||||
|
{
|
||||||
|
unique_media_type_ptr target{ static_cast<AM_MEDIA_TYPE*>(CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE))) };
|
||||||
|
*target = *source;
|
||||||
|
if (source->cbFormat)
|
||||||
|
{
|
||||||
|
target->pbFormat = static_cast<BYTE*>(CoTaskMemAlloc(source->cbFormat));
|
||||||
|
std::copy(source->pbFormat, source->pbFormat + source->cbFormat, target->pbFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target->pUnk)
|
||||||
|
{
|
||||||
|
target->pUnk->AddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IMemAllocator> GetPinAllocator(wil::com_ptr_nothrow<IPin>& inputPin)
|
||||||
|
{
|
||||||
|
if (!inputPin)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
wil::com_ptr_nothrow<IMemAllocator> allocator;
|
||||||
|
if (auto memInput = inputPin.try_query<IMemInputPin>(); memInput)
|
||||||
|
{
|
||||||
|
memInput->GetAllocator(&allocator);
|
||||||
|
return allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
unique_media_type_ptr CopyMediaType(const unique_media_type_ptr& source)
|
||||||
|
{
|
||||||
|
return CopyMediaType(source.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyFreeMediaType(AM_MEDIA_TYPE& mt)
|
||||||
|
{
|
||||||
|
if (mt.cbFormat != 0)
|
||||||
|
{
|
||||||
|
CoTaskMemFree(mt.pbFormat);
|
||||||
|
mt.cbFormat = 0;
|
||||||
|
mt.pbFormat = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mt.pUnk != nullptr)
|
||||||
|
{
|
||||||
|
mt.pUnk->Release();
|
||||||
|
mt.pUnk = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyDeleteMediaType(AM_MEDIA_TYPE* pmt)
|
||||||
|
{
|
||||||
|
if (!pmt)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyFreeMediaType(*pmt);
|
||||||
|
CoTaskMemFree(const_cast<AM_MEDIA_TYPE*>(pmt));
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT MediaTypeEnumerator::Next(ULONG cObjects, AM_MEDIA_TYPE** outObjects, ULONG* pcFetched)
|
||||||
|
{
|
||||||
|
if (!outObjects)
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG fetched = 0;
|
||||||
|
ULONG toFetch = cObjects;
|
||||||
|
while (toFetch-- && _pos < _objects.size())
|
||||||
|
{
|
||||||
|
auto copy = CopyMediaType(_objects[_pos++]);
|
||||||
|
outObjects[fetched++] = copy.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pcFetched)
|
||||||
|
{
|
||||||
|
*pcFetched = fetched;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetched == cObjects ? S_OK : S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT MediaTypeEnumerator::Skip(ULONG cObjects)
|
||||||
|
{
|
||||||
|
_pos += cObjects;
|
||||||
|
return _pos < _objects.size() ? S_OK : S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT MediaTypeEnumerator::Reset()
|
||||||
|
{
|
||||||
|
_pos = 0;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT MediaTypeEnumerator::Clone(IEnumMediaTypes** ppEnum)
|
||||||
|
{
|
||||||
|
auto cloned = winrt::make_self<MediaTypeEnumerator>();
|
||||||
|
cloned->_objects.resize(_objects.size());
|
||||||
|
for (size_t i = 0; i < _objects.size(); ++i)
|
||||||
|
{
|
||||||
|
cloned->_objects[i] = CopyMediaType(_objects[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
cloned->_pos = _pos;
|
||||||
|
cloned.as<IEnumMediaTypes>().copy_to(ppEnum);
|
||||||
|
return S_OK;
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <initguid.h>
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <dshow.h>
|
||||||
|
|
||||||
|
#include <wil/com.h>
|
||||||
|
#include <winrt/Windows.Foundation.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Logging.h"
|
||||||
|
|
||||||
|
void MyDeleteMediaType(AM_MEDIA_TYPE* pmt);
|
||||||
|
|
||||||
|
using unique_media_type_ptr =
|
||||||
|
wistd::unique_ptr<AM_MEDIA_TYPE, wil::function_deleter<decltype(&MyDeleteMediaType), MyDeleteMediaType>>;
|
||||||
|
|
||||||
|
unique_media_type_ptr CopyMediaType(const unique_media_type_ptr& source);
|
||||||
|
unique_media_type_ptr CopyMediaType(const AM_MEDIA_TYPE* source);
|
||||||
|
|
||||||
|
template<typename ObjectInterface, typename EnumeratorInterface>
|
||||||
|
struct ObjectEnumerator : public winrt::implements<ObjectEnumerator<ObjectInterface, EnumeratorInterface>, EnumeratorInterface>
|
||||||
|
{
|
||||||
|
std::vector<wil::com_ptr_nothrow<ObjectInterface>> _objects;
|
||||||
|
ULONG _pos = 0;
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE Next(ULONG cObjects, ObjectInterface** outObjects, ULONG* pcFetched) override
|
||||||
|
{
|
||||||
|
if (!outObjects)
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG fetched = 0;
|
||||||
|
ULONG toFetch = cObjects;
|
||||||
|
while (toFetch-- && _pos < _objects.size())
|
||||||
|
{
|
||||||
|
_objects[_pos++].copy_to(&outObjects[fetched++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pcFetched)
|
||||||
|
{
|
||||||
|
*pcFetched = fetched;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetched == cObjects ? S_OK : S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE Skip(ULONG cObjects) override
|
||||||
|
{
|
||||||
|
_pos += cObjects;
|
||||||
|
return _pos < _objects.size() ? S_OK : S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE Reset() override
|
||||||
|
{
|
||||||
|
_pos = 0;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE Clone(EnumeratorInterface** ppEnum) override
|
||||||
|
{
|
||||||
|
auto cloned = winrt::make_self<ObjectEnumerator>();
|
||||||
|
cloned->_objects = _objects;
|
||||||
|
cloned->_pos = _pos;
|
||||||
|
cloned.as<EnumeratorInterface>().copy_to(ppEnum);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~ObjectEnumerator() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MediaTypeEnumerator : public winrt::implements<MediaTypeEnumerator, IEnumMediaTypes>
|
||||||
|
{
|
||||||
|
std::vector<unique_media_type_ptr> _objects;
|
||||||
|
ULONG _pos = 0;
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE Next(ULONG cObjects, AM_MEDIA_TYPE** outObjects, ULONG* pcFetched) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE Skip(ULONG cObjects) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE Reset() override;
|
||||||
|
HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes** ppEnum) override;
|
||||||
|
|
||||||
|
virtual ~MediaTypeEnumerator() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IMemAllocator> GetPinAllocator(wil::com_ptr_nothrow<IPin>& inputPin);
|
@ -0,0 +1,425 @@
|
|||||||
|
#include <initguid.h>
|
||||||
|
|
||||||
|
#include <dxgiformat.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <winrt/base.h>
|
||||||
|
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4005)
|
||||||
|
#include <wincodec.h>
|
||||||
|
#pragma warning(pop)
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <mfapi.h>
|
||||||
|
#include <shcore.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <wil/resource.h>
|
||||||
|
#include <wil/com.h>
|
||||||
|
|
||||||
|
#include <mfapi.h>
|
||||||
|
#include <mfidl.h>
|
||||||
|
#include <mftransform.h>
|
||||||
|
#include <dshow.h>
|
||||||
|
#include <Wincodecsdk.h>
|
||||||
|
|
||||||
|
#include <shlwapi.h>
|
||||||
|
|
||||||
|
#include "Logging.h"
|
||||||
|
|
||||||
|
IWICImagingFactory* _GetWIC() noexcept
|
||||||
|
{
|
||||||
|
static IWICImagingFactory* s_Factory = nullptr;
|
||||||
|
|
||||||
|
if (s_Factory)
|
||||||
|
{
|
||||||
|
return s_Factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
OK_OR_BAIL(CoCreateInstance(
|
||||||
|
CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, __uuidof(IWICImagingFactory), (LPVOID*)&s_Factory));
|
||||||
|
|
||||||
|
return s_Factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReencodeJPGImage(BYTE* imageBuf, const DWORD imageSize, DWORD& reencodedSize)
|
||||||
|
{
|
||||||
|
auto pWIC = _GetWIC();
|
||||||
|
wil::com_ptr_nothrow<IStream> imageStream = SHCreateMemStream(imageBuf, imageSize);
|
||||||
|
if (!imageStream)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode jpg into bitmap
|
||||||
|
wil::com_ptr_nothrow<IWICBitmapDecoder> bitmapDecoder;
|
||||||
|
OK_OR_BAIL(pWIC->CreateDecoderFromStream(imageStream.get(), nullptr, WICDecodeMetadataCacheOnLoad, &bitmapDecoder));
|
||||||
|
wil::com_ptr_nothrow<IWICBitmapFrameDecode> decodedFrame;
|
||||||
|
OK_OR_BAIL(bitmapDecoder->GetFrame(0, &decodedFrame));
|
||||||
|
wil::com_ptr_nothrow<IWICBitmapSource> bitmap;
|
||||||
|
bitmap.attach(decodedFrame.detach());
|
||||||
|
UINT width = 0, height = 0;
|
||||||
|
OK_OR_BAIL(bitmap->GetSize(&width, &height));
|
||||||
|
|
||||||
|
// Initialize jpg encoder
|
||||||
|
wil::com_ptr_nothrow<IWICBitmapEncoder> encoder;
|
||||||
|
OK_OR_BAIL(pWIC->CreateEncoder(GUID_ContainerFormatJpeg, nullptr, &encoder));
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IStream> outputStream;
|
||||||
|
OK_OR_BAIL(CreateStreamOnHGlobal(nullptr, true, &outputStream));
|
||||||
|
OK_OR_BAIL(encoder->Initialize(outputStream.get(), WICBitmapEncoderNoCache));
|
||||||
|
wil::com_ptr_nothrow<IWICBitmapFrameEncode> encodedFrame;
|
||||||
|
wil::com_ptr_nothrow<IPropertyBag2> encoderOptions;
|
||||||
|
OK_OR_BAIL(encoder->CreateNewFrame(&encodedFrame, &encoderOptions));
|
||||||
|
|
||||||
|
ULONG nProperties = 0;
|
||||||
|
OK_OR_BAIL(encoderOptions->CountProperties(&nProperties));
|
||||||
|
for (ULONG propIdx = 0; propIdx < nProperties; ++propIdx)
|
||||||
|
{
|
||||||
|
PROPBAG2 propBag{};
|
||||||
|
ULONG _;
|
||||||
|
OK_OR_BAIL(encoderOptions->GetPropertyInfo(propIdx, 1, &propBag, &_));
|
||||||
|
if (propBag.pstrName == std::wstring_view{ L"ImageQuality" })
|
||||||
|
{
|
||||||
|
wil::unique_variant variant;
|
||||||
|
variant.vt = VT_R4;
|
||||||
|
variant.fltVal = 0.1f;
|
||||||
|
OK_OR_BAIL(encoderOptions->Write(1, &propBag, &variant));
|
||||||
|
LOG("Successfully set jpg compression quality");
|
||||||
|
// skip the rest of the properties
|
||||||
|
propIdx = nProperties;
|
||||||
|
}
|
||||||
|
CoTaskMemFree(propBag.pstrName);
|
||||||
|
}
|
||||||
|
|
||||||
|
OK_OR_BAIL(encodedFrame->Initialize(encoderOptions.get()));
|
||||||
|
WICPixelFormatGUID intermediateFormat = GUID_WICPixelFormat24bppRGB;
|
||||||
|
|
||||||
|
OK_OR_BAIL(encodedFrame->SetPixelFormat(&intermediateFormat));
|
||||||
|
OK_OR_BAIL(encodedFrame->SetSize(width, height));
|
||||||
|
|
||||||
|
// Commit the image encoding
|
||||||
|
OK_OR_BAIL(encodedFrame->WriteSource(bitmap.get(), nullptr));
|
||||||
|
OK_OR_BAIL(encodedFrame->Commit());
|
||||||
|
OK_OR_BAIL(encoder->Commit());
|
||||||
|
|
||||||
|
STATSTG intermediateStreamStat{};
|
||||||
|
OK_OR_BAIL(outputStream->Stat(&intermediateStreamStat, STATFLAG_NONAME));
|
||||||
|
const ULONGLONG jpgStreamSize = intermediateStreamStat.cbSize.QuadPart;
|
||||||
|
HGLOBAL streamMemoryHandle{};
|
||||||
|
OK_OR_BAIL(GetHGlobalFromStream(outputStream.get(), &streamMemoryHandle));
|
||||||
|
|
||||||
|
auto jpgStreamMemory = static_cast<uint8_t*>(GlobalLock(streamMemoryHandle));
|
||||||
|
std::copy(jpgStreamMemory, jpgStreamMemory + jpgStreamSize, imageBuf);
|
||||||
|
auto unlockJpgStreamMemory = wil::scope_exit([jpgStreamMemory] { GlobalUnlock(jpgStreamMemory); });
|
||||||
|
reencodedSize = (DWORD)jpgStreamSize;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IWICBitmapSource> LoadAsRGB24BitmapWithSize(IWICImagingFactory* pWIC,
|
||||||
|
wil::com_ptr_nothrow<IStream> image,
|
||||||
|
const UINT targetWidth,
|
||||||
|
const UINT targetHeight)
|
||||||
|
{
|
||||||
|
wil::com_ptr_nothrow<IWICBitmapSource> bitmap;
|
||||||
|
// Initialize image bitmap decoder from filename and get the image frame
|
||||||
|
wil::com_ptr_nothrow<IWICBitmapDecoder> bitmapDecoder;
|
||||||
|
OK_OR_BAIL(pWIC->CreateDecoderFromStream(image.get(), nullptr, WICDecodeMetadataCacheOnLoad, &bitmapDecoder));
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IWICBitmapFrameDecode> decodedFrame;
|
||||||
|
OK_OR_BAIL(bitmapDecoder->GetFrame(0, &decodedFrame));
|
||||||
|
|
||||||
|
UINT imageWidth = 0, imageHeight = 0;
|
||||||
|
OK_OR_BAIL(decodedFrame->GetSize(&imageWidth, &imageHeight));
|
||||||
|
|
||||||
|
// Scale the image if required
|
||||||
|
if (targetWidth != imageWidth || targetHeight != imageHeight)
|
||||||
|
{
|
||||||
|
wil::com_ptr_nothrow<IWICBitmapScaler> scaler;
|
||||||
|
OK_OR_BAIL(pWIC->CreateBitmapScaler(&scaler));
|
||||||
|
OK_OR_BAIL(
|
||||||
|
scaler->Initialize(decodedFrame.get(), targetWidth, targetHeight, WICBitmapInterpolationModeHighQualityCubic));
|
||||||
|
bitmap.attach(scaler.detach());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bitmap.attach(decodedFrame.detach());
|
||||||
|
}
|
||||||
|
WICPixelFormatGUID pixelFormat{};
|
||||||
|
OK_OR_BAIL(bitmap->GetPixelFormat(&pixelFormat));
|
||||||
|
|
||||||
|
const auto targetPixelFormat = GUID_WICPixelFormat24bppBGR;
|
||||||
|
if (pixelFormat != targetPixelFormat)
|
||||||
|
{
|
||||||
|
wil::com_ptr_nothrow<IWICBitmapSource> convertedBitmap;
|
||||||
|
if (SUCCEEDED(WICConvertBitmapSource(targetPixelFormat, bitmap.get(), &convertedBitmap)))
|
||||||
|
{
|
||||||
|
return convertedBitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IStream> EncodeBitmapToContainer(IWICImagingFactory* pWIC,
|
||||||
|
wil::com_ptr_nothrow<IWICBitmapSource> bitmap,
|
||||||
|
const GUID& containerGUID,
|
||||||
|
const UINT width,
|
||||||
|
const UINT height,
|
||||||
|
const float quality)
|
||||||
|
{
|
||||||
|
wil::com_ptr_nothrow<IWICBitmapEncoder> encoder;
|
||||||
|
pWIC->CreateEncoder(containerGUID, nullptr, &encoder);
|
||||||
|
|
||||||
|
if (!encoder)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare the encoder output memory stream and encoding params
|
||||||
|
wil::com_ptr_nothrow<IStream> encodedBitmap;
|
||||||
|
OK_OR_BAIL(CreateStreamOnHGlobal(nullptr, true, &encodedBitmap));
|
||||||
|
OK_OR_BAIL(encoder->Initialize(encodedBitmap.get(), WICBitmapEncoderNoCache));
|
||||||
|
wil::com_ptr_nothrow<IWICBitmapFrameEncode> encodedFrame;
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IPropertyBag2> encoderOptions;
|
||||||
|
OK_OR_BAIL(encoder->CreateNewFrame(&encodedFrame, &encoderOptions));
|
||||||
|
|
||||||
|
ULONG nProperties = 0;
|
||||||
|
OK_OR_BAIL(encoderOptions->CountProperties(&nProperties));
|
||||||
|
for (ULONG propIdx = 0; propIdx < nProperties; ++propIdx)
|
||||||
|
{
|
||||||
|
PROPBAG2 propBag{};
|
||||||
|
ULONG _;
|
||||||
|
OK_OR_BAIL(encoderOptions->GetPropertyInfo(propIdx, 1, &propBag, &_));
|
||||||
|
if (propBag.pstrName == std::wstring_view{ L"ImageQuality" })
|
||||||
|
{
|
||||||
|
wil::unique_variant variant;
|
||||||
|
variant.vt = VT_R4;
|
||||||
|
variant.fltVal = quality;
|
||||||
|
OK_OR_BAIL(encoderOptions->Write(1, &propBag, &variant));
|
||||||
|
LOG("Successfully set jpg compression quality");
|
||||||
|
// skip the rest of the properties
|
||||||
|
propIdx = nProperties;
|
||||||
|
}
|
||||||
|
CoTaskMemFree(propBag.pstrName);
|
||||||
|
}
|
||||||
|
|
||||||
|
OK_OR_BAIL(encodedFrame->Initialize(encoderOptions.get()));
|
||||||
|
|
||||||
|
WICPixelFormatGUID intermediateFormat = GUID_WICPixelFormat24bppRGB;
|
||||||
|
OK_OR_BAIL(encodedFrame->SetPixelFormat(&intermediateFormat));
|
||||||
|
OK_OR_BAIL(encodedFrame->SetSize(width, height));
|
||||||
|
|
||||||
|
// Commit the image encoding
|
||||||
|
OK_OR_BAIL(encodedFrame->WriteSource(bitmap.get(), nullptr));
|
||||||
|
OK_OR_BAIL(encodedFrame->Commit());
|
||||||
|
OK_OR_BAIL(encoder->Commit());
|
||||||
|
return encodedBitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMFSample* ConvertIMFVideoSample(const MFT_REGISTER_TYPE_INFO& inputType,
|
||||||
|
IMFMediaType* outputMediaType,
|
||||||
|
const wil::com_ptr_nothrow<IMFSample>& inputSample,
|
||||||
|
const UINT width,
|
||||||
|
const UINT height)
|
||||||
|
{
|
||||||
|
IMFActivate** ppVDActivate = nullptr;
|
||||||
|
UINT32 count = 0;
|
||||||
|
|
||||||
|
MFT_REGISTER_TYPE_INFO outputType = { MFMediaType_Video, {} };
|
||||||
|
outputMediaType->GetGUID(MF_MT_SUBTYPE, &outputType.guidSubtype);
|
||||||
|
|
||||||
|
const std::array<GUID, 3> transformerCategories = {
|
||||||
|
MFT_CATEGORY_VIDEO_PROCESSOR, MFT_CATEGORY_VIDEO_DECODER, MFT_CATEGORY_VIDEO_ENCODER
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& transformerCategory : transformerCategories)
|
||||||
|
{
|
||||||
|
OK_OR_BAIL(MFTEnumEx(transformerCategory, MFT_ENUM_FLAG_SYNCMFT, &inputType, &outputType, &ppVDActivate, &count));
|
||||||
|
if (count != 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IMFTransform> videoTransformer;
|
||||||
|
|
||||||
|
bool videoDecoderActivated = false;
|
||||||
|
for (UINT32 i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
if (!videoDecoderActivated && !FAILED(ppVDActivate[i]->ActivateObject(IID_PPV_ARGS(&videoTransformer))))
|
||||||
|
{
|
||||||
|
videoDecoderActivated = true;
|
||||||
|
}
|
||||||
|
ppVDActivate[i]->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count)
|
||||||
|
{
|
||||||
|
CoTaskMemFree(ppVDActivate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!videoDecoderActivated)
|
||||||
|
{
|
||||||
|
LOG("No converter avialable for the selected format");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto shutdownVideoDecoder = wil::scope_exit([&videoTransformer] { MFShutdownObject(videoTransformer.get()); });
|
||||||
|
// Set input/output types for the decoder
|
||||||
|
wil::com_ptr_nothrow<IMFMediaType> intermediateFrameMediaType;
|
||||||
|
OK_OR_BAIL(MFCreateMediaType(&intermediateFrameMediaType));
|
||||||
|
intermediateFrameMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
|
||||||
|
intermediateFrameMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24);
|
||||||
|
intermediateFrameMediaType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
|
||||||
|
intermediateFrameMediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
|
||||||
|
OK_OR_BAIL(MFSetAttributeSize(intermediateFrameMediaType.get(), MF_MT_FRAME_SIZE, width, height));
|
||||||
|
OK_OR_BAIL(MFSetAttributeRatio(intermediateFrameMediaType.get(), MF_MT_PIXEL_ASPECT_RATIO, width, height));
|
||||||
|
OK_OR_BAIL(videoTransformer->SetInputType(0, intermediateFrameMediaType.get(), 0));
|
||||||
|
OK_OR_BAIL(videoTransformer->SetOutputType(0, outputMediaType, 0));
|
||||||
|
|
||||||
|
// Process the input sample
|
||||||
|
OK_OR_BAIL(videoTransformer->ProcessInput(0, inputSample.get(), 0));
|
||||||
|
|
||||||
|
// Check whether we need to allocate output sample and buffer ourselves
|
||||||
|
MFT_OUTPUT_STREAM_INFO outputStreamInfo{};
|
||||||
|
OK_OR_BAIL(videoTransformer->GetOutputStreamInfo(0, &outputStreamInfo));
|
||||||
|
const bool onlyProvidesSamples = outputStreamInfo.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES;
|
||||||
|
const bool canProvideSamples = outputStreamInfo.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES;
|
||||||
|
const bool mustAllocateSample =
|
||||||
|
(!onlyProvidesSamples && !canProvideSamples) ||
|
||||||
|
(!onlyProvidesSamples && (outputStreamInfo.dwFlags & MFT_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER));
|
||||||
|
|
||||||
|
MFT_OUTPUT_DATA_BUFFER outputSamples{};
|
||||||
|
IMFSample* outputSample = nullptr;
|
||||||
|
|
||||||
|
// If so, do the allocation
|
||||||
|
if (mustAllocateSample)
|
||||||
|
{
|
||||||
|
OK_OR_BAIL(MFCreateSample(&outputSample));
|
||||||
|
OK_OR_BAIL(outputSample->SetSampleDuration(333333));
|
||||||
|
OK_OR_BAIL(outputSample->SetSampleTime(1));
|
||||||
|
OK_OR_BAIL(outputSample->SetUINT32(MF_MT_VIDEO_ROTATION, MFVideoRotationFormat::MFVideoRotationFormat_0));
|
||||||
|
IMFMediaBuffer* outputMediaBuffer = nullptr;
|
||||||
|
OK_OR_BAIL(
|
||||||
|
MFCreateAlignedMemoryBuffer(outputStreamInfo.cbSize, outputStreamInfo.cbAlignment - 1, &outputMediaBuffer));
|
||||||
|
OK_OR_BAIL(outputMediaBuffer->SetCurrentLength(outputStreamInfo.cbSize));
|
||||||
|
OK_OR_BAIL(outputSample->AddBuffer(outputMediaBuffer));
|
||||||
|
outputSamples.pSample = outputSample;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, produce the output sample
|
||||||
|
DWORD processStatus = 0;
|
||||||
|
if (failed(videoTransformer->ProcessOutput(0, 1, &outputSamples, &processStatus)))
|
||||||
|
{
|
||||||
|
LOG("Failed to convert image frame");
|
||||||
|
}
|
||||||
|
if (outputSamples.pEvents)
|
||||||
|
{
|
||||||
|
outputSamples.pEvents->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputSamples.pSample;
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IMFSample> LoadImageAsSample(wil::com_ptr_nothrow<IStream> imageStream,
|
||||||
|
IMFMediaType* sampleMediaType,
|
||||||
|
const float quality) noexcept
|
||||||
|
{
|
||||||
|
UINT targetWidth = 0;
|
||||||
|
UINT targetHeight = 0;
|
||||||
|
OK_OR_BAIL(MFGetAttributeSize(sampleMediaType, MF_MT_FRAME_SIZE, &targetWidth, &targetHeight));
|
||||||
|
MFT_REGISTER_TYPE_INFO outputType = { MFMediaType_Video, {} };
|
||||||
|
OK_OR_BAIL(sampleMediaType->GetGUID(MF_MT_SUBTYPE, &outputType.guidSubtype));
|
||||||
|
|
||||||
|
IWICImagingFactory* pWIC = _GetWIC();
|
||||||
|
if (!pWIC)
|
||||||
|
{
|
||||||
|
LOG("Failed to create IWICImagingFactory");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!imageStream)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto srcImageBitmap = LoadAsRGB24BitmapWithSize(pWIC, imageStream, targetWidth, targetHeight);
|
||||||
|
if (!srcImageBitmap)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, let's create a sample containing RGB24 bitmap
|
||||||
|
IMFSample* outputSample = nullptr;
|
||||||
|
OK_OR_BAIL(MFCreateSample(&outputSample));
|
||||||
|
OK_OR_BAIL(outputSample->SetUINT32(MF_MT_VIDEO_ROTATION, MFVideoRotationFormat::MFVideoRotationFormat_0));
|
||||||
|
OK_OR_BAIL(outputSample->SetSampleDuration(333333));
|
||||||
|
OK_OR_BAIL(outputSample->SetSampleTime(1));
|
||||||
|
IMFMediaBuffer* outputMediaBuffer = nullptr;
|
||||||
|
const DWORD nPixelBytes = targetWidth * targetHeight * 3;
|
||||||
|
OK_OR_BAIL(MFCreateAlignedMemoryBuffer(nPixelBytes, MF_64_BYTE_ALIGNMENT, &outputMediaBuffer));
|
||||||
|
|
||||||
|
const UINT stride = 3 * targetWidth;
|
||||||
|
|
||||||
|
DWORD max_length = 0, current_length = 0;
|
||||||
|
BYTE* sampleBufferMemory = nullptr;
|
||||||
|
OK_OR_BAIL(outputMediaBuffer->Lock(&sampleBufferMemory, &max_length, ¤t_length));
|
||||||
|
OK_OR_BAIL(srcImageBitmap->CopyPixels(nullptr, stride, nPixelBytes, sampleBufferMemory));
|
||||||
|
OK_OR_BAIL(outputMediaBuffer->Unlock());
|
||||||
|
|
||||||
|
OK_OR_BAIL(outputMediaBuffer->SetCurrentLength(nPixelBytes));
|
||||||
|
OK_OR_BAIL(outputSample->AddBuffer(outputMediaBuffer));
|
||||||
|
|
||||||
|
if (outputType.guidSubtype == MFVideoFormat_RGB24)
|
||||||
|
{
|
||||||
|
return outputSample;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case for mjpg, since we need to use jpg container for it instead of supplying raw pixels
|
||||||
|
if (outputType.guidSubtype == MFVideoFormat_MJPG)
|
||||||
|
{
|
||||||
|
// Use an intermediate jpg container sample which will be transcoded to the target format
|
||||||
|
wil::com_ptr_nothrow<IStream> jpgStream =
|
||||||
|
EncodeBitmapToContainer(pWIC, srcImageBitmap, GUID_ContainerFormatJpeg, targetWidth, targetHeight, quality);
|
||||||
|
|
||||||
|
// Obtain stream size and lock its memory pointer
|
||||||
|
STATSTG intermediateStreamStat{};
|
||||||
|
OK_OR_BAIL(jpgStream->Stat(&intermediateStreamStat, STATFLAG_NONAME));
|
||||||
|
const ULONGLONG jpgStreamSize = intermediateStreamStat.cbSize.QuadPart;
|
||||||
|
HGLOBAL streamMemoryHandle{};
|
||||||
|
OK_OR_BAIL(GetHGlobalFromStream(jpgStream.get(), &streamMemoryHandle));
|
||||||
|
|
||||||
|
auto jpgStreamMemory = static_cast<uint8_t*>(GlobalLock(streamMemoryHandle));
|
||||||
|
auto unlockJpgStreamMemory = wil::scope_exit([jpgStreamMemory] { GlobalUnlock(jpgStreamMemory); });
|
||||||
|
|
||||||
|
// Create a sample from the input image buffer
|
||||||
|
wil::com_ptr_nothrow<IMFSample> jpgSample;
|
||||||
|
OK_OR_BAIL(MFCreateSample(&jpgSample));
|
||||||
|
OK_OR_BAIL(jpgSample->SetUINT32(MF_MT_VIDEO_ROTATION, MFVideoRotationFormat::MFVideoRotationFormat_0));
|
||||||
|
IMFMediaBuffer* inputMediaBuffer = nullptr;
|
||||||
|
OK_OR_BAIL(MFCreateAlignedMemoryBuffer(static_cast<DWORD>(jpgStreamSize), MF_64_BYTE_ALIGNMENT, &inputMediaBuffer));
|
||||||
|
BYTE* inputBuf = nullptr;
|
||||||
|
OK_OR_BAIL(inputMediaBuffer->Lock(&inputBuf, &max_length, ¤t_length));
|
||||||
|
if (max_length < jpgStreamSize)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::copy(jpgStreamMemory, jpgStreamMemory + jpgStreamSize, inputBuf);
|
||||||
|
unlockJpgStreamMemory.reset();
|
||||||
|
OK_OR_BAIL(inputMediaBuffer->Unlock());
|
||||||
|
OK_OR_BAIL(inputMediaBuffer->SetCurrentLength(static_cast<DWORD>(jpgStreamSize)));
|
||||||
|
OK_OR_BAIL(jpgSample->AddBuffer(inputMediaBuffer));
|
||||||
|
|
||||||
|
return jpgSample;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we are ready to convert it to the requested media type
|
||||||
|
MFT_REGISTER_TYPE_INFO intermediateType = { MFMediaType_Video, MFVideoFormat_RGB24 };
|
||||||
|
|
||||||
|
// But if no conversion is needed, just return the input sample
|
||||||
|
|
||||||
|
return ConvertIMFVideoSample(intermediateType, sampleMediaType, outputSample, targetWidth, targetHeight);
|
||||||
|
}
|
@ -0,0 +1,634 @@
|
|||||||
|
#include "Logging.h"
|
||||||
|
#include "VideoCaptureDevice.h"
|
||||||
|
|
||||||
|
#include <wil/resource.h>
|
||||||
|
#include <cguid.h>
|
||||||
|
|
||||||
|
struct VideoCaptureReceiverFilter : winrt::implements<VideoCaptureReceiverFilter, IBaseFilter, IAMFilterMiscFlags>
|
||||||
|
{
|
||||||
|
FILTER_STATE _state = State_Stopped;
|
||||||
|
IFilterGraph* _graph = nullptr;
|
||||||
|
wil::com_ptr_nothrow<IPin> _videoReceiverPin;
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE GetMiscFlags() override { return AM_FILTER_MISC_FLAGS_IS_RENDERER; }
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE GetClassID(CLSID*) override { return E_NOTIMPL; }
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE Stop() override
|
||||||
|
{
|
||||||
|
_state = State_Stopped;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE Pause() override
|
||||||
|
{
|
||||||
|
_state = State_Paused;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME) override
|
||||||
|
{
|
||||||
|
_state = State_Running;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE GetState(DWORD, FILTER_STATE* outState) override
|
||||||
|
{
|
||||||
|
*outState = _state;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock** outRefClock) override
|
||||||
|
{
|
||||||
|
*outRefClock = nullptr;
|
||||||
|
return NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock*) override { return S_OK; }
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins** ppEnum) override
|
||||||
|
{
|
||||||
|
auto enumerator = winrt::make_self<ObjectEnumerator<IPin, IEnumPins>>();
|
||||||
|
enumerator->_objects.emplace_back(_videoReceiverPin);
|
||||||
|
*ppEnum = enumerator.detach();
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR, IPin**) override { return E_NOTIMPL; }
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph* pGraph, LPCWSTR) override
|
||||||
|
{
|
||||||
|
_graph = pGraph;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO* pInfo) override
|
||||||
|
{
|
||||||
|
std::copy(std::begin(NAME), std::end(NAME), pInfo->achName);
|
||||||
|
if (_graph)
|
||||||
|
{
|
||||||
|
pInfo->pGraph = _graph;
|
||||||
|
_graph->AddRef();
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR* pVendorInfo) override
|
||||||
|
{
|
||||||
|
auto info = static_cast<LPWSTR>(CoTaskMemAlloc(sizeof(VENDOR)));
|
||||||
|
std::copy(std::begin(VENDOR), std::end(VENDOR), info);
|
||||||
|
*pVendorInfo = info;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~VideoCaptureReceiverFilter() = default;
|
||||||
|
|
||||||
|
constexpr static inline wchar_t NAME[] = L"PowerToysVCMCaptureFilter";
|
||||||
|
constexpr static inline wchar_t VENDOR[] = L"Microsoft Corporation";
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VideoCaptureReceiverPin : winrt::implements<VideoCaptureReceiverPin, IPin, IMemInputPin>
|
||||||
|
{
|
||||||
|
VideoCaptureReceiverFilter* _owningFilter = nullptr;
|
||||||
|
unique_media_type_ptr _expectedMediaType;
|
||||||
|
wil::com_ptr_nothrow<IPin> _captureInputPin;
|
||||||
|
unique_media_type_ptr _inputCaptureMediaType;
|
||||||
|
std::atomic_bool _flushing = false;
|
||||||
|
VideoCaptureDevice::callback_t _frameCallback;
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IMemAllocator> _allocator;
|
||||||
|
|
||||||
|
VideoCaptureReceiverPin(unique_media_type_ptr mediaType, VideoCaptureReceiverFilter* filter) :
|
||||||
|
_expectedMediaType{ std::move(mediaType) }, _owningFilter{ filter }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE Connect(IPin*, const AM_MEDIA_TYPE* pmt) override
|
||||||
|
{
|
||||||
|
if (_owningFilter->_state == State_Running)
|
||||||
|
{
|
||||||
|
return VFW_E_NOT_STOPPED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_captureInputPin)
|
||||||
|
{
|
||||||
|
return VFW_E_ALREADY_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pmt || pmt->majortype == GUID_NULL)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pmt->majortype != _expectedMediaType->majortype || pmt->subtype != _expectedMediaType->subtype)
|
||||||
|
{
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin* pConnector, const AM_MEDIA_TYPE* pmt) override
|
||||||
|
{
|
||||||
|
if (!pConnector || !pmt)
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_captureInputPin)
|
||||||
|
{
|
||||||
|
return VFW_E_ALREADY_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_owningFilter->_state != State_Stopped)
|
||||||
|
{
|
||||||
|
return VFW_E_NOT_STOPPED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QueryAccept(pmt) != S_OK)
|
||||||
|
{
|
||||||
|
return VFW_E_TYPE_NOT_ACCEPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
_captureInputPin = pConnector;
|
||||||
|
_inputCaptureMediaType = CopyMediaType(pmt);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE Disconnect() override
|
||||||
|
{
|
||||||
|
_allocator.reset();
|
||||||
|
_captureInputPin.reset();
|
||||||
|
_inputCaptureMediaType.reset();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE ConnectedTo(IPin** pPin) override
|
||||||
|
{
|
||||||
|
if (!_captureInputPin)
|
||||||
|
{
|
||||||
|
return VFW_E_NOT_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
_captureInputPin.copy_to(pPin);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE* pmt) override
|
||||||
|
{
|
||||||
|
if (!pmt)
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_inputCaptureMediaType)
|
||||||
|
{
|
||||||
|
return VFW_E_NOT_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pmt = *CopyMediaType(_inputCaptureMediaType).release();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO* pInfo) override
|
||||||
|
{
|
||||||
|
if (!pInfo)
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
pInfo->pFilter = _owningFilter;
|
||||||
|
if (_owningFilter)
|
||||||
|
{
|
||||||
|
_owningFilter->AddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
pInfo->dir = PINDIR_INPUT;
|
||||||
|
std::copy(std::begin(NAME), std::end(NAME), pInfo->achName);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION* pPinDir) override
|
||||||
|
{
|
||||||
|
if (!pPinDir)
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pPinDir = PINDIR_INPUT;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryId(LPWSTR* lpId) override
|
||||||
|
{
|
||||||
|
if (!lpId)
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
*lpId = static_cast<LPWSTR>(CoTaskMemAlloc(sizeof(NAME)));
|
||||||
|
|
||||||
|
std::copy(std::begin(NAME), std::end(NAME), *lpId);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE* pmt) override
|
||||||
|
{
|
||||||
|
if (!pmt)
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pmt->majortype != _expectedMediaType->majortype || pmt->subtype != _expectedMediaType->subtype)
|
||||||
|
{
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_captureInputPin)
|
||||||
|
{
|
||||||
|
_inputCaptureMediaType.reset(const_cast<AM_MEDIA_TYPE*>(pmt));
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes** ppEnum) override
|
||||||
|
{
|
||||||
|
if (!ppEnum)
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto enumerator = winrt::make_self<MediaTypeEnumerator>();
|
||||||
|
enumerator->_objects.emplace_back(CopyMediaType(_expectedMediaType));
|
||||||
|
*ppEnum = enumerator.detach();
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin**, ULONG*) override { return E_NOTIMPL; }
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE EndOfStream() override { return S_OK; }
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE BeginFlush() override
|
||||||
|
{
|
||||||
|
_flushing = true;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE EndFlush() override
|
||||||
|
{
|
||||||
|
_flushing = false;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME, REFERENCE_TIME, double) override { return S_OK; }
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE GetAllocator(IMemAllocator** allocator) override
|
||||||
|
{
|
||||||
|
VERBOSE_LOG;
|
||||||
|
if (!_allocator)
|
||||||
|
{
|
||||||
|
return VFW_E_NO_ALLOCATOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
_allocator.copy_to(allocator);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE NotifyAllocator(IMemAllocator* allocator, BOOL readOnly) override
|
||||||
|
{
|
||||||
|
VERBOSE_LOG;
|
||||||
|
LOG(readOnly ? "Allocator READONLY: true" : "Allocator READONLY: false");
|
||||||
|
_allocator = allocator;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE GetAllocatorRequirements(ALLOCATOR_PROPERTIES*) override { return E_NOTIMPL; }
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE Receive(IMediaSample* pSample) override
|
||||||
|
{
|
||||||
|
if (_flushing)
|
||||||
|
{
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pSample)
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pSample && _frameCallback)
|
||||||
|
{
|
||||||
|
_frameCallback(pSample);
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE ReceiveMultiple(IMediaSample** pSamples, long nSamples, long* nSamplesProcessed) override
|
||||||
|
{
|
||||||
|
if (!pSamples && nSamples)
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_flushing)
|
||||||
|
{
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (long i = 0; i < nSamples; i++)
|
||||||
|
{
|
||||||
|
Receive(pSamples[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
*nSamplesProcessed = nSamples;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE ReceiveCanBlock() override { return S_FALSE; }
|
||||||
|
|
||||||
|
virtual ~VideoCaptureReceiverPin() = default;
|
||||||
|
|
||||||
|
constexpr static inline wchar_t NAME[] = L"PowerToysVCMCapturePin";
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr long MINIMAL_FPS_ALLOWED = 29;
|
||||||
|
|
||||||
|
const char* GetMediaSubTypeString(const GUID& guid)
|
||||||
|
{
|
||||||
|
if (guid == MEDIASUBTYPE_RGB24)
|
||||||
|
{
|
||||||
|
return "MEDIASUBTYPE_RGB24";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (guid == MEDIASUBTYPE_YUY2)
|
||||||
|
{
|
||||||
|
return "MEDIASUBTYPE_YUY2";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (guid == MEDIASUBTYPE_MJPG)
|
||||||
|
{
|
||||||
|
return "MEDIASUBTYPE_MJPG";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (guid == MEDIASUBTYPE_NV12)
|
||||||
|
{
|
||||||
|
return "MEDIASUBTYPE_NV12";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "MEDIASUBTYPE_UNKNOWN";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<VideoStreamFormat> SelectBestMediaType(wil::com_ptr_nothrow<IPin>& pin)
|
||||||
|
{
|
||||||
|
VERBOSE_LOG;
|
||||||
|
wil::com_ptr_nothrow<IEnumMediaTypes> mediaTypeEnum;
|
||||||
|
if (pin->EnumMediaTypes(&mediaTypeEnum); !mediaTypeEnum)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG _ = 0;
|
||||||
|
VideoStreamFormat bestFormat;
|
||||||
|
unique_media_type_ptr mt;
|
||||||
|
while (mediaTypeEnum->Next(1, wil::out_param(mt), &_) == S_OK)
|
||||||
|
{
|
||||||
|
if (mt->majortype != MEDIATYPE_Video)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto format = reinterpret_cast<VIDEOINFOHEADER*>(mt->pbFormat);
|
||||||
|
if (!format || !format->AvgTimePerFrame)
|
||||||
|
{
|
||||||
|
LOG("VideoInfoHeader not found");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto formatAvgFPS = 10000000LL / format->AvgTimePerFrame;
|
||||||
|
if (format->AvgTimePerFrame > bestFormat.avgFrameTime || formatAvgFPS < MINIMAL_FPS_ALLOWED)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format->bmiHeader.biWidth < bestFormat.width || format->bmiHeader.biHeight < bestFormat.height)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mt->subtype != MEDIASUBTYPE_YUY2 && mt->subtype != MEDIASUBTYPE_MJPG && mt->subtype != MEDIASUBTYPE_RGB24)
|
||||||
|
{
|
||||||
|
OLECHAR* guidString;
|
||||||
|
StringFromCLSID(mt->subtype, &guidString);
|
||||||
|
LOG("Skipping mediatype due to unsupported subtype: ");
|
||||||
|
LOG(guidString);
|
||||||
|
::CoTaskMemFree(guidString);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bestFormat.avgFrameTime = format->AvgTimePerFrame;
|
||||||
|
bestFormat.width = format->bmiHeader.biWidth;
|
||||||
|
bestFormat.height = format->bmiHeader.biHeight;
|
||||||
|
bestFormat.mediaType = std::move(mt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bestFormat.mediaType)
|
||||||
|
{
|
||||||
|
LOG(L"Couldn't select a suitable media format");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
char selectedFormat[512]{};
|
||||||
|
sprintf_s(selectedFormat, "Selected media format: %s %ldx%ld %lld fps", GetMediaSubTypeString(bestFormat.mediaType->subtype), bestFormat.width, bestFormat.height, 10000000LL / bestFormat.avgFrameTime);
|
||||||
|
LOG(selectedFormat);
|
||||||
|
|
||||||
|
return std::move(bestFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<VideoCaptureDeviceInfo> VideoCaptureDevice::ListAll()
|
||||||
|
{
|
||||||
|
std::vector<VideoCaptureDeviceInfo> devices;
|
||||||
|
auto enumeratorFactory = wil::CoCreateInstanceNoThrow<ICreateDevEnum>(CLSID_SystemDeviceEnum);
|
||||||
|
if (!enumeratorFactory)
|
||||||
|
{
|
||||||
|
LOG("Couldn't create devenum factory");
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IEnumMoniker> enumMoniker;
|
||||||
|
enumeratorFactory->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &enumMoniker, CDEF_DEVMON_PNP_DEVICE);
|
||||||
|
if (!enumMoniker)
|
||||||
|
{
|
||||||
|
LOG("Couldn't create class enumerator");
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG _ = 0;
|
||||||
|
wil::com_ptr_nothrow<IMoniker> moniker;
|
||||||
|
while (enumMoniker->Next(1, &moniker, &_) == S_OK)
|
||||||
|
{
|
||||||
|
LOG("Inspecting moniker");
|
||||||
|
VideoCaptureDeviceInfo deviceInfo;
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IPropertyBag> propertyData;
|
||||||
|
moniker->BindToStorage(nullptr, nullptr, IID_IPropertyBag, reinterpret_cast<void**>(&propertyData));
|
||||||
|
if (!propertyData)
|
||||||
|
{
|
||||||
|
LOG("BindToStorage failed");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::unique_variant propVal;
|
||||||
|
propVal.vt = VT_BSTR;
|
||||||
|
|
||||||
|
if (FAILED(propertyData->Read(L"FriendlyName", &propVal, nullptr)))
|
||||||
|
{
|
||||||
|
LOG("Couldn't obtain FriendlyName property");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceInfo.friendlyName = { propVal.bstrVal, SysStringLen(propVal.bstrVal) };
|
||||||
|
LOG(deviceInfo.friendlyName);
|
||||||
|
|
||||||
|
propVal.reset();
|
||||||
|
propVal.vt = VT_BSTR;
|
||||||
|
|
||||||
|
if (FAILED(propertyData->Read(L"DevicePath", &propVal, nullptr)))
|
||||||
|
{
|
||||||
|
LOG("Couldn't obtain DevicePath property");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
deviceInfo.devicePath = { propVal.bstrVal, SysStringLen(propVal.bstrVal) };
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IBaseFilter> filter;
|
||||||
|
moniker->BindToObject(nullptr, nullptr, IID_IBaseFilter, reinterpret_cast<void**>(&filter));
|
||||||
|
if (!filter)
|
||||||
|
{
|
||||||
|
LOG("Couldn't BindToObject");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IEnumPins> pinsEnum;
|
||||||
|
if (FAILED(filter->EnumPins(&pinsEnum)))
|
||||||
|
{
|
||||||
|
LOG("BindToObject EnumPins");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IPin> pin;
|
||||||
|
while (pinsEnum->Next(1, &pin, &_) == S_OK)
|
||||||
|
{
|
||||||
|
LOG("Inspecting pin");
|
||||||
|
// Skip pins which do not belong to capture category
|
||||||
|
GUID category{};
|
||||||
|
DWORD __;
|
||||||
|
if (auto props = pin.try_copy<IKsPropertySet>();
|
||||||
|
!props ||
|
||||||
|
FAILED(props->Get(AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, nullptr, 0, &category, sizeof(GUID), &__)) ||
|
||||||
|
category != PIN_CATEGORY_CAPTURE)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip non-output pins
|
||||||
|
if (PIN_DIRECTION direction = {}; FAILED(pin->QueryDirection(&direction)) || direction != PINDIR_OUTPUT)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("Found a pin of suitable category and direction, selecting format");
|
||||||
|
auto bestFormat = SelectBestMediaType(pin);
|
||||||
|
if (!bestFormat)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceInfo.captureOutputPin = std::move(pin);
|
||||||
|
deviceInfo.bestFormat = std::move(bestFormat.value());
|
||||||
|
deviceInfo.captureOutputFilter = std::move(filter);
|
||||||
|
devices.emplace_back(std::move(deviceInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<VideoCaptureDevice> VideoCaptureDevice::Create(VideoCaptureDeviceInfo&& vdi, callback_t callback)
|
||||||
|
{
|
||||||
|
VERBOSE_LOG;
|
||||||
|
VideoCaptureDevice result;
|
||||||
|
|
||||||
|
result._graph = wil::CoCreateInstanceNoThrow<IGraphBuilder>(CLSID_FilterGraph);
|
||||||
|
result._builder = wil::CoCreateInstanceNoThrow<ICaptureGraphBuilder2>(CLSID_CaptureGraphBuilder2);
|
||||||
|
if (!result._graph || !result._builder)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(result._builder->SetFiltergraph(result._graph.get())))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
result._control = result._graph.try_query<IMediaControl>();
|
||||||
|
if (!result._control)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pinConfig = vdi.captureOutputPin.try_query<IAMStreamConfig>();
|
||||||
|
if (!pinConfig)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(pinConfig->SetFormat(vdi.bestFormat.mediaType.get())))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto captureInputFilter = winrt::make_self<VideoCaptureReceiverFilter>();
|
||||||
|
auto receiverPin = winrt::make_self<VideoCaptureReceiverPin>(std::move(vdi.bestFormat.mediaType), captureInputFilter.get());
|
||||||
|
receiverPin->_frameCallback = std::move(callback);
|
||||||
|
captureInputFilter->_videoReceiverPin.attach(receiverPin.get());
|
||||||
|
auto detachReceiverPin = wil::scope_exit([&receiverPin]() { receiverPin.detach(); });
|
||||||
|
|
||||||
|
if (FAILED(result._graph->AddFilter(captureInputFilter.get(), nullptr)))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(result._graph->AddFilter(vdi.captureOutputFilter.get(), nullptr)))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(result._graph->ConnectDirect(vdi.captureOutputPin.get(), captureInputFilter->_videoReceiverPin.get(), nullptr)))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
result._allocator = receiverPin->_allocator;
|
||||||
|
return std::make_optional(std::move(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoCaptureDevice::StartCapture()
|
||||||
|
{
|
||||||
|
VERBOSE_LOG;
|
||||||
|
return SUCCEEDED(_control->Run());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoCaptureDevice::StopCapture()
|
||||||
|
{
|
||||||
|
VERBOSE_LOG;
|
||||||
|
return SUCCEEDED(_control->Stop());
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoCaptureDevice::~VideoCaptureDevice()
|
||||||
|
{
|
||||||
|
StopCapture();
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <initguid.h>
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <dshow.h>
|
||||||
|
|
||||||
|
#include <wil/com.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include "DirectShowUtils.h"
|
||||||
|
|
||||||
|
struct VideoStreamFormat
|
||||||
|
{
|
||||||
|
long width = 0;
|
||||||
|
long height = 0;
|
||||||
|
REFERENCE_TIME avgFrameTime = std::numeric_limits<REFERENCE_TIME>::max();
|
||||||
|
unique_media_type_ptr mediaType;
|
||||||
|
|
||||||
|
VideoStreamFormat() = default;
|
||||||
|
|
||||||
|
VideoStreamFormat(const VideoStreamFormat&) = delete;
|
||||||
|
VideoStreamFormat& operator=(const VideoStreamFormat&) = delete;
|
||||||
|
|
||||||
|
VideoStreamFormat(VideoStreamFormat&&) = default;
|
||||||
|
VideoStreamFormat& operator=(VideoStreamFormat&&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VideoCaptureDeviceInfo
|
||||||
|
{
|
||||||
|
std::wstring friendlyName;
|
||||||
|
std::wstring devicePath;
|
||||||
|
wil::com_ptr_nothrow<IPin> captureOutputPin;
|
||||||
|
wil::com_ptr_nothrow<IBaseFilter> captureOutputFilter;
|
||||||
|
VideoStreamFormat bestFormat;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VideoCaptureDevice final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wil::com_ptr_nothrow<IMemAllocator> _allocator;
|
||||||
|
|
||||||
|
using callback_t = std::function<void(IMediaSample*)>;
|
||||||
|
|
||||||
|
static std::vector<VideoCaptureDeviceInfo> ListAll();
|
||||||
|
static std::optional<VideoCaptureDevice> Create(VideoCaptureDeviceInfo&& vdi, callback_t callback);
|
||||||
|
|
||||||
|
bool StartCapture();
|
||||||
|
bool StopCapture();
|
||||||
|
|
||||||
|
~VideoCaptureDevice();
|
||||||
|
|
||||||
|
private:
|
||||||
|
wil::com_ptr_nothrow<IGraphBuilder> _graph;
|
||||||
|
wil::com_ptr_nothrow<ICaptureGraphBuilder2> _builder;
|
||||||
|
wil::com_ptr_nothrow<IMediaControl> _control;
|
||||||
|
callback_t _callback;
|
||||||
|
};
|
@ -0,0 +1,919 @@
|
|||||||
|
#include "VideoCaptureProxyFilter.h"
|
||||||
|
|
||||||
|
#include "VideoCaptureDevice.h"
|
||||||
|
#include <mfidl.h>
|
||||||
|
#include <Shlwapi.h>
|
||||||
|
#include <mfapi.h>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
constexpr static inline wchar_t FILTER_NAME[] = L"PowerToysVCMProxyFilter";
|
||||||
|
constexpr static inline wchar_t PIN_NAME[] = L"PowerToysVCMProxyPIN";
|
||||||
|
constexpr static inline wchar_t VENDOR[] = L"Microsoft Corporation";
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr float initialJpgQuality = 0.5f;
|
||||||
|
constexpr std::array<unsigned char, 3> overlayColor = { 0, 0, 0 };
|
||||||
|
// clang-format off
|
||||||
|
unsigned char bmpPixelData[58] = {
|
||||||
|
0x42, 0x4D, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
|
||||||
|
0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||||
|
0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
|
||||||
|
0x00, 0x00, 0xC4, 0x0E, 0x00, 0x00, 0xC4, 0x0E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, overlayColor[0], overlayColor[1], overlayColor[2], 0x00
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IMemAllocator> VideoCaptureProxyPin::FindAllocator()
|
||||||
|
{
|
||||||
|
auto allocator = GetPinAllocator(_connectedInputPin);
|
||||||
|
if (!allocator && _owningFilter->_captureDevice)
|
||||||
|
{
|
||||||
|
allocator = _owningFilter->_captureDevice->_allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
return allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IMFSample> LoadImageAsSample(wil::com_ptr_nothrow<IStream> imageStream,
|
||||||
|
IMFMediaType* sampleMediaType,
|
||||||
|
const float quality) noexcept;
|
||||||
|
bool ReencodeJPGImage(BYTE* imageBuf, const DWORD imageSize, DWORD& reencodedSize);
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::Connect(IPin* pReceivePin, const AM_MEDIA_TYPE*)
|
||||||
|
{
|
||||||
|
if (!pReceivePin)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::Connect FAILED pReceivePin");
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_owningFilter->_state == State_Running)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::Connect FAILED _owningFilter->_state");
|
||||||
|
return VFW_E_NOT_STOPPED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_connectedInputPin)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::Connect FAILED _connectedInputPin");
|
||||||
|
return VFW_E_ALREADY_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(pReceivePin->ReceiveConnection(this, _mediaFormat.get())))
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::Connect FAILED pReceivePin->ReceiveConnection");
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
_connectedInputPin = pReceivePin;
|
||||||
|
|
||||||
|
auto memInput = _connectedInputPin.try_query<IMemInputPin>();
|
||||||
|
if (!memInput)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::Connect FAILED _connectedInputPin.try_query");
|
||||||
|
return VFW_E_NO_TRANSPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto allocator = FindAllocator();
|
||||||
|
if (allocator == nullptr)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::Connect FAILED FindAllocator");
|
||||||
|
return VFW_E_NO_TRANSPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(memInput->NotifyAllocator(allocator.get(), false)))
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::Connect FAILED memInput->NotifyAllocator");
|
||||||
|
return VFW_E_NO_TRANSPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::ReceiveConnection(IPin*, const AM_MEDIA_TYPE*)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::Disconnect(void)
|
||||||
|
{
|
||||||
|
if (!_connectedInputPin)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::Disconnect FAILED _connectedInputPin");
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_connectedInputPin.reset();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::ConnectedTo(IPin** pPin)
|
||||||
|
{
|
||||||
|
if (!_connectedInputPin)
|
||||||
|
{
|
||||||
|
*pPin = nullptr;
|
||||||
|
return VFW_E_NOT_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
_connectedInputPin.try_copy_to(pPin);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::ConnectionMediaType(AM_MEDIA_TYPE* pmt)
|
||||||
|
{
|
||||||
|
if (!_connectedInputPin)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::ConnectionMediaType FAILED _connectedInputPin");
|
||||||
|
return VFW_E_NOT_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pmt = *CopyMediaType(_mediaFormat).release();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::QueryPinInfo(PIN_INFO* pInfo)
|
||||||
|
{
|
||||||
|
if (!pInfo)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::QueryPinInfo FAILED pInfo");
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
pInfo->pFilter = _owningFilter;
|
||||||
|
if (_owningFilter)
|
||||||
|
{
|
||||||
|
_owningFilter->AddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_mediaFormat->majortype == MEDIATYPE_Video)
|
||||||
|
{
|
||||||
|
std::copy(std::begin(PIN_NAME), std::end(PIN_NAME), pInfo->achName);
|
||||||
|
}
|
||||||
|
|
||||||
|
pInfo->dir = PINDIR_OUTPUT;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::QueryDirection(PIN_DIRECTION* pPinDir)
|
||||||
|
{
|
||||||
|
if (!pPinDir)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::QueryDirection FAILED pPinDir");
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pPinDir = PINDIR_OUTPUT;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::QueryId(LPWSTR* Id)
|
||||||
|
{
|
||||||
|
if (!Id)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::QueryId FAILED Id");
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
*Id = static_cast<LPWSTR>(CoTaskMemAlloc(sizeof(PIN_NAME)));
|
||||||
|
std::copy(std::begin(PIN_NAME), std::end(PIN_NAME), *Id);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::QueryAccept(const AM_MEDIA_TYPE*)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::EnumMediaTypes(IEnumMediaTypes** ppEnum)
|
||||||
|
{
|
||||||
|
if (!ppEnum)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::EnumMediaTypes FAILED ppEnum");
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto enumerator = winrt::make_self<MediaTypeEnumerator>();
|
||||||
|
enumerator->_objects.emplace_back(CopyMediaType(_mediaFormat));
|
||||||
|
*ppEnum = enumerator.detach();
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::QueryInternalConnections(IPin**, ULONG*)
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::EndOfStream(void)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::BeginFlush(void)
|
||||||
|
{
|
||||||
|
_flushing = true;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::EndFlush(void)
|
||||||
|
{
|
||||||
|
_flushing = false;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::NewSegment(REFERENCE_TIME, REFERENCE_TIME, double)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::SetFormat(AM_MEDIA_TYPE* pmt)
|
||||||
|
{
|
||||||
|
if (pmt == nullptr)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
_mediaFormat = CopyMediaType(pmt);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::GetFormat(AM_MEDIA_TYPE** ppmt)
|
||||||
|
{
|
||||||
|
if (!ppmt)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::GetFormat FAILED ppmt");
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ppmt = CopyMediaType(_mediaFormat).release();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::GetNumberOfCapabilities(int* piCount, int* piSize)
|
||||||
|
{
|
||||||
|
if (!piCount || !piSize)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::GetNumberOfCapabilities FAILED piCount || piSize");
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
*piCount = 1;
|
||||||
|
*piSize = sizeof(VIDEO_STREAM_CONFIG_CAPS);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::GetStreamCaps(int iIndex, AM_MEDIA_TYPE** ppmt, BYTE* pSCC)
|
||||||
|
{
|
||||||
|
if (!ppmt || !pSCC)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::GetStreamCaps FAILED ppmt || pSCC");
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iIndex != 0)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::GetStreamCaps FAILED iIndex");
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VIDEOINFOHEADER* vih = reinterpret_cast<decltype(vih)>(_mediaFormat->pbFormat);
|
||||||
|
|
||||||
|
VIDEO_STREAM_CONFIG_CAPS caps{};
|
||||||
|
caps.guid = FORMAT_VideoInfo;
|
||||||
|
caps.MinFrameInterval = vih->AvgTimePerFrame;
|
||||||
|
caps.MaxFrameInterval = vih->AvgTimePerFrame;
|
||||||
|
caps.MinOutputSize.cx = vih->bmiHeader.biWidth;
|
||||||
|
caps.MinOutputSize.cy = vih->bmiHeader.biHeight;
|
||||||
|
caps.MaxOutputSize = caps.MinOutputSize;
|
||||||
|
caps.InputSize = caps.MinOutputSize;
|
||||||
|
caps.MinCroppingSize = caps.MinOutputSize;
|
||||||
|
caps.MaxCroppingSize = caps.MinOutputSize;
|
||||||
|
caps.CropGranularityX = vih->bmiHeader.biWidth;
|
||||||
|
caps.CropGranularityY = vih->bmiHeader.biHeight;
|
||||||
|
caps.MinBitsPerSecond = vih->dwBitRate;
|
||||||
|
caps.MaxBitsPerSecond = caps.MinBitsPerSecond;
|
||||||
|
|
||||||
|
*ppmt = CopyMediaType(_mediaFormat).release();
|
||||||
|
|
||||||
|
const auto caps_begin = reinterpret_cast<const char*>(&caps);
|
||||||
|
std::copy(caps_begin, caps_begin + sizeof(caps), pSCC);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::Set(REFGUID, DWORD, LPVOID, DWORD, LPVOID, DWORD)
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::Get(
|
||||||
|
REFGUID guidPropSet,
|
||||||
|
DWORD dwPropID,
|
||||||
|
LPVOID,
|
||||||
|
DWORD,
|
||||||
|
LPVOID pPropData,
|
||||||
|
DWORD cbPropData,
|
||||||
|
DWORD* pcbReturned)
|
||||||
|
{
|
||||||
|
if (guidPropSet != AMPROPSETID_Pin)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::Get FAILED guidPropSet");
|
||||||
|
return E_PROP_SET_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dwPropID != AMPROPERTY_PIN_CATEGORY)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::Get FAILED dwPropID");
|
||||||
|
return E_PROP_ID_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pPropData)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::Get FAILED pPropData || pcbReturned");
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pcbReturned)
|
||||||
|
{
|
||||||
|
*pcbReturned = sizeof(GUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cbPropData < sizeof(GUID))
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::Get FAILED cbPropData");
|
||||||
|
return E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(GUID*)pPropData = PIN_CATEGORY_CAPTURE;
|
||||||
|
|
||||||
|
LOG("VideoCaptureProxyPin::Get SUCCESS");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyPin::QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD* pTypeSupport)
|
||||||
|
{
|
||||||
|
if (guidPropSet != AMPROPSETID_Pin)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::QuerySupported FAILED guidPropSet");
|
||||||
|
return E_PROP_SET_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dwPropID != AMPROPERTY_PIN_CATEGORY)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::QuerySupported FAILED dwPropID");
|
||||||
|
return E_PROP_ID_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pTypeSupport)
|
||||||
|
{
|
||||||
|
*pTypeSupport = KSPROPERTY_SUPPORT_GET;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
long GetImageSize(wil::com_ptr_nothrow<IMFSample>& image)
|
||||||
|
{
|
||||||
|
if (!image)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD imageSize = 0;
|
||||||
|
wil::com_ptr_nothrow<IMFMediaBuffer> imageBuf;
|
||||||
|
|
||||||
|
OK_OR_BAIL(image->GetBufferByIndex(0, &imageBuf));
|
||||||
|
OK_OR_BAIL(imageBuf->GetCurrentLength(&imageSize));
|
||||||
|
return imageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReencodeFrame(IMediaSample* frame)
|
||||||
|
{
|
||||||
|
BYTE* frameData = nullptr;
|
||||||
|
frame->GetPointer(&frameData);
|
||||||
|
if (!frameData)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::ReencodeFrame FAILED frameData");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const DWORD frameSize = frame->GetSize();
|
||||||
|
DWORD reencodedSize = 0;
|
||||||
|
if (!ReencodeJPGImage(frameData, frameSize, reencodedSize))
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::ReencodeJPGImage FAILED");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
frame->SetActualDataLength(reencodedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OverwriteFrame(IMediaSample* frame, wil::com_ptr_nothrow<IMFSample>& image)
|
||||||
|
{
|
||||||
|
if (!image)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE* frameData = nullptr;
|
||||||
|
frame->GetPointer(&frameData);
|
||||||
|
if (!frameData)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::OverwriteFrame FAILED frameData");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IMFMediaBuffer> imageBuf;
|
||||||
|
const DWORD frameSize = frame->GetSize();
|
||||||
|
|
||||||
|
image->GetBufferByIndex(0, &imageBuf);
|
||||||
|
if (!imageBuf)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::OverwriteFrame FAILED imageBuf");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE* imageData = nullptr;
|
||||||
|
DWORD _ = 0, imageSize = 0;
|
||||||
|
imageBuf->Lock(&imageData, &_, &imageSize);
|
||||||
|
if (!imageData)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::OverwriteFrame FAILED imageData");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageSize > frameSize && failed(frame->SetActualDataLength(imageSize)))
|
||||||
|
{
|
||||||
|
char buf[512]{};
|
||||||
|
sprintf_s(buf, "VideoCaptureProxyPin::OverwriteFrame FAILED overlay image size %lu is larger than frame size %lu", imageSize, frameSize);
|
||||||
|
LOG(buf);
|
||||||
|
imageBuf->Unlock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::copy(imageData, imageData + imageSize, frameData);
|
||||||
|
imageBuf->Unlock();
|
||||||
|
frame->SetActualDataLength(imageSize);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//#define DEBUG_FRAME_DATA
|
||||||
|
//#define DEBUG_OVERWRITE_FRAME
|
||||||
|
//#define DEBUG_REENCODE_JPG_DATA
|
||||||
|
|
||||||
|
#if defined(DEBUG_OVERWRITE_FRAME)
|
||||||
|
void DebugOverwriteFrame(IMediaSample* frame, std::string_view filepath)
|
||||||
|
{
|
||||||
|
std::ifstream file{ filepath.data(), std::ios::binary };
|
||||||
|
std::streampos fileSize = 0;
|
||||||
|
fileSize = file.tellg();
|
||||||
|
file.seekg(0, std::ios::end);
|
||||||
|
fileSize = file.tellg() - fileSize;
|
||||||
|
|
||||||
|
BYTE* frameData = nullptr;
|
||||||
|
if (!frame)
|
||||||
|
{
|
||||||
|
LOG("null frame provided");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
frame->GetPointer(&frameData);
|
||||||
|
const DWORD frameSize = frame->GetSize();
|
||||||
|
|
||||||
|
if (fileSize > frameSize || !frameData)
|
||||||
|
{
|
||||||
|
LOG("frame can't be filled with data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
file.read((char*)frameData, fileSize);
|
||||||
|
frame->SetActualDataLength((long)fileSize);
|
||||||
|
LOG("DebugOverwriteFrame success");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(DEBUG_FRAME_DATA)
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
void DumpSample(IMediaSample* frame, const std::string_view filename)
|
||||||
|
{
|
||||||
|
BYTE* data = nullptr;
|
||||||
|
frame->GetPointer(&data);
|
||||||
|
if (!data)
|
||||||
|
{
|
||||||
|
LOG("Couldn't get sample pointer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const long nBytes = frame->GetActualDataLength();
|
||||||
|
std::ofstream file{ fs::temp_directory_path() / filename, std::ios::binary };
|
||||||
|
file.write((const char*)data, nBytes);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
VideoCaptureProxyFilter::VideoCaptureProxyFilter() :
|
||||||
|
_worker_thread{
|
||||||
|
std::thread{
|
||||||
|
[this]() {
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
const auto uninitializedSleepInterval = 15ms;
|
||||||
|
std::vector<float> lowerJpgQualityModes = { 0.1f, 0.25f };
|
||||||
|
while (!_shutdown_request)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock{ _worker_mutex };
|
||||||
|
_worker_cv.wait(lock, [this] { return _pending_frame != nullptr || _shutdown_request; });
|
||||||
|
|
||||||
|
if (!_outPin || !_outPin->_connectedInputPin)
|
||||||
|
{
|
||||||
|
lock.unlock();
|
||||||
|
std::this_thread::sleep_for(uninitializedSleepInterval);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto input = _outPin->_connectedInputPin.try_query<IMemInputPin>();
|
||||||
|
if (!input)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMediaSample* sample = _pending_frame;
|
||||||
|
if (!sample)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#if defined(DEBUG_FRAME_DATA)
|
||||||
|
static bool realFrameSaved = false;
|
||||||
|
if (!realFrameSaved)
|
||||||
|
{
|
||||||
|
DumpSample(sample, "PowerToysVCMRealFrame.binary");
|
||||||
|
realFrameSaved = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
auto newSettings = SyncCurrentSettings();
|
||||||
|
if (newSettings.webcamDisabled)
|
||||||
|
{
|
||||||
|
#if !defined(DEBUG_OVERWRITE_FRAME)
|
||||||
|
bool overwritten = OverwriteFrame(_pending_frame, _overlayImage ? _overlayImage : _blankImage);
|
||||||
|
while (!overwritten && _overlayImage)
|
||||||
|
{
|
||||||
|
_overlayImage.reset();
|
||||||
|
newSettings = SyncCurrentSettings();
|
||||||
|
if (!lowerJpgQualityModes.empty() && newSettings.overlayImage)
|
||||||
|
{
|
||||||
|
const float quality = lowerJpgQualityModes.back();
|
||||||
|
lowerJpgQualityModes.pop_back();
|
||||||
|
char buf[512]{};
|
||||||
|
sprintf_s(buf, "Reload overlay image with quality %f", quality);
|
||||||
|
LOG(buf);
|
||||||
|
_overlayImage = LoadImageAsSample(newSettings.overlayImage, _targetMediaType.get(), quality);
|
||||||
|
overwritten = OverwriteFrame(_pending_frame, _overlayImage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG("Couldn't overwrite frame with image with all available quality modes.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined(DEBUG_FRAME_DATA)
|
||||||
|
static bool overlayFrameSaved = false;
|
||||||
|
if (!overlayFrameSaved && _overlayImage && overwritten)
|
||||||
|
{
|
||||||
|
DumpSample(sample, "PowerToysVCMOverlayImageFrame.binary");
|
||||||
|
overlayFrameSaved = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!overwritten && !_overlayImage)
|
||||||
|
{
|
||||||
|
OverwriteFrame(_pending_frame, _blankImage);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
DebugOverwriteFrame(_pending_frame, "R:\\frame.data");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if defined(DEBUG_REENCODE_JPG_DATA)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUID subtype{};
|
||||||
|
_targetMediaType->GetGUID(MF_MT_SUBTYPE, &subtype);
|
||||||
|
if (subtype == MFVideoFormat_MJPG)
|
||||||
|
{
|
||||||
|
ReencodeFrame(_pending_frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_pending_frame = nullptr;
|
||||||
|
input->Receive(sample);
|
||||||
|
sample->Release();
|
||||||
|
}
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyFilter::Stop(void)
|
||||||
|
{
|
||||||
|
if (_state != State_Stopped && _captureDevice)
|
||||||
|
{
|
||||||
|
_captureDevice->StopCapture();
|
||||||
|
}
|
||||||
|
|
||||||
|
_state = State_Stopped;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyFilter::Pause(void)
|
||||||
|
{
|
||||||
|
if (_state == State_Stopped)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock{ _worker_mutex };
|
||||||
|
|
||||||
|
if (!_outPin)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::Pause FAILED _outPin");
|
||||||
|
return VFW_E_NO_TRANSPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto allocator = _outPin->FindAllocator();
|
||||||
|
if (!allocator)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::Pause FAILED allocator");
|
||||||
|
return VFW_E_NO_TRANSPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
allocator->Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
_state = State_Paused;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyFilter::Run(REFERENCE_TIME)
|
||||||
|
{
|
||||||
|
_state = State_Running;
|
||||||
|
if (_captureDevice)
|
||||||
|
{
|
||||||
|
_captureDevice->StartCapture();
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyFilter::GetState(DWORD, FILTER_STATE* State)
|
||||||
|
{
|
||||||
|
*State = _state;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyFilter::SetSyncSource(IReferenceClock* pClock)
|
||||||
|
{
|
||||||
|
_clock = pClock;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyFilter::GetSyncSource(IReferenceClock** pClock)
|
||||||
|
{
|
||||||
|
if (!pClock)
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
_clock.try_copy_to(pClock);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUID MapDShowSubtypeToMFT(const GUID& dshowSubtype)
|
||||||
|
{
|
||||||
|
if (dshowSubtype == MEDIASUBTYPE_YUY2)
|
||||||
|
{
|
||||||
|
return MFVideoFormat_YUY2;
|
||||||
|
}
|
||||||
|
else if (dshowSubtype == MEDIASUBTYPE_MJPG)
|
||||||
|
{
|
||||||
|
return MFVideoFormat_MJPG;
|
||||||
|
}
|
||||||
|
else if (dshowSubtype == MEDIASUBTYPE_RGB24)
|
||||||
|
{
|
||||||
|
return MFVideoFormat_RGB24;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG("MapDShowSubtypeToMFT: Unsupported media type format provided!");
|
||||||
|
return MFVideoFormat_MJPG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyFilter::EnumPins(IEnumPins** ppEnum)
|
||||||
|
{
|
||||||
|
if (!ppEnum)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyFilter::EnumPins null arg provided");
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> lock{ _worker_mutex };
|
||||||
|
|
||||||
|
// We cannot initialize capture device and outpin during VideoCaptureProxyFilter ctor
|
||||||
|
// since that results in a deadlock -> initializing now.
|
||||||
|
if (!_outPin)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyFilter::EnumPins started pin initialization");
|
||||||
|
const auto newSettings = SyncCurrentSettings();
|
||||||
|
std::vector<VideoCaptureDeviceInfo> webcams;
|
||||||
|
webcams = VideoCaptureDevice::ListAll();
|
||||||
|
if (webcams.empty())
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyFilter::EnumPins no physical webcams found");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<size_t> selectedCamIdx;
|
||||||
|
for (size_t i = 0; i < size(webcams); ++i)
|
||||||
|
{
|
||||||
|
if (newSettings.newCameraName == webcams[i].friendlyName)
|
||||||
|
{
|
||||||
|
selectedCamIdx = i;
|
||||||
|
LOG("VideoCaptureProxyFilter::EnumPins webcam selected using settings");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!selectedCamIdx)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < size(webcams); ++i)
|
||||||
|
{
|
||||||
|
if (newSettings.newCameraName != CAMERA_NAME)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyFilter::EnumPins webcam selected using first fit");
|
||||||
|
selectedCamIdx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!selectedCamIdx)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyFilter::EnumPins FAILED webcam couldn't be selected");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& webcam = webcams[*selectedCamIdx];
|
||||||
|
auto pin = winrt::make_self<VideoCaptureProxyPin>();
|
||||||
|
pin->_mediaFormat = CopyMediaType(webcam.bestFormat.mediaType);
|
||||||
|
pin->_owningFilter = this;
|
||||||
|
_outPin.attach(pin.detach());
|
||||||
|
|
||||||
|
auto frameCallback = [this](IMediaSample* sample) {
|
||||||
|
std::unique_lock<std::mutex> lock{ _worker_mutex };
|
||||||
|
sample->AddRef();
|
||||||
|
_pending_frame = sample;
|
||||||
|
_worker_cv.notify_one();
|
||||||
|
};
|
||||||
|
|
||||||
|
_targetMediaType.reset();
|
||||||
|
MFCreateMediaType(&_targetMediaType);
|
||||||
|
_targetMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
|
||||||
|
_targetMediaType->SetGUID(MF_MT_SUBTYPE, MapDShowSubtypeToMFT(webcam.bestFormat.mediaType->subtype));
|
||||||
|
_targetMediaType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
|
||||||
|
_targetMediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
|
||||||
|
MFSetAttributeSize(
|
||||||
|
_targetMediaType.get(), MF_MT_FRAME_SIZE, webcam.bestFormat.width, webcam.bestFormat.height);
|
||||||
|
MFSetAttributeRatio(_targetMediaType.get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
|
||||||
|
|
||||||
|
_captureDevice = VideoCaptureDevice::Create(std::move(webcam), std::move(frameCallback));
|
||||||
|
if (_captureDevice)
|
||||||
|
{
|
||||||
|
if (!_blankImage)
|
||||||
|
{
|
||||||
|
wil::com_ptr_nothrow<IStream> blackBMPImage = SHCreateMemStream(bmpPixelData, sizeof(bmpPixelData));
|
||||||
|
_blankImage = LoadImageAsSample(blackBMPImage, _targetMediaType.get(), initialJpgQuality);
|
||||||
|
}
|
||||||
|
|
||||||
|
_overlayImage = LoadImageAsSample(newSettings.overlayImage, _targetMediaType.get(), initialJpgQuality);
|
||||||
|
LOG("VideoCaptureProxyFilter::EnumPins capture device created successfully");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyFilter::EnumPins FAILED couldn't create capture device");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto enumerator = winrt::make_self<ObjectEnumerator<IPin, IEnumPins>>();
|
||||||
|
enumerator->_objects.emplace_back(_outPin);
|
||||||
|
*ppEnum = enumerator.detach();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyFilter::FindPin(LPCWSTR, IPin**)
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyFilter::QueryFilterInfo(FILTER_INFO* pInfo)
|
||||||
|
{
|
||||||
|
if (!pInfo)
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureProxyPin::QueryFilterInfo FAILED pInfo");
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
VERBOSE_LOG;
|
||||||
|
std::copy(std::begin(FILTER_NAME), std::end(FILTER_NAME), pInfo->achName);
|
||||||
|
|
||||||
|
pInfo->pGraph = _graph;
|
||||||
|
if (_graph)
|
||||||
|
{
|
||||||
|
_graph->AddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyFilter::JoinFilterGraph(IFilterGraph* pGraph, LPCWSTR)
|
||||||
|
{
|
||||||
|
_graph = pGraph;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyFilter::QueryVendorInfo(LPWSTR* pVendorInfo)
|
||||||
|
{
|
||||||
|
auto info = static_cast<LPWSTR>(CoTaskMemAlloc(sizeof(VENDOR)));
|
||||||
|
std::copy(std::begin(VENDOR), std::end(VENDOR), info);
|
||||||
|
*pVendorInfo = info;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureProxyFilter::GetClassID(CLSID*)
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG VideoCaptureProxyFilter::GetMiscFlags(void)
|
||||||
|
{
|
||||||
|
return AM_FILTER_MISC_FLAGS_IS_SOURCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoCaptureProxyFilter::~VideoCaptureProxyFilter()
|
||||||
|
{
|
||||||
|
VERBOSE_LOG;
|
||||||
|
_shutdown_request = true;
|
||||||
|
|
||||||
|
_worker_cv.notify_one();
|
||||||
|
_worker_thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoCaptureProxyFilter::SyncedSettings VideoCaptureProxyFilter::SyncCurrentSettings()
|
||||||
|
{
|
||||||
|
SyncedSettings result;
|
||||||
|
if (!_settingsUpdateChannel.has_value())
|
||||||
|
{
|
||||||
|
_settingsUpdateChannel = SerializedSharedMemory::open(CameraSettingsUpdateChannel::endpoint(), sizeof(CameraSettingsUpdateChannel), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_settingsUpdateChannel)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
_settingsUpdateChannel->access([this, &result](auto settingsMemory) {
|
||||||
|
auto settings = reinterpret_cast<CameraSettingsUpdateChannel*>(settingsMemory._data);
|
||||||
|
bool cameraNameUpdated = false;
|
||||||
|
result.webcamDisabled = settings->useOverlayImage;
|
||||||
|
|
||||||
|
settings->cameraInUse = true;
|
||||||
|
|
||||||
|
if (settings->sourceCameraName.has_value())
|
||||||
|
{
|
||||||
|
std::wstring_view newCameraNameView{ settings->sourceCameraName->data() };
|
||||||
|
if (!_currentSourceCameraName.has_value() || *_currentSourceCameraName != newCameraNameView)
|
||||||
|
{
|
||||||
|
cameraNameUpdated = true;
|
||||||
|
result.newCameraName = newCameraNameView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!settings->overlayImageSize.has_value())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings->newOverlayImagePosted || !_overlayImage)
|
||||||
|
{
|
||||||
|
auto imageChannel =
|
||||||
|
SerializedSharedMemory::open(CameraOverlayImageChannel::endpoint(), *settings->overlayImageSize, true);
|
||||||
|
if (!imageChannel)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
imageChannel->access([this, settings, &result](auto imageMemory) {
|
||||||
|
result.overlayImage = SHCreateMemStream(imageMemory._data, static_cast<UINT>(imageMemory._size));
|
||||||
|
if (!result.overlayImage)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
settings->newOverlayImagePosted = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <initguid.h>
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <dshow.h>
|
||||||
|
|
||||||
|
#include <winrt/base.h>
|
||||||
|
#include <wil/resource.h>
|
||||||
|
#include <wil/com.h>
|
||||||
|
|
||||||
|
#include <CameraStateUpdateChannels.h>
|
||||||
|
#include <SerializedSharedMemory.h>
|
||||||
|
|
||||||
|
#include "VideoCaptureDevice.h"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
|
struct VideoCaptureProxyPin;
|
||||||
|
struct IMFSample;
|
||||||
|
struct IMFMediaType;
|
||||||
|
|
||||||
|
inline const wchar_t CAMERA_NAME[] = L"PowerToys VideoConference Mute";
|
||||||
|
|
||||||
|
struct VideoCaptureProxyFilter : winrt::implements<VideoCaptureProxyFilter, IBaseFilter, IAMFilterMiscFlags>
|
||||||
|
{
|
||||||
|
// BLOCK START: member accessed concurrently
|
||||||
|
wil::com_ptr_nothrow<VideoCaptureProxyPin> _outPin;
|
||||||
|
IMediaSample* _pending_frame = nullptr;
|
||||||
|
std::atomic_bool _shutdown_request = false;
|
||||||
|
std::optional<SerializedSharedMemory> _settingsUpdateChannel;
|
||||||
|
std::optional<std::wstring> _currentSourceCameraName;
|
||||||
|
wil::com_ptr_nothrow<IMFSample> _blankImage;
|
||||||
|
wil::com_ptr_nothrow<IMFSample> _overlayImage;
|
||||||
|
wil::com_ptr_nothrow<IMFMediaType> _targetMediaType;
|
||||||
|
// BLOCK END: member accessed concurrently
|
||||||
|
|
||||||
|
std::mutex _worker_mutex;
|
||||||
|
std::condition_variable _worker_cv;
|
||||||
|
|
||||||
|
FILTER_STATE _state = State_Stopped;
|
||||||
|
wil::com_ptr_nothrow<IReferenceClock> _clock;
|
||||||
|
IFilterGraph* _graph = nullptr;
|
||||||
|
std::optional<VideoCaptureDevice> _captureDevice;
|
||||||
|
|
||||||
|
std::thread _worker_thread;
|
||||||
|
|
||||||
|
VideoCaptureProxyFilter();
|
||||||
|
~VideoCaptureProxyFilter();
|
||||||
|
|
||||||
|
struct SyncedSettings
|
||||||
|
{
|
||||||
|
bool webcamDisabled = false;
|
||||||
|
std::wstring newCameraName;
|
||||||
|
wil::com_ptr_nothrow<IStream> overlayImage;
|
||||||
|
};
|
||||||
|
|
||||||
|
SyncedSettings SyncCurrentSettings();
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE Stop(void) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE Pause(void) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE* State) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock* pClock) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock** pClock) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins** ppEnum) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin** ppPin) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO* pInfo) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph* pGraph, LPCWSTR pName) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR* pVendorInfo) override;
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE GetClassID(CLSID* pClassID) override;
|
||||||
|
ULONG STDMETHODCALLTYPE GetMiscFlags(void) override;
|
||||||
|
};
|
||||||
|
struct VideoCaptureProxyPin : winrt::implements<VideoCaptureProxyPin, IPin, IAMStreamConfig, IKsPropertySet>
|
||||||
|
{
|
||||||
|
VideoCaptureProxyFilter* _owningFilter = nullptr;
|
||||||
|
wil::com_ptr_nothrow<IPin> _connectedInputPin;
|
||||||
|
unique_media_type_ptr _mediaFormat;
|
||||||
|
std::atomic_bool _flushing = false;
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE Connect(IPin* pReceivePin, const AM_MEDIA_TYPE* pmt) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin* pConnector, const AM_MEDIA_TYPE* pmt) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE Disconnect(void) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE ConnectedTo(IPin** pPin) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE* pmt) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO* pInfo) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION* pPinDir) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryId(LPWSTR* Id) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE* pmt) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes** ppEnum) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin** apPin, ULONG* nPin) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE EndOfStream(void) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE BeginFlush(void) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE EndFlush(void) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) override;
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE SetFormat(AM_MEDIA_TYPE* pmt) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE GetFormat(AM_MEDIA_TYPE** ppmt) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities(int* piCount, int* piSize) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE GetStreamCaps(int iIndex, AM_MEDIA_TYPE** ppmt, BYTE* pSCC) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet,
|
||||||
|
DWORD dwPropID,
|
||||||
|
LPVOID pInstanceData,
|
||||||
|
DWORD cbInstanceData,
|
||||||
|
LPVOID pPropData,
|
||||||
|
DWORD cbPropData) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet,
|
||||||
|
DWORD dwPropID,
|
||||||
|
LPVOID pInstanceData,
|
||||||
|
DWORD cbInstanceData,
|
||||||
|
LPVOID pPropData,
|
||||||
|
DWORD cbPropData,
|
||||||
|
DWORD* pcbReturned) override;
|
||||||
|
HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD* pTypeSupport) override;
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IMemAllocator> FindAllocator();
|
||||||
|
};
|
@ -0,0 +1,124 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{AC2857B4-103D-4D6D-9740-926EBF785042}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>VideoConferenceProxyFilter</RootNamespace>
|
||||||
|
<ProjectName>VideoConferenceProxyFilter</ProjectName>
|
||||||
|
<OverrideWindowsTargetPlatformVersion>true</OverrideWindowsTargetPlatformVersion>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)\src\;$(ProjectDir)..\..\..\</AdditionalIncludeDirectories>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||||
|
<ClCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
<Lib>
|
||||||
|
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
|
||||||
|
</Lib>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||||
|
<ClCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)\src\;</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
</Link>
|
||||||
|
<Lib>
|
||||||
|
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
|
||||||
|
</Lib>
|
||||||
|
<PreBuildEvent Condition="'$(Platform)'=='x64'">
|
||||||
|
<Command>call "$(ProjectDir)build_vcm_x86.cmd"</Command>
|
||||||
|
</PreBuildEvent>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<PropertyGroup Condition="'$(Platform)'!='Win32'">
|
||||||
|
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\VideoConference\</OutDir>
|
||||||
|
<TargetName>VideoConferenceProxyFilter_x64</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Platform)'=='Win32'">
|
||||||
|
<OutDir>..\..\..\..\x86\$(Configuration)\modules\VideoConference\</OutDir>
|
||||||
|
<TargetName>VideoConferenceProxyFilter_x86</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalIncludeDirectories>..\VideoConferenceShared\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>_LIB;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MultiThreaded</RuntimeLibrary>
|
||||||
|
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>$(OutDir)VideoConferenceShared.lib;mfplat.lib;Mfsensorgroup.lib;OneCoreUAP.lib;Mf.lib;Shlwapi.lib;Strmiids.lib;%(AdditionalDependencies);</AdditionalDependencies>
|
||||||
|
<ModuleDefinitionFile>module.def</ModuleDefinitionFile>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="DirectShowUtils.h" />
|
||||||
|
<ClInclude Include="VideoCaptureDevice.h" />
|
||||||
|
<ClInclude Include="VideoCaptureProxyFilter.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="DirectShowUtils.cpp" />
|
||||||
|
<ClCompile Include="VideoCaptureDevice.cpp" />
|
||||||
|
<ClCompile Include="VideoCaptureProxyFilter.cpp" />
|
||||||
|
<ClCompile Include="dllmain.cpp" />
|
||||||
|
<ClCompile Include="ImageLoading.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="module.def" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\VideoConferenceShared\VideoConferenceShared.vcxproj">
|
||||||
|
<Project>{459e0768-7ebd-4c41-bba1-6db3b3815e0a}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200519.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200519.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||||
|
</ImportGroup>
|
||||||
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200519.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200519.2\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.30907.101
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoConferenceProxyFilter", "VideoConferenceProxyFilter.vcxproj", "{AC2857B4-103D-4D6D-9740-926EBF785042}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoConferenceShared", "..\VideoConferenceShared\VideoConferenceShared.vcxproj", "{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x64.Build.0 = Release|x64
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|x64.Build.0 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {0E41348C-22CB-45A4-8A16-8D7BEA070BB2}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
@ -0,0 +1,3 @@
|
|||||||
|
msbuild VideoConferenceProxyFilterx86.sln -p:Configuration="Release" -p:Platform="Win32"
|
||||||
|
|
||||||
|
exit 0
|
@ -0,0 +1,242 @@
|
|||||||
|
#include "VideoCaptureProxyFilter.h"
|
||||||
|
|
||||||
|
#include <winrt/base.h>
|
||||||
|
|
||||||
|
#include <wil/registry.h>
|
||||||
|
#include <cguid.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
#if defined(_WIN64)
|
||||||
|
class __declspec(uuid("{31AD75E9-8C3A-49C8-B9ED-5880D6B4A764}")) GUID_DECL_POWERTOYS_VCM;
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
class __declspec(uuid("{31AD75E9-8C3A-49C8-B9ED-5880D6B4A732}")) GUID_DECL_POWERTOYS_VCM;
|
||||||
|
#endif
|
||||||
|
const GUID CLSID_POWERTOYS_VCM = __uuidof(GUID_DECL_POWERTOYS_VCM);
|
||||||
|
|
||||||
|
const REGPINTYPES MEDIA_TYPES = { &MEDIATYPE_Video, &MEDIASUBTYPE_MJPG };
|
||||||
|
|
||||||
|
const wchar_t FILTER_NAME[] = L"Output";
|
||||||
|
const REGFILTERPINS PINS_REGISTRATION = {
|
||||||
|
(wchar_t*)FILTER_NAME,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
&CLSID_NULL,
|
||||||
|
nullptr,
|
||||||
|
1,
|
||||||
|
&MEDIA_TYPES
|
||||||
|
};
|
||||||
|
|
||||||
|
HINSTANCE DLLInstance{};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct __declspec(uuid("9DCAF869-9C13-4BDF-BD0D-3592C5579DD6")) VideoCaptureProxyFilterFactory : winrt::implements<VideoCaptureProxyFilterFactory, IClassFactory>
|
||||||
|
{
|
||||||
|
HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown*, REFIID riid, void** ppvObject) noexcept override
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return winrt::make<VideoCaptureProxyFilter>()->QueryInterface(riid, ppvObject);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return winrt::to_hresult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock) noexcept override
|
||||||
|
{
|
||||||
|
if (fLock)
|
||||||
|
{
|
||||||
|
++winrt::get_module_lock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
--winrt::get_module_lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE DllCanUnloadNow()
|
||||||
|
{
|
||||||
|
if (winrt::get_module_lock())
|
||||||
|
{
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt::clear_factory_cache();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE DllGetClassObject(GUID const& clsid, GUID const& iid, void** result)
|
||||||
|
{
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iid != IID_IClassFactory && iid != IID_IUnknown)
|
||||||
|
{
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clsid != CLSID_POWERTOYS_VCM)
|
||||||
|
{
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
*result = nullptr;
|
||||||
|
|
||||||
|
auto factory = winrt::make<VideoCaptureProxyFilterFactory>();
|
||||||
|
factory->AddRef();
|
||||||
|
*result = static_cast<void*>(factory.get());
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return winrt::to_hresult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring RegistryPath()
|
||||||
|
{
|
||||||
|
std::wstring registryPath;
|
||||||
|
registryPath.resize(CHARS_IN_GUID, L'\0');
|
||||||
|
|
||||||
|
StringFromGUID2(CLSID_POWERTOYS_VCM, registryPath.data(), CHARS_IN_GUID);
|
||||||
|
registryPath.resize(registryPath.size() - 1);
|
||||||
|
registryPath = L"CLSID\\" + registryPath;
|
||||||
|
return registryPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RegisterServer()
|
||||||
|
{
|
||||||
|
std::wstring dllPath;
|
||||||
|
dllPath.resize(MAX_PATH, L'\0');
|
||||||
|
if (auto length = GetModuleFileNameW(DLLInstance, dllPath.data(), MAX_PATH); length != 0)
|
||||||
|
{
|
||||||
|
dllPath.resize(length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::unique_hkey key;
|
||||||
|
wil::unique_hkey subkey;
|
||||||
|
const auto registryPath = RegistryPath();
|
||||||
|
if (RegCreateKeyW(HKEY_CLASSES_ROOT, registryPath.c_str(), &key))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RegSetValueW(key.get(), nullptr, REG_SZ, CAMERA_NAME, sizeof(CAMERA_NAME)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RegCreateKeyW(key.get(), L"InprocServer32", &subkey))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RegSetValueW(subkey.get(), nullptr, REG_SZ, dllPath.c_str(), static_cast<DWORD>((dllPath.length() + 1) * sizeof(wchar_t))))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const wchar_t THREADING_MODEL[] = L"Both";
|
||||||
|
RegSetValueExW(subkey.get(), L"ThreadingModel", 0, REG_SZ, (const BYTE*)THREADING_MODEL, sizeof(THREADING_MODEL));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnregisterServer()
|
||||||
|
{
|
||||||
|
const auto registryPath = RegistryPath();
|
||||||
|
return !RegDeleteTreeW(HKEY_CLASSES_ROOT, registryPath.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RegisterFilter()
|
||||||
|
{
|
||||||
|
auto filterMapper = wil::CoCreateInstanceNoThrow<IFilterMapper2>(CLSID_FilterMapper2);
|
||||||
|
if (!filterMapper)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
REGFILTER2 regFilter{ .dwVersion = 1, .dwMerit = MERIT_DO_NOT_USE, .cPins = 1, .rgPins = &PINS_REGISTRATION };
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IMoniker> moniker;
|
||||||
|
|
||||||
|
return SUCCEEDED(filterMapper->RegisterFilter(
|
||||||
|
CLSID_POWERTOYS_VCM, CAMERA_NAME, &moniker, &CLSID_VideoInputDeviceCategory, nullptr, ®Filter));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnregisterFilter()
|
||||||
|
{
|
||||||
|
auto filterMapper = wil::CoCreateInstanceNoThrow<IFilterMapper2>(CLSID_FilterMapper2);
|
||||||
|
if (!filterMapper)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SUCCEEDED(filterMapper->UnregisterFilter(&CLSID_VideoInputDeviceCategory, nullptr, CLSID_POWERTOYS_VCM));
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE DllRegisterServer()
|
||||||
|
{
|
||||||
|
if (!RegisterServer())
|
||||||
|
{
|
||||||
|
UnregisterServer();
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto COMContext = wil::CoInitializeEx(COINIT_APARTMENTTHREADED);
|
||||||
|
|
||||||
|
if (!RegisterFilter())
|
||||||
|
{
|
||||||
|
UnregisterFilter();
|
||||||
|
UnregisterServer();
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE DllUnregisterServer()
|
||||||
|
{
|
||||||
|
auto COMContext = wil::CoInitializeEx(COINIT_APARTMENTTHREADED);
|
||||||
|
|
||||||
|
UnregisterFilter();
|
||||||
|
UnregisterServer();
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE DllInstall(BOOL install, LPCWSTR)
|
||||||
|
{
|
||||||
|
if (install)
|
||||||
|
{
|
||||||
|
return DllRegisterServer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return DllUnregisterServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID)
|
||||||
|
{
|
||||||
|
if (fdwReason == DLL_PROCESS_ATTACH)
|
||||||
|
{
|
||||||
|
DLLInstance = hinstDLL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
EXPORTS
|
||||||
|
DllMain PRIVATE
|
||||||
|
DllGetClassObject PRIVATE
|
||||||
|
DllCanUnloadNow PRIVATE
|
||||||
|
DllRegisterServer PRIVATE
|
||||||
|
DllUnregisterServer PRIVATE
|
||||||
|
DllInstall PRIVATE
|
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.200519.2" targetFramework="native" />
|
||||||
|
</packages>
|
@ -0,0 +1,15 @@
|
|||||||
|
#include "CameraStateUpdateChannels.h"
|
||||||
|
|
||||||
|
#include "naming.h"
|
||||||
|
|
||||||
|
std::wstring_view CameraOverlayImageChannel::endpoint()
|
||||||
|
{
|
||||||
|
static const std::wstring endpoint = ObtainStableGlobalNameForKernelObject(L"PowerToysVideoConferenceCameraOverlayImageChannelSharedMemory", true);
|
||||||
|
return endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring_view CameraSettingsUpdateChannel::endpoint()
|
||||||
|
{
|
||||||
|
static const std::wstring endpoint = ObtainStableGlobalNameForKernelObject(L"PowerToysVideoConferenceSettingsChannelSharedMemory", true);
|
||||||
|
return endpoint;
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <string_view>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
struct alignas(16) CameraSettingsUpdateChannel
|
||||||
|
{
|
||||||
|
bool useOverlayImage = false;
|
||||||
|
bool cameraInUse = false;
|
||||||
|
|
||||||
|
std::optional<uint32_t> overlayImageSize;
|
||||||
|
std::optional<std::array<wchar_t, 256>> sourceCameraName;
|
||||||
|
|
||||||
|
bool newOverlayImagePosted = false;
|
||||||
|
|
||||||
|
static std::wstring_view endpoint();
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace CameraOverlayImageChannel
|
||||||
|
{
|
||||||
|
std::wstring_view endpoint();
|
||||||
|
}
|
203
src/modules/videoconference/VideoConferenceShared/Logging.cpp
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
#include "Logging.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <mutex>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <chrono>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include <mfapi.h>
|
||||||
|
|
||||||
|
#pragma warning(disable : 4127)
|
||||||
|
|
||||||
|
static std::mutex logMutex;
|
||||||
|
constexpr inline size_t maxLogSizeMegabytes = 10;
|
||||||
|
constexpr inline bool alwaysLogVerbose = true;
|
||||||
|
|
||||||
|
void LogToFile(std::wstring what, const bool verbose)
|
||||||
|
{
|
||||||
|
std::error_code _;
|
||||||
|
const auto tempPath = std::filesystem::temp_directory_path(_);
|
||||||
|
if (verbose)
|
||||||
|
{
|
||||||
|
const bool verboseIndicatorFilePresent = std::filesystem::exists(tempPath / L"PowerToysVideoConferenceVerbose.flag", _);
|
||||||
|
if (!alwaysLogVerbose && !verboseIndicatorFilePresent)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||||
|
std::tm tm;
|
||||||
|
localtime_s(&tm, &now);
|
||||||
|
char prefix[64];
|
||||||
|
const auto pid = GetCurrentProcessId();
|
||||||
|
const auto iter = prefix + sprintf_s(prefix, "[%ld]", pid);
|
||||||
|
std::strftime(iter, sizeof(prefix) - (prefix - iter), "[%d.%m %H:%M:%S] ", &tm);
|
||||||
|
|
||||||
|
std::lock_guard lock{ logMutex };
|
||||||
|
std::wstring logFilePath = tempPath;
|
||||||
|
#if defined(_WIN64)
|
||||||
|
logFilePath += L"\\PowerToysVideoConference_x64.log";
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
logFilePath += L"\\PowerToysVideoConference_x86.log";
|
||||||
|
#endif
|
||||||
|
size_t logSizeMBs = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logSizeMBs = static_cast<size_t>(std::filesystem::file_size(logFilePath) >> 20);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
if (logSizeMBs > maxLogSizeMegabytes)
|
||||||
|
{
|
||||||
|
std::error_code __;
|
||||||
|
// Truncate the log file to zero
|
||||||
|
std::filesystem::resize_file(logFilePath, 0, __);
|
||||||
|
}
|
||||||
|
std::wofstream myfile;
|
||||||
|
myfile.open(logFilePath, std::fstream::app);
|
||||||
|
|
||||||
|
static const auto newLaunch = [&] {
|
||||||
|
myfile << prefix << "\n\n<<<NEW SESSION>>";
|
||||||
|
return 0;
|
||||||
|
}();
|
||||||
|
|
||||||
|
myfile << prefix << what << "\n";
|
||||||
|
myfile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogToFile(std::string what, const bool verbose)
|
||||||
|
{
|
||||||
|
std::wstring native{ begin(what), end(what) };
|
||||||
|
LogToFile(std::move(native), verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string toMediaTypeString(GUID subtype)
|
||||||
|
{
|
||||||
|
if (subtype == MFVideoFormat_YUY2)
|
||||||
|
return "MFVideoFormat_YUY2";
|
||||||
|
else if (subtype == MFVideoFormat_RGB32)
|
||||||
|
return "MFVideoFormat_RGB32";
|
||||||
|
else if (subtype == MFVideoFormat_RGB24)
|
||||||
|
return "MFVideoFormat_RGB24";
|
||||||
|
else if (subtype == MFVideoFormat_ARGB32)
|
||||||
|
return "MFVideoFormat_ARGB32";
|
||||||
|
else if (subtype == MFVideoFormat_RGB555)
|
||||||
|
return "MFVideoFormat_RGB555";
|
||||||
|
else if (subtype == MFVideoFormat_RGB565)
|
||||||
|
return "MFVideoFormat_RGB565";
|
||||||
|
else if (subtype == MFVideoFormat_RGB8)
|
||||||
|
return "MFVideoFormat_RGB8";
|
||||||
|
else if (subtype == MFVideoFormat_L8)
|
||||||
|
return "MFVideoFormat_L8";
|
||||||
|
else if (subtype == MFVideoFormat_L16)
|
||||||
|
return "MFVideoFormat_L16";
|
||||||
|
else if (subtype == MFVideoFormat_D16)
|
||||||
|
return "MFVideoFormat_D16";
|
||||||
|
else if (subtype == MFVideoFormat_AYUV)
|
||||||
|
return "MFVideoFormat_AYUV";
|
||||||
|
else if (subtype == MFVideoFormat_YUY2)
|
||||||
|
return "MFVideoFormat_YUY2";
|
||||||
|
else if (subtype == MFVideoFormat_YVYU)
|
||||||
|
return "MFVideoFormat_YVYU";
|
||||||
|
else if (subtype == MFVideoFormat_YVU9)
|
||||||
|
return "MFVideoFormat_YVU9";
|
||||||
|
else if (subtype == MFVideoFormat_UYVY)
|
||||||
|
return "MFVideoFormat_UYVY";
|
||||||
|
else if (subtype == MFVideoFormat_NV11)
|
||||||
|
return "MFVideoFormat_NV11";
|
||||||
|
else if (subtype == MFVideoFormat_NV12)
|
||||||
|
return "MFVideoFormat_NV12";
|
||||||
|
else if (subtype == MFVideoFormat_YV12)
|
||||||
|
return "MFVideoFormat_YV12";
|
||||||
|
else if (subtype == MFVideoFormat_I420)
|
||||||
|
return "MFVideoFormat_I420";
|
||||||
|
else if (subtype == MFVideoFormat_IYUV)
|
||||||
|
return "MFVideoFormat_IYUV";
|
||||||
|
else if (subtype == MFVideoFormat_Y210)
|
||||||
|
return "MFVideoFormat_Y210";
|
||||||
|
else if (subtype == MFVideoFormat_Y216)
|
||||||
|
return "MFVideoFormat_Y216";
|
||||||
|
else if (subtype == MFVideoFormat_Y410)
|
||||||
|
return "MFVideoFormat_Y410";
|
||||||
|
else if (subtype == MFVideoFormat_Y416)
|
||||||
|
return "MFVideoFormat_Y416";
|
||||||
|
else if (subtype == MFVideoFormat_Y41P)
|
||||||
|
return "MFVideoFormat_Y41P";
|
||||||
|
else if (subtype == MFVideoFormat_Y41T)
|
||||||
|
return "MFVideoFormat_Y41T";
|
||||||
|
else if (subtype == MFVideoFormat_Y42T)
|
||||||
|
return "MFVideoFormat_Y42T";
|
||||||
|
else if (subtype == MFVideoFormat_P210)
|
||||||
|
return "MFVideoFormat_P210";
|
||||||
|
else if (subtype == MFVideoFormat_P216)
|
||||||
|
return "MFVideoFormat_P216";
|
||||||
|
else if (subtype == MFVideoFormat_P010)
|
||||||
|
return "MFVideoFormat_P010";
|
||||||
|
else if (subtype == MFVideoFormat_P016)
|
||||||
|
return "MFVideoFormat_P016";
|
||||||
|
else if (subtype == MFVideoFormat_v210)
|
||||||
|
return "MFVideoFormat_v210";
|
||||||
|
else if (subtype == MFVideoFormat_v216)
|
||||||
|
return "MFVideoFormat_v216";
|
||||||
|
else if (subtype == MFVideoFormat_v410)
|
||||||
|
return "MFVideoFormat_v410";
|
||||||
|
else if (subtype == MFVideoFormat_MP43)
|
||||||
|
return "MFVideoFormat_MP43";
|
||||||
|
else if (subtype == MFVideoFormat_MP4S)
|
||||||
|
return "MFVideoFormat_MP4S";
|
||||||
|
else if (subtype == MFVideoFormat_M4S2)
|
||||||
|
return "MFVideoFormat_M4S2";
|
||||||
|
else if (subtype == MFVideoFormat_MP4V)
|
||||||
|
return "MFVideoFormat_MP4V";
|
||||||
|
else if (subtype == MFVideoFormat_WMV1)
|
||||||
|
return "MFVideoFormat_WMV1";
|
||||||
|
else if (subtype == MFVideoFormat_WMV2)
|
||||||
|
return "MFVideoFormat_WMV2";
|
||||||
|
else if (subtype == MFVideoFormat_WMV3)
|
||||||
|
return "MFVideoFormat_WMV3";
|
||||||
|
else if (subtype == MFVideoFormat_WVC1)
|
||||||
|
return "MFVideoFormat_WVC1";
|
||||||
|
else if (subtype == MFVideoFormat_MSS1)
|
||||||
|
return "MFVideoFormat_MSS1";
|
||||||
|
else if (subtype == MFVideoFormat_MSS2)
|
||||||
|
return "MFVideoFormat_MSS2";
|
||||||
|
else if (subtype == MFVideoFormat_MPG1)
|
||||||
|
return "MFVideoFormat_MPG1";
|
||||||
|
else if (subtype == MFVideoFormat_DVSL)
|
||||||
|
return "MFVideoFormat_DVSL";
|
||||||
|
else if (subtype == MFVideoFormat_DVSD)
|
||||||
|
return "MFVideoFormat_DVSD";
|
||||||
|
else if (subtype == MFVideoFormat_DVHD)
|
||||||
|
return "MFVideoFormat_DVHD";
|
||||||
|
else if (subtype == MFVideoFormat_DV25)
|
||||||
|
return "MFVideoFormat_DV25";
|
||||||
|
else if (subtype == MFVideoFormat_DV50)
|
||||||
|
return "MFVideoFormat_DV50";
|
||||||
|
else if (subtype == MFVideoFormat_DVH1)
|
||||||
|
return "MFVideoFormat_DVH1";
|
||||||
|
else if (subtype == MFVideoFormat_DVC)
|
||||||
|
return "MFVideoFormat_DVC";
|
||||||
|
else if (subtype == MFVideoFormat_H264)
|
||||||
|
return "MFVideoFormat_H264";
|
||||||
|
else if (subtype == MFVideoFormat_H265)
|
||||||
|
return "MFVideoFormat_H265";
|
||||||
|
else if (subtype == MFVideoFormat_MJPG)
|
||||||
|
return "MFVideoFormat_MJPG";
|
||||||
|
else if (subtype == MFVideoFormat_420O)
|
||||||
|
return "MFVideoFormat_420O";
|
||||||
|
else if (subtype == MFVideoFormat_HEVC)
|
||||||
|
return "MFVideoFormat_HEVC";
|
||||||
|
else if (subtype == MFVideoFormat_HEVC_ES)
|
||||||
|
return "MFVideoFormat_HEVC_ES";
|
||||||
|
else if (subtype == MFVideoFormat_VP80)
|
||||||
|
return "MFVideoFormat_VP80";
|
||||||
|
else if (subtype == MFVideoFormat_VP90)
|
||||||
|
return "MFVideoFormat_VP90";
|
||||||
|
else if (subtype == MFVideoFormat_ORAW)
|
||||||
|
return "MFVideoFormat_ORAW";
|
||||||
|
else
|
||||||
|
return "Other VideoFormat";
|
||||||
|
}
|
62
src/modules/videoconference/VideoConferenceShared/Logging.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <guiddef.h>
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
|
#include <wil/com.h>
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
void LogToFile(std::string what, const bool verbose = false);
|
||||||
|
void LogToFile(std::wstring what, const bool verbose = false);
|
||||||
|
std::string toMediaTypeString(GUID subtype);
|
||||||
|
|
||||||
|
#define RETURN_IF_FAILED_WITH_LOGGING(val) \
|
||||||
|
hr = (val); \
|
||||||
|
if (FAILED(hr)) \
|
||||||
|
{ \
|
||||||
|
LogToFile(std::string(__FUNCTION__ "() ") + #val + ": " + std::system_category().message(hr)); \
|
||||||
|
return hr; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RETURN_NULLPTR_IF_FAILED_WITH_LOGGING(val) \
|
||||||
|
hr = val; \
|
||||||
|
if (FAILED(hr)) \
|
||||||
|
{ \
|
||||||
|
LogToFile(std::string(__FUNCTION__ "() ") + #val + ": " + std::system_category().message(hr)); \
|
||||||
|
return nullptr; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VERBOSE_LOG \
|
||||||
|
std::string functionNameTMPVAR = __FUNCTION__; \
|
||||||
|
LogToFile(std::string(functionNameTMPVAR + " enter"), true); \
|
||||||
|
auto verboseLogOnScopeEnd = wil::scope_exit([&] { \
|
||||||
|
LogToFile(std::string(functionNameTMPVAR + " exit"), true); \
|
||||||
|
});
|
||||||
|
|
||||||
|
#if defined(PowerToysInterop)
|
||||||
|
#undef LOG
|
||||||
|
#define LOG(...)
|
||||||
|
#else
|
||||||
|
#define LOG(str) LogToFile(str, false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline bool failed(HRESULT hr)
|
||||||
|
{
|
||||||
|
return hr != S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool failed(bool val)
|
||||||
|
{
|
||||||
|
return val == false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool failed(wil::com_ptr_nothrow<T>& ptr)
|
||||||
|
{
|
||||||
|
return ptr == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OK_OR_BAIL(expr) \
|
||||||
|
if (failed(expr)) \
|
||||||
|
return {};
|
@ -0,0 +1,152 @@
|
|||||||
|
#include "MicrophoneDevice.h"
|
||||||
|
|
||||||
|
#include "Logging.h"
|
||||||
|
|
||||||
|
#include <Functiondiscoverykeys_devpkey.h>
|
||||||
|
|
||||||
|
MicrophoneDevice::MicrophoneDevice(wil::com_ptr_nothrow<IMMDevice> device, wil::com_ptr_nothrow<IAudioEndpointVolume> endpoint) :
|
||||||
|
_device{ std::move(device) },
|
||||||
|
_endpoint{ std::move(endpoint) }
|
||||||
|
{
|
||||||
|
if (!_device || !_endpoint)
|
||||||
|
{
|
||||||
|
throw std::logic_error("MicrophoneDevice was initialized with null objects");
|
||||||
|
}
|
||||||
|
_device->GetId(&_id);
|
||||||
|
wil::com_ptr_nothrow<IPropertyStore> props;
|
||||||
|
_device->OpenPropertyStore(
|
||||||
|
STGM_READ, &props);
|
||||||
|
if (props)
|
||||||
|
{
|
||||||
|
props->GetValue(PKEY_Device_FriendlyName, &_friendly_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG("MicrophoneDevice::MicrophoneDevice couldn't open property store");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MicrophoneDevice::~MicrophoneDevice()
|
||||||
|
{
|
||||||
|
if (_notifier)
|
||||||
|
{
|
||||||
|
_endpoint->UnregisterControlChangeNotify(_notifier.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MicrophoneDevice::active() const noexcept
|
||||||
|
{
|
||||||
|
DWORD state = 0;
|
||||||
|
_device->GetState(&state);
|
||||||
|
return state == DEVICE_STATE_ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MicrophoneDevice::set_muted(const bool muted) noexcept
|
||||||
|
{
|
||||||
|
_endpoint->SetMute(muted, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MicrophoneDevice::muted() const noexcept
|
||||||
|
{
|
||||||
|
BOOL muted = FALSE;
|
||||||
|
_endpoint->GetMute(&muted);
|
||||||
|
return muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MicrophoneDevice::toggle_muted() noexcept
|
||||||
|
{
|
||||||
|
set_muted(!muted());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring_view MicrophoneDevice::id() const noexcept
|
||||||
|
{
|
||||||
|
return _id ? _id.get() : FALLBACK_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring_view MicrophoneDevice::name() const noexcept
|
||||||
|
{
|
||||||
|
return _friendly_name.pwszVal ? _friendly_name.pwszVal : FALLBACK_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MicrophoneDevice::set_mute_changed_callback(mute_changed_cb_t callback) noexcept
|
||||||
|
{
|
||||||
|
_mute_changed_callback = std::move(callback);
|
||||||
|
_notifier = winrt::make<VolumeNotifier>(this);
|
||||||
|
|
||||||
|
_endpoint->RegisterControlChangeNotify(_notifier.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<MicrophoneDevice> MicrophoneDevice::getDefault()
|
||||||
|
{
|
||||||
|
auto deviceEnumerator = wil::CoCreateInstanceNoThrow<MMDeviceEnumerator, IMMDeviceEnumerator>();
|
||||||
|
if (!deviceEnumerator)
|
||||||
|
{
|
||||||
|
LOG("MicrophoneDevice::getDefault MMDeviceEnumerator returned null");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
wil::com_ptr_nothrow<IMMDevice> captureDevice;
|
||||||
|
deviceEnumerator->GetDefaultAudioEndpoint(eCapture, eCommunications, &captureDevice);
|
||||||
|
if (!captureDevice)
|
||||||
|
{
|
||||||
|
LOG("MicrophoneDevice::getDefault captureDevice is null");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
wil::com_ptr_nothrow<IAudioEndpointVolume> microphoneEndpoint;
|
||||||
|
captureDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, nullptr, reinterpret_cast<LPVOID*>(µphoneEndpoint));
|
||||||
|
if (!microphoneEndpoint)
|
||||||
|
{
|
||||||
|
LOG("MicrophoneDevice::getDefault captureDevice is null");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return std::make_optional<MicrophoneDevice>(std::move(captureDevice), std::move(microphoneEndpoint));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<MicrophoneDevice> MicrophoneDevice::getAllActive()
|
||||||
|
{
|
||||||
|
std::vector<MicrophoneDevice> microphoneDevices;
|
||||||
|
auto deviceEnumerator = wil::CoCreateInstanceNoThrow<MMDeviceEnumerator, IMMDeviceEnumerator>();
|
||||||
|
if (!deviceEnumerator)
|
||||||
|
{
|
||||||
|
LOG("MicrophoneDevice::getAllActive MMDeviceEnumerator returned null");
|
||||||
|
return microphoneDevices;
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr_nothrow<IMMDeviceCollection> captureDevices;
|
||||||
|
deviceEnumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE, &captureDevices);
|
||||||
|
if (!captureDevices)
|
||||||
|
{
|
||||||
|
LOG("MicrophoneDevice::getAllActive EnumAudioEndpoints returned null");
|
||||||
|
return microphoneDevices;
|
||||||
|
}
|
||||||
|
UINT nDevices = 0;
|
||||||
|
captureDevices->GetCount(&nDevices);
|
||||||
|
microphoneDevices.reserve(nDevices);
|
||||||
|
for (UINT i = 0; i < nDevices; ++i)
|
||||||
|
{
|
||||||
|
wil::com_ptr_nothrow<IMMDevice> device;
|
||||||
|
captureDevices->Item(i, &device);
|
||||||
|
if (!device)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
wil::com_ptr_nothrow<IAudioEndpointVolume> microphoneEndpoint;
|
||||||
|
device->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, nullptr, reinterpret_cast<LPVOID*>(µphoneEndpoint));
|
||||||
|
if (!microphoneEndpoint)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
microphoneDevices.emplace_back(std::move(device), std::move(microphoneEndpoint));
|
||||||
|
}
|
||||||
|
return microphoneDevices;
|
||||||
|
}
|
||||||
|
|
||||||
|
MicrophoneDevice::VolumeNotifier::VolumeNotifier(MicrophoneDevice* subscribedDevice) :
|
||||||
|
_subscribedDevice{ subscribedDevice }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT __stdcall MicrophoneDevice::VolumeNotifier::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA data)
|
||||||
|
{
|
||||||
|
_subscribedDevice->_mute_changed_callback(data->bMuted);
|
||||||
|
return S_OK;
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
#pragma once
|
||||||
|
#define NOMINMAX
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <Unknwn.h>
|
||||||
|
|
||||||
|
#include <winrt/base.h>
|
||||||
|
#include <winrt/Windows.Foundation.Collections.h>
|
||||||
|
|
||||||
|
#include <wil/resource.h>
|
||||||
|
#include <wil/com.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include <Mmdeviceapi.h>
|
||||||
|
#include <Endpointvolume.h>
|
||||||
|
|
||||||
|
class MicrophoneDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using mute_changed_cb_t = std::function<void(bool muted)>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend struct VolumeNotifier;
|
||||||
|
|
||||||
|
struct VolumeNotifier : winrt::implements<VolumeNotifier, IAudioEndpointVolumeCallback>
|
||||||
|
{
|
||||||
|
MicrophoneDevice* _subscribedDevice = nullptr;
|
||||||
|
VolumeNotifier(MicrophoneDevice* subscribedDevice);
|
||||||
|
|
||||||
|
virtual HRESULT __stdcall OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA data) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
wil::unique_cotaskmem_string _id;
|
||||||
|
wil::unique_prop_variant _friendly_name;
|
||||||
|
mute_changed_cb_t _mute_changed_callback;
|
||||||
|
winrt::com_ptr<IAudioEndpointVolumeCallback> _notifier;
|
||||||
|
wil::com_ptr_nothrow<IAudioEndpointVolume> _endpoint;
|
||||||
|
wil::com_ptr_nothrow<IMMDevice> _device;
|
||||||
|
|
||||||
|
constexpr static inline std::wstring_view FALLBACK_NAME = L"Unknown device";
|
||||||
|
constexpr static inline std::wstring_view FALLBACK_ID = L"UNKNOWN_ID";
|
||||||
|
|
||||||
|
public:
|
||||||
|
MicrophoneDevice(MicrophoneDevice&&) noexcept = default;
|
||||||
|
MicrophoneDevice(wil::com_ptr_nothrow<IMMDevice> device, wil::com_ptr_nothrow<IAudioEndpointVolume> endpoint);
|
||||||
|
~MicrophoneDevice();
|
||||||
|
|
||||||
|
bool active() const noexcept;
|
||||||
|
void set_muted(const bool muted) noexcept;
|
||||||
|
bool muted() const noexcept;
|
||||||
|
void toggle_muted() noexcept;
|
||||||
|
|
||||||
|
std::wstring_view id() const noexcept;
|
||||||
|
std::wstring_view name() const noexcept;
|
||||||
|
void set_mute_changed_callback(mute_changed_cb_t callback) noexcept;
|
||||||
|
|
||||||
|
static std::optional<MicrophoneDevice> getDefault();
|
||||||
|
static std::vector<MicrophoneDevice> getAllActive();
|
||||||
|
};
|
@ -0,0 +1,188 @@
|
|||||||
|
#include "SerializedSharedMemory.h"
|
||||||
|
|
||||||
|
inline char* SerializedSharedMemory::lock_flag_addr() noexcept
|
||||||
|
{
|
||||||
|
return reinterpret_cast<char*>(_memory._data + _memory._size);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SerializedSharedMemory::lock() noexcept
|
||||||
|
{
|
||||||
|
if (_read_only)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (LOCKED == _InterlockedCompareExchange8(lock_flag_addr(), LOCKED, !LOCKED))
|
||||||
|
{
|
||||||
|
while (*lock_flag_addr() == LOCKED)
|
||||||
|
{
|
||||||
|
_mm_pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SerializedSharedMemory::unlock() noexcept
|
||||||
|
{
|
||||||
|
if (_read_only)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_InterlockedExchange8(lock_flag_addr(), !LOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedSharedMemory::SerializedSharedMemory(std::array<wil::unique_handle, 2> handles,
|
||||||
|
memory_t memory,
|
||||||
|
const bool readonly) noexcept
|
||||||
|
:
|
||||||
|
_handles{ std::move(handles) }, _memory{ std::move(memory) }, _read_only(readonly)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedSharedMemory::~SerializedSharedMemory() noexcept
|
||||||
|
{
|
||||||
|
if (_memory._data)
|
||||||
|
{
|
||||||
|
UnmapViewOfFile(_memory._data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedSharedMemory::SerializedSharedMemory(SerializedSharedMemory&& rhs) noexcept
|
||||||
|
{
|
||||||
|
*this = std::move(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedSharedMemory& SerializedSharedMemory::operator=(SerializedSharedMemory&& rhs) noexcept
|
||||||
|
{
|
||||||
|
_handles = {};
|
||||||
|
_handles.swap(rhs._handles);
|
||||||
|
_memory = std::move(rhs._memory);
|
||||||
|
rhs._memory = {};
|
||||||
|
_read_only = rhs._read_only;
|
||||||
|
rhs._read_only = true;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<SerializedSharedMemory> SerializedSharedMemory::create(const std::wstring_view object_name,
|
||||||
|
const size_t size,
|
||||||
|
const bool read_only,
|
||||||
|
SECURITY_ATTRIBUTES* maybe_attributes) noexcept
|
||||||
|
{
|
||||||
|
SECURITY_DESCRIPTOR sd;
|
||||||
|
SECURITY_ATTRIBUTES sa = { sizeof SECURITY_ATTRIBUTES };
|
||||||
|
if (!maybe_attributes)
|
||||||
|
{
|
||||||
|
sa.lpSecurityDescriptor = &sd;
|
||||||
|
sa.bInheritHandle = false;
|
||||||
|
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) ||
|
||||||
|
!SetSecurityDescriptorDacl(&sd, true, nullptr, false))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need an extra byte for locking if it's not readonly
|
||||||
|
const ULARGE_INTEGER UISize{ .QuadPart = size + !read_only };
|
||||||
|
|
||||||
|
wil::unique_handle hMapFile{ CreateFileMappingW(INVALID_HANDLE_VALUE,
|
||||||
|
maybe_attributes ? maybe_attributes : &sa,
|
||||||
|
read_only ? PAGE_READONLY : PAGE_READWRITE,
|
||||||
|
UISize.HighPart,
|
||||||
|
UISize.LowPart,
|
||||||
|
object_name.data()) };
|
||||||
|
if (!hMapFile)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
auto shmem = static_cast<uint8_t*>(
|
||||||
|
MapViewOfFile(hMapFile.get(), read_only ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, static_cast<SIZE_T>(UISize.QuadPart)));
|
||||||
|
if (!shmem)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
std::array<wil::unique_handle, 2> handles = { std::move(hMapFile), {} };
|
||||||
|
return SerializedSharedMemory{ std::move(handles), memory_t{ shmem, size }, read_only };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<SerializedSharedMemory> SerializedSharedMemory::open(const std::wstring_view object_name,
|
||||||
|
const size_t size,
|
||||||
|
const bool read_only) noexcept
|
||||||
|
{
|
||||||
|
wil::unique_handle hMapFile{ OpenFileMappingW(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, object_name.data()) };
|
||||||
|
if (!hMapFile)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto shmem = static_cast<uint8_t*>(
|
||||||
|
MapViewOfFile(hMapFile.get(), read_only ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size + !read_only));
|
||||||
|
|
||||||
|
if (!shmem)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
std::array<wil::unique_handle, 2> handles = { std::move(hMapFile), {} };
|
||||||
|
return SerializedSharedMemory{ std::move(handles), memory_t{ shmem, size }, read_only };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<SerializedSharedMemory> SerializedSharedMemory::create_readonly(
|
||||||
|
const std::wstring_view object_name,
|
||||||
|
const std::wstring_view file_path,
|
||||||
|
SECURITY_ATTRIBUTES* maybe_attributes) noexcept
|
||||||
|
{
|
||||||
|
SECURITY_DESCRIPTOR sd;
|
||||||
|
SECURITY_ATTRIBUTES sa = { sizeof SECURITY_ATTRIBUTES };
|
||||||
|
if (!maybe_attributes)
|
||||||
|
{
|
||||||
|
sa.lpSecurityDescriptor = &sd;
|
||||||
|
sa.bInheritHandle = false;
|
||||||
|
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) ||
|
||||||
|
!SetSecurityDescriptorDacl(&sd, true, nullptr, false))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wil::unique_handle hFile{ CreateFileW(file_path.data(),
|
||||||
|
GENERIC_READ,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
maybe_attributes ? maybe_attributes : &sa,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
nullptr) };
|
||||||
|
|
||||||
|
if (!hFile)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
LARGE_INTEGER fileSize;
|
||||||
|
if (!GetFileSizeEx(hFile.get(), &fileSize))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
wil::unique_handle hMapFile{ CreateFileMappingW(hFile.get(),
|
||||||
|
maybe_attributes ? maybe_attributes : &sa,
|
||||||
|
PAGE_READONLY,
|
||||||
|
fileSize.HighPart,
|
||||||
|
fileSize.LowPart,
|
||||||
|
object_name.data()) };
|
||||||
|
if (!hMapFile)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto shmem = static_cast<uint8_t*>(MapViewOfFile(nullptr, FILE_MAP_READ, 0, 0, static_cast<size_t>(fileSize.QuadPart)));
|
||||||
|
if (shmem)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
std::array<wil::unique_handle, 2> handles = { std::move(hMapFile), std::move(hFile) };
|
||||||
|
|
||||||
|
return SerializedSharedMemory{ std::move(handles), memory_t{ shmem, static_cast<size_t>(fileSize.QuadPart) }, true };
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerializedSharedMemory::access(std::function<void(memory_t)> access_routine) noexcept
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
access_routine(_memory);
|
||||||
|
unlock();
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
#include <wil/resource.h>
|
||||||
|
#include <functional>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
// Wrapper class allowing sharing readonly/writable memory with a serialized access via atomic locking.
|
||||||
|
// Note that it doesn't protect against a 3rd party concurrently modifying physical file contents.
|
||||||
|
class SerializedSharedMemory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct memory_t
|
||||||
|
{
|
||||||
|
uint8_t * _data = nullptr;
|
||||||
|
size_t _size = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::optional<SerializedSharedMemory> create(const std::wstring_view object_name,
|
||||||
|
const size_t size,
|
||||||
|
const bool read_only,
|
||||||
|
SECURITY_ATTRIBUTES* maybe_attributes = nullptr) noexcept;
|
||||||
|
static std::optional<SerializedSharedMemory> create_readonly(
|
||||||
|
const std::wstring_view object_name,
|
||||||
|
const std::wstring_view file_path,
|
||||||
|
SECURITY_ATTRIBUTES* maybe_attributes = nullptr) noexcept;
|
||||||
|
static std::optional<SerializedSharedMemory> open(const std::wstring_view object_name,
|
||||||
|
const size_t size,
|
||||||
|
const bool read_only) noexcept;
|
||||||
|
|
||||||
|
void access(std::function<void(memory_t)> access_routine) noexcept;
|
||||||
|
inline size_t size() const noexcept { return _memory._size; }
|
||||||
|
|
||||||
|
~SerializedSharedMemory() noexcept;
|
||||||
|
SerializedSharedMemory(SerializedSharedMemory&&) noexcept;
|
||||||
|
SerializedSharedMemory& operator=(SerializedSharedMemory&&) noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<wil::unique_handle, 2> _handles;
|
||||||
|
memory_t _memory;
|
||||||
|
bool _read_only = true;
|
||||||
|
constexpr static inline int64_t LOCKED = 1;
|
||||||
|
|
||||||
|
char* lock_flag_addr() noexcept;
|
||||||
|
void lock() noexcept;
|
||||||
|
void unlock() noexcept;
|
||||||
|
|
||||||
|
SerializedSharedMemory(std::array<wil::unique_handle, 2> handles, memory_t memory, const bool readonly) noexcept;
|
||||||
|
};
|
@ -0,0 +1,100 @@
|
|||||||
|
#include "VideoCaptureDeviceList.h"
|
||||||
|
#include "Logging.h"
|
||||||
|
#include <mfapi.h>
|
||||||
|
#include <Mfidl.h>
|
||||||
|
|
||||||
|
#include <wil/resource.h>
|
||||||
|
#include <wil/com.h>
|
||||||
|
|
||||||
|
void VideoCaptureDeviceList::Clear()
|
||||||
|
{
|
||||||
|
for (UINT32 i = 0; i < m_numberDevices; i++)
|
||||||
|
{
|
||||||
|
CoTaskMemFree(m_deviceFriendlyNames[i]);
|
||||||
|
if (m_ppDevices[i])
|
||||||
|
{
|
||||||
|
m_ppDevices[i]->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CoTaskMemFree(m_ppDevices);
|
||||||
|
m_ppDevices = nullptr;
|
||||||
|
if (m_deviceFriendlyNames)
|
||||||
|
{
|
||||||
|
delete[] m_deviceFriendlyNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_deviceFriendlyNames = nullptr;
|
||||||
|
m_numberDevices = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureDeviceList::EnumerateDevices()
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
wil::com_ptr<IMFAttributes> pAttributes;
|
||||||
|
Clear();
|
||||||
|
|
||||||
|
// Initialize an attribute store. We will use this to
|
||||||
|
// specify the enumeration parameters.
|
||||||
|
|
||||||
|
hr = MFCreateAttributes(&pAttributes, 1);
|
||||||
|
|
||||||
|
// Ask for source type = video capture devices
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = pAttributes->SetGUID(
|
||||||
|
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
|
||||||
|
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureDeviceList::EnumerateDevices(): Couldn't MFCreateAttributes");
|
||||||
|
}
|
||||||
|
// Enumerate devices.
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = MFEnumDeviceSources(pAttributes.get(), &m_ppDevices, &m_numberDevices);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureDeviceList::EnumerateDevices(): Couldn't SetGUID");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
LOG("VideoCaptureDeviceList::EnumerateDevices(): MFEnumDeviceSources failed");
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_deviceFriendlyNames = new (std::nothrow) wchar_t*[m_numberDevices];
|
||||||
|
for (UINT32 i = 0; i < m_numberDevices; i++)
|
||||||
|
{
|
||||||
|
UINT32 nameLength = 0;
|
||||||
|
m_ppDevices[i]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, &m_deviceFriendlyNames[i], &nameLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT VideoCaptureDeviceList::GetDevice(UINT32 index, IMFActivate** ppActivate)
|
||||||
|
{
|
||||||
|
if (index >= Count())
|
||||||
|
{
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ppActivate = m_ppDevices[index];
|
||||||
|
(*ppActivate)->AddRef();
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring_view VideoCaptureDeviceList::GetDeviceName(UINT32 index)
|
||||||
|
{
|
||||||
|
if (index >= Count())
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_deviceFriendlyNames[index];
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <mfobjects.h>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
class VideoCaptureDeviceList
|
||||||
|
{
|
||||||
|
UINT32 m_numberDevices;
|
||||||
|
// TODO: use wil
|
||||||
|
IMFActivate** m_ppDevices = nullptr;
|
||||||
|
wchar_t** m_deviceFriendlyNames = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VideoCaptureDeviceList() :
|
||||||
|
m_ppDevices(NULL), m_numberDevices(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~VideoCaptureDeviceList()
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 Count() const { return m_numberDevices; }
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
HRESULT EnumerateDevices();
|
||||||
|
HRESULT GetDevice(UINT32 index, IMFActivate** ppActivate);
|
||||||
|
std::wstring_view GetDeviceName(UINT32 index);
|
||||||
|
};
|
@ -0,0 +1,140 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>mfplat.lib;Mfsensorgroup.lib;OneCoreUAP.lib;Mf.lib;Shlwapi.lib;Strmiids.lib;%(AdditionalDependencies);</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<ProjectGuid>{459e0768-7ebd-4c41-bba1-6db3b3815e0a}</ProjectGuid>
|
||||||
|
<RootNamespace>VideoConferenceShared</RootNamespace>
|
||||||
|
<OverrideWindowsTargetPlatformVersion>true</OverrideWindowsTargetPlatformVersion>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Platform)'!='Win32'">
|
||||||
|
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\VideoConference\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Platform)'=='Win32'">
|
||||||
|
<OutDir>..\..\..\..\x86\$(Configuration)\modules\VideoConference\</OutDir>
|
||||||
|
<IntDir>..\..\..\..\x86\$(Configuration)\obj\$(ProjectName)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)\src\;</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
<Lib>
|
||||||
|
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
|
||||||
|
</Lib>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)\src\;</AdditionalIncludeDirectories>
|
||||||
|
<DebugInformationFormat Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">ProgramDatabase</DebugInformationFormat>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
<Lib>
|
||||||
|
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
|
||||||
|
</Lib>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="CameraStateUpdateChannels.cpp" />
|
||||||
|
<ClCompile Include="Logging.cpp" />
|
||||||
|
<ClCompile Include="SerializedSharedMemory.cpp" />
|
||||||
|
<ClCompile Include="naming.cpp" />
|
||||||
|
<ClCompile Include="username.cpp" />
|
||||||
|
<ClCompile Include="MicrophoneDevice.cpp" />
|
||||||
|
<ClCompile Include="VideoCaptureDeviceList.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="CameraStateUpdateChannels.h" />
|
||||||
|
<ClInclude Include="Logging.h" />
|
||||||
|
<ClInclude Include="SerializedSharedMemory.h" />
|
||||||
|
<ClInclude Include="naming.h" />
|
||||||
|
<ClInclude Include="MicrophoneDevice.h" />
|
||||||
|
<ClInclude Include="VideoCaptureDeviceList.h" />
|
||||||
|
<ClInclude Include="username.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200519.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200519.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||||
|
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||||
|
</ImportGroup>
|
||||||
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200519.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200519.2\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
19
src/modules/videoconference/VideoConferenceShared/naming.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include "naming.h"
|
||||||
|
|
||||||
|
#include "username.h"
|
||||||
|
|
||||||
|
std::wstring ObtainStableGlobalNameForKernelObject(const std::wstring_view name, const bool restricted)
|
||||||
|
{
|
||||||
|
static const std::optional<std::wstring> username = ObtainActiveUserName();
|
||||||
|
std::wstring result = L"Global\\";
|
||||||
|
if (restricted)
|
||||||
|
{
|
||||||
|
result += L"Restricted\\";
|
||||||
|
}
|
||||||
|
if (username)
|
||||||
|
{
|
||||||
|
result += *username;
|
||||||
|
}
|
||||||
|
result += name;
|
||||||
|
return result;
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string_view>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
std::wstring ObtainStableGlobalNameForKernelObject(const std::wstring_view name, const bool restricted);
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.200519.2" targetFramework="native" />
|
||||||
|
<package id="Microsoft.Windows.CppWinRT" version="2.0.200729.8" targetFramework="native" />
|
||||||
|
</packages>
|
@ -0,0 +1,20 @@
|
|||||||
|
#include "username.h"
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <wtsapi32.h>
|
||||||
|
|
||||||
|
std::optional<std::wstring> ObtainActiveUserName()
|
||||||
|
{
|
||||||
|
const DWORD sessionId = WTSGetActiveConsoleSessionId();
|
||||||
|
WCHAR* pUserName;
|
||||||
|
DWORD _ = 0;
|
||||||
|
|
||||||
|
if (!WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, &pUserName, &_))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
WTSGetActiveConsoleSessionId();
|
||||||
|
std::wstring result{ pUserName };
|
||||||
|
WTSFreeMemory(pUserName);
|
||||||
|
return result;
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
std::optional<std::wstring> ObtainActiveUserName();
|
||||||
|
|
||||||
|
std::wstring ObtainStableGlobalNameForKernelObject(const std::wstring_view name, const bool restricted);
|
20
src/modules/videoconference/make_cab.ddf
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
; Disable default limits
|
||||||
|
.option EXPLICIT
|
||||||
|
.set CabinetFileCountThreshold=0
|
||||||
|
.set FolderFileCountThreshold=0
|
||||||
|
.set FolderSizeThreshold=0
|
||||||
|
.set MaxCabinetSize=0
|
||||||
|
.set MaxDiskFileCount=0
|
||||||
|
.set MaxDiskSize=0
|
||||||
|
|
||||||
|
.set GenerateInf=ON
|
||||||
|
.set Compress=OFF
|
||||||
|
.set Cabinet=ON
|
||||||
|
.set CabinetNameTemplate=driver.cab
|
||||||
|
.set DestinationDir=cab_output
|
||||||
|
.set DiskDirectoryTemplate=driver
|
||||||
|
|
||||||
|
VideoConferenceCustomMediaSource.dll
|
||||||
|
videoconferencevirtualdriver.cat
|
||||||
|
VideoConferenceVirtualDriver.dll
|
||||||
|
VideoConferenceVirtualDriver.inf
|
@ -20,6 +20,7 @@
|
|||||||
#include <common/updating/updateState.h>
|
#include <common/updating/updateState.h>
|
||||||
#include <common/utils/appMutex.h>
|
#include <common/utils/appMutex.h>
|
||||||
#include <common/utils/elevation.h>
|
#include <common/utils/elevation.h>
|
||||||
|
#include <common/utils/os-detect.h>
|
||||||
#include <common/utils/processApi.h>
|
#include <common/utils/processApi.h>
|
||||||
#include <common/utils/resources.h>
|
#include <common/utils/resources.h>
|
||||||
|
|
||||||
@ -43,6 +44,7 @@
|
|||||||
#include <common/utils/winapi_error.h>
|
#include <common/utils/winapi_error.h>
|
||||||
#include <common/utils/window.h>
|
#include <common/utils/window.h>
|
||||||
#include <common/version/version.h>
|
#include <common/version/version.h>
|
||||||
|
#include <gdiplus.h>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -130,7 +132,7 @@ int runner(bool isProcessElevated, bool openSettings, bool openOobe)
|
|||||||
chdir_current_executable();
|
chdir_current_executable();
|
||||||
// Load Powertoys DLLs
|
// Load Powertoys DLLs
|
||||||
|
|
||||||
const std::array<std::wstring_view, 9> knownModules = {
|
std::vector<std::wstring_view> knownModules = {
|
||||||
L"modules/FancyZones/FancyZonesModuleInterface.dll",
|
L"modules/FancyZones/FancyZonesModuleInterface.dll",
|
||||||
L"modules/FileExplorerPreview/powerpreview.dll",
|
L"modules/FileExplorerPreview/powerpreview.dll",
|
||||||
L"modules/ImageResizer/ImageResizerExt.dll",
|
L"modules/ImageResizer/ImageResizerExt.dll",
|
||||||
@ -140,6 +142,8 @@ int runner(bool isProcessElevated, bool openSettings, bool openOobe)
|
|||||||
L"modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.dll",
|
L"modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.dll",
|
||||||
L"modules/ColorPicker/ColorPicker.dll",
|
L"modules/ColorPicker/ColorPicker.dll",
|
||||||
L"modules/Awake/AwakeModuleInterface.dll",
|
L"modules/Awake/AwakeModuleInterface.dll",
|
||||||
|
// TODO(yuyoyuppe): uncomment when VCM should be enabled
|
||||||
|
//L"modules/VideoConference/VideoConferenceModule.dll"
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto& moduleSubdir : knownModules)
|
for (const auto& moduleSubdir : knownModules)
|
||||||
@ -264,6 +268,10 @@ toast_notification_handler_result toast_notification_handler(const std::wstring_
|
|||||||
|
|
||||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||||
{
|
{
|
||||||
|
Gdiplus::GdiplusStartupInput gpStartupInput;
|
||||||
|
ULONG_PTR gpToken;
|
||||||
|
GdiplusStartup(&gpToken, &gpStartupInput, NULL);
|
||||||
|
|
||||||
winrt::init_apartment();
|
winrt::init_apartment();
|
||||||
const wchar_t* securityDescriptor =
|
const wchar_t* securityDescriptor =
|
||||||
L"O:BA" // Owner: Builtin (local) administrator
|
L"O:BA" // Owner: Builtin (local) administrator
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
<Link>
|
<Link>
|
||||||
<UACExecutionLevel>AsInvoker</UACExecutionLevel>
|
<UACExecutionLevel>AsInvoker</UACExecutionLevel>
|
||||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||||
<AdditionalDependencies>Shcore.lib;Msi.lib;WindowsApp.lib;taskschd.lib;Rstrtmgr.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Shcore.lib;gdiplus.lib;Msi.lib;WindowsApp.lib;taskschd.lib;Rstrtmgr.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<Manifest>
|
<Manifest>
|
||||||
<EnableDpiAwareness>false</EnableDpiAwareness>
|
<EnableDpiAwareness>false</EnableDpiAwareness>
|
||||||
|
@ -80,6 +80,22 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool videoConference = true;
|
||||||
|
|
||||||
|
[JsonPropertyName("Video Conference")]
|
||||||
|
public bool VideoConference
|
||||||
|
{
|
||||||
|
get => this.videoConference;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (this.videoConference != value)
|
||||||
|
{
|
||||||
|
LogTelemetryEvent(value);
|
||||||
|
this.videoConference = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool powerRename = true;
|
private bool powerRename = true;
|
||||||
|
|
||||||
public bool PowerRename
|
public bool PowerRename
|
||||||
|
@ -58,4 +58,11 @@
|
|||||||
<ProjectReference Include="..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
<ProjectReference Include="..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||||
<ProjectReference Include="..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
|
<ProjectReference Include="..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System.Windows.Forms">
|
||||||
|
<HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.Windows.Forms.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|