Преглед изворни кода

make metadata path configurable

Luke Pulverenti пре 11 година
родитељ
комит
31e8288393
33 измењених фајлова са 204 додато и 339 уклоњено
  1. 5 9
      MediaBrowser.Api/AppThemeService.cs
  2. 15 0
      MediaBrowser.Api/BaseApiService.cs
  3. 5 10
      MediaBrowser.Api/ConfigurationService.cs
  4. 11 1
      MediaBrowser.Api/Library/LibraryService.cs
  5. 2 4
      MediaBrowser.Api/Movies/MoviesService.cs
  6. 1 2
      MediaBrowser.Api/Movies/TrailersService.cs
  7. 4 8
      MediaBrowser.Api/Music/InstantMixService.cs
  8. 6 11
      MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
  9. 2 5
      MediaBrowser.Api/UserLibrary/StudiosService.cs
  10. 5 14
      MediaBrowser.Api/UserLibrary/UserLibraryService.cs
  11. 1 1
      MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs
  12. 1 3
      MediaBrowser.Controller/Dlna/CodecProfile.cs
  13. 1 4
      MediaBrowser.Controller/Entities/User.cs
  14. 7 1
      MediaBrowser.Dlna/PlayTo/PlayToManager.cs
  15. 0 8
      MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs
  16. 20 4
      MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs
  17. 1 3
      MediaBrowser.Dlna/PlayTo/StreamHelper.cs
  18. 1 1
      MediaBrowser.Dlna/Profiles/DefaultProfile.cs
  19. 2 13
      MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs
  20. 2 13
      MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs
  21. 2 13
      MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs
  22. 2 13
      MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs
  23. 6 0
      MediaBrowser.Model/Configuration/ServerConfiguration.cs
  24. 3 1
      MediaBrowser.Model/Configuration/UserConfiguration.cs
  25. 8 5
      MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
  26. 32 0
      MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
  27. 39 19
      MediaBrowser.Server.Implementations/Library/UserManager.cs
  28. 9 3
      MediaBrowser.Server.Implementations/ServerApplicationPaths.cs
  29. 1 1
      MediaBrowser.ServerApplication/ApplicationHost.cs
  30. 0 39
      MediaBrowser.WebDashboard/Api/DashboardInfo.cs
  31. 0 62
      MediaBrowser.WebDashboard/Api/DashboardInfoWebSocketListener.cs
  32. 4 66
      MediaBrowser.WebDashboard/Api/DashboardService.cs
  33. 6 2
      MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj

+ 5 - 9
MediaBrowser.Api/AppThemeService.cs

