# Vocaluxe (fork at git.disi.dev/Projects/Vocaluxe) Fork of [Vocaluxe/Vocaluxe](https://github.com/Vocaluxe/Vocaluxe), a karaoke game (C#, .NET 10). Default branch `develop` tracks upstream; the fork's own work happens on feature branches. Keep changes to upstream code small and hook-based, so upstream can still be merged. ## Goal of the fork 1. **Song server** (`VocaluxeSongServer/`, in progress): a central song library on the homelab. The game becomes the frontend and downloads song files on demand. See `VocaluxeSongServer/README.md`. 2. Later: serve the guest WebApp ("browse by phone", `WebApp/` + `VocaluxeWeb/`) directly from the server. 3. Search and download songs that aren't in the library (started: server web UI with the sources `free` and `usdb`; next: more sources, UltraSinger to create songs from audio). ## Layout | Folder | What | |---|---| | `Vocaluxe/` | The game. Song server client: `Base/SongServer/` (`CSongServer` sync, `CRemoteSongFileProvider` downloads) | | `VocaluxeLib/` | Shared library. `Songs/CSongFiles.cs` is the hook every song file access goes through | | `VocaluxeSongServer/` | ASP.NET Core server, Docker image `git.disi.dev/projects/vocaluxe-song-server`. `Sources/`: song search and downloads (free CC songs from GitHub, USDB + yt-dlp). `wwwroot/`: mobile web UI (plain JS, no build) | | `VocaluxeWeb/`, `WebApp/` | Built-in webserver of the game and the guest WebApp (Vue), upstream | | `Tests/` | NUnit; song server tests in `Tests/SongServer` | ## How the song server integration works - `CSongs.LoadSongs` calls `CSongServer.Sync()`: fetches `/api/v1/library` (ETag), mirrors the song `.txt` files into `/SongServer/_` (zip bundles), deletes files no longer on the server, and installs `CRemoteSongFileProvider` as `CSongFiles.Provider`. The cache folder is then loaded like a normal song folder. - `CSongFiles.Exists` (loader header checks) is true for files that only exist on the server. `IsLocal` means the file is downloaded and current (size and mtime match the server). - Downloads on demand: covers (`CSong.LoadSmallCover`, background threads, blocking), preview audio (`CBackgroundMusic.LoadPreview` + `Update`), everything before singing (`CScreenSing._LoadAndStartCurrentSong`, progress via `TR_SCREENSING_DOWNLOADING`). Downloads resume from `.part` files with Range requests. - Config: `config.xml` section `SongServer` (`Url`, `ApiKey`). The contracts (`VocaluxeSongServer/Contracts`) are linked into `Vocaluxe.csproj`; the test project references the server with `extern alias songserver`. ## Song server web UI and sources - The web UI is plain HTML/CSS/JS in `VocaluxeSongServer/wwwroot` (no build step, no external requests except cover images). Check it at phone width: headless Edge has a ~500px minimum window, so render the page in a 390px iframe. - USDB can't be tested without an account (search and text download need a login). Its HTML parsing is covered by `Tests/SongServer/CSongSourcesTest.cs`; if USDB changes its HTML, fix `CUsdbSongSource.ParseList` there. ## Build and test (Windows) - `dotnet build Vocaluxe/Vocaluxe.csproj -c DebugWin -p:Platform=x64` (the whole solution also builds the native `PitchTracker`, which needs Visual Studio's C++ tools). - `dotnet test Tests/Tests.csproj -c DebugWin -p:Platform=x64` - Running the game (`Output\Vocaluxe.exe`) without the C++ tools: take `libs/unmanaged/x64/PitchTracker.dll` (and the `Themes/Vocaluxe 2024/*.mp4` videos) from the upstream Nightly zip (github.com/Vocaluxe/Vocaluxe/releases/tag/Nightly, `Vocaluxe_Nightly_Windows_x64.zip`); the PitchTracker source is unchanged in this fork. Both are gitignored. Data and `Config.xml` are in `Output` (non-installer builds). - First start is slow on Windows with Smart App Control: GStreamer (default `PlayBackLib`) scans its 216 plugins once and each unsigned DLL is checked (~19 min on DisiFramework, window "not responding" in "Init Playback"). Later starts are fast. `PortAudio` in `Config.xml` avoids GStreamer. - Building rewrites the copyright year in `Vocaluxe/Properties/AssemblyInfo.cs`; don't commit that. - Don't use `dotnet sln add`: it rewrites the configuration table of `Vocaluxe.sln`. Copy the lines of `VocaluxeWeb`. - New `config.xml` fields must also go into `Tests/VocaluxeLib/XML/TestFiles/SConfig.xml` (round-trip test; CRLF). ## Known gaps (song server) - Cover/background auto-detection (`[CO]`/`[BG]` files without a tag, `CSong._CheckFiles`) only sees local files. - Media in subfolders of a song folder are not served (only the song folder itself). - On Linux clients, media whose name differs in case from the `.txt` reference won't be found after download. - No cache size limit yet. The WebApp's cover images for server songs depend on the cover loader having fetched them. - No in-game UI for the server address yet (only `config.xml`).