aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Server.Implementations/SyncPlay/Group.cs16
-rw-r--r--Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs8
-rw-r--r--Jellyfin.Server/Filters/AdditionalModelFilter.cs105
-rw-r--r--MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandMessage.cs24
-rw-r--r--MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfGroupInfoMessage.cs25
-rw-r--r--MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfGroupStateUpdateMessage.cs25
-rw-r--r--MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfPlayQueueUpdateMessage.cs25
-rw-r--r--MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfStringMessage.cs25
-rw-r--r--MediaBrowser.Controller/Session/ISessionManager.cs2
-rw-r--r--MediaBrowser.Controller/SyncPlay/GroupStates/AbstractGroupState.cs12
-rw-r--r--MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs16
-rw-r--r--MediaBrowser.Controller/SyncPlay/IGroupStateContext.cs11
-rw-r--r--MediaBrowser.Model/SyncPlay/GroupUpdate.cs17
-rw-r--r--MediaBrowser.Model/SyncPlay/GroupUpdateOfT.cs31
-rw-r--r--MediaBrowser.Model/SyncPlay/GroupUpdateType.cs10
-rw-r--r--MediaBrowser.Model/SyncPlay/SyncPlayGroupDoesNotExistUpdate.cs21
-rw-r--r--MediaBrowser.Model/SyncPlay/SyncPlayGroupJoinedUpdate.cs21
-rw-r--r--MediaBrowser.Model/SyncPlay/SyncPlayGroupLeftUpdate.cs21
-rw-r--r--MediaBrowser.Model/SyncPlay/SyncPlayLibraryAccessDeniedUpdate.cs21
-rw-r--r--MediaBrowser.Model/SyncPlay/SyncPlayNotInGroupUpdate.cs21
-rw-r--r--MediaBrowser.Model/SyncPlay/SyncPlayPlayQueueUpdate.cs21
-rw-r--r--MediaBrowser.Model/SyncPlay/SyncPlayStateUpdate.cs21
-rw-r--r--MediaBrowser.Model/SyncPlay/SyncPlayUserJoinedUpdate.cs21
-rw-r--r--MediaBrowser.Model/SyncPlay/SyncPlayUserLeftUpdate.cs21
24 files changed, 299 insertions, 242 deletions
diff --git a/Emby.Server.Implementations/SyncPlay/Group.cs b/Emby.Server.Implementations/SyncPlay/Group.cs
index d47e47793..c2e834ad5 100644
--- a/Emby.Server.Implementations/SyncPlay/Group.cs
+++ b/Emby.Server.Implementations/SyncPlay/Group.cs
@@ -273,7 +273,7 @@ namespace Emby.Server.Implementations.SyncPlay
SetState(waitingState);
}
- var updateSession = NewSyncPlayGroupUpdate(GroupUpdateType.GroupJoined, GetInfo());
+ var updateSession = new SyncPlayGroupJoinedUpdate(GroupId, GetInfo());
SendGroupUpdate(session, SyncPlayBroadcastType.CurrentSession, updateSession, cancellationToken);
_state.SessionJoined(this, _state.Type, session, cancellationToken);
@@ -291,10 +291,10 @@ namespace Emby.Server.Implementations.SyncPlay
{
AddSession(session);
- var updateSession = NewSyncPlayGroupUpdate(GroupUpdateType.GroupJoined, GetInfo());
+ var updateSession = new SyncPlayGroupJoinedUpdate(GroupId, GetInfo());
SendGroupUpdate(session, SyncPlayBroadcastType.CurrentSession, updateSession, cancellationToken);
- var updateOthers = NewSyncPlayGroupUpdate(GroupUpdateType.UserJoined, session.UserName);
+ var updateOthers = new SyncPlayUserJoinedUpdate(GroupId, session.UserName);
SendGroupUpdate(session, SyncPlayBroadcastType.AllExceptCurrentSession, updateOthers, cancellationToken);
_state.SessionJoined(this, _state.Type, session, cancellationToken);
@@ -314,10 +314,10 @@ namespace Emby.Server.Implementations.SyncPlay
RemoveSession(session);
- var updateSession = NewSyncPlayGroupUpdate(GroupUpdateType.GroupLeft, GroupId.ToString());
+ var updateSession = new SyncPlayGroupLeftUpdate(GroupId, GroupId.ToString());
SendGroupUpdate(session, SyncPlayBroadcastType.CurrentSession, updateSession, cancellationToken);
- var updateOthers = NewSyncPlayGroupUpdate(GroupUpdateType.UserLeft, session.UserName);
+ var updateOthers = new SyncPlayUserLeftUpdate(GroupId, session.UserName);
SendGroupUpdate(session, SyncPlayBroadcastType.AllExceptCurrentSession, updateOthers, cancellationToken);
_logger.LogInformation("Session {SessionId} left group {GroupId}.", session.Id, GroupId.ToString());
@@ -426,12 +426,6 @@ namespace Emby.Server.Implementations.SyncPlay
}
/// <inheritdoc />
- public GroupUpdate<T> NewSyncPlayGroupUpdate<T>(GroupUpdateType type, T data)
- {
- return new GroupUpdate<T>(GroupId, type, data);
- }
-
- /// <inheritdoc />
public long SanitizePositionTicks(long? positionTicks)
{
var ticks = positionTicks ?? 0;
diff --git a/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs b/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs
index fdfff8f3b..92b80e102 100644
--- a/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs
+++ b/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs
@@ -159,7 +159,7 @@ namespace Emby.Server.Implementations.SyncPlay
{
_logger.LogWarning("Session {SessionId} tried to join group {GroupId} that does not exist.", session.Id, request.GroupId);
- var error = new GroupUpdate<string>(Guid.Empty, GroupUpdateType.GroupDoesNotExist, string.Empty);
+ var error = new SyncPlayGroupDoesNotExistUpdate(Guid.Empty, string.Empty);
_sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return;
}
@@ -171,7 +171,7 @@ namespace Emby.Server.Implementations.SyncPlay
{
_logger.LogWarning("Session {SessionId} tried to join group {GroupId} but does not have access to some content of the playing queue.", session.Id, group.GroupId.ToString());
- var error = new GroupUpdate<string>(group.GroupId, GroupUpdateType.LibraryAccessDenied, string.Empty);
+ var error = new SyncPlayLibraryAccessDeniedUpdate(group.GroupId, string.Empty);
_sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return;
}
@@ -248,7 +248,7 @@ namespace Emby.Server.Implementations.SyncPlay
{
_logger.LogWarning("Session {SessionId} does not belong to any group.", session.Id);
- var error = new GroupUpdate<string>(Guid.Empty, GroupUpdateType.NotInGroup, string.Empty);
+ var error = new SyncPlayNotInGroupUpdate(Guid.Empty, string.Empty);
_sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
}
}
@@ -327,7 +327,7 @@ namespace Emby.Server.Implementations.SyncPlay
{
_logger.LogWarning("Session {SessionId} does not belong to any group.", session.Id);
- var error = new GroupUpdate<string>(Guid.Empty, GroupUpdateType.NotInGroup, string.Empty);
+ var error = new SyncPlayNotInGroupUpdate(Guid.Empty, string.Empty);
_sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
}
}
diff --git a/Jellyfin.Server/Filters/AdditionalModelFilter.cs b/Jellyfin.Server/Filters/AdditionalModelFilter.cs
index 4cd0fc231..421eeecda 100644
--- a/Jellyfin.Server/Filters/AdditionalModelFilter.cs
+++ b/Jellyfin.Server/Filters/AdditionalModelFilter.cs
@@ -92,17 +92,51 @@ namespace Jellyfin.Server.Filters
continue;
}
- // Additional discriminator needed for GroupUpdate models...
- if (messageType == SessionMessageType.SyncPlayGroupUpdate && type != typeof(SyncPlayGroupUpdateCommandMessage))
- {
- continue;
- }
-
var schema = context.SchemaGenerator.GenerateSchema(type, context.SchemaRepository);
outboundWebSocketSchemas.Add(schema);
outboundWebSocketDiscriminators.Add(messageType.ToString()!, schema.Reference.ReferenceV3);
}
+ // Add custom "SyncPlayGroupUpdateMessage" schema because Swashbuckle cannot generate it for us
+ var syncPlayGroupUpdateMessageSchema = new OpenApiSchema
+ {
+ Type = "object",
+ Description = "Untyped sync play command.",
+ Properties = new Dictionary<string, OpenApiSchema>
+ {
+ {
+ "Data", new OpenApiSchema
+ {
+ AllOf =
+ [
+ new OpenApiSchema { Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = nameof(GroupUpdate<object>) } }
+ ],
+ Description = "Group update data",
+ Nullable = false,
+ }
+ },
+ { "MessageId", new OpenApiSchema { Type = "string", Format = "uuid", Description = "Gets or sets the message id." } },
+ {
+ "MessageType", new OpenApiSchema
+ {
+ Enum = Enum.GetValues<SessionMessageType>().Select(type => new OpenApiString(type.ToString())).ToList<IOpenApiAny>(),
+ AllOf =
+ [
+ new OpenApiSchema { Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = nameof(SessionMessageType) } }
+ ],
+ Description = "The different kinds of messages that are used in the WebSocket api.",
+ Default = new OpenApiString(nameof(SessionMessageType.SyncPlayGroupUpdate)),
+ ReadOnly = true
+ }
+ },
+ },
+ AdditionalPropertiesAllowed = false,
+ Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "SyncPlayGroupUpdateMessage" }
+ };
+ context.SchemaRepository.AddDefinition("SyncPlayGroupUpdateMessage", syncPlayGroupUpdateMessageSchema);
+ outboundWebSocketSchemas.Add(syncPlayGroupUpdateMessageSchema);
+ outboundWebSocketDiscriminators[nameof(SessionMessageType.SyncPlayGroupUpdate)] = syncPlayGroupUpdateMessageSchema.Reference.ReferenceV3;
+
var outboundWebSocketMessageSchema = new OpenApiSchema
{
Type = "object",
@@ -140,41 +174,46 @@ namespace Jellyfin.Server.Filters
});
// Manually generate sync play GroupUpdate messages.
- if (!context.SchemaRepository.Schemas.TryGetValue(nameof(GroupUpdate), out var groupUpdateSchema))
- {
- groupUpdateSchema = context.SchemaGenerator.GenerateSchema(typeof(GroupUpdate), context.SchemaRepository);
- }
-
- var groupUpdateOfGroupInfoSchema = context.SchemaGenerator.GenerateSchema(typeof(GroupUpdate<GroupInfoDto>), context.SchemaRepository);
- var groupUpdateOfGroupStateSchema = context.SchemaGenerator.GenerateSchema(typeof(GroupUpdate<GroupStateUpdate>), context.SchemaRepository);
- var groupUpdateOfStringSchema = context.SchemaGenerator.GenerateSchema(typeof(GroupUpdate<string>), context.SchemaRepository);
- var groupUpdateOfPlayQueueSchema = context.SchemaGenerator.GenerateSchema(typeof(GroupUpdate<PlayQueueUpdate>), context.SchemaRepository);
+ var groupUpdateTypes = typeof(GroupUpdate<>).Assembly.GetTypes()
+ .Where(t => t.BaseType != null
+ && t.BaseType.IsGenericType
+ && t.BaseType.GetGenericTypeDefinition() == typeof(GroupUpdate<>))
+ .ToList();
- groupUpdateSchema.OneOf = new List<OpenApiSchema>
+ var groupUpdateSchemas = new List<OpenApiSchema>();
+ var groupUpdateDiscriminators = new Dictionary<string, string>();
+ foreach (var type in groupUpdateTypes)
{
- groupUpdateOfGroupInfoSchema,
- groupUpdateOfGroupStateSchema,
- groupUpdateOfStringSchema,
- groupUpdateOfPlayQueueSchema
- };
+ var groupUpdateType = (GroupUpdateType?)type.GetProperty(nameof(GroupUpdate<object>.Type))?.GetCustomAttribute<DefaultValueAttribute>()?.Value;
+ if (groupUpdateType is null)
+ {
+ continue;
+ }
+
+ var schema = context.SchemaGenerator.GenerateSchema(type, context.SchemaRepository);
+ groupUpdateSchemas.Add(schema);
+ groupUpdateDiscriminators[groupUpdateType.ToString()!] = schema.Reference.ReferenceV3;
+ }
- groupUpdateSchema.Discriminator = new OpenApiDiscriminator
+ var groupUpdateSchema = new OpenApiSchema
{
- PropertyName = nameof(GroupUpdate.Type),
- Mapping = new Dictionary<string, string>
+ Type = "object",
+ Description = "Represents the list of possible group update types",
+ Reference = new OpenApiReference
+ {
+ Id = nameof(GroupUpdate<object>),
+ Type = ReferenceType.Schema
+ },
+ OneOf = groupUpdateSchemas,
+ Discriminator = new OpenApiDiscriminator
{
- { GroupUpdateType.UserJoined.ToString(), groupUpdateOfStringSchema.Reference.ReferenceV3 },
- { GroupUpdateType.UserLeft.ToString(), groupUpdateOfStringSchema.Reference.ReferenceV3 },
- { GroupUpdateType.GroupJoined.ToString(), groupUpdateOfGroupInfoSchema.Reference.ReferenceV3 },
- { GroupUpdateType.GroupLeft.ToString(), groupUpdateOfStringSchema.Reference.ReferenceV3 },
- { GroupUpdateType.StateUpdate.ToString(), groupUpdateOfGroupStateSchema.Reference.ReferenceV3 },
- { GroupUpdateType.PlayQueue.ToString(), groupUpdateOfPlayQueueSchema.Reference.ReferenceV3 },
- { GroupUpdateType.NotInGroup.ToString(), groupUpdateOfStringSchema.Reference.ReferenceV3 },
- { GroupUpdateType.GroupDoesNotExist.ToString(), groupUpdateOfStringSchema.Reference.ReferenceV3 },
- { GroupUpdateType.LibraryAccessDenied.ToString(), groupUpdateOfStringSchema.Reference.ReferenceV3 }
+ PropertyName = nameof(GroupUpdate<object>.Type),
+ Mapping = groupUpdateDiscriminators
}
};
+ context.SchemaRepository.Schemas[nameof(GroupUpdate<object>)] = groupUpdateSchema;
+
context.SchemaGenerator.GenerateSchema(typeof(ServerDiscoveryInfo), context.SchemaRepository);
foreach (var configuration in _serverConfigurationManager.GetConfigurationStores())
diff --git a/MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandMessage.cs b/MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandMessage.cs
deleted file mode 100644
index 6a501aa7e..000000000
--- a/MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandMessage.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System.ComponentModel;
-using MediaBrowser.Model.Session;
-using MediaBrowser.Model.SyncPlay;
-
-namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
-
-/// <summary>
-/// Untyped sync play command.
-/// </summary>
-public class SyncPlayGroupUpdateCommandMessage : OutboundWebSocketMessage<GroupUpdate>
-{
- /// <summary>
- /// Initializes a new instance of the <see cref="SyncPlayGroupUpdateCommandMessage"/> class.
- /// </summary>
- /// <param name="data">The send command.</param>
- public SyncPlayGroupUpdateCommandMessage(GroupUpdate data)
- : base(data)
- {
- }
-
- /// <inheritdoc />
- [DefaultValue(SessionMessageType.SyncPlayGroupUpdate)]
- public override SessionMessageType MessageType => SessionMessageType.SyncPlayGroupUpdate;
-}
diff --git a/MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfGroupInfoMessage.cs b/MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfGroupInfoMessage.cs
deleted file mode 100644
index 47f706e2a..000000000
--- a/MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfGroupInfoMessage.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System.ComponentModel;
-using MediaBrowser.Model.Session;
-using MediaBrowser.Model.SyncPlay;
-
-namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
-
-/// <summary>
-/// Sync play group update command with group info.
-/// GroupUpdateTypes: GroupJoined.
-/// </summary>
-public class SyncPlayGroupUpdateCommandOfGroupInfoMessage : OutboundWebSocketMessage<GroupUpdate<GroupInfoDto>>
-{
- /// <summary>
- /// Initializes a new instance of the <see cref="SyncPlayGroupUpdateCommandOfGroupInfoMessage"/> class.
- /// </summary>
- /// <param name="data">The group info.</param>
- public SyncPlayGroupUpdateCommandOfGroupInfoMessage(GroupUpdate<GroupInfoDto> data)
- : base(data)
- {
- }
-
- /// <inheritdoc />
- [DefaultValue(SessionMessageType.SyncPlayGroupUpdate)]
- public override SessionMessageType MessageType => SessionMessageType.SyncPlayGroupUpdate;
-}
diff --git a/MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfGroupStateUpdateMessage.cs b/MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfGroupStateUpdateMessage.cs
deleted file mode 100644
index 11ddb1e25..000000000
--- a/MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfGroupStateUpdateMessage.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System.ComponentModel;
-using MediaBrowser.Model.Session;
-using MediaBrowser.Model.SyncPlay;
-
-namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
-
-/// <summary>
-/// Sync play group update command with group state update.
-/// GroupUpdateTypes: StateUpdate.
-/// </summary>
-public class SyncPlayGroupUpdateCommandOfGroupStateUpdateMessage : OutboundWebSocketMessage<GroupUpdate<GroupStateUpdate>>
-{
- /// <summary>
- /// Initializes a new instance of the <see cref="SyncPlayGroupUpdateCommandOfGroupStateUpdateMessage"/> class.
- /// </summary>
- /// <param name="data">The group info.</param>
- public SyncPlayGroupUpdateCommandOfGroupStateUpdateMessage(GroupUpdate<GroupStateUpdate> data)
- : base(data)
- {
- }
-
- /// <inheritdoc />
- [DefaultValue(SessionMessageType.SyncPlayGroupUpdate)]
- public override SessionMessageType MessageType => SessionMessageType.SyncPlayGroupUpdate;
-}
diff --git a/MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfPlayQueueUpdateMessage.cs b/MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfPlayQueueUpdateMessage.cs
deleted file mode 100644
index 7e73399b1..000000000
--- a/MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfPlayQueueUpdateMessage.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System.ComponentModel;
-using MediaBrowser.Model.Session;
-using MediaBrowser.Model.SyncPlay;
-
-namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
-
-/// <summary>
-/// Sync play group update command with play queue update.
-/// GroupUpdateTypes: PlayQueue.
-/// </summary>
-public class SyncPlayGroupUpdateCommandOfPlayQueueUpdateMessage : OutboundWebSocketMessage<GroupUpdate<PlayQueueUpdate>>
-{
- /// <summary>
- /// Initializes a new instance of the <see cref="SyncPlayGroupUpdateCommandOfPlayQueueUpdateMessage"/> class.
- /// </summary>
- /// <param name="data">The play queue update.</param>
- public SyncPlayGroupUpdateCommandOfPlayQueueUpdateMessage(GroupUpdate<PlayQueueUpdate> data)
- : base(data)
- {
- }
-
- /// <inheritdoc />
- [DefaultValue(SessionMessageType.SyncPlayGroupUpdate)]
- public override SessionMessageType MessageType => SessionMessageType.SyncPlayGroupUpdate;
-}
diff --git a/MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfStringMessage.cs b/MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfStringMessage.cs
deleted file mode 100644
index 5b5ccd3ed..000000000
--- a/MediaBrowser.Controller/Net/WebSocketMessages/Outbound/SyncPlayGroupUpdateCommandOfStringMessage.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System.ComponentModel;
-using MediaBrowser.Model.Session;
-using MediaBrowser.Model.SyncPlay;
-
-namespace MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
-
-/// <summary>
-/// Sync play group update command with string.
-/// GroupUpdateTypes: GroupDoesNotExist (error), LibraryAccessDenied (error), NotInGroup (error), GroupLeft (groupId), UserJoined (username), UserLeft (username).
-/// </summary>
-public class SyncPlayGroupUpdateCommandOfStringMessage : OutboundWebSocketMessage<GroupUpdate<string>>
-{
- /// <summary>
- /// Initializes a new instance of the <see cref="SyncPlayGroupUpdateCommandOfStringMessage"/> class.
- /// </summary>
- /// <param name="data">The send command.</param>
- public SyncPlayGroupUpdateCommandOfStringMessage(GroupUpdate<string> data)
- : base(data)
- {
- }
-
- /// <inheritdoc />
- [DefaultValue(SessionMessageType.SyncPlayGroupUpdate)]
- public override SessionMessageType MessageType => SessionMessageType.SyncPlayGroupUpdate;
-}
diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs
index 47bcfdb6e..2b3afa117 100644
--- a/MediaBrowser.Controller/Session/ISessionManager.cs
+++ b/MediaBrowser.Controller/Session/ISessionManager.cs
@@ -161,7 +161,7 @@ namespace MediaBrowser.Controller.Session
/// <param name="sessionId">The identifier of the session.</param>
/// <param name="command">The group update.</param>
/// <param name="cancellationToken">The cancellation token.</param>
- /// <typeparam name="T">Type of group.</typeparam>
+ /// <typeparam name="T">The group update type.</typeparam>
/// <returns>Task.</returns>
Task SendSyncPlayGroupUpdate<T>(string sessionId, GroupUpdate<T> command, CancellationToken cancellationToken);
diff --git a/MediaBrowser.Controller/SyncPlay/GroupStates/AbstractGroupState.cs b/MediaBrowser.Controller/SyncPlay/GroupStates/AbstractGroupState.cs
index 51c95a1bb..31890c40a 100644
--- a/MediaBrowser.Controller/SyncPlay/GroupStates/AbstractGroupState.cs
+++ b/MediaBrowser.Controller/SyncPlay/GroupStates/AbstractGroupState.cs
@@ -80,7 +80,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
}
var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.RemoveItems);
- var update = context.NewSyncPlayGroupUpdate(GroupUpdateType.PlayQueue, playQueueUpdate);
+ var update = new SyncPlayPlayQueueUpdate(context.GroupId, playQueueUpdate);
context.SendGroupUpdate(session, SyncPlayBroadcastType.AllGroup, update, cancellationToken);
if (playingItemRemoved && !context.PlayQueue.IsItemPlaying())
@@ -106,7 +106,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
}
var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.MoveItem);
- var update = context.NewSyncPlayGroupUpdate(GroupUpdateType.PlayQueue, playQueueUpdate);
+ var update = new SyncPlayPlayQueueUpdate(context.GroupId, playQueueUpdate);
context.SendGroupUpdate(session, SyncPlayBroadcastType.AllGroup, update, cancellationToken);
}
@@ -127,7 +127,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
_ => PlayQueueUpdateReason.Queue
};
var playQueueUpdate = context.GetPlayQueueUpdate(reason);
- var update = context.NewSyncPlayGroupUpdate(GroupUpdateType.PlayQueue, playQueueUpdate);
+ var update = new SyncPlayPlayQueueUpdate(context.GroupId, playQueueUpdate);
context.SendGroupUpdate(session, SyncPlayBroadcastType.AllGroup, update, cancellationToken);
}
@@ -184,7 +184,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
{
context.SetRepeatMode(request.Mode);
var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.RepeatMode);
- var update = context.NewSyncPlayGroupUpdate(GroupUpdateType.PlayQueue, playQueueUpdate);
+ var update = new SyncPlayPlayQueueUpdate(context.GroupId, playQueueUpdate);
context.SendGroupUpdate(session, SyncPlayBroadcastType.AllGroup, update, cancellationToken);
}
@@ -193,7 +193,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
{
context.SetShuffleMode(request.Mode);
var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.ShuffleMode);
- var update = context.NewSyncPlayGroupUpdate(GroupUpdateType.PlayQueue, playQueueUpdate);
+ var update = new SyncPlayPlayQueueUpdate(context.GroupId, playQueueUpdate);
context.SendGroupUpdate(session, SyncPlayBroadcastType.AllGroup, update, cancellationToken);
}
@@ -221,7 +221,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
{
// Notify relevant state change event.
var stateUpdate = new GroupStateUpdate(Type, reason.Action);
- var update = context.NewSyncPlayGroupUpdate(GroupUpdateType.StateUpdate, stateUpdate);
+ var update = new SyncPlayStateUpdate(context.GroupId, stateUpdate);
context.SendGroupUpdate(session, SyncPlayBroadcastType.AllGroup, update, cancellationToken);
}
diff --git a/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs b/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs
index dcc06db1e..132765b71 100644
--- a/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs
+++ b/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs
@@ -78,7 +78,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
// Prepare new session.
var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.NewPlaylist);
- var update = context.NewSyncPlayGroupUpdate(GroupUpdateType.PlayQueue, playQueueUpdate);
+ var update = new SyncPlayPlayQueueUpdate(context.GroupId, playQueueUpdate);
context.SendGroupUpdate(session, SyncPlayBroadcastType.CurrentSession, update, cancellationToken);
context.SetBuffering(session, true);
@@ -152,7 +152,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
}
var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.NewPlaylist);
- var update = context.NewSyncPlayGroupUpdate(GroupUpdateType.PlayQueue, playQueueUpdate);
+ var update = new SyncPlayPlayQueueUpdate(context.GroupId, playQueueUpdate);
context.SendGroupUpdate(session, SyncPlayBroadcastType.AllGroup, update, cancellationToken);
// Reset status of sessions and await for all Ready events.
@@ -177,7 +177,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
if (result)
{
var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.SetCurrentItem);
- var update = context.NewSyncPlayGroupUpdate(GroupUpdateType.PlayQueue, playQueueUpdate);
+ var update = new SyncPlayPlayQueueUpdate(context.GroupId, playQueueUpdate);
context.SendGroupUpdate(session, SyncPlayBroadcastType.AllGroup, update, cancellationToken);
// Reset status of sessions and await for all Ready events.
@@ -215,7 +215,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
context.RestartCurrentItem();
var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.NewPlaylist);
- var update = context.NewSyncPlayGroupUpdate(GroupUpdateType.PlayQueue, playQueueUpdate);
+ var update = new SyncPlayPlayQueueUpdate(context.GroupId, playQueueUpdate);
context.SendGroupUpdate(session, SyncPlayBroadcastType.AllGroup, update, cancellationToken);
// Reset status of sessions and await for all Ready events.
@@ -336,7 +336,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
_logger.LogDebug("Session {SessionId} reported wrong playlist item in group {GroupId}.", session.Id, context.GroupId.ToString());
var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.SetCurrentItem);
- var updateSession = context.NewSyncPlayGroupUpdate(GroupUpdateType.PlayQueue, playQueueUpdate);
+ var updateSession = new SyncPlayPlayQueueUpdate(context.GroupId, playQueueUpdate);
context.SendGroupUpdate(session, SyncPlayBroadcastType.CurrentSession, updateSession, cancellationToken);
context.SetBuffering(session, true);
@@ -410,7 +410,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
_logger.LogDebug("Session {SessionId} reported wrong playlist item in group {GroupId}.", session.Id, context.GroupId.ToString());
var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.SetCurrentItem);
- var update = context.NewSyncPlayGroupUpdate(GroupUpdateType.PlayQueue, playQueueUpdate);
+ var update = new SyncPlayPlayQueueUpdate(context.GroupId, playQueueUpdate);
context.SendGroupUpdate(session, SyncPlayBroadcastType.CurrentSession, update, cancellationToken);
context.SetBuffering(session, true);
@@ -583,7 +583,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
{
// Send playing-queue update.
var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.NextItem);
- var update = context.NewSyncPlayGroupUpdate(GroupUpdateType.PlayQueue, playQueueUpdate);
+ var update = new SyncPlayPlayQueueUpdate(context.GroupId, playQueueUpdate);
context.SendGroupUpdate(session, SyncPlayBroadcastType.AllGroup, update, cancellationToken);
// Reset status of sessions and await for all Ready events.
@@ -629,7 +629,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
{
// Send playing-queue update.
var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.PreviousItem);
- var update = context.NewSyncPlayGroupUpdate(GroupUpdateType.PlayQueue, playQueueUpdate);
+ var update = new SyncPlayPlayQueueUpdate(context.GroupId, playQueueUpdate);
context.SendGroupUpdate(session, SyncPlayBroadcastType.AllGroup, update, cancellationToken);
// Reset status of sessions and await for all Ready events.
diff --git a/MediaBrowser.Controller/SyncPlay/IGroupStateContext.cs b/MediaBrowser.Controller/SyncPlay/IGroupStateContext.cs
index d2de22450..ddf86be71 100644
--- a/MediaBrowser.Controller/SyncPlay/IGroupStateContext.cs
+++ b/MediaBrowser.Controller/SyncPlay/IGroupStateContext.cs
@@ -66,11 +66,11 @@ namespace MediaBrowser.Controller.SyncPlay
/// <summary>
/// Sends a GroupUpdate message to the interested sessions.
/// </summary>
- /// <typeparam name="T">The type of the data of the message.</typeparam>
/// <param name="from">The current session.</param>
/// <param name="type">The filtering type.</param>
/// <param name="message">The message to send.</param>
/// <param name="cancellationToken">The cancellation token.</param>
+ /// <typeparam name="T">The group update type.</typeparam>
/// <returns>The task.</returns>
Task SendGroupUpdate<T>(SessionInfo from, SyncPlayBroadcastType type, GroupUpdate<T> message, CancellationToken cancellationToken);
@@ -92,15 +92,6 @@ namespace MediaBrowser.Controller.SyncPlay
SendCommand NewSyncPlayCommand(SendCommandType type);
/// <summary>
- /// Builds a new group update message.
- /// </summary>
- /// <typeparam name="T">The type of the data of the message.</typeparam>
- /// <param name="type">The update type.</param>
- /// <param name="data">The data to send.</param>
- /// <returns>The group update.</returns>
- GroupUpdate<T> NewSyncPlayGroupUpdate<T>(GroupUpdateType type, T data);
-
- /// <summary>
/// Sanitizes the PositionTicks, considers the current playing item when available.
/// </summary>
/// <param name="positionTicks">The PositionTicks.</param>
diff --git a/MediaBrowser.Model/SyncPlay/GroupUpdate.cs b/MediaBrowser.Model/SyncPlay/GroupUpdate.cs
index ec67d7ea8..794443499 100644
--- a/MediaBrowser.Model/SyncPlay/GroupUpdate.cs
+++ b/MediaBrowser.Model/SyncPlay/GroupUpdate.cs
@@ -5,15 +5,18 @@ namespace MediaBrowser.Model.SyncPlay;
/// <summary>
/// Group update without data.
/// </summary>
-public abstract class GroupUpdate
+/// <typeparam name="T">The type of the update data.</typeparam>
+public abstract class GroupUpdate<T>
{
/// <summary>
- /// Initializes a new instance of the <see cref="GroupUpdate"/> class.
+ /// Initializes a new instance of the <see cref="GroupUpdate{T}"/> class.
/// </summary>
/// <param name="groupId">The group identifier.</param>
- protected GroupUpdate(Guid groupId)
+ /// <param name="data">The update data.</param>
+ protected GroupUpdate(Guid groupId, T data)
{
GroupId = groupId;
+ Data = data;
}
/// <summary>
@@ -23,8 +26,14 @@ public abstract class GroupUpdate
public Guid GroupId { get; }
/// <summary>
+ /// Gets the update data.
+ /// </summary>
+ /// <value>The update data.</value>
+ public T Data { get; }
+
+ /// <summary>
/// Gets the update type.
/// </summary>
/// <value>The update type.</value>
- public GroupUpdateType Type { get; init; }
+ public abstract GroupUpdateType Type { get; }
}
diff --git a/MediaBrowser.Model/SyncPlay/GroupUpdateOfT.cs b/MediaBrowser.Model/SyncPlay/GroupUpdateOfT.cs
deleted file mode 100644
index 25cd44461..000000000
--- a/MediaBrowser.Model/SyncPlay/GroupUpdateOfT.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-#pragma warning disable SA1649
-
-using System;
-
-namespace MediaBrowser.Model.SyncPlay;
-
-/// <summary>
-/// Class GroupUpdate.
-/// </summary>
-/// <typeparam name="T">The type of the data of the message.</typeparam>
-public class GroupUpdate<T> : GroupUpdate
-{
- /// <summary>
- /// Initializes a new instance of the <see cref="GroupUpdate{T}"/> class.
- /// </summary>
- /// <param name="groupId">The group identifier.</param>
- /// <param name="type">The update type.</param>
- /// <param name="data">The update data.</param>
- public GroupUpdate(Guid groupId, GroupUpdateType type, T data)
- : base(groupId)
- {
- Data = data;
- Type = type;
- }
-
- /// <summary>
- /// Gets the update data.
- /// </summary>
- /// <value>The update data.</value>
- public T Data { get; }
-}
diff --git a/MediaBrowser.Model/SyncPlay/GroupUpdateType.cs b/MediaBrowser.Model/SyncPlay/GroupUpdateType.cs
index 907d1defe..e792229a4 100644
--- a/MediaBrowser.Model/SyncPlay/GroupUpdateType.cs
+++ b/MediaBrowser.Model/SyncPlay/GroupUpdateType.cs
@@ -46,16 +46,6 @@ namespace MediaBrowser.Model.SyncPlay
GroupDoesNotExist,
/// <summary>
- /// The create-group-denied error. Sent when a user tries to create a group without required permissions.
- /// </summary>
- CreateGroupDenied,
-
- /// <summary>
- /// The join-group-denied error. Sent when a user tries to join a group without required permissions.
- /// </summary>
- JoinGroupDenied,
-
- /// <summary>
/// The library-access-denied error. Sent when a user tries to join a group without required access to the library.
/// </summary>
LibraryAccessDenied
diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayGroupDoesNotExistUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayGroupDoesNotExistUpdate.cs
new file mode 100644
index 000000000..7e2d10c8b
--- /dev/null
+++ b/MediaBrowser.Model/SyncPlay/SyncPlayGroupDoesNotExistUpdate.cs
@@ -0,0 +1,21 @@
+using System;
+using System.ComponentModel;
+
+namespace MediaBrowser.Model.SyncPlay;
+
+/// <inheritdoc />
+public class SyncPlayGroupDoesNotExistUpdate : GroupUpdate<string>
+{
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SyncPlayGroupDoesNotExistUpdate"/> class.
+ /// </summary>
+ /// <param name="groupId">The groupId.</param>
+ /// <param name="data">The data.</param>
+ public SyncPlayGroupDoesNotExistUpdate(Guid groupId, string data) : base(groupId, data)
+ {
+ }
+
+ /// <inheritdoc />
+ [DefaultValue(GroupUpdateType.GroupDoesNotExist)]
+ public override GroupUpdateType Type => GroupUpdateType.GroupDoesNotExist;
+}
diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayGroupJoinedUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayGroupJoinedUpdate.cs
new file mode 100644
index 000000000..bfb49152a
--- /dev/null
+++ b/MediaBrowser.Model/SyncPlay/SyncPlayGroupJoinedUpdate.cs
@@ -0,0 +1,21 @@
+using System;
+using System.ComponentModel;
+
+namespace MediaBrowser.Model.SyncPlay;
+
+/// <inheritdoc />
+public class SyncPlayGroupJoinedUpdate : GroupUpdate<GroupInfoDto>
+{
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SyncPlayGroupJoinedUpdate"/> class.
+ /// </summary>
+ /// <param name="groupId">The groupId.</param>
+ /// <param name="data">The data.</param>
+ public SyncPlayGroupJoinedUpdate(Guid groupId, GroupInfoDto data) : base(groupId, data)
+ {
+ }
+
+ /// <inheritdoc />
+ [DefaultValue(GroupUpdateType.GroupJoined)]
+ public override GroupUpdateType Type => GroupUpdateType.GroupJoined;
+}
diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayGroupLeftUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayGroupLeftUpdate.cs
new file mode 100644
index 000000000..5ff60c5c2
--- /dev/null
+++ b/MediaBrowser.Model/SyncPlay/SyncPlayGroupLeftUpdate.cs
@@ -0,0 +1,21 @@
+using System;
+using System.ComponentModel;
+
+namespace MediaBrowser.Model.SyncPlay;
+
+/// <inheritdoc />
+public class SyncPlayGroupLeftUpdate : GroupUpdate<string>
+{
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SyncPlayGroupLeftUpdate"/> class.
+ /// </summary>
+ /// <param name="groupId">The groupId.</param>
+ /// <param name="data">The data.</param>
+ public SyncPlayGroupLeftUpdate(Guid groupId, string data) : base(groupId, data)
+ {
+ }
+
+ /// <inheritdoc />
+ [DefaultValue(GroupUpdateType.GroupLeft)]
+ public override GroupUpdateType Type => GroupUpdateType.GroupLeft;
+}
diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayLibraryAccessDeniedUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayLibraryAccessDeniedUpdate.cs
new file mode 100644
index 000000000..0d9a722f7
--- /dev/null
+++ b/MediaBrowser.Model/SyncPlay/SyncPlayLibraryAccessDeniedUpdate.cs
@@ -0,0 +1,21 @@
+using System;
+using System.ComponentModel;
+
+namespace MediaBrowser.Model.SyncPlay;
+
+/// <inheritdoc />
+public class SyncPlayLibraryAccessDeniedUpdate : GroupUpdate<string>
+{
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SyncPlayLibraryAccessDeniedUpdate"/> class.
+ /// </summary>
+ /// <param name="groupId">The groupId.</param>
+ /// <param name="data">The data.</param>
+ public SyncPlayLibraryAccessDeniedUpdate(Guid groupId, string data) : base(groupId, data)
+ {
+ }
+
+ /// <inheritdoc />
+ [DefaultValue(GroupUpdateType.LibraryAccessDenied)]
+ public override GroupUpdateType Type => GroupUpdateType.LibraryAccessDenied;
+}
diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayNotInGroupUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayNotInGroupUpdate.cs
new file mode 100644
index 000000000..a3b610f61
--- /dev/null
+++ b/MediaBrowser.Model/SyncPlay/SyncPlayNotInGroupUpdate.cs
@@ -0,0 +1,21 @@
+using System;
+using System.ComponentModel;
+
+namespace MediaBrowser.Model.SyncPlay;
+
+/// <inheritdoc />
+public class SyncPlayNotInGroupUpdate : GroupUpdate<string>
+{
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SyncPlayNotInGroupUpdate"/> class.
+ /// </summary>
+ /// <param name="groupId">The groupId.</param>
+ /// <param name="data">The data.</param>
+ public SyncPlayNotInGroupUpdate(Guid groupId, string data) : base(groupId, data)
+ {
+ }
+
+ /// <inheritdoc />
+ [DefaultValue(GroupUpdateType.NotInGroup)]
+ public override GroupUpdateType Type => GroupUpdateType.NotInGroup;
+}
diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayPlayQueueUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayPlayQueueUpdate.cs
new file mode 100644
index 000000000..83d9bd40b
--- /dev/null
+++ b/MediaBrowser.Model/SyncPlay/SyncPlayPlayQueueUpdate.cs
@@ -0,0 +1,21 @@
+using System;
+using System.ComponentModel;
+
+namespace MediaBrowser.Model.SyncPlay;
+
+/// <inheritdoc />
+public class SyncPlayPlayQueueUpdate : GroupUpdate<PlayQueueUpdate>
+{
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SyncPlayPlayQueueUpdate"/> class.
+ /// </summary>
+ /// <param name="groupId">The groupId.</param>
+ /// <param name="data">The data.</param>
+ public SyncPlayPlayQueueUpdate(Guid groupId, PlayQueueUpdate data) : base(groupId, data)
+ {
+ }
+
+ /// <inheritdoc />
+ [DefaultValue(GroupUpdateType.PlayQueue)]
+ public override GroupUpdateType Type => GroupUpdateType.PlayQueue;
+}
diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayStateUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayStateUpdate.cs
new file mode 100644
index 000000000..744ca46a0
--- /dev/null
+++ b/MediaBrowser.Model/SyncPlay/SyncPlayStateUpdate.cs
@@ -0,0 +1,21 @@
+using System;
+using System.ComponentModel;
+
+namespace MediaBrowser.Model.SyncPlay;
+
+/// <inheritdoc />
+public class SyncPlayStateUpdate : GroupUpdate<GroupStateUpdate>
+{
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SyncPlayStateUpdate"/> class.
+ /// </summary>
+ /// <param name="groupId">The groupId.</param>
+ /// <param name="data">The data.</param>
+ public SyncPlayStateUpdate(Guid groupId, GroupStateUpdate data) : base(groupId, data)
+ {
+ }
+
+ /// <inheritdoc />
+ [DefaultValue(GroupUpdateType.StateUpdate)]
+ public override GroupUpdateType Type => GroupUpdateType.StateUpdate;
+}
diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayUserJoinedUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayUserJoinedUpdate.cs
new file mode 100644
index 000000000..e8c6b4df4
--- /dev/null
+++ b/MediaBrowser.Model/SyncPlay/SyncPlayUserJoinedUpdate.cs
@@ -0,0 +1,21 @@
+using System;
+using System.ComponentModel;
+
+namespace MediaBrowser.Model.SyncPlay;
+
+/// <inheritdoc />
+public class SyncPlayUserJoinedUpdate : GroupUpdate<string>
+{
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SyncPlayUserJoinedUpdate"/> class.
+ /// </summary>
+ /// <param name="groupId">The groupId.</param>
+ /// <param name="data">The data.</param>
+ public SyncPlayUserJoinedUpdate(Guid groupId, string data) : base(groupId, data)
+ {
+ }
+
+ /// <inheritdoc />
+ [DefaultValue(GroupUpdateType.UserJoined)]
+ public override GroupUpdateType Type => GroupUpdateType.UserJoined;
+}
diff --git a/MediaBrowser.Model/SyncPlay/SyncPlayUserLeftUpdate.cs b/MediaBrowser.Model/SyncPlay/SyncPlayUserLeftUpdate.cs
new file mode 100644
index 000000000..97be8e63a
--- /dev/null
+++ b/MediaBrowser.Model/SyncPlay/SyncPlayUserLeftUpdate.cs
@@ -0,0 +1,21 @@
+using System;
+using System.ComponentModel;
+
+namespace MediaBrowser.Model.SyncPlay;
+
+/// <inheritdoc />
+public class SyncPlayUserLeftUpdate : GroupUpdate<string>
+{
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SyncPlayUserLeftUpdate"/> class.
+ /// </summary>
+ /// <param name="groupId">The groupId.</param>
+ /// <param name="data">The data.</param>
+ public SyncPlayUserLeftUpdate(Guid groupId, string data) : base(groupId, data)
+ {
+ }
+
+ /// <inheritdoc />
+ [DefaultValue(GroupUpdateType.UserLeft)]
+ public override GroupUpdateType Type => GroupUpdateType.UserLeft;
+}