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