Skip to content

Commit

Permalink
Allow monitor choice
Browse files Browse the repository at this point in the history
If more than one monitor is found on the target, an interactive dialog
will be prompted to the user to choose from, displaying monitor name
(port) and resolution and geometry for better identification. The
monitor can be enforced by the target by environment variable.

Fixes: QubesOS/qubes-issues#9275
  • Loading branch information
ben-grande committed Jun 2, 2024
1 parent 6246500 commit 14ffef1
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 16 deletions.
4 changes: 4 additions & 0 deletions doc/qubes-video-companion.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ The project emphasizes correctness and security all the while also sporting supe

OPTIONS
=======
resolution
The video resolution to stream and receive video in. The format is [WIDTHxHEIGHTxFPS], meaning resolution is optional. If you set the environment variable "QVC_MONITOR" in the target, that monitor is going to be preferred and if not found, will fallback to the primary monitor. Example: "1920x1080x60"


video_source
The video source to stream and receive video from. Either "webcam" or "screenshare".

Expand Down
26 changes: 25 additions & 1 deletion qubes-rpc/services/qvc.ScreenShare
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
#!/bin/sh --

# Copyright (C) 2021 Elliot Killick <[email protected]>
# Copyright (C) 2021 Demi Marie Obenour <[email protected]>
# Licensed under the MIT License. See LICENSE file for details.

set -eu

## DISPLAY variable used by: xrandr, zenity
export DISPLAY=:0

true "${XDG_RUNTIME_DIR:="/run/user/$(id -u)"}"
true "${DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus"}"
monitors="$(xrandr --listactivemonitors \
| awk '/^ [0-9]+: \+/ { print "FALSE", $4, $3 }')"
monitor_count="$(echo "${monitors}" | wc -l)"
monitor_longest_line="$(echo "${monitors}" | wc -L)"
dialog_height="$((monitor_count*50+60))"
dialog_width="$((monitor_longest_line*10))"
if test "${monitor_count}" -gt 1; then
# shellcheck disable=SC2086
QVC_MONITOR="$(zenity --list --radiolist \
--height="${dialog_height}" --width="${dialog_width}" \
--column "ID" --column "Name" --column "Resolution" \
--title "Screen share" \
--text "Select monitor to present to qube ${QREXEC_REMOTE_DOMAIN}" \
${monitors})"
fi
true "${QVC_MONITOR:=}"

export XDG_RUNTIME_DIR DBUS_SESSION_BUS_ADDRESS QVC_MONITOR
exec python3 -- /usr/share/qubes-video-companion/sender/screenshare.py
8 changes: 5 additions & 3 deletions qubes-rpc/services/qvc.Webcam
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#!/bin/sh --

# Copyright (C) 2021 Elliot Killick <[email protected]>
# Copyright (C) 2021 Demi Marie Obenour <[email protected]>
# Licensed under the MIT License. See LICENSE file for details.
export DISPLAY=:0
exec python3 -- /usr/share/qubes-video-companion/sender/webcam.py ${1:+"$1"}
set -eu
true "${XDG_RUNTIME_DIR:="/run/user/$(id -u)"}"
true "${DBUS_SESSION_BUS_ADDRESS:="unix:path=${XDG_RUNTIME_DIR}/bus"}"
export DISPLAY=:0 XDG_RUNTIME_DIR DBUS_SESSION_BUS_ADDRESS
exec python3 -- /usr/share/qubes-video-companion/sender/webcam.py "${1:+"$1"}"
13 changes: 7 additions & 6 deletions receiver/qubes-video-companion
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ unset GETOPT_COMPATIBLE
name=${0##*/}

usage() {
printf '%s: Usage: qubes-video-companion [--resolution=WIDTHxHEIGHTxFPS] [--] webcam|screenshare [destination qube]\n' "$name"
echo "Usage: $name [--resolution=[WIDTHxHEIGHTxFPS]] [--] webcam|screenshare [destination qube]" >&2
echo "Resolution example: 1920x1080x60"
exit "$1"
}

Expand All @@ -23,14 +24,14 @@ while :; do
case $1 in
-r|--resolution)
if [[ -z "$2" ]]; then
printf '%s: Empty resolution argument\n' "$name"
usage 0
fi >&2
echo "$name: Empty resolution argument" >&2
usage 1
fi
resolution=${2//@/+}
resolution=${resolution//x/+}
shift 2
;;
--help) usage 0;;
-h|--help) usage 0;;
--) shift; break;;
*) exit 1;; # cannot happen
esac
Expand Down Expand Up @@ -71,7 +72,7 @@ if ! [ -f "$qvc_lock_file" ]; then
trap exit_clean EXIT
sudo touch "$qvc_lock_file"
else
echo "Qubes Video Companion is already running! Please stop the previous session before starting a new one." >&2
echo "Qubes Video Companion is already running! Please stop the previous session before starting a new one. If you think this is an error, remove the lockfile $qvc_lock_file" >&2
exit 1
fi

Expand Down
22 changes: 16 additions & 6 deletions sender/screenshare.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
# pylint: disable=wrong-import-position

import gi
import os

gi.require_version("Gdk", "3.0")
from gi.repository import Gdk
Expand All @@ -30,15 +31,24 @@ def icon(self) -> str:
return "video-display"

def parameters(self) -> Tuple[int, int, int]:
monitor = Gdk.Display().get_default().get_monitor(0).get_geometry()
display = Gdk.Display().get_default()
monitor_count = display.get_n_monitors()
monitor_wanted = os.environ["QVC_MONITOR"]
## If wanted monitor is not found, use the primary monitor (0).
monitor_index = 0
for m in range(monitor_count):
if display.get_monitor(m).get_model() == monitor_wanted:
monitor_index = m
break
geometry = display.get_monitor(monitor_index).get_geometry()
screen = Gdk.Screen().get_default()
kwargs = {
"crop_t": monitor.y,
"crop_l": monitor.x,
"crop_r": screen.width() - monitor.x - monitor.width,
"crop_b": screen.height() - monitor.y - monitor.height,
"crop_t": geometry.y,
"crop_l": geometry.x,
"crop_r": screen.width() - geometry.x - geometry.width,
"crop_b": screen.height() - geometry.y - geometry.height,
}
return (monitor.width, monitor.height, 30, kwargs)
return (geometry.width, geometry.height, 30, kwargs)

def pipeline(self, width: int, height: int, fps: int,
**kwargs) -> List[str]:
Expand Down

0 comments on commit 14ffef1

Please sign in to comment.