Browse Source

update video player layout

Luke Pulverenti 11 years ago
parent
commit
608ebf4829

+ 37 - 0
MediaBrowser.Api/ApiEntryPoint.cs

@@ -324,6 +324,35 @@ namespace MediaBrowser.Api
             }
         }
 
+        /// <summary>
+        /// Kills the transcoding jobs.
+        /// </summary>
+        /// <param name="deviceId">The device identifier.</param>
+        /// <param name="outputPath">The output path.</param>
+        /// <param name="deleteMode">The delete mode.</param>
+        /// <exception cref="System.ArgumentNullException">deviceId</exception>
+        internal void KillTranscodingJobs(string deviceId, string outputPath, FileDeleteMode deleteMode)
+        {
+            if (string.IsNullOrEmpty(deviceId))
+            {
+                throw new ArgumentNullException("deviceId");
+            }
+
+            var jobs = new List<TranscodingJob>();
+
+            lock (_activeTranscodingJobs)
+            {
+                // This is really only needed for HLS. 
+                // Progressive streams can stop on their own reliably
+                jobs.AddRange(_activeTranscodingJobs.Where(i => string.Equals(deviceId, i.DeviceId, StringComparison.OrdinalIgnoreCase) && string.Equals(outputPath, i.Path, StringComparison.OrdinalIgnoreCase)));
+            }
+
+            foreach (var job in jobs)
+            {
+                KillTranscodingJob(job, deleteMode);
+            }
+        }
+
         /// <summary>
         /// Kills the transcoding job.
         /// </summary>
@@ -443,6 +472,8 @@ namespace MediaBrowser.Api
                 .Where(f => f.IndexOf(name, StringComparison.OrdinalIgnoreCase) != -1)
                 .ToList();
 
+            Exception e = null;
+
             foreach (var file in filesToDelete)
             {
                 try
@@ -452,9 +483,15 @@ namespace MediaBrowser.Api
                 }
                 catch (IOException ex)
                 {
+                    e = ex;
                     Logger.ErrorException("Error deleting HLS file {0}", ex, file);
                 }
             }
+
+            if (e != null)
+            {
+                throw e;
+            }
         }
     }
 

+ 71 - 38
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -123,7 +123,11 @@ namespace MediaBrowser.Api.Playback
 
             var outputFileExtension = GetOutputFileExtension(state);
 
-            return Path.Combine(folder, GetCommandLineArguments("dummy\\dummy", state, false).GetMD5() + (outputFileExtension ?? string.Empty).ToLower());
+            var data = GetCommandLineArguments("dummy\\dummy", state, false);
+
+            data += "-" + (state.Request.DeviceId ?? string.Empty);
+
+            return Path.Combine(folder, data.GetMD5().ToString("N") + (outputFileExtension ?? string.Empty).ToLower());
         }
 
         protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
@@ -772,7 +776,7 @@ namespace MediaBrowser.Api.Playback
         /// </summary>
         /// <param name="state">The state.</param>
         /// <returns>System.String.</returns>
-        protected string GetInputArgument(StreamState state)
+        protected virtual string GetInputArgument(StreamState state)
         {
             var protocol = state.InputProtocol;
 
@@ -789,6 +793,58 @@ namespace MediaBrowser.Api.Playback
             return MediaEncoder.GetInputArgument(inputPath, protocol);
         }
 
