From a86b71899ec52c44ddc6c3018e8cc5e9d7ff4d62 Mon Sep 17 00:00:00 2001 From: Andrew Rabert Date: Thu, 27 Dec 2018 18:27:57 -0500 Subject: Add GPL modules --- .../Session/AuthenticationRequest.cs | 19 + .../Session/ISessionController.cs | 25 ++ MediaBrowser.Controller/Session/ISessionManager.cs | 328 +++++++++++++++++ .../Session/SessionEventArgs.cs | 9 + MediaBrowser.Controller/Session/SessionInfo.cs | 396 +++++++++++++++++++++ 5 files changed, 777 insertions(+) create mode 100644 MediaBrowser.Controller/Session/AuthenticationRequest.cs create mode 100644 MediaBrowser.Controller/Session/ISessionController.cs create mode 100644 MediaBrowser.Controller/Session/ISessionManager.cs create mode 100644 MediaBrowser.Controller/Session/SessionEventArgs.cs create mode 100644 MediaBrowser.Controller/Session/SessionInfo.cs (limited to 'MediaBrowser.Controller/Session') diff --git a/MediaBrowser.Controller/Session/AuthenticationRequest.cs b/MediaBrowser.Controller/Session/AuthenticationRequest.cs new file mode 100644 index 0000000000..eb64db8c3a --- /dev/null +++ b/MediaBrowser.Controller/Session/AuthenticationRequest.cs @@ -0,0 +1,19 @@ +using System; + + +namespace MediaBrowser.Controller.Session +{ + public class AuthenticationRequest + { + public string Username { get; set; } + public Guid UserId { get; set; } + public string Password { get; set; } + public string PasswordSha1 { get; set; } + public string PasswordMd5 { get; set; } + public string App { get; set; } + public string AppVersion { get; set; } + public string DeviceId { get; set; } + public string DeviceName { get; set; } + public string RemoteEndPoint { get; set; } + } +} diff --git a/MediaBrowser.Controller/Session/ISessionController.cs b/MediaBrowser.Controller/Session/ISessionController.cs new file mode 100644 index 0000000000..e1d3a7ee62 --- /dev/null +++ b/MediaBrowser.Controller/Session/ISessionController.cs @@ -0,0 +1,25 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Session +{ + public interface ISessionController + { + /// + /// Gets a value indicating whether this instance is session active. + /// + /// true if this instance is session active; otherwise, false. + bool IsSessionActive { get; } + + /// + /// Gets a value indicating whether [supports media remote control]. + /// + /// true if [supports media remote control]; otherwise, false. + bool SupportsMediaControl { get; } + + /// + /// Sends the message. + /// + Task SendMessage(string name, string messageId, T data, ISessionController[] allControllers, CancellationToken cancellationToken); + } +} diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs new file mode 100644 index 0000000000..b7719e556f --- /dev/null +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -0,0 +1,328 @@ +using MediaBrowser.Controller.Authentication; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Security; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Events; +using MediaBrowser.Model.Session; +using MediaBrowser.Model.Users; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Session +{ + /// + /// Interface ISessionManager + /// + public interface ISessionManager + { + /// + /// Occurs when [playback start]. + /// + event EventHandler PlaybackStart; + + /// + /// Occurs when [playback progress]. + /// + event EventHandler PlaybackProgress; + + /// + /// Occurs when [playback stopped]. + /// + event EventHandler PlaybackStopped; + + /// + /// Occurs when [session started]. + /// + event EventHandler SessionStarted; + + /// + /// Occurs when [session ended]. + /// + event EventHandler SessionEnded; + + event EventHandler SessionActivity; + + /// + /// Occurs when [capabilities changed]. + /// + event EventHandler CapabilitiesChanged; + + /// + /// Occurs when [authentication failed]. + /// + event EventHandler> AuthenticationFailed; + + /// + /// Occurs when [authentication succeeded]. + /// + event EventHandler> AuthenticationSucceeded; + + /// + /// Gets the sessions. + /// + /// The sessions. + IEnumerable Sessions { get; } + + /// + /// Logs the user activity. + /// + /// Type of the client. + /// The app version. + /// The device id. + /// Name of the device. + /// The remote end point. + /// The user. + SessionInfo LogSessionActivity(string appName, string appVersion, string deviceId, string deviceName, string remoteEndPoint, User user); + + void UpdateDeviceName(string sessionId, string reportedDeviceName); + + /// + /// Used to report that playback has started for an item + /// + /// The info. + /// Task. + Task OnPlaybackStart(PlaybackStartInfo info); + + /// + /// Used to report playback progress for an item + /// + /// The info. + /// Task. + /// + Task OnPlaybackProgress(PlaybackProgressInfo info); + + Task OnPlaybackProgress(PlaybackProgressInfo info, bool isAutomated); + + /// + /// Used to report that playback has ended for an item + /// + /// The info. + /// Task. + /// + Task OnPlaybackStopped(PlaybackStopInfo info); + + /// + /// Reports the session ended. + /// + /// The session identifier. + /// Task. + void ReportSessionEnded(string sessionId); + + /// + /// Sends the general command. + /// + /// The controlling session identifier. + /// The session identifier. + /// The command. + /// The cancellation token. + /// Task. + Task SendGeneralCommand(string controllingSessionId, string sessionId, GeneralCommand command, CancellationToken cancellationToken); + + /// + /// Sends the message command. + /// + /// The controlling session identifier. + /// The session id. + /// The command. + /// The cancellation token. + /// Task. + Task SendMessageCommand(string controllingSessionId, string sessionId, MessageCommand command, CancellationToken cancellationToken); + + /// + /// Sends the play command. + /// + /// The controlling session identifier. + /// The session id. + /// The command. + /// The cancellation token. + /// Task. + Task SendPlayCommand(string controllingSessionId, string sessionId, PlayRequest command, CancellationToken cancellationToken); + + /// + /// Sends the browse command. + /// + /// The controlling session identifier. + /// The session id. + /// The command. + /// The cancellation token. + /// Task. + Task SendBrowseCommand(string controllingSessionId, string sessionId, BrowseRequest command, CancellationToken cancellationToken); + + /// + /// Sends the playstate command. + /// + /// The controlling session identifier. + /// The session id. + /// The command. + /// The cancellation token. + /// Task. + Task SendPlaystateCommand(string controllingSessionId, string sessionId, PlaystateRequest command, CancellationToken cancellationToken); + + /// + /// Sends the message to admin sessions. + /// + /// + /// The name. + /// The data. + /// The cancellation token. + /// Task. + Task SendMessageToAdminSessions(string name, T data, CancellationToken cancellationToken); + + /// + /// Sends the message to user sessions. + /// + /// + /// Task. + Task SendMessageToUserSessions(List userIds, string name, T data, CancellationToken cancellationToken); + + Task SendMessageToUserSessions(List userIds, string name, Func dataFn, CancellationToken cancellationToken); + + /// + /// Sends the message to user device sessions. + /// + /// + /// The device identifier. + /// The name. + /// The data. + /// The cancellation token. + /// Task. + Task SendMessageToUserDeviceSessions(string deviceId, string name, T data, CancellationToken cancellationToken); + + /// + /// Sends the restart required message. + /// + /// The cancellation token. + /// Task. + Task SendRestartRequiredNotification(CancellationToken cancellationToken); + + /// + /// Sends the server shutdown notification. + /// + /// The cancellation token. + /// Task. + Task SendServerShutdownNotification(CancellationToken cancellationToken); + + /// + /// Sends the server restart notification. + /// + /// The cancellation token. + /// Task. + Task SendServerRestartNotification(CancellationToken cancellationToken); + + /// + /// Adds the additional user. + /// + /// The session identifier. + /// The user identifier. + void AddAdditionalUser(string sessionId, Guid userId); + + /// + /// Removes the additional user. + /// + /// The session identifier. + /// The user identifier. + void RemoveAdditionalUser(string sessionId, Guid userId); + + /// + /// Reports the now viewing item. + /// + /// The session identifier. + /// The item identifier. + void ReportNowViewingItem(string sessionId, string itemId); + + /// + /// Reports the now viewing item. + /// + /// The session identifier. + /// The item. + void ReportNowViewingItem(string sessionId, BaseItemDto item); + + /// + /// Authenticates the new session. + /// + /// The request. + /// Task{SessionInfo}. + Task AuthenticateNewSession(AuthenticationRequest request); + + /// + /// Creates the new session. + /// + /// The request. + /// Task<AuthenticationResult>. + Task CreateNewSession(AuthenticationRequest request); + + /// + /// Reports the capabilities. + /// + /// The session identifier. + /// The capabilities. + void ReportCapabilities(string sessionId, ClientCapabilities capabilities); + + /// + /// Reports the transcoding information. + /// + /// The device identifier. + /// The information. + void ReportTranscodingInfo(string deviceId, TranscodingInfo info); + + /// + /// Clears the transcoding information. + /// + /// The device identifier. + void ClearTranscodingInfo(string deviceId); + + /// + /// Gets the session. + /// + /// The device identifier. + /// The client. + /// The version. + /// SessionInfo. + SessionInfo GetSession(string deviceId, string client, string version); + + /// + /// Gets the session by authentication token. + /// + /// The token. + /// The device identifier. + /// The remote endpoint. + /// SessionInfo. + SessionInfo GetSessionByAuthenticationToken(string token, string deviceId, string remoteEndpoint); + + /// + /// Gets the session by authentication token. + /// + /// The information. + /// The device identifier. + /// The remote endpoint. + /// The application version. + /// Task<SessionInfo>. + SessionInfo GetSessionByAuthenticationToken(AuthenticationInfo info, string deviceId, string remoteEndpoint, string appVersion); + + /// + /// Logouts the specified access token. + /// + /// The access token. + /// Task. + void Logout(string accessToken); + void Logout(AuthenticationInfo accessToken); + + /// + /// Revokes the user tokens. + /// + /// Task. + void RevokeUserTokens(Guid userId, string currentAccessToken); + + /// + /// Revokes the token. + /// + /// The identifier. + /// Task. + void RevokeToken(string id); + + void CloseIfNeeded(SessionInfo session); + } +} diff --git a/MediaBrowser.Controller/Session/SessionEventArgs.cs b/MediaBrowser.Controller/Session/SessionEventArgs.cs new file mode 100644 index 0000000000..96daa6ec93 --- /dev/null +++ b/MediaBrowser.Controller/Session/SessionEventArgs.cs @@ -0,0 +1,9 @@ +using System; + +namespace MediaBrowser.Controller.Session +{ + public class SessionEventArgs : EventArgs + { + public SessionInfo SessionInfo { get; set; } + } +} diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs new file mode 100644 index 0000000000..869d3fcb05 --- /dev/null +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -0,0 +1,396 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Serialization; +using MediaBrowser.Model.Session; +using MediaBrowser.Model.Threading; +using System.Linq; +using System; + +namespace MediaBrowser.Controller.Session +{ + /// + /// Class SessionInfo + /// + public class SessionInfo : IDisposable + { + private ISessionManager _sessionManager; + private readonly ILogger _logger; + + public SessionInfo(ISessionManager sessionManager, ILogger logger) + { + _sessionManager = sessionManager; + _logger = logger; + + AdditionalUsers = new SessionUserInfo[] { }; + PlayState = new PlayerStateInfo(); + SessionControllers = new ISessionController[] { }; + } + + public PlayerStateInfo PlayState { get; set; } + + public SessionUserInfo[] AdditionalUsers { get; set; } + + public ClientCapabilities Capabilities { get; set; } + + /// + /// Gets or sets the remote end point. + /// + /// The remote end point. + public string RemoteEndPoint { get; set; } + + /// + /// Gets or sets the playable media types. + /// + /// The playable media types. + public string[] PlayableMediaTypes + { + get + { + if (Capabilities == null) + { + return new string[] {}; + } + return Capabilities.PlayableMediaTypes; + } + } + + /// + /// Gets or sets the id. + /// + /// The id. + public string Id { get; set; } + + /// + /// Gets or sets the user id. + /// + /// The user id. + public Guid UserId { get; set; } + + /// + /// Gets or sets the username. + /// + /// The username. + public string UserName { get; set; } + + /// + /// Gets or sets the type of the client. + /// + /// The type of the client. + public string Client { get; set; } + + /// + /// Gets or sets the last activity date. + /// + /// The last activity date. + public DateTime LastActivityDate { get; set; } + + /// + /// Gets or sets the last playback check in. + /// + /// The last playback check in. + public DateTime LastPlaybackCheckIn { get; set; } + + /// + /// Gets or sets the name of the device. + /// + /// The name of the device. + public string DeviceName { get; set; } + + public string DeviceType { get; set; } + + /// + /// Gets or sets the now playing item. + /// + /// The now playing item. + public BaseItemDto NowPlayingItem { get; set; } + + public BaseItem FullNowPlayingItem { get; set; } + + /// + /// Gets or sets the device id. + /// + /// The device id. + public string DeviceId { get; set; } + + /// + /// Gets or sets the application version. + /// + /// The application version. + public string ApplicationVersion { get; set; } + + /// + /// Gets or sets the session controller. + /// + /// The session controller. + [IgnoreDataMember] + public ISessionController[] SessionControllers { get; set; } + + /// + /// Gets or sets the application icon URL. + /// + /// The application icon URL. + public string AppIconUrl { get; set; } + + /// + /// Gets or sets the supported commands. + /// + /// The supported commands. + public string[] SupportedCommands + { + get + { + if (Capabilities == null) + { + return new string[] {}; + } + return Capabilities.SupportedCommands; + } + } + + public TranscodingInfo TranscodingInfo { get; set; } + + /// + /// Gets a value indicating whether this instance is active. + /// + /// true if this instance is active; otherwise, false. + public bool IsActive + { + get + { + var controllers = SessionControllers; + foreach (var controller in controllers) + { + if (controller.IsSessionActive) + { + return true; + } + } + if (controllers.Length > 0) + { + return false; + } + + return true; + } + } + + public bool SupportsMediaControl + { + get + { + if (Capabilities == null || !Capabilities.SupportsMediaControl) + { + return false; + } + + var controllers = SessionControllers; + foreach (var controller in controllers) + { + if (controller.SupportsMediaControl) + { + return true; + } + } + + return false; + } + } + + public bool SupportsRemoteControl + { + get + { + if (Capabilities == null || !Capabilities.SupportsMediaControl) + { + return false; + } + + var controllers = SessionControllers; + foreach (var controller in controllers) + { + if (controller.SupportsMediaControl) + { + return true; + } + } + + return false; + } + } + + public Tuple EnsureController(Func factory) + { + var controllers = SessionControllers.ToList(); + foreach (var controller in controllers) + { + if (controller is T) + { + return new Tuple(controller, false); + } + } + + var newController = factory(this); + _logger.Debug("Creating new {0}", newController.GetType().Name); + controllers.Add(newController); + + SessionControllers = controllers.ToArray(); + return new Tuple(newController, true); + } + + public void AddController(ISessionController controller) + { + var controllers = SessionControllers.ToList(); + controllers.Add(controller); + SessionControllers = controllers.ToArray(); + } + + public bool ContainsUser(string userId) + { + return ContainsUser(new Guid(userId)); + } + + public bool ContainsUser(Guid userId) + { + if (UserId.Equals(userId)) + { + return true; + } + + foreach (var additionalUser in AdditionalUsers) + { + if (userId.Equals(userId)) + { + return true; + } + } + return false; + } + + private readonly object _progressLock = new object(); + private ITimer _progressTimer; + private PlaybackProgressInfo _lastProgressInfo; + + public void StartAutomaticProgress(ITimerFactory timerFactory, PlaybackProgressInfo progressInfo) + { + if (_disposed) + { + return; + } + + lock (_progressLock) + { + _lastProgressInfo = progressInfo; + + if (_progressTimer == null) + { + _progressTimer = timerFactory.Create(OnProgressTimerCallback, null, 1000, 1000); + } + else + { + _progressTimer.Change(1000, 1000); + } + } + } + + // 1 second + private const long ProgressIncrement = 10000000; + + private async void OnProgressTimerCallback(object state) + { + if (_disposed) + { + return; + } + + var progressInfo = _lastProgressInfo; + if (progressInfo == null) + { + return; + } + if (progressInfo.IsPaused) + { + return; + } + + var positionTicks = progressInfo.PositionTicks ?? 0; + if (positionTicks < 0) + { + positionTicks = 0; + } + + var newPositionTicks = positionTicks + ProgressIncrement; + var item = progressInfo.Item; + long? runtimeTicks = item == null ? null : item.RunTimeTicks; + + // Don't report beyond the runtime + if (runtimeTicks.HasValue && newPositionTicks >= runtimeTicks.Value) + { + return; + } + + progressInfo.PositionTicks = newPositionTicks; + + try + { + await _sessionManager.OnPlaybackProgress(progressInfo, true).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error reporting playback progress", ex); + } + } + + public void StopAutomaticProgress() + { + lock (_progressLock) + { + if (_progressTimer != null) + { + _progressTimer.Dispose(); + _progressTimer = null; + } + _lastProgressInfo = null; + } + } + + private bool _disposed = false; + + public void Dispose() + { + _disposed = true; + + StopAutomaticProgress(); + + var controllers = SessionControllers.ToList(); + SessionControllers = new ISessionController[] { }; + + foreach (var controller in controllers) + { + var disposable = controller as IDisposable; + + if (disposable != null) + { + _logger.Debug("Disposing session controller {0}", disposable.GetType().Name); + + try + { + disposable.Dispose(); + } + catch (Exception ex) + { + _logger.ErrorException("Error disposing session controller", ex); + } + } + } + + _sessionManager = null; + } + + public QueueItem[] NowPlayingQueue { get; set; } + public bool HasCustomDeviceName { get; set; } + public string PlaylistItemId { get; set; } + public string ServerId { get; set; } + public string UserPrimaryImageTag { get; set; } + } +} -- cgit v1.2.3