Skip to content

Enable headless/library usage of sldl#164

Merged
fiso64 merged 6 commits intofiso64:masterfrom
markst:dev/headless
Mar 24, 2026
Merged

Enable headless/library usage of sldl#164
fiso64 merged 6 commits intofiso64:masterfrom
markst:dev/headless

Conversation

@markst
Copy link
Copy Markdown

@markst markst commented Mar 24, 2026

This PR makes it possible to use sldl as an in-process library (e.g. from an ASP.NET host) rather than only as a standalone CLI tool.

Changes

IProgressReporter interface — New callback interface (IProgressReporter) that receives track list, download progress, track state changes, and job completion events. Integrated into Searcher and Downloader. A NullProgressReporter is used by default so existing CLI behavior is unchanged. Also includes a JsonStreamProgressReporter implementation for structured output.

Remove Environment.Exit() calls — All 8 Environment.Exit() calls across Spotify.cs, MusicBrainz.cs, Config.cs, and Help.cs are replaced with thrown exceptions (for errors) or early returns (for --help/--version). This prevents the host process from being killed when sldl encounters an error.

Public Cancel() on DownloaderApplication — Exposes the internal appCts cancellation token so callers can stop a running download.

Logger.SetConsoleLogLevel tolerance — Uses FirstOrDefault instead of First so it doesn't throw when no console output is configured (library consumers may not call Logger.AddConsole()).

Headless supportProgram class made internal to avoid conflicts with the host app's entry point. Added --no-listen flag that sets listenPort = null, which creates the Soulseek client with enableListener: false to avoid port bind failures in server environments.

net8.0 — Target framework upgraded from net6.0 to net8.0.

Motivation

I'm building a web UI (slsk-batchdl-gui) that calls DownloaderApplication.RunAsync() directly from a Blazor Server app. These changes were the minimum needed to make that work without forking the entire codebase.

Backward compatibility

  • CLI behavior is unchanged — NullProgressReporter is the default, Program is still the entry point when built standalone, and Environment.Exit replacements throw the same errors that would have been fatal anyway.
  • The --no-listen flag is opt-in.
  • net8.0 is the only breaking change (drops net6.0 support).

GitHub Copilot added 6 commits March 24, 2026 18:42
When no console output is configured (e.g. when used as a library),
OutputConfigs has no matching element, causing .First() to throw
InvalidOperationException. Use FirstOrDefault with a null check instead.
Expose the internal appCts cancellation token so callers using sldl
as a library can cancel a running download job.
Environment.Exit() kills the entire hosting process when sldl is used
as a library. Replace error exits with thrown exceptions (caught by the
caller) and help/version exits with early returns.
Add IProgressReporter with hooks for track list, download progress,
track state changes, overall progress, and job completion. Integrate
callbacks into Searcher and Downloader services.
- Upgrade target framework from net6.0 to net8.0
- Make Program class internal to avoid conflicts with host app
- Add --no-listen flag and enableListener:false support to avoid
  port bind failures when used as a library
@fiso64
Copy link
Copy Markdown
Owner

fiso64 commented Mar 24, 2026

Good stuff! I was planning to add a server mode that would expose an http API, but this is quicker if the gui is .net based (besides these changes would be needed either way). Thanks.

@fiso64 fiso64 merged commit 9adf504 into fiso64:master Mar 24, 2026
0 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants