diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/SessionsService.cs
index e688973f9..0e69c96d1 100644
--- a/MediaBrowser.Api/SessionsService.cs
+++ b/MediaBrowser.Api/SessionsService.cs
@@ -217,6 +217,9 @@ namespace MediaBrowser.Api
[ApiMember(Name = "SupportedCommands", Description = "A list of supported remote control commands, comma delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
public string SupportedCommands { get; set; }
+
+ [ApiMember(Name = "SupportsMediaControl", Description = "Determines whether media can be played remotely.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
+ public bool SupportsMediaControl { get; set; }
}
///
@@ -258,6 +261,8 @@ namespace MediaBrowser.Api
if (request.ControllableByUserId.HasValue)
{
+ result = result.Where(i => i.SupportsMediaControl);
+
var user = _userManager.GetUserById(request.ControllableByUserId.Value);
if (!user.Configuration.EnableRemoteControlOfOtherUsers)
@@ -407,7 +412,9 @@ namespace MediaBrowser.Api
{
PlayableMediaTypes = request.PlayableMediaTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
- SupportedCommands = request.SupportedCommands.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList()
+ SupportedCommands = request.SupportedCommands.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
+
+ SupportsMediaControl = request.SupportsMediaControl
});
}
diff --git a/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs b/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs
index 24ac48e83..014fd6f82 100644
--- a/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs
+++ b/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs
@@ -351,18 +351,21 @@ namespace MediaBrowser.Common.Implementations.IO
throw new ArgumentNullException("to");
}
- path = path.Replace(from, to, StringComparison.OrdinalIgnoreCase);
+ var newPath = path.Replace(from, to, StringComparison.OrdinalIgnoreCase);
- if (to.IndexOf('/') != -1)
+ if (!string.Equals(newPath, path))
{
- path = path.Replace('\\', '/');
- }
- else
- {
- path = path.Replace('/', '\\');
+ if (to.IndexOf('/') != -1)
+ {
+ newPath = path.Replace('\\', '/');
+ }
+ else
+ {
+ newPath = path.Replace('/', '\\');
+ }
}
- return path;
+ return newPath;
}
}
}
diff --git a/MediaBrowser.Common/Net/IWebSocket.cs b/MediaBrowser.Common/Net/IWebSocket.cs
index 748c6642c..05f7975bc 100644
--- a/MediaBrowser.Common/Net/IWebSocket.cs
+++ b/MediaBrowser.Common/Net/IWebSocket.cs
@@ -10,6 +10,11 @@ namespace MediaBrowser.Common.Net
///
public interface IWebSocket : IDisposable
{
+ ///
+ /// Occurs when [closed].
+ ///
+ event EventHandler Closed;
+
///
/// Gets or sets the state.
///
diff --git a/MediaBrowser.Common/Net/IWebSocketConnection.cs b/MediaBrowser.Common/Net/IWebSocketConnection.cs
index 514a52d96..9f9dfaeca 100644
--- a/MediaBrowser.Common/Net/IWebSocketConnection.cs
+++ b/MediaBrowser.Common/Net/IWebSocketConnection.cs
@@ -7,6 +7,11 @@ namespace MediaBrowser.Common.Net
{
public interface IWebSocketConnection : IDisposable
{
+ ///
+ /// Occurs when [closed].
+ ///
+ event EventHandler Closed;
+
///
/// Gets the id.
///
diff --git a/MediaBrowser.Controller/Session/ISessionController.cs b/MediaBrowser.Controller/Session/ISessionController.cs
index 1b50bad47..5f07b9ff8 100644
--- a/MediaBrowser.Controller/Session/ISessionController.cs
+++ b/MediaBrowser.Controller/Session/ISessionController.cs
@@ -13,6 +13,12 @@ namespace MediaBrowser.Controller.Session
/// 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 play command.
///
diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs
index 9f5b687cc..bc0f8a5d1 100644
--- a/MediaBrowser.Controller/Session/SessionInfo.cs
+++ b/MediaBrowser.Controller/Session/SessionInfo.cs
@@ -139,6 +139,19 @@ namespace MediaBrowser.Controller.Session
}
}
+ public bool SupportsMediaControl
+ {
+ get
+ {
+ if (SessionController != null)
+ {
+ return SessionController.SupportsMediaControl;
+ }
+
+ return false;
+ }
+ }
+
public bool ContainsUser(Guid userId)
{
return (UserId ?? Guid.Empty) == UserId || AdditionalUsers.Any(i => userId == new Guid(i.UserId));
diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
index f0fc8c485..9312b8442 100644
--- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs
+++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
@@ -46,6 +46,11 @@ namespace MediaBrowser.Dlna.PlayTo
}
}
+ public bool SupportsMediaControl
+ {
+ get { return IsSessionActive; }
+ }
+
private Timer _updateTimer;
public PlayToController(SessionInfo session, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IDtoService dtoService, IImageProcessor imageProcessor, SsdpHandler ssdpHandler, string serverAddress)
diff --git a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs
index 5bd85d3c9..240a87b90 100644
--- a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs
+++ b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs
@@ -306,7 +306,9 @@ namespace MediaBrowser.Dlna.PlayTo
GeneralCommandType.Unmute.ToString(),
GeneralCommandType.ToggleMute.ToString(),
GeneralCommandType.SetVolume.ToString()
- }
+ },
+
+ SupportsMediaControl = true
});
_logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);
diff --git a/MediaBrowser.Model/Configuration/LiveTvOptions.cs b/MediaBrowser.Model/Configuration/LiveTvOptions.cs
index ae8aeb200..575f0b863 100644
--- a/MediaBrowser.Model/Configuration/LiveTvOptions.cs
+++ b/MediaBrowser.Model/Configuration/LiveTvOptions.cs
@@ -3,5 +3,6 @@
public class LiveTvOptions
{
public int? GuideDays { get; set; }
+ public string ActiveService { get; set; }
}
}
\ No newline at end of file
diff --git a/MediaBrowser.Model/Session/SessionCapabilities.cs b/MediaBrowser.Model/Session/SessionCapabilities.cs
index 290b0e4d4..5eeede126 100644
--- a/MediaBrowser.Model/Session/SessionCapabilities.cs
+++ b/MediaBrowser.Model/Session/SessionCapabilities.cs
@@ -8,6 +8,8 @@ namespace MediaBrowser.Model.Session
public List SupportedCommands { get; set; }
+ public bool SupportsMediaControl { get; set; }
+
public SessionCapabilities()
{
PlayableMediaTypes = new List();
diff --git a/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs b/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs
index ff822a4e6..f89cdac47 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Common.Net;
using MediaBrowser.Model.Logging;
using System;
using System.Net.WebSockets;
@@ -19,6 +20,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer
///
private readonly ILogger _logger;
+ public event EventHandler Closed;
+
///
/// Gets or sets the web socket.
///
@@ -97,6 +100,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
if (bytes == null)
{
// Connection closed
+ EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger);
break;
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
index 11d010ca1..d989c0866 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -84,7 +84,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
_services.AddRange(services);
- SetActiveService(_services.FirstOrDefault());
+ SetActiveService(_config.Configuration.LiveTvOptions.ActiveService);
+ }
+
+ private void SetActiveService(string name)
+ {
+ var service = _services.FirstOrDefault(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase)) ??
+ _services.FirstOrDefault();
+
+ SetActiveService(service);
}
private void SetActiveService(ILiveTvService service)
diff --git a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
index b800a9cbe..2b60f3116 100644
--- a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
+++ b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Common.Net;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization;
@@ -14,6 +15,8 @@ namespace MediaBrowser.Server.Implementations.ServerManager
///
public class WebSocketConnection : IWebSocketConnection
{
+ public event EventHandler Closed;
+
///
/// The _socket
///
@@ -96,6 +99,13 @@ namespace MediaBrowser.Server.Implementations.ServerManager
_socket.OnReceive = OnReceiveInternal;
RemoteEndPoint = remoteEndPoint;
_logger = logger;
+
+ socket.Closed += socket_Closed;
+ }
+
+ void socket_Closed(object sender, EventArgs e)
+ {
+ EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger);
}
///
diff --git a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs b/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs
index 8d6289217..236963b9b 100644
--- a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs
+++ b/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs
@@ -45,6 +45,11 @@ namespace MediaBrowser.Server.Implementations.Session
}
}
+ public bool SupportsMediaControl
+ {
+ get { return true; }
+ }
+
private Task SendMessage(object obj, CancellationToken cancellationToken)
{
var json = _json.SerializeToString(obj);
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index 26e451a81..cfa7cef67 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -1164,7 +1164,7 @@ namespace MediaBrowser.Server.Implementations.Session
SupportedCommands = session.SupportedCommands,
UserName = session.UserName,
NowPlayingItem = session.NowPlayingItem,
-
+ SupportsRemoteControl = session.SupportsMediaControl,
PlayState = session.PlayState
};
diff --git a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
index 565d83ac3..1a042ede6 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
@@ -138,10 +138,10 @@ namespace MediaBrowser.Server.Implementations.Session
if (controller == null)
{
- controller = new WebSocketController(session, _appHost, _logger);
+ controller = new WebSocketController(session, _appHost, _logger, _sessionManager);
}
- controller.Sockets.Add(message.Connection);
+ controller.AddWebSocket(message.Connection);
session.SessionController = controller;
}
diff --git a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
index 040705171..6f4dd0a72 100644
--- a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
+++ b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
@@ -17,16 +17,19 @@ namespace MediaBrowser.Server.Implementations.Session
public class WebSocketController : ISessionController
{
public SessionInfo Session { get; private set; }
- public List Sockets { get; private set; }
+ public IReadOnlyList Sockets { get; private set; }
private readonly IServerApplicationHost _appHost;
private readonly ILogger _logger;
- public WebSocketController(SessionInfo session, IServerApplicationHost appHost, ILogger logger)
+ private readonly ISessionManager _sessionManager;
+
+ public WebSocketController(SessionInfo session, IServerApplicationHost appHost, ILogger logger, ISessionManager sessionManager)
{
Session = session;
_appHost = appHost;
_logger = logger;
+ _sessionManager = sessionManager;
Sockets = new List();
}
@@ -38,6 +41,11 @@ namespace MediaBrowser.Server.Implementations.Session
}
}
+ public bool SupportsMediaControl
+ {
+ get { return GetActiveSockets().Any(); }
+ }
+
private IEnumerable GetActiveSockets()
{
return Sockets
@@ -45,6 +53,28 @@ namespace MediaBrowser.Server.Implementations.Session
.Where(i => i.State == WebSocketState.Open);
}
+ public void AddWebSocket(IWebSocketConnection connection)
+ {
+ var sockets = Sockets.ToList();
+ sockets.Add(connection);
+
+ Sockets = sockets;
+
+ connection.Closed += connection_Closed;
+ }
+
+ void connection_Closed(object sender, EventArgs e)
+ {
+ var capabilities = new SessionCapabilities
+ {
+ PlayableMediaTypes = Session.PlayableMediaTypes,
+ SupportedCommands = Session.SupportedCommands,
+ SupportsMediaControl = SupportsMediaControl
+ };
+
+ _sessionManager.ReportCapabilities(Session.Id, capabilities);
+ }
+
private IWebSocketConnection GetActiveSocket()
{
var socket = GetActiveSockets()
diff --git a/MediaBrowser.Server.Implementations/WebSocket/AlchemyWebSocket.cs b/MediaBrowser.Server.Implementations/WebSocket/AlchemyWebSocket.cs
index 2918c7ecd..35c5e780b 100644
--- a/MediaBrowser.Server.Implementations/WebSocket/AlchemyWebSocket.cs
+++ b/MediaBrowser.Server.Implementations/WebSocket/AlchemyWebSocket.cs
@@ -1,4 +1,5 @@
using Alchemy.Classes;
+using MediaBrowser.Common.Events;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
@@ -18,6 +19,8 @@ namespace MediaBrowser.Server.Implementations.WebSocket
///
private readonly ILogger _logger;
+ public event EventHandler Closed;
+
///
/// Gets or sets the web socket.
///
@@ -66,6 +69,8 @@ namespace MediaBrowser.Server.Implementations.WebSocket
private void OnDisconnected(UserContext context)
{
_disconnected = true;
+
+ EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger);
}
///
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec
index 1c90bdc87..6dd8fb458 100644
--- a/Nuget/MediaBrowser.Common.Internal.nuspec
+++ b/Nuget/MediaBrowser.Common.Internal.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Common.Internal
- 3.0.366
+ 3.0.367
MediaBrowser.Common.Internal
Luke
ebr,Luke,scottisafool
@@ -12,7 +12,7 @@
Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.
Copyright © Media Browser 2013
-
+
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index 72bd0cbc0..2a9820925 100644
--- a/Nuget/MediaBrowser.Common.nuspec
+++ b/Nuget/MediaBrowser.Common.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Common
- 3.0.366
+ 3.0.367
MediaBrowser.Common
Media Browser Team
ebr,Luke,scottisafool
diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec
index 2fa54ab0d..7df46236c 100644
--- a/Nuget/MediaBrowser.Server.Core.nuspec
+++ b/Nuget/MediaBrowser.Server.Core.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Server.Core
- 3.0.366
+ 3.0.367
Media Browser.Server.Core
Media Browser Team
ebr,Luke,scottisafool
@@ -12,7 +12,7 @@
Contains core components required to build plugins for Media Browser Server.
Copyright © Media Browser 2013
-
+