+        private async Task AcquireResources(StreamState state, CancellationTokenSource cancellationTokenSource)
+        {
+            if (state.VideoType == VideoType.Iso && state.IsoType.HasValue && IsoManager.CanMount(state.MediaPath))
+            {
+                state.IsoMount = await IsoManager.Mount(state.MediaPath, cancellationTokenSource.Token).ConfigureAwait(false);
+            }
+
+            if (string.IsNullOrEmpty(state.MediaPath))
+            {
+                if (string.Equals(state.ItemType, typeof(LiveTvChannel).Name))
+                {
+                    var streamInfo = await LiveTvManager.GetChannelStream(state.Request.Id, cancellationTokenSource.Token).ConfigureAwait(false);
+
+                    state.LiveTvStreamId = streamInfo.Id;
+
+                    if (!string.IsNullOrEmpty(streamInfo.Path))
+                    {
+                        state.MediaPath = streamInfo.Path;
+                        state.InputProtocol = MediaProtocol.File;
+
+                        await Task.Delay(1000, cancellationTokenSource.Token).ConfigureAwait(false);
+                    }
+                    else if (!string.IsNullOrEmpty(streamInfo.Url))
+                    {
+                        state.MediaPath = streamInfo.Url;
+                        state.InputProtocol = MediaProtocol.Http;
+                    }
+                }
+
+                else if (string.Equals(state.ItemType, typeof(LiveTvVideoRecording).Name) ||
+                    string.Equals(state.ItemType, typeof(LiveTvAudioRecording).Name))
+                {
+                    var streamInfo = await LiveTvManager.GetRecordingStream(state.Request.Id, cancellationTokenSource.Token).ConfigureAwait(false);
+
+                    state.LiveTvStreamId = streamInfo.Id;
+
+                    if (!string.IsNullOrEmpty(streamInfo.Path))
+                    {
+                        state.MediaPath = streamInfo.Path;
+                        state.InputProtocol = MediaProtocol.File;
+
+                        await Task.Delay(1000, cancellationTokenSource.Token).ConfigureAwait(false);
+                    }
+                    else if (!string.IsNullOrEmpty(streamInfo.Url))
+                    {
+                        state.MediaPath = streamInfo.Url;
+                        state.InputProtocol = MediaProtocol.Http;
+                    }
+                }
+            }
+        }
+
         /// <summary>
         /// Starts the FFMPEG.
         /// </summary>
@@ -806,10 +862,7 @@ namespace MediaBrowser.Api.Playback
 
             Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
 
-            if (state.VideoType == VideoType.Iso && state.IsoType.HasValue && IsoManager.CanMount(state.MediaPath))
-            {
-                state.IsoMount = await IsoManager.Mount(state.MediaPath, cancellationTokenSource.Token).ConfigureAwait(false);
-            }
+            await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false);
 
             var commandLineArgs = GetCommandLineArguments(outputPath, state, true);
 
@@ -1363,6 +1416,8 @@ namespace MediaBrowser.Api.Playback
 
             List<MediaStream> mediaStreams = null;
 
