-
Notifications
You must be signed in to change notification settings - Fork 2
Getting Started
Chris edited this page Jan 29, 2026
·
2 revisions
This guide will get you connected to a Sendspin server in about 5 minutes. We'll start with a simple console app that discovers servers and logs track changes - no audio playback yet.
dotnet new console -n MyFirstPlayer
cd MyFirstPlayerdotnet add package Sendspin.SDK
dotnet add package Microsoft.Extensions.Logging.ConsoleReplace Program.cs with:
using Microsoft.Extensions.Logging;
using Sendspin.SDK.Client;
using Sendspin.SDK.Connection;
using Sendspin.SDK.Discovery;
using Sendspin.SDK.Synchronization;
// Set up logging
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConsole();
builder.SetMinimumLevel(LogLevel.Information);
});
var logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Starting Sendspin player...");
// Step 1: Discover servers via mDNS
var discovery = new MdnsServerDiscovery(loggerFactory.CreateLogger<MdnsServerDiscovery>());
discovery.ServerFound += (sender, server) =>
logger.LogInformation("Found server: {Name} at {Uri}", server.Name, server.GetWebSocketUri());
discovery.ServerLost += (sender, server) =>
logger.LogInformation("Lost server: {Name}", server.Name);
await discovery.StartAsync();
logger.LogInformation("Scanning for servers (5 seconds)...");
await Task.Delay(5000);
var servers = discovery.Servers.ToList();
if (servers.Count == 0)
{
logger.LogError("No Sendspin servers found. Is Music Assistant running?");
return;
}
// Step 2: Connect to the first server
var serverUri = servers.First().GetWebSocketUri();
logger.LogInformation("Connecting to {Uri}...", serverUri);
var connection = new SendspinConnection(loggerFactory.CreateLogger<SendspinConnection>());
var clockSync = new KalmanClockSynchronizer(loggerFactory.CreateLogger<KalmanClockSynchronizer>());
var capabilities = new ClientCapabilities
{
ClientName = "My First Player",
ProductName = "Tutorial Player",
Manufacturer = "Me",
SoftwareVersion = "1.0.0"
};
var client = new SendspinClientService(
loggerFactory.CreateLogger<SendspinClientService>(),
connection,
clockSync,
capabilities
);
// Step 3: Handle events
client.ConnectionStateChanged += (sender, state) =>
logger.LogInformation("Connection state: {State}", state);
client.GroupStateChanged += (sender, group) =>
{
var meta = group.Metadata;
if (meta != null)
{
logger.LogInformation("Now playing: {Title} by {Artist}",
meta.Title ?? "Unknown",
meta.Artist ?? "Unknown");
}
logger.LogInformation("Playback state: {State}, Volume: {Volume}",
group.PlaybackState, group.Volume);
};
client.ClockSyncConverged += (sender, status) =>
logger.LogInformation("Clock sync converged! Offset: {Offset:F2}ms",
status.OffsetMicroseconds / 1000.0);
// Step 4: Connect!
await client.ConnectAsync(serverUri);
logger.LogInformation("Connected to {ServerName}!", client.ServerName);
// Keep running
logger.LogInformation("Press Enter to disconnect...");
Console.ReadLine();
await client.DisconnectAsync();
await discovery.StopAsync();
logger.LogInformation("Disconnected. Goodbye!");dotnet runinfo: Program[0]
Starting Sendspin player...
info: Program[0]
Scanning for servers (5 seconds)...
info: Program[0]
Found server: Music Assistant at ws://192.168.1.100:8927/sendspin
info: Program[0]
Connecting to ws://192.168.1.100:8927/sendspin...
info: Program[0]
Connection state: Connected
info: Program[0]
Clock sync converged! Offset: 1234567.89ms
info: Program[0]
Connected to Music Assistant!
info: Program[0]
Now playing: Bohemian Rhapsody by Queen
info: Program[0]
Playback state: Playing, Volume: 75
Note: The large clock offset (millions of ms) is normal - the server uses monotonic time starting near 0, while we use Unix epoch time. The Kalman filter handles this difference.
-
mDNS Discovery -
MdnsServerDiscoveryscanned the network for_sendspin-server._tcpservices -
WebSocket Connection -
SendspinConnectionestablished a WebSocket to the server -
Handshake -
SendspinClientServicesentclient/hellowith our capabilities -
Clock Sync -
KalmanClockSynchronizerexchanged timing messages to synchronize clocks -
Group State - Server sent
group/updatewith current playback state and metadata
- Check your server - Is Music Assistant running with Sendspin enabled?
- Same network - Are you on the same subnet as the server?
- Firewall - mDNS uses UDP port 5353. Ensure it's not blocked.
- Try manual connection - Skip discovery and connect directly:
// Instead of discovery, connect directly:
var serverUri = new Uri("ws://192.168.1.100:8927/sendspin");
await client.ConnectAsync(serverUri);-
Check the URL - Default port is 8927, path is
/sendspin - Firewall - Ensure TCP port 8927 is open
- Server logs - Check Music Assistant logs for errors
- This usually indicates network issues (high latency/packet loss)
- The SDK will still work, but sync accuracy may be reduced
- Check for network congestion or Wi-Fi interference
You've successfully connected to a Sendspin server! But there's no audio yet. In the next section, we'll implement IAudioPlayer and wire up the full audio pipeline.
Next: Building a Minimal Player - Add audio playback with sync correction