67 lines
2.2 KiB
C#
67 lines
2.2 KiB
C#
using System.Collections.Concurrent;
|
|
using ErsatzTV.Core.Domain;
|
|
using ErsatzTV.Core.Interfaces.Streaming;
|
|
|
|
namespace ErsatzTV.Core.Streaming;
|
|
|
|
public class DirectStreamSessionTracker : IDirectStreamSessionTracker
|
|
{
|
|
private readonly ConcurrentDictionary<string, ConcurrentDictionary<Guid, DirectStreamSession>> _sessions = new();
|
|
|
|
public IDisposable Register(string channelNumber, StreamingMode streamingMode)
|
|
{
|
|
var session = new DirectStreamSession(Guid.NewGuid(), channelNumber, streamingMode, DateTimeOffset.Now);
|
|
|
|
ConcurrentDictionary<Guid, DirectStreamSession> channelSessions =
|
|
_sessions.GetOrAdd(channelNumber, _ => new ConcurrentDictionary<Guid, DirectStreamSession>());
|
|
|
|
OnRegisteringSession();
|
|
|
|
channelSessions.TryAdd(session.Id, session);
|
|
|
|
return new Registration(this, session);
|
|
}
|
|
|
|
protected virtual void OnRegisteringSession()
|
|
{
|
|
}
|
|
|
|
public bool IsActive(string channelNumber) => GetViewerCount(channelNumber) > 0;
|
|
|
|
public int GetViewerCount(string channelNumber) =>
|
|
_sessions.TryGetValue(channelNumber, out ConcurrentDictionary<Guid, DirectStreamSession> channelSessions)
|
|
? channelSessions.Count
|
|
: 0;
|
|
|
|
public IReadOnlyCollection<DirectStreamSession> GetActiveSessions() =>
|
|
_sessions.Values.SelectMany(s => s.Values).ToList();
|
|
|
|
public IReadOnlyCollection<DirectStreamSession> GetActiveSessions(string channelNumber) =>
|
|
_sessions.TryGetValue(channelNumber, out ConcurrentDictionary<Guid, DirectStreamSession> channelSessions)
|
|
? channelSessions.Values.ToList()
|
|
: [];
|
|
|
|
private void Remove(DirectStreamSession session)
|
|
{
|
|
if (!_sessions.TryGetValue(session.ChannelNumber, out ConcurrentDictionary<Guid, DirectStreamSession> channelSessions))
|
|
{
|
|
return;
|
|
}
|
|
|
|
channelSessions.TryRemove(session.Id, out _);
|
|
}
|
|
|
|
private sealed class Registration(DirectStreamSessionTracker tracker, DirectStreamSession session) : IDisposable
|
|
{
|
|
private int _disposed;
|
|
|
|
public void Dispose()
|
|
{
|
|
if (Interlocked.Exchange(ref _disposed, 1) == 0)
|
|
{
|
|
tracker.Remove(session);
|
|
}
|
|
}
|
|
}
|
|
}
|