From 0ba267f8e26471b4b831b926027c76798f88bef4 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 2 Aug 2017 03:30:17 -0400 Subject: Enable hardware acceleration for image extraction --- Emby.Server.Implementations/Localization/Core/en-US.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations/Localization') diff --git a/Emby.Server.Implementations/Localization/Core/en-US.json b/Emby.Server.Implementations/Localization/Core/en-US.json index bc0dc236d..133644ff7 100644 --- a/Emby.Server.Implementations/Localization/Core/en-US.json +++ b/Emby.Server.Implementations/Localization/Core/en-US.json @@ -69,7 +69,7 @@ "ViewTypeTvResume": "Resume", "ViewTypeTvNextUp": "Next Up", "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", + "ViewTypeTvShowSeries": "Shows", "ViewTypeTvGenres": "Genres", "ViewTypeTvFavoriteSeries": "Favorite Series", "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", -- cgit v1.2.3 From d50ffcbfb22e1b22c80c033606601f22b1de66d2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 3 Aug 2017 12:26:01 -0400 Subject: 3.2.26.13 --- .../Localization/Ratings/us.txt | 1 + MediaBrowser.Api/ItemUpdateService.cs | 1 - MediaBrowser.Api/Playback/UniversalAudioService.cs | 18 ++++++++++++++---- MediaBrowser.Server.Mono/Program.cs | 2 +- SharedVersion.cs | 2 +- 5 files changed, 17 insertions(+), 7 deletions(-) (limited to 'Emby.Server.Implementations/Localization') diff --git a/Emby.Server.Implementations/Localization/Ratings/us.txt b/Emby.Server.Implementations/Localization/Ratings/us.txt index 3f5311e0e..9bd78c72b 100644 --- a/Emby.Server.Implementations/Localization/Ratings/us.txt +++ b/Emby.Server.Implementations/Localization/Ratings/us.txt @@ -1,3 +1,4 @@ +APPROVED,1 G,1 E,1 EC,1 diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index 5325df325..19220cdec 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -242,7 +242,6 @@ namespace MediaBrowser.Api item.CriticRating = request.CriticRating; - item.DisplayMediaType = request.DisplayMediaType; item.CommunityRating = request.CommunityRating; item.HomePageUrl = request.HomePageUrl; item.IndexNumber = request.IndexNumber; diff --git a/MediaBrowser.Api/Playback/UniversalAudioService.cs b/MediaBrowser.Api/Playback/UniversalAudioService.cs index 118bf5246..0211fe75e 100644 --- a/MediaBrowser.Api/Playback/UniversalAudioService.cs +++ b/MediaBrowser.Api/Playback/UniversalAudioService.cs @@ -128,11 +128,21 @@ namespace MediaBrowser.Api.Playback var directPlayProfiles = new List(); - directPlayProfiles.Add(new DirectPlayProfile + var containers = (request.Container ?? string.Empty).Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries); + + foreach (var container in containers) { - Type = DlnaProfileType.Audio, - Container = request.Container - }); + var parts = container.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); + + var audioCodecs = parts.Length == 1 ? null : string.Join(",", parts.Skip(1).ToArray()); + + directPlayProfiles.Add(new DirectPlayProfile + { + Type = DlnaProfileType.Audio, + Container = parts[0], + AudioCodec = audioCodecs + }); + } deviceProfile.DirectPlayProfiles = directPlayProfiles.ToArray(); diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 2d5bf85e5..0a70c446f 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -97,7 +97,7 @@ namespace MediaBrowser.Server.Mono private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, StartupOptions options) { // Allow all https requests - //ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; }); + ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; }); var environmentInfo = GetEnvironmentInfo(); diff --git a/SharedVersion.cs b/SharedVersion.cs index d0e3bdd02..bbaac5d90 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.26.12")] +[assembly: AssemblyVersion("3.2.26.13")] -- cgit v1.2.3 From db315c4e3279a0f7c5fd5507887b32c6436b90af Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 5 Aug 2017 15:02:33 -0400 Subject: update media source methods --- Emby.Dlna/Didl/DidlBuilder.cs | 4 +- Emby.Dlna/PlayTo/PlayToController.cs | 2 +- .../Data/SqliteItemRepository.cs | 25 +--- .../Data/SqliteUserDataRepository.cs | 2 +- Emby.Server.Implementations/Dto/DtoService.cs | 4 +- .../Emby.Server.Implementations.csproj | 3 + .../Library/MediaSourceManager.cs | 15 ++- .../LiveTv/LiveTvManager.cs | 4 +- .../LiveTv/LiveTvMediaSourceProvider.cs | 3 +- .../Localization/Ratings/es.txt | 1 + .../Localization/Ratings/ro.txt | 1 + .../MediaEncoder/EncodingManager.cs | 22 ++-- MediaBrowser.Controller/Entities/Audio/Audio.cs | 22 +++- MediaBrowser.Controller/Entities/IHasId.cs | 9 -- MediaBrowser.Controller/Entities/IHasImages.cs | 2 +- .../Entities/IHasMediaSources.cs | 4 +- MediaBrowser.Controller/Entities/IHasMetadata.cs | 1 + MediaBrowser.Controller/Entities/IHasUserData.cs | 7 +- MediaBrowser.Controller/Entities/Video.cs | 66 +++++++--- .../Library/IMediaSourceManager.cs | 8 +- .../LiveTv/LiveTvAudioRecording.cs | 4 +- MediaBrowser.Controller/LiveTv/LiveTvChannel.cs | 7 +- .../LiveTv/LiveTvVideoRecording.cs | 4 +- .../MediaBrowser.Controller.csproj | 1 - .../MediaEncoding/EncodingHelper.cs | 28 ++++- .../Persistence/IItemRepository.cs | 2 +- MediaBrowser.Model/Dto/MediaSourceInfo.cs | 2 - .../MediaInfo/AudioImageProvider.cs | 4 +- .../MediaInfo/FFProbeVideoInfo.cs | 78 +++++------- .../MediaInfo/VideoImageProvider.cs | 138 +++++++-------------- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 9 +- 31 files changed, 235 insertions(+), 247 deletions(-) create mode 100644 Emby.Server.Implementations/Localization/Ratings/ro.txt delete mode 100644 MediaBrowser.Controller/Entities/IHasId.cs (limited to 'Emby.Server.Implementations/Localization') diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index a1b692d98..71a049394 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -193,7 +193,7 @@ namespace Emby.Dlna.Didl { if (streamInfo == null) { - var sources = _mediaSourceManager.GetStaticMediaSources(video, true, _user).ToList(); + var sources = _mediaSourceManager.GetStaticMediaSources(video, true, _user); streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildVideoItem(new VideoOptions { @@ -508,7 +508,7 @@ namespace Emby.Dlna.Didl if (streamInfo == null) { - var sources = _mediaSourceManager.GetStaticMediaSources(audio, true, _user).ToList(); + var sources = _mediaSourceManager.GetStaticMediaSources(audio, true, _user); streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildAudioItem(new AudioOptions { diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index 15d73e824..7164cf598 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -503,7 +503,7 @@ namespace Emby.Dlna.PlayTo var hasMediaSources = item as IHasMediaSources; var mediaSources = hasMediaSources != null - ? (_mediaSourceManager.GetStaticMediaSources(hasMediaSources, true, user)).ToList() + ? (_mediaSourceManager.GetStaticMediaSources(hasMediaSources, true, user)) : new List(); var playlistItem = GetPlaylistItem(item, mediaSources, profile, _session.DeviceId, mediaSourceId, audioStreamIndex, subtitleStreamIndex); diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 80a5defd6..3825389bf 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -113,7 +113,7 @@ namespace Emby.Server.Implementations.Data { get { - return true; + return false; } } @@ -1972,20 +1972,7 @@ namespace Emby.Server.Implementations.Data /// Task{IEnumerable{ItemReview}}. public IEnumerable GetCriticReviews(Guid itemId) { - try - { - var path = Path.Combine(_criticReviewsPath, itemId + ".json"); - - return _jsonSerializer.DeserializeFromFile>(path); - } - catch (FileNotFoundException) - { - return new List(); - } - catch (IOException) - { - return new List(); - } + return new List(); } private readonly Task _cachedTask = Task.FromResult(true); @@ -1997,12 +1984,6 @@ namespace Emby.Server.Implementations.Data /// Task. public Task SaveCriticReviews(Guid itemId, IEnumerable criticReviews) { - _fileSystem.CreateDirectory(_criticReviewsPath); - - var path = Path.Combine(_criticReviewsPath, itemId + ".json"); - - _jsonSerializer.SerializeToFile(criticReviews.ToList(), path); - return _cachedTask; } @@ -5610,7 +5591,7 @@ namespace Emby.Server.Implementations.Data return item; } - public IEnumerable GetMediaStreams(MediaStreamQuery query) + public List GetMediaStreams(MediaStreamQuery query) { CheckDisposed(); diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index bf6388f5d..b76555bde 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -95,7 +95,7 @@ namespace Emby.Server.Implementations.Data { get { - return true; + return false; } } diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index a57ee0b9b..c50e5600a 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -359,11 +359,11 @@ namespace Emby.Server.Implementations.Dto { if (user == null) { - dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true).ToList(); + dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true); } else { - dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true, user).ToList(); + dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true, user); } } } diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 3d6e02816..ed69c9755 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -413,6 +413,9 @@ + + + - \ No newline at end of file diff --git a/Emby.Server.Core/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Core/EntryPoints/ExternalPortForwarding.cs deleted file mode 100644 index 2c7e6a487..000000000 --- a/Emby.Server.Core/EntryPoints/ExternalPortForwarding.cs +++ /dev/null @@ -1,334 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Net; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Threading; -using Mono.Nat; -using System.Threading.Tasks; - -namespace Emby.Server.Core.EntryPoints -{ - public class ExternalPortForwarding : IServerEntryPoint - { - private readonly IServerApplicationHost _appHost; - private readonly ILogger _logger; - private readonly IHttpClient _httpClient; - private readonly IServerConfigurationManager _config; - private readonly IDeviceDiscovery _deviceDiscovery; - - private ITimer _timer; - private bool _isStarted; - private readonly ITimerFactory _timerFactory; - - public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, ITimerFactory timerFactory) - { - _logger = logmanager.GetLogger("PortMapper"); - _appHost = appHost; - _config = config; - _deviceDiscovery = deviceDiscovery; - _httpClient = httpClient; - _timerFactory = timerFactory; - } - - private string _lastConfigIdentifier; - private string GetConfigIdentifier() - { - var values = new List(); - var config = _config.Configuration; - - values.Add(config.EnableUPnP.ToString()); - values.Add(config.PublicPort.ToString(CultureInfo.InvariantCulture)); - values.Add(_appHost.HttpPort.ToString(CultureInfo.InvariantCulture)); - values.Add(_appHost.HttpsPort.ToString(CultureInfo.InvariantCulture)); - values.Add(config.EnableHttps.ToString()); - values.Add(_appHost.EnableHttps.ToString()); - - return string.Join("|", values.ToArray()); - } - - void _config_ConfigurationUpdated(object sender, EventArgs e) - { - if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase)) - { - if (_isStarted) - { - DisposeNat(); - } - - Run(); - } - } - - public void Run() - { - NatUtility.Logger = _logger; - NatUtility.HttpClient = _httpClient; - - if (_config.Configuration.EnableUPnP) - { - Start(); - } - - _config.ConfigurationUpdated -= _config_ConfigurationUpdated; - _config.ConfigurationUpdated += _config_ConfigurationUpdated; - } - - private void Start() - { - _logger.Debug("Starting NAT discovery"); - NatUtility.EnabledProtocols = new List - { - NatProtocol.Pmp - }; - NatUtility.DeviceFound += NatUtility_DeviceFound; - - // Mono.Nat does never rise this event. The event is there however it is useless. - // You could remove it with no risk. - NatUtility.DeviceLost += NatUtility_DeviceLost; - - - NatUtility.StartDiscovery(); - - _timer = _timerFactory.Create(ClearCreatedRules, null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); - - _deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered; - - _lastConfigIdentifier = GetConfigIdentifier(); - - _isStarted = true; - } - - private async void _deviceDiscovery_DeviceDiscovered(object sender, GenericEventArgs e) - { - if (_disposed) - { - return; - } - - var info = e.Argument; - - string usn; - if (!info.Headers.TryGetValue("USN", out usn)) usn = string.Empty; - - string nt; - if (!info.Headers.TryGetValue("NT", out nt)) nt = string.Empty; - - // Filter device type - if (usn.IndexOf("WANIPConnection:", StringComparison.OrdinalIgnoreCase) == -1 && - nt.IndexOf("WANIPConnection:", StringComparison.OrdinalIgnoreCase) == -1 && - usn.IndexOf("WANPPPConnection:", StringComparison.OrdinalIgnoreCase) == -1 && - nt.IndexOf("WANPPPConnection:", StringComparison.OrdinalIgnoreCase) == -1) - { - return; - } - - var identifier = string.IsNullOrWhiteSpace(usn) ? nt : usn; - - if (info.Location == null) - { - return; - } - - lock (_usnsHandled) - { - if (_usnsHandled.Contains(identifier)) - { - return; - } - _usnsHandled.Add(identifier); - } - - _logger.Debug("Found NAT device: " + identifier); - - IPAddress address; - if (IPAddress.TryParse(info.Location.Host, out address)) - { - // The Handle method doesn't need the port - var endpoint = new IPEndPoint(address, info.Location.Port); - - IPAddress localAddress = null; - - try - { - var localAddressString = await _appHost.GetLocalApiUrl().ConfigureAwait(false); - - Uri uri; - if (Uri.TryCreate(localAddressString, UriKind.Absolute, out uri)) - { - localAddressString = uri.Host; - - if (!IPAddress.TryParse(localAddressString, out localAddress)) - { - return; - } - } - } - catch (Exception ex) - { - return; - } - - if (_disposed) - { - return; - } - - _logger.Debug("Calling Nat.Handle on " + identifier); - NatUtility.Handle(localAddress, info, endpoint, NatProtocol.Upnp); - } - } - - private void ClearCreatedRules(object state) - { - lock (_createdRules) - { - _createdRules.Clear(); - } - lock (_usnsHandled) - { - _usnsHandled.Clear(); - } - } - - void NatUtility_DeviceFound(object sender, DeviceEventArgs e) - { - if (_disposed) - { - return; - } - - try - { - var device = e.Device; - _logger.Debug("NAT device found: {0}", device.LocalAddress.ToString()); - - CreateRules(device); - } - catch - { - // I think it could be a good idea to log the exception because - // you are using permanent portmapping here (never expire) and that means that next time - // CreatePortMap is invoked it can fails with a 718-ConflictInMappingEntry or not. That depends - // on the router's upnp implementation (specs says it should fail however some routers don't do it) - // It also can fail with others like 727-ExternalPortOnlySupportsWildcard, 728-NoPortMapsAvailable - // and those errors (upnp errors) could be useful for diagnosting. - - // Commenting out because users are reporting problems out of our control - //_logger.ErrorException("Error creating port forwarding rules", ex); - } - } - - private List _createdRules = new List(); - private List _usnsHandled = new List(); - private async void CreateRules(INatDevice device) - { - if (_disposed) - { - throw new ObjectDisposedException("PortMapper"); - } - - // On some systems the device discovered event seems to fire repeatedly - // This check will help ensure we're not trying to port map the same device over and over - - var address = device.LocalAddress.ToString(); - - lock (_createdRules) - { - if (!_createdRules.Contains(address)) - { - _createdRules.Add(address); - } - else - { - return; - } - } - - var success = await CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort).ConfigureAwait(false); - - if (success) - { - await CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort).ConfigureAwait(false); - } - } - - private async Task CreatePortMap(INatDevice device, int privatePort, int publicPort) - { - _logger.Debug("Creating port map on port {0}", privatePort); - - try - { - await device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort) - { - Description = _appHost.Name - - }).ConfigureAwait(false); - - return true; - } - catch (Exception ex) - { - _logger.Error("Error creating port map: " + ex.Message); - - return false; - } - } - - // As I said before, this method will be never invoked. You can remove it. - void NatUtility_DeviceLost(object sender, DeviceEventArgs e) - { - var device = e.Device; - _logger.Debug("NAT device lost: {0}", device.LocalAddress.ToString()); - } - - private bool _disposed = false; - public void Dispose() - { - _disposed = true; - DisposeNat(); - } - - private void DisposeNat() - { - _logger.Debug("Stopping NAT discovery"); - - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } - - _deviceDiscovery.DeviceDiscovered -= _deviceDiscovery_DeviceDiscovered; - - try - { - // This is not a significant improvement - NatUtility.StopDiscovery(); - NatUtility.DeviceFound -= NatUtility_DeviceFound; - NatUtility.DeviceLost -= NatUtility_DeviceLost; - } - // Statements in try-block will no fail because StopDiscovery is a one-line - // method that was no chances to fail. - // public static void StopDiscovery () - // { - // searching.Reset(); - // } - // IMO you could remove the catch-block - catch (Exception ex) - { - _logger.ErrorException("Error stopping NAT Discovery", ex); - } - finally - { - _isStarted = false; - } - } - } -} \ No newline at end of file diff --git a/Emby.Server.Core/HttpServerFactory.cs b/Emby.Server.Core/HttpServerFactory.cs deleted file mode 100644 index e16cbea0e..000000000 --- a/Emby.Server.Core/HttpServerFactory.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.IO; -using System.Net.Security; -using System.Net.Sockets; -using System.Security.Cryptography.X509Certificates; -using System.Threading; -using System.Threading.Tasks; -using Emby.Common.Implementations.Net; -using Emby.Server.Implementations.HttpServer; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Net; -using MediaBrowser.Model.Cryptography; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.System; -using MediaBrowser.Model.Text; -using ServiceStack.Text.Jsv; -using SocketHttpListener.Primitives; - -namespace Emby.Server.Core -{ - /// - /// Class ServerFactory - /// - public static class HttpServerFactory - { - /// - /// Creates the server. - /// - /// IHttpServer. - public static IHttpServer CreateServer(IServerApplicationHost applicationHost, - ILogManager logManager, - IServerConfigurationManager config, - INetworkManager networkmanager, - IMemoryStreamFactory streamProvider, - string serverName, - string defaultRedirectpath, - ITextEncoding textEncoding, - ISocketFactory socketFactory, - ICryptoProvider cryptoProvider, - IJsonSerializer json, - IXmlSerializer xml, - IEnvironmentInfo environment, - ICertificate certificate, - IFileSystem fileSystem, - bool enableDualModeSockets) - { - var logger = logManager.GetLogger("HttpServer"); - - return new HttpListenerHost(applicationHost, - logger, - config, - serverName, - defaultRedirectpath, - networkmanager, - streamProvider, - textEncoding, - socketFactory, - cryptoProvider, - json, - xml, - environment, - certificate, - new StreamFactory(), - GetParseFn, - enableDualModeSockets, - fileSystem); - } - - private static Func GetParseFn(Type propertyType) - { - return s => JsvReader.GetParseFn(propertyType)(s); - } - } - - public class StreamFactory : IStreamFactory - { - public Stream CreateNetworkStream(IAcceptSocket acceptSocket, bool ownsSocket) - { - var netSocket = (NetAcceptSocket)acceptSocket; - - return new SocketStream(netSocket.Socket, ownsSocket); - } - - public Task AuthenticateSslStreamAsServer(Stream stream, ICertificate certificate) - { - var sslStream = (SslStream)stream; - var cert = (Certificate)certificate; - - return sslStream.AuthenticateAsServerAsync(cert.X509Certificate); - } - - public Stream CreateSslStream(Stream innerStream, bool leaveInnerStreamOpen) - { - return new SslStream(innerStream, leaveInnerStreamOpen); - } - } - - public class Certificate : ICertificate - { - public Certificate(X509Certificate x509Certificate) - { - X509Certificate = x509Certificate; - } - - public X509Certificate X509Certificate { get; private set; } - } -} diff --git a/Emby.Server.Core/IO/LibraryMonitor.cs b/Emby.Server.Core/IO/LibraryMonitor.cs deleted file mode 100644 index ebc5e5e55..000000000 --- a/Emby.Server.Core/IO/LibraryMonitor.cs +++ /dev/null @@ -1,653 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.System; -using MediaBrowser.Model.Tasks; -using MediaBrowser.Model.Threading; -using Emby.Server.Implementations.IO; - -namespace Emby.Server.Core.IO -{ - public class LibraryMonitor : ILibraryMonitor - { - /// - /// The file system watchers - /// - private readonly ConcurrentDictionary _fileSystemWatchers = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - /// - /// The affected paths - /// - private readonly List _activeRefreshers = new List(); - - /// - /// A dynamic list of paths that should be ignored. Added to during our own file sytem modifications. - /// - private readonly ConcurrentDictionary _tempIgnoredPaths = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - - /// - /// Any file name ending in any of these will be ignored by the watchers - /// - private readonly IReadOnlyList _alwaysIgnoreFiles = new List - { - "small.jpg", - "albumart.jpg", - - // WMC temp recording directories that will constantly be written to - "TempRec", - "TempSBE" - }; - - private readonly IReadOnlyList _alwaysIgnoreSubstrings = new List - { - // Synology - "eaDir", - "#recycle", - ".wd_tv", - ".actors" - }; - - private readonly IReadOnlyList _alwaysIgnoreExtensions = new List - { - // thumbs.db - ".db", - - // bts sync files - ".bts", - ".sync" - }; - - /// - /// Add the path to our temporary ignore list. Use when writing to a path within our listening scope. - /// - /// The path. - private void TemporarilyIgnore(string path) - { - _tempIgnoredPaths[path] = path; - } - - public void ReportFileSystemChangeBeginning(string path) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException("path"); - } - - TemporarilyIgnore(path); - } - - public bool IsPathLocked(string path) - { - var lockedPaths = _tempIgnoredPaths.Keys.ToList(); - return lockedPaths.Any(i => _fileSystem.AreEqual(i, path) || _fileSystem.ContainsSubPath(i, path)); - } - - public async void ReportFileSystemChangeComplete(string path, bool refreshPath) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException("path"); - } - - // This is an arbitraty amount of time, but delay it because file system writes often trigger events long after the file was actually written to. - // Seeing long delays in some situations, especially over the network, sometimes up to 45 seconds - // But if we make this delay too high, we risk missing legitimate changes, such as user adding a new file, or hand-editing metadata - await Task.Delay(45000).ConfigureAwait(false); - - string val; - _tempIgnoredPaths.TryRemove(path, out val); - - if (refreshPath) - { - try - { - ReportFileSystemChanged(path); - } - catch (Exception ex) - { - Logger.ErrorException("Error in ReportFileSystemChanged for {0}", ex, path); - } - } - } - - /// - /// Gets or sets the logger. - /// - /// The logger. - private ILogger Logger { get; set; } - - /// - /// Gets or sets the task manager. - /// - /// The task manager. - private ITaskManager TaskManager { get; set; } - - private ILibraryManager LibraryManager { get; set; } - private IServerConfigurationManager ConfigurationManager { get; set; } - - private readonly IFileSystem _fileSystem; - private readonly ITimerFactory _timerFactory; - private readonly IEnvironmentInfo _environmentInfo; - - /// - /// Initializes a new instance of the class. - /// - public LibraryMonitor(ILogManager logManager, ITaskManager taskManager, ILibraryManager libraryManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ITimerFactory timerFactory, ISystemEvents systemEvents, IEnvironmentInfo environmentInfo) - { - if (taskManager == null) - { - throw new ArgumentNullException("taskManager"); - } - - LibraryManager = libraryManager; - TaskManager = taskManager; - Logger = logManager.GetLogger(GetType().Name); - ConfigurationManager = configurationManager; - _fileSystem = fileSystem; - _timerFactory = timerFactory; - _environmentInfo = environmentInfo; - - systemEvents.Resume += _systemEvents_Resume; - } - - private void _systemEvents_Resume(object sender, EventArgs e) - { - Restart(); - } - - private void Restart() - { - Stop(); - - if (!_disposed) - { - Start(); - } - } - - private bool IsLibraryMonitorEnabaled(BaseItem item) - { - if (item is BasePluginFolder) - { - return false; - } - - var options = LibraryManager.GetLibraryOptions(item); - - if (options != null) - { - return options.EnableRealtimeMonitor; - } - - return false; - } - - public void Start() - { - LibraryManager.ItemAdded += LibraryManager_ItemAdded; - LibraryManager.ItemRemoved += LibraryManager_ItemRemoved; - - var pathsToWatch = new List { }; - - var paths = LibraryManager - .RootFolder - .Children - .Where(IsLibraryMonitorEnabaled) - .OfType() - .SelectMany(f => f.PhysicalLocations) - .Distinct(StringComparer.OrdinalIgnoreCase) - .OrderBy(i => i) - .ToList(); - - foreach (var path in paths) - { - if (!ContainsParentFolder(pathsToWatch, path)) - { - pathsToWatch.Add(path); - } - } - - foreach (var path in pathsToWatch) - { - StartWatchingPath(path); - } - } - - private void StartWatching(BaseItem item) - { - if (IsLibraryMonitorEnabaled(item)) - { - StartWatchingPath(item.Path); - } - } - - /// - /// Handles the ItemRemoved event of the LibraryManager control. - /// - /// The source of the event. - /// The instance containing the event data. - void LibraryManager_ItemRemoved(object sender, ItemChangeEventArgs e) - { - if (e.Item.GetParent() is AggregateFolder) - { - StopWatchingPath(e.Item.Path); - } - } - - /// - /// Handles the ItemAdded event of the LibraryManager control. - /// - /// The source of the event. - /// The instance containing the event data. - void LibraryManager_ItemAdded(object sender, ItemChangeEventArgs e) - { - if (e.Item.GetParent() is AggregateFolder) - { - StartWatching(e.Item); - } - } - - /// - /// Examine a list of strings assumed to be file paths to see if it contains a parent of - /// the provided path. - /// - /// The LST. - /// The path. - /// true if [contains parent folder] [the specified LST]; otherwise, false. - /// path - private static bool ContainsParentFolder(IEnumerable lst, string path) - { - if (string.IsNullOrWhiteSpace(path)) - { - throw new ArgumentNullException("path"); - } - - path = path.TrimEnd(Path.DirectorySeparatorChar); - - return lst.Any(str => - { - //this should be a little quicker than examining each actual parent folder... - var compare = str.TrimEnd(Path.DirectorySeparatorChar); - - return path.Equals(compare, StringComparison.OrdinalIgnoreCase) || (path.StartsWith(compare, StringComparison.OrdinalIgnoreCase) && path[compare.Length] == Path.DirectorySeparatorChar); - }); - } - - /// - /// Starts the watching path. - /// - /// The path. - private void StartWatchingPath(string path) - { - if (!_fileSystem.DirectoryExists(path)) - { - // Seeing a crash in the mono runtime due to an exception being thrown on a different thread - Logger.Info("Skipping realtime monitor for {0} because the path does not exist", path); - return; - } - - if (_environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows) - { - if (path.StartsWith("\\\\", StringComparison.OrdinalIgnoreCase) || path.StartsWith("smb://", StringComparison.OrdinalIgnoreCase)) - { - // not supported - return; - } - } - - // Already being watched - if (_fileSystemWatchers.ContainsKey(path)) - { - return; - } - - // Creating a FileSystemWatcher over the LAN can take hundreds of milliseconds, so wrap it in a Task to do them all in parallel - Task.Run(() => - { - try - { - var newWatcher = new FileSystemWatcher(path, "*") - { - IncludeSubdirectories = true - }; - - if (_environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows) - { - newWatcher.InternalBufferSize = 32767; - } - - newWatcher.NotifyFilter = NotifyFilters.CreationTime | - NotifyFilters.DirectoryName | - NotifyFilters.FileName | - NotifyFilters.LastWrite | - NotifyFilters.Size | - NotifyFilters.Attributes; - - newWatcher.Created += watcher_Changed; - - // Seeing mono crashes on background threads we can't catch, testing if this might help - if (_environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows) - { - newWatcher.Deleted += watcher_Changed; - } - - newWatcher.Renamed += watcher_Changed; - newWatcher.Changed += watcher_Changed; - - newWatcher.Error += watcher_Error; - - if (_fileSystemWatchers.TryAdd(path, newWatcher)) - { - newWatcher.EnableRaisingEvents = true; - Logger.Info("Watching directory " + path); - } - else - { - newWatcher.Dispose(); - } - - } - catch (Exception ex) - { - Logger.ErrorException("Error watching path: {0}", ex, path); - } - }); - } - - /// - /// Stops the watching path. - /// - /// The path. - private void StopWatchingPath(string path) - { - FileSystemWatcher watcher; - - if (_fileSystemWatchers.TryGetValue(path, out watcher)) - { - DisposeWatcher(watcher); - } - } - - /// - /// Disposes the watcher. - /// - /// The watcher. - private void DisposeWatcher(FileSystemWatcher watcher) - { - try - { - using (watcher) - { - Logger.Info("Stopping directory watching for path {0}", watcher.Path); - - watcher.EnableRaisingEvents = false; - } - } - catch - { - - } - finally - { - RemoveWatcherFromList(watcher); - } - } - - /// - /// Removes the watcher from list. - /// - /// The watcher. - private void RemoveWatcherFromList(FileSystemWatcher watcher) - { - FileSystemWatcher removed; - - _fileSystemWatchers.TryRemove(watcher.Path, out removed); - } - - /// - /// Handles the Error event of the watcher control. - /// - /// The source of the event. - /// The instance containing the event data. - void watcher_Error(object sender, ErrorEventArgs e) - { - var ex = e.GetException(); - var dw = (FileSystemWatcher)sender; - - Logger.ErrorException("Error in Directory watcher for: " + dw.Path, ex); - - DisposeWatcher(dw); - } - - /// - /// Handles the Changed event of the watcher control. - /// - /// The source of the event. - /// The instance containing the event data. - void watcher_Changed(object sender, FileSystemEventArgs e) - { - try - { - //Logger.Debug("Changed detected of type " + e.ChangeType + " to " + e.FullPath); - - var path = e.FullPath; - - ReportFileSystemChanged(path); - } - catch (Exception ex) - { - Logger.ErrorException("Exception in ReportFileSystemChanged. Path: {0}", ex, e.FullPath); - } - } - - public void ReportFileSystemChanged(string path) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException("path"); - } - - var filename = Path.GetFileName(path); - - var monitorPath = !string.IsNullOrEmpty(filename) && - !_alwaysIgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase) && - !_alwaysIgnoreExtensions.Contains(Path.GetExtension(path) ?? string.Empty, StringComparer.OrdinalIgnoreCase) && - _alwaysIgnoreSubstrings.All(i => path.IndexOf(i, StringComparison.OrdinalIgnoreCase) == -1); - - // Ignore certain files - var tempIgnorePaths = _tempIgnoredPaths.Keys.ToList(); - - // If the parent of an ignored path has a change event, ignore that too - if (tempIgnorePaths.Any(i => - { - if (_fileSystem.AreEqual(i, path)) - { - Logger.Debug("Ignoring change to {0}", path); - return true; - } - - if (_fileSystem.ContainsSubPath(i, path)) - { - Logger.Debug("Ignoring change to {0}", path); - return true; - } - - // Go up a level - var parent = _fileSystem.GetDirectoryName(i); - if (!string.IsNullOrEmpty(parent)) - { - if (_fileSystem.AreEqual(parent, path)) - { - Logger.Debug("Ignoring change to {0}", path); - return true; - } - } - - return false; - - })) - { - monitorPath = false; - } - - if (monitorPath) - { - // Avoid implicitly captured closure - CreateRefresher(path); - } - } - - private void CreateRefresher(string path) - { - var parentPath = _fileSystem.GetDirectoryName(path); - - lock (_activeRefreshers) - { - var refreshers = _activeRefreshers.ToList(); - foreach (var refresher in refreshers) - { - // Path is already being refreshed - if (_fileSystem.AreEqual(path, refresher.Path)) - { - refresher.RestartTimer(); - return; - } - - // Parent folder is already being refreshed - if (_fileSystem.ContainsSubPath(refresher.Path, path)) - { - refresher.AddPath(path); - return; - } - - // New path is a parent - if (_fileSystem.ContainsSubPath(path, refresher.Path)) - { - refresher.ResetPath(path, null); - return; - } - - // They are siblings. Rebase the refresher to the parent folder. - if (string.Equals(parentPath, _fileSystem.GetDirectoryName(refresher.Path), StringComparison.Ordinal)) - { - refresher.ResetPath(parentPath, path); - return; - } - } - - var newRefresher = new FileRefresher(path, _fileSystem, ConfigurationManager, LibraryManager, TaskManager, Logger, _timerFactory, _environmentInfo, LibraryManager); - newRefresher.Completed += NewRefresher_Completed; - _activeRefreshers.Add(newRefresher); - } - } - - private void NewRefresher_Completed(object sender, EventArgs e) - { - var refresher = (FileRefresher)sender; - DisposeRefresher(refresher); - } - - /// - /// Stops this instance. - /// - public void Stop() - { - LibraryManager.ItemAdded -= LibraryManager_ItemAdded; - LibraryManager.ItemRemoved -= LibraryManager_ItemRemoved; - - foreach (var watcher in _fileSystemWatchers.Values.ToList()) - { - watcher.Created -= watcher_Changed; - watcher.Deleted -= watcher_Changed; - watcher.Renamed -= watcher_Changed; - watcher.Changed -= watcher_Changed; - - try - { - watcher.EnableRaisingEvents = false; - } - catch (InvalidOperationException) - { - // Seeing this under mono on linux sometimes - // Collection was modified; enumeration operation may not execute. - } - - watcher.Dispose(); - } - - _fileSystemWatchers.Clear(); - DisposeRefreshers(); - } - - private void DisposeRefresher(FileRefresher refresher) - { - lock (_activeRefreshers) - { - refresher.Dispose(); - _activeRefreshers.Remove(refresher); - } - } - - private void DisposeRefreshers() - { - lock (_activeRefreshers) - { - foreach (var refresher in _activeRefreshers.ToList()) - { - refresher.Dispose(); - } - _activeRefreshers.Clear(); - } - } - - private bool _disposed; - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - _disposed = true; - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - Stop(); - } - } - } - - public class LibraryMonitorStartup : IServerEntryPoint - { - private readonly ILibraryMonitor _monitor; - - public LibraryMonitorStartup(ILibraryMonitor monitor) - { - _monitor = monitor; - } - - public void Run() - { - _monitor.Start(); - } - - public void Dispose() - { - } - } -} diff --git a/Emby.Server.Core/IO/MemoryStreamProvider.cs b/Emby.Server.Core/IO/MemoryStreamProvider.cs deleted file mode 100644 index f6dd1ecbc..000000000 --- a/Emby.Server.Core/IO/MemoryStreamProvider.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.IO; -using MediaBrowser.Model.IO; -using Microsoft.IO; - -namespace Emby.Server.Core.IO -{ - public class RecyclableMemoryStreamProvider : IMemoryStreamFactory - { - readonly RecyclableMemoryStreamManager _manager = new RecyclableMemoryStreamManager(); - - public MemoryStream CreateNew() - { - return _manager.GetStream(); - } - - public MemoryStream CreateNew(int capacity) - { - return _manager.GetStream("RecyclableMemoryStream", capacity); - } - - public MemoryStream CreateNew(byte[] buffer) - { - return _manager.GetStream("RecyclableMemoryStream", buffer, 0, buffer.Length); - } - - public bool TryGetBuffer(MemoryStream stream, out byte[] buffer) - { - buffer = stream.GetBuffer(); - return true; - } - } - - public class MemoryStreamProvider : IMemoryStreamFactory - { - public MemoryStream CreateNew() - { - return new MemoryStream(); - } - - public MemoryStream CreateNew(int capacity) - { - return new MemoryStream(capacity); - } - - public MemoryStream CreateNew(byte[] buffer) - { - return new MemoryStream(buffer); - } - - public bool TryGetBuffer(MemoryStream stream, out byte[] buffer) - { - buffer = stream.GetBuffer(); - return true; - } - } -} diff --git a/Emby.Server.Core/Localization/TextLocalizer.cs b/Emby.Server.Core/Localization/TextLocalizer.cs deleted file mode 100644 index 1e8ccbbfa..000000000 --- a/Emby.Server.Core/Localization/TextLocalizer.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using Emby.Server.Implementations.Localization; - -namespace Emby.Server.Core.Localization -{ - public class TextLocalizer : ITextLocalizer - { - public string RemoveDiacritics(string text) - { - if (text == null) - { - throw new ArgumentNullException("text"); - } - - var chars = Normalize(text, NormalizationForm.FormD) - .Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) != UnicodeCategory.NonSpacingMark); - - return Normalize(String.Concat(chars), NormalizationForm.FormC); - } - - private static string Normalize(string text, NormalizationForm form, bool stripStringOnFailure = true) - { - if (stripStringOnFailure) - { - try - { - return text.Normalize(form); - } - catch (ArgumentException) - { - // will throw if input contains invalid unicode chars - // https://mnaoumov.wordpress.com/2014/06/14/stripping-invalid-characters-from-utf-16-strings/ - text = StripInvalidUnicodeCharacters(text); - return Normalize(text, form, false); - } - } - - try - { - return text.Normalize(form); - } - catch (ArgumentException) - { - // if it still fails, return the original text - return text; - } - } - - private static string StripInvalidUnicodeCharacters(string str) - { - var invalidCharactersRegex = new Regex("([\ud800-\udbff](?![\udc00-\udfff]))|((? - - - - - - - - - - diff --git a/Emby.Server.Core/packages.config b/Emby.Server.Core/packages.config deleted file mode 100644 index 6311b55eb..000000000 --- a/Emby.Server.Core/packages.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 567f139fd..702917832 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Extensions; namespace Emby.Server.Implementations.Activity { @@ -436,7 +437,7 @@ namespace Emby.Server.Implementations.Activity { Name = string.Format(_localization.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name), Type = "ScheduledTaskFailed", - Overview = string.Join(Environment.NewLine, vals.ToArray()), + Overview = string.Join(Environment.NewLine, vals.ToArray(vals.Count)), ShortOverview = runningTime, Severity = LogSeverity.Error }); diff --git a/Emby.Server.Implementations/Activity/ActivityRepository.cs b/Emby.Server.Implementations/Activity/ActivityRepository.cs index e9b6f7a40..7720f8f2f 100644 --- a/Emby.Server.Implementations/Activity/ActivityRepository.cs +++ b/Emby.Server.Implementations/Activity/ActivityRepository.cs @@ -10,6 +10,7 @@ using MediaBrowser.Model.Activity; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Querying; using SQLitePCL.pretty; +using MediaBrowser.Model.Extensions; namespace Emby.Server.Implementations.Activity { @@ -94,13 +95,13 @@ namespace Emby.Server.Implementations.Activity var whereTextWithoutPaging = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count)); if (startIndex.HasValue && startIndex.Value > 0) { var pagingWhereText = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count)); whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM ActivityLogEntries {0} ORDER BY DateCreated DESC LIMIT {1})", pagingWhereText, @@ -109,7 +110,7 @@ namespace Emby.Server.Implementations.Activity var whereText = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + " where " + string.Join(" AND ", whereClauses.ToArray(whereClauses.Count)); commandText += whereText; @@ -154,7 +155,7 @@ namespace Emby.Server.Implementations.Activity result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); } - result.Items = list.ToArray(); + result.Items = list.ToArray(list.Count); return result; }, ReadTransactionMode); diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs new file mode 100644 index 000000000..f1f24660c --- /dev/null +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -0,0 +1,1749 @@ +using Emby.Common.Implementations; +using Emby.Common.Implementations.Archiving; +using Emby.Common.Implementations.IO; +using Emby.Common.Implementations.Reflection; +using Emby.Common.Implementations.ScheduledTasks; +using Emby.Common.Implementations.Serialization; +using Emby.Common.Implementations.TextEncoding; +using Emby.Common.Implementations.Xml; +using Emby.Dlna; +using Emby.Dlna.ConnectionManager; +using Emby.Dlna.ContentDirectory; +using Emby.Dlna.Main; +using Emby.Dlna.MediaReceiverRegistrar; +using Emby.Dlna.Ssdp; +using Emby.Drawing; +using Emby.Photos; +using Emby.Server.Implementations.Activity; +using Emby.Server.Implementations.Channels; +using Emby.Server.Implementations.Collections; +using Emby.Server.Implementations.Configuration; +using Emby.Server.Implementations.Data; +using Emby.Server.Implementations.Devices; +using Emby.Server.Implementations.Dto; +using Emby.Server.Implementations.FFMpeg; +using Emby.Server.Implementations.HttpServer; +using Emby.Server.Implementations.HttpServer.Security; +using Emby.Server.Implementations.IO; +using Emby.Server.Implementations.Library; +using Emby.Server.Implementations.LiveTv; +using Emby.Server.Implementations.Localization; +using Emby.Server.Implementations.MediaEncoder; +using Emby.Server.Implementations.Migrations; +using Emby.Server.Implementations.Notifications; +using Emby.Server.Implementations.Playlists; +using Emby.Server.Implementations.Security; +using Emby.Server.Implementations.Session; +using Emby.Server.Implementations.Social; +using Emby.Server.Implementations.TV; +using Emby.Server.Implementations.Updates; +using MediaBrowser.Api; +using MediaBrowser.Common; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Events; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Net; +using MediaBrowser.Common.Plugins; +using MediaBrowser.Common.Progress; +using MediaBrowser.Common.Security; +using MediaBrowser.Common.Updates; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Channels; +using MediaBrowser.Controller.Chapters; +using MediaBrowser.Controller.Collections; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Connect; +using MediaBrowser.Controller.Devices; +using MediaBrowser.Controller.Dlna; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Controller.Net; +using MediaBrowser.Controller.Notifications; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Playlists; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Controller.Resolvers; +using MediaBrowser.Controller.Security; +using MediaBrowser.Controller.Session; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Controller.Subtitles; +using MediaBrowser.Controller.Sync; +using MediaBrowser.Controller.TV; +using MediaBrowser.LocalMetadata.Savers; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Diagnostics; +using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.Net; +using MediaBrowser.Model.News; +using MediaBrowser.Model.Reflection; +using MediaBrowser.Model.Serialization; +using MediaBrowser.Model.Services; +using MediaBrowser.Model.Social; +using MediaBrowser.Model.System; +using MediaBrowser.Model.Text; +using MediaBrowser.Model.Updates; +using MediaBrowser.Model.Xml; +using MediaBrowser.Providers.Chapters; +using MediaBrowser.Providers.Manager; +using MediaBrowser.Providers.Subtitles; +using MediaBrowser.WebDashboard.Api; +using MediaBrowser.XbmcMetadata.Providers; +using OpenSubtitlesHandler; +using ServiceStack; +using SocketHttpListener.Primitives; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; +using Emby.Server.MediaEncoding.Subtitles; +using MediaBrowser.MediaEncoding.BdInfo; +using StringExtensions = MediaBrowser.Controller.Extensions.StringExtensions; + +namespace Emby.Server.Implementations +{ + /// + /// Class CompositionRoot + /// + public abstract class ApplicationHost : BaseApplicationHost, IServerApplicationHost, IDependencyContainer + { + /// + /// Gets the server configuration manager. + /// + /// The server configuration manager. + public IServerConfigurationManager ServerConfigurationManager + { + get { return (IServerConfigurationManager)ConfigurationManager; } + } + + /// + /// Gets the configuration manager. + /// + /// IConfigurationManager. + protected override IConfigurationManager GetConfigurationManager() + { + return new ServerConfigurationManager(ApplicationPaths, LogManager, XmlSerializer, FileSystemManager); + } + + /// + /// Gets or sets the server manager. + /// + /// The server manager. + private IServerManager ServerManager { get; set; } + /// + /// Gets or sets the user manager. + /// + /// The user manager. + public IUserManager UserManager { get; set; } + /// + /// Gets or sets the library manager. + /// + /// The library manager. + internal ILibraryManager LibraryManager { get; set; } + /// + /// Gets or sets the directory watchers. + /// + /// The directory watchers. + private ILibraryMonitor LibraryMonitor { get; set; } + /// + /// Gets or sets the provider manager. + /// + /// The provider manager. + private IProviderManager ProviderManager { get; set; } + /// + /// Gets or sets the HTTP server. + /// + /// The HTTP server. + private IHttpServer HttpServer { get; set; } + private IDtoService DtoService { get; set; } + public IImageProcessor ImageProcessor { get; set; } + + /// + /// Gets or sets the media encoder. + /// + /// The media encoder. + private IMediaEncoder MediaEncoder { get; set; } + private ISubtitleEncoder SubtitleEncoder { get; set; } + + private IConnectManager ConnectManager { get; set; } + private ISessionManager SessionManager { get; set; } + + private ILiveTvManager LiveTvManager { get; set; } + + public ILocalizationManager LocalizationManager { get; set; } + + private IEncodingManager EncodingManager { get; set; } + private IChannelManager ChannelManager { get; set; } + private ISyncManager SyncManager { get; set; } + + /// + /// Gets or sets the user data repository. + /// + /// The user data repository. + private IUserDataManager UserDataManager { get; set; } + private IUserRepository UserRepository { get; set; } + internal IDisplayPreferencesRepository DisplayPreferencesRepository { get; set; } + internal IItemRepository ItemRepository { get; set; } + private INotificationsRepository NotificationsRepository { get; set; } + + private INotificationManager NotificationManager { get; set; } + private ISubtitleManager SubtitleManager { get; set; } + private IChapterManager ChapterManager { get; set; } + private IDeviceManager DeviceManager { get; set; } + + internal IUserViewManager UserViewManager { get; set; } + + private IAuthenticationRepository AuthenticationRepository { get; set; } + private ISyncRepository SyncRepository { get; set; } + private ITVSeriesManager TVSeriesManager { get; set; } + private ICollectionManager CollectionManager { get; set; } + private IMediaSourceManager MediaSourceManager { get; set; } + private IPlaylistManager PlaylistManager { get; set; } + + /// + /// Gets or sets the installation manager. + /// + /// The installation manager. + protected IInstallationManager InstallationManager { get; private set; } + /// + /// Gets the security manager. + /// + /// The security manager. + protected ISecurityManager SecurityManager { get; private set; } + + /// + /// Gets or sets the zip client. + /// + /// The zip client. + protected IZipClient ZipClient { get; private set; } + + protected IAuthService AuthService { get; private set; } + + protected readonly StartupOptions StartupOptions; + private readonly string _releaseAssetFilename; + + internal IPowerManagement PowerManagement { get; private set; } + internal IImageEncoder ImageEncoder { get; private set; } + + private readonly Action _certificateGenerator; + private readonly Func _defaultUserNameFactory; + + /// + /// Initializes a new instance of the class. + /// + public ApplicationHost(ServerApplicationPaths applicationPaths, + ILogManager logManager, + StartupOptions options, + IFileSystem fileSystem, + IPowerManagement powerManagement, + string releaseAssetFilename, + IEnvironmentInfo environmentInfo, + IImageEncoder imageEncoder, + ISystemEvents systemEvents, + IMemoryStreamFactory memoryStreamFactory, + INetworkManager networkManager, + Action certificateGenerator, + Func defaultUsernameFactory) + : base(applicationPaths, + logManager, + fileSystem, + environmentInfo, + systemEvents, + memoryStreamFactory, + networkManager) + { + StartupOptions = options; + _certificateGenerator = certificateGenerator; + _releaseAssetFilename = releaseAssetFilename; + _defaultUserNameFactory = defaultUsernameFactory; + PowerManagement = powerManagement; + + ImageEncoder = imageEncoder; + + SetBaseExceptionMessage(); + + if (environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows) + { + fileSystem.AddShortcutHandler(new LnkShortcutHandler()); + } + + fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); + } + + private Version _version; + /// + /// Gets the current application version + /// + /// The application version. + public override Version ApplicationVersion + { + get + { + return _version ?? (_version = GetAssembly(GetType()).GetName().Version); + } + } + + public virtual bool SupportsRunningAsService + { + get + { + return false; + } + } + + /// + /// Gets the name. + /// + /// The name. + public override string Name + { + get + { + return "Emby Server"; + } + } + + public virtual bool IsRunningAsService + { + get + { + return false; + } + } + + private Assembly GetAssembly(Type type) + { + return type.GetTypeInfo().Assembly; + } + + public virtual bool SupportsAutoRunAtStartup + { + get + { + return EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows; + } + } + + private void SetBaseExceptionMessage() + { + var builder = GetBaseExceptionMessage(ApplicationPaths); + + builder.Insert(0, string.Format("Version: {0}{1}", ApplicationVersion, Environment.NewLine)); + builder.Insert(0, "*** Error Report ***" + Environment.NewLine); + + LogManager.ExceptionMessagePrefix = builder.ToString(); + } + + /// + /// Runs the startup tasks. + /// + public override async Task RunStartupTasks() + { + await PerformPreInitMigrations().ConfigureAwait(false); + + await base.RunStartupTasks().ConfigureAwait(false); + + await MediaEncoder.Init().ConfigureAwait(false); + + if (string.IsNullOrWhiteSpace(MediaEncoder.EncoderPath)) + { + if (ServerConfigurationManager.Configuration.IsStartupWizardCompleted) + { + ServerConfigurationManager.Configuration.IsStartupWizardCompleted = false; + ServerConfigurationManager.SaveConfiguration(); + } + } + + Logger.Info("ServerId: {0}", SystemId); + Logger.Info("Core startup complete"); + HttpServer.GlobalResponse = null; + + PerformPostInitMigrations(); + Logger.Info("Post-init migrations complete"); + + foreach (var entryPoint in GetExports().ToList()) + { + var name = entryPoint.GetType().FullName; + Logger.Info("Starting entry point {0}", name); + var now = DateTime.UtcNow; + try + { + entryPoint.Run(); + } + catch (Exception ex) + { + Logger.ErrorException("Error in {0}", ex, name); + } + Logger.Info("Entry point completed: {0}. Duration: {1} seconds", name, (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture), "ImageInfos"); + } + Logger.Info("All entry points have started"); + + LogManager.RemoveConsoleOutput(); + } + + protected override IJsonSerializer CreateJsonSerializer() + { + try + { + // https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.IntegrationTests/Web.config#L4 + Licensing.RegisterLicense("1001-e1JlZjoxMDAxLE5hbWU6VGVzdCBCdXNpbmVzcyxUeXBlOkJ1c2luZXNzLEhhc2g6UHVNTVRPclhvT2ZIbjQ5MG5LZE1mUTd5RUMzQnBucTFEbTE3TDczVEF4QUNMT1FhNXJMOWkzVjFGL2ZkVTE3Q2pDNENqTkQyUktRWmhvUVBhYTBiekJGUUZ3ZE5aZHFDYm9hL3lydGlwUHI5K1JsaTBYbzNsUC85cjVJNHE5QVhldDN6QkE4aTlvdldrdTgyTk1relY2eis2dFFqTThYN2lmc0JveHgycFdjPSxFeHBpcnk6MjAxMy0wMS0wMX0="); + } + catch + { + // Failing under mono + } + + var result = new JsonSerializer(FileSystemManager, LogManager.GetLogger("JsonSerializer")); + + ServiceStack.Text.JsConfig.ExcludePropertyNames = new[] { "ProviderIds" }; + ServiceStack.Text.JsConfig.ExcludePropertyNames = new[] { "ProviderIds" }; + ServiceStack.Text.JsConfig.ExcludePropertyNames = new[] { "ProviderIds" }; + ServiceStack.Text.JsConfig.ExcludePropertyNames = new[] { "ProviderIds" }; + ServiceStack.Text.JsConfig.ExcludePropertyNames = new[] { "ProviderIds" }; + ServiceStack.Text.JsConfig