Implement syncplay backend

This commit is contained in:
gion
2020-04-01 17:52:42 +02:00
parent ab8a5595f6
commit 10c2c62f07
17 changed files with 1491 additions and 0 deletions

View File

@@ -0,0 +1,148 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Session;
namespace MediaBrowser.Controller.Syncplay
{
/// <summary>
/// Class GroupInfo.
/// </summary>
public class GroupInfo
{
/// <summary>
/// Default ping value used for users.
/// </summary>
public readonly long DefaulPing = 500;
/// <summary>
/// Gets or sets the group identifier.
/// </summary>
/// <value>The group identifier.</value>
public readonly Guid GroupId = Guid.NewGuid();
/// <summary>
/// Gets or sets the playing item.
/// </summary>
/// <value>The playing item.</value>
public BaseItem PlayingItem { get; set; }
/// <summary>
/// Gets or sets whether playback is paused.
/// </summary>
/// <value>Playback is paused.</value>
public bool IsPaused { get; set; }
/// <summary>
/// Gets or sets the position ticks.
/// </summary>
/// <value>The position ticks.</value>
public long PositionTicks { get; set; }
/// <summary>
/// Gets or sets the last activity.
/// </summary>
/// <value>The last activity.</value>
public DateTime LastActivity { get; set; }
/// <summary>
/// Gets the partecipants.
/// </summary>
/// <value>The partecipants.</value>
public readonly ConcurrentDictionary<string, GroupMember> Partecipants =
new ConcurrentDictionary<string, GroupMember>(StringComparer.OrdinalIgnoreCase);
/// <summary>
/// Checks if a user is in this group.
/// </summary>
/// <value><c>true</c> if the user is in this group; <c>false</c> otherwise.</value>
public bool ContainsUser(string sessionId)
{
return Partecipants.ContainsKey(sessionId);
}
/// <summary>
/// Adds the user to the group.
/// </summary>
/// <param name="user">The session.</param>
public void AddUser(SessionInfo user)
{
if (ContainsUser(user.Id.ToString())) return;
var member = new GroupMember();
member.Session = user;
member.Ping = DefaulPing;
member.IsBuffering = false;
Partecipants[user.Id.ToString()] = member;
}
/// <summary>
/// Removes the user from the group.
/// </summary>
/// <param name="user">The session.</param>
public void RemoveUser(SessionInfo user)
{
if (!ContainsUser(user.Id.ToString())) return;
GroupMember member;
Partecipants.Remove(user.Id.ToString(), out member);
}
/// <summary>
/// Updates the ping of a user.
/// </summary>
/// <param name="user">The session.</param>
/// <param name="ping">The ping.</param>
public void UpdatePing(SessionInfo user, long ping)
{
if (!ContainsUser(user.Id.ToString())) return;
Partecipants[user.Id.ToString()].Ping = ping;
}
/// <summary>
/// Gets the highest ping in the group.
/// </summary>
/// <value name="user">The highest ping in the group.</value>
public long GetHighestPing()
{
long max = Int64.MinValue;
foreach (var user in Partecipants.Values)
{
max = Math.Max(max, user.Ping);
}
return max;
}
/// <summary>
/// Sets the user's buffering state.
/// </summary>
/// <param name="user">The session.</param>
/// <param name="isBuffering">The state.</param>
public void SetBuffering(SessionInfo user, bool isBuffering)
{
if (!ContainsUser(user.Id.ToString())) return;
Partecipants[user.Id.ToString()].IsBuffering = isBuffering;
}
/// <summary>
/// Gets the group buffering state.
/// </summary>
/// <value><c>true</c> if there is a user buffering in the group; <c>false</c> otherwise.</value>
public bool IsBuffering()
{
foreach (var user in Partecipants.Values)
{
if (user.IsBuffering) return true;
}
return false;
}
/// <summary>
/// Checks if the group is empty.
/// </summary>
/// <value><c>true</c> if the group is empty; <c>false</c> otherwise.</value>
public bool IsEmpty()
{
return Partecipants.Count == 0;
}
}
}

