first commit

This commit is contained in:
Patrick
2026-05-01 18:48:36 +02:00
commit f23d5afaa3
6 changed files with 468 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
$DefaultName = "winniepc"
+201
View File
@@ -0,0 +1,201 @@
param(
[string]$Distro = "Ubuntu"
)
$ErrorActionPreference = "Stop"
function Write-Info {
param([string]$Message)
Write-Host $Message
}
function Ensure-WslInstalled {
if (-not (Get-Command wsl.exe -ErrorAction SilentlyContinue)) {
Write-Warning "WSL is not installed. Install it with: wsl --install -d $Distro"
throw "WSL is required."
}
}
function Ensure-WslDistro {
$distros = @()
try {
$distros = wsl -l -q 2>$null
} catch {
$distros = @()
}
if (-not $distros -or ($distros -notcontains $Distro)) {
Write-Warning "WSL distro '$Distro' is not installed. Install it with: wsl --install -d $Distro"
throw "WSL distro not found."
}
}
function Ensure-WslConfig {
$configPath = Join-Path $env:USERPROFILE ".wslconfig"
$lines = [System.Collections.Generic.List[string]]::new()
if (Test-Path $configPath) {
$content = Get-Content -Path $configPath -ErrorAction SilentlyContinue
foreach ($line in $content) {
$null = $lines.Add([string]$line)
}
}
$wsl2Index = $lines.FindIndex({ param($l) $l -match '^\s*\[wsl2\]\s*$' })
if ($wsl2Index -lt 0) {
if ($lines.Count -gt 0 -and $lines[$lines.Count - 1] -ne "") {
$lines.Add("")
}
$lines.Add("[wsl2]")
$lines.Add("networkingMode=mirrored")
$lines.Add("guiApplications=true")
} else {
$blockEnd = $lines.Count
for ($i = $wsl2Index + 1; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match '^\s*\[.+\]\s*$') {
$blockEnd = $i
break
}
}
$netIndex = -1
$guiIndex = -1
for ($i = $wsl2Index + 1; $i -lt $blockEnd; $i++) {
if ($lines[$i] -match '^\s*networkingMode=') { $netIndex = $i }
if ($lines[$i] -match '^\s*guiApplications=') { $guiIndex = $i }
}
if ($netIndex -ge 0) {
$lines[$netIndex] = "networkingMode=mirrored"
} else {
$lines.Insert($blockEnd, "networkingMode=mirrored")
$blockEnd++
}
if ($guiIndex -ge 0) {
$lines[$guiIndex] = "guiApplications=true"
} else {
$lines.Insert($blockEnd, "guiApplications=true")
}
}
Set-Content -Path $configPath -Value $lines -Encoding ASCII
}
function New-StartMenuShortcut {
param(
[string]$ShortcutName,
[string]$ScriptPath,
[string]$WorkingDirectory
)
$startMenuDir = Join-Path $env:APPDATA "Microsoft\Windows\Start Menu\Programs"
$shortcutPath = Join-Path $startMenuDir "$ShortcutName.lnk"
$iconPath = Join-Path $env:SystemRoot "System32\imageres.dll"
$shell = New-Object -ComObject WScript.Shell
$shortcut = $shell.CreateShortcut($shortcutPath)
$shortcut.TargetPath = (Get-Command powershell.exe).Source
$shortcut.Arguments = "-NoProfile -ExecutionPolicy Bypass -File `"$ScriptPath`""
$shortcut.WorkingDirectory = $WorkingDirectory
$shortcut.IconLocation = "$iconPath,15"
$shortcut.WindowStyle = 1
$shortcut.Save()
}
function Test-IsAdmin {
$current = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal($current)
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
function Add-FirewallRules {
$rulePrefix = "ScreenShare AirPlay"
New-NetFirewallRule -DisplayName "$rulePrefix TCP" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 35000-35002 | Out-Null
New-NetFirewallRule -DisplayName "$rulePrefix UDP" -Direction Inbound -Action Allow -Protocol UDP -LocalPort 35000-35002 | Out-Null
New-NetFirewallRule -DisplayName "$rulePrefix mDNS" -Direction Inbound -Action Allow -Protocol UDP -LocalPort 5353 | Out-Null
}
function Write-Config {
param(
[string]$ConfigPath,
[string]$DefaultName
)
$lines = @()
if (-not [string]::IsNullOrWhiteSpace($DefaultName)) {
$safeName = $DefaultName.Replace('"', '`"')
$lines += "`$DefaultName = `"$safeName`""
}
Set-Content -Path $ConfigPath -Value $lines -Encoding ASCII
}
Ensure-WslInstalled
Ensure-WslDistro
Write-Info "Updating .wslconfig to enable mirrored networking and GUI apps..."
Ensure-WslConfig
$repoRoot = Resolve-Path (Join-Path $PSScriptRoot "..")
$wslScriptWindows = Resolve-Path (Join-Path $repoRoot "wsl\setup-uxplay.sh")
$wslScriptWindowsPath = $wslScriptWindows.Path
$wslScriptWindowsForWsl = $wslScriptWindowsPath -replace "\\", "/"
$wslScriptLinux = (wsl -d $Distro -- wslpath -a "$wslScriptWindowsForWsl" 2>$null)
if (-not $wslScriptLinux) {
throw "Failed to resolve WSL path for setup script: $wslScriptWindowsPath"
}
$wslScriptLinux = $wslScriptLinux.Trim()
Write-Info "Running WSL setup script..."
$bashCmd = "chmod +x '$wslScriptLinux'; '$wslScriptLinux'"
& wsl -d $Distro -- bash -lc $bashCmd
Write-Info "Restarting WSL to apply systemd and networking changes..."
& wsl --shutdown
Write-Info "Attempting to enable Avahi after restart (may prompt for sudo password)..."
$enableCmd = "if command -v systemctl >/dev/null 2>&1; then sudo systemctl enable --now avahi-daemon; else echo 'systemctl not available'; fi"
& wsl -d $Distro -- bash -lc $enableCmd
$startScriptPath = Resolve-Path (Join-Path $repoRoot "scripts\start-airplay.ps1")
$startShortcutName = "ScreenShare"
$prompt = "Create Start Menu shortcut for $startShortcutName? (Y/N) [Y]"
$response = Read-Host $prompt
if ([string]::IsNullOrWhiteSpace($response) -or $response -match '^[Yy]') {
New-StartMenuShortcut -ShortcutName $startShortcutName -ScriptPath $startScriptPath.Path -WorkingDirectory $repoRoot.Path
Write-Info "Start Menu shortcut created: $startShortcutName"
} else {
Write-Info "Skipped Start Menu shortcut."
}
$firewallPrompt = "Add Windows Firewall rules for ports 35000-35002 and 5353? (Y/N) [Y]"
$firewallResponse = Read-Host $firewallPrompt
if ([string]::IsNullOrWhiteSpace($firewallResponse) -or $firewallResponse -match '^[Yy]') {
if (Test-IsAdmin) {
Add-FirewallRules
Write-Info "Firewall rules added."
} else {
Write-Info "Skipping firewall rules (requires an elevated PowerShell)."
}
} else {
Write-Info "Skipped firewall rules."
}
$configPath = Join-Path $repoRoot "scripts\config.ps1"
$namePrompt = "Set default AirPlay name? (Y/N) [Y]"
$nameResponse = Read-Host $namePrompt
if ([string]::IsNullOrWhiteSpace($nameResponse) -or $nameResponse -match '^[Yy]') {
$defaultName = Read-Host "Default name (blank keeps ScreenShare)"
if ([string]::IsNullOrWhiteSpace($defaultName)) {
$defaultName = "ScreenShare"
}
Write-Config -ConfigPath $configPath -DefaultName $defaultName
Write-Info "Default name set to: $defaultName"
} else {
Write-Info "Skipped default name configuration."
}
Write-Info "Setup complete. You can now run scripts\\start-airplay.ps1"
+161
View File
@@ -0,0 +1,161 @@
param(
[string]$Distro = "Ubuntu",
[string]$Name = "ScreenShare",
[switch]$NoHostSuffix,
[switch]$LowLatency,
[switch]$UseVsync,
[switch]$HardwareDecode,
[switch]$SoftwareDecode,
[string]$VideoSink = "gtksink",
[switch]$AutoVideo,
[int]$PortBase = 35000,
[switch]$Quiet,
[string]$LogPath = ""
)
$ErrorActionPreference = "Stop"
$configPath = Join-Path $PSScriptRoot "config.ps1"
if (Test-Path $configPath) {
try {
. $configPath
} catch {
}
}
if (-not $PSBoundParameters.ContainsKey("Name") -and $DefaultName) {
$Name = $DefaultName
}
if ([string]::IsNullOrWhiteSpace($Name)) {
$Name = "ScreenShare"
}
function Reset-OutputCursor {
try {
if ([Console]::CursorLeft -ne 0) {
[Console]::WriteLine("")
}
[Console]::CursorLeft = 0
} catch {
try {
$pos = $Host.UI.RawUI.CursorPosition
if ($pos.X -ne 0) {
Write-Host ""
}
$Host.UI.RawUI.CursorPosition = New-Object Management.Automation.Host.Coordinates 0 $Host.UI.RawUI.CursorPosition.Y
} catch {
Write-Host ""
}
}
}
try {
if ($Host.UI.RawUI.CursorPosition.X -ne 0) {
Write-Host ""
}
} catch {
}
if (-not (Get-Command wsl.exe -ErrorAction SilentlyContinue)) {
throw "WSL is not installed. Run scripts\\setup-wsl-airplay.ps1 first."
}
$distros = @()
try {
$distros = wsl -l -q 2>$null
} catch {
$distros = @()
}
if (-not $distros -or ($distros -notcontains $Distro)) {
throw "WSL distro '$Distro' not found. Run scripts\\setup-wsl-airplay.ps1 first."
}
$uxplayPath = (wsl -d $Distro -- bash -lc "command -v uxplay" 2>$null).Trim()
if (-not $uxplayPath) {
throw "UxPlay is not installed in WSL. Run scripts\\setup-wsl-airplay.ps1 first."
}
if ($PortBase -ne 0) {
if ($PortBase -lt 1024 -or $PortBase -gt 65533) {
throw "PortBase must be between 1024 and 65533."
}
}
$escapedName = $Name -replace '"', '\\"'
$cmd = "uxplay -n `"$escapedName`""
if ($NoHostSuffix) {
$cmd += " -nh"
}
$useLowLatency = $true
if ($UseVsync) {
$useLowLatency = $false
}
if ($LowLatency) {
$useLowLatency = $true
}
$useHardwareDecode = $true
if ($SoftwareDecode) {
$useHardwareDecode = $false
}
if ($HardwareDecode) {
$useHardwareDecode = $true
}
if (-not $useHardwareDecode) {
$cmd += " -avdec"
}
if ($useLowLatency) {
$cmd += " -vsync no"
}
if (-not $AutoVideo -and $VideoSink) {
$cmd += " -vs $VideoSink"
}
if ($PortBase -ne 0) {
$cmd += " -p $PortBase"
}
Reset-OutputCursor
[Console]::WriteLine("Starting ScreenShare. Logs follow below.")
$redirectLogs = $Quiet
if ($redirectLogs -and [string]::IsNullOrWhiteSpace($LogPath)) {
$LogPath = Join-Path $PSScriptRoot "screenshare.log"
}
$nativePrefSet = $false
$nativePrefValue = $null
if (Get-Variable -Name PSNativeCommandUseErrorActionPreference -ErrorAction SilentlyContinue) {
$nativePrefSet = $true
$nativePrefValue = $PSNativeCommandUseErrorActionPreference
$PSNativeCommandUseErrorActionPreference = $false
}
$savedErrorActionPreference = $ErrorActionPreference
if ($redirectLogs) {
$ErrorActionPreference = "SilentlyContinue"
} else {
$ErrorActionPreference = "Continue"
}
try {
if ($redirectLogs) {
& wsl -d $Distro -- bash -lc $cmd 1>$LogPath 2>&1
Reset-OutputCursor
[Console]::WriteLine("ScreenShare logs written to: $LogPath")
} else {
& wsl -d $Distro -- bash -lc $cmd
}
} finally {
$ErrorActionPreference = $savedErrorActionPreference
if ($nativePrefSet) {
$PSNativeCommandUseErrorActionPreference = $nativePrefValue
}
}