diff options
19 files changed, 185 insertions, 156 deletions
diff --git a/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs b/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs index 6cc4626ea..dcc974413 100644 --- a/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs +++ b/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs @@ -10,11 +10,17 @@ namespace Emby.Common.Implementations.EnvironmentInfo public class EnvironmentInfo : IEnvironmentInfo { public MediaBrowser.Model.System.Architecture? CustomArchitecture { get; set; } + public MediaBrowser.Model.System.OperatingSystem? CustomOperatingSystem { get; set; } public MediaBrowser.Model.System.OperatingSystem OperatingSystem { get { + if (CustomOperatingSystem.HasValue) + { + return CustomOperatingSystem.Value; + } + #if NET46 switch (Environment.OSVersion.Platform) { diff --git a/Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index cbc7c7c2d..de528a94f 100644 --- a/Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -282,9 +282,12 @@ namespace Emby.Common.Implementations.ScheduledTasks throw new ArgumentNullException("value"); } - SaveTriggers(value); + // This null check is not great, but is needed to handle bad user input, or user mucking with the config file incorrectly + var triggerList = value.Where(i => i != null).ToArray(); - InternalTriggers = value.Select(i => new Tuple<TaskTriggerInfo, ITaskTrigger>(i, GetTrigger(i))).ToArray(); + SaveTriggers(triggerList); + + InternalTriggers = triggerList.Select(i => new Tuple<TaskTriggerInfo, ITaskTrigger>(i, GetTrigger(i))).ToArray(); } } @@ -535,7 +538,8 @@ namespace Emby.Common.Implementations.ScheduledTasks /// <returns>IEnumerable{BaseTaskTrigger}.</returns> private Tuple<TaskTriggerInfo, ITaskTrigger>[] LoadTriggers() { - var settings = LoadTriggerSettings(); + // This null check is not great, but is needed to handle bad user input, or user mucking with the config file incorrectly + var settings = LoadTriggerSettings().Where(i => i != null).ToArray(); return settings.Select(i => new Tuple<TaskTriggerInfo, ITaskTrigger>(i, GetTrigger(i))).ToArray(); } @@ -544,8 +548,12 @@ namespace Emby.Common.Implementations.ScheduledTasks { try { - return JsonSerializer.DeserializeFromFile<IEnumerable<TaskTriggerInfo>>(GetConfigurationFilePath()) - .ToArray(); + var list = JsonSerializer.DeserializeFromFile<IEnumerable<TaskTriggerInfo>>(GetConfigurationFilePath()); + + if (list != null) + { + return list.ToArray(); + } } catch (FileNotFoundException) { @@ -555,8 +563,8 @@ namespace Emby.Common.Implementations.ScheduledTasks catch (DirectoryNotFoundException) { // File doesn't exist. No biggie. Return defaults. - return ScheduledTask.GetDefaultTriggers().ToArray(); } + return ScheduledTask.GetDefaultTriggers().ToArray(); } /// <summary> diff --git a/Emby.Server.Core/ApplicationHost.cs b/Emby.Server.Core/ApplicationHost.cs index a0a7416e7..3590ade40 100644 --- a/Emby.Server.Core/ApplicationHost.cs +++ b/Emby.Server.Core/ApplicationHost.cs @@ -1583,7 +1583,8 @@ namespace Emby.Server.Core public void LaunchUrl(string url) { - if (EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows) + if (EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows && + EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.OSX) { throw new NotImplementedException(); } @@ -1591,7 +1592,7 @@ namespace Emby.Server.Core var process = ProcessFactory.Create(new ProcessOptions { FileName = url, - EnableRaisingEvents = true, + //EnableRaisingEvents = true, UseShellExecute = true, ErrorDialog = false }); diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs index 995dc7b7b..e78446bc8 100644 --- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -203,20 +203,12 @@ namespace Emby.Server.Implementations.HttpServer // Do not use the memoryStreamFactory here, they don't place nice with compression using (var ms = new MemoryStream()) { - using (var compressionStream = GetCompressionStream(ms, compressionType)) - { - ContentTypes.Instance.SerializeToStream(request, dto, compressionStream); - compressionStream.Dispose(); - - var compressedBytes = ms.ToArray(); + ContentTypes.Instance.SerializeToStream(request, dto, ms); + ms.Position = 0; - var httpResult = new StreamWriter(compressedBytes, request.ResponseContentType, _logger); + var responseHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - //httpResult.Headers["Content-Length"] = compressedBytes.Length.ToString(UsCulture); - httpResult.Headers["Content-Encoding"] = compressionType; - - return httpResult; - } + return GetCompressedResult(ms, compressionType, responseHeaders, false, request.ResponseContentType).Result; } } @@ -591,45 +583,53 @@ namespace Emby.Server.Implementations.HttpServer }; } - string content; - using (var stream = await factoryFn().ConfigureAwait(false)) { - using (var reader = new StreamReader(stream)) + return await GetCompressedResult(stream, requestedCompressionType, responseHeaders, isHeadRequest, contentType).ConfigureAwait(false); + } + } + + private async Task<IHasHeaders> GetCompressedResult(Stream stream, + string requestedCompressionType, + IDictionary<string,string> responseHeaders, + bool isHeadRequest, + string contentType) + { + using (var reader = new MemoryStream()) + { + await stream.CopyToAsync(reader).ConfigureAwait(false); + + reader.Position = 0; + var content = reader.ToArray(); + + if (content.Length >= 1024) { - content = await reader.ReadToEndAsync().ConfigureAwait(false); + content = Compress(content, requestedCompressionType); + responseHeaders["Content-Encoding"] = requestedCompressionType; } - } - var contents = Compress(content, requestedCompressionType); + responseHeaders["Content-Length"] = content.Length.ToString(UsCulture); - responseHeaders["Content-Length"] = contents.Length.ToString(UsCulture); - responseHeaders["Content-Encoding"] = requestedCompressionType; + if (isHeadRequest) + { + return GetHttpResult(new byte[] { }, contentType, true); + } - if (isHeadRequest) - { - return GetHttpResult(new byte[] { }, contentType, true); + return GetHttpResult(content, contentType, true, responseHeaders); } - - return GetHttpResult(contents, contentType, true, responseHeaders); } - private byte[] Compress(string text, string compressionType) + private byte[] Compress(byte[] bytes, string compressionType) { if (compressionType == "deflate") - return Deflate(text); + return Deflate(bytes); if (compressionType == "gzip") - return GZip(text); + return GZip(bytes); throw new NotSupportedException(compressionType); } - private byte[] Deflate(string text) - { - return Deflate(Encoding.UTF8.GetBytes(text)); - } - private byte[] Deflate(byte[] bytes) { // In .NET FX incompat-ville, you can't access compressed bytes without closing DeflateStream @@ -644,11 +644,6 @@ namespace Emby.Server.Implementations.HttpServer } } - private byte[] GZip(string text) - { - return GZip(Encoding.UTF8.GetBytes(text)); - } - private byte[] GZip(byte[] buffer) { using (var ms = new MemoryStream()) diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 55a63b4e5..b791311f9 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -74,21 +74,21 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) { - return ResolveVideos<MusicVideo>(parent, files, directoryService, false); + return ResolveVideos<MusicVideo>(parent, files, directoryService, false, collectionType); } if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) || string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase)) { - return ResolveVideos<Video>(parent, files, directoryService, false); + return ResolveVideos<Video>(parent, files, directoryService, false, collectionType); } - if (string.IsNullOrEmpty(collectionType)) + if (string.IsNullOrWhiteSpace(collectionType)) { // Owned items should just use the plain video type if (parent == null) { - return ResolveVideos<Video>(parent, files, directoryService, false); + return ResolveVideos<Video>(parent, files, directoryService, false, collectionType); } if (parent is Series || parent.GetParents().OfType<Series>().Any()) @@ -96,18 +96,18 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return null; } - return ResolveVideos<Movie>(parent, files, directoryService, false); + return ResolveVideos<Movie>(parent, files, directoryService, false, collectionType); } if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase)) { - return ResolveVideos<Movie>(parent, files, directoryService, true); + return ResolveVideos<Movie>(parent, files, directoryService, true, collectionType); } return null; } - private MultiItemResolverResult ResolveVideos<T>(Folder parent, IEnumerable<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, bool suppportMultiEditions) + private MultiItemResolverResult ResolveVideos<T>(Folder parent, IEnumerable<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, bool suppportMultiEditions, string collectionType) where T : Video, new() { var files = new List<FileSystemMetadata>(); @@ -117,6 +117,16 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies // Loop through each child file/folder and see if we find a video foreach (var child in fileSystemEntries) { + // This is a hack but currently no better way to resolve a sometimes ambiguous situation + if (string.IsNullOrWhiteSpace(collectionType)) + { + if (string.Equals(child.Name, "tvshow.nfo", StringComparison.OrdinalIgnoreCase) || + string.Equals(child.Name, "season.nfo", StringComparison.OrdinalIgnoreCase)) + { + return null; + } + } + if (child.IsDirectory) { leftOver.Add(child); @@ -408,7 +418,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies !string.Equals(collectionType, CollectionType.Photos) && !string.Equals(collectionType, CollectionType.MusicVideos); - var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, supportsMultiVersion); + var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, supportsMultiVersion, collectionType) ?? + new MultiItemResolverResult(); if (result.Items.Count == 1) { diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 04fc78c95..e2446b16f 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -422,7 +422,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings } var showType = details.showType ?? string.Empty; - + var info = new ProgramInfo { ChannelId = channel, @@ -440,10 +440,23 @@ namespace Emby.Server.Implementations.LiveTv.Listings IsKids = string.Equals(details.audience, "children", StringComparison.OrdinalIgnoreCase), IsSports = showType.IndexOf("sports", StringComparison.OrdinalIgnoreCase) != -1, IsMovie = showType.IndexOf("movie", StringComparison.OrdinalIgnoreCase) != -1 || showType.IndexOf("film", StringComparison.OrdinalIgnoreCase) != -1, - ShowId = programInfo.programID, Etag = programInfo.md5 }; + var showId = programInfo.programID ?? string.Empty; + + // According to SchedulesDirect, these are generic, unidentified episodes + // SH005316560000 + var hasUniqueShowId = !showId.StartsWith("SH", StringComparison.OrdinalIgnoreCase) || + !showId.EndsWith("0000", StringComparison.OrdinalIgnoreCase); + + if (!hasUniqueShowId) + { + showId = newID; + } + + info.ShowId = showId; + if (programInfo.videoProperties != null) { info.IsHD = programInfo.videoProperties.Contains("hdtv", StringComparer.OrdinalIgnoreCase); diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 525db4036..62a0738c7 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -2647,7 +2647,7 @@ namespace Emby.Server.Implementations.LiveTv public GuideInfo GetGuideInfo() { var startDate = DateTime.UtcNow; - var endDate = startDate.AddDays(14); + var endDate = startDate.AddDays(GetGuideDays()); return new GuideInfo { diff --git a/Emby.Server.Implementations/Sync/SyncManager.cs b/Emby.Server.Implementations/Sync/SyncManager.cs index 13f60f5ee..061129e5f 100644 --- a/Emby.Server.Implementations/Sync/SyncManager.cs +++ b/Emby.Server.Implementations/Sync/SyncManager.cs @@ -1042,10 +1042,7 @@ namespace Emby.Server.Implementations.Sync throw new ArgumentException("Operation is not valid for this job item"); } - if (jobItem.Status != SyncJobItemStatus.Synced) - { - jobItem.Status = SyncJobItemStatus.Cancelled; - } + jobItem.Status = SyncJobItemStatus.Cancelled; jobItem.Progress = 0; jobItem.IsMarkedForRemoval = true; @@ -1071,18 +1068,18 @@ namespace Emby.Server.Implementations.Sync _logger.ErrorException("Error deleting directory {0}", ex, path); } - //var jobItemsResult = GetJobItems(new SyncJobItemQuery - //{ - // AddMetadata = false, - // JobId = jobItem.JobId, - // Limit = 0, - // Statuses = new[] { SyncJobItemStatus.Converting, SyncJobItemStatus.Failed, SyncJobItemStatus.Queued, SyncJobItemStatus.ReadyToTransfer, SyncJobItemStatus.Synced, SyncJobItemStatus.Transferring } - //}); + var jobItemsResult = GetJobItems(new SyncJobItemQuery + { + AddMetadata = false, + JobId = jobItem.JobId, + Limit = 0, + Statuses = new[] { SyncJobItemStatus.Converting, SyncJobItemStatus.Queued, SyncJobItemStatus.ReadyToTransfer, SyncJobItemStatus.Synced, SyncJobItemStatus.Transferring } + }); - //if (jobItemsResult.TotalRecordCount == 0) - //{ - // await CancelJob(jobItem.JobId).ConfigureAwait(false); - //} + if (jobItemsResult.TotalRecordCount == 0) + { + await CancelJob(jobItem.JobId).ConfigureAwait(false); + } } public Task MarkJobItemForRemoval(string id) diff --git a/Emby.Server.Implementations/Sync/SyncNotificationEntryPoint.cs b/Emby.Server.Implementations/Sync/SyncNotificationEntryPoint.cs index 46cdb28a4..06e0e66a9 100644 --- a/Emby.Server.Implementations/Sync/SyncNotificationEntryPoint.cs +++ b/Emby.Server.Implementations/Sync/SyncNotificationEntryPoint.cs @@ -38,6 +38,18 @@ namespace Emby.Server.Implementations.Sync } } + + if (item.Status == SyncJobItemStatus.Cancelled) + { + try + { + await _sessionManager.SendMessageToUserDeviceSessions(item.TargetId, "SyncJobItemCancelled", item, CancellationToken.None).ConfigureAwait(false); + } + catch + { + + } + } } public void Dispose() diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index e29aa7d5a..7ae64b834 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -153,7 +153,7 @@ namespace MediaBrowser.Api.Playback.Progressive if (!state.RunTimeTicks.HasValue) { - args += " -fflags +genpts -flags +global_header"; + args += " -flags -global_header -fflags +genpts"; } return args; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 23e63dad0..116a6a7cf 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -95,6 +95,11 @@ namespace MediaBrowser.MediaEncoding.Encoder int defaultImageExtractionTimeoutMs, bool enableEncoderFontFile, IEnvironmentInfo environmentInfo) { + if (jsonSerializer == null) + { + throw new ArgumentNullException("jsonSerializer"); + } + _logger = logger; _jsonSerializer = jsonSerializer; ConfigurationManager = configurationManager; @@ -632,7 +637,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var result = _jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream); - if (result.streams == null && result.format == null) + if (result == null || (result.streams == null && result.format == null)) { throw new Exception("ffprobe failed - streams and format are both null."); } diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index 4992675da..538512557 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -238,7 +238,7 @@ namespace MediaBrowser.Providers.TV var targetSeries = DetermineAppropriateSeries(series, tuple.Item1); var seasonOffset = TvdbSeriesProvider.GetSeriesOffset(targetSeries.ProviderIds) ?? ((targetSeries.AnimeSeriesIndex ?? 1) - 1); - var unairedThresholdDays = 1; + var unairedThresholdDays = 2; now = now.AddDays(0 - unairedThresholdDays); if (airDate.Value < now) diff --git a/MediaBrowser.Server.Mac/Main.cs b/MediaBrowser.Server.Mac/Main.cs index cda6f459a..6d02c7a1a 100644 --- a/MediaBrowser.Server.Mac/Main.cs +++ b/MediaBrowser.Server.Mac/Main.cs @@ -142,7 +142,10 @@ namespace MediaBrowser.Server.Mac private static EnvironmentInfo GetEnvironmentInfo() { - var info = new EnvironmentInfo(); + var info = new EnvironmentInfo() + { + CustomOperatingSystem = MediaBrowser.Model.System.OperatingSystem.OSX + }; var uname = GetUnixName(); diff --git a/MediaBrowser.Server.Mono/MonoAppHost.cs b/MediaBrowser.Server.Mono/MonoAppHost.cs index 8def1ca2b..932e2d6cd 100644 --- a/MediaBrowser.Server.Mono/MonoAppHost.cs +++ b/MediaBrowser.Server.Mono/MonoAppHost.cs @@ -51,8 +51,11 @@ namespace MediaBrowser.Server.Mono } else if (environment.OperatingSystem == Model.System.OperatingSystem.Linux) { + info.FFMpegFilename = "ffmpeg"; + info.FFProbeFilename = "ffprobe"; info.ArchiveType = "7z"; info.Version = "20160215"; + info.DownloadUrls = GetDownloadUrls(); } // No version available - user requirement @@ -61,6 +64,25 @@ namespace MediaBrowser.Server.Mono return info; } + private string[] GetDownloadUrls() + { + switch (EnvironmentInfo.SystemArchitecture) + { + case Architecture.X64: + return new[] + { + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-git-20160215-64bit-static.7z" + }; + case Architecture.X86: + return new[] + { + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-git-20160215-32bit-static.7z" + }; + } + + return new string[] { }; + } + protected override void RestartInternal() { MainClass.Restart(StartupOptions); diff --git a/MediaBrowser.ServerApplication/Native/LnkShortcutHandler.cs b/MediaBrowser.ServerApplication/Native/LnkShortcutHandler.cs index 91ff7033e..b4a87b9b4 100644 --- a/MediaBrowser.ServerApplication/Native/LnkShortcutHandler.cs +++ b/MediaBrowser.ServerApplication/Native/LnkShortcutHandler.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; using System.Security; using System.Text; using MediaBrowser.Model.IO; @@ -52,7 +53,7 @@ namespace MediaBrowser.ServerApplication.Native /// <summary> /// The STG m_ READ /// </summary> - public const uint STGM_READ = 0; + public const int STGM_READ = 0; } /// <summary> @@ -319,72 +320,6 @@ namespace MediaBrowser.ServerApplication.Native } - /// <summary> - /// Interface IPersist - /// </summary> - [ComImport, Guid("0000010c-0000-0000-c000-000000000046"), - InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IPersist - { - /// <summary> - /// Gets the class ID. - /// </summary> - /// <param name="pClassID">The p class ID.</param> - [PreserveSig] - void GetClassID(out Guid pClassID); - } - - /// <summary> - /// Interface IPersistFile - /// </summary> - [ComImport, Guid("0000010b-0000-0000-C000-000000000046"), - InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IPersistFile : IPersist - { - /// <summary> - /// Gets the class ID. - /// </summary> - /// <param name="pClassID">The p class ID.</param> - new void GetClassID(out Guid pClassID); - /// <summary> - /// Determines whether this instance is dirty. - /// </summary> - [PreserveSig] - int IsDirty(); - - /// <summary> - /// Loads the specified PSZ file name. - /// </summary> - /// <param name="pszFileName">Name of the PSZ file.</param> - /// <param name="dwMode">The dw mode.</param> - [PreserveSig] - void Load([In, MarshalAs(UnmanagedType.LPWStr)] - string pszFileName, uint dwMode); - - /// <summary> - /// Saves the specified PSZ file name. - /// </summary> - /// <param name="pszFileName">Name of the PSZ file.</param> - /// <param name="remember">if set to <c>true</c> [remember].</param> - [PreserveSig] - void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, - [In, MarshalAs(UnmanagedType.Bool)] bool remember); - - /// <summary> - /// Saves the completed. - /// </summary> - /// <param name="pszFileName">Name of the PSZ file.</param> - [PreserveSig] - void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName); - - /// <summary> - /// Gets the cur file. - /// </summary> - /// <param name="ppszFileName">Name of the PPSZ file.</param> - [PreserveSig] - void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName); - } - // CLSID_ShellLink from ShlGuid.h /// <summary> /// Class ShellLink diff --git a/MediaBrowser.ServerApplication/WindowsAppHost.cs b/MediaBrowser.ServerApplication/WindowsAppHost.cs index c2cdb9ab0..398d21f32 100644 --- a/MediaBrowser.ServerApplication/WindowsAppHost.cs +++ b/MediaBrowser.ServerApplication/WindowsAppHost.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; +using System.Runtime.InteropServices.ComTypes; using Emby.Server.Core; using Emby.Server.Implementations; using Emby.Server.Implementations.EntryPoints; @@ -93,21 +94,30 @@ namespace MediaBrowser.ServerApplication protected override void ConfigureAutoRunInternal(bool autorun) { - var shortcutPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.StartMenu), "Emby", "Emby Server.lnk"); - var startupPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Startup); - if (autorun) + if (autorun && !MainStartup.IsRunningAsService) { //Copy our shortut into the startup folder for this user - var targetPath = Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk"); - FileSystemManager.CreateDirectory(Path.GetDirectoryName(targetPath)); - File.Copy(shortcutPath, targetPath, true); + var targetPath = Path.Combine(startupPath, "Emby Server.lnk"); + + IShellLinkW link = (IShellLinkW)new ShellLink(); + + var appPath = Process.GetCurrentProcess().MainModule.FileName; + + // setup shortcut information + link.SetDescription(Name); + link.SetPath(appPath); + link.SetWorkingDirectory(Path.GetDirectoryName(appPath)); + + // save it + IPersistFile file = (IPersistFile)link; + file.Save(targetPath, false); } else { //Remove our shortcut from the startup folder for this user - FileSystemManager.DeleteFile(Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk")); + FileSystemManager.DeleteFile(Path.Combine(startupPath, "Emby Server.lnk")); } } diff --git a/SocketHttpListener.Portable/Net/HttpConnection.cs b/SocketHttpListener.Portable/Net/HttpConnection.cs index bc4286dc8..3baffd258 100644 --- a/SocketHttpListener.Portable/Net/HttpConnection.cs +++ b/SocketHttpListener.Portable/Net/HttpConnection.cs @@ -209,7 +209,7 @@ namespace SocketHttpListener.Net // TODO: can we get this stream before reading the input? if (o_stream == null) { - context.Response.DetermineIfChunked(); + //context.Response.DetermineIfChunked(); if (context.Response.SendChunked || isExpect100Continue || context.Request.IsWebSocketRequest || true) { @@ -508,7 +508,7 @@ namespace SocketHttpListener.Net { force_close |= !context.Request.KeepAlive; if (!force_close) - force_close = (context.Response.Headers["connection"] == "close"); + force_close = (string.Equals(context.Response.Headers["connection"], "close", StringComparison.OrdinalIgnoreCase)); /* if (!force_close) { // bool conn_close = (status_code == 400 || status_code == 408 || status_code == 411 || diff --git a/SocketHttpListener.Portable/Net/HttpListenerResponse.cs b/SocketHttpListener.Portable/Net/HttpListenerResponse.cs index c1182de34..9a5862cb9 100644 --- a/SocketHttpListener.Portable/Net/HttpListenerResponse.cs +++ b/SocketHttpListener.Portable/Net/HttpListenerResponse.cs @@ -386,7 +386,7 @@ namespace SocketHttpListener.Net if (content_type != null) { - if (content_encoding != null && content_type.IndexOf("charset=", StringComparison.Ordinal) == -1) + if (content_encoding != null && content_type.IndexOf("charset=", StringComparison.OrdinalIgnoreCase) == -1) { string enc_name = content_encoding.WebName; headers.SetInternal("Content-Type", content_type + "; charset=" + enc_name); @@ -429,9 +429,10 @@ namespace SocketHttpListener.Net * HttpStatusCode.InternalServerError 500 * HttpStatusCode.ServiceUnavailable 503 */ - bool conn_close = (status_code == 408 || status_code == 411 || + bool conn_close = status_code == 400 || status_code == 408 || status_code == 411 || status_code == 413 || status_code == 414 || - status_code == 503); + status_code == 500 || + status_code == 503; if (conn_close == false) conn_close = !context.Request.KeepAlive; diff --git a/SocketHttpListener.Portable/Net/ResponseStream.cs b/SocketHttpListener.Portable/Net/ResponseStream.cs index 6067a89ec..a79a18791 100644 --- a/SocketHttpListener.Portable/Net/ResponseStream.cs +++ b/SocketHttpListener.Portable/Net/ResponseStream.cs @@ -136,6 +136,11 @@ namespace SocketHttpListener.Net if (disposed) throw new ObjectDisposedException(GetType().ToString()); + if (count == 0) + { + //return; + } + byte[] bytes = null; MemoryStream ms = GetHeaders(response, _memoryStreamFactory, false); bool chunked = response.SendChunked; @@ -176,6 +181,11 @@ namespace SocketHttpListener.Net if (disposed) throw new ObjectDisposedException(GetType().ToString()); + if (count == 0) + { + //return; + } + byte[] bytes = null; MemoryStream ms = GetHeaders(response, _memoryStreamFactory, false); bool chunked = response.SendChunked; @@ -206,7 +216,7 @@ namespace SocketHttpListener.Net await stream.WriteAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false); } - if (response.SendChunked) + if (chunked) stream.Write(crlf, 0, 2); } |
