135 lines
6.6 KiB
PowerShell
135 lines
6.6 KiB
PowerShell
# Dependency setup is kept separate from the process supervisor. Nothing is
|
|
# downloaded or installed when all configured executables already exist.
|
|
$script:depsProjectRoot = $PSScriptRoot
|
|
$script:depsManifest = Get-Content -LiteralPath (Join-Path $PSScriptRoot 'dependencies.json') -Raw | ConvertFrom-Json
|
|
$script:depsDownloadDir = Join-Path $PSScriptRoot '.runtime\downloads'
|
|
$script:depsInstallDir = Join-Path $PSScriptRoot '.deps'
|
|
|
|
function Test-JackPaths($config) {
|
|
return (Test-Path -LiteralPath $config.jackd -PathType Leaf) -and
|
|
(Test-Path -LiteralPath (Join-Path $config.jackTools 'jack_lsp.exe') -PathType Leaf) -and
|
|
(Test-Path -LiteralPath (Join-Path $config.jackTools 'jack_connect.exe') -PathType Leaf)
|
|
}
|
|
|
|
function Test-JackRouter {
|
|
return (Test-Path -LiteralPath 'HKLM:\SOFTWARE\ASIO\JackRouter') -and
|
|
(Test-Path -LiteralPath 'HKLM:\SOFTWARE\WOW6432Node\ASIO\JackRouter')
|
|
}
|
|
|
|
function Use-DefaultJackPaths($config) {
|
|
$candidate = 'C:\Program Files\JACK2'
|
|
if (-not (Test-Path -LiteralPath (Join-Path $candidate 'jackd.exe'))) {
|
|
$location = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\JACK' -Name Location -ErrorAction SilentlyContinue).Location
|
|
if ($location) {
|
|
$candidate = if ($location -like '*.exe') { Split-Path -Path $location -Parent } else { $location }
|
|
}
|
|
}
|
|
$config.jackd = Join-Path $candidate 'jackd.exe'
|
|
$config.jackTools = Join-Path $candidate 'tools'
|
|
}
|
|
|
|
function Get-PinnedDownload($asset) {
|
|
New-Item -ItemType Directory -Force -Path $script:depsDownloadDir | Out-Null
|
|
$destination = Join-Path $script:depsDownloadDir $asset.file
|
|
if (Test-Path -LiteralPath $destination) {
|
|
$existingHash = (Get-FileHash -LiteralPath $destination -Algorithm SHA256).Hash
|
|
if ($existingHash -ieq $asset.sha256) { return $destination }
|
|
Write-Warning "Cached $($asset.file) failed SHA-256 verification; downloading it again."
|
|
Remove-Item -LiteralPath $destination
|
|
}
|
|
$partial = "$destination.partial"
|
|
Remove-Item -LiteralPath $partial -ErrorAction SilentlyContinue
|
|
Write-Host "Downloading $($asset.file) from $($asset.url)"
|
|
try {
|
|
Invoke-WebRequest -Uri $asset.url -OutFile $partial -UseBasicParsing
|
|
$actual = (Get-FileHash -LiteralPath $partial -Algorithm SHA256).Hash
|
|
if ($actual -ine $asset.sha256) { throw "SHA-256 mismatch for $($asset.file): got $actual" }
|
|
Move-Item -LiteralPath $partial -Destination $destination
|
|
return $destination
|
|
} finally {
|
|
Remove-Item -LiteralPath $partial -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
|
|
function Assert-DependencyPath([string]$path) {
|
|
$base = [System.IO.Path]::GetFullPath($script:depsInstallDir).TrimEnd('\') + '\'
|
|
$target = [System.IO.Path]::GetFullPath($path)
|
|
if (-not $target.StartsWith($base, [StringComparison]::OrdinalIgnoreCase)) {
|
|
throw "Refusing to modify directory outside .deps: $target"
|
|
}
|
|
return $target
|
|
}
|
|
|
|
function Remove-DependencyStaging([string]$path) {
|
|
$target = Assert-DependencyPath $path
|
|
if (Test-Path -LiteralPath $target) { Remove-Item -LiteralPath $target -Recurse -Force }
|
|
}
|
|
|
|
function Get-ManagedJackTrip {
|
|
$folder = Join-Path $script:depsInstallDir "JackTrip-v$($script:depsManifest.jacktrip.version)-Windows-x64"
|
|
if (-not (Test-Path -LiteralPath $folder)) { return $null }
|
|
$exe = Get-ChildItem -LiteralPath $folder -Recurse -File -Filter 'jacktrip.exe' | Select-Object -First 1
|
|
if ($exe) { return $exe.FullName }
|
|
return $null
|
|
}
|
|
|
|
function Install-ManagedJackTrip {
|
|
$asset = $script:depsManifest.jacktrip
|
|
$archive = Get-PinnedDownload $asset
|
|
New-Item -ItemType Directory -Force -Path $script:depsInstallDir | Out-Null
|
|
$folder = Assert-DependencyPath (Join-Path $script:depsInstallDir "JackTrip-v$($asset.version)-Windows-x64")
|
|
$staging = Assert-DependencyPath (Join-Path $script:depsInstallDir ('.staging-' + [guid]::NewGuid().ToString('n')))
|
|
try {
|
|
Expand-Archive -LiteralPath $archive -DestinationPath $staging
|
|
$exe = Get-ChildItem -LiteralPath $staging -Recurse -File -Filter 'jacktrip.exe' | Select-Object -First 1
|
|
if (-not $exe) { throw 'Verified JackTrip archive did not contain jacktrip.exe' }
|
|
if (Test-Path -LiteralPath $folder) { Remove-DependencyStaging $folder }
|
|
Move-Item -LiteralPath $staging -Destination $folder
|
|
} finally {
|
|
Remove-DependencyStaging $staging
|
|
}
|
|
return Get-ManagedJackTrip
|
|
}
|
|
|
|
function Resolve-AudioDependencies($config, [bool]$allowDownload, [bool]$interactive) {
|
|
if (-not (Test-Path -LiteralPath $config.bridge -PathType Leaf)) {
|
|
$defaultBridge = 'C:\Program Files (x86)\VB\ASIOBridge\VBCABLE_AsioBridge.exe'
|
|
if (Test-Path -LiteralPath $defaultBridge -PathType Leaf) { $config.bridge = $defaultBridge }
|
|
}
|
|
if (-not (Test-Path -LiteralPath $config.bridge -PathType Leaf)) {
|
|
Write-Warning 'Hi-Fi Cable / ASIO Bridge is missing. Download and install it as administrator, then reboot Windows.'
|
|
if ($interactive) {
|
|
$answer = Read-Host 'Open the official VB-Audio download page now? [y/N]'
|
|
if ($answer -match '^(y|yes)$') { Start-Process $script:depsManifest.hifiPage }
|
|
}
|
|
throw "Hi-Fi Cable installation required: $($script:depsManifest.hifiPage)"
|
|
}
|
|
|
|
if (-not (Test-JackPaths $config)) { Use-DefaultJackPaths $config }
|
|
if (-not (Test-JackPaths $config) -or -not (Test-JackRouter)) {
|
|
if (-not $allowDownload) { throw 'JACK or JACK Router is missing. Run .\audio.ps1 setup in an interactive PowerShell window.' }
|
|
$installer = Get-PinnedDownload $script:depsManifest.jack
|
|
if ($interactive) {
|
|
$answer = Read-Host "JACK or JACK Router is missing. Run its installer ($installer) now? [y/N]"
|
|
if ($answer -match '^(y|yes)$') {
|
|
Start-Process -FilePath $installer -Verb RunAs -Wait
|
|
Use-DefaultJackPaths $config
|
|
}
|
|
}
|
|
if (-not (Test-JackPaths $config) -or -not (Test-JackRouter)) {
|
|
throw "Install JACK with Full installation (with JACK-Router) from $installer, then run setup again."
|
|
}
|
|
}
|
|
|
|
if (-not (Test-Path -LiteralPath $config.jacktrip -PathType Leaf)) {
|
|
$managed = Get-ManagedJackTrip
|
|
if (-not $managed) {
|
|
if (-not $allowDownload) { throw 'JackTrip is missing. Run .\audio.ps1 setup first.' }
|
|
$managed = Install-ManagedJackTrip
|
|
}
|
|
$config.jacktrip = $managed
|
|
}
|
|
if (-not (Test-Path -LiteralPath $config.jacktrip -PathType Leaf)) { throw 'JackTrip is still missing after setup.' }
|
|
return $config
|
|
}
|