2
0
Эх сурвалжийг харах

Add remote control chapter menu

Luke Pulverenti 11 жил өмнө
parent
commit
6314428830

+ 0 - 1
MediaBrowser.Api/ApiEntryPoint.cs

@@ -1,6 +1,5 @@
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Plugins;
-using MediaBrowser.Controller.Resolvers;
 using MediaBrowser.Model.Logging;
 using System;
 using System.Collections.Generic;

+ 8 - 22
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -444,18 +444,11 @@ namespace MediaBrowser.Api.Playback
 
             var pts = string.Empty;
 
-            if (state.SubtitleStream != null)
+            if (state.SubtitleStream != null && !state.SubtitleStream.IsGraphicalSubtitleStream)
             {
-                if (state.SubtitleStream.Codec.IndexOf("srt", StringComparison.OrdinalIgnoreCase) != -1 ||
-                   state.SubtitleStream.Codec.IndexOf("subrip", StringComparison.OrdinalIgnoreCase) != -1 ||
-                   string.Equals(state.SubtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase) ||
-                   string.Equals(state.SubtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase))
-                {
-                    var seconds = TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds;
+                var seconds = TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds;
 
-                    pts = string.Format(",asetpts=PTS-{0}/TB",
-                Math.Round(seconds).ToString(UsCulture));
-                }
+                pts = string.Format(",asetpts=PTS-{0}/TB", Math.Round(seconds).ToString(UsCulture));
             }
 
             return string.Format("-af \"{0}aresample={1}async={4}{2}{3}\"",
@@ -484,16 +477,10 @@ namespace MediaBrowser.Api.Playback
 
             var request = state.VideoRequest;
 
-            if (state.SubtitleStream != null)
+            if (state.SubtitleStream != null && !state.SubtitleStream.IsGraphicalSubtitleStream)
             {
-                if (state.SubtitleStream.Codec.IndexOf("srt", StringComparison.OrdinalIgnoreCase) != -1 ||
-                    state.SubtitleStream.Codec.IndexOf("subrip", StringComparison.OrdinalIgnoreCase) != -1 ||
-                    string.Equals(state.SubtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase) ||
-                    string.Equals(state.SubtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase))
-                {
-                    assSubtitleParam = GetTextSubtitleParam(state, performTextSubtitleConversion);
-                    copyTsParam = " -copyts";
-                }
+                assSubtitleParam = GetTextSubtitleParam(state, performTextSubtitleConversion);
+                copyTsParam = " -copyts";
             }
 
             // If fixed dimensions were supplied
@@ -713,12 +700,11 @@ namespace MediaBrowser.Api.Playback
         /// <summary>
         /// Gets the probe size argument.
         /// </summary>
-        /// <param name="mediaPath">The media path.</param>
         /// <param name="isVideo">if set to <c>true</c> [is video].</param>
         /// <param name="videoType">Type of the video.</param>
         /// <param name="isoType">Type of the iso.</param>
         /// <returns>System.String.</returns>
-        private string GetProbeSizeArgument(string mediaPath, bool isVideo, VideoType? videoType, IsoType? isoType)
+        private string GetProbeSizeArgument(bool isVideo, VideoType? videoType, IsoType? isoType)
         {
             var type = !isVideo ? MediaEncoderHelpers.GetInputType(null, null) :
                 MediaEncoderHelpers.GetInputType(videoType, isoType);
@@ -1831,7 +1817,7 @@ namespace MediaBrowser.Api.Playback
         {
             var inputModifier = string.Empty;
 
-            var probeSize = GetProbeSizeArgument(state.MediaPath, state.IsInputVideo, state.VideoType, state.IsoType);
+            var probeSize = GetProbeSizeArgument(state.IsInputVideo, state.VideoType, state.IsoType);
             inputModifier += " " + probeSize;
             inputModifier = inputModifier.Trim();
 

+ 0 - 2
MediaBrowser.Common/Constants/Constants.cs

@@ -4,7 +4,5 @@ namespace MediaBrowser.Common.Constants
     public static class Constants
     {
         public const string MbAdminUrl = "http://www.mb3admin.com/admin/";
-        public const string MbServerPkgName = "MBServer";
-        public const string MbTheaterPkgName = "MBTheater";
     }
 }

+ 17 - 0
MediaBrowser.Model/Configuration/UserConfiguration.cs

@@ -24,6 +24,12 @@ namespace MediaBrowser.Model.Configuration
         /// <value>The audio language preference.</value>
         public string AudioLanguagePreference { get; set; }
 
+        /// <summary>
+        /// Gets or sets a value indicating whether [play default audio track].
+        /// </summary>
+        /// <value><c>true</c> if [play default audio track]; otherwise, <c>false</c>.</value>
+        public bool PlayDefaultAudioTrack { get; set; }
+
         /// <summary>
         /// Gets or sets the subtitle language preference.
         /// </summary>
@@ -61,6 +67,8 @@ namespace MediaBrowser.Model.Configuration
 
         public UnratedItem[] BlockUnratedItems { get; set; }
 
+        public SubtitlePlaybackMode SubtitleMode { get; set; }
+
         /// <summary>
         /// Initializes a new instance of the <see cref="UserConfiguration" /> class.
         /// </summary>
@@ -68,6 +76,7 @@ namespace MediaBrowser.Model.Configuration
         {
             IsAdministrator = true;
 
+            PlayDefaultAudioTrack = true;
             EnableRemoteControlOfOtherUsers = true;
             EnableLiveTvManagement = true;
             EnableMediaPlayback = true;
@@ -79,4 +88,12 @@ namespace MediaBrowser.Model.Configuration
             BlockUnratedItems = new UnratedItem[] { };
         }
     }
+
+    public enum SubtitlePlaybackMode
+    {
+        Default = 0,
+        Always = 1,
+        OnlyForced = 2,
+        None = 3
+    }
 }

