aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ci/azure-pipelines.yml2
-rw-r--r--DvdLib/Ifo/AudioAttributes.cs36
-rw-r--r--DvdLib/Ifo/PgcCommandTable.cs17
-rw-r--r--DvdLib/Ifo/ProgramChain.cs4
-rw-r--r--DvdLib/Ifo/VideoAttributes.cs46
-rw-r--r--Emby.Dlna/PlayTo/CurrentIdEventArgs.cs9
-rw-r--r--Emby.Dlna/PlayTo/Device.cs9
-rw-r--r--Emby.Dlna/PlayTo/PlaylistItemFactory.cs2
-rw-r--r--Emby.Dlna/PlayTo/TransportStateEventArgs.cs9
-rw-r--r--Emby.Dlna/PlayTo/uParser.cs47
-rw-r--r--Emby.Dlna/PlayTo/uParserObject.cs9
-rw-r--r--Emby.Server.Implementations/Diagnostics/CommonProcess.cs2
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs27
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs4
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs26
-rw-r--r--Emby.Server.Implementations/MediaEncoder/EncodingManager.cs4
-rw-r--r--Jellyfin.Server/Program.cs3
-rw-r--r--MediaBrowser.Api/ApiEntryPoint.cs5
-rw-r--r--MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs2
-rw-r--r--MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs16
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs6
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs65
-rw-r--r--MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs13
-rw-r--r--SocketHttpListener/Net/HttpConnection.cs532
24 files changed, 633 insertions, 262 deletions
diff --git a/.ci/azure-pipelines.yml b/.ci/azure-pipelines.yml
index e5845c0ef..4cd19dc83 100644
--- a/.ci/azure-pipelines.yml
+++ b/.ci/azure-pipelines.yml
@@ -156,7 +156,7 @@ jobs:
overWrite: true # Optional
flattenFolders: true # Optional
- - task: DownloadGitHubReleases@0
+ - task: DownloadGitHubRelease@0
displayName: Download ABI compatibility check tool from GitHub
inputs:
connection: Jellyfin GitHub
diff --git a/DvdLib/Ifo/AudioAttributes.cs b/DvdLib/Ifo/AudioAttributes.cs
deleted file mode 100644
index b76f9fc05..000000000
--- a/DvdLib/Ifo/AudioAttributes.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-namespace DvdLib.Ifo
-{
- public enum AudioCodec
- {
- AC3 = 0,
- MPEG1 = 2,
- MPEG2ext = 3,
- LPCM = 4,
- DTS = 6,
- }
-
- public enum ApplicationMode
- {
- Unspecified = 0,
- Karaoke = 1,
- Surround = 2,
- }
-
- public class AudioAttributes
- {
- public readonly AudioCodec Codec;
- public readonly bool MultichannelExtensionPresent;
- public readonly ApplicationMode Mode;
- public readonly byte QuantDRC;
- public readonly byte SampleRate;
- public readonly byte Channels;
- public readonly ushort LanguageCode;
- public readonly byte LanguageExtension;
- public readonly byte CodeExtension;
- }
-
- public class MultiChannelExtension
- {
-
- }
-}
diff --git a/DvdLib/Ifo/PgcCommandTable.cs b/DvdLib/Ifo/PgcCommandTable.cs
deleted file mode 100644
index d329fcba2..000000000
--- a/DvdLib/Ifo/PgcCommandTable.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System.Collections.Generic;
-
-namespace DvdLib.Ifo
-{
- public class ProgramChainCommandTable
- {
- public readonly ushort LastByteAddress;
- public readonly List<VirtualMachineCommand> PreCommands;
- public readonly List<VirtualMachineCommand> PostCommands;
- public readonly List<VirtualMachineCommand> CellCommands;
- }
-
- public class VirtualMachineCommand
- {
- public readonly byte[] Command;
- }
-}
diff --git a/DvdLib/Ifo/ProgramChain.cs b/DvdLib/Ifo/ProgramChain.cs
index 80889738f..7b003005b 100644
--- a/DvdLib/Ifo/ProgramChain.cs
+++ b/DvdLib/Ifo/ProgramChain.cs
@@ -25,13 +25,10 @@ namespace DvdLib.Ifo
public byte[] SubpictureStreamControl { get; private set; } // 32*4 entries
private ushort _nextProgramNumber;
- public readonly ProgramChain Next;
private ushort _prevProgramNumber;
- public readonly ProgramChain Previous;
private ushort _goupProgramNumber;
- public readonly ProgramChain Goup; // ?? maybe Group
public ProgramPlaybackMode PlaybackMode { get; private set; }
public uint ProgramCount { get; private set; }
@@ -40,7 +37,6 @@ namespace DvdLib.Ifo
public byte[] Palette { get; private set; } // 16*4 entries
private ushort _commandTableOffset;
- public readonly ProgramChainCommandTable CommandTable;
private ushort _programMapOffset;
private ushort _cellPlaybackOffset;
diff --git a/DvdLib/Ifo/VideoAttributes.cs b/DvdLib/Ifo/VideoAttributes.cs
deleted file mode 100644
index 8b3996715..000000000
--- a/DvdLib/Ifo/VideoAttributes.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-namespace DvdLib.Ifo
-{
- public enum VideoCodec
- {
- MPEG1 = 0,
- MPEG2 = 1,
- }
-
- public enum VideoFormat
- {
- NTSC = 0,
- PAL = 1,
- }
-
- public enum AspectRatio
- {
- ar4to3 = 0,
- ar16to9 = 3
- }
-
- public enum FilmMode
- {
- None = -1,
- Camera = 0,
- Film = 1,
- }
-
- public class VideoAttributes
- {
- public readonly VideoCodec Codec;
- public readonly VideoFormat Format;
- public readonly AspectRatio Aspect;
- public readonly bool AutomaticPanScan;
- public readonly bool AutomaticLetterBox;
- public readonly bool Line21CCField1;
- public readonly bool Line21CCField2;
- public readonly int Width;
- public readonly int Height;
- public readonly bool Letterboxed;
- public readonly FilmMode FilmMode;
-
- public VideoAttributes()
- {
- }
- }
-}
diff --git a/Emby.Dlna/PlayTo/CurrentIdEventArgs.cs b/Emby.Dlna/PlayTo/CurrentIdEventArgs.cs
deleted file mode 100644
index fdf435bcf..000000000
--- a/Emby.Dlna/PlayTo/CurrentIdEventArgs.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using System;
-
-namespace Emby.Dlna.PlayTo
-{
- public class CurrentIdEventArgs : EventArgs
- {
- public string Id { get; set; }
- }
-}
diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs
index b62c5e1d4..0c5ddee65 100644
--- a/Emby.Dlna/PlayTo/Device.cs
+++ b/Emby.Dlna/PlayTo/Device.cs
@@ -1126,6 +1126,11 @@ namespace Emby.Dlna.PlayTo
private void OnPlaybackStart(uBaseObject mediaInfo)
{
+ if (string.IsNullOrWhiteSpace(mediaInfo.Url))
+ {
+ return;
+ }
+
PlaybackStart?.Invoke(this, new PlaybackStartEventArgs
{
MediaInfo = mediaInfo
@@ -1134,8 +1139,7 @@ namespace Emby.Dlna.PlayTo
private void OnPlaybackProgress(uBaseObject mediaInfo)
{
- var mediaUrl = mediaInfo.Url;
- if (string.IsNullOrWhiteSpace(mediaUrl))
+ if (string.IsNullOrWhiteSpace(mediaInfo.Url))
{
return;
}
@@ -1148,7 +1152,6 @@ namespace Emby.Dlna.PlayTo
private void OnPlaybackStop(uBaseObject mediaInfo)
{
-
PlaybackStopped?.Invoke(this, new PlaybackStoppedEventArgs
{
MediaInfo = mediaInfo
diff --git a/Emby.Dlna/PlayTo/PlaylistItemFactory.cs b/Emby.Dlna/PlayTo/PlaylistItemFactory.cs
index aceb634e3..446d8e1e6 100644
--- a/Emby.Dlna/PlayTo/PlaylistItemFactory.cs
+++ b/Emby.Dlna/PlayTo/PlaylistItemFactory.cs
@@ -9,8 +9,6 @@ namespace Emby.Dlna.PlayTo
{
public class PlaylistItemFactory
{
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
-
public PlaylistItem Create(Photo item, DeviceProfile profile)
{
var playlistItem = new PlaylistItem
diff --git a/Emby.Dlna/PlayTo/TransportStateEventArgs.cs b/Emby.Dlna/PlayTo/TransportStateEventArgs.cs
deleted file mode 100644
index 7dcd39e10..000000000
--- a/Emby.Dlna/PlayTo/TransportStateEventArgs.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using System;
-
-namespace Emby.Dlna.PlayTo
-{
- public class TransportStateEventArgs : EventArgs
- {
- public TRANSPORTSTATE State { get; set; }
- }
-}
diff --git a/Emby.Dlna/PlayTo/uParser.cs b/Emby.Dlna/PlayTo/uParser.cs
deleted file mode 100644
index 3a0ffffd4..000000000
--- a/Emby.Dlna/PlayTo/uParser.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Xml.Linq;
-
-namespace Emby.Dlna.PlayTo
-{
- public class uParser
- {
- public static IList<uBaseObject> ParseBrowseXml(XDocument doc)
- {
- if (doc == null)
- {
- throw new ArgumentException("doc");
- }
-
- var list = new List<uBaseObject>();
-
- var document = doc.Document;
-
- if (document == null)
- return list;
-
- var item = (from result in document.Descendants("Result") select result).FirstOrDefault();
-
- if (item == null)
- return list;
-
- var uPnpResponse = XElement.Parse((string)item);
-
- var uObjects = from container in uPnpResponse.Elements(uPnpNamespaces.containers)
- select new uParserObject { Element = container };
-
- var uObjects2 = from container in uPnpResponse.Elements(uPnpNamespaces.items)
- select new uParserObject { Element = container };
-
- list.AddRange(uObjects.Concat(uObjects2).Select(CreateObjectFromXML).Where(uObject => uObject != null));
-
- return list;
- }
-
- public static uBaseObject CreateObjectFromXML(uParserObject uItem)
- {
- return UpnpContainer.Create(uItem.Element);
- }
- }
-}
diff --git a/Emby.Dlna/PlayTo/uParserObject.cs b/Emby.Dlna/PlayTo/uParserObject.cs
deleted file mode 100644
index 87a7f69c6..000000000
--- a/Emby.Dlna/PlayTo/uParserObject.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using System.Xml.Linq;
-
-namespace Emby.Dlna.PlayTo
-{
- public class uParserObject
- {
- public XElement Element { get; set; }
- }
-}
diff --git a/Emby.Server.Implementations/Diagnostics/CommonProcess.cs b/Emby.Server.Implementations/Diagnostics/CommonProcess.cs
index 78b22bda3..2c4ef170d 100644
--- a/Emby.Server.Implementations/Diagnostics/CommonProcess.cs
+++ b/Emby.Server.Implementations/Diagnostics/CommonProcess.cs
@@ -130,7 +130,7 @@ namespace Emby.Server.Implementations.Diagnostics
public void Dispose()
{
- _process.Dispose();
+ _process?.Dispose();
}
}
}
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index 3c2272b56..6591d54c5 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -278,6 +278,7 @@ namespace Emby.Server.Implementations.Library
{
throw new ArgumentNullException(nameof(item));
}
+
if (item is IItemByName)
{
if (!(item is MusicArtist))
@@ -285,18 +286,7 @@ namespace Emby.Server.Implementations.Library
return;
}
}
-
- else if (item.IsFolder)
- {
- //if (!(item is ICollectionFolder) && !(item is UserView) && !(item is Channel) && !(item is AggregateFolder))
- //{
- // if (item.SourceType != SourceType.Library)
- // {
- // return;
- // }
- //}
- }
- else
+ else if (!item.IsFolder)
{
if (!(item is Video) && !(item is LiveTvChannel))
{
@@ -371,19 +361,20 @@ namespace Emby.Server.Implementations.Library
foreach (var metadataPath in GetMetadataPaths(item, children))
{
- _logger.LogDebug("Deleting path {0}", metadataPath);
+ if (!Directory.Exists(metadataPath))
+ {
+ continue;
+ }
+
+ _logger.LogDebug("Deleting path {MetadataPath}", metadataPath);
try
{
Directory.Delete(metadataPath, true);
}
- catch (IOException)
- {
-
- }
catch (Exception ex)
{
- _logger.LogError(ex, "Error deleting {metadataPath}", metadataPath);
+ _logger.LogError(ex, "Error deleting {MetadataPath}", metadataPath);
}
}
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index fceb82ba1..f424bdf5c 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -105,8 +105,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_mediaSourceManager = mediaSourceManager;
_streamHelper = streamHelper;
- _seriesTimerProvider = new SeriesTimerManager(jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers"));
- _timerProvider = new TimerManager(jsonSerializer, _logger, Path.Combine(DataPath, "timers"), _logger);
+ _seriesTimerProvider = new SeriesTimerManager(jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers.json"));
+ _timerProvider = new TimerManager(jsonSerializer, _logger, Path.Combine(DataPath, "timers.json"), _logger);
_timerProvider.TimerFired += _timerProvider_TimerFired;
_config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated;
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
index a2ac60b31..9c45ee36a 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using MediaBrowser.Model.IO;
using MediaBrowser.Model.Serialization;
using Microsoft.Extensions.Logging;
@@ -32,32 +31,28 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
if (_items == null)
{
+ if (!File.Exists(_dataPath))
+ {
+ return new List<T>();
+ }
+
Logger.LogInformation("Loading live tv data from {0}", _dataPath);
_items = GetItemsFromFile(_dataPath);
}
+
return _items.ToList();
}
}
private List<T> GetItemsFromFile(string path)
{
- var jsonFile = path + ".json";
-
- if (!File.Exists(jsonFile))
- {
- return new List<T>();
- }
-
try
{
- return _jsonSerializer.DeserializeFromFile<List<T>>(jsonFile) ?? new List<T>();
- }
- catch (IOException)
- {
+ return _jsonSerializer.DeserializeFromFile<List<T>>(path);
}
catch (Exception ex)
{
- Logger.LogError(ex, "Error deserializing {jsonFile}", jsonFile);
+ Logger.LogError(ex, "Error deserializing {Path}", path);
}
return new List<T>();
@@ -70,12 +65,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
throw new ArgumentNullException(nameof(newList));
}
- var file = _dataPath + ".json";
- Directory.CreateDirectory(Path.GetDirectoryName(file));
+ Directory.CreateDirectory(Path.GetDirectoryName(_dataPath));
lock (_fileDataLock)
{
- _jsonSerializer.SerializeToFile(newList, file);
+ _jsonSerializer.SerializeToFile(newList, _dataPath);
_items = newList;
}
}
diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
index e68046f6d..52d07d784 100644
--- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
+++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
@@ -202,6 +202,10 @@ namespace Emby.Server.Implementations.MediaEncoder
private static List<string> GetSavedChapterImages(Video video, IDirectoryService directoryService)
{
var path = GetChapterImagesPath(video);
+ if (!Directory.Exists(path))
+ {
+ return new List<string>();
+ }
try
{
diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs
index a43c3fea5..0ef1711d4 100644
--- a/Jellyfin.Server/Program.cs
+++ b/Jellyfin.Server/Program.cs
@@ -125,7 +125,7 @@ namespace Jellyfin.Server
SQLitePCL.Batteries_V2.Init();
// Allow all https requests
- ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; } );
+ ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; });
var fileSystem = new ManagedFileSystem(_loggerFactory, environmentInfo, appPaths);
@@ -144,7 +144,6 @@ namespace Jellyfin.Server
appHost.ImageProcessor.ImageEncoder = GetImageEncoder(fileSystem, appPaths, appHost.LocalizationManager);
await appHost.RunStartupTasks().ConfigureAwait(false);
- // TODO: read input for a stop command
try
{
diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs
index ceff6b02e..700cbb943 100644
--- a/MediaBrowser.Api/ApiEntryPoint.cs
+++ b/MediaBrowser.Api/ApiEntryPoint.cs
@@ -172,6 +172,11 @@ namespace MediaBrowser.Api
{
var path = _config.ApplicationPaths.GetTranscodingTempPath();
+ if (!Directory.Exists(path))
+ {
+ return;
+ }
+
foreach (var file in _fileSystem.GetFilePaths(path, true))
{
_fileSystem.DeleteFile(file);
diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
index d4ac3b7c3..d032a849e 100644
--- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
@@ -74,7 +74,7 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <param name="inputFiles">The input files.</param>
/// <param name="protocol">The protocol.</param>
/// <returns>System.String.</returns>
- string GetInputArgument(string[] inputFiles, MediaProtocol protocol);
+ string GetInputArgument(IReadOnlyList<string> inputFiles, MediaProtocol protocol);
/// <summary>
/// Gets the time parameter.
diff --git a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs
index c0706ceeb..25a8ad596 100644
--- a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs
@@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.IO;
+using Microsoft.Extensions.Logging;
namespace MediaBrowser.LocalMetadata.Images
{
@@ -12,11 +13,16 @@ namespace MediaBrowser.LocalMetadata.Images
{
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
+ private readonly ILogger _logger;
- public InternalMetadataFolderImageProvider(IServerConfigurationManager config, IFileSystem fileSystem)
+ public InternalMetadataFolderImageProvider(
+ IServerConfigurationManager config,
+ IFileSystem fileSystem,
+ ILogger<InternalMetadataFolderImageProvider> logger)
{
_config = config;
_fileSystem = fileSystem;
+ _logger = logger;
}
public string Name => "Internal Images";
@@ -53,12 +59,18 @@ namespace MediaBrowser.LocalMetadata.Images
{
var path = item.GetInternalMetadataPath();
+ if (!Directory.Exists(path))
+ {
+ return new List<LocalImageInfo>();
+ }
+
try
{
return new LocalImageProvider(_fileSystem).GetImages(item, path, false, directoryService);
}
- catch (IOException)
+ catch (IOException ex)
{
+ _logger.LogError(ex, "Error while getting images for {Library}", item.Name);
return new List<LocalImageInfo>();
}
}
diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs
index 44e62446b..d4aede572 100644
--- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs
@@ -6,11 +6,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
public static class EncodingUtils
{
- public static string GetInputArgument(List<string> inputFiles, MediaProtocol protocol)
+ public static string GetInputArgument(IReadOnlyList<string> inputFiles, MediaProtocol protocol)
{
if (protocol != MediaProtocol.File)
{
- var url = inputFiles.First();
+ var url = inputFiles[0];
return string.Format("\"{0}\"", url);
}
@@ -29,7 +29,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
// If there's more than one we'll need to use the concat command
if (inputFiles.Count > 1)
{
- var files = string.Join("|", inputFiles.Select(NormalizePath).ToArray());
+ var files = string.Join("|", inputFiles.Select(NormalizePath));
return string.Format("concat:\"{0}\"", files);
}
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index 292457788..94beda3db 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -334,10 +334,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// <param name="protocol">The protocol.</param>
/// <returns>System.String.</returns>
/// <exception cref="ArgumentException">Unrecognized InputType</exception>
- public string GetInputArgument(string[] inputFiles, MediaProtocol protocol)
- {
- return EncodingUtils.GetInputArgument(inputFiles.ToList(), protocol);
- }
+ public string GetInputArgument(IReadOnlyList<string> inputFiles, MediaProtocol protocol)
+ => EncodingUtils.GetInputArgument(inputFiles, protocol);
/// <summary>
/// Gets the media info internal.
@@ -354,8 +352,9 @@ namespace MediaBrowser.MediaEncoding.Encoder
CancellationToken cancellationToken)
{
var args = extractChapters
- ? "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_chapters -show_format"
- : "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_format";
+ ? "{0} -i {1} -threads 0 -v warning -print_format json -show_streams -show_chapters -show_format"
+ : "{0} -i {1} -threads 0 -v warning -print_format json -show_streams -show_format";
+ args = string.Format(args, probeSizeArgument, inputPath).Trim();
var process = _processFactory.Create(new ProcessOptions
{
@@ -364,8 +363,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
// Must consume both or ffmpeg may hang due to deadlocks. See comments below.
RedirectStandardOutput = true,
+
FileName = FFprobePath,
- Arguments = string.Format(args, probeSizeArgument, inputPath).Trim(),
+ Arguments = args,
+
IsHidden = true,
ErrorDialog = false,
@@ -383,43 +384,45 @@ namespace MediaBrowser.MediaEncoding.Encoder
using (var processWrapper = new ProcessWrapper(process, this, _logger))
{
+ _logger.LogDebug("Starting ffprobe with args {Args}", args);
StartProcess(processWrapper);
+ InternalMediaInfoResult result;
try
{
- //process.BeginErrorReadLine();
+ result = await _jsonSerializer.DeserializeFromStreamAsync<InternalMediaInfoResult>(
+ process.StandardOutput.BaseStream).ConfigureAwait(false);
+ }
+ catch
+ {
+ StopProcess(processWrapper, 100);
- var result = await _jsonSerializer.DeserializeFromStreamAsync<InternalMediaInfoResult>(process.StandardOutput.BaseStream).ConfigureAwait(false);
+ throw;
+ }
- if (result == null || (result.streams == null && result.format == null))
- {
- throw new Exception("ffprobe failed - streams and format are both null.");
- }
+ if (result == null || (result.streams == null && result.format == null))
+ {
+ throw new Exception("ffprobe failed - streams and format are both null.");
+ }
- if (result.streams != null)
+ if (result.streams != null)
+ {
+ // Normalize aspect ratio if invalid
+ foreach (var stream in result.streams)
{
- // Normalize aspect ratio if invalid
- foreach (var stream in result.streams)
+ if (string.Equals(stream.display_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase))
{
- if (string.Equals(stream.display_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase))
- {
- stream.display_aspect_ratio = string.Empty;
- }
- if (string.Equals(stream.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase))
- {
- stream.sample_aspect_ratio = string.Empty;
- }
+ stream.display_aspect_ratio = string.Empty;
}
- }
- return new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol);
+ if (string.Equals(stream.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase))
+ {
+ stream.sample_aspect_ratio = string.Empty;
+ }
+ }
}
- catch
- {
- StopProcess(processWrapper, 100);
- throw;
- }
+ return new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol);
}
}
diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
index cd026b39b..8195591e1 100644
--- a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
+++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
@@ -16,7 +16,7 @@ namespace MediaBrowser.Providers.MediaInfo
private readonly ILocalizationManager _localization;
private readonly IFileSystem _fileSystem;
- private string[] SubtitleExtensions = new[]
+ private static readonly HashSet<string> SubtitleExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
".srt",
".ssa",
@@ -49,9 +49,16 @@ namespace MediaBrowser.Providers.MediaInfo
startIndex += streams.Count;
+ string folder = video.GetInternalMetadataPath();
+
+ if (!Directory.Exists(folder))
+ {
+ return streams;
+ }
+
try
{
- AddExternalSubtitleStreams(streams, video.GetInternalMetadataPath(), video.Path, startIndex, directoryService, clearCache);
+ AddExternalSubtitleStreams(streams, folder, video.Path, startIndex, directoryService, clearCache);
}
catch (IOException)
{
@@ -105,7 +112,7 @@ namespace MediaBrowser.Providers.MediaInfo
{
var extension = Path.GetExtension(fullName);
- if (!SubtitleExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
+ if (!SubtitleExtensions.Contains(extension))
{
continue;
}
diff --git a/SocketHttpListener/Net/HttpConnection.cs b/SocketHttpListener/Net/HttpConnection.cs
new file mode 100644
index 000000000..5beea5f22
--- /dev/null
+++ b/SocketHttpListener/Net/HttpConnection.cs
@@ -0,0 +1,532 @@
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Security;
+using System.Net.Sockets;
+using System.Security.Authentication;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Model.Cryptography;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.System;
+using Microsoft.Extensions.Logging;
+namespace SocketHttpListener.Net
+{
+ sealed class HttpConnection
+ {
+ private static AsyncCallback s_onreadCallback = new AsyncCallback(OnRead);
+ const int BufferSize = 8192;
+ Socket _socket;
+ Stream _stream;
+ HttpEndPointListener _epl;
+ MemoryStream _memoryStream;
+ byte[] _buffer;
+ HttpListenerContext _context;
+ StringBuilder _currentLine;
+ ListenerPrefix _prefix;
+ HttpRequestStream _requestStream;
+ HttpResponseStream _responseStream;
+ bool _chunked;
+ int _reuses;
+ bool _contextBound;
+ bool secure;
+ IPEndPoint local_ep;
+ HttpListener _lastListener;
+ X509Certificate cert;
+ SslStream ssl_stream;
+
+ private readonly ILogger _logger;
+ private readonly ICryptoProvider _cryptoProvider;
+ private readonly IStreamHelper _streamHelper;
+ private readonly IFileSystem _fileSystem;
+ private readonly IEnvironmentInfo _environment;
+
+ public HttpConnection(ILogger logger, Socket socket, HttpEndPointListener epl, bool secure,
+ X509Certificate cert, ICryptoProvider cryptoProvider, IStreamHelper streamHelper, IFileSystem fileSystem,
+ IEnvironmentInfo environment)
+ {
+ _logger = logger;
+ this._socket = socket;
+ this._epl = epl;
+ this.secure = secure;
+ this.cert = cert;
+ _cryptoProvider = cryptoProvider;
+ _streamHelper = streamHelper;
+ _fileSystem = fileSystem;
+ _environment = environment;
+
+ if (secure == false)
+ {
+ _stream = new SocketStream(_socket, false);
+ }
+ else
+ {
+ ssl_stream = new SslStream(new SocketStream(_socket, false), false, (t, c, ch, e) =>
+ {
+ if (c == null)
+ {
+ return true;
+ }
+
+ //var c2 = c as X509Certificate2;
+ //if (c2 == null)
+ //{
+ // c2 = new X509Certificate2(c.GetRawCertData());
+ //}
+
+ //_clientCert = c2;
+ //_clientCertErrors = new int[] { (int)e };
+ return true;
+ });
+
+ _stream = ssl_stream;
+ }
+ }
+
+ public Stream Stream => _stream;
+
+ public async Task Init()
+ {
+ if (ssl_stream != null)
+ {
+ var enableAsync = true;
+ if (enableAsync)
+ {
+ await ssl_stream.AuthenticateAsServerAsync(cert, false, (SslProtocols)ServicePointManager.SecurityProtocol, false).ConfigureAwait(false);
+ }
+ else
+ {
+ ssl_stream.AuthenticateAsServer(cert, false, (SslProtocols)ServicePointManager.SecurityProtocol, false);
+ }
+ }
+
+ InitInternal();
+ }
+
+ private void InitInternal()
+ {
+ _contextBound = false;
+ _requestStream = null;
+ _responseStream = null;
+ _prefix = null;
+ _chunked = false;
+ _memoryStream = new MemoryStream();
+ _position = 0;
+ _inputState = InputState.RequestLine;
+ _lineState = LineState.None;
+ _context = new HttpListenerContext(this);
+ }
+
+ public bool IsClosed => (_socket == null);
+
+ public int Reuses => _reuses;
+
+ public IPEndPoint LocalEndPoint
+ {
+ get
+ {
+ if (local_ep != null)
+ return local_ep;
+
+ local_ep = (IPEndPoint)_socket.LocalEndPoint;
+ return local_ep;
+ }
+ }
+
+ public IPEndPoint RemoteEndPoint => _socket.RemoteEndPoint as IPEndPoint;
+
+ public bool IsSecure => secure;
+
+ public ListenerPrefix Prefix
+ {
+ get => _prefix;
+ set => _prefix = value;
+ }
+
+ private void OnTimeout(object unused)
+ {
+ //_logger.LogInformation("HttpConnection timer fired");
+ CloseSocket();
+ Unbind();
+ }
+
+ public void BeginReadRequest()
+ {
+ if (_buffer == null)
+ {
+ _buffer = new byte[BufferSize];
+ }
+
+ try
+ {
+ _stream.BeginRead(_buffer, 0, BufferSize, s_onreadCallback, this);
+ }
+ catch
+ {
+ CloseSocket();
+ Unbind();
+ }
+ }
+
+ public HttpRequestStream GetRequestStream(bool chunked, long contentlength)
+ {
+ if (_requestStream == null)
+ {
+ byte[] buffer = _memoryStream.GetBuffer();
+ int length = (int)_memoryStream.Length;
+ _memoryStream = null;
+ if (chunked)
+ {
+ _chunked = true;
+ //_context.Response.SendChunked = true;
+ _requestStream = new ChunkedInputStream(_context, _stream, buffer, _position, length - _position);
+ }
+ else
+ {
+ _requestStream = new HttpRequestStream(_stream, buffer, _position, length - _position, contentlength);
+ }
+ }
+ return _requestStream;
+ }
+
+ public HttpResponseStream GetResponseStream(bool isExpect100Continue = false)
+ {
+ // TODO: can we get this _stream before reading the input?
+ if (_responseStream == null)
+ {
+ var supportsDirectSocketAccess = !_context.Response.SendChunked && !isExpect100Continue && !secure;
+
+ _responseStream = new HttpResponseStream(_stream, _context.Response, false, _streamHelper, _socket, supportsDirectSocketAccess, _environment, _fileSystem, _logger);
+ }
+ return _responseStream;
+ }
+
+ private static void OnRead(IAsyncResult ares)
+ {
+ var cnc = (HttpConnection)ares.AsyncState;
+ cnc.OnReadInternal(ares);
+ }
+
+ private void OnReadInternal(IAsyncResult ares)
+ {
+ int nread = -1;
+ try
+ {
+ nread = _stream.EndRead(ares);
+ _memoryStream.Write(_buffer, 0, nread);
+ if (_memoryStream.Length > 32768)
+ {
+ SendError("Bad Request", 400);
+ Close(true);
+ return;
+ }
+ }
+ catch
+ {
+ if (_memoryStream != null && _memoryStream.Length > 0)
+ {
+ SendError();
+ }
+
+ if (_socket != null)
+ {
+ CloseSocket();
+ Unbind();
+ }
+ return;
+ }
+
+ if (nread == 0)
+ {
+ CloseSocket();
+ Unbind();
+ return;
+ }
+
+ if (ProcessInput(_memoryStream))
+ {
+ if (!_context.HaveError)
+ _context.Request.FinishInitialization();
+
+ if (_context.HaveError)
+ {
+ SendError();
+ Close(true);
+ return;
+ }
+
+ if (!_epl.BindContext(_context))
+ {
+ const int NotFoundErrorCode = 404;
+ SendError(HttpStatusDescription.Get(NotFoundErrorCode), NotFoundErrorCode);
+ Close(true);
+ return;
+ }
+ HttpListener listener = _epl.Listener;
+ if (_lastListener != listener)
+ {
+ RemoveConnection();
+ listener.AddConnection(this);
+ _lastListener = listener;
+ }
+
+ _contextBound = true;
+ listener.RegisterContext(_context);
+ return;
+ }
+ _stream.BeginRead(_buffer, 0, BufferSize, s_onreadCallback, this);
+ }
+
+ private void RemoveConnection()
+ {
+ if (_lastListener == null)
+ _epl.RemoveConnection(this);
+ else
+ _lastListener.RemoveConnection(this);
+ }
+
+ private enum InputState
+ {
+ RequestLine,
+ Headers
+ }
+
+ private enum LineState
+ {
+ None,
+ CR,
+ LF
+ }
+
+ InputState _inputState = InputState.RequestLine;
+ LineState _lineState = LineState.None;
+ int _position;
+
+ // true -> done processing
+ // false -> need more input
+ private bool ProcessInput(MemoryStream ms)
+ {
+ byte[] buffer = ms.GetBuffer();
+ int len = (int)ms.Length;
+ int used = 0;
+ string line;
+
+ while (true)
+ {
+ if (_context.HaveError)
+ return true;
+
+ if (_position >= len)
+ break;
+
+ try
+ {
+ line = ReadLine(buffer, _position, len - _position, ref used);
+ _position += used;
+ }
+ catch
+ {
+ _context.ErrorMessage = "Bad request";
+ _context.ErrorStatus = 400;
+ return true;
+ }
+
+ if (line == null)
+ break;
+
+ if (line == "")
+ {
+ if (_inputState == InputState.RequestLine)
+ continue;
+ _currentLine = null;
+ ms = null;
+ return true;
+ }
+
+ if (_inputState == InputState.RequestLine)
+ {
+ _context.Request.SetRequestLine(line);
+ _inputState = InputState.Headers;
+ }
+ else
+ {
+ try
+ {
+ _context.Request.AddHeader(line);
+ }
+ catch (Exception e)
+ {
+ _context.ErrorMessage = e.Message;
+ _context.ErrorStatus = 400;
+ return true;
+ }
+ }
+ }
+
+ if (used == len)
+ {
+ ms.SetLength(0);
+ _position = 0;
+ }
+ return false;
+ }
+
+ private string ReadLine(byte[] buffer, int offset, int len, ref int used)
+ {
+ if (_currentLine == null)
+ _currentLine = new StringBuilder(128);
+ int last = offset + len;
+ used = 0;
+ for (int i = offset; i < last && _lineState != LineState.LF; i++)
+ {
+ used++;
+ byte b = buffer[i];
+ if (b == 13)
+ {
+ _lineState = LineState.CR;
+ }
+ else if (b == 10)
+ {
+ _lineState = LineState.LF;
+ }
+ else
+ {
+ _currentLine.Append((char)b);
+ }
+ }
+
+ string result = null;
+ if (_lineState == LineState.LF)
+ {
+ _lineState = LineState.None;
+ result = _currentLine.ToString();
+ _currentLine.Length = 0;
+ }
+
+ return result;
+ }
+
+ public void SendError(string msg, int status)
+ {
+ try
+ {
+ HttpListenerResponse response = _context.Response;
+ response.StatusCode = status;
+ response.ContentType = "text/html";
+ string description = HttpStatusDescription.Get(status);
+ string str;
+ if (msg != null)
+ str = string.Format("<h1>{0} ({1})</h1>", description, msg);
+ else
+ str = string.Format("<h1>{0}</h1>", description);
+
+ byte[] error = Encoding.UTF8.GetBytes(str);
+ response.Close(error, false);
+ }
+ catch
+ {
+ // response was already closed
+ }
+ }
+
+ public void SendError()
+ {
+ SendError(_context.ErrorMessage, _context.ErrorStatus);
+ }
+
+ private void Unbind()
+ {
+ if (_contextBound)
+ {
+ _epl.UnbindContext(_context);
+ _contextBound = false;
+ }
+ }
+
+ public void Close()
+ {
+ Close(false);
+ }
+
+ private void CloseSocket()
+ {
+ if (_socket == null)
+ return;
+
+ try
+ {
+ _socket.Close();
+ }
+ catch { }
+ finally
+ {
+ _socket = null;
+ }
+
+ RemoveConnection();
+ }
+
+ internal void Close(bool force)
+ {
+ if (_socket != null)
+ {
+ Stream st = GetResponseStream();
+ if (st != null)
+ st.Close();
+
+ _responseStream = null;
+ }
+
+ if (_socket != null)
+ {
+ force |= !_context.Request.KeepAlive;
+ if (!force)
+ {
+ force = string.Equals(_context.Response.Headers["connection"], "close", StringComparison.OrdinalIgnoreCase);
+ }
+
+ if (!force && _context.Request.FlushInput())
+ {
+ if (_chunked && _context.Response.ForceCloseChunked == false)
+ {
+ // Don't close. Keep working.
+ _reuses++;
+ Unbind();
+ InitInternal();
+ BeginReadRequest();
+ return;
+ }
+
+ _reuses++;
+ Unbind();
+ InitInternal();
+ BeginReadRequest();
+ return;
+ }
+
+ Socket s = _socket;
+ _socket = null;
+ try
+ {
+ s?.Shutdown(SocketShutdown.Both);
+ }
+ catch
+ {
+ }
+ finally
+ {
+ try
+ {
+ s?.Close();
+ }
+ catch { }
+ }
+ Unbind();
+ RemoveConnection();
+ return;
+ }
+ }
+ }
+}