View File

@@ -0,0 +1,28 @@
using MediaBrowser.Controller.Session;
namespace MediaBrowser.Controller.Syncplay
{
/// <summary>
/// Class GroupMember.
/// </summary>
public class GroupMember
{
/// <summary>
/// Gets or sets whether this member is buffering.
/// </summary>
/// <value><c>true</c> if member is buffering; <c>false</c> otherwise.</value>
public bool IsBuffering { get; set; }
/// <summary>
/// Gets or sets the session.
/// </summary>
/// <value>The session.</value>
public SessionInfo Session { get; set; }
/// <summary>
/// Gets or sets the ping.
/// </summary>
/// <value>The ping.</value>
public long Ping { get; set; }
}
}

View File

@@ -0,0 +1,61 @@
using System;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Syncplay;
namespace MediaBrowser.Controller.Syncplay
{
/// <summary>
/// Interface ISyncplayController.
/// </summary>
public interface ISyncplayController
{
/// <summary>
/// Gets the group id.
/// </summary>
/// <value>The group id.</value>
Guid GetGroupId();
/// <summary>
/// Gets the playing item id.
/// </summary>
/// <value>The playing item id.</value>
Guid GetPlayingItemId();
/// <summary>
/// Checks if the group is empty.
/// </summary>
/// <value>If the group is empty.</value>
bool IsGroupEmpty();
/// <summary>
/// Initializes the group with the user's info.
/// </summary>
/// <param name="user">The session.</param>
void InitGroup(SessionInfo user);
/// <summary>
/// Adds the user to the group.
/// </summary>
/// <param name="user">The session.</param>
void UserJoin(SessionInfo user);
/// <summary>
/// Removes the user from the group.
/// </summary>
/// <param name="user">The session.</param>
void UserLeave(SessionInfo user);
/// <summary>
/// Handles the requested action by the user.
/// </summary>
/// <param name="user">The session.</param>
/// <param name="request">The requested action.</param>
void HandleRequest(SessionInfo user, SyncplayRequestInfo request);
/// <summary>
/// Gets the info about the group for the clients.
/// </summary>
/// <value>The group info for the clients.</value>
GroupInfoView GetInfo();
}
}

View File

@@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Syncplay;
namespace MediaBrowser.Controller.Syncplay
{
/// <summary>
/// Interface ISyncplayManager.
/// </summary>
public interface ISyncplayManager
{
/// <summary>
/// Creates a new group.
/// </summary>
/// <param name="user">The user that's creating the group.</param>
void NewGroup(SessionInfo user);
/// <summary>
/// Adds the user to a group.
/// </summary>
/// <param name="user">The session.</param>
/// <param name="groupId">The group id.</param>
void JoinGroup(SessionInfo user, string groupId);
/// <summary>
/// Removes the user from a group.
/// </summary>
/// <param name="user">The session.</param>
void LeaveGroup(SessionInfo user);
/// <summary>
/// Gets list of available groups for a user.
/// </summary>
/// <param name="user">The user.</param>
/// <value>The list of available groups.</value>
List<GroupInfoView> ListGroups(SessionInfo user);
/// <summary>
/// Handle a request by a user in a group.
/// </summary>
/// <param name="user">The session.</param>
/// <param name="request">The request.</param>
void HandleRequest(SessionInfo user, SyncplayRequestInfo request);
/// <summary>
/// Maps a user to a group.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="group">The group.</param>
/// <exception cref="InvalidOperationException"></exception>
void MapUserToGroup(SessionInfo user, ISyncplayController group);
/// <summary>
/// Unmaps a user from a group.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="group">The group.</param>
/// <exception cref="InvalidOperationException"></exception>
void UnmapUserFromGroup(SessionInfo user, ISyncplayController group);
}
}