@@ -9,16 +9,14 @@ using System.Linq;
 
 namespace MediaBrowser.Api
 {
-    [Route("/Themes", "GET")]
-    [Api(Description = "Gets a list of available themes for an app")]
+    [Route("/Themes", "GET", Summary = "Gets a list of available themes for an app")]
     public class GetAppThemes : IReturn<List<AppThemeInfo>>
     {
         [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
         public string App { get; set; }
     }
 
-    [Route("/Themes/Info", "GET")]
-    [Api(Description = "Gets an app theme")]
+    [Route("/Themes/Info", "GET", Summary = "Gets an app theme")]
     public class GetAppTheme : IReturn<AppTheme>
     {
         [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@@ -28,8 +26,7 @@ namespace MediaBrowser.Api
         public string Name { get; set; }
     }
 
-    [Route("/Themes/Images", "GET")]
-    [Api(Description = "Gets an app theme")]
+    [Route("/Themes/Images", "GET", Summary = "Gets an app theme")]
     public class GetAppThemeImage
     {
         [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@@ -45,12 +42,11 @@ namespace MediaBrowser.Api
         public string CacheTag { get; set; }
     }
 
-    [Route("/Themes", "POST")]
-    [Api(Description = "Saves a theme")]
+    [Route("/Themes", "POST", Summary = "Saves a theme")]
     public class SaveTheme : AppTheme, IReturnVoid
     {
     }
-    
+
     public class AppThemeService : BaseApiService
     {
         private readonly IAppThemeManager _themeManager;

+ 15 - 0
MediaBrowser.Api/BaseApiService.cs

@@ -2,6 +2,7 @@
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Net;
+using MediaBrowser.Controller.Session;
 using MediaBrowser.Model.Logging;
 using ServiceStack.Web;
 using System;
@@ -78,6 +79,20 @@ namespace MediaBrowser.Api
             return ToOptimizedResult(result);
         }
 
+        /// <summary>
+        /// Gets the session.
+        /// </summary>
+        /// <param name="sessionManager">The session manager.</param>
+        /// <returns>SessionInfo.</returns>
+        protected SessionInfo GetSession(ISessionManager sessionManager)
+        {
+            var auth = AuthorizationRequestFilterAttribute.GetAuthorization(Request);
+
+            return sessionManager.Sessions.First(i => string.Equals(i.DeviceId, auth.DeviceId) &&
+                string.Equals(i.Client, auth.Client) &&
+                string.Equals(i.ApplicationVersion, auth.Version));
+        }
+
         /// <summary>
         /// To the cached result.
         /// </summary>

+ 5 - 10
MediaBrowser.Api/ConfigurationService.cs

@@ -17,8 +17,7 @@ namespace MediaBrowser.Api
     /// <summary>
     /// Class GetConfiguration
     /// </summary>
-    [Route("/System/Configuration", "GET")]
-    [Api(("Gets application configuration"))]
+    [Route("/System/Configuration", "GET", Summary = "Gets application configuration")]
     public class GetConfiguration : IReturn<ServerConfiguration>
     {
 
@@ -27,28 +26,24 @@ namespace MediaBrowser.Api
     /// <summary>
     /// Class UpdateConfiguration
     /// </summary>
-    [Route("/System/Configuration", "POST")]
-    [Api(("Updates application configuration"))]
+    [Route("/System/Configuration", "POST", Summary = "Updates application configuration")]
     public class UpdateConfiguration : ServerConfiguration, IReturnVoid
     {
     }
 
-    [Route("/System/Configuration/MetadataOptions/Default", "GET")]
-    [Api(("Gets a default MetadataOptions object"))]
+    [Route("/System/Configuration/MetadataOptions/Default", "GET", Summary = "Gets a default MetadataOptions object")]
     public class GetDefaultMetadataOptions : IReturn<MetadataOptions>
     {
 
     }
 
-    [Route("/System/Configuration/MetadataPlugins", "GET")]
-    [Api(("Gets all available metadata plugins"))]
+    [Route("/System/Configuration/MetadataPlugins", "GET", Summary = "Gets all available metadata plugins")]
     public class GetMetadataPlugins : IReturn<List<MetadataPluginSummary>>
     {
 
     }
 
-    [Route("/System/Configuration/VideoImageExtraction", "POST")]
-    [Api(("Updates image extraction for all types"))]
+    [Route("/System/Configuration/VideoImageExtraction", "POST", Summary = "Updates image extraction for all types")]
     public class UpdateVideoImageExtraction : IReturnVoid
     {
         public bool Enabled { get; set; }

+ 11 - 1
MediaBrowser.Api/Library/LibraryService.cs

@@ -7,6 +7,7 @@ using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.Session;
 using MediaBrowser.Model.Channels;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
@@ -245,12 +246,13 @@ namespace MediaBrowser.Api.Library
 
         private readonly IDtoService _dtoService;
         private readonly IChannelManager _channelManager;
+        private readonly ISessionManager _sessionManager;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="LibraryService" /> class.
         /// </summary>
         public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
-                              IDtoService dtoService, IUserDataManager userDataManager, IChannelManager channelManager)
+                              IDtoService dtoService, IUserDataManager userDataManager, IChannelManager channelManager, ISessionManager sessionManager)
         {
             _itemRepo = itemRepo;
             _libraryManager = libraryManager;
@@ -258,6 +260,7 @@ namespace MediaBrowser.Api.Library
             _dtoService = dtoService;
             _userDataManager = userDataManager;
             _channelManager = channelManager;
+            _sessionManager = sessionManager;
         }
 
         public object Get(GetMediaFolders request)
@@ -504,6 +507,13 @@ namespace MediaBrowser.Api.Library
         {
             var item = _dtoService.GetItemByDtoId(request.Id);
 
+            var session = GetSession(_sessionManager);
+
+            if (!session.UserId.HasValue || !_userManager.GetUserById(session.UserId.Value).Configuration.EnableContentDeletion)
+            {
+                throw new UnauthorizedAccessException("This operation requires a logged in user with delete access.");
+            }
+            
             return _libraryManager.DeleteItem(item);
         }
 

+ 2 - 4
MediaBrowser.Api/Movies/MoviesService.cs

@@ -17,8 +17,7 @@ namespace MediaBrowser.Api.Movies
     /// <summary>
     /// Class GetSimilarMovies
     /// </summary>
-    [Route("/Movies/{Id}/Similar", "GET")]
-    [Api(Description = "Finds movies and trailers similar to a given movie.")]
+    [Route("/Movies/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given movie.")]
     public class GetSimilarMovies : BaseGetSimilarItemsFromItem
     {
         [ApiMember(Name = "IncludeTrailers", Description = "Whether or not to include trailers within the results. Defaults to true.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
@@ -30,8 +29,7 @@ namespace MediaBrowser.Api.Movies
         }
     }
 
-    [Route("/Movies/Recommendations", "GET")]
-    [Api(Description = "Gets movie recommendations")]
+    [Route("/Movies/Recommendations", "GET", Summary = "Gets movie recommendations")]
     public class GetMovieRecommendations : IReturn<RecommendationDto[]>, IHasItemFields
     {
         [ApiMember(Name = "CategoryLimit", Description = "The max number of categories to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]

+ 1 - 2
MediaBrowser.Api/Movies/TrailersService.cs

@@ -10,8 +10,7 @@ namespace MediaBrowser.Api.Movies
     /// <summary>
     /// Class GetSimilarTrailers
     /// </summary>
-    [Route("/Trailers/{Id}/Similar", "GET")]
-    [Api(Description = "Finds movies and trailers similar to a given trailer.")]
+    [Route("/Trailers/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
     public class GetSimilarTrailers : BaseGetSimilarItemsFromItem
     {
     }

+ 4 - 8
MediaBrowser.Api/Music/InstantMixService.cs

@@ -9,28 +9,24 @@ using System.Linq;
 
 namespace MediaBrowser.Api.Music
 {
-    [Route("/Songs/{Id}/InstantMix", "GET")]
-    [Api(Description = "Creates an instant playlist based on a given song")]
+    [Route("/Songs/{Id}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given song")]
     public class GetInstantMixFromSong : BaseGetSimilarItemsFromItem
     {
     }
 
-    [Route("/Albums/{Id}/InstantMix", "GET")]
-    [Api(Description = "Creates an instant playlist based on a given album")]
+    [Route("/Albums/{Id}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given album")]
     public class GetInstantMixFromAlbum : BaseGetSimilarItemsFromItem
     {
     }
 
-    [Route("/Artists/{Name}/InstantMix", "GET")]
-    [Api(Description = "Creates an instant playlist based on a given artist")]
+    [Route("/Artists/{Name}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given artist")]
     public class GetInstantMixFromArtist : BaseGetSimilarItems
     {
         [ApiMember(Name = "Name", Description = "The artist name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
         public string Name { get; set; }
     }
 
-    [Route("/MusicGenres/{Name}/InstantMix", "GET")]
-    [Api(Description = "Creates an instant playlist based on a music genre")]
+    [Route("/MusicGenres/{Name}/InstantMix", "GET", Summary = "Creates an instant playlist based on a music genre")]
     public class GetInstantMixFromMusicGenre : BaseGetSimilarItems
     {
         [ApiMember(Name = "Name", Description = "The genre name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]

+ 6 - 11
MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs

@@ -2,18 +2,17 @@
 using MediaBrowser.Common.ScheduledTasks;
 using MediaBrowser.Model.Tasks;
 using ServiceStack;
+using ServiceStack.Text.Controller;
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using ServiceStack.Text.Controller;
 
 namespace MediaBrowser.Api.ScheduledTasks
 {
     /// <summary>
     /// Class GetScheduledTask
     /// </summary>
-    [Route("/ScheduledTasks/{Id}", "GET")]
-    [Api(Description = "Gets a scheduled task, by Id")]
+    [Route("/ScheduledTasks/{Id}", "GET", Summary = "Gets a scheduled task, by Id")]
     public class GetScheduledTask : IReturn<TaskInfo>
     {
         /// <summary>
@@ -27,8 +26,7 @@ namespace MediaBrowser.Api.ScheduledTasks
     /// <summary>
     /// Class GetScheduledTasks
     /// </summary>
-    [Route("/ScheduledTasks", "GET")]
-    [Api(Description = "Gets scheduled tasks")]
+    [Route("/ScheduledTasks", "GET", Summary = "Gets scheduled tasks")]
     public class GetScheduledTasks : IReturn<List<TaskInfo>>
     {
         [ApiMember(Name = "IsHidden", Description = "Optional filter tasks that are hidden, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
@@ -38,8 +36,7 @@ namespace MediaBrowser.Api.ScheduledTasks
     /// <summary>
     /// Class StartScheduledTask
     /// </summary>
-    [Route("/ScheduledTasks/Running/{Id}", "POST")]
-    [Api(Description = "Starts a scheduled task")]
+    [Route("/ScheduledTasks/Running/{Id}", "POST", Summary = "Starts a scheduled task")]
     public class StartScheduledTask : IReturnVoid
     {
         /// <summary>
@@ -53,8 +50,7 @@ namespace MediaBrowser.Api.ScheduledTasks
     /// <summary>
     /// Class StopScheduledTask
     /// </summary>
-    [Route("/ScheduledTasks/Running/{Id}", "DELETE")]
-    [Api(Description = "Stops a scheduled task")]
+    [Route("/ScheduledTasks/Running/{Id}", "DELETE", Summary = "Stops a scheduled task")]
     public class StopScheduledTask : IReturnVoid
     {
         /// <summary>
@@ -68,8 +64,7 @@ namespace MediaBrowser.Api.ScheduledTasks
     /// <summary>
     /// Class UpdateScheduledTaskTriggers
     /// </summary>
-    [Route("/ScheduledTasks/{Id}/Triggers", "POST")]
-    [Api(Description = "Updates the triggers for a scheduled task")]
+    [Route("/ScheduledTasks/{Id}/Triggers", "POST", Summary = "Updates the triggers for a scheduled task")]
     public class UpdateScheduledTaskTriggers : List<TaskTriggerInfo>, IReturnVoid
     {
         /// <summary>

+ 2 - 5
MediaBrowser.Api/UserLibrary/StudiosService.cs

@@ -8,15 +8,13 @@ using ServiceStack;
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.UserLibrary
 {
     /// <summary>
     /// Class GetStudios
     /// </summary>
-    [Route("/Studios", "GET")]
-    [Api(Description = "Gets all studios from a given item, folder, or the entire library")]
+    [Route("/Studios", "GET", Summary = "Gets all studios from a given item, folder, or the entire library")]
     public class GetStudios : GetItemsByName
     {
     }
@@ -24,8 +22,7 @@ namespace MediaBrowser.Api.UserLibrary
     /// <summary>
     /// Class GetStudio
     /// </summary>
-    [Route("/Studios/{Name}", "GET")]
-    [Api(Description = "Gets a studio, by name")]
+    [Route("/Studios/{Name}", "GET", Summary = "Gets a studio, by name")]
     public class GetStudio : IReturn<BaseItemDto>
     {
         /// <summary>

+ 5 - 14
MediaBrowser.Api/UserLibrary/UserLibraryService.cs

@@ -705,7 +705,7 @@ namespace MediaBrowser.Api.UserLibrary
                 datePlayed = DateTime.ParseExact(request.DatePlayed, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
             }
 
-            var session = GetSession();
+            var session = GetSession(_sessionManager);
 
             var dto = await UpdatePlayedStatus(user, request.Id, true, datePlayed).ConfigureAwait(false);
 
@@ -719,15 +719,6 @@ namespace MediaBrowser.Api.UserLibrary
             return dto;
         }
 
-        private SessionInfo GetSession()
-        {
-            var auth = AuthorizationRequestFilterAttribute.GetAuthorization(Request);
-
-            return _sessionManager.Sessions.First(i => string.Equals(i.DeviceId, auth.DeviceId) &&
-                string.Equals(i.Client, auth.Client) &&
-                string.Equals(i.ApplicationVersion, auth.Version));
-        }
-
         /// <summary>
         /// Posts the specified request.
         /// </summary>
@@ -744,7 +735,7 @@ namespace MediaBrowser.Api.UserLibrary
             {
                 CanSeek = request.CanSeek,
                 Item = item,
-                SessionId = GetSession().Id,
+                SessionId = GetSession(_sessionManager).Id,
                 QueueableMediaTypes = queueableMediaTypes.Split(',').ToList(),
                 MediaSourceId = request.MediaSourceId
             };
@@ -768,7 +759,7 @@ namespace MediaBrowser.Api.UserLibrary
                 PositionTicks = request.PositionTicks,
                 IsMuted = request.IsMuted,
                 IsPaused = request.IsPaused,
-                SessionId = GetSession().Id,
+                SessionId = GetSession(_sessionManager).Id,
                 MediaSourceId = request.MediaSourceId
             };
 
@@ -787,7 +778,7 @@ namespace MediaBrowser.Api.UserLibrary
 
             var item = _dtoService.GetItemByDtoId(request.Id, user.Id);
 
-            var session = GetSession();
+            var session = GetSession(_sessionManager);
 
             var info = new PlaybackStopInfo
             {
@@ -817,7 +808,7 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var session = GetSession();
+            var session = GetSession(_sessionManager);
 
             var dto = await UpdatePlayedStatus(user, request.Id, false, null).ConfigureAwait(false);
 

+ 1 - 1
MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs

@@ -49,7 +49,7 @@ namespace MediaBrowser.Api.WebSocket
         /// <returns>Task{SystemInfo}.</returns>
         protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(object state)
         {
-            return Task.FromResult(_sessionManager.Sessions.Select(_dtoService.GetSessionInfoDto));
+            return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_dtoService.GetSessionInfoDto));
         }
     }
 }

+ 1 - 3
MediaBrowser.Controller/Dlna/CodecProfile.cs

@@ -69,8 +69,6 @@ namespace MediaBrowser.Controller.Dlna
         VideoBitrate,
         VideoFramerate,
         VideoLevel,
-        VideoPacketLength,
-        VideoProfile,
-        VideoTimestamp
+        VideoProfile
     }
 }

+ 1 - 4
MediaBrowser.Controller/Entities/User.cs

@@ -121,10 +121,7 @@ namespace MediaBrowser.Controller.Entities
             {
                 _configuration = value;
 
-                if (value == null)
-                {
-                    _configurationInitialized = false;
-                }
+                _configurationInitialized = value != null;
             }
         }
 

+ 7 - 1
MediaBrowser.Dlna/PlayTo/PlayToManager.cs

@@ -241,7 +241,13 @@ namespace MediaBrowser.Dlna.PlayTo
 
                     _sessionManager.ReportCapabilities(sessionInfo.Id, new SessionCapabilities
                     {
-                        PlayableMediaTypes = new[] { MediaType.Audio, MediaType.Video, MediaType.Photo },
+                        PlayableMediaTypes = new[]
+                        {
+                            MediaType.Audio, 
+                            MediaType.Video, 
+                            MediaType.Photo
+                        },
+
                         SupportsFullscreenToggle = false
                     });
 

+ 0 - 8
MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs

@@ -191,9 +191,7 @@ namespace MediaBrowser.Dlna.PlayTo
                     case ProfileConditionValue.AudioProfile:
                     case ProfileConditionValue.Has64BitOffsets:
                     case ProfileConditionValue.VideoBitDepth:
-                    case ProfileConditionValue.VideoPacketLength:
                     case ProfileConditionValue.VideoProfile:
-                    case ProfileConditionValue.VideoTimestamp:
                     {
                         // Not supported yet
                         break;
@@ -461,12 +459,6 @@ namespace MediaBrowser.Dlna.PlayTo
                     return videoStream == null ? null : videoStream.Width;
                 case ProfileConditionValue.VideoLevel:
                     return videoStream == null ? null : ConvertToLong(videoStream.Level);
-                case ProfileConditionValue.VideoPacketLength:
-                    // TODO: Determine how to get this
-                    return null;
-                case ProfileConditionValue.VideoTimestamp:
-                    // TODO: Determine how to get this
-                    return null;
                 default:
                     throw new InvalidOperationException("Unexpected Property");
             }

+ 20 - 4
MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs

@@ -22,7 +22,11 @@ namespace MediaBrowser.Dlna.PlayTo
             _config = config;
         }
 
-        public async Task<XDocument> SendCommandAsync(string baseUrl, DeviceService service, string command, string postData, string header = null)
+        public async Task<XDocument> SendCommandAsync(string baseUrl, 
+            DeviceService service, 
+            string command, 
+            string postData, 
+            string header = null)
         {
             var serviceUrl = service.ControlUrl;
             if (!serviceUrl.StartsWith("/"))
@@ -40,7 +44,12 @@ namespace MediaBrowser.Dlna.PlayTo
             }
         }
 
-        public async Task SubscribeAsync(string url, string ip, int port, string localIp, int eventport, int timeOut = 3600)
+        public async Task SubscribeAsync(string url, 
+            string ip, 
+            int port, 
+            string localIp, 
+            int eventport, 
+            int timeOut = 3600)
         {
             var options = new HttpRequestOptions
             {
@@ -59,7 +68,11 @@ namespace MediaBrowser.Dlna.PlayTo
             }
         }
 
-        public async Task RespondAsync(Uri url, string ip, int port, string localIp, int eventport, int timeOut = 20000)
+        public async Task RespondAsync(Uri url, 
+            string ip, 
+            int port, 
+            string localIp, 
+            int eventport)
         {
             var options = new HttpRequestOptions
             {
@@ -97,7 +110,10 @@ namespace MediaBrowser.Dlna.PlayTo
             }
         }
 
-        private Task<HttpResponseInfo> PostSoapDataAsync(string url, string soapAction, string postData, string header = null)
+        private Task<HttpResponseInfo> PostSoapDataAsync(string url, 
+            string soapAction, 
+            string postData, 
+            string header = null)
         {
             if (!soapAction.StartsWith("\""))
                 soapAction = "\"" + soapAction + "\"";

+ 1 - 3
MediaBrowser.Dlna/PlayTo/StreamHelper.cs

@@ -1,8 +1,6 @@
-using MediaBrowser.Controller.Dlna;
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Entities;
 using System.Collections.Generic;
 using System.Globalization;
-using System.Linq;
 
 namespace MediaBrowser.Dlna.PlayTo
 {

+ 1 - 1
MediaBrowser.Dlna/Profiles/DefaultProfile.cs

@@ -6,7 +6,7 @@ namespace MediaBrowser.Dlna.Profiles
     {
         public DefaultProfile()
         {
-            Name = "Generic Device";
+            Name = "Media Browser";
 
             ProtocolInfo = "DLNA";
 

+ 2 - 13
MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs

@@ -96,13 +96,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/vnd.dlna.mpeg-tts",
                     OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile
@@ -112,12 +106,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/mpeg",
                     OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile

+ 2 - 13
MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs

@@ -138,13 +138,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/vnd.dlna.mpeg-tts",
                     OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile
@@ -154,12 +148,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/mpeg",
                     OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile

+ 2 - 13
MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs

@@ -126,13 +126,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/vnd.dlna.mpeg-tts",
                     OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile
@@ -142,12 +136,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/mpeg",
                     OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile

+ 2 - 13
MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs

@@ -182,13 +182,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/vnd.dlna.mpeg-tts",
                     OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile
@@ -198,12 +192,7 @@ namespace MediaBrowser.Dlna.Profiles
                     AudioCodec="ac3,aac,mp3",
                     MimeType = "video/mpeg",
                     OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new []
-                    {
-                        new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
-                    }
+                    Type = DlnaProfileType.Video
                 },
 
                 new MediaProfile

+ 6 - 0
MediaBrowser.Model/Configuration/ServerConfiguration.cs

@@ -57,6 +57,12 @@ namespace MediaBrowser.Model.Configuration
         /// <value>The item by name path.</value>
         public string ItemsByNamePath { get; set; }
 
+        /// <summary>
+        /// Gets or sets the metadata path.
+        /// </summary>
+        /// <value>The metadata path.</value>
+        public string MetadataPath { get; set; }
+        
         /// <summary>
         /// Gets or sets the display name of the season zero.
         /// </summary>

+ 3 - 1
MediaBrowser.Model/Configuration/UserConfiguration.cs

@@ -52,6 +52,7 @@ namespace MediaBrowser.Model.Configuration
         public bool EnableLiveTvAccess { get; set; }
 
         public bool EnableMediaPlayback { get; set; }
+        public bool EnableContentDeletion { get; set; }
 
         public string[] BlockedMediaFolders { get; set; }
 
@@ -63,8 +64,9 @@ namespace MediaBrowser.Model.Configuration
         public UserConfiguration()
         {
             IsAdministrator = true;
-            EnableRemoteControlOfOtherUsers = true;
 
+            EnableRemoteControlOfOtherUsers = true;
+            EnableContentDeletion = true;
             EnableLiveTvManagement = true;
             EnableMediaPlayback = true;
             EnableLiveTvAccess = true;

+ 8 - 5
MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs

@@ -148,7 +148,7 @@ namespace MediaBrowser.Providers.MediaInfo
 
                 if (!string.IsNullOrWhiteSpace(composer))
                 {
-                    foreach (var person in Split(composer))
+                    foreach (var person in Split(composer, false))
                     {
                         audio.AddPerson(new PersonInfo { Name = person, Type = PersonType.Composer });
                     }
@@ -221,12 +221,15 @@ namespace MediaBrowser.Providers.MediaInfo
         /// Splits the specified val.
         /// </summary>
         /// <param name="val">The val.</param>
+        /// <param name="allowCommaDelimiter">if set to <c>true</c> [allow comma delimiter].</param>
         /// <returns>System.String[][].</returns>
-        private IEnumerable<string> Split(string val)
+        private IEnumerable<string> Split(string val, bool allowCommaDelimiter)
         {
             // Only use the comma as a delimeter if there are no slashes or pipes. 
             // We want to be careful not to split names that have commas in them
-            var delimeter = _nameDelimiters.Any(i => val.IndexOf(i) != -1) ? _nameDelimiters : new[] { ',' };
+            var delimeter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i) != -1) ? 
+                _nameDelimiters : 
+                new[] { ',' };
 
             return val.Split(delimeter, StringSplitOptions.RemoveEmptyEntries)
                 .Where(i => !string.IsNullOrWhiteSpace(i))
@@ -312,7 +315,7 @@ namespace MediaBrowser.Providers.MediaInfo
             if (!string.IsNullOrEmpty(val))
             {
                 // Sometimes the artist name is listed here, account for that
-                var studios = Split(val).Where(i => !audio.HasArtist(i));
+                var studios = Split(val, true).Where(i => !audio.HasArtist(i));
 
                 foreach (var studio in studios)
                 {
@@ -334,7 +337,7 @@ namespace MediaBrowser.Providers.MediaInfo
             {
                 audio.Genres.Clear();
 
-                foreach (var genre in Split(val))
+                foreach (var genre in Split(val, true))
                 {
                     audio.AddGenre(genre);
                 }

+ 32 - 0
MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs

@@ -26,6 +26,7 @@ namespace MediaBrowser.Server.Implementations.Configuration
         {
             UpdateItemsByNamePath();
             UpdateTranscodingTempPath();
+            UpdateMetadataPath();
         }
 
         /// <summary>
@@ -76,6 +77,16 @@ namespace MediaBrowser.Server.Implementations.Configuration
                 Configuration.ItemsByNamePath;
         }
 
+        /// <summary>
+        /// Updates the metadata path.
+        /// </summary>
+        private void UpdateMetadataPath()
+        {
+            ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = string.IsNullOrEmpty(Configuration.MetadataPath) ?
+                null :
+                Configuration.MetadataPath;
+        }
+
         /// <summary>
         /// Updates the transcoding temporary path.
         /// </summary>
@@ -98,6 +109,7 @@ namespace MediaBrowser.Server.Implementations.Configuration
             ValidateItemByNamePath(newConfig);
             ValidateTranscodingTempPath(newConfig);
             ValidatePathSubstitutions(newConfig);
+            ValidateMetadataPath(newConfig);
 
             base.ReplaceConfiguration(newConfiguration);
         }
@@ -166,5 +178,25 @@ namespace MediaBrowser.Server.Implementations.Configuration
                 }
             }
         }
+
+        /// <summary>
+        /// Validates the metadata path.
+        /// </summary>
+        /// <param name="newConfig">The new configuration.</param>
+        /// <exception cref="System.IO.DirectoryNotFoundException"></exception>
+        private void ValidateMetadataPath(ServerConfiguration newConfig)
+        {
+            var newPath = newConfig.MetadataPath;
+
+            if (!string.IsNullOrWhiteSpace(newPath)
+                && !string.Equals(Configuration.MetadataPath ?? string.Empty, newPath))
+            {
+                // Validate
+                if (!Directory.Exists(newPath))
+                {
+                    throw new DirectoryNotFoundException(string.Format("{0} does not exist.", newPath));
+                }
+            }
+        }
     }
 }

+ 39 - 19
MediaBrowser.Server.Implementations/Library/UserManager.cs

@@ -260,6 +260,8 @@ namespace MediaBrowser.Server.Implementations.Library
 
         public event EventHandler<GenericEventArgs<User>> UserCreated;
 
+        private readonly SemaphoreSlim _userListLock = new SemaphoreSlim(1, 1);
+
         /// <summary>
         /// Creates the user.
         /// </summary>
@@ -279,19 +281,28 @@ namespace MediaBrowser.Server.Implementations.Library
                 throw new ArgumentException(string.Format("A user with the name '{0}' already exists.", name));
             }
 
-            var user = InstantiateNewUser(name);
+            await _userListLock.WaitAsync(CancellationToken.None).ConfigureAwait(false);
 
-            var list = Users.ToList();
-            list.Add(user);
-            Users = list;
+            try
+            {
+                var user = InstantiateNewUser(name);
 
-            user.DateLastSaved = DateTime.UtcNow;
+                var list = Users.ToList();
+                list.Add(user);
+                Users = list;
 
-            await UserRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false);
+                user.DateLastSaved = DateTime.UtcNow;
 
-            EventHelper.QueueEventIfNotNull(UserCreated, this, new GenericEventArgs<User> { Argument = user }, _logger);
+                await UserRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false);
 
-            return user;
+                EventHelper.QueueEventIfNotNull(UserCreated, this, new GenericEventArgs<User> { Argument = user }, _logger);
+
+                return user;
+            }
+            finally
+            {
+                _userListLock.Release();
+            }
         }
 
         /// <summary>
@@ -325,23 +336,32 @@ namespace MediaBrowser.Server.Implementations.Library
                 throw new ArgumentException(string.Format("The user '{0}' cannot be deleted because there must be at least one admin user in the system.", user.Name));
             }
 
-            await UserRepository.DeleteUser(user, CancellationToken.None).ConfigureAwait(false);
-
-            var path = user.ConfigurationFilePath;
+            await _userListLock.WaitAsync(CancellationToken.None).ConfigureAwait(false);
 
             try
             {
-                File.Delete(path);
+                await UserRepository.DeleteUser(user, CancellationToken.None).ConfigureAwait(false);
+
+                var path = user.ConfigurationFilePath;
+
+                try
+                {
+                    File.Delete(path);
+                }
+                catch (IOException ex)
+                {
+                    _logger.ErrorException("Error deleting file {0}", ex, path);
+                }
+
+                // Force this to be lazy loaded again
+                Users = await LoadUsers().ConfigureAwait(false);
+
+                OnUserDeleted(user);
             }
-            catch (IOException ex)
+            finally
             {
-                _logger.ErrorException("Error deleting file {0}", ex, path);
+                _userListLock.Release();
             }
-
-            // Force this to be lazy loaded again
-            Users = await LoadUsers().ConfigureAwait(false);
-
-            OnUserDeleted(user);
         }
 
         /// <summary>

+ 9 - 3
MediaBrowser.Server.Implementations/ServerApplicationPaths.cs

@@ -1,6 +1,6 @@
-using System;
-using MediaBrowser.Common.Implementations;
+using MediaBrowser.Common.Implementations;
 using MediaBrowser.Controller;
+using System;
 using System.IO;
 
 namespace MediaBrowser.Server.Implementations
@@ -239,14 +239,20 @@ namespace MediaBrowser.Server.Implementations
             }
         }
 
+        private string _internalMetadataPath;
         public string InternalMetadataPath
         {
             get
             {
-                return Path.Combine(DataPath, "metadata");
+                return _internalMetadataPath ?? (_internalMetadataPath = Path.Combine(DataPath, "metadata"));
+            }
+            set
+            {
+                _internalMetadataPath = value;
             }
         }
 
+
         public string GetInternalMetadataPath(Guid id)
         {
             var idString = id.ToString("N");

+ 1 - 1
MediaBrowser.ServerApplication/ApplicationHost.cs

@@ -795,7 +795,7 @@ namespace MediaBrowser.ServerApplication
             list.Add(typeof(ApiEntryPoint).Assembly);
 
             // Include composable parts in the Dashboard assembly 
-            list.Add(typeof(DashboardInfo).Assembly);
+            list.Add(typeof(DashboardService).Assembly);
 
             // Include composable parts in the Model assembly 
             list.Add(typeof(SystemInfo).Assembly);

+ 0 - 39
MediaBrowser.WebDashboard/Api/DashboardInfo.cs

@@ -1,39 +0,0 @@
-using MediaBrowser.Model.Session;
-using MediaBrowser.Model.System;
-using MediaBrowser.Model.Tasks;
-using System;
-using System.Collections.Generic;
-
-namespace MediaBrowser.WebDashboard.Api
-{
-    /// <summary>
-    /// Class DashboardInfo
-    /// </summary>
-    public class DashboardInfo
-    {
-        /// <summary>
-        /// Gets or sets the system info.
-        /// </summary>
-        /// <value>The system info.</value>
-        public SystemInfo SystemInfo { get; set; }
-
-        /// <summary>
-        /// Gets or sets the running tasks.
-        /// </summary>
-        /// <value>The running tasks.</value>
-        public List<TaskInfo> RunningTasks { get; set; }
-
-        /// <summary>
-        /// Gets or sets the application update task id.
-        /// </summary>
-        /// <value>The application update task id.</value>
-        public Guid ApplicationUpdateTaskId { get; set; }
-
-        /// <summary>
-        /// Gets or sets the active connections.
-        /// </summary>
-        /// <value>The active connections.</value>
-        public List<SessionInfoDto> ActiveConnections { get; set; }
-    }
-
-}

+ 0 - 62
MediaBrowser.WebDashboard/Api/DashboardInfoWebSocketListener.cs

@@ -1,62 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Common.ScheduledTasks;
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Session;
-using MediaBrowser.Model.Logging;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.WebDashboard.Api
-{
-    /// <summary>
-    /// Class DashboardInfoWebSocketListener
-    /// </summary>
-    class DashboardInfoWebSocketListener : BasePeriodicWebSocketListener<DashboardInfo, object>
-    {
-        /// <summary>
-        /// Gets the name.
-        /// </summary>
-        /// <value>The name.</value>
-        protected override string Name
-        {
-            get { return "DashboardInfo"; }
-        }
-
-        private readonly IServerApplicationHost _appHost;
-
-        /// <summary>
-        /// Gets or sets the task manager.
-        /// </summary>
-        /// <value>The task manager.</value>
-        private readonly ITaskManager _taskManager;
-
-        private readonly ISessionManager _sessionManager;
-        private readonly IDtoService _dtoService;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="DashboardInfoWebSocketListener" /> class.
-        /// </summary>
-        /// <param name="appHost">The app host.</param>
-        /// <param name="logger">The logger.</param>
-        /// <param name="taskManager">The task manager.</param>
-        /// <param name="sessionManager">The session manager.</param>
-        public DashboardInfoWebSocketListener(IServerApplicationHost appHost, ILogger logger, ITaskManager taskManager, ISessionManager sessionManager, IDtoService dtoService)
-            : base(logger)
-        {
-            _appHost = appHost;
-            _taskManager = taskManager;
-            _sessionManager = sessionManager;
-            _dtoService = dtoService;
-        }
-
-        /// <summary>
-        /// Gets the data to send.
-        /// </summary>
-        /// <param name="state">The state.</param>
-        /// <returns>Task{IEnumerable{TaskInfo}}.</returns>
-        protected override Task<DashboardInfo> GetDataToSend(object state)
-        {
-            return Task.FromResult(DashboardService.GetDashboardInfo(_appHost, _taskManager, _sessionManager, _dtoService));
-        }
-    }
-}

+ 4 - 66
MediaBrowser.WebDashboard/Api/DashboardService.cs

@@ -1,16 +1,13 @@
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Net;
-using MediaBrowser.Common.ScheduledTasks;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Controller.Plugins;
-using MediaBrowser.Controller.Session;
 using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Tasks;
 using ServiceStack;
+using ServiceStack.Web;
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -18,7 +15,6 @@ using System.Linq;
 using System.Reflection;
 using System.Text;
 using System.Threading.Tasks;
-using ServiceStack.Web;
 
 namespace MediaBrowser.WebDashboard.Api
 {
@@ -66,14 +62,6 @@ namespace MediaBrowser.WebDashboard.Api
         public string V { get; set; }
     }
 
-    /// <summary>
-    /// Class GetDashboardInfo
-    /// </summary>
-    [Route("/dashboard/dashboardInfo", "GET")]
-    public class GetDashboardInfo : IReturn<DashboardInfo>
-    {
-    }
-
     /// <summary>
     /// Class DashboardService
     /// </summary>
@@ -97,12 +85,6 @@ namespace MediaBrowser.WebDashboard.Api
         /// <value>The request context.</value>
         public IRequest Request { get; set; }
 
-        /// <summary>
-        /// Gets or sets the task manager.
-        /// </summary>
-        /// <value>The task manager.</value>
-        private readonly ITaskManager _taskManager;
-
         /// <summary>
         /// The _app host
         /// </summary>
@@ -113,24 +95,18 @@ namespace MediaBrowser.WebDashboard.Api
         /// </summary>
         private readonly IServerConfigurationManager _serverConfigurationManager;
 
-        private readonly ISessionManager _sessionManager;
-        private readonly IDtoService _dtoService;
         private readonly IFileSystem _fileSystem;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="DashboardService" /> class.
         /// </summary>
-        /// <param name="taskManager">The task manager.</param>
         /// <param name="appHost">The app host.</param>
         /// <param name="serverConfigurationManager">The server configuration manager.</param>
-        /// <param name="sessionManager">The session manager.</param>
-        public DashboardService(ITaskManager taskManager, IServerApplicationHost appHost, IServerConfigurationManager serverConfigurationManager, ISessionManager sessionManager, IDtoService dtoService, IFileSystem fileSystem)
+        /// <param name="fileSystem">The file system.</param>
+        public DashboardService(IServerApplicationHost appHost, IServerConfigurationManager serverConfigurationManager, IFileSystem fileSystem)
         {
-            _taskManager = taskManager;
             _appHost = appHost;
             _serverConfigurationManager = serverConfigurationManager;
-            _sessionManager = sessionManager;
-            _dtoService = dtoService;
             _fileSystem = fileSystem;
         }
 
@@ -163,45 +139,6 @@ namespace MediaBrowser.WebDashboard.Api
             return Path.Combine(DashboardUIPath, virtualPath.Replace('/', Path.DirectorySeparatorChar));
         }
 
-        /// <summary>
-        /// Gets the specified request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>System.Object.</returns>
-        public object Get(GetDashboardInfo request)
-        {
-            var result = GetDashboardInfo(_appHost, _taskManager, _sessionManager, _dtoService);
-
-            return ResultFactory.GetOptimizedResult(Request, result);
-        }
-
-        /// <summary>
-        /// Gets the dashboard info.
-        /// </summary>
-        /// <param name="appHost">The app host.</param>
-        /// <param name="taskManager">The task manager.</param>
-        /// <param name="connectionManager">The connection manager.</param>
-        /// <returns>DashboardInfo.</returns>
-        public static DashboardInfo GetDashboardInfo(IServerApplicationHost appHost,
-            ITaskManager taskManager,
-            ISessionManager connectionManager, IDtoService dtoService)
-        {
-            var connections = connectionManager.Sessions.Where(i => i.IsActive).ToList();
-
-            return new DashboardInfo
-            {
-                SystemInfo = appHost.GetSystemInfo(),
-
-                RunningTasks = taskManager.ScheduledTasks.Where(i => i.State == TaskState.Running || i.State == TaskState.Cancelling)
-                                     .Select(ScheduledTaskHelpers.GetTaskInfo)
-                                     .ToList(),
-
-                ApplicationUpdateTaskId = taskManager.ScheduledTasks.First(t => t.ScheduledTask.GetType().Name.Equals("SystemUpdateTask", StringComparison.OrdinalIgnoreCase)).Id,
-
-                ActiveConnections = connections.Select(dtoService.GetSessionInfoDto).ToList()
-            };
-        }
-
         /// <summary>
         /// Gets the specified request.
         /// </summary>
@@ -473,6 +410,7 @@ namespace MediaBrowser.WebDashboard.Api
                                       "alphapicker.js",
                                       "addpluginpage.js",
                                       "advancedconfigurationpage.js",
+                                      "advancedpaths.js",
                                       "advancedserversettings.js",
                                       "metadataadvanced.js",
                                       "appsplayback.js",

+ 6 - 2
MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj

@@ -63,9 +63,7 @@
       <Link>Properties\SharedVersion.cs</Link>
     </Compile>
     <Compile Include="Api\ConfigurationPageInfo.cs" />
-    <Compile Include="Api\DashboardInfo.cs" />
     <Compile Include="Api\DashboardService.cs" />
-    <Compile Include="Api\DashboardInfoWebSocketListener.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="ServerEntryPoint.cs" />
   </ItemGroup>
@@ -85,6 +83,9 @@
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="ApiClient.js" />
+    <Content Include="dashboard-ui\advancedpaths.html">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
     <Content Include="dashboard-ui\advancedserversettings.html">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
@@ -483,6 +484,9 @@
     <Content Include="dashboard-ui\livetvrecordings.html">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
+    <Content Include="dashboard-ui\scripts\advancedpaths.js">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
     <Content Include="dashboard-ui\scripts\advancedserversettings.js">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>