+ 19 - 3
MediaBrowser.Model/Dto/MediaSourceInfo.cs

@@ -1,8 +1,8 @@
-using System;
-using System.Runtime.Serialization;
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.MediaInfo;
+using System;
 using System.Collections.Generic;
+using System.Runtime.Serialization;
 
 namespace MediaBrowser.Model.Dto
 {
@@ -41,11 +41,27 @@ namespace MediaBrowser.Model.Dto
             MediaStreams = new List<MediaStream>();
         }
 
+        public int? DefaultAudioStreamIndex { get; set; }
+        public int? DefaultSubtitleStreamIndex { get; set; }
+
         [IgnoreDataMember]
         public MediaStream DefaultAudioStream
         {
             get
             {
+                if (DefaultAudioStreamIndex.HasValue)
+                {
+                    var val = DefaultAudioStreamIndex.Value;
+
+                    foreach (MediaStream i in MediaStreams)
+                    {
+                        if (i.Type == MediaStreamType.Audio && i.Index == val)
+                        {
+                            return i;
+                        }
+                    }
+                }
+
                 foreach (MediaStream i in MediaStreams)
                 {
                     if (i.Type == MediaStreamType.Audio && i.IsDefault)

+ 3 - 2
MediaBrowser.Model/MediaInfo/AudioCodec.cs

@@ -2,7 +2,8 @@
 {
     public class AudioCodec
     {
-        public const string AAC = "AAC";
-        public const string MP3 = "MP3";
+        public const string AAC = "aac";
+        public const string MP3 = "mp3";
+        public const string AC3 = "ac3";
     }
 }

+ 2 - 1
MediaBrowser.Model/MediaInfo/Container.cs

@@ -3,6 +3,7 @@ namespace MediaBrowser.Model.MediaInfo
 {
     public class Container
     {
-        public const string MP4 = "MP4";
+        public const string MP4 = "mp4";
+        public const string MKV = "mkv";
     }
 }

+ 5 - 1
MediaBrowser.Model/MediaInfo/SubtitleFormat.cs

@@ -2,6 +2,10 @@
 {
     public class SubtitleFormat
     {
-        public const string SRT = "SRT";
+        public const string SRT = "srt";
+        public const string SSA = "ssa";
+        public const string ASS = "ass";
+        public const string VTT = "vtt";
+        public const string SUB = "sub";
     }
 }

+ 8 - 6
MediaBrowser.Model/MediaInfo/VideoCodec.cs

@@ -2,11 +2,13 @@
 {
     public class VideoCodec
     {
-        public const string H263 = "H263";
-        public const string H264 = "H264";
-        public const string H265 = "H265";
-        public const string MPEG4 = "MPEG4";
-        public const string MSMPEG4 = "MSMPEG4";
-        public const string VC1 = "VC1";
+        public const string H263 = "h263";
+        public const string H264 = "h264";
+        public const string H265 = "h265";
+        public const string MPEG4 = "mpeg4";
+        public const string MPEG1 = "mpeg1video";
+        public const string MPEG2 = "mpeg2video";
+        public const string MSMPEG4 = "msmpeg4";
+        public const string VC1 = "vc1";
     }
 }

+ 10 - 0
MediaBrowser.Server.Implementations/Dto/DtoService.cs

@@ -12,6 +12,7 @@ using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Controller.Session;
+using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Drawing;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
@@ -110,6 +111,15 @@ namespace MediaBrowser.Server.Implementations.Dto
 
             AttachBasicFields(dto, item, owner, fields);
 
+            if (user != null && dto.MediaSources != null && item is Video)
+            {
+                foreach (var source in dto.MediaSources)
+                {
+                    //source.DefaultAudioStreamIndex = GetDefaultAudioStreamIndex(source, user.Configuration);
+                    //source.DefaultSubtitleStreamIndex = GetDefaultSubtitleStreamIndex(source, user.Configuration);
+                }
+            }
+
             if (fields.Contains(ItemFields.SoundtrackIds))
             {
                 var hasSoundtracks = item as IHasSoundtracks;

+ 7 - 3
MediaBrowser.Server.Implementations/Localization/Server/server.json

@@ -63,7 +63,7 @@
 	"HeaderPlaybackSettings": "Playback Settings",
 	"LabelAudioLanguagePreference": "Audio language preference:",
 	"LabelSubtitleLanguagePreference": "Subtitle language preference:",
-	"LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
+	"OptionDefaultSubtitles": "Default",
 	"TabProfiles": "Profiles",
 	"TabSecurity": "Security",
 	"ButtonAddUser": "Add User",
@@ -228,6 +228,8 @@
 	"ButtonSearch": "Search",
 	"ButtonGroupVersions": "Group Versions",
 	"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
+	"TangibleSoftwareMessage": "Utilizing Tangible Solutions Java/C# converters through a donated license.",
+	"HeaderCredits": "Credits",
 	"PleaseSupportOtherProduces": "Please support other free products we utilize:",
 	"VersionNumber": "Version {0}",
 	"TabPaths": "Paths",
@@ -327,7 +329,7 @@
 	"OptionAutomatic": "Auto",
 	"LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.",
 	"LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.",
-	"HeaderCustomizeOptionsPerMediaType": "Customize options per media type",
+	"LabelCustomizeOptionsPerMediaType": "Customize for media type:",
 	"OptionDownloadThumbImage": "Thumb",
 	"OptionDownloadMenuImage": "Menu",
 	"OptionDownloadLogoImage": "Logo",
@@ -339,6 +341,7 @@
 	"OptionDownloadPrimaryImage": "Primary",
 	"HeaderFetchImages": "Fetch Images:",
 	"HeaderImageSettings": "Image Settings",
+	"TabCustomizations": "Customizations",
 	"LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:",
 	"LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:",
 	"LabelMinBackdropDownloadWidth": "Minimum backdrop download width:",
@@ -721,7 +724,8 @@
 	"TabSubtitles": "Subtitles",
 	"LabelOpenSubtitlesUsername": "Open Subtitles username:",
 	"LabelOpenSubtitlesPassword": "Open Subtitles password:",
-	"LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+	"LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
+	"LabelSubtitlePlaybackMode": "Subtitle mode:",
 	"LabelDownloadLanguages": "Download languages:",
 	"ButtonRegister": "Register",
 	"LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",

+ 1 - 2
MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj

@@ -200,7 +200,6 @@
     <Compile Include="Persistence\SqliteShrinkMemoryTimer.cs" />
     <Compile Include="Persistence\TypeMapper.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="Roku\RokuControllerFactory.cs" />
     <Compile Include="ScheduledTasks\PeopleValidationTask.cs" />
     <Compile Include="ScheduledTasks\ChapterImagesTask.cs" />
     <Compile Include="ScheduledTasks\RefreshIntrosTask.cs" />
@@ -209,7 +208,7 @@
     <Compile Include="ServerApplicationPaths.cs" />
     <Compile Include="ServerManager\ServerManager.cs" />
     <Compile Include="ServerManager\WebSocketConnection.cs" />
-    <Compile Include="Roku\RokuSessionController.cs" />
+    <Compile Include="Session\HttpSessionController.cs" />
     <Compile Include="Session\SessionManager.cs">
       <SubType>Code</SubType>
     </Compile>

+ 0 - 36
MediaBrowser.Server.Implementations/Roku/RokuControllerFactory.cs

@@ -1,36 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Session;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Serialization;
-using System;
-using System.Collections.Generic;
-
-namespace MediaBrowser.Server.Implementations.Roku
-{
-    public class RokuControllerFactory : ISessionControllerFactory
-    {
-        private readonly IHttpClient _httpClient;
-        private readonly IJsonSerializer _json;
-        private readonly IServerApplicationHost _appHost;
-
-        public RokuControllerFactory(IHttpClient httpClient, IJsonSerializer json, IServerApplicationHost appHost)
-        {
-            _httpClient = httpClient;
-            _json = json;
-            _appHost = appHost;
-        }
-
-        public ISessionController GetSessionController(SessionInfo session)
-        {
-            if (string.Equals(session.Client, "roku", StringComparison.OrdinalIgnoreCase))
-            {
-                session.PlayableMediaTypes = new List<string> { MediaType.Video, MediaType.Audio };
-
-                return new RokuSessionController(_httpClient, _json, _appHost, session);
-            }
-
-            return null;
-        }
-    }
-}

+ 32 - 25
MediaBrowser.Server.Implementations/Roku/RokuSessionController.cs → MediaBrowser.Server.Implementations/Session/HttpSessionController.cs

@@ -10,9 +10,9 @@ using System;
 using System.Threading;
 using System.Threading.Tasks;
 
-namespace MediaBrowser.Server.Implementations.Roku
+namespace MediaBrowser.Server.Implementations.Session
 {
-    public class RokuSessionController : ISessionController
+    public class HttpSessionController : ISessionController
     {
         private readonly IHttpClient _httpClient;
         private readonly IJsonSerializer _json;
@@ -20,12 +20,21 @@ namespace MediaBrowser.Server.Implementations.Roku
 
         public SessionInfo Session { get; private set; }
 
-        public RokuSessionController(IHttpClient httpClient, IJsonSerializer json, IServerApplicationHost appHost, SessionInfo session)
+        //var postUrl = string.Format("http://{0}/mediabrowser/message", session.RemoteEndPoint);
+        
+        private readonly string _postUrl;
+
+        public HttpSessionController(IHttpClient httpClient, 
+            IJsonSerializer json, 
+            IServerApplicationHost appHost, 
+            SessionInfo session, 
+            string postUrl)
         {
             _httpClient = httpClient;
             _json = json;
             _appHost = appHost;
             Session = session;
+            _postUrl = postUrl;
         }
 
         public bool SupportsMediaRemoteControl
@@ -41,6 +50,19 @@ namespace MediaBrowser.Server.Implementations.Roku
             }
         }
 
+        private Task SendMessage(object obj, CancellationToken cancellationToken)
+        {
+            var json = _json.SerializeToString(obj);
+
+            return _httpClient.Post(new HttpRequestOptions
+            {
+                Url = _postUrl,
+                CancellationToken = cancellationToken,
+                RequestContent = json,
+                RequestContentType = "application/json"
+            });
+        }
+
         public Task SendSessionEndedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken)
         {
             return Task.FromResult(true);
@@ -58,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Roku
 
         public Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken)
         {
-            return SendCommand(new WebSocketMessage<PlayRequest>
+            return SendMessage(new WebSocketMessage<PlayRequest>
             {
                 MessageType = "Play",
                 Data = command
@@ -68,7 +90,7 @@ namespace MediaBrowser.Server.Implementations.Roku
 
         public Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken)
         {
-            return SendCommand(new WebSocketMessage<PlaystateRequest>
+            return SendMessage(new WebSocketMessage<PlaystateRequest>
             {
                 MessageType = "Playstate",
                 Data = command
@@ -78,13 +100,12 @@ namespace MediaBrowser.Server.Implementations.Roku
 
         public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken)
         {
-            // Roku probably won't care about this
             return Task.FromResult(true);
         }
 
         public Task SendRestartRequiredNotification(CancellationToken cancellationToken)
         {
-            return SendCommand(new WebSocketMessage<SystemInfo>
+            return SendMessage(new WebSocketMessage<SystemInfo>
             {
                 MessageType = "RestartRequired",
                 Data = _appHost.GetSystemInfo()
@@ -94,13 +115,12 @@ namespace MediaBrowser.Server.Implementations.Roku
 
         public Task SendUserDataChangeInfo(UserDataChangeInfo info, CancellationToken cancellationToken)
         {
-            // Roku probably won't care about this
             return Task.FromResult(true);
         }
 
         public Task SendServerShutdownNotification(CancellationToken cancellationToken)
         {
-            return SendCommand(new WebSocketMessage<string>
+            return SendMessage(new WebSocketMessage<string>
             {
                 MessageType = "ServerShuttingDown",
                 Data = string.Empty
@@ -110,7 +130,7 @@ namespace MediaBrowser.Server.Implementations.Roku
 
         public Task SendServerRestartNotification(CancellationToken cancellationToken)
         {
-            return SendCommand(new WebSocketMessage<string>
+            return SendMessage(new WebSocketMessage<string>
             {
                 MessageType = "ServerRestarting",
                 Data = string.Empty
@@ -118,24 +138,11 @@ namespace MediaBrowser.Server.Implementations.Roku
             }, cancellationToken);
         }
 
-        private Task SendCommand(object obj, CancellationToken cancellationToken)
-        {
-            var json = _json.SerializeToString(obj);
-
-            return _httpClient.Post(new HttpRequestOptions
-            {
-                Url = "http://" + Session.RemoteEndPoint + "/mb/remotecontrol",
-                CancellationToken = cancellationToken,
-                RequestContent = json,
-                RequestContentType = "application/json"
-            });
-        }
-
         public Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken)
         {
-            return SendCommand(new WebSocketMessage<GeneralCommand>
+            return SendMessage(new WebSocketMessage<GeneralCommand>
             {
-                MessageType = "Command",
+                MessageType = "GeneralCommand",
                 Data = command
 
             }, cancellationToken);

+ 1 - 1
MediaBrowser.ServerApplication/ApplicationHost.cs

@@ -1039,7 +1039,7 @@ namespace MediaBrowser.ServerApplication
         {
             var availablePackages = await InstallationManager.GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
 
-            var version = InstallationManager.GetLatestCompatibleVersion(availablePackages, Constants.MbServerPkgName, null, ApplicationVersion,
+            var version = InstallationManager.GetLatestCompatibleVersion(availablePackages, "MBServer", null, ApplicationVersion,
                                                            ConfigurationManager.CommonConfiguration.SystemUpdateLevel);
 
             HasUpdateAvailable = version != null && version.version >= ApplicationVersion;

+ 1 - 1
MediaBrowser.ServerApplication/MainStartup.cs

@@ -481,7 +481,7 @@ namespace MediaBrowser.ServerApplication
         private static bool PerformUpdateIfNeeded(ServerApplicationPaths appPaths, ILogger logger)
         {
             // Look for the existence of an update archive
-            var updateArchive = Path.Combine(appPaths.TempUpdatePath, Constants.MbServerPkgName + ".zip");
+            var updateArchive = Path.Combine(appPaths.TempUpdatePath, "MBServer" + ".zip");
             if (File.Exists(updateArchive))
             {
                 logger.Info("An update is available from {0}", updateArchive);

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

@@ -378,7 +378,7 @@ namespace MediaBrowser.WebDashboard.Api
             //sb.Append("<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\">");
 
             sb.Append("<link rel=\"icon\" sizes=\"114x114\" href=\"css/images/touchicon114.png\" />");
-            
+
             // http://developer.apple.com/library/ios/#DOCUMENTATION/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html
             sb.Append("<link rel=\"apple-touch-icon\" href=\"css/images/touchicon.png\" />");
             sb.Append("<link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"css/images/touchicon72.png\" />");
@@ -469,7 +469,7 @@ namespace MediaBrowser.WebDashboard.Api
                     builder.Append(Environment.NewLine);
                 }
             }
-            
+
             foreach (var file in GetScriptFiles())
             {
                 var path = GetDashboardResourcePath("scripts/" + file);
@@ -563,7 +563,7 @@ namespace MediaBrowser.WebDashboard.Api
                                 "itemgallery.js",
                                 "itemlistpage.js",
                                 "librarypathmapping.js",
-                                "libraryreport.js",
+                                "reports.js",
                                 "librarysettings.js",
                                 "livetvchannel.js",
                                 "livetvchannels.js",
@@ -670,6 +670,7 @@ namespace MediaBrowser.WebDashboard.Api
                                       "remotecontrol.css",
                                       "userimage.css",
                                       "livetv.css",
+                                      "nowplaying.css",
                                       "icons.css"
                                   };
 

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

@@ -172,6 +172,9 @@
     <Content Include="dashboard-ui\css\images\items\folders\edit.png">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
+    <Content Include="dashboard-ui\css\images\items\folders\report.png">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
     <Content Include="dashboard-ui\css\images\items\folders\settings.png">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
@@ -280,6 +283,9 @@
     <Content Include="dashboard-ui\css\mediaplayer.css">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
+    <Content Include="dashboard-ui\css\nowplaying.css">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
     <Content Include="dashboard-ui\dashboardgeneral.html">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
@@ -313,7 +319,7 @@
     <Content Include="dashboard-ui\librarypathmapping.html">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
-    <Content Include="dashboard-ui\libraryreport.html">
+    <Content Include="dashboard-ui\reports.html">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
     <Content Include="dashboard-ui\livetvchannel.html">
@@ -631,7 +637,7 @@
     <Content Include="dashboard-ui\scripts\librarypathmapping.js">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
-    <Content Include="dashboard-ui\scripts\libraryreport.js">
+    <Content Include="dashboard-ui\scripts\reports.js">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
     <Content Include="dashboard-ui\scripts\livetvchannel.js">