diff options
| author | Niels van Velzen <nielsvanvelzen@users.noreply.github.com> | 2025-04-19 21:08:15 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-19 13:08:15 -0600 |
| commit | 269508be9f78901b3a3b2bea88392aeef88359e4 (patch) | |
| tree | 8885ff1537b6acb2217a372837e9714a9ada048f | |
| parent | 1c190f79522268fb6b3c870749e2ab9a4b8b22fb (diff) | |
Fix SyncPlay WebSocket OpenAPI schemas (#13946)
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; +} |