+            state.ItemType = item.GetType().Name;
+
             if (item is ILiveTvRecording)
             {
                 var recording = await LiveTvManager.GetInternalRecording(request.Id, cancellationToken).ConfigureAwait(false);
@@ -1379,16 +1434,8 @@ namespace MediaBrowser.Api.Playback
 
                 mediaStreams = source.MediaStreams;
 
-                if (string.IsNullOrWhiteSpace(path) && string.IsNullOrWhiteSpace(mediaUrl))
-                {
-                    var streamInfo = await LiveTvManager.GetRecordingStream(request.Id, cancellationToken).ConfigureAwait(false);
-
-                    state.LiveTvStreamId = streamInfo.Id;
-                    mediaStreams = streamInfo.MediaStreams;
-
-                    path = streamInfo.Path;
-                    mediaUrl = streamInfo.Url;
-                }
+                // Just to prevent this from being null and causing other methods to fail
+                state.MediaPath = string.Empty;
 
                 if (!string.IsNullOrEmpty(path))
                 {
@@ -1421,30 +1468,16 @@ namespace MediaBrowser.Api.Playback
 
                 state.VideoType = VideoType.VideoFile;
                 state.IsInputVideo = string.Equals(channel.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
-
-                var streamInfo = await LiveTvManager.GetChannelStream(request.Id, cancellationToken).ConfigureAwait(false);
-
-                state.LiveTvStreamId = streamInfo.Id;
-                mediaStreams = streamInfo.MediaStreams;
-
-                if (!string.IsNullOrEmpty(streamInfo.Path))
-                {
-                    state.MediaPath = streamInfo.Path;
-                    state.InputProtocol = MediaProtocol.File;
-
-                    await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
-                }
-                else if (!string.IsNullOrEmpty(streamInfo.Url))
-                {
-                    state.MediaPath = streamInfo.Url;
-                    state.InputProtocol = MediaProtocol.Http;
-                }
+                mediaStreams = new List<MediaStream>();
 
                 state.ReadInputAtNativeFramerate = true;
                 state.OutputAudioSync = "1000";
                 state.DeInterlace = true;
                 state.InputVideoSync = "-1";
                 state.InputAudioSync = "1";
+
+                // Just to prevent this from being null and causing other methods to fail
+                state.MediaPath = string.Empty;
             }
             else if (item is IChannelMediaItem)
             {
@@ -1500,7 +1533,7 @@ namespace MediaBrowser.Api.Playback
 
             AttachMediaStreamInfo(state, mediaStreams, videoRequest, url);
 
-            state.SegmentLength = state.ReadInputAtNativeFramerate ? 5 : 10;
+            state.SegmentLength = state.ReadInputAtNativeFramerate ? 5 : 7;
             state.HlsListSize = state.ReadInputAtNativeFramerate ? 100 : 1440;
 
             var container = Path.GetExtension(state.RequestedUrl);
@@ -1928,7 +1961,7 @@ namespace MediaBrowser.Api.Playback
             videoRequest.Height = null;
         }
 
-        protected string GetInputModifier(StreamState state)
+        protected string GetInputModifier(StreamState state, bool genPts = true)
         {
             var inputModifier = string.Empty;
 
@@ -1948,9 +1981,9 @@ namespace MediaBrowser.Api.Playback
             inputModifier += " " + GetFastSeekCommandLineParameter(state.Request);
             inputModifier = inputModifier.Trim();
 
-            if (state.VideoRequest != null)
+            if (state.VideoRequest != null && genPts)
             {
-                inputModifier += " -fflags genpts";
+                inputModifier += " -fflags +genpts";
             }
 
             if (!string.IsNullOrEmpty(state.InputAudioSync))

+ 1 - 1
MediaBrowser.Api/Playback/Hls/BaseHlsService.cs

@@ -272,7 +272,7 @@ namespace MediaBrowser.Api.Playback.Hls
             // If isEncoding is true we're actually starting ffmpeg
             var startNumberParam = isEncoding ? GetStartNumber(state).ToString(UsCulture) : "0";
 
-            var args = string.Format("{0} {1} -i {2} -map_metadata -1 -threads {3} {4} {5} {6} -hls_time {7} -start_number {8} -hls_list_size {9} -y \"{10}\"",
+            var args = string.Format("{0} {1} -i {2} -map_metadata -1 -threads {3} {4} {5} -sc_threshold 0 {6} -hls_time {7} -start_number {8} -hls_list_size {9} -y \"{10}\"",
                 itsOffset,
                 inputModifier,
                 GetInputArgument(state),

+ 1 - 1
MediaBrowser.Api/Playback/StreamRequest.cs

@@ -33,7 +33,7 @@ namespace MediaBrowser.Api.Playback
         /// <value>The start time ticks.</value>
         [ApiMember(Name = "StartTimeTicks", Description = "Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
         public long? StartTimeTicks { get; set; }
-
+        
         /// <summary>
         /// Gets or sets the audio bit rate.
         /// </summary>

+ 4 - 0
MediaBrowser.Api/Playback/StreamState.cs

@@ -94,6 +94,10 @@ namespace MediaBrowser.Api.Playback
         public bool EnableMpegtsM2TsMode { get; set; }
         public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
 
+        public long? EncodingDurationTicks { get; set; }
+
+        public string ItemType { get; set; }
+
         public string GetMimeType(string outputPath)
         {
             if (!string.IsNullOrEmpty(MimeType))

+ 2 - 2
MediaBrowser.Api/UserLibrary/ArtistsService.cs

@@ -88,10 +88,10 @@ namespace MediaBrowser.Api.UserLibrary
             {
                 var user = UserManager.GetUserById(request.UserId.Value);
 
-                return DtoService.GetItemByNameDto(item, fields.ToList(), user);
+                return DtoService.GetBaseItemDto(item, fields.ToList(), user);
             }
 
-            return DtoService.GetItemByNameDto(item, fields.ToList());
+            return DtoService.GetBaseItemDto(item, fields.ToList());
         }
 
         /// <summary>

+ 2 - 2
MediaBrowser.Api/UserLibrary/GameGenresService.cs

@@ -76,10 +76,10 @@ namespace MediaBrowser.Api.UserLibrary
             {
                 var user = UserManager.GetUserById(request.UserId.Value);
 
-                return DtoService.GetItemByNameDto(item, fields.ToList(), user);
+                return DtoService.GetBaseItemDto(item, fields.ToList(), user);
             }
 
-            return DtoService.GetItemByNameDto(item, fields.ToList());
+            return DtoService.GetBaseItemDto(item, fields.ToList());
         }
 
         /// <summary>

+ 2 - 2
MediaBrowser.Api/UserLibrary/GenresService.cs

@@ -81,10 +81,10 @@ namespace MediaBrowser.Api.UserLibrary
             {
                 var user = UserManager.GetUserById(request.UserId.Value);
 
-                return DtoService.GetItemByNameDto(item, fields.ToList(), user);
+                return DtoService.GetBaseItemDto(item, fields.ToList(), user);
             }
 
-            return DtoService.GetItemByNameDto(item, fields.ToList());
+            return DtoService.GetBaseItemDto(item, fields.ToList());
         }
 
         /// <summary>

+ 2 - 2
MediaBrowser.Api/UserLibrary/MusicGenresService.cs

@@ -76,10 +76,10 @@ namespace MediaBrowser.Api.UserLibrary
             {
                 var user = UserManager.GetUserById(request.UserId.Value);
 
-                return DtoService.GetItemByNameDto(item, fields.ToList(), user);
+                return DtoService.GetBaseItemDto(item, fields.ToList(), user);
             }
 
-            return DtoService.GetItemByNameDto(item, fields.ToList());
+            return DtoService.GetBaseItemDto(item, fields.ToList());
         }
 
         /// <summary>

+ 2 - 2
MediaBrowser.Api/UserLibrary/PersonsService.cs

@@ -93,10 +93,10 @@ namespace MediaBrowser.Api.UserLibrary
             {
                 var user = UserManager.GetUserById(request.UserId.Value);
 
-                return DtoService.GetItemByNameDto(item, fields.ToList(), user);
+                return DtoService.GetBaseItemDto(item, fields.ToList(), user);
             }
 
-            return DtoService.GetItemByNameDto(item, fields.ToList());
+            return DtoService.GetBaseItemDto(item, fields.ToList());
         }
 
         /// <summary>

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

@@ -78,10 +78,10 @@ namespace MediaBrowser.Api.UserLibrary
             {
                 var user = UserManager.GetUserById(request.UserId.Value);
 
-                return DtoService.GetItemByNameDto(item, fields.ToList(), user);
+                return DtoService.GetBaseItemDto(item, fields.ToList(), user);
             }
 
-            return DtoService.GetItemByNameDto(item, fields.ToList());
+            return DtoService.GetBaseItemDto(item, fields.ToList());
         }
 
         /// <summary>

+ 2 - 2
MediaBrowser.Api/UserLibrary/YearsService.cs

@@ -78,10 +78,10 @@ namespace MediaBrowser.Api.UserLibrary
             {
                 var user = UserManager.GetUserById(request.UserId.Value);
 
-                return DtoService.GetItemByNameDto(item, fields.ToList(), user);
+                return DtoService.GetBaseItemDto(item, fields.ToList(), user);
             }
 
-            return DtoService.GetItemByNameDto(item, fields.ToList());
+            return DtoService.GetBaseItemDto(item, fields.ToList());
         }
 
         /// <summary>

+ 0 - 10
MediaBrowser.Controller/Dto/IDtoService.cs

@@ -49,16 +49,6 @@ namespace MediaBrowser.Controller.Dto
         /// <returns>Task{BaseItemDto}.</returns>
         BaseItemDto GetBaseItemDto(BaseItem item, List<ItemFields> fields, User user = null, BaseItem owner = null);
 
-        /// <summary>
-        /// Gets the item by name dto.
-        /// </summary>
-        /// <param name="item">The item.</param>
-        /// <param name="fields">The fields.</param>
-        /// <param name="user">The user.</param>
-        /// <returns>BaseItemDto.</returns>
-        BaseItemDto GetItemByNameDto<T>(T item, List<ItemFields> fields, User user = null)
-            where T : BaseItem, IItemByName;
-
         /// <summary>
         /// Gets the chapter information dto.
         /// </summary>

+ 2 - 2
MediaBrowser.Controller/LiveTv/LiveTvChannel.cs

@@ -3,13 +3,13 @@ using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.LiveTv;
+using MediaBrowser.Model.MediaInfo;
 using System.Collections.Generic;
 using System.Linq;
-using MediaBrowser.Model.MediaInfo;
 
 namespace MediaBrowser.Controller.LiveTv
 {
-    public class LiveTvChannel : BaseItem, IItemByName, IHasMediaSources
+    public class LiveTvChannel : BaseItem, IHasMediaSources
     {
         /// <summary>
         /// Gets the user data key.

+ 2 - 26
MediaBrowser.Dlna/PlayTo/Device.cs

@@ -289,7 +289,8 @@ namespace MediaBrowser.Dlna.PlayTo
                 throw new InvalidOperationException("Unable to find service");
             }
 
-            await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType, url, dictionary), header)
+            var post = AvCommands.BuildPost(command, service.ServiceType, url, dictionary);
+            await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header)
                 .ConfigureAwait(false);
 
             await Task.Delay(50).ConfigureAwait(false);
