aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/Session
diff options
context:
space:
mode:
authorEric Reed <ebr@mediabrowser3.com>2013-09-25 14:32:36 -0400
committerEric Reed <ebr@mediabrowser3.com>2013-09-25 14:32:36 -0400
commitc02c0db35af078e1a78897aecdade2efe57d3f06 (patch)
treeaf9ef64305efd2e353a202c27b188d2c44cd9b5b /MediaBrowser.Server.Implementations/Session
parentc6e57c6448c04998bcae5a906e7a064300542e75 (diff)
parent2d9b48d00fd31aaa96676c82a054b2794493fbf9 (diff)
Merge branch 'master' of https://github.com/MediaBrowser/MediaBrowser
Diffstat (limited to 'MediaBrowser.Server.Implementations/Session')
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionManager.cs151
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs52
-rw-r--r--MediaBrowser.Server.Implementations/Session/WebSocketController.cs92
3 files changed, 274 insertions, 21 deletions
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index ce757d142..79dfbc8a5 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Events;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@@ -6,6 +7,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Session;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -75,6 +77,12 @@ namespace MediaBrowser.Server.Implementations.Session
_userRepository = userRepository;
}
+ private List<ISessionRemoteController> _remoteControllers;
+ public void AddParts(IEnumerable<ISessionRemoteController> remoteControllers)
+ {
+ _remoteControllers = remoteControllers.ToList();
+ }
+
/// <summary>
/// Gets all connections.
/// </summary>
@@ -122,7 +130,7 @@ namespace MediaBrowser.Server.Implementations.Session
var activityDate = DateTime.UtcNow;
var session = GetSessionInfo(clientType, appVersion, deviceId, deviceName, user);
-
+
session.LastActivityDate = activityDate;
if (user == null)
@@ -207,25 +215,33 @@ namespace MediaBrowser.Server.Implementations.Session
/// <summary>
/// Used to report that playback has started for an item
/// </summary>
- /// <param name="item">The item.</param>
- /// <param name="sessionId">The session id.</param>
+ /// <param name="info">The info.</param>
/// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException"></exception>
- public async Task OnPlaybackStart(BaseItem item, Guid sessionId)
+ /// <exception cref="System.ArgumentNullException">info</exception>
+ public async Task OnPlaybackStart(PlaybackInfo info)
{
- if (item == null)
+ if (info == null)
{
- throw new ArgumentNullException();
+ throw new ArgumentNullException("info");
+ }
+ if (info.SessionId == Guid.Empty)
+ {
+ throw new ArgumentNullException("info");
}
- var session = Sessions.First(i => i.Id.Equals(sessionId));
+ var session = Sessions.First(i => i.Id.Equals(info.SessionId));
+
+ var item = info.Item;
UpdateNowPlayingItem(session, item, false, false);
+ session.CanSeek = info.CanSeek;
+ session.QueueableMediaTypes = info.QueueableMediaTypes;
+
var key = item.GetUserDataKey();
var user = session.User;
-
+
var data = _userDataRepository.GetUserData(user.Id, key);
data.PlayCount++;
@@ -313,7 +329,7 @@ namespace MediaBrowser.Server.Implementations.Session
{
throw new ArgumentOutOfRangeException("positionTicks");
}
-
+
var session = Sessions.First(i => i.Id.Equals(sessionId));
RemoveNowPlayingItem(session, item);
@@ -321,7 +337,7 @@ namespace MediaBrowser.Server.Implementations.Session
var key = item.GetUserDataKey();
var user = session.User;
-
+
var data = _userDataRepository.GetUserData(user.Id, key);
if (positionTicks.HasValue)
@@ -400,5 +416,118 @@ namespace MediaBrowser.Server.Implementations.Session
data.PlaybackPositionTicks = positionTicks;
}
+
+ /// <summary>
+ /// Gets the session for remote control.
+ /// </summary>
+ /// <param name="sessionId">The session id.</param>
+ /// <returns>SessionInfo.</returns>
+ /// <exception cref="ResourceNotFoundException"></exception>
+ private SessionInfo GetSessionForRemoteControl(Guid sessionId)
+ {
+ var session = Sessions.First(i => i.Id.Equals(sessionId));
+
+ if (session == null)
+ {
+ throw new ResourceNotFoundException(string.Format("Session {0} not found.", sessionId));
+ }
+
+ if (!session.SupportsRemoteControl)
+ {
+ throw new ArgumentException(string.Format("Session {0} does not support remote control.", session.Id));
+ }
+
+ return session;
+ }
+
+ /// <summary>
+ /// Gets the controllers.
+ /// </summary>
+ /// <param name="session">The session.</param>
+ /// <returns>IEnumerable{ISessionRemoteController}.</returns>
+ private IEnumerable<ISessionRemoteController> GetControllers(SessionInfo session)
+ {
+ return _remoteControllers.Where(i => i.Supports(session));
+ }
+
+ /// <summary>
+ /// Sends the system command.
+ /// </summary>
+ /// <param name="sessionId">The session id.</param>
+ /// <param name="command">The command.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ public Task SendSystemCommand(Guid sessionId, SystemCommand command, CancellationToken cancellationToken)
+ {
+ var session = GetSessionForRemoteControl(sessionId);
+
+ var tasks = GetControllers(session).Select(i => i.SendSystemCommand(session, command, cancellationToken));
+
+ return Task.WhenAll(tasks);
+ }
+
+ /// <summary>
+ /// Sends the message command.
+ /// </summary>
+ /// <param name="sessionId">The session id.</param>
+ /// <param name="command">The command.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ public Task SendMessageCommand(Guid sessionId, MessageCommand command, CancellationToken cancellationToken)
+ {
+ var session = GetSessionForRemoteControl(sessionId);
+
+ var tasks = GetControllers(session).Select(i => i.SendMessageCommand(session, command, cancellationToken));
+
+ return Task.WhenAll(tasks);
+ }
+
+ /// <summary>
+ /// Sends the play command.
+ /// </summary>
+ /// <param name="sessionId">The session id.</param>
+ /// <param name="command">The command.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ public Task SendPlayCommand(Guid sessionId, PlayRequest command, CancellationToken cancellationToken)
+ {
+ var session = GetSessionForRemoteControl(sessionId);
+
+ var tasks = GetControllers(session).Select(i => i.SendPlayCommand(session, command, cancellationToken));
+
+ return Task.WhenAll(tasks);
+ }
+
+ /// <summary>
+ /// Sends the browse command.
+ /// </summary>
+ /// <param name="sessionId">The session id.</param>
+ /// <param name="command">The command.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ public Task SendBrowseCommand(Guid sessionId, BrowseRequest command, CancellationToken cancellationToken)
+ {
+ var session = GetSessionForRemoteControl(sessionId);
+
+ var tasks = GetControllers(session).Select(i => i.SendBrowseCommand(session, command, cancellationToken));
+
+ return Task.WhenAll(tasks);
+ }
+
+ /// <summary>
+ /// Sends the playstate command.
+ /// </summary>
+ /// <param name="sessionId">The session id.</param>
+ /// <param name="command">The command.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ public Task SendPlaystateCommand(Guid sessionId, PlaystateRequest command, CancellationToken cancellationToken)
+ {
+ var session = GetSessionForRemoteControl(sessionId);
+
+ var tasks = GetControllers(session).Select(i => i.SendPlaystateCommand(session, command, cancellationToken));
+
+ return Task.WhenAll(tasks);
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
index 2a4361e61..95eb5948f 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
@@ -101,16 +101,7 @@ namespace MediaBrowser.Server.Implementations.Session
}
else if (string.Equals(message.MessageType, "PlaybackStart", StringComparison.OrdinalIgnoreCase))
{
- _logger.Debug("Received PlaybackStart message");
-
- var session = _sessionManager.Sessions.FirstOrDefault(i => i.WebSockets.Contains(message.Connection));
-
- if (session != null && session.User != null)
- {
- var item = _dtoService.GetItemByDtoId(message.Data);
-
- _sessionManager.OnPlaybackStart(item, session.Id);
- }
+ ReportPlaybackStart(message);
}
else if (string.Equals(message.MessageType, "PlaybackProgress", StringComparison.OrdinalIgnoreCase))
{
@@ -170,5 +161,46 @@ namespace MediaBrowser.Server.Implementations.Session
return _trueTaskResult;
}
+
+ /// <summary>
+ /// Reports the playback start.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ private void ReportPlaybackStart(WebSocketMessageInfo message)
+ {
+ _logger.Debug("Received PlaybackStart message");
+
+ var session = _sessionManager.Sessions
+ .FirstOrDefault(i => i.WebSockets.Contains(message.Connection));
+
+ if (session != null && session.User != null)
+ {
+ var vals = message.Data.Split('|');
+
+ var item = _dtoService.GetItemByDtoId(vals[0]);
+
+ var queueableMediaTypes = string.Empty;
+ var canSeek = true;
+
+ if (vals.Length > 1)
+ {
+ canSeek = string.Equals(vals[1], "true", StringComparison.OrdinalIgnoreCase);
+ }
+ if (vals.Length > 2)
+ {
+ queueableMediaTypes = vals[2];
+ }
+
+ var info = new PlaybackInfo
+ {
+ CanSeek = canSeek,
+ Item = item,
+ SessionId = session.Id,
+ QueueableMediaTypes = queueableMediaTypes.Split(',').ToList()
+ };
+
+ _sessionManager.OnPlaybackStart(info);
+ }
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
new file mode 100644
index 000000000..6915cfc64
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
@@ -0,0 +1,92 @@
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Session;
+using MediaBrowser.Model.Net;
+using MediaBrowser.Model.Session;
+using System;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.Session
+{
+ public class WebSocketController : ISessionRemoteController
+ {
+ public bool Supports(SessionInfo session)
+ {
+ return session.WebSockets.Any(i => i.State == WebSocketState.Open);
+ }
+
+ private IWebSocketConnection GetSocket(SessionInfo session)
+ {
+ var socket = session.WebSockets.OrderByDescending(i => i.LastActivityDate).FirstOrDefault(i => i.State == WebSocketState.Open);
+
+
+ if (socket == null)
+ {
+ throw new InvalidOperationException("The requested session does not have an open web socket.");
+ }
+
+ return socket;
+ }
+
+ public Task SendSystemCommand(SessionInfo session, SystemCommand command, CancellationToken cancellationToken)
+ {
+ var socket = GetSocket(session);
+
+ return socket.SendAsync(new WebSocketMessage<string>
+ {
+ MessageType = "SystemCommand",
+ Data = command.ToString()
+
+ }, cancellationToken);
+ }
+
+ public Task SendMessageCommand(SessionInfo session, MessageCommand command, CancellationToken cancellationToken)
+ {
+ var socket = GetSocket(session);
+
+ return socket.SendAsync(new WebSocketMessage<MessageCommand>
+ {
+ MessageType = "MessageCommand",
+ Data = command
+
+ }, cancellationToken);
+ }
+
+ public Task SendPlayCommand(SessionInfo session, PlayRequest command, CancellationToken cancellationToken)
+ {
+ var socket = GetSocket(session);
+
+ return socket.SendAsync(new WebSocketMessage<PlayRequest>
+ {
+ MessageType = "Play",
+ Data = command
+
+ }, cancellationToken);
+ }
+
+ public Task SendBrowseCommand(SessionInfo session, BrowseRequest command, CancellationToken cancellationToken)
+ {
+ var socket = GetSocket(session);
+
+ return socket.SendAsync(new WebSocketMessage<BrowseRequest>
+ {
+ MessageType = "Browse",
+ Data = command
+
+ }, cancellationToken);
+ }
+
+ public Task SendPlaystateCommand(SessionInfo session, PlaystateRequest command, CancellationToken cancellationToken)
+ {
+ var socket = GetSocket(session);
+
+ return socket.SendAsync(new WebSocketMessage<PlaystateRequest>
+ {
+ MessageType = "Playstate",
+ Data = command
+
+ }, cancellationToken);
+ }
+ }
+}