feat: Add streaming support (#125)

This adds:
- [x] Keyboard and mouse handling on the frontend
- [x] Video and audio streaming from the backend to the frontend
- [x] Input server that works with Websockets

Update - 17/11
- [ ] Master docker container to run this
- [ ] Steam runtime
- [ ] Entrypoint.sh

---------

Co-authored-by: Kristian Ollikainen <14197772+DatCaptainHorse@users.noreply.github.com>
Co-authored-by: Kristian Ollikainen <DatCaptainHorse@users.noreply.github.com>
This commit is contained in:
Wanjohi
2024-12-08 14:54:56 +03:00
committed by GitHub
parent 5eb21eeadb
commit 379db1c87b
137 changed files with 12737 additions and 5234 deletions

12
packages/scripts/envs.sh Normal file
View File

@@ -0,0 +1,12 @@
#!/bin/bash -e
export XDG_RUNTIME_DIR=/run/user/${UID}/
export WAYLAND_DISPLAY=wayland-0
export DISPLAY=:0
export $(dbus-launch)
# Fixes freezing issue
export PROTON_NO_FSYNC=1
# Our preferred prefix
export WINEPREFIX=${USER_HOME}/.nestripfx/

View File

@@ -0,0 +1,277 @@
#!/bin/bash -e
# Various helper functions for handling available GPUs
declare -ga gpu_map
declare -gA gpu_bus_map
declare -gA gpu_card_map
declare -gA gpu_product_map
declare -gA vendor_index_map
declare -gA vendor_full_map
# Map to help get shorter vendor identifiers
declare -A vendor_keywords=(
["advanced micro devices"]='amd'
["ati"]='amd'
["amd"]='amd'
["radeon"]='amd'
["nvidia"]='nvidia'
["intel"]='intel'
)
get_gpu_info() {
# Clear out previous data
gpu_map=()
gpu_bus_map=()
gpu_card_map=()
gpu_product_map=()
vendor_index_map=()
vendor_full_map=()
local vendor=""
local product=""
local bus_info=""
local vendor_full=""
while read -r line; do
line="${line##*( )}"
if [[ "${line,,}" =~ "vendor:" ]]; then
vendor=""
vendor_full=$(echo "$line" | awk '{$1=""; print $0}' | xargs)
# Look for short vendor keyword in line
for keyword in "${!vendor_keywords[@]}"; do
if [[ "${line,,}" == *"$keyword"* ]]; then
vendor="${vendor_keywords[$keyword]}"
break
fi
done
# If no vendor keywords match, use first word
if [[ -z "$vendor" ]]; then
vendor=$(echo "$vendor_full" | awk '{print tolower($1)}')
fi
elif [[ "${line,,}" =~ "product:" ]]; then
product=$(echo "$line" | awk '{$1=""; print $0}' | xargs)
elif [[ "${line,,}" =~ "bus info:" ]]; then
bus_info=$(echo "$line" | awk '{print $3}')
fi
if [[ -n "$vendor" && -n "$product" && -n "$bus_info" && ! "${line,,}" =~ \*"-display" ]]; then
# We have gathered all GPU info necessary, store it
# Check if vendor index is being tracked
if [[ -z "${vendor_index_map[$vendor]}" ]]; then
# Start new vendor index tracking
vendor_index_map[$vendor]=0
else
# Another GPU of same vendor, increment index
vendor_index_map[$vendor]="$((vendor_index_map[$vendor] + 1))"
fi
# Resolved GPU index
local gpu_index="${vendor_index_map[$vendor]}"
local gpu_key="$vendor:$gpu_index"
# Get /dev/dri/cardN of GPU
local gpu_card=$({ ls -1d /sys/bus/pci/devices/*${bus_info#pci@}/drm/*; } 2>&1 | grep card* | grep -oP '(?<=card)\d+')
# Store info in maps
gpu_map+=("$gpu_key")
gpu_bus_map["$gpu_key"]="$bus_info"
gpu_product_map["$gpu_key"]="$product"
vendor_full_map["$gpu_key"]="$vendor_full"
if [[ -n "$gpu_card" ]]; then
gpu_card_map["$gpu_key"]="$gpu_card"
fi
# Clear values for additional GPUs
vendor=""
product=""
bus_info=""
vendor_full=""
fi
if [[ "${line,,}" =~ \*"-display" ]]; then
# New GPU found before storing, clear incomplete values to prevent mixing
vendor=""
product=""
bus_info=""
vendor_full=""
fi
done < <(sudo lshw -c video)
}
check_and_populate_gpus() {
if [[ "${#gpu_map[@]}" -eq 0 ]]; then
get_gpu_info # Gather info incase info not gathered yet
if [[ "${#gpu_map[@]}" -eq 0 ]]; then
echo "No GPUs found on this system" >&2
return 1
fi
fi
}
check_selected_gpu() {
local selected_gpu="${1,,}"
if [[ ! " ${gpu_map[*]} " =~ " $selected_gpu " ]]; then
echo "No such GPU: '$selected_gpu'" >&2
return 1
fi
echo "$selected_gpu"
}
list_available_gpus() {
if ! check_and_populate_gpus; then
return 1
fi
echo "Available GPUs:" >&2
for gpu in "${gpu_map[@]}"; do
echo " [$gpu] \"${gpu_product_map[$gpu]}\" @[${gpu_bus_map[$gpu]}]"
done
}
convert_bus_id_to_xorg() {
local bus_info="$1"
IFS=":." read -ra bus_parts <<< "${bus_info#pci@????:}" # Remove "pci@" and the following 4 characters (domain)
# Check if bus_info has the correct format (at least 3 parts after removing domain)
if [[ "${#bus_parts[@]}" -lt 3 ]]; then
echo "Invalid bus info format: $bus_info" >&2
return 1
fi
# Convert each part from hexadecimal to decimal
bus_info_xorg="PCI:"
for part in "${bus_parts[@]}"; do
bus_info_xorg+="$((16#$part)):"
done
bus_info_xorg="${bus_info_xorg%:}" # Remove the trailing colon
echo "$bus_info_xorg"
}
print_gpu_info() {
if ! check_and_populate_gpus; then
return 1
fi
local selected_gpu
if ! selected_gpu=$(check_selected_gpu "$1"); then
return 1
fi
echo "[$selected_gpu]"
echo " Vendor: ${vendor_full_map[$selected_gpu]}"
echo " Product: ${gpu_product_map[$selected_gpu]}"
echo " Bus: ${gpu_bus_map[$selected_gpu]}"
# Check if card path was found
if [[ "${gpu_card_map[$selected_gpu]}" ]]; then
echo " Card: /dev/dri/card${gpu_card_map[$selected_gpu]}"
fi
echo
}
get_gpu_vendor() {
if ! check_and_populate_gpus; then
return 1
fi
local selected_gpu
if ! selected_gpu=$(check_selected_gpu "$1"); then
return 1
fi
echo "${selected_gpu%%:*}"
}
get_gpu_vendor_full() {
if ! check_and_populate_gpus; then
return 1
fi
local selected_gpu
if ! selected_gpu=$(check_selected_gpu "$1"); then
return 1
fi
echo "${vendor_full_map[$selected_gpu]}"
}
get_gpu_index() {
if ! check_and_populate_gpus; then
return 1
fi
local selected_gpu
if ! selected_gpu=$(check_selected_gpu "$1"); then
return 1
fi
echo "${selected_gpu#*:}"
}
get_gpu_product() {
if ! check_and_populate_gpus; then
return 1
fi
local selected_gpu
if ! selected_gpu=$(check_selected_gpu "$1"); then
return 1
fi
echo "${gpu_product_map[$selected_gpu]}"
}
get_gpu_bus() {
if ! check_and_populate_gpus; then
return 1
fi
local selected_gpu
if ! selected_gpu=$(check_selected_gpu "$1"); then
return 1
fi
echo "${gpu_bus_map[$selected_gpu]}"
}
get_gpu_bus_xorg() {
if ! check_and_populate_gpus; then
return 1
fi
local selected_gpu
if ! selected_gpu=$(check_selected_gpu "$1"); then
return 1
fi
echo $(convert_bus_id_to_xorg "${gpu_bus_map[$selected_gpu]}")
}
get_gpu_card() {
if ! check_and_populate_gpus; then
return 1
fi
local selected_gpu
if ! selected_gpu=$(check_selected_gpu "$1"); then
return 1
fi
# Check if card path was found
if [[ -z "${gpu_card_map[$selected_gpu]}" ]]; then
echo "No card device found for GPU: $selected_gpu" >&2
return 1
fi
echo "/dev/dri/card${gpu_card_map[$selected_gpu]}"
}