@@ -315,31 +316,6 @@ namespace MediaBrowser.Dlna.PlayTo
             return SecurityElement.Escape(value);
         }
 
-        public async Task SetNextAvTransport(string value, string header, string metaData)
-        {
-            var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetNextAVTransportURI");
-            if (command == null)
-                return;
-
-            var dictionary = new Dictionary<string, string>
-            {
-                {"NextURI", value},
-                {"NextURIMetaData", CreateDidlMeta(metaData)}
-            };
-
-            var service = Properties.Services.FirstOrDefault(s => s.ServiceType == ServiceAvtransportType);
-
-            if (service == null)
-            {
-                throw new InvalidOperationException("Unable to find service");
-            }
-
-            await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType, value, dictionary), header)
-                .ConfigureAwait(false);
-
-            RestartTimer();
-        }
-
         public async Task SetPlay()
         {
             var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "Play");

+ 3 - 3
MediaBrowser.Dlna/PlayTo/TransportCommands.cs

@@ -165,12 +165,12 @@ namespace MediaBrowser.Dlna.PlayTo
 
         private string BuildArgumentXml(Argument argument, string value, string commandParameter = "")
         {
-            var state = StateVariables.FirstOrDefault(a => a.Name == argument.RelatedStateVariable);
+            var state = StateVariables.FirstOrDefault(a => string.Equals(a.Name, argument.RelatedStateVariable, StringComparison.OrdinalIgnoreCase));
 
             if (state != null)
             {
-                var sendValue = (state.AllowedValues.FirstOrDefault(a => a == commandParameter) ??
-                                 state.AllowedValues.FirstOrDefault()) ?? 
+                var sendValue = state.AllowedValues.FirstOrDefault(a => string.Equals(a, commandParameter, StringComparison.OrdinalIgnoreCase)) ??
+                                 state.AllowedValues.FirstOrDefault() ?? 
                                  value;
 
                 return string.Format("<{0} xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"{1}\">{2}</{0}>", argument.Name, state.DataType ?? "string", sendValue);

+ 1 - 2
MediaBrowser.Model/Dto/ChapterInfoDto.cs

@@ -1,5 +1,4 @@
-using System;
-using System.ComponentModel;
+using System.ComponentModel;
 using System.Diagnostics;
 using System.Runtime.Serialization;
 

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

@@ -62,6 +62,26 @@ namespace MediaBrowser.Server.Implementations.Dto
         /// <returns>Task{DtoBaseItem}.</returns>
         /// <exception cref="System.ArgumentNullException">item</exception>
         public BaseItemDto GetBaseItemDto(BaseItem item, List<ItemFields> fields, User user = null, BaseItem owner = null)
+        {
+            var byName = item as IItemByName;
+
+            if (byName != null)
+            {
+                var libraryItems = user != null ?
+                    user.RootFolder.GetRecursiveChildren(user) :
+                    _libraryManager.RootFolder.RecursiveChildren;
+
+                var dto = GetBaseItemDtoInternal(item, fields, user);
+
+                SetItemByNameInfo(item, dto, byName.GetTaggedItems(libraryItems).ToList(), user);
+
+                return dto;
+            }
+
+            return GetBaseItemDtoInternal(item, fields, user, owner);
+        }
+
+        private BaseItemDto GetBaseItemDtoInternal(BaseItem item, List<ItemFields> fields, User user = null, BaseItem owner = null)
         {
             if (item == null)
             {
@@ -141,20 +161,18 @@ namespace MediaBrowser.Server.Implementations.Dto
             return dto;
         }
 
-        public BaseItemDto GetItemByNameDto<T>(T item, List<ItemFields> fields, User user = null)
+        public BaseItemDto GetItemByNameDto<T>(T item, List<ItemFields> fields, List<BaseItem> taggedItems, User user = null)
             where T : BaseItem, IItemByName
         {
-            var libraryItems = user != null ? user.RootFolder.GetRecursiveChildren(user) :
-                _libraryManager.RootFolder.RecursiveChildren;
+            var dto = GetBaseItemDtoInternal(item, fields, user);
+
+            SetItemByNameInfo(item, dto, taggedItems, user);
 
-            return GetItemByNameDto(item, fields, item.GetTaggedItems(libraryItems).ToList(), user);
+            return dto;
         }
 
-        public BaseItemDto GetItemByNameDto<T>(T item, List<ItemFields> fields, List<BaseItem> taggedItems, User user = null)
-            where T : BaseItem, IItemByName
+        private void SetItemByNameInfo(BaseItem item, BaseItemDto dto, List<BaseItem> taggedItems, User user = null)
         {
-            var dto = GetBaseItemDto(item, fields, user);
-
             if (item is MusicArtist || item is MusicGenre)
             {
                 dto.AlbumCount = taggedItems.Count(i => i is MusicAlbum);
@@ -181,8 +199,6 @@ namespace MediaBrowser.Server.Implementations.Dto
             }
 
             dto.ChildCount = taggedItems.Count;
-
-            return dto;
         }
 
         /// <summary>

+ 3 - 2
MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Model.Logging;
+using System.Globalization;
+using MediaBrowser.Model.Logging;
 using System;
 using System.Linq;
 using System.Net;
@@ -45,7 +46,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
 
             //log.AppendLine("Headers: " + string.Join(",", response.Headers.AllKeys.Select(k => k + "=" + response.Headers[k])));
 
-            var responseTime = string.Format(". Response time: {0} ms", duration.TotalMilliseconds);
+            var responseTime = string.Format(". Response time: {0} ms. Content length: {1} bytes.", duration.TotalMilliseconds, response.ContentLength64.ToString(CultureInfo.InvariantCulture));
 
             var msg = "HTTP Response " + statusCode + " to " + endPoint + responseTime;
 

+ 0 - 1
MediaBrowser.WebDashboard/Api/DashboardService.cs

@@ -668,7 +668,6 @@ namespace MediaBrowser.WebDashboard.Api
                                   {
                                       "site.css",
                                       "chromecast.css",
-                                      "contextmenu.css",
                                       "mediaplayer.css",
                                       "mediaplayer-video.css",
                                       "librarymenu.css",

+ 0 - 3
MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj

@@ -113,9 +113,6 @@
     <Content Include="dashboard-ui\css\chromecast.css">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
-    <Content Include="dashboard-ui\css\contextmenu.css">
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </Content>
     <Content Include="dashboard-ui\css\icons.css">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>