From 5bf1dcd5199026cb52d15892f48dbf8727b17036 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 29 Mar 2016 23:10:01 -0400 Subject: update channel view --- MediaBrowser.Server.Implementations/Library/UserViewManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index 9f6e39b46..1bba20ec5 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -121,7 +121,7 @@ namespace MediaBrowser.Server.Implementations.Library var channels = channelResult.Items; - if (!user.Configuration.DisplayChannelsInline && channels.Length > 0) + if (user.Configuration.EnableChannelView && channels.Length > 0) { list.Add(await _channelManager.GetInternalChannelFolder(cancellationToken).ConfigureAwait(false)); } -- cgit v1.2.3 From b293211628409753b8d8f47c31bbf19414440f73 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 29 Mar 2016 23:31:11 -0400 Subject: resolve missing trailers --- MediaBrowser.Controller/Entities/BaseItem.cs | 6 +++++- .../Persistence/SqliteItemRepository.cs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 903c5cfd5..bf25da2ac 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2084,7 +2084,7 @@ namespace MediaBrowser.Controller.Entities { get { - if (GetParent() is AggregateFolder || this is Channel || this is BasePluginFolder) + if (GetParent() is AggregateFolder || this is BasePluginFolder) { return true; } @@ -2094,6 +2094,10 @@ namespace MediaBrowser.Controller.Entities { return true; } + if (view != null && string.Equals(view.ViewType, CollectionType.Channels, StringComparison.OrdinalIgnoreCase)) + { + return true; + } return false; } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index af275faee..4a7235928 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; - private const int LatestSchemaVersion = 53; + private const int LatestSchemaVersion = 55; /// /// Initializes a new instance of the class. -- cgit v1.2.3 From f308a41cab09d8ee09bdc4188cbe6f7799730a2e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 30 Mar 2016 12:37:29 -0400 Subject: update cinema mode trailer selection --- MediaBrowser.Controller/Entities/Trailer.cs | 6 +++--- MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs | 7 ++++++- MediaBrowser.Server.Implementations/Library/LibraryManager.cs | 1 + .../Persistence/SqliteItemRepository.cs | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index bd7d30858..c3e24090c 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -21,11 +21,11 @@ namespace MediaBrowser.Controller.Entities Taglines = new List(); Keywords = new List(); ProductionLocations = new List(); - TrailerTypes = new List(); + TrailerTypes = new List { TrailerType.LocalTrailer }; } public List TrailerTypes { get; set; } - + public float? Metascore { get; set; } public List RemoteTrailers { get; set; } @@ -86,7 +86,7 @@ namespace MediaBrowser.Controller.Entities var info = GetItemLookupInfo(); info.IsLocalTrailer = TrailerTypes.Contains(TrailerType.LocalTrailer); - + if (!IsInMixedFolder) { info.Name = System.IO.Path.GetFileName(ContainingFolderPath); diff --git a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs index 49012c65a..9ebae5d91 100644 --- a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs +++ b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs @@ -102,10 +102,15 @@ namespace MediaBrowser.Server.Implementations.Intros if (trailerTypes.Count > 0) { + var excludeTrailerTypes = Enum.GetNames(typeof(TrailerType)) + .Select(i => (TrailerType)Enum.Parse(typeof(TrailerType), i, true)) + .Except(trailerTypes) + .ToArray(); + var trailerResult = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = new[] { typeof(Trailer).Name }, - TrailerTypes = trailerTypes.ToArray() + ExcludeTrailerTypes = excludeTrailerTypes }); candidates.AddRange(trailerResult.Select(i => new ItemWithTrailer diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 28671fb7c..ccba293a3 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -2361,6 +2361,7 @@ namespace MediaBrowser.Server.Implementations.Library } video.ExtraType = ExtraType.Trailer; + video.TrailerTypes = new List { TrailerType.LocalTrailer }; return video; diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 4a7235928..de914b773 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; - private const int LatestSchemaVersion = 55; + private const int LatestSchemaVersion = 56; /// /// Initializes a new instance of the class. -- cgit v1.2.3 From 6ebaf278886a8fac90e3dceee21b401c5d7ddb1c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 30 Mar 2016 15:08:52 -0400 Subject: update translations --- MediaBrowser.Server.Implementations/Localization/Core/hu.json | 6 +++--- MediaBrowser.Server.Implementations/Localization/Core/sv.json | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Localization/Core/hu.json b/MediaBrowser.Server.Implementations/Localization/Core/hu.json index b175ae6c1..d098a893c 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/hu.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/hu.json @@ -33,10 +33,10 @@ "CategoryPlugin": "B\u0151v\u00edtm\u00e9ny", "NotificationOptionPluginError": "B\u0151v\u00edtm\u00e9ny hiba", "NotificationOptionApplicationUpdateAvailable": "Friss\u00edt\u00e9s el\u00e9rhet\u0151", - "NotificationOptionApplicationUpdateInstalled": "Friss\u00edt\u00e9s telep\u00edtve", - "NotificationOptionPluginUpdateInstalled": "B\u0151v\u00edtm\u00e9ny friss\u00edtve", + "NotificationOptionApplicationUpdateInstalled": "Program friss\u00edt\u00e9s telep\u00edtve", + "NotificationOptionPluginUpdateInstalled": "B\u0151v\u00edtm\u00e9ny friss\u00edt\u00e9s telep\u00edtve", "NotificationOptionPluginInstalled": "B\u0151v\u00edtm\u00e9ny telep\u00edtve", - "NotificationOptionPluginUninstalled": "B\u0151v\u00edtm\u00e9ny t\u00f6r\u00f6lve", + "NotificationOptionPluginUninstalled": "B\u0151v\u00edtm\u00e9ny elt\u00e1vol\u00edtva", "NotificationOptionVideoPlayback": "Vide\u00f3 elind\u00edtva", "NotificationOptionAudioPlayback": "Zene elind\u00edtva", "NotificationOptionGamePlayback": "J\u00e1t\u00e9k elind\u00edtva", diff --git a/MediaBrowser.Server.Implementations/Localization/Core/sv.json b/MediaBrowser.Server.Implementations/Localization/Core/sv.json index f52f656d4..eca16e2b4 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/sv.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/sv.json @@ -24,9 +24,9 @@ "LabelApiDocumentation": "Api Dokumentation", "LabelDeveloperResources": "Resurser f\u00f6r utvecklare", "LabelBrowseLibrary": "Bl\u00e4ddra i biblioteket", - "LabelConfigureServer": "Configure Emby", + "LabelConfigureServer": "Konfigurera Emby", "LabelRestartServer": "Starta om servern", - "CategorySync": "Sync", + "CategorySync": "Synka", "CategoryUser": "Anv\u00e4ndare", "CategorySystem": "System", "CategoryApplication": "App", -- cgit v1.2.3 From 12a1414d73c0671b0b502352b524aac66bf9c4c6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 30 Mar 2016 15:43:37 -0400 Subject: remove unneeded wait for exit --- MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs | 3 --- 1 file changed, 3 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 69cc8ebf7..442f151dd 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -175,9 +175,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV //process.Kill(); _process.StandardInput.WriteLine("q"); - - // Need to wait because killing is asynchronous - _process.WaitForExit(5000); } catch (Exception ex) { -- cgit v1.2.3 From d5b7ed325e5930b30fd8ecf54088d1bccdd2e8ba Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 14:46:03 -0400 Subject: switch from Mono.Nat to Open.Nat --- .../EntryPoints/ExternalPortForwarding.cs | 221 ++++----------------- .../MediaBrowser.Server.Implementations.csproj | 4 + .../packages.config | 1 + 3 files changed, 49 insertions(+), 177 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 95763c43f..c0c626438 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -3,7 +3,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Logging; -using Mono.Nat; using System; using System.Collections.Generic; using System.Globalization; @@ -11,6 +10,9 @@ using System.IO; using System.Net; using System.Text; using MediaBrowser.Common.Threading; +using Open.Nat; +using System.Threading; +using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.EntryPoints { @@ -20,9 +22,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private readonly ILogger _logger; private readonly IServerConfigurationManager _config; private readonly ISsdpHandler _ssdp; - - private PeriodicTimer _timer; - private bool _isStarted; + private CancellationTokenSource _currentCancellationTokenSource; + private TimeSpan _interval = TimeSpan.FromHours(1); public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, ISsdpHandler ssdp) { @@ -32,223 +33,89 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _ssdp = ssdp; } - 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) - { - _config.ConfigurationUpdated -= _config_ConfigurationUpdated; - - if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase)) - { - if (_isStarted) - { - DisposeNat(); - } - - Run(); - } - } - public void Run() { //NatUtility.Logger = new LogWriter(_logger); if (_config.Configuration.EnableUPnP) { - Start(); + Discover(); } - - _config.ConfigurationUpdated -= _config_ConfigurationUpdated; - _config.ConfigurationUpdated += _config_ConfigurationUpdated; } - private void Start() + private async void Discover() { - _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; - - - // it is hard to say what one should do when an unhandled exception is raised - // because there isn't anything one can do about it. Probably save a log or ignored it. - NatUtility.UnhandledException += NatUtility_UnhandledException; - NatUtility.StartDiscovery(); - - _timer = new PeriodicTimer(s => _createdRules = new List(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); - - _ssdp.MessageReceived += _ssdp_MessageReceived; + var discoverer = new NatDiscoverer(); - _lastConfigIdentifier = GetConfigIdentifier(); + var cancellationTokenSource = new CancellationTokenSource(10000); + _currentCancellationTokenSource = cancellationTokenSource; - _isStarted = true; - } - - void _ssdp_MessageReceived(object sender, SsdpMessageEventArgs e) - { - var endpoint = e.EndPoint as IPEndPoint; - - if (endpoint != null && e.LocalEndPoint != null) + try { - NatUtility.Handle(e.LocalEndPoint.Address, e.Message, endpoint, NatProtocol.Upnp); - } - } - - void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e) - { - var ex = e.ExceptionObject as Exception; + var device = await discoverer.DiscoverDeviceAsync(PortMapper.Upnp, cancellationTokenSource).ConfigureAwait(false); - if (ex == null) - { - //_logger.Error("Unidentified error reported by Mono.Nat"); + await CreateRules(device).ConfigureAwait(false); } - else + catch (OperationCanceledException) { - // Seeing some blank exceptions coming through here - //_logger.ErrorException("Error reported by Mono.Nat: ", ex); - } - } - - void NatUtility_DeviceFound(object sender, DeviceEventArgs e) - { - try - { - var device = e.Device; - _logger.Debug("NAT device found: {0}", device.LocalAddress.ToString()); - CreateRules(device); } catch (Exception ex) { - // 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); + _logger.ErrorException("Error discovering NAT devices", ex); } - } - - private List _createdRules = new List(); - private void CreateRules(INatDevice device) - { - // 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(); - - if (!_createdRules.Contains(address)) + finally { - _createdRules.Add(address); - - CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort); - CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort); + _currentCancellationTokenSource = null; } - } - private void CreatePortMap(INatDevice device, int privatePort, int publicPort) - { - _logger.Debug("Creating port map on port {0}", privatePort); - device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort) + if (_config.Configuration.EnableUPnP) { - Description = _appHost.Name - }); + await Task.Delay(_interval).ConfigureAwait(false); + Discover(); + } } - // As I said before, this method will be never invoked. You can remove it. - void NatUtility_DeviceLost(object sender, DeviceEventArgs e) + private async Task CreateRules(NatDevice device) { - var device = e.Device; - _logger.Debug("NAT device lost: {0}", device.LocalAddress.ToString()); - } + // 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 - public void Dispose() - { - DisposeNat(); + await CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort).ConfigureAwait(false); + await CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort).ConfigureAwait(false); } - private void DisposeNat() + private async Task CreatePortMap(NatDevice device, int privatePort, int publicPort) { - _logger.Debug("Stopping NAT discovery"); - - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } - - _ssdp.MessageReceived -= _ssdp_MessageReceived; + _logger.Debug("Creating port map on port {0}", privatePort); try { - // This is not a significant improvement - NatUtility.StopDiscovery(); - NatUtility.DeviceFound -= NatUtility_DeviceFound; - NatUtility.DeviceLost -= NatUtility_DeviceLost; - NatUtility.UnhandledException -= NatUtility_UnhandledException; + await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, privatePort, publicPort, _appHost.Name)).ConfigureAwait(false); } - // 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; + _logger.ErrorException("Error creating port map", ex); } } - private class LogWriter : TextWriter + public void Dispose() { - private readonly ILogger _logger; - - public LogWriter(ILogger logger) - { - _logger = logger; - } - - public override Encoding Encoding - { - get { return Encoding.UTF8; } - } - - public override void WriteLine(string format, params object[] arg) - { - _logger.Debug(format, arg); - } + DisposeNat(); + } - public override void WriteLine(string value) + private void DisposeNat() + { + if (_currentCancellationTokenSource != null) { - _logger.Debug(value); + try + { + _currentCancellationTokenSource.Cancel(); + } + catch (Exception ex) + { + _logger.ErrorException("Error calling _currentCancellationTokenSource.Cancel", ex); + } } } } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 97f090ab2..84c1cae54 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -62,6 +62,10 @@ ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll + + ..\packages\Open.NAT.2.0.15.0\lib\net45\Open.Nat.dll + True + ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 66aede029..814a67643 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -7,6 +7,7 @@ + \ No newline at end of file -- cgit v1.2.3 From e13fcb3cd42b67374621d7e02961e4bd335a235f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 15:22:07 -0400 Subject: update sat/ip --- .../EntryPoints/ExternalPortForwarding.cs | 18 ++- .../LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs | 170 +++++++++------------ .../MediaBrowser.Server.Implementations.csproj | 1 + 3 files changed, 83 insertions(+), 106 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index c0c626438..a7e5396eb 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -31,20 +31,26 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _appHost = appHost; _config = config; _ssdp = ssdp; + + _config.ConfigurationUpdated += _config_ConfigurationUpdated; } - public void Run() + private void _config_ConfigurationUpdated(object sender, EventArgs e) { - //NatUtility.Logger = new LogWriter(_logger); + } - if (_config.Configuration.EnableUPnP) - { - Discover(); - } + public void Run() + { + Discover(); } private async void Discover() { + if (!_config.Configuration.EnableUPnP) + { + return; + } + var discoverer = new NatDiscoverer(); var cancellationTokenSource = new CancellationTokenSource(10000); diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs index da1894bb7..413ce4549 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs @@ -15,6 +15,7 @@ using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Extensions; +using System.Xml.Linq; namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp { @@ -171,58 +172,87 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp public async Task GetInfo(string url, CancellationToken cancellationToken) { + Uri locationUri = new Uri(url); + string devicetype = ""; + string friendlyname = ""; + string uniquedevicename = ""; + string manufacturer = ""; + string manufacturerurl = ""; + string modelname = ""; + string modeldescription = ""; + string modelnumber = ""; + string modelurl = ""; + string serialnumber = ""; + string presentationurl = ""; + string capabilities = ""; + string m3u = ""; + var document = XDocument.Load(locationUri.AbsoluteUri); + var xnm = new XmlNamespaceManager(new NameTable()); + XNamespace n1 = "urn:ses-com:satip"; + XNamespace n0 = "urn:schemas-upnp-org:device-1-0"; + xnm.AddNamespace("root", n0.NamespaceName); + xnm.AddNamespace("satip:", n1.NamespaceName); + if (document.Root != null) + { + var deviceElement = document.Root.Element(n0 + "device"); + if (deviceElement != null) + { + var devicetypeElement = deviceElement.Element(n0 + "deviceType"); + if (devicetypeElement != null) + devicetype = devicetypeElement.Value; + var friendlynameElement = deviceElement.Element(n0 + "friendlyName"); + if (friendlynameElement != null) + friendlyname = friendlynameElement.Value; + var manufactureElement = deviceElement.Element(n0 + "manufacturer"); + if (manufactureElement != null) + manufacturer = manufactureElement.Value; + var manufactureurlElement = deviceElement.Element(n0 + "manufacturerURL"); + if (manufactureurlElement != null) + manufacturerurl = manufactureurlElement.Value; + var modeldescriptionElement = deviceElement.Element(n0 + "modelDescription"); + if (modeldescriptionElement != null) + modeldescription = modeldescriptionElement.Value; + var modelnameElement = deviceElement.Element(n0 + "modelName"); + if (modelnameElement != null) + modelname = modelnameElement.Value; + var modelnumberElement = deviceElement.Element(n0 + "modelNumber"); + if (modelnumberElement != null) + modelnumber = modelnumberElement.Value; + var modelurlElement = deviceElement.Element(n0 + "modelURL"); + if (modelurlElement != null) + modelurl = modelurlElement.Value; + var serialnumberElement = deviceElement.Element(n0 + "serialNumber"); + if (serialnumberElement != null) + serialnumber = serialnumberElement.Value; + var uniquedevicenameElement = deviceElement.Element(n0 + "UDN"); + if (uniquedevicenameElement != null) uniquedevicename = uniquedevicenameElement.Value; + var presentationUrlElement = deviceElement.Element(n0 + "presentationURL"); + if (presentationUrlElement != null) presentationurl = presentationUrlElement.Value; + var capabilitiesElement = deviceElement.Element(n1 + "X_SATIPCAP"); + if (capabilitiesElement != null) capabilities = capabilitiesElement.Value; + var m3uElement = deviceElement.Element(n1 + "X_SATIPM3U"); + if (m3uElement != null) m3u = m3uElement.Value; + } + } + + var result = new SatIpTunerHostInfo { Url = url, + Id = uniquedevicename, IsEnabled = true, Type = SatIpHost.DeviceType, Tuners = 1, - TunersAvailable = 1 + TunersAvailable = 1, + M3UUrl = m3u }; - using (var stream = await _httpClient.Get(url, cancellationToken).ConfigureAwait(false)) - { - using (var streamReader = new StreamReader(stream)) - { - // Use XmlReader for best performance - using (var reader = XmlReader.Create(streamReader)) - { - reader.MoveToContent(); - - // Loop through each element - while (reader.Read()) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "device": - using (var subtree = reader.ReadSubtree()) - { - FillFromDeviceNode(result, subtree); - } - break; - default: - reader.Skip(); - break; - } - } - } - } - } - } - - if (string.IsNullOrWhiteSpace(result.DeviceId)) + result.FriendlyName = friendlyname; + if (string.IsNullOrWhiteSpace(result.Id)) { throw new NotImplementedException(); } - // Device hasn't implemented an m3u list - if (string.IsNullOrWhiteSpace(result.M3UUrl)) - { - result.IsEnabled = false; - } - else if (!result.M3UUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { var fullM3uUrl = url.Substring(0, url.LastIndexOf('/')); @@ -233,66 +263,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp return result; } - - private void FillFromDeviceNode(SatIpTunerHostInfo info, XmlReader reader) - { - reader.MoveToContent(); - - while (reader.Read()) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.LocalName) - { - case "UDN": - { - info.DeviceId = reader.ReadElementContentAsString(); - break; - } - - case "friendlyName": - { - info.FriendlyName = reader.ReadElementContentAsString(); - break; - } - - case "satip:X_SATIPCAP": - case "X_SATIPCAP": - { - // DVBS2-2 - var value = reader.ReadElementContentAsString() ?? string.Empty; - var parts = value.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries); - if (parts.Length == 2) - { - int intValue; - if (int.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out intValue)) - { - info.TunersAvailable = intValue; - } - - if (int.TryParse(parts[0].Substring(parts[0].Length - 1), NumberStyles.Any, CultureInfo.InvariantCulture, out intValue)) - { - info.Tuners = intValue; - } - } - break; - } - - case "satip:X_SATIPM3U": - case "X_SATIPM3U": - { - // /channellist.lua?select=m3u - info.M3UUrl = reader.ReadElementContentAsString(); - break; - } - - default: - reader.Skip(); - break; - } - } - } - } } public class SatIpTunerHostInfo : TunerHostInfo diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 84c1cae54..14d275505 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -103,6 +103,7 @@ ..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll + ..\ThirdParty\UniversalDetector\UniversalDetector.dll -- cgit v1.2.3 From 54de1b744b996683fe9209c8ebbd2316290e9eb0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 15:32:26 -0400 Subject: stub out sat channel scan --- MediaBrowser.Api/LiveTv/LiveTvService.cs | 16 +++++++++++++++- MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 2 ++ .../LiveTv/LiveTvManager.cs | 7 +++++++ .../LiveTv/TunerHosts/SatIp/ChannelScan.cs | 20 ++++++++++++++++++++ .../MediaBrowser.Server.Implementations.csproj | 1 + 5 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 5b7bc78a8..ebcf8fbea 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -482,7 +482,14 @@ namespace MediaBrowser.Api.LiveTv [Authenticated(AllowBeforeStartupWizard = true)] public class GetSatIniMappings : IReturn> { - + + } + + [Route("/LiveTv/TunerHosts/Satip/ChannelScan", "GET", Summary = "Scans for available channels")] + [Authenticated(AllowBeforeStartupWizard = true)] + public class GetSatChannnelScanResult : TunerHostInfo + { + } public class LiveTvService : BaseApiService @@ -504,6 +511,13 @@ namespace MediaBrowser.Api.LiveTv _dtoService = dtoService; } + public async Task Get(GetSatChannnelScanResult request) + { + var result = await _liveTvManager.GetSatChannelScanResult(request, CancellationToken.None).ConfigureAwait(false); + + return ToOptimizedResult(result); + } + public async Task Get(GetLiveTvRegistrationInfo request) { var result = await _liveTvManager.GetRegistrationInfo(request.ChannelId, request.ProgramId, request.Feature).ConfigureAwait(false); diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index 56b7a307a..a4bd32fff 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -383,5 +383,7 @@ namespace MediaBrowser.Controller.LiveTv /// /// List<NameValuePair>. List GetSatIniMappings(); + + Task> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 3849f44ab..87c2e8394 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -2480,5 +2480,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv } } } + + public async Task> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken) + { + var result = await new TunerHosts.SatIp.ChannelScan().Scan(info, cancellationToken).ConfigureAwait(false); + + return result.Select(i => new ChannelInfo()).ToList(); + } } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs new file mode 100644 index 000000000..2277f8f63 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Model.LiveTv; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp +{ + public class ChannelScan + { + public async Task> Scan(TunerHostInfo info, CancellationToken cancellationToken) + { + return new List(); + } + } + + public class SatChannel + { + // TODO: Add properties + } +} diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 14d275505..b5ec4649e 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -247,6 +247,7 @@ + -- cgit v1.2.3 From edd9ad6d63aaa320e97cd48b75ac544ed7c8b361 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 16:01:27 -0400 Subject: add rtsp classes --- .../LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs | 88 ++++++++ .../LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs | 141 ++++++++++++ .../LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs | 150 ++++++++++++ .../LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs | 251 +++++++++++++++++++++ .../LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs | 1 - .../MediaBrowser.Server.Implementations.csproj | 4 + 6 files changed, 634 insertions(+), 1 deletion(-) create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs new file mode 100644 index 000000000..fae7c4bfc --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs @@ -0,0 +1,88 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ + +using System.Collections.Generic; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +{ + /// + /// Standard RTSP request methods. + /// + public sealed class RtspMethod + { + public override int GetHashCode() + { + return (_name != null ? _name.GetHashCode() : 0); + } + + private readonly string _name; + private static readonly IDictionary _values = new Dictionary(); + + public static readonly RtspMethod Describe = new RtspMethod("DESCRIBE"); + public static readonly RtspMethod Announce = new RtspMethod("ANNOUNCE"); + public static readonly RtspMethod GetParameter = new RtspMethod("GET_PARAMETER"); + public static readonly RtspMethod Options = new RtspMethod("OPTIONS"); + public static readonly RtspMethod Pause = new RtspMethod("PAUSE"); + public static readonly RtspMethod Play = new RtspMethod("PLAY"); + public static readonly RtspMethod Record = new RtspMethod("RECORD"); + public static readonly RtspMethod Redirect = new RtspMethod("REDIRECT"); + public static readonly RtspMethod Setup = new RtspMethod("SETUP"); + public static readonly RtspMethod SetParameter = new RtspMethod("SET_PARAMETER"); + public static readonly RtspMethod Teardown = new RtspMethod("TEARDOWN"); + + private RtspMethod(string name) + { + _name = name; + _values.Add(name, this); + } + + public override string ToString() + { + return _name; + } + + public override bool Equals(object obj) + { + var method = obj as RtspMethod; + if (method != null && this == method) + { + return true; + } + return false; + } + + public static ICollection Values + { + get { return _values.Values; } + } + + public static explicit operator RtspMethod(string name) + { + RtspMethod value; + if (!_values.TryGetValue(name, out value)) + { + return null; + } + return value; + } + + public static implicit operator string(RtspMethod method) + { + return method._name; + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs new file mode 100644 index 000000000..d8462b223 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs @@ -0,0 +1,141 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ + +using System.Collections.Generic; +using System.Text; + + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +{ + /// + /// A simple class that can be used to serialise RTSP requests. + /// + public class RtspRequest + { + private readonly RtspMethod _method; + private readonly string _uri; + private readonly int _majorVersion; + private readonly int _minorVersion; + private IDictionary _headers = new Dictionary(); + private string _body = string.Empty; + + /// + /// Initialise a new instance of the class. + /// + /// The request method. + /// The request URI + /// The major version number. + /// The minor version number. + public RtspRequest(RtspMethod method, string uri, int majorVersion, int minorVersion) + { + _method = method; + _uri = uri; + _majorVersion = majorVersion; + _minorVersion = minorVersion; + } + + /// + /// Get the request method. + /// + public RtspMethod Method + { + get + { + return _method; + } + } + + /// + /// Get the request URI. + /// + public string Uri + { + get + { + return _uri; + } + } + + /// + /// Get the request major version number. + /// + public int MajorVersion + { + get + { + return _majorVersion; + } + } + + /// + /// Get the request minor version number. + /// + public int MinorVersion + { + get + { + return _minorVersion; + } + } + + /// + /// Get or set the request headers. + /// + public IDictionary Headers + { + get + { + return _headers; + } + set + { + _headers = value; + } + } + + /// + /// Get or set the request body. + /// + public string Body + { + get + { + return _body; + } + set + { + _body = value; + } + } + + /// + /// Serialise this request. + /// + /// raw request bytes + public byte[] Serialise() + { + var request = new StringBuilder(); + request.AppendFormat("{0} {1} RTSP/{2}.{3}\r\n", _method, _uri, _majorVersion, _minorVersion); + foreach (var header in _headers) + { + request.AppendFormat("{0}: {1}\r\n", header.Key, header.Value); + } + request.AppendFormat("\r\n{0}", _body); + return Encoding.UTF8.GetBytes(request.ToString()); + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs new file mode 100644 index 000000000..0bf80012d --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs @@ -0,0 +1,150 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +{ + /// + /// A simple class that can be used to deserialise RTSP responses. + /// + public class RtspResponse + { + private static readonly Regex RegexStatusLine = new Regex(@"RTSP/(\d+)\.(\d+)\s+(\d+)\s+([^.]+?)\r\n(.*)", RegexOptions.Singleline); + + private int _majorVersion = 1; + private int _minorVersion; + private RtspStatusCode _statusCode; + private string _reasonPhrase; + private IDictionary _headers; + private string _body; + + /// + /// Initialise a new instance of the class. + /// + private RtspResponse() + { + } + + /// + /// Get the response major version number. + /// + public int MajorVersion + { + get + { + return _majorVersion; + } + } + + /// + /// Get the response minor version number. + /// + public int MinorVersion + { + get + { + return _minorVersion; + } + } + + /// + /// Get the response status code. + /// + public RtspStatusCode StatusCode + { + get + { + return _statusCode; + } + } + + /// + /// Get the response reason phrase. + /// + public string ReasonPhrase + { + get + { + return _reasonPhrase; + } + } + + /// + /// Get the response headers. + /// + public IDictionary Headers + { + get + { + return _headers; + } + } + + /// + /// Get the response body. + /// + public string Body + { + get + { + return _body; + } + set + { + _body = value; + } + } + + /// + /// Deserialise/parse an RTSP response. + /// + /// The raw response bytes. + /// The number of valid bytes in the response. + /// a response object + public static RtspResponse Deserialise(byte[] responseBytes, int responseByteCount) + { + var response = new RtspResponse(); + var responseString = Encoding.UTF8.GetString(responseBytes, 0, responseByteCount); + + var m = RegexStatusLine.Match(responseString); + if (m.Success) + { + response._majorVersion = int.Parse(m.Groups[1].Captures[0].Value); + response._minorVersion = int.Parse(m.Groups[2].Captures[0].Value); + response._statusCode = (RtspStatusCode)int.Parse(m.Groups[3].Captures[0].Value); + response._reasonPhrase = m.Groups[4].Captures[0].Value; + responseString = m.Groups[5].Captures[0].Value; + } + + var sections = responseString.Split(new[] { "\r\n\r\n" }, StringSplitOptions.None); + response._body = sections[1]; + var headers = sections[0].Split(new[] { "\r\n" }, StringSplitOptions.None); + response._headers = new Dictionary(); + foreach (var headerInfo in headers.Select(header => header.Split(':'))) + { + response._headers.Add(headerInfo[0], headerInfo[1].Trim()); + } + return response; + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs new file mode 100644 index 000000000..8786314ed --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs @@ -0,0 +1,251 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ + +using System.ComponentModel; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +{ + /// + /// Standard RTSP status codes. + /// + public enum RtspStatusCode + { + /// + /// 100 continue + /// + Continue = 100, + + /// + /// 200 OK + /// + [Description("Okay")] + Ok = 200, + /// + /// 201 created + /// + Created = 201, + + /// + /// 250 low on storage space + /// + [Description("Low On Storage Space")] + LowOnStorageSpace = 250, + + /// + /// 300 multiple choices + /// + [Description("Multiple Choices")] + MultipleChoices = 300, + /// + /// 301 moved permanently + /// + [Description("Moved Permanently")] + MovedPermanently = 301, + /// + /// 302 moved temporarily + /// + [Description("Moved Temporarily")] + MovedTemporarily = 302, + /// + /// 303 see other + /// + [Description("See Other")] + SeeOther = 303, + /// + /// 304 not modified + /// + [Description("Not Modified")] + NotModified = 304, + /// + /// 305 use proxy + /// + [Description("Use Proxy")] + UseProxy = 305, + + /// + /// 400 bad request + /// + [Description("Bad Request")] + BadRequest = 400, + /// + /// 401 unauthorised + /// + Unauthorised = 401, + /// + /// 402 payment required + /// + [Description("Payment Required")] + PaymentRequired = 402, + /// + /// 403 forbidden + /// + Forbidden = 403, + /// + /// 404 not found + /// + [Description("Not Found")] + NotFound = 404, + /// + /// 405 method not allowed + /// + [Description("Method Not Allowed")] + MethodNotAllowed = 405, + /// + /// 406 not acceptable + /// + [Description("Not Acceptable")] + NotAcceptable = 406, + /// + /// 407 proxy authentication required + /// + [Description("Proxy Authentication Required")] + ProxyAuthenticationRequred = 407, + /// + /// 408 request time-out + /// + [Description("Request Time-Out")] + RequestTimeOut = 408, + + /// + /// 410 gone + /// + Gone = 410, + /// + /// 411 length required + /// + [Description("Length Required")] + LengthRequired = 411, + /// + /// 412 precondition failed + /// + [Description("Precondition Failed")] + PreconditionFailed = 412, + /// + /// 413 request entity too large + /// + [Description("Request Entity Too Large")] + RequestEntityTooLarge = 413, + /// + /// 414 request URI too large + /// + [Description("Request URI Too Large")] + RequestUriTooLarge = 414, + /// + /// 415 unsupported media type + /// + [Description("Unsupported Media Type")] + UnsupportedMediaType = 415, + + /// + /// 451 parameter not understood + /// + [Description("Parameter Not Understood")] + ParameterNotUnderstood = 451, + /// + /// 452 conference not found + /// + [Description("Conference Not Found")] + ConferenceNotFound = 452, + /// + /// 453 not enough bandwidth + /// + [Description("Not Enough Bandwidth")] + NotEnoughBandwidth = 453, + /// + /// 454 session not found + /// + [Description("Session Not Found")] + SessionNotFound = 454, + /// + /// 455 method not valid in this state + /// + [Description("Method Not Valid In This State")] + MethodNotValidInThisState = 455, + /// + /// 456 header field not valid for this resource + /// + [Description("Header Field Not Valid For This Resource")] + HeaderFieldNotValidForThisResource = 456, + /// + /// 457 invalid range + /// + [Description("Invalid Range")] + InvalidRange = 457, + /// + /// 458 parameter is read-only + /// + [Description("Parameter Is Read-Only")] + ParameterIsReadOnly = 458, + /// + /// 459 aggregate operation not allowed + /// + [Description("Aggregate Operation Not Allowed")] + AggregateOperationNotAllowed = 459, + /// + /// 460 only aggregate operation allowed + /// + [Description("Only Aggregate Operation Allowed")] + OnlyAggregateOperationAllowed = 460, + /// + /// 461 unsupported transport + /// + [Description("Unsupported Transport")] + UnsupportedTransport = 461, + /// + /// 462 destination unreachable + /// + [Description("Destination Unreachable")] + DestinationUnreachable = 462, + + /// + /// 500 internal server error + /// + [Description("Internal Server Error")] + InternalServerError = 500, + /// + /// 501 not implemented + /// + [Description("Not Implemented")] + NotImplemented = 501, + /// + /// 502 bad gateway + /// + [Description("Bad Gateway")] + BadGateway = 502, + /// + /// 503 service unavailable + /// + [Description("Service Unavailable")] + ServiceUnavailable = 503, + /// + /// 504 gateway time-out + /// + [Description("Gateway Time-Out")] + GatewayTimeOut = 504, + /// + /// 505 RTSP version not supported + /// + [Description("RTSP Version Not Supported")] + RtspVersionNotSupported = 505, + + /// + /// 551 option not supported + /// + [Description("Option Not Supported")] + OptionNotSupported = 551 + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs index 413ce4549..d0a55966f 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs @@ -235,7 +235,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp } } - var result = new SatIpTunerHostInfo { Url = url, diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index b5ec4649e..02f7596e0 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -248,6 +248,10 @@ + + + + -- cgit v1.2.3 From fa841e86104cb05f59b4caec686b69dba9284084 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 16:04:07 -0400 Subject: add RtspSession --- .../LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs | 681 +++++++++++++++++++++ .../MediaBrowser.Server.Implementations.csproj | 1 + 2 files changed, 682 insertions(+) create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs new file mode 100644 index 000000000..e76fb7175 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs @@ -0,0 +1,681 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Net; +using System.Net.NetworkInformation; +using System.Net.Sockets; +using System.Text.RegularExpressions; +using MediaBrowser.Model.Logging; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +{ + public class RtspSession : IDisposable + { + #region Private Fields + private static readonly Regex RegexRtspSessionHeader = new Regex(@"\s*([^\s;]+)(;timeout=(\d+))?"); + private const int DefaultRtspSessionTimeout = 30; // unit = s + private static readonly Regex RegexDescribeResponseSignalInfo = new Regex(@";tuner=\d+,(\d+),(\d+),(\d+),", RegexOptions.Singleline | RegexOptions.IgnoreCase); + private string _address; + private string _rtspSessionId; + + public string RtspSessionId + { + get { return _rtspSessionId; } + set { _rtspSessionId = value; } + } + private int _rtspSessionTimeToLive = 0; + private string _rtspStreamId; + private int _clientRtpPort; + private int _clientRtcpPort; + private int _serverRtpPort; + private int _serverRtcpPort; + private int _rtpPort; + private int _rtcpPort; + private string _rtspStreamUrl; + private string _destination; + private string _source; + private string _transport; + private int _signalLevel; + private int _signalQuality; + private Socket _rtspSocket; + private int _rtspSequenceNum = 1; + private bool _disposed = false; + private ILogger _logger; + #endregion + + #region Constructor + + public RtspSession(string address, ILogger logger) + { + _address = address; + _logger = logger; + } + ~RtspSession() + { + Dispose(false); + } + #endregion + + #region Properties + + #region Rtsp + + public string RtspStreamId + { + get { return _rtspStreamId; } + set { if (_rtspStreamId != value) { _rtspStreamId = value; OnPropertyChanged("RtspStreamId"); } } + } + public string RtspStreamUrl + { + get { return _rtspStreamUrl; } + set { if (_rtspStreamUrl != value) { _rtspStreamUrl = value; OnPropertyChanged("RtspStreamUrl"); } } + } + + public int RtspSessionTimeToLive + { + get + { + if (_rtspSessionTimeToLive == 0) + _rtspSessionTimeToLive = DefaultRtspSessionTimeout; + return _rtspSessionTimeToLive * 1000 - 20; + } + set { if (_rtspSessionTimeToLive != value) { _rtspSessionTimeToLive = value; OnPropertyChanged("RtspSessionTimeToLive"); } } + } + + #endregion + + #region Rtp Rtcp + + /// + /// The LocalEndPoint Address + /// + public string Destination + { + get + { + if (string.IsNullOrEmpty(_destination)) + { + var result = ""; + var host = Dns.GetHostName(); + var hostentry = Dns.GetHostEntry(host); + foreach (var ip in hostentry.AddressList.Where(ip => ip.AddressFamily == AddressFamily.InterNetwork)) + { + result = ip.ToString(); + } + + _destination = result; + } + return _destination; + } + set + { + if (_destination != value) + { + _destination = value; + OnPropertyChanged("Destination"); + } + } + } + + /// + /// The RemoteEndPoint Address + /// + public string Source + { + get { return _source; } + set + { + if (_source != value) + { + _source = value; + OnPropertyChanged("Source"); + } + } + } + + /// + /// The Media Data Delivery RemoteEndPoint Port if we use Unicast + /// + public int ServerRtpPort + { + get + { + return _serverRtpPort; + } + set { if (_serverRtpPort != value) { _serverRtpPort = value; OnPropertyChanged("ServerRtpPort"); } } + } + + /// + /// The Media Metadata Delivery RemoteEndPoint Port if we use Unicast + /// + public int ServerRtcpPort + { + get { return _serverRtcpPort; } + set { if (_serverRtcpPort != value) { _serverRtcpPort = value; OnPropertyChanged("ServerRtcpPort"); } } + } + + /// + /// The Media Data Delivery LocalEndPoint Port if we use Unicast + /// + public int ClientRtpPort + { + get { return _clientRtpPort; } + set { if (_clientRtpPort != value) { _clientRtpPort = value; OnPropertyChanged("ClientRtpPort"); } } + } + + /// + /// The Media Metadata Delivery LocalEndPoint Port if we use Unicast + /// + public int ClientRtcpPort + { + get { return _clientRtcpPort; } + set { if (_clientRtcpPort != value) { _clientRtcpPort = value; OnPropertyChanged("ClientRtcpPort"); } } + } + + /// + /// The Media Data Delivery RemoteEndPoint Port if we use Multicast + /// + public int RtpPort + { + get { return _rtpPort; } + set { if (_rtpPort != value) { _rtpPort = value; OnPropertyChanged("RtpPort"); } } + } + + /// + /// The Media Meta Delivery RemoteEndPoint Port if we use Multicast + /// + public int RtcpPort + { + get { return _rtcpPort; } + set { if (_rtcpPort != value) { _rtcpPort = value; OnPropertyChanged("RtcpPort"); } } + } + + #endregion + + public string Transport + { + get + { + if (string.IsNullOrEmpty(_transport)) + { + _transport = "unicast"; + } + return _transport; + } + set + { + if (_transport != value) + { + _transport = value; + OnPropertyChanged("Transport"); + } + } + } + public int SignalLevel + { + get { return _signalLevel; } + set { if (_signalLevel != value) { _signalLevel = value; OnPropertyChanged("SignalLevel"); } } + } + public int SignalQuality + { + get { return _signalQuality; } + set { if (_signalQuality != value) { _signalQuality = value; OnPropertyChanged("SignalQuality"); } } + } + + #endregion + + #region Private Methods + + private void ProcessSessionHeader(string sessionHeader, string response) + { + if (!string.IsNullOrEmpty(sessionHeader)) + { + var m = RegexRtspSessionHeader.Match(sessionHeader); + if (!m.Success) + { + _logger.Error("Failed to tune, RTSP {0} response session header {1} format not recognised", response, sessionHeader); + } + _rtspSessionId = m.Groups[1].Captures[0].Value; + _rtspSessionTimeToLive = m.Groups[3].Captures.Count == 1 ? int.Parse(m.Groups[3].Captures[0].Value) : DefaultRtspSessionTimeout; + } + } + private void ProcessTransportHeader(string transportHeader) + { + if (!string.IsNullOrEmpty(transportHeader)) + { + var transports = transportHeader.Split(','); + foreach (var transport in transports) + { + if (transport.Trim().StartsWith("RTP/AVP")) + { + var sections = transport.Split(';'); + foreach (var section in sections) + { + var parts = section.Split('='); + if (parts[0].Equals("server_port")) + { + var ports = parts[1].Split('-'); + _serverRtpPort = int.Parse(ports[0]); + _serverRtcpPort = int.Parse(ports[1]); + } + else if (parts[0].Equals("destination")) + { + _destination = parts[1]; + } + else if (parts[0].Equals("port")) + { + var ports = parts[1].Split('-'); + _rtpPort = int.Parse(ports[0]); + _rtcpPort = int.Parse(ports[1]); + } + else if (parts[0].Equals("ttl")) + { + _rtspSessionTimeToLive = int.Parse(parts[1]); + } + else if (parts[0].Equals("source")) + { + _source = parts[1]; + } + else if (parts[0].Equals("client_port")) + { + var ports = parts[1].Split('-'); + var rtp = int.Parse(ports[0]); + var rtcp = int.Parse(ports[1]); + //if (!rtp.Equals(_rtpPort)) + //{ + // Logger.Error("SAT>IP base: server specified RTP client port {0} instead of {1}", rtp, _rtpPort); + //} + //if (!rtcp.Equals(_rtcpPort)) + //{ + // Logger.Error("SAT>IP base: server specified RTCP client port {0} instead of {1}", rtcp, _rtcpPort); + //} + _rtpPort = rtp; + _rtcpPort = rtcp; + } + } + } + } + } + } + private void Connect() + { + _rtspSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + var ip = IPAddress.Parse(_address); + var rtspEndpoint = new IPEndPoint(ip, 554); + _rtspSocket.Connect(rtspEndpoint); + } + private void Disconnect() + { + if (_rtspSocket != null && _rtspSocket.Connected) + { + _rtspSocket.Shutdown(SocketShutdown.Both); + _rtspSocket.Close(); + } + } + private void SendRequest(RtspRequest request) + { + if (_rtspSocket == null) + { + Connect(); + } + try + { + request.Headers.Add("CSeq", _rtspSequenceNum.ToString()); + _rtspSequenceNum++; + byte[] requestBytes = request.Serialise(); + if (_rtspSocket != null) + { + var requestBytesCount = _rtspSocket.Send(requestBytes, requestBytes.Length, SocketFlags.None); + if (requestBytesCount < 1) + { + + } + } + } + catch (Exception e) + { + _logger.Error(e.Message); + } + } + private void ReceiveResponse(out RtspResponse response) + { + response = null; + var responseBytesCount = 0; + byte[] responseBytes = new byte[1024]; + try + { + responseBytesCount = _rtspSocket.Receive(responseBytes, responseBytes.Length, SocketFlags.None); + response = RtspResponse.Deserialise(responseBytes, responseBytesCount); + string contentLengthString; + int contentLength = 0; + if (response.Headers.TryGetValue("Content-Length", out contentLengthString)) + { + contentLength = int.Parse(contentLengthString); + if ((string.IsNullOrEmpty(response.Body) && contentLength > 0) || response.Body.Length < contentLength) + { + if (response.Body == null) + { + response.Body = string.Empty; + } + while (responseBytesCount > 0 && response.Body.Length < contentLength) + { + responseBytesCount = _rtspSocket.Receive(responseBytes, responseBytes.Length, SocketFlags.None); + response.Body += System.Text.Encoding.UTF8.GetString(responseBytes, 0, responseBytesCount); + } + } + } + } + catch (SocketException) + { + } + } + + #endregion + + #region Public Methods + + public RtspStatusCode Setup(string query, string transporttype) + { + + RtspRequest request; + RtspResponse response; + //_rtspClient = new RtspClient(_rtspDevice.ServerAddress); + if ((_rtspSocket == null)) + { + Connect(); + } + if (string.IsNullOrEmpty(_rtspSessionId)) + { + request = new RtspRequest(RtspMethod.Setup, string.Format("rtsp://{0}:{1}/?{2}", _address, 554, query), 1, 0); + switch (transporttype) + { + case "multicast": + request.Headers.Add("Transport", string.Format("RTP/AVP;multicast")); + break; + case "unicast": + var activeTcpConnections = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections(); + var usedPorts = new HashSet(); + foreach (var connection in activeTcpConnections) + { + usedPorts.Add(connection.LocalEndPoint.Port); + } + for (var port = 40000; port <= 65534; port += 2) + { + if (!usedPorts.Contains(port) && !usedPorts.Contains(port + 1)) + { + + _clientRtpPort = port; + _clientRtcpPort = port + 1; + break; + } + } + request.Headers.Add("Transport", string.Format("RTP/AVP;unicast;client_port={0}-{1}", _clientRtpPort, _clientRtcpPort)); + break; + } + } + else + { + request = new RtspRequest(RtspMethod.Setup, string.Format("rtsp://{0}:{1}/?{2}", _address, 554, query), 1, 0); + switch (transporttype) + { + case "multicast": + request.Headers.Add("Transport", string.Format("RTP/AVP;multicast")); + break; + case "unicast": + request.Headers.Add("Transport", string.Format("RTP/AVP;unicast;client_port={0}-{1}", _clientRtpPort, _clientRtcpPort)); + break; + } + + } + SendRequest(request); + ReceiveResponse(out response); + + //if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) + //{ + // Logger.Error("Failed to tune, non-OK RTSP SETUP status code {0} {1}", response.StatusCode, response.ReasonPhrase); + //} + if (!response.Headers.TryGetValue("com.ses.streamID", out _rtspStreamId)) + { + _logger.Error(string.Format("Failed to tune, not able to locate Stream ID header in RTSP SETUP response")); + } + string sessionHeader; + if (!response.Headers.TryGetValue("Session", out sessionHeader)) + { + _logger.Error(string.Format("Failed to tune, not able to locate Session header in RTSP SETUP response")); + } + ProcessSessionHeader(sessionHeader, "Setup"); + string transportHeader; + if (!response.Headers.TryGetValue("Transport", out transportHeader)) + { + _logger.Error(string.Format("Failed to tune, not able to locate Transport header in RTSP SETUP response")); + } + ProcessTransportHeader(transportHeader); + return response.StatusCode; + } + + public RtspStatusCode Play(string query) + { + if ((_rtspSocket == null)) + { + Connect(); + } + //_rtspClient = new RtspClient(_rtspDevice.ServerAddress); + RtspResponse response; + string data; + if (string.IsNullOrEmpty(query)) + { + data = string.Format("rtsp://{0}:{1}/stream={2}", _address, + 554, _rtspStreamId); + } + else + { + data = string.Format("rtsp://{0}:{1}/stream={2}?{3}", _address, + 554, _rtspStreamId, query); + } + var request = new RtspRequest(RtspMethod.Play, data, 1, 0); + request.Headers.Add("Session", _rtspSessionId); + SendRequest(request); + ReceiveResponse(out response); + //if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) + //{ + // Logger.Error("Failed to tune, non-OK RTSP SETUP status code {0} {1}", response.StatusCode, response.ReasonPhrase); + //} + //Logger.Info("RtspSession-Play : \r\n {0}", response); + string sessionHeader; + if (!response.Headers.TryGetValue("Session", out sessionHeader)) + { + _logger.Error(string.Format("Failed to tune, not able to locate Session header in RTSP Play response")); + } + ProcessSessionHeader(sessionHeader, "Play"); + string rtpinfoHeader; + if (!response.Headers.TryGetValue("RTP-Info", out rtpinfoHeader)) + { + _logger.Error(string.Format("Failed to tune, not able to locate Rtp-Info header in RTSP Play response")); + } + return response.StatusCode; + } + + public RtspStatusCode Options() + { + if ((_rtspSocket == null)) + { + Connect(); + } + //_rtspClient = new RtspClient(_rtspDevice.ServerAddress); + RtspRequest request; + RtspResponse response; + + + if (string.IsNullOrEmpty(_rtspSessionId)) + { + request = new RtspRequest(RtspMethod.Options, string.Format("rtsp://{0}:{1}/", _address, 554), 1, 0); + } + else + { + request = new RtspRequest(RtspMethod.Options, string.Format("rtsp://{0}:{1}/", _address, 554), 1, 0); + request.Headers.Add("Session", _rtspSessionId); + } + SendRequest(request); + ReceiveResponse(out response); + //if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) + //{ + // Logger.Error("Failed to tune, non-OK RTSP SETUP status code {0} {1}", response.StatusCode, response.ReasonPhrase); + //} + //Logger.Info("RtspSession-Options : \r\n {0}", response); + string sessionHeader; + if (!response.Headers.TryGetValue("Session", out sessionHeader)) + { + _logger.Error(string.Format("Failed to tune, not able to locate session header in RTSP Options response")); + } + ProcessSessionHeader(sessionHeader, "Options"); + string optionsHeader; + if (!response.Headers.TryGetValue("Public", out optionsHeader)) + { + _logger.Error(string.Format("Failed to tune, not able to Options header in RTSP Options response")); + } + return response.StatusCode; + } + + public RtspStatusCode Describe(out int level, out int quality) + { + if ((_rtspSocket == null)) + { + Connect(); + } + //_rtspClient = new RtspClient(_rtspDevice.ServerAddress); + RtspRequest request; + RtspResponse response; + level = 0; + quality = 0; + + if (string.IsNullOrEmpty(_rtspSessionId)) + { + request = new RtspRequest(RtspMethod.Describe, string.Format("rtsp://{0}:{1}/", _address, 554), 1, 0); + request.Headers.Add("Accept", "application/sdp"); + + } + else + { + request = new RtspRequest(RtspMethod.Describe, string.Format("rtsp://{0}:{1}/stream={2}", _address, 554, _rtspStreamId), 1, 0); + request.Headers.Add("Accept", "application/sdp"); + request.Headers.Add("Session", _rtspSessionId); + } + SendRequest(request); + ReceiveResponse(out response); + //if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) + //{ + // Logger.Error("Failed to tune, non-OK RTSP Describe status code {0} {1}", response.StatusCode, response.ReasonPhrase); + //} + //Logger.Info("RtspSession-Describe : \r\n {0}", response); + string sessionHeader; + if (!response.Headers.TryGetValue("Session", out sessionHeader)) + { + _logger.Error(string.Format("Failed to tune, not able to locate session header in RTSP Describe response")); + } + ProcessSessionHeader(sessionHeader, "Describe"); + var m = RegexDescribeResponseSignalInfo.Match(response.Body); + if (m.Success) + { + + //isSignalLocked = m.Groups[2].Captures[0].Value.Equals("1"); + level = int.Parse(m.Groups[1].Captures[0].Value) * 100 / 255; // level: 0..255 => 0..100 + quality = int.Parse(m.Groups[3].Captures[0].Value) * 100 / 15; // quality: 0..15 => 0..100 + + } + /* + v=0 + o=- 1378633020884883 1 IN IP4 192.168.2.108 + s=SatIPServer:1 4 + t=0 0 + a=tool:idl4k + m=video 52780 RTP/AVP 33 + c=IN IP4 0.0.0.0 + b=AS:5000 + a=control:stream=4 + a=fmtp:33 ver=1.0;tuner=1,0,0,0,12344,h,dvbs2,,off,,22000,34;pids=0,100,101,102,103,106 + =sendonly + */ + + + return response.StatusCode; + } + + public RtspStatusCode TearDown() + { + if ((_rtspSocket == null)) + { + Connect(); + } + //_rtspClient = new RtspClient(_rtspDevice.ServerAddress); + RtspResponse response; + + var request = new RtspRequest(RtspMethod.Teardown, string.Format("rtsp://{0}:{1}/stream={2}", _address, 554, _rtspStreamId), 1, 0); + request.Headers.Add("Session", _rtspSessionId); + SendRequest(request); + ReceiveResponse(out response); + //if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) + //{ + // Logger.Error("Failed to tune, non-OK RTSP Teardown status code {0} {1}", response.StatusCode, response.ReasonPhrase); + //} + return response.StatusCode; + } + + #endregion + + #region Public Events + + public event PropertyChangedEventHandler PropertyChanged; + + #endregion + + #region Protected Methods + + protected void OnPropertyChanged(string name) + { + //var handler = PropertyChanged; + //if (handler != null) + //{ + // handler(this, new PropertyChangedEventArgs(name)); + //} + } + + #endregion + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this);//Disconnect(); + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + TearDown(); + Disconnect(); + } + } + _disposed = true; + } + } +} diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 02f7596e0..ae39d3eb9 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -251,6 +251,7 @@ + -- cgit v1.2.3 From 31e98681fa980bc17fbe8ff4ae717b21f1b25f8f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 17:14:03 -0400 Subject: update sort names --- MediaBrowser.Controller/Entities/BaseItem.cs | 18 ++++++++++++------ MediaBrowser.Controller/Entities/TV/Episode.cs | 2 +- .../Persistence/CleanDatabaseScheduledTask.cs | 2 +- .../Persistence/SqliteItemRepository.cs | 2 +- 4 files changed, 15 insertions(+), 9 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index bf25da2ac..74ff187c5 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -494,7 +494,18 @@ namespace MediaBrowser.Controller.Entities { get { - return _sortName ?? (_sortName = CreateSortName()); + if (_sortName == null) + { + if (!string.IsNullOrWhiteSpace(ForcedSortName)) + { + _sortName = ModifySortChunks(ForcedSortName); + } + else + { + _sortName = CreateSortName(); + } + } + return _sortName; } set { @@ -529,11 +540,6 @@ namespace MediaBrowser.Controller.Entities /// System.String. protected virtual string CreateSortName() { - if (!string.IsNullOrWhiteSpace(ForcedSortName)) - { - return ModifySortChunks(ForcedSortName).ToLower(); - } - if (Name == null) return null; //some items may not have name filled in properly if (!EnableAlphaNumericSorting) diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 88dae3c7c..d016392e8 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -175,7 +175,7 @@ namespace MediaBrowser.Controller.Entities.TV /// System.String. protected override string CreateSortName() { - return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("000-") : "") + return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("000 - ") : "") + (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name; } diff --git a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs index 3c8a0ffeb..38cca3c35 100644 --- a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs @@ -32,7 +32,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private readonly ILocalizationManager _localization; private readonly ITaskManager _taskManager; - public const int MigrationVersion = 20; + public const int MigrationVersion = 22; public static bool EnableUnavailableMessage = false; public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IHttpServer httpServer, ILocalizationManager localization, ITaskManager taskManager) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index de914b773..308645d02 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; - private const int LatestSchemaVersion = 56; + private const int LatestSchemaVersion = 57; /// /// Initializes a new instance of the class. -- cgit v1.2.3 From 1381447bda7982aa0fd8aac30fa29fc42dc437e3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 19:26:13 -0400 Subject: update sat/ip --- .../LiveTv/LiveTvManager.cs | 13 +-- .../LiveTv/TunerHosts/SatIp/ChannelScan.cs | 95 +++++++++++++++++++++- .../LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs | 2 +- .../LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs | 3 +- .../LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs | 3 +- .../LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs | 11 ++- .../LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs | 2 +- .../LiveTv/TunerHosts/SatIp/SatIpHost.cs | 3 +- 8 files changed, 114 insertions(+), 18 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 87c2e8394..d40f2a141 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -2450,7 +2450,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv public List GetSatIniMappings() { - var names = GetType().Assembly.GetManifestResourceNames().Where(i => i.IndexOf("SatIp.ini.satellite", StringComparison.OrdinalIgnoreCase) != -1).ToList(); + var names = GetType().Assembly.GetManifestResourceNames().Where(i => i.IndexOf("SatIp.ini", StringComparison.OrdinalIgnoreCase) != -1).ToList(); return names.Select(GetSatIniMappings).Where(i => i != null).DistinctBy(i => i.Value.Split('|')[0]).ToList(); } @@ -2472,20 +2472,21 @@ namespace MediaBrowser.Server.Implementations.LiveTv return null; } + var srch = "SatIp.ini."; + var filename = Path.GetFileName(resource); + return new NameValuePair { Name = satType1 + " " + satType2, - Value = satType2 + "|" + Path.GetFileName(resource) + Value = satType2 + "|" + filename.Substring(filename.IndexOf(srch) + srch.Length) }; } } } - public async Task> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken) + public Task> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken) { - var result = await new TunerHosts.SatIp.ChannelScan().Scan(info, cancellationToken).ConfigureAwait(false); - - return result.Select(i => new ChannelInfo()).ToList(); + return new TunerHosts.SatIp.ChannelScan(_logger).Scan(info, cancellationToken); } } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs index 2277f8f63..20737df50 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs @@ -1,15 +1,104 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; +using IniParser; +using IniParser.Model; +using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.LiveTv; +using MediaBrowser.Model.Logging; +using MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp; namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp { public class ChannelScan { - public async Task> Scan(TunerHostInfo info, CancellationToken cancellationToken) + private readonly ILogger _logger; + + public ChannelScan(ILogger logger) + { + _logger = logger; + } + + public async Task> Scan(TunerHostInfo info, CancellationToken cancellationToken) + { + var timedToken = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(timedToken.Token, cancellationToken); + + using (var rtspSession = new RtspSession(info.Url, _logger)) + { + var ini = info.SourceA.Split('|')[1]; + var resource = GetType().Assembly.GetManifestResourceNames().FirstOrDefault(i => i.EndsWith(ini, StringComparison.OrdinalIgnoreCase)); + + _logger.Info("Opening ini file {0}", resource); + using (var stream = GetType().Assembly.GetManifestResourceStream(resource)) + { + using (var reader = new StreamReader(stream)) + { + var parser = new StreamIniDataParser(); + var data = parser.ReadData(reader); + + var count = GetInt(data, "DVB", "0", 0); + + var index = 1; + var source = "1"; + + while (!linkedToken.IsCancellationRequested) + { + float percent = count == 0 ? 0 : (float)(index) / count; + percent = Math.Max(percent * 100, 100); + + //SetControlPropertyThreadSafe(pgbSearchResult, "Value", (int)percent); + var strArray = data["DVB"][index.ToString(CultureInfo.InvariantCulture)].Split(','); + + string tuning; + if (strArray[4] == "S2") + { + tuning = string.Format("src={0}&freq={1}&pol={2}&sr={3}&fec={4}&msys=dvbs2&mtype={5}&plts=on&ro=0.35&pids=0,16,17,18,20", source, strArray[0], strArray[1].ToLower(), strArray[2].ToLower(), strArray[3], strArray[5].ToLower()); + } + else + { + tuning = string.Format("src={0}&freq={1}&pol={2}&sr={3}&fec={4}&msys=dvbs&mtype={5}&pids=0,16,17,18,20", source, strArray[0], strArray[1].ToLower(), strArray[2], strArray[3], strArray[5].ToLower()); + } + + if (string.IsNullOrEmpty(rtspSession.RtspSessionId)) + { + rtspSession.Setup(tuning, "unicast"); + + rtspSession.Play(string.Empty); + } + else + { + rtspSession.Play(tuning); + } + + int signallevel; + int signalQuality; + rtspSession.Describe(out signallevel, out signalQuality); + + await Task.Delay(500).ConfigureAwait(false); + index++; + } + } + } + } + + return new List(); + } + + private int GetInt(IniData data, string s1, string s2, int defaultValue) { - return new List(); + var value = data[s1][s2]; + int numericValue; + if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out numericValue)) + { + return numericValue; + } + + return defaultValue; } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs index fae7c4bfc..5f286f1db 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs @@ -17,7 +17,7 @@ using System.Collections.Generic; -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp { /// /// Standard RTSP request methods. diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs index d8462b223..600eda02d 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs @@ -18,8 +18,7 @@ using System.Collections.Generic; using System.Text; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp { /// /// A simple class that can be used to serialise RTSP requests. diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs index 0bf80012d..97290623b 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs @@ -21,8 +21,7 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp { /// /// A simple class that can be used to deserialise RTSP responses. diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs index e76fb7175..71b3f8a18 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs @@ -25,7 +25,7 @@ using System.Net.Sockets; using System.Text.RegularExpressions; using MediaBrowser.Model.Logging; -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp { public class RtspSession : IDisposable { @@ -58,15 +58,22 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp private Socket _rtspSocket; private int _rtspSequenceNum = 1; private bool _disposed = false; - private ILogger _logger; + private readonly ILogger _logger; #endregion #region Constructor public RtspSession(string address, ILogger logger) { + if (string.IsNullOrWhiteSpace(address)) + { + throw new ArgumentNullException("address"); + } + _address = address; _logger = logger; + + _logger.Info("Creating RtspSession with url {0}", address); } ~RtspSession() { diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs index 8786314ed..6d6d50623 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs @@ -17,7 +17,7 @@ using System.ComponentModel; -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp { /// /// Standard RTSP status codes. diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs index 46a2a8524..ffd85fd18 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs @@ -40,7 +40,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp return await new M3uParser(Logger, _fileSystem, _httpClient).Parse(tuner.M3UUrl, ChannelIdPrefix, tuner.Id, cancellationToken).ConfigureAwait(false); } - return new List(); + var channels = await new ChannelScan(Logger).Scan(tuner, cancellationToken).ConfigureAwait(false); + return channels; } public static string DeviceType -- cgit v1.2.3 From 0694dba1e0ac86e9f8b6f6a135baddbe76b41033 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 20:31:55 -0400 Subject: update channel scan --- .../LiveTv/TunerHosts/SatIp/ChannelScan.cs | 48 ++++++++++------------ 1 file changed, 22 insertions(+), 26 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs index 20737df50..fdeae25b0 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs @@ -25,28 +25,31 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp public async Task> Scan(TunerHostInfo info, CancellationToken cancellationToken) { - var timedToken = new CancellationTokenSource(TimeSpan.FromSeconds(30)); - var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(timedToken.Token, cancellationToken); + var ini = info.SourceA.Split('|')[1]; + var resource = GetType().Assembly.GetManifestResourceNames().FirstOrDefault(i => i.EndsWith(ini, StringComparison.OrdinalIgnoreCase)); - using (var rtspSession = new RtspSession(info.Url, _logger)) - { - var ini = info.SourceA.Split('|')[1]; - var resource = GetType().Assembly.GetManifestResourceNames().FirstOrDefault(i => i.EndsWith(ini, StringComparison.OrdinalIgnoreCase)); + _logger.Info("Opening ini file {0}", resource); + var list = new List(); - _logger.Info("Opening ini file {0}", resource); - using (var stream = GetType().Assembly.GetManifestResourceStream(resource)) + using (var stream = GetType().Assembly.GetManifestResourceStream(resource)) + { + using (var reader = new StreamReader(stream)) { - using (var reader = new StreamReader(stream)) - { - var parser = new StreamIniDataParser(); - var data = parser.ReadData(reader); + var parser = new StreamIniDataParser(); + var data = parser.ReadData(reader); - var count = GetInt(data, "DVB", "0", 0); + var count = GetInt(data, "DVB", "0", 0); - var index = 1; - var source = "1"; + _logger.Info("DVB Count: {0}", count); + + var index = 1; + var source = "1"; + + while (index <= count) + { + cancellationToken.ThrowIfCancellationRequested(); - while (!linkedToken.IsCancellationRequested) + using (var rtspSession = new RtspSession(info.Url, _logger)) { float percent = count == 0 ? 0 : (float)(index) / count; percent = Math.Max(percent * 100, 100); @@ -64,16 +67,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp tuning = string.Format("src={0}&freq={1}&pol={2}&sr={3}&fec={4}&msys=dvbs&mtype={5}&pids=0,16,17,18,20", source, strArray[0], strArray[1].ToLower(), strArray[2], strArray[3], strArray[5].ToLower()); } - if (string.IsNullOrEmpty(rtspSession.RtspSessionId)) - { - rtspSession.Setup(tuning, "unicast"); + rtspSession.Setup(tuning, "unicast"); - rtspSession.Play(string.Empty); - } - else - { - rtspSession.Play(tuning); - } + rtspSession.Play(string.Empty); int signallevel; int signalQuality; @@ -86,7 +82,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp } } - return new List(); + return list; } private int GetInt(IniData data, string s1, string s2, int defaultValue) -- cgit v1.2.3 From 132766ff15cd2511ca09be0f2b878ebf5ceb5632 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 2 Apr 2016 00:16:18 -0400 Subject: update ffmpeg --- .../Security/MbAdmin.cs | 4 +- .../Security/PluginSecurityManager.cs | 2 +- MediaBrowser.Dlna/Ssdp/SsdpHandler.cs | 47 +++++++++++++++------- .../EntryPoints/UsageReporter.cs | 2 +- .../ApplicationHost.cs | 2 +- .../FFMpeg/FFMpegDownloadInfo.cs | 16 +++----- .../FFMpeg/FFMpegDownloader.cs | 47 +++++++++++++++------- .../MediaBrowser.ServerApplication.csproj | 2 + .../ffmpeg/ffmpegx64.7z.REMOVED.git-id | 1 + .../ffmpeg/ffmpegx86.7z.REMOVED.git-id | 1 + 10 files changed, 80 insertions(+), 44 deletions(-) create mode 100644 MediaBrowser.ServerApplication/ffmpeg/ffmpegx64.7z.REMOVED.git-id create mode 100644 MediaBrowser.ServerApplication/ffmpeg/ffmpegx86.7z.REMOVED.git-id (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Common.Implementations/Security/MbAdmin.cs b/MediaBrowser.Common.Implementations/Security/MbAdmin.cs index ab4a83257..76ff92c2e 100644 --- a/MediaBrowser.Common.Implementations/Security/MbAdmin.cs +++ b/MediaBrowser.Common.Implementations/Security/MbAdmin.cs @@ -3,11 +3,11 @@ namespace MediaBrowser.Common.Implementations.Security { public class MbAdmin { - public const string HttpUrl = "http://www.mb3admin.com/admin/"; + public const string HttpUrl = "https://www.mb3admin.com/admin/"; /// /// Leaving as http for now until we get it squared away /// - public const string HttpsUrl = "http://www.mb3admin.com/admin/"; + public const string HttpsUrl = "https://www.mb3admin.com/admin/"; } } diff --git a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs index af58c3731..4e01041bc 100644 --- a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs +++ b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs @@ -21,7 +21,7 @@ namespace MediaBrowser.Common.Implementations.Security public class PluginSecurityManager : ISecurityManager { private const string MBValidateUrl = MbAdmin.HttpsUrl + "service/registration/validate"; - private const string AppstoreRegUrl = /*MbAdmin.HttpsUrl*/ "http://mb3admin.com/admin/service/appstore/register"; + private const string AppstoreRegUrl = /*MbAdmin.HttpsUrl*/ "https://mb3admin.com/admin/service/appstore/register"; /// /// The _is MB supporter diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs index 2d1ec1273..3cdeb1afd 100644 --- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs +++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.Dlna.Ssdp private Timer _notificationTimer; private bool _isDisposed; - private readonly ConcurrentDictionary> _devices = new ConcurrentDictionary>(); + private readonly Dictionary> _devices = new Dictionary>(); private readonly IApplicationHost _appHost; @@ -172,9 +172,12 @@ namespace MediaBrowser.Dlna.Ssdp { get { - var devices = _devices.ToList(); + lock (_devices) + { + var devices = _devices.ToList(); - return devices.SelectMany(i => i.Value).ToList(); + return devices.SelectMany(i => i.Value).ToList(); + } } } @@ -482,26 +485,42 @@ namespace MediaBrowser.Dlna.Ssdp public void RegisterNotification(string uuid, Uri descriptionUri, IPAddress address, IEnumerable services) { - var list = _devices.GetOrAdd(uuid, new List()); + lock (_devices) + { + List list; + List dl; + if (_devices.TryGetValue(uuid, out dl)) + { + list = dl; + } + else + { + list = new List(); + _devices[uuid] = list; + } - list.AddRange(services.Select(i => new UpnpDevice(uuid, i, descriptionUri, address))); + list.AddRange(services.Select(i => new UpnpDevice(uuid, i, descriptionUri, address))); - NotifyAll(); - _logger.Debug("Registered mount {0} at {1}", uuid, descriptionUri); + NotifyAll(); + _logger.Debug("Registered mount {0} at {1}", uuid, descriptionUri); + } } public void UnregisterNotification(string uuid) { - List dl; - if (_devices.TryRemove(uuid, out dl)) + lock (_devices) { - - foreach (var d in dl.ToList()) + List dl; + if (_devices.TryGetValue(uuid, out dl)) { - NotifyDevice(d, "byebye", true); - } + _devices.Remove(uuid); + foreach (var d in dl.ToList()) + { + NotifyDevice(d, "byebye", true); + } - _logger.Debug("Unregistered mount {0}", uuid); + _logger.Debug("Unregistered mount {0}", uuid); + } } } diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs index 7e22efb23..7b3a7a30d 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private readonly IHttpClient _httpClient; private readonly IUserManager _userManager; private readonly ILogger _logger; - private const string MbAdminUrl = "http://www.mb3admin.com/admin/"; + private const string MbAdminUrl = "https://www.mb3admin.com/admin/"; public UsageReporter(IApplicationHost applicationHost, IHttpClient httpClient, IUserManager userManager, ILogger logger) { diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index dd7e3cc01..b5988b18a 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -618,7 +618,7 @@ namespace MediaBrowser.Server.Startup.Common /// Task. private async Task RegisterMediaEncoder(IProgress progress) { - var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, NativeApp.Environment) + var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, NativeApp.Environment, NativeApp.GetType().Assembly) .GetFFMpegInfo(NativeApp.Environment, _startupOptions, progress).ConfigureAwait(false); var mediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs index 60cb50e30..4979ff82b 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs @@ -8,6 +8,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg public string FFProbeFilename { get; set; } public string ArchiveType { get; set; } public string[] DownloadUrls { get; set; } + public bool IsEmbedded { get; set; } public FFMpegDownloadInfo() { @@ -54,8 +55,9 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg info.FFMpegFilename = "ffmpeg.exe"; info.FFProbeFilename = "ffprobe.exe"; - info.Version = "20160131"; + info.Version = "20160401"; info.ArchiveType = "7z"; + info.IsEmbedded = true; switch (environment.SystemArchitecture) { @@ -81,17 +83,9 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg switch (environment.SystemArchitecture) { case Architecture.X86_X64: - return new[] - { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20160131-win64.7z", - "http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20151109-git-480bad7-win64-static.7z" - }; + return new string[] { "MediaBrowser.ServerApplication.ffmpeg.ffmpegx64.7z" }; case Architecture.X86: - return new[] - { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20160131-win32.7z", - "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20151109-git-480bad7-win32-static.7z" - }; + return new string[] { "MediaBrowser.ServerApplication.ffmpeg.ffmpegx86.7z" }; } break; diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs index 000568c15..c538b81a4 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -23,13 +24,14 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg private readonly IZipClient _zipClient; private readonly IFileSystem _fileSystem; private readonly NativeEnvironment _environment; + private Assembly _ownerAssembly; private readonly string[] _fontUrls = { "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/ARIALUNI.7z" }; - public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient, IFileSystem fileSystem, NativeEnvironment environment) + public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient, IFileSystem fileSystem, NativeEnvironment environment, Assembly ownerAssembly) { _logger = logger; _appPaths = appPaths; @@ -37,6 +39,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg _zipClient = zipClient; _fileSystem = fileSystem; _environment = environment; + _ownerAssembly = ownerAssembly; } public async Task GetFFMpegInfo(NativeEnvironment environment, StartupOptions options, IProgress progress) @@ -78,11 +81,11 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg Version = version }; - _fileSystem.CreateDirectory(versionedDirectoryPath); + _fileSystem.CreateDirectory(versionedDirectoryPath); var excludeFromDeletions = new List { versionedDirectoryPath }; - if (!_fileSystem.FileExists(info.ProbePath) || !_fileSystem.FileExists(info.EncoderPath)) + if (!_fileSystem.FileExists(info.ProbePath) || !_fileSystem.FileExists(info.EncoderPath)) { // ffmpeg not present. See if there's an older version we can start with var existingVersion = GetExistingVersion(info, rootEncoderPath); @@ -106,7 +109,10 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg } } - await DownloadFonts(versionedDirectoryPath).ConfigureAwait(false); + if (_environment.OperatingSystem == OperatingSystem.Windows) + { + await DownloadFonts(versionedDirectoryPath).ConfigureAwait(false); + } DeleteOlderFolders(Path.GetDirectoryName(versionedDirectoryPath), excludeFromDeletions); @@ -189,6 +195,21 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg private async Task DownloadFFMpeg(FFMpegDownloadInfo downloadinfo, string directory, IProgress progress) { + if (downloadinfo.IsEmbedded) + { + var tempFile = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString()); + _fileSystem.CreateDirectory(Path.GetDirectoryName(tempFile)); + + using (var stream = _ownerAssembly.GetManifestResourceStream(downloadinfo.DownloadUrls[0])) + { + using (var fs = _fileSystem.GetFileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read, true)) + { + await stream.CopyToAsync(fs).ConfigureAwait(false); + } + } + ExtractFFMpeg(downloadinfo, tempFile, directory); + } + foreach (var url in downloadinfo.DownloadUrls) { progress.Report(0); @@ -216,10 +237,8 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg { throw new ApplicationException("ffmpeg unvailable. Please install it and start the server with two command line arguments: -ffmpeg \"{PATH}\" and -ffprobe \"{PATH}\""); } - else - { - throw new ApplicationException("Unable to download required components. Please try again later."); - } + + throw new ApplicationException("Unable to download required components. Please try again later."); } private void ExtractFFMpeg(FFMpegDownloadInfo downloadinfo, string tempFile, string targetFolder) @@ -228,7 +247,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg var tempFolder = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString()); - _fileSystem.CreateDirectory(tempFolder); + _fileSystem.CreateDirectory(tempFolder); try { @@ -247,7 +266,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg })) { var targetFile = Path.Combine(targetFolder, Path.GetFileName(file)); - _fileSystem.CopyFile(file, targetFile, true); + _fileSystem.CopyFile(file, targetFile, true); SetFilePermissions(targetFile); } } @@ -311,13 +330,13 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg { var fontsDirectory = Path.Combine(targetPath, "fonts"); - _fileSystem.CreateDirectory(fontsDirectory); + _fileSystem.CreateDirectory(fontsDirectory); const string fontFilename = "ARIALUNI.TTF"; var fontFile = Path.Combine(fontsDirectory, fontFilename); - if (_fileSystem.FileExists(fontFile)) + if (_fileSystem.FileExists(fontFile)) { await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false); } @@ -360,7 +379,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg { try { - _fileSystem.CopyFile(existingFile, Path.Combine(fontsDirectory, fontFilename), true); + _fileSystem.CopyFile(existingFile, Path.Combine(fontsDirectory, fontFilename), true); return; } catch (IOException ex) @@ -422,7 +441,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg const string fontConfigFilename = "fonts.conf"; var fontConfigFile = Path.Combine(fontsDirectory, fontConfigFilename); - if (!_fileSystem.FileExists(fontConfigFile)) + if (!_fileSystem.FileExists(fontConfigFile)) { var contents = string.Format("{0}ArialArial Unicode MS", fontsDirectory); diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 6ba91c06f..d1bf58dda 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -144,6 +144,8 @@ + + diff --git a/MediaBrowser.ServerApplication/ffmpeg/ffmpegx64.7z.REMOVED.git-id b/MediaBrowser.ServerApplication/ffmpeg/ffmpegx64.7z.REMOVED.git-id new file mode 100644 index 000000000..b0542b75f --- /dev/null +++ b/MediaBrowser.ServerApplication/ffmpeg/ffmpegx64.7z.REMOVED.git-id @@ -0,0 +1 @@ +9dc10b022537738edce7eb71aa8dd4adbfee2c7b \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/ffmpeg/ffmpegx86.7z.REMOVED.git-id b/MediaBrowser.ServerApplication/ffmpeg/ffmpegx86.7z.REMOVED.git-id new file mode 100644 index 000000000..3939ec44d --- /dev/null +++ b/MediaBrowser.ServerApplication/ffmpeg/ffmpegx86.7z.REMOVED.git-id @@ -0,0 +1 @@ +00fa1afa35fbd0a7e97ad7956e42ae17f6882f64 \ No newline at end of file -- cgit v1.2.3 From cbcadbf892b9546ec6b6d1ce821401dfa463a090 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 2 Apr 2016 12:47:23 -0400 Subject: update sorting --- MediaBrowser.Controller/Entities/BaseItem.cs | 3 ++- .../Persistence/CleanDatabaseScheduledTask.cs | 2 +- .../Persistence/SqliteItemRepository.cs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 453ffd23f..ba5da03d1 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -503,7 +503,8 @@ namespace MediaBrowser.Controller.Entities { if (!string.IsNullOrWhiteSpace(ForcedSortName)) { - _sortName = ModifySortChunks(ForcedSortName); + // Need the ToLower because that's what CreateSortName does + _sortName = ModifySortChunks(ForcedSortName).ToLower(); } else { diff --git a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs index 38cca3c35..031333f2c 100644 --- a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs @@ -32,7 +32,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private readonly ILocalizationManager _localization; private readonly ITaskManager _taskManager; - public const int MigrationVersion = 22; + public const int MigrationVersion = 23; public static bool EnableUnavailableMessage = false; public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IHttpServer httpServer, ILocalizationManager localization, ITaskManager taskManager) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 308645d02..eda0a263a 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; - private const int LatestSchemaVersion = 57; + private const int LatestSchemaVersion = 58; /// /// Initializes a new instance of the class. -- cgit v1.2.3 From 4afc2c9156a266a980d06b6657a74f0f4ad47a65 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 3 Apr 2016 14:23:17 -0400 Subject: set notification info url --- MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs | 3 ++- MediaBrowser.Model/Updates/PackageVersionInfo.cs | 2 ++ .../EntryPoints/Notifications/Notifications.cs | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs b/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs index 82ebf92b2..2ffaedc4b 100644 --- a/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs +++ b/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs @@ -111,7 +111,8 @@ namespace MediaBrowser.Common.Implementations.Updates targetFilename = targetFilename, versionStr = version.ToString(), requiredVersionStr = "1.0.0", - description = obj.body + description = obj.body, + infoUrl = obj.html_url } }; } diff --git a/MediaBrowser.Model/Updates/PackageVersionInfo.cs b/MediaBrowser.Model/Updates/PackageVersionInfo.cs index b9bf6e7fe..22404b6f6 100644 --- a/MediaBrowser.Model/Updates/PackageVersionInfo.cs +++ b/MediaBrowser.Model/Updates/PackageVersionInfo.cs @@ -87,5 +87,7 @@ namespace MediaBrowser.Model.Updates /// /// The target filename. public string targetFilename { get; set; } + + public string infoUrl { get; set; } } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs index 918110226..9e68ce4ef 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs @@ -116,7 +116,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications var notification = new NotificationRequest { - NotificationType = type + NotificationType = type, + Url = e.Argument.infoUrl }; notification.Variables["Version"] = e.Argument.versionStr; -- cgit v1.2.3 From 04c8cb5aec70b2ec04fd65c662af7a46cb760b1a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 3 Apr 2016 19:20:43 -0400 Subject: get dynamic info from hdhr --- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 81 ++++++++++++++-------- 1 file changed, 52 insertions(+), 29 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index db7f6f86c..9629f608c 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -59,7 +59,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun return id; } - protected override async Task> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken) + private async Task> GetLineup(TunerHostInfo info, CancellationToken cancellationToken) { var options = new HttpRequestOptions { @@ -68,29 +68,29 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun }; using (var stream = await _httpClient.Get(options)) { - var root = JsonSerializer.DeserializeFromStream>(stream); + var lineup = JsonSerializer.DeserializeFromStream>(stream) ?? new List(); - if (root != null) + if (info.ImportFavoritesOnly) { - var result = root.Select(i => new ChannelInfo - { - Name = i.GuideName, - Number = i.GuideNumber.ToString(CultureInfo.InvariantCulture), - Id = GetChannelId(info, i), - IsFavorite = i.Favorite, - TunerHostId = info.Id + lineup = lineup.Where(i => i.Favorite).ToList(); + } - }); + return lineup; + } + } - if (info.ImportFavoritesOnly) - { - result = result.Where(i => i.IsFavorite ?? true).ToList(); - } + protected override async Task> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken) + { + var lineup = await GetLineup(info, cancellationToken).ConfigureAwait(false); - return result; - } - return new List(); - } + return lineup.Select(i => new ChannelInfo + { + Name = i.GuideName, + Number = i.GuideNumber.ToString(CultureInfo.InvariantCulture), + Id = GetChannelId(info, i), + IsFavorite = i.Favorite, + TunerHostId = info.Id + }); } private async Task GetModelInfo(TunerHostInfo info, CancellationToken cancellationToken) @@ -226,17 +226,21 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun { public string GuideNumber { get; set; } public string GuideName { get; set; } + public string VideoCodec { get; set; } + public string AudioCodec { get; set; } public string URL { get; set; } public bool Favorite { get; set; } public bool DRM { get; set; } + public int HD { get; set; } } - private MediaSourceInfo GetMediaSource(TunerHostInfo info, string channelId, string profile) + private async Task GetMediaSource(TunerHostInfo info, string channelId, string profile) { int? width = null; int? height = null; bool isInterlaced = true; - var videoCodec = !string.IsNullOrWhiteSpace(GetEncodingOptions().HardwareAccelerationType) ? null : "mpeg2video"; + string videoCodec = null; + string audioCodec = "ac3"; int? videoBitrate = null; @@ -297,6 +301,25 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun videoBitrate = 1000000; } + if (string.IsNullOrWhiteSpace(videoCodec)) + { + var lineup = await GetLineup(info, CancellationToken.None).ConfigureAwait(false); + var channel = lineup.FirstOrDefault(i => string.Equals(i.GuideNumber, channelId, StringComparison.OrdinalIgnoreCase)); + if (channel != null) + { + videoCodec = channel.VideoCodec; + audioCodec = channel.AudioCodec; + + videoBitrate = channel.HD == 1 ? 15000000 : 2000000; + } + } + + // normalize + if (string.Equals(videoCodec, "mpeg2", StringComparison.OrdinalIgnoreCase)) + { + videoCodec = "mpeg2video"; + } + var url = GetApiUrl(info, true) + "/auto/v" + channelId; if (!string.IsNullOrWhiteSpace(profile) && !string.Equals(profile, "native", StringComparison.OrdinalIgnoreCase)) @@ -327,7 +350,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun Type = MediaStreamType.Audio, // Set the index to -1 because we don't know the exact index of the audio stream within the container Index = -1, - Codec = "ac3", + Codec = audioCodec, BitRate = 192000 } }, @@ -364,7 +387,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun } var hdhrId = GetHdHrIdFromChannelId(channelId); - list.Add(GetMediaSource(info, hdhrId, "native")); + list.Add(await GetMediaSource(info, hdhrId, "native").ConfigureAwait(false)); try { @@ -373,12 +396,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun if (model.IndexOf("hdtc", StringComparison.OrdinalIgnoreCase) != -1) { - list.Insert(0, GetMediaSource(info, hdhrId, "heavy")); + list.Add(await GetMediaSource(info, hdhrId, "heavy").ConfigureAwait(false)); - list.Add(GetMediaSource(info, hdhrId, "internet480")); - list.Add(GetMediaSource(info, hdhrId, "internet360")); - list.Add(GetMediaSource(info, hdhrId, "internet240")); - list.Add(GetMediaSource(info, hdhrId, "mobile")); + list.Add(await GetMediaSource(info, hdhrId, "internet480").ConfigureAwait(false)); + list.Add(await GetMediaSource(info, hdhrId, "internet360").ConfigureAwait(false)); + list.Add(await GetMediaSource(info, hdhrId, "internet240").ConfigureAwait(false)); + list.Add(await GetMediaSource(info, hdhrId, "mobile").ConfigureAwait(false)); } } catch (Exception ex) @@ -409,7 +432,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun } var hdhrId = GetHdHrIdFromChannelId(channelId); - return GetMediaSource(info, hdhrId, streamId); + return await GetMediaSource(info, hdhrId, streamId).ConfigureAwait(false); } public async Task Validate(TunerHostInfo info) -- cgit v1.2.3 From d9dcd21c47b95919745ec7b5058383357fd73d65 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 3 Apr 2016 20:01:03 -0400 Subject: update hdhr streaming --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 23 +++++----------------- .../Playback/Progressive/VideoService.cs | 4 +--- MediaBrowser.Api/Playback/StreamRequest.cs | 3 --- MediaBrowser.Api/Playback/StreamState.cs | 13 ------------ MediaBrowser.Controller/LiveTv/ChannelInfo.cs | 4 ++++ .../MediaEncoding/EncodingJobOptions.cs | 3 --- MediaBrowser.Dlna/Didl/DidlBuilder.cs | 2 -- MediaBrowser.Dlna/PlayTo/PlayToController.cs | 1 - MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs | 13 ------------ .../Encoder/EncodingJobFactory.cs | 9 --------- MediaBrowser.Model/Dlna/ConditionProcessor.cs | 3 --- MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs | 2 -- MediaBrowser.Model/Dlna/DeviceProfile.cs | 3 +-- MediaBrowser.Model/Dlna/ProfileConditionValue.cs | 1 - MediaBrowser.Model/Dlna/StreamBuilder.cs | 21 ++------------------ MediaBrowser.Model/Dlna/StreamInfo.cs | 18 +++-------------- MediaBrowser.Model/Entities/MediaStream.cs | 6 ------ .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 13 +++++++----- .../Persistence/SqliteItemRepository.cs | 7 ++----- 19 files changed, 26 insertions(+), 123 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 00ac7be87..108b59494 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1452,10 +1452,7 @@ namespace MediaBrowser.Api.Playback } else if (i == 19) { - if (videoRequest != null) - { - videoRequest.Cabac = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); - } + // cabac no longer used } else if (i == 20) { @@ -1805,10 +1802,10 @@ namespace MediaBrowser.Api.Playback { if (string.IsNullOrEmpty(videoStream.Profile)) { - return false; + //return false; } - if (!string.Equals(request.Profile, videoStream.Profile, StringComparison.OrdinalIgnoreCase)) + if (!string.IsNullOrEmpty(videoStream.Profile) && !string.Equals(request.Profile, videoStream.Profile, StringComparison.OrdinalIgnoreCase)) { var currentScore = GetVideoProfileScore(videoStream.Profile); var requestedScore = GetVideoProfileScore(request.Profile); @@ -1884,24 +1881,16 @@ namespace MediaBrowser.Api.Playback { if (!videoStream.Level.HasValue) { - return false; + //return false; } - if (videoStream.Level.Value > requestLevel) + if (videoStream.Level.HasValue && videoStream.Level.Value > requestLevel) { return false; } } } - if (request.Cabac.HasValue && request.Cabac.Value) - { - if (videoStream.IsCabac.HasValue && !videoStream.IsCabac.Value) - { - return false; - } - } - return request.EnableAutoStreamCopy; } @@ -2028,7 +2017,6 @@ namespace MediaBrowser.Api.Playback state.TargetPacketLength, state.TargetTimestamp, state.IsTargetAnamorphic, - state.IsTargetCabac, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, @@ -2131,7 +2119,6 @@ namespace MediaBrowser.Api.Playback state.TargetPacketLength, state.TranscodeSeekInfo, state.IsTargetAnamorphic, - state.IsTargetCabac, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 7c68b1731..b0d87c975 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -137,12 +137,10 @@ namespace MediaBrowser.Api.Playback.Progressive args += " -mpegts_m2ts_mode 1"; } - var isOutputMkv = string.Equals(state.OutputContainer, "mkv", StringComparison.OrdinalIgnoreCase); - if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { if (state.VideoStream != null && IsH264(state.VideoStream) && - (string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) || isOutputMkv)) + (string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase))) { args += " -bsf:v h264_mp4toannexb"; } diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index 1135a3a54..5167af98a 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -190,9 +190,6 @@ namespace MediaBrowser.Api.Playback [ApiMember(Name = "CopyTimestamps", Description = "Whether or not to copy timestamps when transcoding with an offset. Defaults to false.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool CopyTimestamps { get; set; } - [ApiMember(Name = "Cabac", Description = "Enable if cabac encoding is required", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] - public bool? Cabac { get; set; } - public VideoStreamRequest() { EnableAutoStreamCopy = true; diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index f1f6bb71f..ed8a27faf 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -480,18 +480,5 @@ namespace MediaBrowser.Api.Playback return false; } } - - public bool? IsTargetCabac - { - get - { - if (Request.Static) - { - return VideoStream == null ? null : VideoStream.IsCabac; - } - - return true; - } - } } } diff --git a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs index 7d8df96ed..372b095fd 100644 --- a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs +++ b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs @@ -59,5 +59,9 @@ namespace MediaBrowser.Controller.LiveTv /// /// null if [is favorite] contains no value, true if [is favorite]; otherwise, false. public bool? IsFavorite { get; set; } + + public bool? IsHD { get; set; } + public string AudioCodec { get; set; } + public string VideoCodec { get; set; } } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index ddaf7ff6d..c87ac4e73 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -58,8 +58,6 @@ namespace MediaBrowser.Controller.MediaEncoding } } - public bool? Cabac { get; set; } - public EncodingJobOptions() { @@ -87,7 +85,6 @@ namespace MediaBrowser.Controller.MediaEncoding MaxRefFrames = info.MaxRefFrames; MaxVideoBitDepth = info.MaxVideoBitDepth; SubtitleMethod = info.SubtitleDeliveryMethod; - Cabac = info.Cabac; Context = info.Context; if (info.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External) diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index e8e969a5f..728b397de 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -171,7 +171,6 @@ namespace MediaBrowser.Dlna.Didl streamInfo.TargetPacketLength, streamInfo.TranscodeSeekInfo, streamInfo.IsTargetAnamorphic, - streamInfo.IsTargetCabac, streamInfo.TargetRefFrames, streamInfo.TargetVideoStreamCount, streamInfo.TargetAudioStreamCount, @@ -317,7 +316,6 @@ namespace MediaBrowser.Dlna.Didl streamInfo.TargetPacketLength, streamInfo.TargetTimestamp, streamInfo.IsTargetAnamorphic, - streamInfo.IsTargetCabac, streamInfo.TargetRefFrames, streamInfo.TargetVideoStreamCount, streamInfo.TargetAudioStreamCount, diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index 314756cdf..db5e0ee29 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -523,7 +523,6 @@ namespace MediaBrowser.Dlna.PlayTo streamInfo.TargetPacketLength, streamInfo.TranscodeSeekInfo, streamInfo.IsTargetAnamorphic, - streamInfo.IsTargetCabac, streamInfo.TargetRefFrames, streamInfo.TargetVideoStreamCount, streamInfo.TargetAudioStreamCount, diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs index ae676dbc5..b23bd16f3 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs @@ -391,19 +391,6 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - public bool? IsTargetCabac - { - get - { - if (Options.Static) - { - return VideoStream == null ? null : VideoStream.IsCabac; - } - - return true; - } - } - public int? TargetVideoStreamCount { get diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index f782fd05f..070aae3a7 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -664,14 +664,6 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - if (request.Cabac.HasValue && request.Cabac.Value) - { - if (videoStream.IsCabac.HasValue && !videoStream.IsCabac.Value) - { - return false; - } - } - return request.EnableAutoStreamCopy; } @@ -773,7 +765,6 @@ namespace MediaBrowser.MediaEncoding.Encoder state.TargetPacketLength, state.TargetTimestamp, state.IsTargetAnamorphic, - state.IsTargetCabac, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, diff --git a/MediaBrowser.Model/Dlna/ConditionProcessor.cs b/MediaBrowser.Model/Dlna/ConditionProcessor.cs index fef04647a..69f1369dc 100644 --- a/MediaBrowser.Model/Dlna/ConditionProcessor.cs +++ b/MediaBrowser.Model/Dlna/ConditionProcessor.cs @@ -17,7 +17,6 @@ namespace MediaBrowser.Model.Dlna int? packetLength, TransportStreamTimestamp? timestamp, bool? isAnamorphic, - bool? isCabac, int? refFrames, int? numVideoStreams, int? numAudioStreams, @@ -27,8 +26,6 @@ namespace MediaBrowser.Model.Dlna { case ProfileConditionValue.IsAnamorphic: return IsConditionSatisfied(condition, isAnamorphic); - case ProfileConditionValue.IsCabac: - return IsConditionSatisfied(condition, isCabac); case ProfileConditionValue.VideoFramerate: return IsConditionSatisfied(condition, videoFramerate); case ProfileConditionValue.VideoLevel: diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs index 58d669c22..c4b3383a2 100644 --- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs +++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs @@ -115,7 +115,6 @@ namespace MediaBrowser.Model.Dlna int? packetLength, TranscodeSeekInfo transcodeSeekInfo, bool? isAnamorphic, - bool? isCabac, int? refFrames, int? numVideoStreams, int? numAudioStreams, @@ -157,7 +156,6 @@ namespace MediaBrowser.Model.Dlna packetLength, timestamp, isAnamorphic, - isCabac, refFrames, numVideoStreams, numAudioStreams, diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs index 80c060c49..423928f62 100644 --- a/MediaBrowser.Model/Dlna/DeviceProfile.cs +++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs @@ -283,7 +283,6 @@ namespace MediaBrowser.Model.Dlna int? packetLength, TransportStreamTimestamp timestamp, bool? isAnamorphic, - bool? isCabac, int? refFrames, int? numVideoStreams, int? numAudioStreams, @@ -321,7 +320,7 @@ namespace MediaBrowser.Model.Dlna var anyOff = false; foreach (ProfileCondition c in i.Conditions) { - if (!conditionProcessor.IsVideoConditionSatisfied(c, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams, videoCodecTag)) + if (!conditionProcessor.IsVideoConditionSatisfied(c, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames, numVideoStreams, numAudioStreams, videoCodecTag)) { anyOff = true; break; diff --git a/MediaBrowser.Model/Dlna/ProfileConditionValue.cs b/MediaBrowser.Model/Dlna/ProfileConditionValue.cs index 4ad326e51..c17a09c3f 100644 --- a/MediaBrowser.Model/Dlna/ProfileConditionValue.cs +++ b/MediaBrowser.Model/Dlna/ProfileConditionValue.cs @@ -17,7 +17,6 @@ VideoTimestamp = 12, IsAnamorphic = 13, RefFrames = 14, - IsCabac = 15, NumAudioStreams = 16, NumVideoStreams = 17, IsSecondaryAudio = 18, diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index e5477cfd0..f80c52e38 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -597,7 +597,6 @@ namespace MediaBrowser.Model.Dlna string videoProfile = videoStream == null ? null : videoStream.Profile; float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate; bool? isAnamorphic = videoStream == null ? null : videoStream.IsAnamorphic; - bool? isCabac = videoStream == null ? null : videoStream.IsCabac; string videoCodecTag = videoStream == null ? null : videoStream.CodecTag; int? audioBitrate = audioStream == null ? null : audioStream.BitRate; @@ -614,7 +613,7 @@ namespace MediaBrowser.Model.Dlna // Check container conditions foreach (ProfileCondition i in conditions) { - if (!conditionProcessor.IsVideoConditionSatisfied(i, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams, videoCodecTag)) + if (!conditionProcessor.IsVideoConditionSatisfied(i, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames, numVideoStreams, numAudioStreams, videoCodecTag)) { LogConditionFailure(profile, "VideoContainerProfile", i, mediaSource); @@ -647,7 +646,7 @@ namespace MediaBrowser.Model.Dlna foreach (ProfileCondition i in conditions) { - if (!conditionProcessor.IsVideoConditionSatisfied(i, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams, videoCodecTag)) + if (!conditionProcessor.IsVideoConditionSatisfied(i, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames, numVideoStreams, numAudioStreams, videoCodecTag)) { LogConditionFailure(profile, "VideoCodecProfile", i, mediaSource); @@ -910,22 +909,6 @@ namespace MediaBrowser.Model.Dlna } break; } - case ProfileConditionValue.IsCabac: - { - bool val; - if (BoolHelper.TryParseCultureInvariant(value, out val)) - { - if (condition.Condition == ProfileConditionType.Equals) - { - item.Cabac = val; - } - else if (condition.Condition == ProfileConditionType.NotEquals) - { - item.Cabac = !val; - } - } - break; - } case ProfileConditionValue.IsAnamorphic: case ProfileConditionValue.AudioProfile: case ProfileConditionValue.Has64BitOffsets: diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 436ed2071..a2867dcc9 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -30,7 +30,6 @@ namespace MediaBrowser.Model.Dlna public string VideoCodec { get; set; } public string VideoProfile { get; set; } - public bool? Cabac { get; set; } public bool CopyTimestamps { get; set; } public string AudioCodec { get; set; } @@ -219,7 +218,9 @@ namespace MediaBrowser.Model.Dlna list.Add(new NameValuePair("MaxRefFrames", item.MaxRefFrames.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxRefFrames.Value) : string.Empty)); list.Add(new NameValuePair("MaxVideoBitDepth", item.MaxVideoBitDepth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxVideoBitDepth.Value) : string.Empty)); list.Add(new NameValuePair("Profile", item.VideoProfile ?? string.Empty)); - list.Add(new NameValuePair("Cabac", item.Cabac.HasValue ? item.Cabac.Value.ToString() : string.Empty)); + + // no longer used + list.Add(new NameValuePair("Cabac", string.Empty)); list.Add(new NameValuePair("PlaySessionId", item.PlaySessionId ?? string.Empty)); list.Add(new NameValuePair("api_key", accessToken ?? string.Empty)); @@ -632,19 +633,6 @@ namespace MediaBrowser.Model.Dlna } } - public bool? IsTargetCabac - { - get - { - if (IsDirectStream) - { - return TargetVideoStream == null ? null : TargetVideoStream.IsCabac; - } - - return true; - } - } - public int? TargetWidth { get diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 79fa46baf..bdc043e9a 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -232,11 +232,5 @@ namespace MediaBrowser.Model.Entities /// /// true if this instance is anamorphic; otherwise, false. public bool? IsAnamorphic { get; set; } - - /// - /// Gets or sets a value indicating whether this instance is cabac. - /// - /// null if [is cabac] contains no value, true if [is cabac]; otherwise, false. - public bool? IsCabac { get; set; } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 9629f608c..ef8efbe98 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -89,7 +89,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun Number = i.GuideNumber.ToString(CultureInfo.InvariantCulture), Id = GetChannelId(info, i), IsFavorite = i.Favorite, - TunerHostId = info.Id + TunerHostId = info.Id, + IsHD = i.HD == 1, + AudioCodec = i.AudioCodec, + VideoCodec = i.VideoCodec }); } @@ -303,14 +306,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun if (string.IsNullOrWhiteSpace(videoCodec)) { - var lineup = await GetLineup(info, CancellationToken.None).ConfigureAwait(false); - var channel = lineup.FirstOrDefault(i => string.Equals(i.GuideNumber, channelId, StringComparison.OrdinalIgnoreCase)); + var channels = await GetChannels(info, true, CancellationToken.None).ConfigureAwait(false); + var channel = channels.FirstOrDefault(i => string.Equals(i.Number, channelId, StringComparison.OrdinalIgnoreCase)); if (channel != null) { videoCodec = channel.VideoCodec; audioCodec = channel.AudioCodec; - videoBitrate = channel.HD == 1 ? 15000000 : 2000000; + videoBitrate = (channel.IsHD ?? true) ? 15000000 : 2000000; } } @@ -343,7 +346,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun Width = width, Height = height, BitRate = videoBitrate - + }, new MediaStream { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index eda0a263a..71c338fdb 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -2755,7 +2755,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveStreamCommand.GetParameter(index++).Value = stream.BitDepth; _saveStreamCommand.GetParameter(index++).Value = stream.IsAnamorphic; _saveStreamCommand.GetParameter(index++).Value = stream.RefFrames; - _saveStreamCommand.GetParameter(index++).Value = stream.IsCabac; + _saveStreamCommand.GetParameter(index++).Value = null; _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; _saveStreamCommand.GetParameter(index++).Value = stream.Comment; @@ -2907,10 +2907,7 @@ namespace MediaBrowser.Server.Implementations.Persistence item.RefFrames = reader.GetInt32(24); } - if (!reader.IsDBNull(25)) - { - item.IsCabac = reader.GetBoolean(25); - } + // cabac no longer used if (!reader.IsDBNull(26)) { -- cgit v1.2.3 From ddbf183df59b43e5b9f47c81e923b2669b4e26cf Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 4 Apr 2016 15:07:43 -0400 Subject: update edge playback --- .../EntryPoints/ExternalPortForwarding.cs | 202 +++++++++++++++------ .../MediaBrowser.Server.Implementations.csproj | 4 - .../packages.config | 1 - 3 files changed, 151 insertions(+), 56 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index a7e5396eb..5777a0af7 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -3,6 +3,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Logging; +using Mono.Nat; using System; using System.Collections.Generic; using System.Globalization; @@ -10,9 +11,6 @@ using System.IO; using System.Net; using System.Text; using MediaBrowser.Common.Threading; -using Open.Nat; -using System.Threading; -using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.EntryPoints { @@ -22,8 +20,9 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private readonly ILogger _logger; private readonly IServerConfigurationManager _config; private readonly ISsdpHandler _ssdp; - private CancellationTokenSource _currentCancellationTokenSource; - private TimeSpan _interval = TimeSpan.FromHours(1); + + private PeriodicTimer _timer; + private bool _isStarted; public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, ISsdpHandler ssdp) { @@ -31,78 +30,157 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _appHost = appHost; _config = config; _ssdp = ssdp; + } - _config.ConfigurationUpdated += _config_ConfigurationUpdated; + 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()); } - private void _config_ConfigurationUpdated(object sender, EventArgs e) + void _config_ConfigurationUpdated(object sender, EventArgs e) { + if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase)) + { + if (_isStarted) + { + DisposeNat(); + } + + Run(); + } } public void Run() { - Discover(); + //NatUtility.Logger = new LogWriter(_logger); + + if (_config.Configuration.EnableUPnP) + { + Start(); + } + + _config.ConfigurationUpdated -= _config_ConfigurationUpdated; + _config.ConfigurationUpdated += _config_ConfigurationUpdated; } - private async void Discover() + private void Start() { - if (!_config.Configuration.EnableUPnP) + _logger.Debug("Starting NAT discovery"); + NatUtility.EnabledProtocols = new List { - return; - } + NatProtocol.Pmp + }; + NatUtility.DeviceFound += NatUtility_DeviceFound; - var discoverer = new NatDiscoverer(); + // 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; - var cancellationTokenSource = new CancellationTokenSource(10000); - _currentCancellationTokenSource = cancellationTokenSource; - try - { - var device = await discoverer.DiscoverDeviceAsync(PortMapper.Upnp, cancellationTokenSource).ConfigureAwait(false); + // it is hard to say what one should do when an unhandled exception is raised + // because there isn't anything one can do about it. Probably save a log or ignored it. + NatUtility.UnhandledException += NatUtility_UnhandledException; + NatUtility.StartDiscovery(); - await CreateRules(device).ConfigureAwait(false); - } - catch (OperationCanceledException) - { + _timer = new PeriodicTimer(s => _createdRules = new List(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); + + _ssdp.MessageReceived += _ssdp_MessageReceived; + + _lastConfigIdentifier = GetConfigIdentifier(); + + _isStarted = true; + } + + void _ssdp_MessageReceived(object sender, SsdpMessageEventArgs e) + { + var endpoint = e.EndPoint as IPEndPoint; + if (endpoint != null && e.LocalEndPoint != null) + { + NatUtility.Handle(e.LocalEndPoint.Address, e.Message, endpoint, NatProtocol.Upnp); } - catch (Exception ex) + } + + void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + var ex = e.ExceptionObject as Exception; + + if (ex == null) { - _logger.ErrorException("Error discovering NAT devices", ex); + //_logger.Error("Unidentified error reported by Mono.Nat"); } - finally + else { - _currentCancellationTokenSource = null; + // Seeing some blank exceptions coming through here + //_logger.ErrorException("Error reported by Mono.Nat: ", ex); } + } - if (_config.Configuration.EnableUPnP) + void NatUtility_DeviceFound(object sender, DeviceEventArgs e) + { + try { - await Task.Delay(_interval).ConfigureAwait(false); - Discover(); + var device = e.Device; + _logger.Debug("NAT device found: {0}", device.LocalAddress.ToString()); + + CreateRules(device); + } + catch (Exception ex) + { + // 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 async Task CreateRules(NatDevice device) + private List _createdRules = new List(); + private void CreateRules(INatDevice device) { // 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 - await CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort).ConfigureAwait(false); - await CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort).ConfigureAwait(false); + var address = device.LocalAddress.ToString(); + + if (!_createdRules.Contains(address)) + { + _createdRules.Add(address); + + CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort); + CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort); + } } - private async Task CreatePortMap(NatDevice device, int privatePort, int publicPort) + private void CreatePortMap(INatDevice device, int privatePort, int publicPort) { _logger.Debug("Creating port map on port {0}", privatePort); - - try + device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort) { - await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, privatePort, publicPort, _appHost.Name)).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error creating port map", ex); - } + Description = _appHost.Name + }); + } + + // 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()); } public void Dispose() @@ -112,17 +190,39 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private void DisposeNat() { - if (_currentCancellationTokenSource != null) + _logger.Debug("Stopping NAT discovery"); + + if (_timer != null) { - try - { - _currentCancellationTokenSource.Cancel(); - } - catch (Exception ex) - { - _logger.ErrorException("Error calling _currentCancellationTokenSource.Cancel", ex); - } + _timer.Dispose(); + _timer = null; + } + + _ssdp.MessageReceived -= _ssdp_MessageReceived; + + try + { + // This is not a significant improvement + NatUtility.StopDiscovery(); + NatUtility.DeviceFound -= NatUtility_DeviceFound; + NatUtility.DeviceLost -= NatUtility_DeviceLost; + NatUtility.UnhandledException -= NatUtility_UnhandledException; + } + // 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/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index ae39d3eb9..60d8f737f 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -62,10 +62,6 @@ ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll - - ..\packages\Open.NAT.2.0.15.0\lib\net45\Open.Nat.dll - True - ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 814a67643..66aede029 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -7,7 +7,6 @@ - \ No newline at end of file -- cgit v1.2.3 From b844471860e468bc1641e2d854fd8a5ab8ce7f3f Mon Sep 17 00:00:00 2001 From: Daniel Becker Date: Sun, 3 Apr 2016 23:39:40 -0700 Subject: fix resolution for internet540 profile; remove obsolete internet720 profile --- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index ef8efbe98..2503412d5 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -263,18 +263,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun videoCodec = "h264"; videoBitrate = 15000000; } - else if (string.Equals(profile, "internet720", StringComparison.OrdinalIgnoreCase)) - { - width = 1280; - height = 720; - isInterlaced = false; - videoCodec = "h264"; - videoBitrate = 8000000; - } else if (string.Equals(profile, "internet540", StringComparison.OrdinalIgnoreCase)) { - width = 1280; - height = 720; + width = 960; + height = 546; isInterlaced = false; videoCodec = "h264"; videoBitrate = 2500000; -- cgit v1.2.3 From aa817508e25ce164184c44d2c16fd5091961dc6d Mon Sep 17 00:00:00 2001 From: Daniel Becker Date: Sun, 3 Apr 2016 23:42:07 -0700 Subject: actually add internet540 profile --- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 2503412d5..101238567 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -393,6 +393,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun { list.Add(await GetMediaSource(info, hdhrId, "heavy").ConfigureAwait(false)); + list.Add(await GetMediaSource(info, hdhrId, "internet540").ConfigureAwait(false)); list.Add(await GetMediaSource(info, hdhrId, "internet480").ConfigureAwait(false)); list.Add(await GetMediaSource(info, hdhrId, "internet360").ConfigureAwait(false)); list.Add(await GetMediaSource(info, hdhrId, "internet240").ConfigureAwait(false)); -- cgit v1.2.3 From c9092de032b4166f5907283f35d361ee7c49a3ee Mon Sep 17 00:00:00 2001 From: Daniel Becker Date: Sun, 3 Apr 2016 23:46:45 -0700 Subject: allow disabling of hardware transcoding on HDTC-2US --- MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 4 +++- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index 660f30cc9..46f630fe0 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -31,6 +31,7 @@ namespace MediaBrowser.Model.LiveTv public string Type { get; set; } public string DeviceId { get; set; } public bool ImportFavoritesOnly { get; set; } + public bool AllowHWTranscoding { get; set; } public bool IsEnabled { get; set; } public string M3UUrl { get; set; } public string InfoUrl { get; set; } @@ -47,6 +48,7 @@ namespace MediaBrowser.Model.LiveTv public TunerHostInfo() { IsEnabled = true; + AllowHWTranscoding = true; } } @@ -70,4 +72,4 @@ namespace MediaBrowser.Model.LiveTv EnableAllTuners = true; } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index ef8efbe98..64780a8e3 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -397,7 +397,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun string model = await GetModelInfo(info, cancellationToken).ConfigureAwait(false); model = model ?? string.Empty; - if (model.IndexOf("hdtc", StringComparison.OrdinalIgnoreCase) != -1) + if (info.AllowHWTranscoding && (model.IndexOf("hdtc", StringComparison.OrdinalIgnoreCase) != -1)) { list.Add(await GetMediaSource(info, hdhrId, "heavy").ConfigureAwait(false)); -- cgit v1.2.3 From f15e534d41a1f34bb7492671c4590f11303ed39a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 5 Apr 2016 15:34:27 -0400 Subject: update initial user permissions --- MediaBrowser.Server.Implementations/Library/UserManager.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index c1807efe9..5ba83d6c7 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -352,6 +352,7 @@ namespace MediaBrowser.Server.Implementations.Library users.Add(user); user.Policy.IsAdministrator = true; + user.Policy.EnableContentDeletion = true; user.Policy.EnableRemoteControlOfOtherUsers = true; await UpdateUserPolicy(user, user.Policy, false).ConfigureAwait(false); } -- cgit v1.2.3 From 3ac2002759c324aef82c62fcf6cf54ab30ca8dcf Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 5 Apr 2016 15:34:45 -0400 Subject: normalize user specified external address --- .../Connect/ConnectManager.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs index 9ed67f77e..e308acef0 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs @@ -62,6 +62,17 @@ namespace MediaBrowser.Server.Implementations.Connect { var address = _config.Configuration.WanDdns; + if (!string.IsNullOrWhiteSpace(address)) + { + try + { + address = new Uri(address).Host; + } + catch + { + } + } + if (string.IsNullOrWhiteSpace(address) && DiscoveredWanIpAddress != null) { if (DiscoveredWanIpAddress.AddressFamily == AddressFamily.InterNetworkV6) @@ -237,8 +248,8 @@ namespace MediaBrowser.Server.Implementations.Connect var postData = new Dictionary { - {"name", _appHost.FriendlyName}, - {"url", wanApiAddress}, + {"name", _appHost.FriendlyName}, + {"url", wanApiAddress}, {"systemId", _appHost.SystemId} }; -- cgit v1.2.3 From 1cea5bcbd8360fa7c5c9bfd273f27f472809a178 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 5 Apr 2016 22:18:56 -0400 Subject: improve identify feature --- MediaBrowser.Api/ItemLookupService.cs | 15 +++++++++----- .../Providers/MetadataRefreshOptions.cs | 3 +++ MediaBrowser.Providers/Manager/MetadataService.cs | 13 ++++++++++++ MediaBrowser.Providers/Omdb/OmdbItemProvider.cs | 6 ++---- .../HttpServer/HttpListenerHost.cs | 23 ++++++++++++---------- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 2 +- 6 files changed, 42 insertions(+), 20 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs index 8be37e210..41bfd9da2 100644 --- a/MediaBrowser.Api/ItemLookupService.cs +++ b/MediaBrowser.Api/ItemLookupService.cs @@ -202,14 +202,19 @@ namespace MediaBrowser.Api // } //} Logger.Info("Setting provider id's to item {0}-{1}: {2}", item.Id, item.Name, _json.SerializeToString(request.ProviderIds)); + + // Since the refresh process won't erase provider Ids, we need to set this explicitly now. item.ProviderIds = request.ProviderIds; + //item.ProductionYear = request.ProductionYear; + //item.Name = request.Name; - var task = _providerManager.RefreshFullItem(item, new MetadataRefreshOptions(_fileSystem) + var task = _providerManager.RefreshFullItem(item, new MetadataRefreshOptions(_fileSystem) { MetadataRefreshMode = MetadataRefreshMode.FullRefresh, ImageRefreshMode = ImageRefreshMode.FullRefresh, ReplaceAllMetadata = true, - ReplaceAllImages = request.ReplaceAllImages + ReplaceAllImages = request.ReplaceAllImages, + SearchResult = request }, CancellationToken.None); Task.WaitAll(task); @@ -234,7 +239,7 @@ namespace MediaBrowser.Api contentPath = await reader.ReadToEndAsync().ConfigureAwait(false); } - if (_fileSystem.FileExists(contentPath)) + if (_fileSystem.FileExists(contentPath)) { return ToStaticFileResult(contentPath); } @@ -275,7 +280,7 @@ namespace MediaBrowser.Api var fullCachePath = GetFullCachePath(urlHash + "." + ext); - _fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath)); using (var stream = result.Content) { using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, true)) @@ -284,7 +289,7 @@ namespace MediaBrowser.Api } } - _fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); using (var writer = new StreamWriter(pointerCachePath)) { await writer.WriteAsync(fullCachePath).ConfigureAwait(false); diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs index 29f4feb3d..9427b2afd 100644 --- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs +++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs @@ -1,5 +1,6 @@ using System.Linq; using CommonIO; +using MediaBrowser.Model.Providers; namespace MediaBrowser.Controller.Providers { @@ -13,6 +14,7 @@ namespace MediaBrowser.Controller.Providers public bool IsPostRecursiveRefresh { get; set; } public MetadataRefreshMode MetadataRefreshMode { get; set; } + public RemoteSearchResult SearchResult { get; set; } public bool ForceSave { get; set; } @@ -37,6 +39,7 @@ namespace MediaBrowser.Controller.Providers ImageRefreshMode = copy.ImageRefreshMode; ReplaceAllImages = copy.ReplaceAllImages; ReplaceImages = copy.ReplaceImages.ToList(); + SearchResult = copy.SearchResult; } } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index c1ae43124..8f7c93f32 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using CommonIO; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Model.Providers; namespace MediaBrowser.Providers.Manager { @@ -136,6 +137,11 @@ namespace MediaBrowser.Providers.Manager { var id = itemOfType.GetLookupInfo(); + if (refreshOptions.SearchResult != null) + { + ApplySearchResult(id, refreshOptions.SearchResult); + } + //await FindIdentities(id, cancellationToken).ConfigureAwait(false); id.IsAutomated = refreshOptions.IsAutomated; @@ -207,6 +213,13 @@ namespace MediaBrowser.Providers.Manager return updateType; } + private void ApplySearchResult(ItemLookupInfo lookupInfo, RemoteSearchResult result) + { + lookupInfo.ProviderIds = result.ProviderIds; + lookupInfo.Name = result.Name; + lookupInfo.Year = result.ProductionYear; + } + private async Task FindIdentities(TIdType id, CancellationToken cancellationToken) { try diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs index 75bec7b65..894750c81 100644 --- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs @@ -60,9 +60,8 @@ namespace MediaBrowser.Providers.Omdb return GetSearchResultsInternal(searchInfo, type, true, cancellationToken); } - private async Task> GetSearchResultsInternal(ItemLookupInfo searchInfo, string type, bool enableMultipleResults, CancellationToken cancellationToken) + private async Task> GetSearchResultsInternal(ItemLookupInfo searchInfo, string type, bool isSearch, CancellationToken cancellationToken) { - bool isSearch = false; var episodeSearchInfo = searchInfo as EpisodeInfo; var list = new List(); @@ -95,10 +94,9 @@ namespace MediaBrowser.Providers.Omdb } // &s means search and returns a list of results as opposed to t - if (enableMultipleResults) + if (isSearch) { url += "&s=" + WebUtility.UrlEncode(name); - isSearch = true; } else { diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 3e4f4a70c..25463b660 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -344,6 +344,19 @@ namespace MediaBrowser.Server.Implementations.HttpServer LoggerUtils.LogRequest(_logger, urlToLog, httpReq.HttpMethod, httpReq.UserAgent); } + if (string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase) || + string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase)) + { + httpRes.RedirectToUrl(DefaultRedirectPath); + return Task.FromResult(true); + } + if (string.Equals(localPath, "/emby", StringComparison.OrdinalIgnoreCase) || + string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase)) + { + httpRes.RedirectToUrl("emby/" + DefaultRedirectPath); + return Task.FromResult(true); + } + if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase) || string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase) || localPath.IndexOf("mediabrowser/web", StringComparison.OrdinalIgnoreCase) != -1 || @@ -363,16 +376,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer } } - if (string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl(DefaultRedirectPath); - return Task.FromResult(true); - } - if (string.Equals(localPath, "/emby", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl("emby/" + DefaultRedirectPath); - return Task.FromResult(true); - } if (string.Equals(localPath, "/web", StringComparison.OrdinalIgnoreCase)) { httpRes.RedirectToUrl(DefaultRedirectPath); diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index ef8efbe98..7fc54819d 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -75,7 +75,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun lineup = lineup.Where(i => i.Favorite).ToList(); } - return lineup; + return lineup.Where(i => !i.DRM).ToList(); } } -- cgit v1.2.3 From 0e0398026232dac5b7fe71f0dfac1df854c10282 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 5 Apr 2016 23:14:39 -0400 Subject: fix query case sensitivity --- MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 71c338fdb..b6699d164 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -2283,7 +2283,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private static Dictionary GetTypeMapDictionary() { - var dict = new Dictionary(); + var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (var t in KnownTypes) { -- cgit v1.2.3 From 3889bc0a115070892dcfb60fda7d8802d6edc242 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 8 Apr 2016 14:00:35 -0400 Subject: fixes #1609 - Generated links are relative to site root --- MediaBrowser.Server.Implementations/Social/SharingManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Social/SharingManager.cs b/MediaBrowser.Server.Implementations/Social/SharingManager.cs index 326b2893c..2ffd33ca4 100644 --- a/MediaBrowser.Server.Implementations/Social/SharingManager.cs +++ b/MediaBrowser.Server.Implementations/Social/SharingManager.cs @@ -84,7 +84,7 @@ namespace MediaBrowser.Server.Implementations.Social var externalUrl = _appHost.GetSystemInfo().WanAddress; info.ImageUrl = externalUrl + "/Social/Shares/Public/" + info.Id + "/Image"; - info.Url = externalUrl + "/web/shared.html?id=" + info.Id; + info.Url = externalUrl + "/emby/web/shared.html?id=" + info.Id; var item = _libraryManager.GetItemById(info.ItemId); -- cgit v1.2.3 From e31aec4bc5bdda2731fcef9d1d85ccd0f41847f3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 8 Apr 2016 14:32:38 -0400 Subject: update metadata refresh --- MediaBrowser.Controller/Channels/IChannelItem.cs | 11 ---- .../Channels/IChannelMediaItem.cs | 18 ----- MediaBrowser.Controller/Entities/BaseItem.cs | 3 + MediaBrowser.Controller/Entities/IHasImages.cs | 5 +- MediaBrowser.Controller/Entities/IHasMetadata.cs | 2 + .../MediaBrowser.Controller.csproj | 2 - .../Providers/IHasItemChangeMonitor.cs | 3 +- .../Folders/DefaultImageProvider.cs | 2 +- MediaBrowser.Providers/Manager/MetadataService.cs | 76 ++++++++++++++++++---- .../MediaInfo/AudioImageProvider.cs | 9 +-- .../MediaInfo/FFProbeProvider.cs | 6 +- .../MediaInfo/VideoImageProvider.cs | 6 +- MediaBrowser.Providers/Photos/PhotoProvider.cs | 6 +- .../TV/TheTVDB/TvdbSeriesImageProvider.cs | 4 +- .../Channels/ChannelImageProvider.cs | 2 +- .../Channels/ChannelManager.cs | 3 +- .../LiveTv/ChannelImageProvider.cs | 2 +- .../LiveTv/ProgramImageProvider.cs | 2 +- .../LiveTv/RecordingImageProvider.cs | 2 +- .../Persistence/SqliteItemRepository.cs | 23 ++++++- 20 files changed, 115 insertions(+), 72 deletions(-) delete mode 100644 MediaBrowser.Controller/Channels/IChannelItem.cs delete mode 100644 MediaBrowser.Controller/Channels/IChannelMediaItem.cs (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Channels/IChannelItem.cs b/MediaBrowser.Controller/Channels/IChannelItem.cs deleted file mode 100644 index 9b5f0359b..000000000 --- a/MediaBrowser.Controller/Channels/IChannelItem.cs +++ /dev/null @@ -1,11 +0,0 @@ -using MediaBrowser.Controller.Entities; - -namespace MediaBrowser.Controller.Channels -{ - public interface IChannelItem : IHasImages, IHasTags - { - string ChannelId { get; set; } - - string ExternalId { get; set; } - } -} diff --git a/MediaBrowser.Controller/Channels/IChannelMediaItem.cs b/MediaBrowser.Controller/Channels/IChannelMediaItem.cs deleted file mode 100644 index 60a29da90..000000000 --- a/MediaBrowser.Controller/Channels/IChannelMediaItem.cs +++ /dev/null @@ -1,18 +0,0 @@ -using MediaBrowser.Model.Channels; -using MediaBrowser.Model.Entities; -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Channels -{ - public interface IChannelMediaItem : IChannelItem - { - long? RunTimeTicks { get; set; } - string MediaType { get; } - - ChannelMediaContentType ContentType { get; set; } - - ExtraType? ExtraType { get; set; } - - List ChannelMediaSources { get; set; } - } -} \ No newline at end of file diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index ba5da03d1..29f416b8c 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -412,6 +412,9 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public DateTime DateLastRefreshed { get; set; } + [IgnoreDataMember] + public DateTime? DateModifiedDuringLastRefresh { get; set; } + /// /// The logger /// diff --git a/MediaBrowser.Controller/Entities/IHasImages.cs b/MediaBrowser.Controller/Entities/IHasImages.cs index a38b7394d..897250caa 100644 --- a/MediaBrowser.Controller/Entities/IHasImages.cs +++ b/MediaBrowser.Controller/Entities/IHasImages.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Providers; +using System; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using System.Collections.Generic; using System.Threading; @@ -206,6 +207,8 @@ namespace MediaBrowser.Controller.Entities /// The image. /// The index. void SetImage(ItemImageInfo image, int index); + + DateTime? DateModifiedDuringLastRefresh { get; set; } } public static class HasImagesExtensions diff --git a/MediaBrowser.Controller/Entities/IHasMetadata.cs b/MediaBrowser.Controller/Entities/IHasMetadata.cs index 0e4ae04ff..1f680b35f 100644 --- a/MediaBrowser.Controller/Entities/IHasMetadata.cs +++ b/MediaBrowser.Controller/Entities/IHasMetadata.cs @@ -25,6 +25,8 @@ namespace MediaBrowser.Controller.Entities /// The date last saved. DateTime DateLastSaved { get; set; } + SourceType SourceType { get; set; } + /// /// Gets or sets the date last refreshed. /// diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 6f429ed2f..235638b5f 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -85,10 +85,8 @@ - - diff --git a/MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs b/MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs index 4c7069dd6..9441c3ecd 100644 --- a/MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs +++ b/MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs @@ -8,9 +8,8 @@ namespace MediaBrowser.Controller.Providers /// Determines whether the specified item has changed. /// /// The item. - /// The status. /// The directory service. /// true if the specified item has changed; otherwise, false. - bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService); + bool HasChanged(IHasMetadata item, IDirectoryService directoryService); } } \ No newline at end of file diff --git a/MediaBrowser.Providers/Folders/DefaultImageProvider.cs b/MediaBrowser.Providers/Folders/DefaultImageProvider.cs index ee83efd26..afd8c583d 100644 --- a/MediaBrowser.Providers/Folders/DefaultImageProvider.cs +++ b/MediaBrowser.Providers/Folders/DefaultImageProvider.cs @@ -157,7 +157,7 @@ namespace MediaBrowser.Providers.Folders }); } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { return GetSupportedImages(item).Any(i => !item.HasImage(i)); } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 8f7c93f32..47783ebc6 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -11,8 +12,11 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.Playlists; using MediaBrowser.Model.Providers; namespace MediaBrowser.Providers.Manager @@ -68,6 +72,11 @@ namespace MediaBrowser.Providers.Manager result.ItemDateModified = item.DateModified; + if (EnableDateLastRefreshed(item)) + { + return Task.FromResult(true); + } + return ProviderRepo.SaveMetadataStatus(result, CancellationToken.None); } @@ -83,7 +92,22 @@ namespace MediaBrowser.Providers.Manager return new MetadataStatus { ItemId = item.Id }; } - return ProviderRepo.GetMetadataStatus(item.Id) ?? new MetadataStatus { ItemId = item.Id }; + if (EnableDateLastRefreshed(item) && item.DateModifiedDuringLastRefresh.HasValue) + { + return new MetadataStatus + { + ItemId = item.Id, + DateLastImagesRefresh = item.DateLastRefreshed, + DateLastMetadataRefresh = item.DateLastRefreshed, + ItemDateModified = item.DateModifiedDuringLastRefresh.Value + }; + } + + var result = ProviderRepo.GetMetadataStatus(item.Id) ?? new MetadataStatus { ItemId = item.Id }; + + item.DateModifiedDuringLastRefresh = result.ItemDateModified; + + return result; } public async Task RefreshMetadata(IHasMetadata item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) @@ -119,13 +143,20 @@ namespace MediaBrowser.Providers.Manager Item = itemOfType }; + bool hasRefreshedMetadata = false; + bool hasRefreshedImages = false; + // Next run metadata providers if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None) { var providers = GetProviders(item, refreshResult, refreshOptions) .ToList(); - if (providers.Count > 0 || !refreshResult.DateLastMetadataRefresh.HasValue) + var dateLastRefresh = EnableDateLastRefreshed(item) + ? item.DateLastRefreshed + : refreshResult.DateLastMetadataRefresh ?? default(DateTime); + + if (providers.Count > 0 || dateLastRefresh == default(DateTime)) { if (item.BeforeMetadataRefresh()) { @@ -151,6 +182,7 @@ namespace MediaBrowser.Providers.Manager if (result.Failures == 0) { refreshResult.SetDateLastMetadataRefresh(DateTime.UtcNow); + hasRefreshedMetadata = true; } else { @@ -172,6 +204,7 @@ namespace MediaBrowser.Providers.Manager if (result.Failures == 0) { refreshResult.SetDateLastImagesRefresh(DateTime.UtcNow); + hasRefreshedImages = true; } else { @@ -194,9 +227,15 @@ namespace MediaBrowser.Providers.Manager updateType = updateType | ItemUpdateType.MetadataDownload; } - if (refreshOptions.MetadataRefreshMode >= MetadataRefreshMode.Default && refreshOptions.ImageRefreshMode >= ImageRefreshMode.Default) + if (hasRefreshedMetadata && hasRefreshedImages) { item.DateLastRefreshed = DateTime.UtcNow; + item.DateModifiedDuringLastRefresh = item.DateModified; + } + else + { + item.DateLastRefreshed = default(DateTime); + item.DateModifiedDuringLastRefresh = null; } // Save to database @@ -254,7 +293,12 @@ namespace MediaBrowser.Providers.Manager return true; } - if (item is BoxSet || (item is IItemByName && !(item is MusicArtist))) + if (item is BoxSet || item is IItemByName || item is Playlist) + { + return true; + } + + if (item.SourceType != SourceType.Library) { return true; } @@ -364,8 +408,12 @@ namespace MediaBrowser.Providers.Manager // Get providers to refresh var providers = ((ProviderManager)ProviderManager).GetMetadataProviders(item).ToList(); + var dateLastRefresh = EnableDateLastRefreshed(item) + ? item.DateLastRefreshed + : status.DateLastMetadataRefresh ?? default(DateTime); + // Run all if either of these flags are true - var runAllProviders = options.ReplaceAllMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || !status.DateLastMetadataRefresh.HasValue; + var runAllProviders = options.ReplaceAllMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || dateLastRefresh == default(DateTime); if (!runAllProviders) { @@ -384,7 +432,7 @@ namespace MediaBrowser.Providers.Manager var hasFileChangeMonitor = i as IHasItemChangeMonitor; if (hasFileChangeMonitor != null) { - return HasChanged(item, hasFileChangeMonitor, status, options.DirectoryService); + return HasChanged(item, hasFileChangeMonitor, options.DirectoryService); } return false; @@ -429,8 +477,12 @@ namespace MediaBrowser.Providers.Manager // Get providers to refresh var providers = allImageProviders.Where(i => !(i is ILocalImageProvider)).ToList(); + var dateLastImageRefresh = EnableDateLastRefreshed(item) + ? item.DateLastRefreshed + : status.DateLastImagesRefresh ?? default(DateTime); + // Run all if either of these flags are true - var runAllProviders = options.ImageRefreshMode == ImageRefreshMode.FullRefresh || !status.DateLastImagesRefresh.HasValue; + var runAllProviders = options.ImageRefreshMode == ImageRefreshMode.FullRefresh || dateLastImageRefresh == default(DateTime); if (!runAllProviders) { @@ -440,13 +492,13 @@ namespace MediaBrowser.Providers.Manager var hasChangeMonitor = i as IHasChangeMonitor; if (hasChangeMonitor != null) { - return HasChanged(item, hasChangeMonitor, status.DateLastImagesRefresh.Value, options.DirectoryService); + return HasChanged(item, hasChangeMonitor, dateLastImageRefresh, options.DirectoryService); } var hasFileChangeMonitor = i as IHasItemChangeMonitor; if (hasFileChangeMonitor != null) { - return HasChanged(item, hasFileChangeMonitor, status, options.DirectoryService); + return HasChanged(item, hasFileChangeMonitor, options.DirectoryService); } return false; @@ -558,7 +610,7 @@ namespace MediaBrowser.Providers.Manager if (options.MetadataRefreshMode != MetadataRefreshMode.FullRefresh) { // If the local provider fails don't continue with remote providers because the user's saved metadata could be lost - return refreshResult; + //return refreshResult; } } } @@ -738,11 +790,11 @@ namespace MediaBrowser.Providers.Manager } } - private bool HasChanged(IHasMetadata item, IHasItemChangeMonitor changeMonitor, MetadataStatus status, IDirectoryService directoryService) + private bool HasChanged(IHasMetadata item, IHasItemChangeMonitor changeMonitor, IDirectoryService directoryService) { try { - var hasChanged = changeMonitor.HasChanged(item, status, directoryService); + var hasChanged = changeMonitor.HasChanged(item, directoryService); //if (hasChanged) //{ diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index af610520f..aa495afbc 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -159,14 +159,11 @@ namespace MediaBrowser.Providers.MediaInfo return item.LocationType == LocationType.FileSystem && audio != null && !audio.IsArchive; } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - if (status.ItemDateModified.HasValue) + if (item.DateModifiedDuringLastRefresh.HasValue) { - if (status.ItemDateModified.Value != item.DateModified) - { - return true; - } + return item.DateModifiedDuringLastRefresh.Value != item.DateModified; } return false; diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs index a2d15d863..9db4ab96e 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs @@ -163,11 +163,11 @@ namespace MediaBrowser.Providers.MediaInfo return prober.Probe(item, cancellationToken); } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - if (status.ItemDateModified.HasValue) + if (item.DateModifiedDuringLastRefresh.HasValue) { - if (status.ItemDateModified.Value != item.DateModified) + if (item.DateModifiedDuringLastRefresh.Value != item.DateModified) { return true; } diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index f3235a102..a5751da0a 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -151,11 +151,11 @@ namespace MediaBrowser.Providers.MediaInfo } } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - if (status.ItemDateModified.HasValue) + if (item.DateModifiedDuringLastRefresh.HasValue) { - if (status.ItemDateModified.Value != item.DateModified) + if (item.DateModifiedDuringLastRefresh.Value != item.DateModified) { return true; } diff --git a/MediaBrowser.Providers/Photos/PhotoProvider.cs b/MediaBrowser.Providers/Photos/PhotoProvider.cs index ef3144958..882363b2f 100644 --- a/MediaBrowser.Providers/Photos/PhotoProvider.cs +++ b/MediaBrowser.Providers/Photos/PhotoProvider.cs @@ -152,11 +152,11 @@ namespace MediaBrowser.Providers.Photos get { return "Embedded Information"; } } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - if (status.ItemDateModified.HasValue) + if (item.DateModifiedDuringLastRefresh.HasValue) { - return status.ItemDateModified.Value != item.DateModified; + return item.DateModifiedDuringLastRefresh.Value != item.DateModified; } return false; diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs index 011ed9ed0..d1cdc717e 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs @@ -332,7 +332,7 @@ namespace MediaBrowser.Providers.TV }); } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { if (!TvdbSeriesProvider.Current.GetTvDbOptions().EnableAutomaticUpdates) { @@ -346,7 +346,7 @@ namespace MediaBrowser.Providers.TV var fileInfo = _fileSystem.GetFileInfo(imagesXmlPath); - return fileInfo.Exists && _fileSystem.GetLastWriteTimeUtc(fileInfo) > (status.DateLastMetadataRefresh ?? DateTime.MinValue); + return fileInfo.Exists && _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed; } return false; diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelImageProvider.cs b/MediaBrowser.Server.Implementations/Channels/ChannelImageProvider.cs index f13c71c6d..c98f71ce2 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelImageProvider.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.Channels return ((ChannelManager)_channelManager).GetChannelProvider(channel); } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { return GetSupportedImages(item).Any(i => !item.HasImage(i)); } diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index a206c1925..c9956c68a 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -1406,7 +1406,8 @@ namespace MediaBrowser.Server.Implementations.Channels throw new ArgumentNullException("channel"); } - var result = GetAllChannels().FirstOrDefault(i => string.Equals(GetInternalChannelId(i.Name).ToString("N"), channel.ChannelId, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, channel.Name, StringComparison.OrdinalIgnoreCase)); + var result = GetAllChannels() + .FirstOrDefault(i => string.Equals(GetInternalChannelId(i.Name).ToString("N"), channel.ChannelId, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, channel.Name, StringComparison.OrdinalIgnoreCase)); if (result == null) { diff --git a/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs index 24d38a63e..dccc7aa93 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs @@ -77,7 +77,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv get { return 0; } } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { return GetSupportedImages(item).Any(i => !item.HasImage(i)); } diff --git a/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs index ab8ec720b..3f0538bd0 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs @@ -74,7 +74,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv } } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { var liveTvItem = item as LiveTvProgram; diff --git a/MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs index fce3223ea..25678c29d 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs @@ -68,7 +68,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv get { return 0; } } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { var liveTvItem = item as ILiveTvRecording; diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index b6699d164..a30ff66df 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -223,6 +223,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(Logger, "TypedBaseItems", "TrailerTypes", "Text"); _connection.AddColumn(Logger, "TypedBaseItems", "CriticRating", "Float"); _connection.AddColumn(Logger, "TypedBaseItems", "CriticRatingSummary", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "DateModifiedDuringLastRefresh", "DATETIME"); PrepareStatements(); @@ -355,7 +356,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "Studios", "Tags", "SourceType", - "TrailerTypes" + "TrailerTypes", + "DateModifiedDuringLastRefresh" }; private readonly string[] _mediaStreamSaveColumns = @@ -459,7 +461,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "SourceType", "TrailerTypes", "CriticRating", - "CriticRatingSummary" + "CriticRatingSummary", + "DateModifiedDuringLastRefresh" }; _saveItemCommand = _connection.CreateCommand(); _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -752,7 +755,16 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = item.CriticRating; _saveItemCommand.GetParameter(index++).Value = item.CriticRatingSummary; - + + if (!item.DateModifiedDuringLastRefresh.HasValue || item.DateModifiedDuringLastRefresh.Value == default(DateTime)) + { + _saveItemCommand.GetParameter(index++).Value = null; + } + else + { + _saveItemCommand.GetParameter(index++).Value = item.DateModifiedDuringLastRefresh.Value; + } + _saveItemCommand.Transaction = transaction; _saveItemCommand.ExecuteNonQuery(); @@ -1125,6 +1137,11 @@ namespace MediaBrowser.Server.Implementations.Persistence } } + if (!reader.IsDBNull(51)) + { + item.DateModifiedDuringLastRefresh = reader.GetDateTime(51).ToUniversalTime(); + } + return item; } -- cgit v1.2.3 From a95cbac07610ec2ac4e10676bd97615a443eddf3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 8 Apr 2016 22:30:22 -0400 Subject: update detail screen --- MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs | 2 +- Nuget/MediaBrowser.Common.Internal.nuspec | 4 ++-- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Model.Signed.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 2c0257c5f..13a06afc2 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -251,7 +251,7 @@ namespace MediaBrowser.Server.Implementations.IO /// path private static bool ContainsParentFolder(IEnumerable lst, string path) { - if (string.IsNullOrEmpty(path)) + if (string.IsNullOrWhiteSpace(path)) { throw new ArgumentNullException("path"); } diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 10a898785..0ae08c4ad 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.644 + 3.0.645 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption. Copyright © Emby 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 616f0ca2a..b9bce00d0 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.644 + 3.0.645 MediaBrowser.Common Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec index d17ff16b6..3af1b91e2 100644 --- a/Nuget/MediaBrowser.Model.Signed.nuspec +++ b/Nuget/MediaBrowser.Model.Signed.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Model.Signed - 3.0.644 + 3.0.645 MediaBrowser.Model - Signed Edition Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 2098bbcfe..d48b421c5 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.644 + 3.0.645 Media Browser.Server.Core Emby Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Emby Server. Copyright © Emby 2013 - + -- cgit v1.2.3 From 2ec515027fe8fc14a4e91a4e991e19fa3cd3590b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 9 Apr 2016 00:16:53 -0400 Subject: update DisplayParent --- .../Channels/ChannelAudioItem.cs | 101 ----------------- .../Channels/ChannelFolderItem.cs | 89 --------------- .../Channels/ChannelVideoItem.cs | 126 --------------------- MediaBrowser.Controller/Entities/BaseItem.cs | 29 ++++- MediaBrowser.Controller/Entities/IHasTrailers.cs | 12 +- MediaBrowser.Controller/Entities/Movies/Movie.cs | 11 -- MediaBrowser.Controller/Entities/TV/Episode.cs | 4 +- MediaBrowser.Controller/Entities/TV/Season.cs | 8 +- .../MediaBrowser.Controller.csproj | 3 - MediaBrowser.Dlna/Didl/DidlBuilder.cs | 28 +++-- .../Dto/DtoService.cs | 6 +- 11 files changed, 67 insertions(+), 350 deletions(-) delete mode 100644 MediaBrowser.Controller/Channels/ChannelAudioItem.cs delete mode 100644 MediaBrowser.Controller/Channels/ChannelFolderItem.cs delete mode 100644 MediaBrowser.Controller/Channels/ChannelVideoItem.cs (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs deleted file mode 100644 index 41e9dd203..000000000 --- a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs +++ /dev/null @@ -1,101 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Model.Channels; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; -using System.Threading; - -namespace MediaBrowser.Controller.Channels -{ - public class ChannelAudioItem : Audio - { - public ChannelMediaContentType ContentType { get; set; } - - public List ChannelMediaSources { get; set; } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.ChannelContent; - } - - protected override string CreateUserDataKey() - { - return ExternalId; - } - - [IgnoreDataMember] - public override bool SupportsLocalMetadata - { - get - { - return false; - } - } - - public override bool IsSaveLocalMetadataEnabled() - { - return false; - } - - public ChannelAudioItem() - { - ChannelMediaSources = new List(); - } - - [IgnoreDataMember] - public override LocationType LocationType - { - get - { - if (string.IsNullOrEmpty(Path)) - { - return LocationType.Remote; - } - - return base.LocationType; - } - } - - protected override string GetInternalMetadataPath(string basePath) - { - return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N")); - } - - public override IEnumerable GetMediaSources(bool enablePathSubstitution) - { - var sources = ChannelManager.GetStaticMediaSources(this, false, CancellationToken.None) - .Result.ToList(); - - if (sources.Count > 0) - { - return sources; - } - - var list = base.GetMediaSources(enablePathSubstitution).ToList(); - - foreach (var mediaSource in list) - { - if (string.IsNullOrWhiteSpace(mediaSource.Path)) - { - mediaSource.Type = MediaSourceType.Placeholder; - } - } - - return list; - } - - public override bool CanDelete() - { - return false; - } - - public override bool IsVisibleStandalone(User user) - { - return IsVisibleStandaloneInternal(user, false) && ChannelVideoItem.IsChannelVisible(this, user); - } - } -} diff --git a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs deleted file mode 100644 index 62e0d694e..000000000 --- a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs +++ /dev/null @@ -1,89 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.Channels; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Users; -using System; -using System.Runtime.Serialization; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.Configuration; - -namespace MediaBrowser.Controller.Channels -{ - public class ChannelFolderItem : Folder - { - public ChannelFolderType ChannelFolderType { get; set; } - - protected override bool GetBlockUnratedValue(UserPolicy config) - { - // Don't block. - return false; - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.ChannelContent; - } - - [IgnoreDataMember] - public override bool SupportsLocalMetadata - { - get - { - return false; - } - } - - public override bool IsSaveLocalMetadataEnabled() - { - return false; - } - - protected override string CreateUserDataKey() - { - return ExternalId; - } - - protected override async Task> GetItemsInternal(InternalItemsQuery query) - { - try - { - // Don't blow up here because it could cause parent screens with other content to fail - return await ChannelManager.GetChannelItemsInternal(new ChannelItemQuery - { - ChannelId = ChannelId, - FolderId = Id.ToString("N"), - Limit = query.Limit, - StartIndex = query.StartIndex, - UserId = query.User.Id.ToString("N"), - SortBy = query.SortBy, - SortOrder = query.SortOrder - - }, new Progress(), CancellationToken.None); - } - catch - { - // Already logged at lower levels - return new QueryResult - { - - }; - } - } - - protected override string GetInternalMetadataPath(string basePath) - { - return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N")); - } - - public override bool CanDelete() - { - return false; - } - - public override bool IsVisibleStandalone(User user) - { - return IsVisibleStandaloneInternal(user, false) && ChannelVideoItem.IsChannelVisible(this, user); - } - } -} diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs deleted file mode 100644 index 9fe04812e..000000000 --- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs +++ /dev/null @@ -1,126 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.Channels; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Runtime.Serialization; -using System.Threading; - -namespace MediaBrowser.Controller.Channels -{ - public class ChannelVideoItem : Video - { - public ChannelMediaContentType ContentType { get; set; } - - public List ChannelMediaSources { get; set; } - - protected override string CreateUserDataKey() - { - if (ContentType == ChannelMediaContentType.MovieExtra) - { - var key = this.GetProviderId(MetadataProviders.Imdb) ?? this.GetProviderId(MetadataProviders.Tmdb); - - if (!string.IsNullOrWhiteSpace(key)) - { - key = key + "-" + ExtraType.ToString().ToLower(); - - // Make sure different trailers have their own data. - if (RunTimeTicks.HasValue) - { - key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture); - } - - return key; - } - } - - return ExternalId; - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.ChannelContent; - } - - [IgnoreDataMember] - public override bool SupportsLocalMetadata - { - get - { - return false; - } - } - - public override bool IsSaveLocalMetadataEnabled() - { - return false; - } - - public ChannelVideoItem() - { - ChannelMediaSources = new List(); - } - - [IgnoreDataMember] - public override LocationType LocationType - { - get - { - if (string.IsNullOrEmpty(Path)) - { - return LocationType.Remote; - } - - return base.LocationType; - } - } - - public override IEnumerable GetMediaSources(bool enablePathSubstitution) - { - var sources = ChannelManager.GetStaticMediaSources(this, false, CancellationToken.None) - .Result.ToList(); - - if (sources.Count > 0) - { - return sources; - } - - var list = base.GetMediaSources(enablePathSubstitution).ToList(); - - foreach (var mediaSource in list) - { - if (string.IsNullOrWhiteSpace(mediaSource.Path)) - { - mediaSource.Type = MediaSourceType.Placeholder; - } - } - - return list; - } - - protected override string GetInternalMetadataPath(string basePath) - { - return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N")); - } - - public override bool CanDelete() - { - return false; - } - - public override bool IsVisibleStandalone(User user) - { - return IsVisibleStandaloneInternal(user, false) && IsChannelVisible(this, user); - } - - internal static bool IsChannelVisible(BaseItem item, User user) - { - var channel = ChannelManager.GetChannel(item.ChannelId); - - return channel.IsVisible(user); - } - } -} diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 29f416b8c..26aae285d 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -306,7 +306,7 @@ namespace MediaBrowser.Controller.Entities } } - private List> GetSortChunks(string s1) + private List> GetSortChunks(string s1) { var list = new List>(); @@ -668,9 +668,30 @@ namespace MediaBrowser.Controller.Entities } [IgnoreDataMember] - public virtual BaseItem DisplayParent + public virtual Guid? DisplayParentId { - get { return GetParent(); } + get + { + if (ParentId == Guid.Empty) + { + return null; + } + return ParentId; + } + } + + [IgnoreDataMember] + public BaseItem DisplayParent + { + get + { + var id = DisplayParentId; + if (!id.HasValue) + { + return null; + } + return LibraryManager.GetItemById(id.Value); + } } /// @@ -1454,7 +1475,7 @@ namespace MediaBrowser.Controller.Entities public virtual string GetClientTypeName() { - if (IsFolder && SourceType == SourceType.Channel) + if (IsFolder && SourceType == SourceType.Channel && !(this is Channel)) { return "ChannelFolderItem"; } diff --git a/MediaBrowser.Controller/Entities/IHasTrailers.cs b/MediaBrowser.Controller/Entities/IHasTrailers.cs index bc1c7d875..e5cbdff72 100644 --- a/MediaBrowser.Controller/Entities/IHasTrailers.cs +++ b/MediaBrowser.Controller/Entities/IHasTrailers.cs @@ -1,6 +1,7 @@ using MediaBrowser.Model.Entities; using System; using System.Collections.Generic; +using System.Linq; namespace MediaBrowser.Controller.Entities { @@ -18,11 +19,20 @@ namespace MediaBrowser.Controller.Entities /// The local trailer ids. List LocalTrailerIds { get; set; } List RemoteTrailerIds { get; set; } + } + public static class HasTrailerExtensions + { /// /// Gets the trailer ids. /// /// List<Guid>. - List GetTrailerIds(); + public static List GetTrailerIds(this IHasTrailers item) + { + var list = item.LocalTrailerIds.ToList(); + list.AddRange(item.RemoteTrailerIds); + return list; + } + } } diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index f5c2a9935..4d2ca9ffe 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -78,17 +78,6 @@ namespace MediaBrowser.Controller.Entities.Movies set { TmdbCollectionName = value; } } - /// - /// Gets the trailer ids. - /// - /// List<Guid>. - public List GetTrailerIds() - { - var list = LocalTrailerIds.ToList(); - list.AddRange(RemoteTrailerIds); - return list; - } - /// /// Gets the user data key. /// diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index d016392e8..ec65221bc 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -90,11 +90,11 @@ namespace MediaBrowser.Controller.Entities.TV } [IgnoreDataMember] - public override BaseItem DisplayParent + public override Guid? DisplayParentId { get { - return Season ?? GetParent(); + return SeasonId; } } diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 5e067afd4..acd02e8ab 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -33,9 +33,13 @@ namespace MediaBrowser.Controller.Entities.TV } [IgnoreDataMember] - public override BaseItem DisplayParent + public override Guid? DisplayParentId { - get { return Series ?? GetParent(); } + get + { + var series = Series; + return series == null ? ParentId : series.Id; + } } // Genre, Rating and Stuido will all be the same diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 235638b5f..6ff4e39e2 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -75,15 +75,12 @@ - - - diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index ba42a06e2..89d00eb32 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -93,10 +93,10 @@ namespace MediaBrowser.Dlna.Didl } else { - var parent = item.DisplayParent; - if (parent != null) + var parent = item.DisplayParentId; + if (parent.HasValue) { - element.SetAttribute("parentID", GetClientId(parent, null)); + element.SetAttribute("parentID", GetClientId(parent.Value, null)); } } @@ -499,14 +499,21 @@ namespace MediaBrowser.Dlna.Didl { container.SetAttribute("id", clientId); - var parent = context ?? folder.DisplayParent; - if (parent == null) + if (context != null) { - container.SetAttribute("parentID", "0"); + container.SetAttribute("parentID", GetClientId(context, null)); } else { - container.SetAttribute("parentID", GetClientId(parent, null)); + var parent = folder.DisplayParentId; + if (!parent.HasValue) + { + container.SetAttribute("parentID", "0"); + } + else + { + container.SetAttribute("parentID", GetClientId(parent.Value, null)); + } } } @@ -1059,7 +1066,12 @@ namespace MediaBrowser.Dlna.Didl public static string GetClientId(BaseItem item, StubType? stubType) { - var id = item.Id.ToString("N"); + return GetClientId(item.Id, stubType); + } + + public static string GetClientId(Guid idValue, StubType? stubType) + { + var id = idValue.ToString("N"); if (stubType.HasValue) { diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 234e15a66..50ae19580 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1149,10 +1149,10 @@ namespace MediaBrowser.Server.Implementations.Dto if (fields.Contains(ItemFields.ParentId)) { - var displayParent = item.DisplayParent; - if (displayParent != null) + var displayParentId = item.DisplayParentId; + if (displayParentId.HasValue) { - dto.ParentId = GetDtoId(displayParent); + dto.ParentId = displayParentId.Value.ToString("N"); } } -- cgit v1.2.3 From 4ac4e4a0f5d224b7eeecad2002f96b088315597f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 9 Apr 2016 17:16:17 -0400 Subject: update components --- .../EntryPoints/Notifications/Notifications.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs index 9e68ce4ef..c7a5e3b18 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs @@ -335,12 +335,17 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications private bool FilterItem(BaseItem item) { - if (!item.IsFolder && item.LocationType == LocationType.Virtual) + if (item.IsFolder) { return false; } - if (item is IItemByName && !(item is MusicArtist)) + if (item.LocationType == LocationType.Virtual) + { + return false; + } + + if (item is IItemByName) { return false; } -- cgit v1.2.3 From 3d1c950de8eaa7292ab87f29c9cdb27bbdf18d0e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 10 Apr 2016 17:11:06 -0400 Subject: improve connect error messages --- .../Connect/ConnectManager.cs | 20 +++++++++++++++++--- .../MediaBrowser.WebDashboard.csproj | 3 --- 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs index e308acef0..f3d545492 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs @@ -24,6 +24,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Common.Extensions; namespace MediaBrowser.Server.Implementations.Connect { @@ -555,9 +556,22 @@ namespace MediaBrowser.Server.Implementations.Connect } catch (HttpException ex) { - if (!ex.StatusCode.HasValue || - ex.StatusCode.Value != HttpStatusCode.NotFound || - !Validator.EmailIsValid(connectUsername)) + if (!ex.StatusCode.HasValue) + { + throw; + } + + // If they entered a username, then whatever the error is just throw it, for example, user not found + if (!Validator.EmailIsValid(connectUsername)) + { + if (ex.StatusCode.Value == HttpStatusCode.NotFound) + { + throw new ResourceNotFoundException(); + } + throw; + } + + if (ex.StatusCode.Value != HttpStatusCode.NotFound) { throw; } diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 122176fac..70b19f971 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -1688,9 +1688,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest -- cgit v1.2.3 From 5c8bd5559d2b8706c423c81918ec42c7dc8a5550 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 11 Apr 2016 10:26:54 -0400 Subject: trim search requests --- MediaBrowser.Server.Implementations/Library/SearchEngine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs index 276fc329f..61a5d98a3 100644 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs @@ -92,7 +92,7 @@ namespace MediaBrowser.Server.Implementations.Library throw new ArgumentNullException("searchTerm"); } - searchTerm = searchTerm.RemoveDiacritics(); + searchTerm = searchTerm.Trim().RemoveDiacritics(); var terms = GetWords(searchTerm); -- cgit v1.2.3 From 5bddb226f6ad3e42c3c32199684c4382d8e1661d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 12 Apr 2016 13:37:58 -0400 Subject: update hdhr stream --- MediaBrowser.Model/Dlna/StreamBuilder.cs | 4 ++++ .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index d28e21bf2..6bb2a9f82 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -509,6 +509,10 @@ namespace MediaBrowser.Model.Dlna private int GetAudioBitrate(int? maxTotalBitrate, int? targetAudioChannels, string targetAudioCodec, MediaStream audioStream) { var defaultBitrate = 128000; + if (StringHelper.EqualsIgnoreCase(targetAudioCodec, "ac3")) + { + defaultBitrate = 192000; + } if (targetAudioChannels.HasValue) { diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 3c1e4af36..638b4b9af 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -354,8 +354,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun BufferMs = 0, Container = "ts", Id = profile, - SupportsDirectPlay = true, - SupportsDirectStream = true, + SupportsDirectPlay = false, + SupportsDirectStream = false, SupportsTranscoding = true }; -- cgit v1.2.3 From 41ee4600fd2b5af9732b363790d6b0f44dc272e5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 13 Apr 2016 12:17:52 -0400 Subject: fix tabs --- MediaBrowser.Api/TvShowsService.cs | 22 ++++++++++++++++++++-- .../EntryPoints/Notifications/Notifications.cs | 13 +++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 5b5b0a902..3c32232ac 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -123,7 +123,7 @@ namespace MediaBrowser.Api } [Route("/Shows/{Id}/Episodes", "GET", Summary = "Gets episodes for a tv season")] - public class GetEpisodes : IReturn, IHasItemFields + public class GetEpisodes : IReturn, IHasItemFields, IHasDtoOptions { /// /// Gets or sets the user id. @@ -173,10 +173,19 @@ namespace MediaBrowser.Api /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? Limit { get; set; } + + [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] + public bool? EnableImages { get; set; } + + [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? ImageTypeLimit { get; set; } + + [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string EnableImageTypes { get; set; } } [Route("/Shows/{Id}/Seasons", "GET", Summary = "Gets seasons for a tv series")] - public class GetSeasons : IReturn, IHasItemFields + public class GetSeasons : IReturn, IHasItemFields, IHasDtoOptions { /// /// Gets or sets the user id. @@ -206,6 +215,15 @@ namespace MediaBrowser.Api [ApiMember(Name = "AdjacentTo", Description = "Optional. Return items that are siblings of a supplied item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string AdjacentTo { get; set; } + + [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] + public bool? EnableImages { get; set; } + + [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? ImageTypeLimit { get; set; } + + [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string EnableImageTypes { get; set; } } /// diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs index c7a5e3b18..71019e0ad 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs @@ -22,6 +22,7 @@ using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Controller.Entities.TV; namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications { @@ -393,6 +394,18 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications public static string GetItemName(BaseItem item) { var name = item.Name; + var episode = item as Episode; + if (episode != null) + { + if (episode.IndexNumber.HasValue) + { + name = string.Format("Ep{0} - {1}", episode.IndexNumber.Value.ToString(CultureInfo.InvariantCulture), name); + } + if (episode.ParentIndexNumber.HasValue) + { + name = string.Format("S{0}, {1}", episode.ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture), name); + } + } var hasSeries = item as IHasSeries; -- cgit v1.2.3 From 57e3bb72f93baca695ba2b6670faec8ee0e1796b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 14 Apr 2016 15:12:00 -0400 Subject: update stream selection --- MediaBrowser.Api/Playback/Hls/VideoHlsService.cs | 7 +++---- MediaBrowser.Api/Playback/MediaInfoService.cs | 21 +++++++++++++++++++-- MediaBrowser.Model/Dlna/StreamBuilder.cs | 10 +++++----- MediaBrowser.Model/Dlna/StreamInfoSorter.cs | 19 ++++++++++++++++++- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 4 +++- 5 files changed, 48 insertions(+), 13 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 610628ced..5f427146e 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -86,11 +86,10 @@ namespace MediaBrowser.Api.Playback.Hls // See if we can save come cpu cycles by avoiding encoding if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase)) { - return state.VideoStream != null && IsH264(state.VideoStream) ? - args + " -bsf:v h264_mp4toannexb" : - args; + // if h264_mp4toannexb is ever added, do not use it for live tv + return args; } - + var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"", state.SegmentLength.ToString(UsCulture)); diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 2bf61f90b..ffe7c50c8 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -227,7 +227,7 @@ namespace MediaBrowser.Api.Playback SetDeviceSpecificData(item, mediaSource, profile, auth, maxBitrate, startTimeTicks, mediaSourceId, audioStreamIndex, subtitleStreamIndex, result.PlaySessionId); } - SortMediaSources(result); + SortMediaSources(result, maxBitrate); } private void SetDeviceSpecificData(BaseItem item, @@ -375,7 +375,7 @@ namespace MediaBrowser.Api.Playback } } - private void SortMediaSources(PlaybackInfoResponse result) + private void SortMediaSources(PlaybackInfoResponse result, int? maxBitrate) { var originalList = result.MediaSources.ToList(); @@ -409,6 +409,23 @@ namespace MediaBrowser.Api.Playback return 1; } + }).ThenBy(i => + { + if (maxBitrate.HasValue) + { + if (i.Bitrate.HasValue) + { + if (i.Bitrate.Value <= maxBitrate.Value) + { + return 0; + } + + return 2; + } + } + + return 1; + }).ThenBy(originalList.IndexOf) .ToList(); } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 09d762aae..1e6b7c729 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -55,7 +55,7 @@ namespace MediaBrowser.Model.Dlna stream.DeviceProfileId = options.Profile.Id; } - return GetOptimalStream(streams); + return GetOptimalStream(streams, options.GetMaxBitrate()); } public StreamInfo BuildVideoItem(VideoOptions options) @@ -88,12 +88,12 @@ namespace MediaBrowser.Model.Dlna stream.DeviceProfileId = options.Profile.Id; } - return GetOptimalStream(streams); + return GetOptimalStream(streams, options.GetMaxBitrate()); } - private StreamInfo GetOptimalStream(List streams) + private StreamInfo GetOptimalStream(List streams, int? maxBitrate) { - streams = StreamInfoSorter.SortMediaSources(streams); + streams = StreamInfoSorter.SortMediaSources(streams, maxBitrate); foreach (StreamInfo stream in streams) { @@ -424,7 +424,7 @@ namespace MediaBrowser.Model.Dlna playlistItem.EstimateContentLength = transcodingProfile.EstimateContentLength; playlistItem.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo; - // TODO: We should probably preserve the full list and sent it tp the server that way + // TODO: We should probably preserve the full list and sent it to the server that way string[] supportedAudioCodecs = transcodingProfile.AudioCodec.Split(','); string inputAudioCodec = audioStream == null ? null : audioStream.Codec; foreach (string supportedAudioCodec in supportedAudioCodecs) diff --git a/MediaBrowser.Model/Dlna/StreamInfoSorter.cs b/MediaBrowser.Model/Dlna/StreamInfoSorter.cs index 0cccd8080..293054e5b 100644 --- a/MediaBrowser.Model/Dlna/StreamInfoSorter.cs +++ b/MediaBrowser.Model/Dlna/StreamInfoSorter.cs @@ -7,7 +7,7 @@ namespace MediaBrowser.Model.Dlna { public class StreamInfoSorter { - public static List SortMediaSources(List streams) + public static List SortMediaSources(List streams, int? maxBitrate) { return streams.OrderBy(i => { @@ -41,6 +41,23 @@ namespace MediaBrowser.Model.Dlna return 1; } + }).ThenBy(i => + { + if (maxBitrate.HasValue) + { + if (i.MediaSource.Bitrate.HasValue) + { + if (i.MediaSource.Bitrate.Value <= maxBitrate.Value) + { + return 0; + } + + return 2; + } + } + + return 1; + }).ToList(); } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 638b4b9af..3499fad41 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -246,6 +246,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun string audioCodec = "ac3"; int? videoBitrate = null; + int? audioBitrate = null; if (string.Equals(profile, "mobile", StringComparison.OrdinalIgnoreCase)) { @@ -306,6 +307,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun audioCodec = channel.AudioCodec; videoBitrate = (channel.IsHD ?? true) ? 15000000 : 2000000; + audioBitrate = (channel.IsHD ?? true) ? 448000 : 192000; } } @@ -346,7 +348,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun // Set the index to -1 because we don't know the exact index of the audio stream within the container Index = -1, Codec = audioCodec, - BitRate = 192000 + BitRate = audioBitrate } }, RequiresOpening = false, -- cgit v1.2.3 From 7f2b2e1b9aa5011413c6f9dc1098d547ea415fde Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 14 Apr 2016 22:39:39 -0400 Subject: fix block by inherited tags --- MediaBrowser.Controller/Entities/BaseItem.cs | 18 +++ .../Entities/InternalItemsQuery.cs | 4 +- .../Persistence/SqliteItemRepository.cs | 129 ++++++++++++++++++++- 3 files changed, 144 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 438c5cf23..6a3f3ba19 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1348,6 +1348,24 @@ namespace MediaBrowser.Controller.Entities return LocalizationManager.GetRatingLevel(rating); } + public List GetInheritedTags() + { + var list = new List(); + list.AddRange(Tags); + + foreach (var parent in GetParents()) + { + list.AddRange(parent.Tags); + } + + foreach (var parent in LibraryManager.GetCollectionFolders(this)) + { + list.AddRange(parent.Tags); + } + + return list.Distinct(StringComparer.OrdinalIgnoreCase).ToList(); + } + private bool IsVisibleViaTags(User user) { var hasTags = this as IHasTags; diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index b568aec18..fbf246b3a 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -33,6 +33,7 @@ namespace MediaBrowser.Controller.Entities public string[] IncludeItemTypes { get; set; } public string[] ExcludeItemTypes { get; set; } public string[] ExcludeTags { get; set; } + public string[] ExcludeInheritedTags { get; set; } public string[] Genres { get; set; } public bool? IsMissing { get; set; } @@ -157,6 +158,7 @@ namespace MediaBrowser.Controller.Entities AncestorIds = new string[] { }; TopParentIds = new string[] { }; ExcludeTags = new string[] { }; + ExcludeInheritedTags = new string[] { }; LocationTypes = new LocationType[] { }; ExcludeLocationTypes = new LocationType[] { }; PresetViews = new string[] { }; @@ -181,7 +183,7 @@ namespace MediaBrowser.Controller.Entities BlockUnratedItems = policy.BlockUnratedItems; } - ExcludeTags = policy.BlockedTags; + ExcludeInheritedTags = policy.BlockedTags; User = user; } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index a30ff66df..4a784e253 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -78,8 +78,9 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _saveAncestorCommand; private IDbCommand _updateInheritedRatingCommand; + private IDbCommand _updateInheritedTagsCommand; - private const int LatestSchemaVersion = 58; + private const int LatestSchemaVersion = 61; /// /// Initializes a new instance of the class. @@ -135,7 +136,7 @@ namespace MediaBrowser.Server.Implementations.Persistence "create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, AncestorIdText TEXT, PRIMARY KEY (ItemId, AncestorId))", "create index if not exists idx_AncestorIds1 on AncestorIds(AncestorId)", "create index if not exists idx_AncestorIds2 on AncestorIds(AncestorIdText)", - + "create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)", "create index if not exists idxPeopleItemId on People(ItemId)", "create index if not exists idxPeopleName on People(Name)", @@ -224,6 +225,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(Logger, "TypedBaseItems", "CriticRating", "Float"); _connection.AddColumn(Logger, "TypedBaseItems", "CriticRatingSummary", "Text"); _connection.AddColumn(Logger, "TypedBaseItems", "DateModifiedDuringLastRefresh", "DATETIME"); + _connection.AddColumn(Logger, "TypedBaseItems", "InheritedTags", "Text"); PrepareStatements(); @@ -402,7 +404,7 @@ namespace MediaBrowser.Server.Implementations.Persistence "guid", "type", "data", - "Path", + "Path", "StartDate", "EndDate", "ChannelId", @@ -462,7 +464,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "TrailerTypes", "CriticRating", "CriticRatingSummary", - "DateModifiedDuringLastRefresh" + "DateModifiedDuringLastRefresh", + "InheritedTags" }; _saveItemCommand = _connection.CreateCommand(); _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -540,8 +543,13 @@ namespace MediaBrowser.Server.Implementations.Persistence _updateInheritedRatingCommand = _connection.CreateCommand(); _updateInheritedRatingCommand.CommandText = "Update TypedBaseItems set InheritedParentalRatingValue=@InheritedParentalRatingValue where Guid=@Guid"; - _updateInheritedRatingCommand.Parameters.Add(_updateInheritedRatingCommand, "@InheritedParentalRatingValue"); _updateInheritedRatingCommand.Parameters.Add(_updateInheritedRatingCommand, "@Guid"); + _updateInheritedRatingCommand.Parameters.Add(_updateInheritedRatingCommand, "@InheritedParentalRatingValue"); + + _updateInheritedTagsCommand = _connection.CreateCommand(); + _updateInheritedTagsCommand.CommandText = "Update TypedBaseItems set InheritedTags=@InheritedTags where Guid=@Guid"; + _updateInheritedTagsCommand.Parameters.Add(_updateInheritedTagsCommand, "@Guid"); + _updateInheritedTagsCommand.Parameters.Add(_updateInheritedTagsCommand, "@InheritedTags"); } /// @@ -715,7 +723,15 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = item.ServiceName; - _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Tags.ToArray()); + if (item.Tags.Count > 0) + { + _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Tags.ToArray()); + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } + _saveItemCommand.GetParameter(index++).Value = item.IsFolder; _saveItemCommand.GetParameter(index++).Value = item.GetBlockUnratedType().ToString(); @@ -765,6 +781,16 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = item.DateModifiedDuringLastRefresh.Value; } + var inheritedTags = item.GetInheritedTags(); + if (inheritedTags.Count > 0) + { + _saveItemCommand.GetParameter(index++).Value = string.Join("|", inheritedTags.ToArray()); + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } + _saveItemCommand.Transaction = transaction; _saveItemCommand.ExecuteNonQuery(); @@ -2165,6 +2191,14 @@ namespace MediaBrowser.Server.Implementations.Persistence excludeTagIndex++; } + excludeTagIndex = 0; + foreach (var excludeTag in query.ExcludeInheritedTags) + { + whereClauses.Add("InheritedTags not like @excludeInheritedTag" + excludeTagIndex); + cmd.Parameters.Add(cmd, "@excludeInheritedTag" + excludeTagIndex, DbType.String).Value = "%" + excludeTag + "%"; + excludeTagIndex++; + } + if (addPaging) { if (query.StartIndex.HasValue && query.StartIndex.Value > 0) @@ -2224,6 +2258,88 @@ namespace MediaBrowser.Server.Implementations.Persistence }; public async Task UpdateInheritedValues(CancellationToken cancellationToken) + { + await UpdateInheritedParentalRating(cancellationToken).ConfigureAwait(false); + await UpdateInheritedTags(cancellationToken).ConfigureAwait(false); + } + + private async Task UpdateInheritedTags(CancellationToken cancellationToken) + { + var newValues = new List>(); + + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = "select Guid,InheritedTags,(select group_concat(Tags, '|') from TypedBaseItems where (guid=outer.guid) OR (guid in (Select AncestorId from AncestorIds where ItemId=Outer.guid))) as NewInheritedTags from typedbaseitems as Outer where NewInheritedTags <> InheritedTags"; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + var id = reader.GetGuid(0); + string value = reader.IsDBNull(2) ? null : reader.GetString(2); + + newValues.Add(new Tuple(id, value)); + } + } + } + + Logger.Debug("UpdateInheritedTags - {0} rows", newValues.Count); + if (newValues.Count == 0) + { + return; + } + + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + IDbTransaction transaction = null; + + try + { + transaction = _connection.BeginTransaction(); + + foreach (var item in newValues) + { + _updateInheritedTagsCommand.GetParameter(0).Value = item.Item1; + _updateInheritedTagsCommand.GetParameter(1).Value = item.Item2; + + _updateInheritedTagsCommand.Transaction = transaction; + _updateInheritedTagsCommand.ExecuteNonQuery(); + } + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } + + throw; + } + catch (Exception e) + { + Logger.ErrorException("Error running query:", e); + + if (transaction != null) + { + transaction.Rollback(); + } + + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); + } + + WriteLock.Release(); + } + } + + private async Task UpdateInheritedParentalRating(CancellationToken cancellationToken) { var newValues = new List>(); @@ -2243,6 +2359,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } } + Logger.Debug("UpdateInheritedParentalRatings - {0} rows", newValues.Count); if (newValues.Count == 0) { return; -- cgit v1.2.3 From bfc8facc60f919f8455d4c6c7f48a4eca17f2812 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 01:05:34 -0400 Subject: fixes #1261 - Sync quality cannot be changed --- .../Sync/SyncJobProcessor.cs | 45 +++++++++------------- .../Sync/SyncManager.cs | 8 ++-- .../Sync/SyncRepository.cs | 2 +- 3 files changed, 23 insertions(+), 32 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index 01334c121..33874b4d4 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -149,16 +149,6 @@ namespace MediaBrowser.Server.Implementations.Sync { var job = _syncRepo.GetJob(id); - return UpdateJobStatus(job); - } - - private Task UpdateJobStatus(SyncJob job) - { - if (job == null) - { - throw new ArgumentNullException("job"); - } - var result = _syncManager.GetJobItems(new SyncJobItemQuery { JobId = job.Id, @@ -476,14 +466,12 @@ namespace MediaBrowser.Server.Implementations.Sync if (jobItem != null) { - var job = _syncRepo.GetJob(jobItem.JobId); if (jobItem.Status != SyncJobItemStatus.Cancelled) { - await ProcessJobItem(job, jobItem, enableConversion, innerProgress, cancellationToken).ConfigureAwait(false); + await ProcessJobItem(jobItem, enableConversion, innerProgress, cancellationToken).ConfigureAwait(false); } - job = _syncRepo.GetJob(jobItem.JobId); - await UpdateJobStatus(job).ConfigureAwait(false); + await UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); } numComplete++; @@ -493,7 +481,7 @@ namespace MediaBrowser.Server.Implementations.Sync } } - private async Task ProcessJobItem(SyncJob job, SyncJobItem jobItem, bool enableConversion, IProgress progress, CancellationToken cancellationToken) + private async Task ProcessJobItem(SyncJobItem jobItem, bool enableConversion, IProgress progress, CancellationToken cancellationToken) { var item = _libraryManager.GetItemById(jobItem.ItemId); if (item == null) @@ -507,6 +495,7 @@ namespace MediaBrowser.Server.Implementations.Sync jobItem.Progress = 0; var syncOptions = _config.GetSyncOptions(); + var job = _syncManager.GetJob(jobItem.JobId); var user = _userManager.GetUserById(job.UserId); if (user == null) { @@ -521,7 +510,7 @@ namespace MediaBrowser.Server.Implementations.Sync { AddMetadata = false, ItemId = jobItem.ItemId, - TargetId = job.TargetId, + TargetId = jobItem.TargetId, Statuses = new[] { SyncJobItemStatus.Converting, SyncJobItemStatus.Queued, SyncJobItemStatus.ReadyToTransfer, SyncJobItemStatus.Synced, SyncJobItemStatus.Transferring } }); @@ -531,7 +520,7 @@ namespace MediaBrowser.Server.Implementations.Sync if (duplicateJobItems.Count > 0) { - var syncProvider = _syncManager.GetSyncProvider(jobItem, job) as IHasDuplicateCheck; + var syncProvider = _syncManager.GetSyncProvider(jobItem) as IHasDuplicateCheck; if (!duplicateJobItems.Any(i => AllowDuplicateJobItem(syncProvider, i, jobItem))) { @@ -545,12 +534,12 @@ namespace MediaBrowser.Server.Implementations.Sync var video = item as Video; if (video != null) { - await Sync(jobItem, job, video, user, enableConversion, syncOptions, progress, cancellationToken).ConfigureAwait(false); + await Sync(jobItem, video, user, enableConversion, syncOptions, progress, cancellationToken).ConfigureAwait(false); } else if (item is Audio) { - await Sync(jobItem, job, (Audio)item, user, enableConversion, syncOptions, progress, cancellationToken).ConfigureAwait(false); + await Sync(jobItem, (Audio)item, user, enableConversion, syncOptions, progress, cancellationToken).ConfigureAwait(false); } else if (item is Photo) @@ -574,8 +563,9 @@ namespace MediaBrowser.Server.Implementations.Sync return true; } - private async Task Sync(SyncJobItem jobItem, SyncJob job, Video item, User user, bool enableConversion, SyncOptions syncOptions, IProgress progress, CancellationToken cancellationToken) + private async Task Sync(SyncJobItem jobItem, Video item, User user, bool enableConversion, SyncOptions syncOptions, IProgress progress, CancellationToken cancellationToken) { + var job = _syncManager.GetJob(jobItem.JobId); var jobOptions = _syncManager.GetVideoOptions(jobItem, job); var conversionOptions = new VideoOptions { @@ -616,7 +606,7 @@ namespace MediaBrowser.Server.Implementations.Sync { // Save the job item now since conversion could take a while await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - await UpdateJobStatus(job).ConfigureAwait(false); + await UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); try { @@ -630,7 +620,7 @@ namespace MediaBrowser.Server.Implementations.Sync { jobItem.Progress = pct / 2; await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - await UpdateJobStatus(job).ConfigureAwait(false); + await UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); } }); @@ -642,7 +632,7 @@ namespace MediaBrowser.Server.Implementations.Sync }, innerProgress, cancellationToken); - _syncManager.OnConversionComplete(jobItem, job); + _syncManager.OnConversionComplete(jobItem); } catch (OperationCanceledException) { @@ -775,8 +765,9 @@ namespace MediaBrowser.Server.Implementations.Sync private const int DatabaseProgressUpdateIntervalSeconds = 2; - private async Task Sync(SyncJobItem jobItem, SyncJob job, Audio item, User user, bool enableConversion, SyncOptions syncOptions, IProgress progress, CancellationToken cancellationToken) + private async Task Sync(SyncJobItem jobItem, Audio item, User user, bool enableConversion, SyncOptions syncOptions, IProgress progress, CancellationToken cancellationToken) { + var job = _syncManager.GetJob(jobItem.JobId); var jobOptions = _syncManager.GetAudioOptions(jobItem, job); var conversionOptions = new AudioOptions { @@ -803,7 +794,7 @@ namespace MediaBrowser.Server.Implementations.Sync jobItem.Status = SyncJobItemStatus.Converting; await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - await UpdateJobStatus(job).ConfigureAwait(false); + await UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); try { @@ -817,7 +808,7 @@ namespace MediaBrowser.Server.Implementations.Sync { jobItem.Progress = pct / 2; await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - await UpdateJobStatus(job).ConfigureAwait(false); + await UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); } }); @@ -828,7 +819,7 @@ namespace MediaBrowser.Server.Implementations.Sync }, innerProgress, cancellationToken); - _syncManager.OnConversionComplete(jobItem, job); + _syncManager.OnConversionComplete(jobItem); } catch (OperationCanceledException) { diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index 2effad2f7..044c8b93a 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -1117,7 +1117,7 @@ namespace MediaBrowser.Server.Implementations.Sync public SyncJobOptions GetAudioOptions(SyncJobItem jobItem, SyncJob job) { var options = GetSyncJobOptions(jobItem.TargetId, null, null); - + if (job.Bitrate.HasValue) { options.DeviceProfile.MaxStaticBitrate = job.Bitrate.Value; @@ -1126,7 +1126,7 @@ namespace MediaBrowser.Server.Implementations.Sync return options; } - public ISyncProvider GetSyncProvider(SyncJobItem jobItem, SyncJob job) + public ISyncProvider GetSyncProvider(SyncJobItem jobItem) { foreach (var provider in _providers) { @@ -1323,9 +1323,9 @@ namespace MediaBrowser.Server.Implementations.Sync return list; } - protected internal void OnConversionComplete(SyncJobItem item, SyncJob job) + protected internal void OnConversionComplete(SyncJobItem item) { - var syncProvider = GetSyncProvider(item, job); + var syncProvider = GetSyncProvider(item); if (syncProvider is AppSyncProvider) { return; diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs index 39153526a..464e8aa58 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs @@ -104,7 +104,7 @@ namespace MediaBrowser.Server.Implementations.Sync // _updateJobCommand _updateJobCommand = _connection.CreateCommand(); - _updateJobCommand.CommandText = "update SyncJobs set TargetId=@TargetId,Name=@Name,Profile=@Profile,Quality=@Quality,Bitrate=@Bitrate,Status=@Status,Progress=@Progress,UserId=@UserId,ItemIds=@ItemIds,Category=@Category,ParentId=@ParentId,UnwatchedOnly=@UnwatchedOnly,ItemLimit=@ItemLimit,SyncNewContent=@SyncNewContent,DateCreated=@DateCreated,DateLastModified=@DateLastModified,ItemCount=@ItemCount where Id=@ID"; + _updateJobCommand.CommandText = "update SyncJobs set TargetId=@TargetId,Name=@Name,Profile=@Profile,Quality=@Quality,Bitrate=@Bitrate,Status=@Status,Progress=@Progress,UserId=@UserId,ItemIds=@ItemIds,Category=@Category,ParentId=@ParentId,UnwatchedOnly=@UnwatchedOnly,ItemLimit=@ItemLimit,SyncNewContent=@SyncNewContent,DateCreated=@DateCreated,DateLastModified=@DateLastModified,ItemCount=@ItemCount where Id=@Id"; _updateJobCommand.Parameters.Add(_updateJobCommand, "@Id"); _updateJobCommand.Parameters.Add(_updateJobCommand, "@TargetId"); -- cgit v1.2.3 From d1b3342e75f61b27f0cb9a8457b6e5ba9b86821c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 01:09:58 -0400 Subject: update inherited tags --- MediaBrowser.Controller/Entities/BaseItem.cs | 5 ----- .../Persistence/SqliteItemRepository.cs | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 6a3f3ba19..04371c13b 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1358,11 +1358,6 @@ namespace MediaBrowser.Controller.Entities list.AddRange(parent.Tags); } - foreach (var parent in LibraryManager.GetCollectionFolders(this)) - { - list.AddRange(parent.Tags); - } - return list.Distinct(StringComparer.OrdinalIgnoreCase).ToList(); } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 4a784e253..212be2849 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - private const int LatestSchemaVersion = 61; + private const int LatestSchemaVersion = 62; /// /// Initializes a new instance of the class. -- cgit v1.2.3 From cf4a14357ef8c602dd6dbfc0d8e9737ae0badaaa Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 13:19:20 -0400 Subject: restore hdhr direct play for now --- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 3499fad41..4c140602d 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -356,7 +356,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun BufferMs = 0, Container = "ts", Id = profile, - SupportsDirectPlay = false, + SupportsDirectPlay = true, SupportsDirectStream = false, SupportsTranscoding = true }; -- cgit v1.2.3 From 4c64c42876d06fa8ea71d2a64494d74d737936bd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 13:24:00 -0400 Subject: update translations --- .../Localization/Core/ca.json | 10 +- .../Localization/Core/es.json | 142 ++++++++++----------- .../Localization/Core/hu.json | 4 +- .../Localization/Core/nl.json | 2 +- .../Localization/Core/ru.json | 16 +-- .../Localization/Core/sv.json | 78 +++++------ .../Localization/Core/zh-TW.json | 18 +-- 7 files changed, 135 insertions(+), 135 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ca.json b/MediaBrowser.Server.Implementations/Localization/Core/ca.json index 7cec213d3..7ca8e1553 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/ca.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/ca.json @@ -1,5 +1,5 @@ { - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", + "DbUpgradeMessage": "Si et plau espera mentre la teva base de dades del Servidor Emby \u00e9s actualitzada. {0}% completat.", "AppDeviceValues": "App: {0}, Dispositiu: {1}", "UserDownloadingItemWithValues": "{0} est\u00e0 descarregant {1}", "FolderTypeMixed": "Contingut barrejat", @@ -19,11 +19,11 @@ "LabelChapterName": "Cap\u00edtol {0}", "NameSeasonNumber": "Temporada {0}", "LabelExit": "Sortir", - "LabelVisitCommunity": "Visita la comunitat", + "LabelVisitCommunity": "Visita la Comunitat", "LabelGithub": "Github", "LabelApiDocumentation": "Documentaci\u00f3 de l'API", - "LabelDeveloperResources": "Recursos per a programadors", - "LabelBrowseLibrary": "Examina la biblioteca", + "LabelDeveloperResources": "Recursos per a Desenvolupadors", + "LabelBrowseLibrary": "Examina la Biblioteca", "LabelConfigureServer": "Configura Emby", "LabelRestartServer": "Reiniciar Servidor", "CategorySync": "Sync", @@ -131,7 +131,7 @@ "HeaderType": "Type", "HeaderSeverity": "Severity", "HeaderUser": "Usuari", - "HeaderName": "Name", + "HeaderName": "Nom", "HeaderDate": "Data", "HeaderPremiereDate": "Premiere Date", "HeaderDateAdded": "Data afegida", diff --git a/MediaBrowser.Server.Implementations/Localization/Core/es.json b/MediaBrowser.Server.Implementations/Localization/Core/es.json index 2a715a5b3..d1a56240d 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/es.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/es.json @@ -1,7 +1,7 @@ { - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", + "DbUpgradeMessage": "Por favor espere mientras la base de datos de su servidor Emby se actualiza. {0}% completado.", + "AppDeviceValues": "Aplicaci\u00f3n: {0}, Dispositivo: {1}", + "UserDownloadingItemWithValues": "{0} est\u00e1 descargando {1}", "FolderTypeMixed": "Contenido mezclado", "FolderTypeMovies": "Peliculas", "FolderTypeMusic": "Musica", @@ -14,10 +14,10 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Heredado", "HeaderCastCrew": "Reparto y equipo t\u00e9cnico", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", + "HeaderPeople": "Gente", + "ValueSpecialEpisodeName": "Especial - {0}", "LabelChapterName": "Cap\u00edtulo {0}", - "NameSeasonNumber": "Season {0}", + "NameSeasonNumber": "Temporada {0}", "LabelExit": "Salir", "LabelVisitCommunity": "Visitar la comunidad", "LabelGithub": "Github", @@ -50,77 +50,77 @@ "NotificationOptionCameraImageUploaded": "Imagen de camara se a carcado", "NotificationOptionUserLockedOut": "Usuario bloqueado", "NotificationOptionServerRestartRequired": "Se requiere el reinicio del servidor", - "ViewTypePlaylists": "Playlists", + "ViewTypePlaylists": "Listas de reproducci\u00f3n", "ViewTypeMovies": "Pel\u00edculas", "ViewTypeTvShows": "TV", "ViewTypeGames": "Juegos", "ViewTypeMusic": "M\u00fasica", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", + "ViewTypeMusicGenres": "G\u00e9neros", + "ViewTypeMusicArtists": "Artistas", "ViewTypeBoxSets": "Colecciones", "ViewTypeChannels": "Canales", "ViewTypeLiveTV": "Tv en vivo", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", + "ViewTypeLiveTvNowPlaying": "Transmiti\u00e9ndose ahora", + "ViewTypeLatestGames": "\u00daltimos juegos", + "ViewTypeRecentlyPlayedGames": "Reproducido recientemente", + "ViewTypeGameFavorites": "Favoritos", + "ViewTypeGameSystems": "Sistemas de juego", + "ViewTypeGameGenres": "G\u00e9neros", + "ViewTypeTvResume": "Reanudar", + "ViewTypeTvNextUp": "Pr\u00f3ximamente", + "ViewTypeTvLatest": "\u00daltimas", "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", + "ViewTypeTvGenres": "G\u00e9neros", + "ViewTypeTvFavoriteSeries": "Series favoritas", + "ViewTypeTvFavoriteEpisodes": "Episodios favoritos", + "ViewTypeMovieResume": "Reanudar", + "ViewTypeMovieLatest": "\u00daltimas", + "ViewTypeMovieMovies": "Pel\u00edculas", + "ViewTypeMovieCollections": "Colecciones", + "ViewTypeMovieFavorites": "Favoritos", + "ViewTypeMovieGenres": "G\u00e9neros", + "ViewTypeMusicLatest": "\u00daltimas", + "ViewTypeMusicPlaylists": "Lista", + "ViewTypeMusicAlbums": "\u00c1lbumes", + "ViewTypeMusicAlbumArtists": "\u00c1lbumes de artistas", "HeaderOtherDisplaySettings": "Configuraci\u00f3n de pantalla", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", + "ViewTypeMusicSongs": "Canciones", + "ViewTypeMusicFavorites": "Favoritos", + "ViewTypeMusicFavoriteAlbums": "\u00c1lbumes favoritos", + "ViewTypeMusicFavoriteArtists": "Artistas favoritos", + "ViewTypeMusicFavoriteSongs": "Canciones favoritas", + "ViewTypeFolders": "Carpetas", + "ViewTypeLiveTvRecordingGroups": "Grabaciones", + "ViewTypeLiveTvChannels": "Canales", + "ScheduledTaskFailedWithName": "{0} fall\u00f3", + "LabelRunningTimeValue": "Tiempo de ejecuci\u00f3n: {0}", + "ScheduledTaskStartedWithName": "{0} iniciado", "VersionNumber": "Versi\u00f3n {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", + "PluginInstalledWithName": "{0} ha sido instalado", + "PluginUpdatedWithName": "{0} ha sido actualizado", + "PluginUninstalledWithName": "{0} ha sido desinstalado", + "ItemAddedWithName": "{0} ha sido a\u00f1adido a la biblioteca", + "ItemRemovedWithName": "{0} se ha eliminado de la biblioteca", + "LabelIpAddressValue": "Direcci\u00f3n IP: {0}", + "DeviceOnlineWithName": "{0} est\u00e1 conectado", + "UserOnlineFromDevice": "{0} est\u00e1 conectado desde {1}", + "ProviderValue": "Proveedor: {0}", + "SubtitlesDownloadedForItem": "Subt\u00edtulos descargados para {0}", + "UserConfigurationUpdatedWithName": "Se ha actualizado la configuraci\u00f3n de usuario para {0}", + "UserCreatedWithName": "Se ha creado el usuario {0}", + "UserPasswordChangedWithName": "Contrase\u00f1a cambiada al usuario {0}", + "UserDeletedWithName": "El usuario {0} ha sido eliminado", + "MessageServerConfigurationUpdated": "Se ha actualizado la configuraci\u00f3n del servidor", + "MessageNamedServerConfigurationUpdatedWithValue": "Se ha actualizado la secci\u00f3n {0} de la configuraci\u00f3n del servidor", + "MessageApplicationUpdated": "Se ha actualizado el servidor Emby", + "FailedLoginAttemptWithUserName": "Intento de inicio de sesi\u00f3n fallido desde {0}", + "AuthenticationSucceededWithUserName": "{0} se ha autenticado satisfactoriamente", + "DeviceOfflineWithName": "{0} se ha desconectado", + "UserLockedOutWithName": "El usuario {0} ha sido bloqueado", + "UserOfflineFromDevice": "{0} se ha desconectado de {1}", + "UserStartedPlayingItemWithValues": "{0} ha empezado a reproducir {1}", + "UserStoppedPlayingItemWithValues": "{0} ha parado de reproducir {1}", + "SubtitleDownloadFailureForItem": "Fallo en la descarga de subt\u00edtulos para {0}", "HeaderUnidentified": "Unidentified", "HeaderImagePrimary": "Primary", "HeaderImageBackdrop": "Backdrop", @@ -159,20 +159,20 @@ "HeaderEmbeddedImage": "Embedded image", "HeaderResolution": "Resolution", "HeaderSubtitles": "Subt\u00edtulos", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", + "HeaderGenres": "G\u00e9neros", + "HeaderCountries": "Paises", "HeaderStatus": "Estado", "HeaderTracks": "Tracks", "HeaderMusicArtist": "Music artist", "HeaderLocked": "Locked", - "HeaderStudios": "Studios", + "HeaderStudios": "Estudios", "HeaderActor": "Actors", "HeaderComposer": "Composers", "HeaderDirector": "Directors", "HeaderGuestStar": "Guest star", "HeaderProducer": "Producers", "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", + "HeaderParentalRatings": "Clasificaci\u00f3n parental", "HeaderCommunityRatings": "Community ratings", "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/hu.json b/MediaBrowser.Server.Implementations/Localization/Core/hu.json index d098a893c..2b9d28d8c 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/hu.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/hu.json @@ -169,8 +169,8 @@ "HeaderActor": "Sz\u00edn\u00e9szek", "HeaderComposer": "Zeneszerz\u0151k", "HeaderDirector": "Rendez\u0151k", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", + "HeaderGuestStar": "Vend\u00e9g szt\u00e1r", + "HeaderProducer": "Producerek", "HeaderWriter": "\u00cdr\u00f3k", "HeaderParentalRatings": "Korhat\u00e1r besorol\u00e1s", "HeaderCommunityRatings": "K\u00f6z\u00f6ss\u00e9gi \u00e9rt\u00e9kel\u00e9sek", diff --git a/MediaBrowser.Server.Implementations/Localization/Core/nl.json b/MediaBrowser.Server.Implementations/Localization/Core/nl.json index a83182ee8..2818fbf6a 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/nl.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/nl.json @@ -1,5 +1,5 @@ { - "DbUpgradeMessage": "Even geduld svp terwijl de Emby Server database ge-upgrade wordt. {0}% gereed.", + "DbUpgradeMessage": "Een ogenblik geduld terwijl uw Emby Server-database wordt bijgewerkt. {0}% voltooid.", "AppDeviceValues": "App: {0}, Apparaat: {1}", "UserDownloadingItemWithValues": "{0} download {1}", "FolderTypeMixed": "Gemengde inhoud", diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ru.json b/MediaBrowser.Server.Implementations/Localization/Core/ru.json index fa68aadb9..62fe3b496 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/ru.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/ru.json @@ -2,17 +2,17 @@ "DbUpgradeMessage": "\u041f\u043e\u0434\u043e\u0436\u0434\u0438\u0442\u0435, \u043f\u043e\u043a\u0430 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0432\u0430\u0448\u0435\u043c Emby Server \u043c\u043e\u0434\u0435\u0440\u043d\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f. {0} % \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e.", "AppDeviceValues": "\u041f\u0440\u0438\u043b.: {0}, \u0423\u0441\u0442\u0440.: {1}", "UserDownloadingItemWithValues": "{0} \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 {1}", - "FolderTypeMixed": "\u0420\u0430\u0437\u043d\u043e\u0442\u0438\u043f\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435", + "FolderTypeMixed": "\u0421\u043c\u0435\u0448\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435", "FolderTypeMovies": "\u041a\u0438\u043d\u043e", "FolderTypeMusic": "\u041c\u0443\u0437\u044b\u043a\u0430", - "FolderTypeAdultVideos": "\u0412\u0438\u0434\u0435\u043e \u0434\u043b\u044f \u0432\u0437\u0440\u043e\u0441\u043b\u044b\u0445", - "FolderTypePhotos": "\u0424\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438", - "FolderTypeMusicVideos": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u0438\u0434\u0435\u043e", - "FolderTypeHomeVideos": "\u0414\u043e\u043c\u0430\u0448\u043d\u0438\u0435 \u0432\u0438\u0434\u0435\u043e", + "FolderTypeAdultVideos": "\u0414\u043b\u044f \u0432\u0437\u0440\u043e\u0441\u043b\u044b\u0445", + "FolderTypePhotos": "\u0424\u043e\u0442\u043e", + "FolderTypeMusicVideos": "\u041c\u0443\u0437. \u0432\u0438\u0434\u0435\u043e", + "FolderTypeHomeVideos": "\u0414\u043e\u043c. \u0432\u0438\u0434\u0435\u043e", "FolderTypeGames": "\u0418\u0433\u0440\u044b", - "FolderTypeBooks": "\u041a\u043d\u0438\u0433\u0438", + "FolderTypeBooks": "\u041b\u0438\u0442\u0435\u0440\u0430\u0442\u0443\u0440\u0430", "FolderTypeTvShows": "\u0422\u0412", - "FolderTypeInherit": "\u041d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435", + "FolderTypeInherit": "\u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u043c\u044b\u0439", "HeaderCastCrew": "\u0421\u043d\u0438\u043c\u0430\u043b\u0438\u0441\u044c \u0438 \u0441\u043d\u0438\u043c\u0430\u043b\u0438", "HeaderPeople": "\u041b\u044e\u0434\u0438", "ValueSpecialEpisodeName": "\u0421\u043f\u0435\u0446\u044d\u043f\u0438\u0437\u043e\u0434 - {0}", @@ -163,7 +163,7 @@ "HeaderCountries": "\u0421\u0442\u0440\u0430\u043d\u044b", "HeaderStatus": "\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435", "HeaderTracks": "\u0414\u043e\u0440-\u043a\u0438", - "HeaderMusicArtist": "\u0418\u0441\u043f. \u043c\u0443\u0437\u044b\u043a\u0438", + "HeaderMusicArtist": "\u041c\u0443\u0437. \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c", "HeaderLocked": "\u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043e", "HeaderStudios": "\u0421\u0442\u0443\u0434\u0438\u0438", "HeaderActor": "\u0410\u043a\u0442\u0451\u0440\u044b", diff --git a/MediaBrowser.Server.Implementations/Localization/Core/sv.json b/MediaBrowser.Server.Implementations/Localization/Core/sv.json index eca16e2b4..4a6565aff 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/sv.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/sv.json @@ -1,7 +1,7 @@ { - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", + "DbUpgradeMessage": "V\u00e4nligen v\u00e4nta medan databasen p\u00e5 din Emby Server uppgraderas. {0}% klar", "AppDeviceValues": "App: {0}, enhet: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", + "UserDownloadingItemWithValues": "{0} laddar ned {1}", "FolderTypeMixed": "Blandat inneh\u00e5ll", "FolderTypeMovies": "Filmer", "FolderTypeMusic": "Musik", @@ -15,18 +15,18 @@ "FolderTypeInherit": "\u00c4rv", "HeaderCastCrew": "Rollista & bes\u00e4ttning", "HeaderPeople": "Personer", - "ValueSpecialEpisodeName": "Special - {0}", + "ValueSpecialEpisodeName": "Specialavsnitt - {0}", "LabelChapterName": "Kapitel {0}", - "NameSeasonNumber": "Season {0}", + "NameSeasonNumber": "S\u00e4song {0}", "LabelExit": "Avsluta", "LabelVisitCommunity": "Bes\u00f6k v\u00e5rt diskussionsforum", "LabelGithub": "Github", - "LabelApiDocumentation": "Api Dokumentation", + "LabelApiDocumentation": "Api-dokumentation", "LabelDeveloperResources": "Resurser f\u00f6r utvecklare", "LabelBrowseLibrary": "Bl\u00e4ddra i biblioteket", "LabelConfigureServer": "Konfigurera Emby", "LabelRestartServer": "Starta om servern", - "CategorySync": "Synka", + "CategorySync": "Synkronisera", "CategoryUser": "Anv\u00e4ndare", "CategorySystem": "System", "CategoryApplication": "App", @@ -47,10 +47,10 @@ "NotificationOptionInstallationFailed": "Fel vid installation", "NotificationOptionNewLibraryContent": "Nytt inneh\u00e5ll har tillkommit", "NotificationOptionNewLibraryContentMultiple": "Nytillkommet inneh\u00e5ll finns (flera objekt)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", + "NotificationOptionCameraImageUploaded": "Kaberabild uppladdad", + "NotificationOptionUserLockedOut": "Anv\u00e4ndare har l\u00e5sts ute", "NotificationOptionServerRestartRequired": "Servern m\u00e5ste startas om", - "ViewTypePlaylists": "Playlists", + "ViewTypePlaylists": "Spellistor", "ViewTypeMovies": "Filmer", "ViewTypeTvShows": "TV", "ViewTypeGames": "Spel", @@ -80,10 +80,10 @@ "ViewTypeMovieFavorites": "Favoriter", "ViewTypeMovieGenres": "Genrer", "ViewTypeMusicLatest": "Nytillkommet", - "ViewTypeMusicPlaylists": "Playlists", + "ViewTypeMusicPlaylists": "Spellistor", "ViewTypeMusicAlbums": "Album", "ViewTypeMusicAlbumArtists": "Albumartister", - "HeaderOtherDisplaySettings": "Visningsinst\u00e4llningar", + "HeaderOtherDisplaySettings": "Visningsalternativ", "ViewTypeMusicSongs": "L\u00e5tar", "ViewTypeMusicFavorites": "Favoriter", "ViewTypeMusicFavoriteAlbums": "Favoritalbum", @@ -112,45 +112,45 @@ "UserDeletedWithName": "Anv\u00e4ndaren {0} har tagits bort", "MessageServerConfigurationUpdated": "Server konfigurationen har uppdaterats", "MessageNamedServerConfigurationUpdatedWithValue": "Serverinst\u00e4llningarnas del {0} ar uppdaterats", - "MessageApplicationUpdated": "Emby Server has been updated", + "MessageApplicationUpdated": "Emby Server har uppdaterats", "FailedLoginAttemptWithUserName": "Misslyckat inloggningsf\u00f6rs\u00f6k fr\u00e5n {0}", "AuthenticationSucceededWithUserName": "{0} har autentiserats", "DeviceOfflineWithName": "{0} har avbrutit anslutningen", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} har kopplats bort fr\u00e5n {1}", + "UserLockedOutWithName": "Anv\u00e4ndare {0} har l\u00e5sts ute", + "UserOfflineFromDevice": "{0} har avbrutit anslutningen fr\u00e5n {1}", "UserStartedPlayingItemWithValues": "{0} har p\u00e5b\u00f6rjat uppspelning av {1}", "UserStoppedPlayingItemWithValues": "{0} har avslutat uppspelning av {1}", "SubtitleDownloadFailureForItem": "Nerladdning av undertexter f\u00f6r {0} misslyckades", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", + "HeaderUnidentified": "Oidentifierad", + "HeaderImagePrimary": "Huvudbild", + "HeaderImageBackdrop": "Bakgrundsbild", + "HeaderImageLogo": "Logotyp", + "HeaderUserPrimaryImage": "Anv\u00e4ndarbild", + "HeaderOverview": "\u00d6versikt", + "HeaderShortOverview": "Kort \u00f6versikt", + "HeaderType": "Typ", "HeaderSeverity": "Severity", "HeaderUser": "Anv\u00e4ndare", "HeaderName": "Namn", "HeaderDate": "Datum", - "HeaderPremiereDate": "Premiere Date", + "HeaderPremiereDate": "Premi\u00e4rdatum", "HeaderDateAdded": "Date Added", "HeaderReleaseDate": "Premi\u00e4rdatum:", "HeaderRuntime": "Speltid", - "HeaderPlayCount": "Play Count", + "HeaderPlayCount": "Antal spelningar", "HeaderSeason": "S\u00e4song", "HeaderSeasonNumber": "S\u00e4songsnummer:", - "HeaderSeries": "Series:", + "HeaderSeries": "Serie:", "HeaderNetwork": "TV-bolag", - "HeaderYear": "Year:", - "HeaderYears": "Years:", + "HeaderYear": "\u00c5r:", + "HeaderYears": "\u00c5r:", "HeaderParentalRating": "Parental Rating", "HeaderCommunityRating": "Anv\u00e4ndaromd\u00f6me", "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specialer", + "HeaderSpecials": "Specialavsnitt", "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", + "HeaderPlayers": "Spelare:", + "HeaderAlbumArtists": "Albumartister", "HeaderAlbums": "Album", "HeaderDisc": "Skiva", "HeaderTrack": "Sp\u00e5r", @@ -163,16 +163,16 @@ "HeaderCountries": "L\u00e4nder", "HeaderStatus": "Status", "HeaderTracks": "Sp\u00e5r", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", + "HeaderMusicArtist": "Musikartist", + "HeaderLocked": "L\u00e5st", "HeaderStudios": "Studior", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", + "HeaderActor": "Sk\u00e5despelare", + "HeaderComposer": "Komposit\u00f6rer", + "HeaderDirector": "Regiss\u00f6r", + "HeaderGuestStar": "G\u00e4startist", + "HeaderProducer": "Producenter", + "HeaderWriter": "F\u00f6rfattare", "HeaderParentalRatings": "Parental Ratings", "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." + "StartupEmbyServerIsLoading": "Emby Server startar. V\u00e4nligen f\u00f6rs\u00f6k igen om en kort stund." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json b/MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json index 7f289fc1f..b711aab1f 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json @@ -1,5 +1,5 @@ { - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", + "DbUpgradeMessage": "\u8acb\u7a0d\u5019\uff0cEmby\u4f3a\u670d\u5668\u8cc7\u6599\u5eab\u6b63\u5728\u66f4\u65b0...\uff08\u5df2\u5b8c\u6210{0}%\uff09", "AppDeviceValues": "App: {0}, Device: {1}", "UserDownloadingItemWithValues": "{0} is downloading {1}", "FolderTypeMixed": "Mixed content", @@ -19,13 +19,13 @@ "LabelChapterName": "Chapter {0}", "NameSeasonNumber": "Season {0}", "LabelExit": "\u96e2\u958b", - "LabelVisitCommunity": "\u8a2a\u554f\u793e\u5340", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "\u700f\u89bd\u5a92\u9ad4\u5eab", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "\u91cd\u65b0\u555f\u52d5\u4f3a\u5668\u670d", + "LabelVisitCommunity": "\u8a2a\u554f\u793e\u7fa4", + "LabelGithub": "GitHub", + "LabelApiDocumentation": "API\u8aaa\u660e\u6587\u4ef6", + "LabelDeveloperResources": "\u958b\u767c\u4eba\u54e1\u5c08\u5340", + "LabelBrowseLibrary": "\u700f\u89bd\u5a92\u9ad4\u6ac3", + "LabelConfigureServer": "Emby\u8a2d\u5b9a", + "LabelRestartServer": "\u91cd\u65b0\u555f\u52d5\u4f3a\u670d\u5668", "CategorySync": "Sync", "CategoryUser": "User", "CategorySystem": "System", @@ -59,7 +59,7 @@ "ViewTypeMusicArtists": "Artists", "ViewTypeBoxSets": "Collections", "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", + "ViewTypeLiveTV": "\u96fb\u8996", "ViewTypeLiveTvNowPlaying": "Now Airing", "ViewTypeLatestGames": "Latest Games", "ViewTypeRecentlyPlayedGames": "Recently Played", -- cgit v1.2.3 From 0688be857eb3645260d4ca8aa0a0792f93497e58 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 15:49:26 -0400 Subject: update people validator --- .../Library/Validators/PeopleValidator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs index 5c43f2e13..500a5ad3d 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs @@ -125,7 +125,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators validIds.Add(item.Id); var hasMetdata = !string.IsNullOrWhiteSpace(item.Overview); - var performFullRefresh = !hasMetdata && (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= 30; + var performFullRefresh = !hasMetdata && (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= 14; var defaultMetadataRefreshMode = performFullRefresh ? MetadataRefreshMode.FullRefresh -- cgit v1.2.3 From 23e3243a733c3ed18190758d9403d6da213378f6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 17 Apr 2016 00:07:06 -0400 Subject: update inherited tags --- .../Persistence/SqliteItemRepository.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 212be2849..746321e70 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - private const int LatestSchemaVersion = 62; + private const int LatestSchemaVersion = 63; /// /// Initializes a new instance of the class. @@ -760,7 +760,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = item.SourceType.ToString(); var trailer = item as Trailer; - if (trailer != null) + if (trailer != null && trailer.TrailerTypes.Count > 0) { _saveItemCommand.GetParameter(index++).Value = string.Join("|", trailer.TrailerTypes.Select(i => i.ToString()).ToArray()); } @@ -1962,7 +1962,7 @@ namespace MediaBrowser.Server.Implementations.Persistence var index = 0; foreach (var type in query.ExcludeTrailerTypes) { - clauses.Add("TrailerTypes not like @TrailerTypes" + index); + clauses.Add("(TrailerTypes is null OR TrailerTypes not like @TrailerTypes" + index + ")"); cmd.Parameters.Add(cmd, "@TrailerTypes" + index, DbType.String).Value = "%" + type + "%"; index++; } @@ -2186,7 +2186,7 @@ namespace MediaBrowser.Server.Implementations.Persistence var excludeTagIndex = 0; foreach (var excludeTag in query.ExcludeTags) { - whereClauses.Add("Tags not like @excludeTag" + excludeTagIndex); + whereClauses.Add("(Tags is null OR Tags not like @excludeTag" + excludeTagIndex + ")"); cmd.Parameters.Add(cmd, "@excludeTag" + excludeTagIndex, DbType.String).Value = "%" + excludeTag + "%"; excludeTagIndex++; } @@ -2194,7 +2194,7 @@ namespace MediaBrowser.Server.Implementations.Persistence excludeTagIndex = 0; foreach (var excludeTag in query.ExcludeInheritedTags) { - whereClauses.Add("InheritedTags not like @excludeInheritedTag" + excludeTagIndex); + whereClauses.Add("(InheritedTags is null OR InheritedTags not like @excludeInheritedTag" + excludeTagIndex +")"); cmd.Parameters.Add(cmd, "@excludeInheritedTag" + excludeTagIndex, DbType.String).Value = "%" + excludeTag + "%"; excludeTagIndex++; } -- cgit v1.2.3 From 565b3350a125cf49cd288542bf28188ef906dd10 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 17 Apr 2016 16:57:57 -0400 Subject: update version --- MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index d33b2c51d..3c7ee55b7 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -40,7 +40,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { onStarted(); - _logger.Info("Copying recording stream to file stream"); + _logger.Info("Copying recording stream to file {0}", targetFile); var durationToken = new CancellationTokenSource(duration); var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; @@ -48,6 +48,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV await response.Content.CopyToAsync(output, StreamDefaults.DefaultCopyToBufferSize, linkedToken).ConfigureAwait(false); } } + + _logger.Info("Recording completed to file {0}", targetFile); } } } -- cgit v1.2.3 From 2b4dece54afbe8dff04b18ef454abd60af0ab826 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 17 Apr 2016 23:50:44 -0400 Subject: record nal length size --- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 3 +- MediaBrowser.Api/Playback/Hls/VideoHlsService.cs | 5 ++++ .../Playback/Progressive/VideoService.cs | 4 +-- MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs | 4 +-- .../Probing/ProbeResultNormalizer.cs | 3 +- MediaBrowser.Model/Entities/MediaStream.cs | 4 ++- .../Persistence/MediaStreamColumns.cs | 32 ++++++++++++++++++++++ .../Persistence/SqliteItemRepository.cs | 11 ++++++-- 8 files changed, 57 insertions(+), 9 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 65e236525..fa8f0c009 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -828,8 +828,9 @@ namespace MediaBrowser.Api.Playback.Hls // See if we can save come cpu cycles by avoiding encoding if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream)) + if (state.VideoStream != null && IsH264(state.VideoStream) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) { + Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; } diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 5f427146e..5709ca15a 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -87,6 +87,11 @@ namespace MediaBrowser.Api.Playback.Hls if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase)) { // if h264_mp4toannexb is ever added, do not use it for live tv + if (state.VideoStream != null && IsH264(state.VideoStream) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) + { + Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); + args += " -bsf:v h264_mp4toannexb"; + } return args; } diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index b0d87c975..6054a245b 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -139,9 +139,9 @@ namespace MediaBrowser.Api.Playback.Progressive if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream) && - (string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase))) + if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) { + Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; } diff --git a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs index 41bfb3b96..3a0526f43 100644 --- a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs @@ -73,9 +73,9 @@ namespace MediaBrowser.MediaEncoding.Encoder if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream) && - (string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) || isOutputMkv)) + if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) { + Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 6ec9e6435..38528d845 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -407,7 +407,8 @@ namespace MediaBrowser.MediaEncoding.Probing Profile = streamInfo.profile, Level = streamInfo.level, Index = streamInfo.index, - PixelFormat = streamInfo.pix_fmt + PixelFormat = streamInfo.pix_fmt, + NalLengthSize = streamInfo.nal_length_size }; // Filter out junk diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index bdc043e9a..fa7a51291 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -33,7 +33,9 @@ namespace MediaBrowser.Model.Entities /// /// The comment. public string Comment { get; set; } - + + public string NalLengthSize { get; set; } + /// /// Gets or sets a value indicating whether this instance is interlaced. /// diff --git a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs index 211c77107..518659930 100644 --- a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs +++ b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs @@ -26,6 +26,38 @@ namespace MediaBrowser.Server.Implementations.Persistence AddRefFramesCommand(); AddCodecTagColumn(); AddCommentColumn(); + AddNalColumn(); + } + + private void AddNalColumn() + { + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = "PRAGMA table_info(mediastreams)"; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + if (!reader.IsDBNull(1)) + { + var name = reader.GetString(1); + + if (string.Equals(name, "NalLengthSize", StringComparison.OrdinalIgnoreCase)) + { + return; + } + } + } + } + } + + var builder = new StringBuilder(); + + builder.AppendLine("alter table mediastreams"); + builder.AppendLine("add column NalLengthSize TEXT"); + + _connection.RunQueries(new[] { builder.ToString() }, _logger); } private void AddCommentColumn() diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 746321e70..590279db4 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -124,7 +124,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); var createMediaStreamsTableCommand - = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, CodecTag TEXT NULL, Comment TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; + = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; string[] queries = { @@ -391,7 +391,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "RefFrames", "IsCabac", "CodecTag", - "Comment" + "Comment", + "NalLengthSize" }; /// @@ -2893,6 +2894,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; _saveStreamCommand.GetParameter(index++).Value = stream.Comment; + _saveStreamCommand.GetParameter(index++).Value = stream.NalLengthSize; _saveStreamCommand.Transaction = transaction; _saveStreamCommand.ExecuteNonQuery(); @@ -3053,6 +3055,11 @@ namespace MediaBrowser.Server.Implementations.Persistence item.Comment = reader.GetString(27); } + if (!reader.IsDBNull(28)) + { + item.NalLengthSize = reader.GetString(28); + } + return item; } -- cgit v1.2.3 From 169554ccc4087e36f63aab8e929a25b306570ac1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 00:25:12 -0400 Subject: finish removing cabac --- .../Persistence/MediaStreamColumns.cs | 32 ---------------------- .../Persistence/SqliteItemRepository.cs | 18 +++++------- 2 files changed, 7 insertions(+), 43 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs index 518659930..debcd054f 100644 --- a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs +++ b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs @@ -21,7 +21,6 @@ namespace MediaBrowser.Server.Implementations.Persistence AddPixelFormatColumnCommand(); AddBitDepthCommand(); AddIsAnamorphicColumn(); - AddIsCabacColumn(); AddKeyFramesColumn(); AddRefFramesCommand(); AddCodecTagColumn(); @@ -215,37 +214,6 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.RunQueries(new[] { builder.ToString() }, _logger); } - private void AddIsCabacColumn() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(mediastreams)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "IsCabac", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table mediastreams"); - builder.AppendLine("add column IsCabac BIT NULL"); - - _connection.RunQueries(new[] { builder.ToString() }, _logger); - } - private void AddKeyFramesColumn() { using (var cmd = _connection.CreateCommand()) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 590279db4..fb655c9cb 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -124,7 +124,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); var createMediaStreamsTableCommand - = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; + = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; string[] queries = { @@ -389,7 +389,6 @@ namespace MediaBrowser.Server.Implementations.Persistence "BitDepth", "IsAnamorphic", "RefFrames", - "IsCabac", "CodecTag", "Comment", "NalLengthSize" @@ -2890,7 +2889,6 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveStreamCommand.GetParameter(index++).Value = stream.BitDepth; _saveStreamCommand.GetParameter(index++).Value = stream.IsAnamorphic; _saveStreamCommand.GetParameter(index++).Value = stream.RefFrames; - _saveStreamCommand.GetParameter(index++).Value = null; _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; _saveStreamCommand.GetParameter(index++).Value = stream.Comment; @@ -3043,21 +3041,19 @@ namespace MediaBrowser.Server.Implementations.Persistence item.RefFrames = reader.GetInt32(24); } - // cabac no longer used - - if (!reader.IsDBNull(26)) + if (!reader.IsDBNull(25)) { - item.CodecTag = reader.GetString(26); + item.CodecTag = reader.GetString(25); } - if (!reader.IsDBNull(27)) + if (!reader.IsDBNull(26)) { - item.Comment = reader.GetString(27); + item.Comment = reader.GetString(26); } - if (!reader.IsDBNull(28)) + if (!reader.IsDBNull(27)) { - item.NalLengthSize = reader.GetString(28); + item.NalLengthSize = reader.GetString(27); } return item; -- cgit v1.2.3 From 0ebb82dc57fefcdf765855e3fda0dd0f90c43f33 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 13:43:00 -0400 Subject: update NAL usage --- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 2 +- MediaBrowser.Api/Playback/Hls/VideoHlsService.cs | 2 +- MediaBrowser.Api/Playback/Progressive/VideoService.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs | 2 +- MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs | 9 ++++++++- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 9 ++++++++- 6 files changed, 20 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index fa8f0c009..bc155ff45 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -828,7 +828,7 @@ namespace MediaBrowser.Api.Playback.Hls // See if we can save come cpu cycles by avoiding encoding if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) + if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 5709ca15a..87b1c4248 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -87,7 +87,7 @@ namespace MediaBrowser.Api.Playback.Hls if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase)) { // if h264_mp4toannexb is ever added, do not use it for live tv - if (state.VideoStream != null && IsH264(state.VideoStream) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) + if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 6054a245b..3319fbaec 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -139,7 +139,7 @@ namespace MediaBrowser.Api.Playback.Progressive if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) + if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; diff --git a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs index 3a0526f43..b8efedf09 100644 --- a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs @@ -73,7 +73,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) + if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index d40f2a141..ab2b59d48 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -511,8 +511,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (!(service is EmbyTV.EmbyTV)) { // We can't trust that we'll be able to direct stream it through emby server, no matter what the provider says - mediaSource.SupportsDirectStream = true; + mediaSource.SupportsDirectStream = false; mediaSource.SupportsTranscoding = true; + foreach (var stream in mediaSource.MediaStreams) + { + if (stream.Type == MediaStreamType.Video && string.IsNullOrWhiteSpace(stream.NalLengthSize)) + { + stream.NalLengthSize = "0"; + } + } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 4c140602d..469767c65 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -317,6 +317,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun videoCodec = "mpeg2video"; } + string nal = null; + if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) + { + nal = "0"; + } + var url = GetApiUrl(info, true) + "/auto/v" + channelId; if (!string.IsNullOrWhiteSpace(profile) && !string.Equals(profile, "native", StringComparison.OrdinalIgnoreCase)) @@ -339,7 +345,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun Codec = videoCodec, Width = width, Height = height, - BitRate = videoBitrate + BitRate = videoBitrate, + NalLengthSize = nal }, new MediaStream -- cgit v1.2.3 From 992ca4c78a2bf44e1365d648989f6d028cdb9e8a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 20 Apr 2016 01:21:40 -0400 Subject: add OriginalTitle to metadata editor --- MediaBrowser.Api/ItemUpdateService.cs | 6 ++++++ MediaBrowser.Controller/Entities/BaseItem.cs | 2 ++ MediaBrowser.Controller/Entities/Movies/Movie.cs | 2 -- MediaBrowser.Controller/Entities/TV/Series.cs | 2 -- MediaBrowser.Controller/Entities/Trailer.cs | 2 +- MediaBrowser.Model/Dto/BaseItemDto.cs | 2 ++ MediaBrowser.Model/Querying/ItemFields.cs | 2 ++ MediaBrowser.Providers/Manager/ProviderUtils.cs | 9 +++++++++ MediaBrowser.Server.Implementations/Dto/DtoService.cs | 5 +++++ 9 files changed, 27 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index f37874774..5bb4ed5f0 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -247,6 +247,12 @@ namespace MediaBrowser.Api hasBudget.Revenue = request.Revenue; } + var hasOriginalTitle = item as IHasOriginalTitle; + if (hasOriginalTitle != null) + { + hasOriginalTitle.OriginalTitle = hasOriginalTitle.OriginalTitle; + } + var hasCriticRating = item as IHasCriticRating; if (hasCriticRating != null) { diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 04371c13b..959334d78 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -125,6 +125,8 @@ namespace MediaBrowser.Controller.Entities } } + public string OriginalTitle { get; set; } + /// /// Gets or sets the id. /// diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 4d2ca9ffe..6004992cc 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -18,8 +18,6 @@ namespace MediaBrowser.Controller.Entities.Movies { public List SpecialFeatureIds { get; set; } - public string OriginalTitle { get; set; } - public List ThemeSongIds { get; set; } public List ThemeVideoIds { get; set; } public List ProductionLocations { get; set; } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 9eeb89a1f..7eabff072 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -19,8 +19,6 @@ namespace MediaBrowser.Controller.Entities.TV { public List SpecialFeatureIds { get; set; } - public string OriginalTitle { get; set; } - public int? AnimeSeriesIndex { get; set; } public Series() diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index c3e24090c..fe8bf3ed3 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Controller.Entities /// /// Class Trailer /// - public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasLookupInfo + public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasOriginalTitle, IHasLookupInfo { public List ProductionLocations { get; set; } diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 7928d0bf9..49ec9f8ef 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -26,6 +26,8 @@ namespace MediaBrowser.Model.Dto /// The name. public string Name { get; set; } + public string OriginalTitle { get; set; } + /// /// Gets or sets the server identifier. /// diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs index 1540f178a..cea638a39 100644 --- a/MediaBrowser.Model/Querying/ItemFields.cs +++ b/MediaBrowser.Model/Querying/ItemFields.cs @@ -130,6 +130,8 @@ /// Metascore, + OriginalTitle, + /// /// The item overview /// diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs index 278d8ed71..59a2da460 100644 --- a/MediaBrowser.Providers/Manager/ProviderUtils.cs +++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs @@ -40,6 +40,15 @@ namespace MediaBrowser.Providers.Manager } } + if (replaceData || string.IsNullOrEmpty(target.OriginalTitle)) + { + // Safeguard against incoming data having an emtpy name + if (!string.IsNullOrWhiteSpace(source.OriginalTitle)) + { + target.OriginalTitle = source.OriginalTitle; + } + } + if (replaceData || !target.CommunityRating.HasValue) { target.CommunityRating = source.CommunityRating; diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 50ae19580..2ee55edb9 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1126,6 +1126,11 @@ namespace MediaBrowser.Server.Implementations.Dto dto.Overview = item.Overview; } + if (fields.Contains(ItemFields.OriginalTitle)) + { + dto.OriginalTitle = item.OriginalTitle; + } + if (fields.Contains(ItemFields.ShortOverview)) { var hasShortOverview = item as IHasShortOverview; -- cgit v1.2.3 From f3c3c74d84d81ada293ff10c2eabcd1be418f54f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Apr 2016 14:00:46 -0400 Subject: add probe property --- .../LiveTv/TunerHosts/BaseTunerHost.cs | 30 +++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index 02a8d6938..9bb5b4fd7 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -224,7 +224,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts var stream = await GetChannelStream(host, channelId, streamId, cancellationToken).ConfigureAwait(false); - //await AddMediaInfo(stream, false, resourcePool, cancellationToken).ConfigureAwait(false); + if (EnableMediaProbing) + { + await AddMediaInfo(stream, false, resourcePool, cancellationToken).ConfigureAwait(false); + } + return new Tuple(stream, resourcePool); } catch (Exception ex) @@ -239,6 +243,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts throw new LiveTvConflictException(); } + protected virtual bool EnableMediaProbing + { + get { return false; } + } + protected async Task IsAvailable(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken) { try @@ -268,6 +277,25 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts return _semaphoreLocks.GetOrAdd(url, key => new SemaphoreSlim(1, 1)); } + private async Task AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio, SemaphoreSlim resourcePool, CancellationToken cancellationToken) + { + await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + await AddMediaInfoInternal(mediaSource, isAudio, cancellationToken).ConfigureAwait(false); + + // Leave the resource locked. it will be released upstream + } + catch (Exception) + { + // Release the resource if there's some kind of failure. + resourcePool.Release(); + + throw; + } + } + private async Task AddMediaInfoInternal(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken) { var originalRuntime = mediaSource.RunTimeTicks; -- cgit v1.2.3 From c94706d6eec63f705eb69ec87a4887f314986dc0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Apr 2016 12:12:20 -0400 Subject: update shutdown --- .../HttpServer/HttpListenerHost.cs | 17 +++++++++++++++++ .../ServerManager/ServerManager.cs | 19 +++++++++++++++++++ MediaBrowser.ServerApplication/MainStartup.cs | 5 +++-- 3 files changed, 39 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 25463b660..c5cb810e5 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -179,6 +179,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer private void OnWebSocketConnecting(WebSocketConnectingEventArgs args) { + if (_disposed) + { + return; + } + if (WebSocketConnecting != null) { WebSocketConnecting(this, args); @@ -187,6 +192,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer private void OnWebSocketConnected(WebSocketConnectEventArgs args) { + if (_disposed) + { + return; + } + if (WebSocketConnected != null) { WebSocketConnected(this, args); @@ -331,6 +341,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer var httpRes = httpReq.Response; + if (_disposed) + { + httpRes.StatusCode = 503; + httpRes.Close(); + return Task.FromResult(true); + } + var operationName = httpReq.OperationName; var localPath = url.LocalPath; diff --git a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs index 8719f5448..33d106916 100644 --- a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs +++ b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs @@ -71,6 +71,8 @@ namespace MediaBrowser.Server.Implementations.ServerManager /// The web socket listeners. private readonly List _webSocketListeners = new List(); + private bool _disposed; + /// /// Initializes a new instance of the class. /// @@ -143,6 +145,11 @@ namespace MediaBrowser.Server.Implementations.ServerManager /// The instance containing the event data. void HttpServer_WebSocketConnected(object sender, WebSocketConnectEventArgs e) { + if (_disposed) + { + return; + } + var connection = new WebSocketConnection(e.WebSocket, e.Endpoint, _jsonSerializer, _logger) { OnReceive = ProcessWebSocketMessageReceived, @@ -164,6 +171,11 @@ namespace MediaBrowser.Server.Implementations.ServerManager /// The result. private async void ProcessWebSocketMessageReceived(WebSocketMessageInfo result) { + if (_disposed) + { + return; + } + //_logger.Debug("Websocket message received: {0}", result.MessageType); var tasks = _webSocketListeners.Select(i => Task.Run(async () => @@ -244,6 +256,11 @@ namespace MediaBrowser.Server.Implementations.ServerManager throw new ArgumentNullException("dataFunction"); } + if (_disposed) + { + throw new ObjectDisposedException(GetType().Name); + } + cancellationToken.ThrowIfCancellationRequested(); var connectionsList = connections.Where(s => s.State == WebSocketState.Open).ToList(); @@ -301,6 +318,8 @@ namespace MediaBrowser.Server.Implementations.ServerManager /// public void Dispose() { + _disposed = true; + Dispose(true); GC.SuppressFinalize(this); } diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index ac1b7ca99..f83c7d545 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -555,9 +555,10 @@ namespace MediaBrowser.ServerApplication private static void ShutdownWindowsApplication() { - _logger.Info("Calling Application.Exit"); - Application.Exit(); + //_logger.Info("Calling Application.Exit"); + //Application.Exit(); + _logger.Info("Calling Environment.Exit"); Environment.Exit(0); _logger.Info("Calling ApplicationTaskCompletionSource.SetResult"); -- cgit v1.2.3 From 584e793a6d8782956fee5ae1658fdd99d72860ed Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Apr 2016 12:27:17 -0400 Subject: auto-organize fixes --- .../FileOrganization/EpisodeFileOrganizer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index e45df3f4a..270f01b2b 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -304,7 +304,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization if (otherDuplicatePaths.Count > 0) { - var msg = string.Format("File '{0}' already exists as '{1}', stopping organization", sourcePath, otherDuplicatePaths); + var msg = string.Format("File '{0}' already exists as these:'{1}'. Stopping organization", sourcePath, string.Join("', '", otherDuplicatePaths)); _logger.Info(msg); result.Status = FileSortingStatus.SkippedExisting; result.StatusMessage = msg; -- cgit v1.2.3 From 85a9363c7806be6206c6e6f4a533d7ed578c3787 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Apr 2016 01:52:33 -0400 Subject: update packages --- .../MediaBrowser.Common.Implementations.csproj | 10 ++++++---- MediaBrowser.Common.Implementations/packages.config | 6 +++--- .../MediaBrowser.Server.Implementations.csproj | 10 +++++++--- MediaBrowser.Server.Implementations/packages.config | 3 ++- Nuget/MediaBrowser.Common.Internal.nuspec | 4 ++-- 5 files changed, 20 insertions(+), 13 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj index 2017b40f4..8da1beb68 100644 --- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj +++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj @@ -54,8 +54,9 @@ ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll - - ..\packages\NLog.4.2.3\lib\net45\NLog.dll + + ..\packages\NLog.4.3.1\lib\net45\NLog.dll + True ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll @@ -64,8 +65,9 @@ False ..\ThirdParty\SharpCompress\SharpCompress.dll - - ..\packages\SimpleInjector.3.1.2\lib\net45\SimpleInjector.dll + + ..\packages\SimpleInjector.3.1.3\lib\net45\SimpleInjector.dll + True diff --git a/MediaBrowser.Common.Implementations/packages.config b/MediaBrowser.Common.Implementations/packages.config index 64b337221..6d7d86182 100644 --- a/MediaBrowser.Common.Implementations/packages.config +++ b/MediaBrowser.Common.Implementations/packages.config @@ -2,7 +2,7 @@ - + - - + + \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 60d8f737f..43f5d741b 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -68,9 +68,13 @@ ..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll - - False - ..\packages\SocketHttpListener.1.0.0.29\lib\net45\SocketHttpListener.dll + + ..\packages\SimpleInjector.3.1.3\lib\net45\SimpleInjector.dll + True + + + ..\packages\SocketHttpListener.1.0.0.30\lib\net45\SocketHttpListener.dll + True diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 66aede029..dce839b57 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -8,5 +8,6 @@ - + + \ No newline at end of file diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 0ae08c4ad..a561dbf4b 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -13,8 +13,8 @@ Copyright © Emby 2013 - - + + -- cgit v1.2.3 From 5401641e2b4c0eb35a308a952e5370dd968b9621 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 25 Apr 2016 13:35:49 -0400 Subject: remove special characters from sort names --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 959334d78..f5fb72de5 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -605,7 +605,7 @@ namespace MediaBrowser.Controller.Entities builder.Append(chunkBuilder); } //Logger.Debug("ModifySortChunks Start: {0} End: {1}", name, builder.ToString()); - return builder.ToString(); + return builder.ToString().RemoveDiacritics(); } [IgnoreDataMember] diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index fb655c9cb..fb91a2dd2 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - private const int LatestSchemaVersion = 63; + private const int LatestSchemaVersion = 64; /// /// Initializes a new instance of the class. -- cgit v1.2.3 From 54e04dd027f75066981524f7db02664b3afed2ab Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 25 Apr 2016 22:16:46 -0400 Subject: support duration on recording url --- MediaBrowser.Controller/LiveTv/ITunerHost.cs | 2 ++ .../LiveTv/EmbyTV/DirectRecorder.cs | 9 ++++++--- .../LiveTv/EmbyTV/EmbyTV.cs | 23 ++++++++++++++++------ .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 8 ++++++++ .../LiveTv/TunerHosts/M3UTunerHost.cs | 5 +++++ .../LiveTv/TunerHosts/SatIp/SatIpHost.cs | 5 +++++ 6 files changed, 43 insertions(+), 9 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/LiveTv/ITunerHost.cs b/MediaBrowser.Controller/LiveTv/ITunerHost.cs index 498602ddf..1e7aa3de5 100644 --- a/MediaBrowser.Controller/LiveTv/ITunerHost.cs +++ b/MediaBrowser.Controller/LiveTv/ITunerHost.cs @@ -46,6 +46,8 @@ namespace MediaBrowser.Controller.LiveTv /// The cancellation token. /// Task<List<MediaSourceInfo>>. Task> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken); + + string ApplyDuration(string streamPath, TimeSpan duration); } public interface IConfigurableTunerHost { diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 3c7ee55b7..98249f5ac 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -42,10 +42,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV _logger.Info("Copying recording stream to file {0}", targetFile); - var durationToken = new CancellationTokenSource(duration); - var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + if (!mediaSource.RunTimeTicks.HasValue) + { + var durationToken = new CancellationTokenSource(duration); + cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + } - await response.Content.CopyToAsync(output, StreamDefaults.DefaultCopyToBufferSize, linkedToken).ConfigureAwait(false); + await response.Content.CopyToAsync(output, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false); } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 60ff23b04..d85e8ba3f 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -591,7 +591,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV throw new ApplicationException("Tuner not found."); } - private async Task> GetChannelStreamInternal(string channelId, string streamId, CancellationToken cancellationToken) + private async Task> GetChannelStreamInternal(string channelId, string streamId, CancellationToken cancellationToken) { _logger.Info("Streaming Channel " + channelId); @@ -599,7 +599,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { try { - return await hostInstance.GetChannelStream(channelId, streamId, cancellationToken).ConfigureAwait(false); + var result = await hostInstance.GetChannelStream(channelId, streamId, cancellationToken).ConfigureAwait(false); + + return new Tuple(result.Item1, hostInstance, result.Item2); } catch (Exception e) { @@ -797,8 +799,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV // HDHR doesn't seem to release the tuner right away after first probing with ffmpeg //await Task.Delay(3000, cancellationToken).ConfigureAwait(false); - var duration = recordingEndDate - DateTime.UtcNow; - var recorder = await GetRecorder().ConfigureAwait(false); if (recorder is EncodedRecorder) @@ -816,6 +816,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV recording.DateLastUpdated = DateTime.UtcNow; _recordingProvider.AddOrUpdate(recording); + var duration = recordingEndDate - DateTime.UtcNow; + _logger.Info("Beginning recording. Will record for {0} minutes.", duration.TotalMinutes.ToString(CultureInfo.InvariantCulture)); _logger.Info("Writing file to path: " + recordPath); @@ -823,10 +825,19 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV Action onStarted = () => { - result.Item2.Release(); + result.Item3.Release(); isResourceOpen = false; }; + var pathWithDuration = result.Item2.ApplyDuration(mediaStreamInfo.Path, duration); + + // If it supports supplying duration via url + if (!string.Equals(pathWithDuration, mediaStreamInfo.Path, StringComparison.OrdinalIgnoreCase)) + { + mediaStreamInfo.Path = pathWithDuration; + mediaStreamInfo.RunTimeTicks = duration.Ticks; + } + await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken).ConfigureAwait(false); recording.Status = RecordingStatus.Completed; @@ -836,7 +847,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { if (isResourceOpen) { - result.Item2.Release(); + result.Item3.Release(); } _libraryMonitor.ReportFileSystemChangeComplete(recordPath, false); diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 469767c65..a3e5589e8 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -59,6 +59,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun return id; } + public string ApplyDuration(string streamPath, TimeSpan duration) + { + streamPath += streamPath.IndexOf('?') == -1 ? "?" : "&"; + streamPath += "duration=" + Convert.ToInt32(duration.TotalSeconds).ToString(CultureInfo.InvariantCulture); + + return streamPath; + } + private async Task> GetLineup(TunerHostInfo info, CancellationToken cancellationToken) { var options = new HttpRequestOptions diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index 523f14dfc..c874e51b6 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -146,5 +146,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts { return Task.FromResult(true); } + + public string ApplyDuration(string streamPath, TimeSpan duration) + { + return streamPath; + } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs index ffd85fd18..1e571c84f 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs @@ -164,5 +164,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp return list; } + + public string ApplyDuration(string streamPath, TimeSpan duration) + { + return streamPath; + } } } -- cgit v1.2.3 From 69622a74a8c60f60d9859de8d247bcbe488e68d3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 25 Apr 2016 23:39:21 -0400 Subject: faster cleanup of missing episodes --- MediaBrowser.Controller/Library/ILibraryManager.cs | 30 ++--- .../TV/MissingEpisodeProvider.cs | 18 ++- MediaBrowser.Providers/TV/SeriesPostScanTask.cs | 127 +++++++++++++++++++-- .../Library/LibraryManager.cs | 3 + 4 files changed, 151 insertions(+), 27 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index c8b3d5131..0f6b10b43 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Controller.Library /// The file information. /// The parent. /// BaseItem. - BaseItem ResolvePath(FileSystemMetadata fileInfo, + BaseItem ResolvePath(FileSystemMetadata fileInfo, Folder parent = null); /// @@ -36,9 +36,9 @@ namespace MediaBrowser.Controller.Library /// The parent. /// Type of the collection. /// List{``0}. - IEnumerable ResolvePaths(IEnumerable files, + IEnumerable ResolvePaths(IEnumerable files, IDirectoryService directoryService, - Folder parent, string + Folder parent, string collectionType = null); /// @@ -60,7 +60,7 @@ namespace MediaBrowser.Controller.Library /// The path. /// BaseItem. BaseItem FindByPath(string path); - + /// /// Gets the artist. /// @@ -156,7 +156,7 @@ namespace MediaBrowser.Controller.Library /// The identifier. /// BaseItem. BaseItem GetMemoryItemById(Guid id); - + /// /// Gets the intros. /// @@ -243,6 +243,8 @@ namespace MediaBrowser.Controller.Library /// BaseItem. BaseItem RetrieveItem(Guid id); + bool IsScanRunning { get; } + /// /// Occurs when [item added]. /// @@ -290,7 +292,7 @@ namespace MediaBrowser.Controller.Library /// The path. /// System.String. string GetConfiguredContentType(string path); - + /// /// Normalizes the root path list. /// @@ -332,8 +334,8 @@ namespace MediaBrowser.Controller.Library Task GetNamedView(User user, string name, string parentId, - string viewType, - string sortName, + string viewType, + string sortName, CancellationToken cancellationToken); /// @@ -346,8 +348,8 @@ namespace MediaBrowser.Controller.Library /// The cancellation token. /// Task<UserView>. Task GetNamedView(User user, - string name, - string viewType, + string name, + string viewType, string sortName, CancellationToken cancellationToken); @@ -393,7 +395,7 @@ namespace MediaBrowser.Controller.Library string viewType, string sortName, CancellationToken cancellationToken); - + /// /// Determines whether [is video file] [the specified path]. /// @@ -477,14 +479,14 @@ namespace MediaBrowser.Controller.Library /// The query. /// List<PersonInfo>. List GetPeople(InternalPeopleQuery query); - + /// /// Gets the people items. /// /// The query. /// List<Person>. List GetPeopleItems(InternalPeopleQuery query); - + /// /// Gets all people names. /// @@ -559,7 +561,7 @@ namespace MediaBrowser.Controller.Library /// The query. /// QueryResult<BaseItem>. QueryResult GetItemsResult(InternalItemsQuery query); - + /// /// Ignores the file. /// diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index ad55c186a..8ae9aa5bb 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -27,6 +27,8 @@ namespace MediaBrowser.Providers.TV private readonly IFileSystem _fileSystem; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + private static readonly SemaphoreSlim _resourceLock = new SemaphoreSlim(1, 1); + public static bool IsRunning = false; public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization, IFileSystem fileSystem) { @@ -37,13 +39,16 @@ namespace MediaBrowser.Providers.TV _fileSystem = fileSystem; } - public async Task Run(IEnumerable> series, CancellationToken cancellationToken) + public async Task Run(List> series, bool addNewItems, CancellationToken cancellationToken) { + await _resourceLock.WaitAsync(cancellationToken).ConfigureAwait(false); + IsRunning = true; + foreach (var seriesGroup in series) { try { - await Run(seriesGroup, cancellationToken).ConfigureAwait(false); + await Run(seriesGroup, addNewItems, cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { @@ -58,9 +63,12 @@ namespace MediaBrowser.Providers.TV _logger.ErrorException("Error in missing episode provider for series id {0}", ex, seriesGroup.Key); } } + + IsRunning = false; + _resourceLock.Release(); } - private async Task Run(IGrouping group, CancellationToken cancellationToken) + private async Task Run(IGrouping group, bool addNewItems, CancellationToken cancellationToken) { var tvdbId = group.Key; @@ -110,7 +118,7 @@ namespace MediaBrowser.Providers.TV var hasNewEpisodes = false; - if (_config.Configuration.EnableInternetProviders) + if (_config.Configuration.EnableInternetProviders && addNewItems) { var seriesConfig = _config.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, typeof(Series).Name, StringComparison.OrdinalIgnoreCase)); @@ -427,7 +435,7 @@ namespace MediaBrowser.Providers.TV await season.AddChild(episode, cancellationToken).ConfigureAwait(false); - await episode.RefreshMetadata(new MetadataRefreshOptions(_fileSystem) + await episode.RefreshMetadata(new MetadataRefreshOptions(_fileSystem) { }, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs index 5428e6c92..0fd6fa56f 100644 --- a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs +++ b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs @@ -11,6 +11,10 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Model.Tasks; namespace MediaBrowser.Providers.TV { @@ -46,14 +50,17 @@ namespace MediaBrowser.Providers.TV private async Task RunInternal(IProgress progress, CancellationToken cancellationToken) { - var seriesList = _libraryManager.RootFolder - .GetRecursiveChildren(i => i is Series) - .Cast() - .ToList(); + var seriesList = _libraryManager.GetItemList(new InternalItemsQuery() + { + IncludeItemTypes = new[] { typeof(Series).Name }, + Recursive = true + + }).Cast().ToList(); var seriesGroups = FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList(); - await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem).Run(seriesGroups, cancellationToken).ConfigureAwait(false); + await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem) + .Run(seriesGroups, true, cancellationToken).ConfigureAwait(false); var numComplete = 0; @@ -82,7 +89,7 @@ namespace MediaBrowser.Providers.TV } } - private IEnumerable> FindSeriesGroups(List seriesList) + internal static IEnumerable> FindSeriesGroups(List seriesList) { var links = seriesList.ToDictionary(s => s, s => seriesList.Where(c => c != s && ShareProviderId(s, c)).ToList()); @@ -102,7 +109,7 @@ namespace MediaBrowser.Providers.TV } } - private void FindAllLinked(Series series, HashSet visited, IDictionary> linksMap, List results) + private static void FindAllLinked(Series series, HashSet visited, IDictionary> linksMap, List results) { results.Add(series); visited.Add(series); @@ -118,7 +125,7 @@ namespace MediaBrowser.Providers.TV } } - private bool ShareProviderId(Series a, Series b) + private static bool ShareProviderId(Series a, Series b) { return a.ProviderIds.Any(id => { @@ -137,4 +144,108 @@ namespace MediaBrowser.Providers.TV } } + public class CleanMissingEpisodesEntryPoint : IServerEntryPoint + { + private readonly ILibraryManager _libraryManager; + private readonly IServerConfigurationManager _config; + private readonly ILogger _logger; + private readonly ILocalizationManager _localization; + private readonly IFileSystem _fileSystem; + private readonly object _libraryChangedSyncLock = new object(); + private const int LibraryUpdateDuration = 180000; + private readonly ITaskManager _taskManager; + + public CleanMissingEpisodesEntryPoint(ILibraryManager libraryManager, IServerConfigurationManager config, ILogger logger, ILocalizationManager localization, IFileSystem fileSystem, ITaskManager taskManager) + { + _libraryManager = libraryManager; + _config = config; + _logger = logger; + _localization = localization; + _fileSystem = fileSystem; + _taskManager = taskManager; + } + + private Timer LibraryUpdateTimer { get; set; } + + public void Run() + { + _libraryManager.ItemAdded += _libraryManager_ItemAdded; + } + + private void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e) + { + if (!FilterItem(e.Item)) + { + return; + } + + lock (_libraryChangedSyncLock) + { + if (LibraryUpdateTimer == null) + { + LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, Timeout.Infinite); + } + else + { + LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); + } + } + } + + private async void LibraryUpdateTimerCallback(object state) + { + if (MissingEpisodeProvider.IsRunning) + { + return; + } + + if (_libraryManager.IsScanRunning) + { + return ; + } + + var seriesList = _libraryManager.GetItemList(new InternalItemsQuery() + { + IncludeItemTypes = new[] { typeof(Series).Name }, + Recursive = true + + }).Cast().ToList(); + + var seriesGroups = SeriesPostScanTask.FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList(); + + await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem) + .Run(seriesGroups, false, CancellationToken.None).ConfigureAwait(false); + } + + private bool FilterItem(BaseItem item) + { + return item is Episode && item.LocationType != LocationType.Virtual; + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + } + + /// + /// 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) + { + if (LibraryUpdateTimer != null) + { + LibraryUpdateTimer.Dispose(); + LibraryUpdateTimer = null; + } + + _libraryManager.ItemAdded -= _libraryManager_ItemAdded; + } + } + } } diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index ccba293a3..17c4f59ba 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -143,6 +143,7 @@ namespace MediaBrowser.Server.Implementations.Library private readonly Func _libraryMonitorFactory; private readonly Func _providerManagerFactory; private readonly Func _userviewManager; + public bool IsScanRunning { get; private set; } /// /// The _library items cache @@ -1102,6 +1103,7 @@ namespace MediaBrowser.Server.Implementations.Library /// Task. public async Task ValidateMediaLibraryInternal(IProgress progress, CancellationToken cancellationToken) { + IsScanRunning = true; _libraryMonitorFactory().Stop(); try @@ -1111,6 +1113,7 @@ namespace MediaBrowser.Server.Implementations.Library finally { _libraryMonitorFactory().Start(); + IsScanRunning = false; } } -- cgit v1.2.3 From 371cbc0c1d712b702d5a792a0f2ddb05dbe7af2d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 26 Apr 2016 22:59:43 -0400 Subject: support headroom with guide --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- .../EntryPoints/Notifications/Notifications.cs | 12 ++++++++++++ MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 3 +++ 3 files changed, 16 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index f5fb72de5..f9f03a9c5 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1546,7 +1546,7 @@ namespace MediaBrowser.Controller.Entities if (itemByPath == null) { - Logger.Warn("Unable to find linked item at path {0}", info.Path); + //Logger.Warn("Unable to find linked item at path {0}", info.Path); } return itemByPath; diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs index 71019e0ad..e84b66c5a 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs @@ -215,6 +215,12 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications return; } + var video = e.Item as Video; + if (video != null && video.IsThemeMedia) + { + return; + } + var type = GetPlaybackNotificationType(item.MediaType); SendPlaybackNotification(type, e); @@ -230,6 +236,12 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications return; } + var video = e.Item as Video; + if (video != null && video.IsThemeMedia) + { + return; + } + var type = GetPlaybackStoppedNotificationType(item.MediaType); SendPlaybackNotification(type, e); diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 5534b95a9..bfa4995cf 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -1712,6 +1712,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest -- cgit v1.2.3 From 8499183d77a5351e4dd0a9b200b8f82a6d303fe7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 13:43:09 -0400 Subject: update SearchEngine --- MediaBrowser.Server.Implementations/Library/SearchEngine.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs index 61a5d98a3..e271fbcb2 100644 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs @@ -87,13 +87,16 @@ namespace MediaBrowser.Server.Implementations.Library { var searchTerm = query.SearchTerm; + if (searchTerm != null) + { + searchTerm = searchTerm.Trim().RemoveDiacritics(); + } + if (string.IsNullOrWhiteSpace(searchTerm)) { throw new ArgumentNullException("searchTerm"); } - searchTerm = searchTerm.Trim().RemoveDiacritics(); - var terms = GetWords(searchTerm); var hints = new List>(); -- cgit v1.2.3 From 64f51a3643a32bf21586b5b5e075802787868560 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 13:52:43 -0400 Subject: update IsFolder sorting --- .../Persistence/SqliteItemRepository.cs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index fb91a2dd2..fcc39deb5 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1574,6 +1574,10 @@ namespace MediaBrowser.Server.Implementations.Persistence { return "RuntimeTicks"; } + if (string.Equals(name, ItemSortBy.IsFolder, StringComparison.OrdinalIgnoreCase)) + { + return "IsFolder"; + } if (string.Equals(name, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase)) { return "RANDOM()"; -- cgit v1.2.3 From 1e16ac9f2ac0cdc8833f2e53540a942876a3e979 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 13:52:56 -0400 Subject: add missing localization text --- .../Localization/Core/en-US.json | 353 +++++++++++---------- 1 file changed, 177 insertions(+), 176 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Localization/Core/en-US.json b/MediaBrowser.Server.Implementations/Localization/Core/en-US.json index 0d5b5c4aa..5e2f98c09 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/en-US.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/en-US.json @@ -1,178 +1,179 @@ { - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server", - "CategorySync": "Sync", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." + "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", + "AppDeviceValues": "App: {0}, Device: {1}", + "UserDownloadingItemWithValues": "{0} is downloading {1}", + "FolderTypeMixed": "Mixed content", + "FolderTypeMovies": "Movies", + "FolderTypeMusic": "Music", + "FolderTypeAdultVideos": "Adult videos", + "FolderTypePhotos": "Photos", + "FolderTypeMusicVideos": "Music videos", + "FolderTypeHomeVideos": "Home videos", + "FolderTypeGames": "Games", + "FolderTypeBooks": "Books", + "FolderTypeTvShows": "TV", + "FolderTypeInherit": "Inherit", + "HeaderCastCrew": "Cast & Crew", + "HeaderPeople": "People", + "ValueSpecialEpisodeName": "Special - {0}", + "LabelChapterName": "Chapter {0}", + "NameSeasonUnknown": "Season Unknown", + "NameSeasonNumber": "Season {0}", + "LabelExit": "Exit", + "LabelVisitCommunity": "Visit Community", + "LabelGithub": "Github", + "LabelApiDocumentation": "Api Documentation", + "LabelDeveloperResources": "Developer Resources", + "LabelBrowseLibrary": "Browse Library", + "LabelConfigureServer": "Configure Emby", + "LabelRestartServer": "Restart Server", + "CategorySync": "Sync", + "CategoryUser": "User", + "CategorySystem": "System", + "CategoryApplication": "Application", + "CategoryPlugin": "Plugin", + "NotificationOptionPluginError": "Plugin failure", + "NotificationOptionApplicationUpdateAvailable": "Application update available", + "NotificationOptionApplicationUpdateInstalled": "Application update installed", + "NotificationOptionPluginUpdateInstalled": "Plugin update installed", + "NotificationOptionPluginInstalled": "Plugin installed", + "NotificationOptionPluginUninstalled": "Plugin uninstalled", + "NotificationOptionVideoPlayback": "Video playback started", + "NotificationOptionAudioPlayback": "Audio playback started", + "NotificationOptionGamePlayback": "Game playback started", + "NotificationOptionVideoPlaybackStopped": "Video playback stopped", + "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", + "NotificationOptionGamePlaybackStopped": "Game playback stopped", + "NotificationOptionTaskFailed": "Scheduled task failure", + "NotificationOptionInstallationFailed": "Installation failure", + "NotificationOptionNewLibraryContent": "New content added", + "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", + "NotificationOptionUserLockedOut": "User locked out", + "NotificationOptionServerRestartRequired": "Server restart required", + "ViewTypePlaylists": "Playlists", + "ViewTypeMovies": "Movies", + "ViewTypeTvShows": "TV", + "ViewTypeGames": "Games", + "ViewTypeMusic": "Music", + "ViewTypeMusicGenres": "Genres", + "ViewTypeMusicArtists": "Artists", + "ViewTypeBoxSets": "Collections", + "ViewTypeChannels": "Channels", + "ViewTypeLiveTV": "Live TV", + "ViewTypeLiveTvNowPlaying": "Now Airing", + "ViewTypeLatestGames": "Latest Games", + "ViewTypeRecentlyPlayedGames": "Recently Played", + "ViewTypeGameFavorites": "Favorites", + "ViewTypeGameSystems": "Game Systems", + "ViewTypeGameGenres": "Genres", + "ViewTypeTvResume": "Resume", + "ViewTypeTvNextUp": "Next Up", + "ViewTypeTvLatest": "Latest", + "ViewTypeTvShowSeries": "Series", + "ViewTypeTvGenres": "Genres", + "ViewTypeTvFavoriteSeries": "Favorite Series", + "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", + "ViewTypeMovieResume": "Resume", + "ViewTypeMovieLatest": "Latest", + "ViewTypeMovieMovies": "Movies", + "ViewTypeMovieCollections": "Collections", + "ViewTypeMovieFavorites": "Favorites", + "ViewTypeMovieGenres": "Genres", + "ViewTypeMusicLatest": "Latest", + "ViewTypeMusicPlaylists": "Playlists", + "ViewTypeMusicAlbums": "Albums", + "ViewTypeMusicAlbumArtists": "Album Artists", + "HeaderOtherDisplaySettings": "Display Settings", + "ViewTypeMusicSongs": "Songs", + "ViewTypeMusicFavorites": "Favorites", + "ViewTypeMusicFavoriteAlbums": "Favorite Albums", + "ViewTypeMusicFavoriteArtists": "Favorite Artists", + "ViewTypeMusicFavoriteSongs": "Favorite Songs", + "ViewTypeFolders": "Folders", + "ViewTypeLiveTvRecordingGroups": "Recordings", + "ViewTypeLiveTvChannels": "Channels", + "ScheduledTaskFailedWithName": "{0} failed", + "LabelRunningTimeValue": "Running time: {0}", + "ScheduledTaskStartedWithName": "{0} started", + "VersionNumber": "Version {0}", + "PluginInstalledWithName": "{0} was installed", + "PluginUpdatedWithName": "{0} was updated", + "PluginUninstalledWithName": "{0} was uninstalled", + "ItemAddedWithName": "{0} was added to the library", + "ItemRemovedWithName": "{0} was removed from the library", + "LabelIpAddressValue": "Ip address: {0}", + "DeviceOnlineWithName": "{0} is connected", + "UserOnlineFromDevice": "{0} is online from {1}", + "ProviderValue": "Provider: {0}", + "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", + "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", + "UserCreatedWithName": "User {0} has been created", + "UserPasswordChangedWithName": "Password has been changed for user {0}", + "UserDeletedWithName": "User {0} has been deleted", + "MessageServerConfigurationUpdated": "Server configuration has been updated", + "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", + "MessageApplicationUpdated": "Emby Server has been updated", + "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", + "AuthenticationSucceededWithUserName": "{0} successfully authenticated", + "DeviceOfflineWithName": "{0} has disconnected", + "UserLockedOutWithName": "User {0} has been locked out", + "UserOfflineFromDevice": "{0} has disconnected from {1}", + "UserStartedPlayingItemWithValues": "{0} has started playing {1}", + "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", + "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", + "HeaderUnidentified": "Unidentified", + "HeaderImagePrimary": "Primary", + "HeaderImageBackdrop": "Backdrop", + "HeaderImageLogo": "Logo", + "HeaderUserPrimaryImage": "User Image", + "HeaderOverview": "Overview", + "HeaderShortOverview": "Short Overview", + "HeaderType": "Type", + "HeaderSeverity": "Severity", + "HeaderUser": "User", + "HeaderName": "Name", + "HeaderDate": "Date", + "HeaderPremiereDate": "Premiere Date", + "HeaderDateAdded": "Date Added", + "HeaderReleaseDate": "Release date", + "HeaderRuntime": "Runtime", + "HeaderPlayCount": "Play Count", + "HeaderSeason": "Season", + "HeaderSeasonNumber": "Season number", + "HeaderSeries": "Series:", + "HeaderNetwork": "Network", + "HeaderYear": "Year:", + "HeaderYears": "Years:", + "HeaderParentalRating": "Parental Rating", + "HeaderCommunityRating": "Community rating", + "HeaderTrailers": "Trailers", + "HeaderSpecials": "Specials", + "HeaderGameSystems": "Game Systems", + "HeaderPlayers": "Players:", + "HeaderAlbumArtists": "Album Artists", + "HeaderAlbums": "Albums", + "HeaderDisc": "Disc", + "HeaderTrack": "Track", + "HeaderAudio": "Audio", + "HeaderVideo": "Video", + "HeaderEmbeddedImage": "Embedded image", + "HeaderResolution": "Resolution", + "HeaderSubtitles": "Subtitles", + "HeaderGenres": "Genres", + "HeaderCountries": "Countries", + "HeaderStatus": "Status", + "HeaderTracks": "Tracks", + "HeaderMusicArtist": "Music artist", + "HeaderLocked": "Locked", + "HeaderStudios": "Studios", + "HeaderActor": "Actors", + "HeaderComposer": "Composers", + "HeaderDirector": "Directors", + "HeaderGuestStar": "Guest star", + "HeaderProducer": "Producers", + "HeaderWriter": "Writers", + "HeaderParentalRatings": "Parental Ratings", + "HeaderCommunityRatings": "Community ratings", + "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." } \ No newline at end of file -- cgit v1.2.3 From 6c62c20a9e3081950bf46fc96966e470ffc73b54 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 13:53:23 -0400 Subject: update CollectionFolder --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- .../Entities/CollectionFolder.cs | 27 +++++++++++++++++++--- MediaBrowser.Controller/Library/ILibraryManager.cs | 2 +- .../IO/LibraryMonitor.cs | 2 +- .../Library/LibraryManager.cs | 5 ++-- 5 files changed, 30 insertions(+), 8 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index f9f03a9c5..908d65977 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1542,7 +1542,7 @@ namespace MediaBrowser.Controller.Entities { if (!string.IsNullOrEmpty(info.Path)) { - var itemByPath = LibraryManager.FindByPath(info.Path); + var itemByPath = LibraryManager.FindByPath(info.Path, null); if (itemByPath == null) { diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 429700327..5e0cf6e88 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -8,6 +8,7 @@ using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MoreLinq; namespace MediaBrowser.Controller.Entities { @@ -97,7 +98,6 @@ namespace MediaBrowser.Controller.Entities } } - return base.IsValidFromResolver(newItem); } @@ -200,9 +200,30 @@ namespace MediaBrowser.Controller.Entities public IEnumerable GetPhysicalParents() { - return LibraryManager.RootFolder.Children + var rootChildren = LibraryManager.RootFolder.Children .OfType() - .Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase)); + .ToList(); + + return PhysicalLocations.Where(i => !string.Equals(i, Path, StringComparison.OrdinalIgnoreCase)).SelectMany(i => GetPhysicalParents(i, rootChildren)).DistinctBy(i => i.Id); + } + + private IEnumerable GetPhysicalParents(string path, List rootChildren) + { + var result = rootChildren + .Where(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase)) + .ToList(); + + if (result.Count == 0) + { + var folder = LibraryManager.FindByPath(path, true) as Folder; + + if (folder != null) + { + result.Add(folder); + } + } + + return result; } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 0f6b10b43..5388b8668 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -59,7 +59,7 @@ namespace MediaBrowser.Controller.Library /// /// The path. /// BaseItem. - BaseItem FindByPath(string path); + BaseItem FindByPath(string path, bool? isFolder); /// /// Gets the artist. diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 13a06afc2..09ca134d1 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -663,7 +663,7 @@ namespace MediaBrowser.Server.Implementations.IO while (item == null && !string.IsNullOrEmpty(path)) { - item = LibraryManager.FindByPath(path); + item = LibraryManager.FindByPath(path, null); path = Path.GetDirectoryName(path); } diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 17c4f59ba..e1bcfa861 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -801,11 +801,12 @@ namespace MediaBrowser.Server.Implementations.Library return _userRootFolder; } - public BaseItem FindByPath(string path) + public BaseItem FindByPath(string path, bool? isFolder) { var query = new InternalItemsQuery { - Path = path + Path = path, + IsFolder = isFolder }; // Only use the database result if there's exactly one item, otherwise we run the risk of returning old data that hasn't been cleaned yet. -- cgit v1.2.3 From 92bdbe22b4db258996725d7452e628d8a456f8e2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 14:44:08 -0400 Subject: disable remember track selections for live channels --- MediaBrowser.Controller/Entities/BaseItem.cs | 9 +++++++++ MediaBrowser.Controller/Entities/IHasUserData.cs | 2 ++ MediaBrowser.Controller/LiveTv/LiveTvChannel.cs | 9 +++++++++ .../Library/MediaSourceManager.cs | 14 ++++++++------ 4 files changed, 28 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 908d65977..9171c2a71 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1555,6 +1555,15 @@ namespace MediaBrowser.Controller.Entities return null; } + [IgnoreDataMember] + public virtual bool EnableRememberingTrackSelections + { + get + { + return true; + } + } + /// /// Adds a studio to the item /// diff --git a/MediaBrowser.Controller/Entities/IHasUserData.cs b/MediaBrowser.Controller/Entities/IHasUserData.cs index 34a820853..faddc3778 100644 --- a/MediaBrowser.Controller/Entities/IHasUserData.cs +++ b/MediaBrowser.Controller/Entities/IHasUserData.cs @@ -20,5 +20,7 @@ namespace MediaBrowser.Controller.Entities /// The user data. /// The user. void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user); + + bool EnableRememberingTrackSelections { get; } } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index 35b9a1959..2bb6cc182 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -45,6 +45,15 @@ namespace MediaBrowser.Controller.LiveTv set { } } + [IgnoreDataMember] + public override bool EnableRememberingTrackSelections + { + get + { + return false; + } + } + /// /// Gets or sets the number. /// diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs index 95f5cb0e1..092b797ce 100644 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -269,13 +269,15 @@ namespace MediaBrowser.Server.Implementations.Library { var userData = item == null ? new UserItemData() : _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); - SetDefaultAudioStreamIndex(source, userData, user); - SetDefaultSubtitleStreamIndex(source, userData, user); + var allowRememberingSelection = item == null || item.EnableRememberingTrackSelections; + + SetDefaultAudioStreamIndex(source, userData, user, allowRememberingSelection); + SetDefaultSubtitleStreamIndex(source, userData, user, allowRememberingSelection); } - private void SetDefaultSubtitleStreamIndex(MediaSourceInfo source, UserItemData userData, User user) + private void SetDefaultSubtitleStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection) { - if (userData.SubtitleStreamIndex.HasValue && user.Configuration.RememberSubtitleSelections && user.Configuration.SubtitleMode != SubtitlePlaybackMode.None) + if (userData.SubtitleStreamIndex.HasValue && user.Configuration.RememberSubtitleSelections && user.Configuration.SubtitleMode != SubtitlePlaybackMode.None && allowRememberingSelection) { var index = userData.SubtitleStreamIndex.Value; // Make sure the saved index is still valid @@ -304,9 +306,9 @@ namespace MediaBrowser.Server.Implementations.Library user.Configuration.SubtitleMode, audioLangage); } - private void SetDefaultAudioStreamIndex(MediaSourceInfo source, UserItemData userData, User user) + private void SetDefaultAudioStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection) { - if (userData.AudioStreamIndex.HasValue && user.Configuration.RememberAudioSelections) + if (userData.AudioStreamIndex.HasValue && user.Configuration.RememberAudioSelections && allowRememberingSelection) { var index = userData.AudioStreamIndex.Value; // Make sure the saved index is still valid -- cgit v1.2.3 From dfa2557874a3023eedb0b67601a8dee80e80683d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 15:23:05 -0400 Subject: record IsAvc --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 15 ++++++++-- .../Encoder/EncodingJobFactory.cs | 8 ++++++ .../Probing/ProbeResultNormalizer.cs | 11 ++++++++ MediaBrowser.Model/Entities/MediaStream.cs | 2 ++ .../Persistence/MediaStreamColumns.cs | 32 ++++++++++++++++++++++ .../Persistence/SqliteItemRepository.cs | 11 ++++++-- 6 files changed, 74 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 9278de3be..45f1a64c9 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -288,9 +288,9 @@ namespace MediaBrowser.Api.Playback { if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { - - return "h264_qsv"; - + + return "h264_qsv"; + } return "libx264"; @@ -1804,6 +1804,15 @@ namespace MediaBrowser.Api.Playback } } + if (string.Equals("h264", videoStream.Codec, StringComparison.OrdinalIgnoreCase)) + { + if (videoStream.IsAVC.HasValue && !videoStream.IsAVC.Value) + { + Logger.Debug("Cannot stream copy video. Stream is marked as not AVC"); + return false; + } + } + // Source and target codecs must match if (!string.Equals(request.VideoCodec, videoStream.Codec, StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index 070aae3a7..ff5a3010e 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -575,6 +575,14 @@ namespace MediaBrowser.MediaEncoding.Encoder return false; } + if (string.Equals("h264", videoStream.Codec, StringComparison.OrdinalIgnoreCase)) + { + if (videoStream.IsAVC.HasValue && !videoStream.IsAVC.Value) + { + return false; + } + } + // If client is requesting a specific video profile, it must match the source if (!string.IsNullOrEmpty(request.Profile)) { diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 38528d845..c7c001cee 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -411,6 +411,17 @@ namespace MediaBrowser.MediaEncoding.Probing NalLengthSize = streamInfo.nal_length_size }; + if (string.Equals(streamInfo.is_avc, "true", StringComparison.OrdinalIgnoreCase) || + string.Equals(streamInfo.is_avc, "1", StringComparison.OrdinalIgnoreCase)) + { + stream.IsAVC = true; + } + else if (string.Equals(streamInfo.is_avc, "false", StringComparison.OrdinalIgnoreCase) || + string.Equals(streamInfo.is_avc, "0", StringComparison.OrdinalIgnoreCase)) + { + stream.IsAVC = false; + } + // Filter out junk if (!string.IsNullOrWhiteSpace(streamInfo.codec_tag_string) && streamInfo.codec_tag_string.IndexOf("[0]", StringComparison.OrdinalIgnoreCase) == -1) { diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index fa7a51291..25252956b 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -42,6 +42,8 @@ namespace MediaBrowser.Model.Entities /// true if this instance is interlaced; otherwise, false. public bool IsInterlaced { get; set; } + public bool? IsAVC { get; set; } + /// /// Gets or sets the channel layout. /// diff --git a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs index debcd054f..76682c63b 100644 --- a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs +++ b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs @@ -26,6 +26,38 @@ namespace MediaBrowser.Server.Implementations.Persistence AddCodecTagColumn(); AddCommentColumn(); AddNalColumn(); + AddIsAvcColumn(); + } + + private void AddIsAvcColumn() + { + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = "PRAGMA table_info(mediastreams)"; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + if (!reader.IsDBNull(1)) + { + var name = reader.GetString(1); + + if (string.Equals(name, "IsAvc", StringComparison.OrdinalIgnoreCase)) + { + return; + } + } + } + } + } + + var builder = new StringBuilder(); + + builder.AppendLine("alter table mediastreams"); + builder.AppendLine("add column IsAvc BIT NULL"); + + _connection.RunQueries(new[] { builder.ToString() }, _logger); } private void AddNalColumn() diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index fcc39deb5..783bd5ff4 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -124,7 +124,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); var createMediaStreamsTableCommand - = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; + = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, IsAvc BIT NULL, PRIMARY KEY (ItemId, StreamIndex))"; string[] queries = { @@ -391,7 +391,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "RefFrames", "CodecTag", "Comment", - "NalLengthSize" + "NalLengthSize", + "IsAvc" }; /// @@ -2897,6 +2898,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; _saveStreamCommand.GetParameter(index++).Value = stream.Comment; _saveStreamCommand.GetParameter(index++).Value = stream.NalLengthSize; + _saveStreamCommand.GetParameter(index++).Value = stream.IsAVC; _saveStreamCommand.Transaction = transaction; _saveStreamCommand.ExecuteNonQuery(); @@ -3060,6 +3062,11 @@ namespace MediaBrowser.Server.Implementations.Persistence item.NalLengthSize = reader.GetString(27); } + if (!reader.IsDBNull(28)) + { + item.IsAVC = reader.GetBoolean(28); + } + return item; } -- cgit v1.2.3 From f7128c7f8f04a39272ec10c699f3a05dac1a8e67 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 16:24:53 -0400 Subject: resync media after changes --- MediaBrowser.Model/Sync/SyncJobItem.cs | 2 ++ .../Sync/SyncJobProcessor.cs | 6 ++++++ MediaBrowser.Server.Implementations/Sync/SyncManager.cs | 16 +++++++++++++++- .../Sync/SyncRepository.cs | 9 ++++++++- 4 files changed, 31 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Model/Sync/SyncJobItem.cs b/MediaBrowser.Model/Sync/SyncJobItem.cs index 77464be58..1c72ccd52 100644 --- a/MediaBrowser.Model/Sync/SyncJobItem.cs +++ b/MediaBrowser.Model/Sync/SyncJobItem.cs @@ -102,6 +102,8 @@ namespace MediaBrowser.Model.Sync /// The index of the job item. public int JobItemIndex { get; set; } + public long ItemDateModifiedTicks { get; set; } + public SyncJobItem() { AdditionalFiles = new List(); diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index 33874b4d4..0bec528bb 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -632,6 +632,7 @@ namespace MediaBrowser.Server.Implementations.Sync }, innerProgress, cancellationToken); + jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; _syncManager.OnConversionComplete(jobItem); } catch (OperationCanceledException) @@ -668,6 +669,7 @@ namespace MediaBrowser.Server.Implementations.Sync throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol)); } + jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; jobItem.MediaSource = mediaSource; } @@ -819,6 +821,7 @@ namespace MediaBrowser.Server.Implementations.Sync }, innerProgress, cancellationToken); + jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; _syncManager.OnConversionComplete(jobItem); } catch (OperationCanceledException) @@ -855,6 +858,7 @@ namespace MediaBrowser.Server.Implementations.Sync throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol)); } + jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; jobItem.MediaSource = mediaSource; } @@ -871,6 +875,7 @@ namespace MediaBrowser.Server.Implementations.Sync jobItem.Progress = 50; jobItem.Status = SyncJobItemStatus.ReadyToTransfer; + jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); } @@ -880,6 +885,7 @@ namespace MediaBrowser.Server.Implementations.Sync jobItem.Progress = 50; jobItem.Status = SyncJobItemStatus.ReadyToTransfer; + jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index 044c8b93a..fe1a7fb28 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -775,6 +775,13 @@ namespace MediaBrowser.Server.Implementations.Sync removeFromDevice = true; } } + else if (libraryItem != null && libraryItem.DateModified.Ticks != jobItem.ItemDateModifiedTicks && jobItem.ItemDateModifiedTicks > 0) + { + _logger.Info("Setting status to Queued for {0} because the media has been modified since the original sync.", jobItem.ItemId); + jobItem.Status = SyncJobItemStatus.Queued; + jobItem.Progress = 0; + requiresSaving = true; + } } else { @@ -881,6 +888,13 @@ namespace MediaBrowser.Server.Implementations.Sync removeFromDevice = true; } } + else if (libraryItem != null && libraryItem.DateModified.Ticks != jobItem.ItemDateModifiedTicks && jobItem.ItemDateModifiedTicks > 0) + { + _logger.Info("Setting status to Queued for {0} because the media has been modified since the original sync.", jobItem.ItemId); + jobItem.Status = SyncJobItemStatus.Queued; + jobItem.Progress = 0; + requiresSaving = true; + } } else { @@ -1117,7 +1131,7 @@ namespace MediaBrowser.Server.Implementations.Sync public SyncJobOptions GetAudioOptions(SyncJobItem jobItem, SyncJob job) { var options = GetSyncJobOptions(jobItem.TargetId, null, null); - + if (job.Bitrate.HasValue) { options.DeviceProfile.MaxStaticBitrate = job.Bitrate.Value; diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs index 464e8aa58..249c4212e 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs @@ -50,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.Sync "create table if not exists SyncJobs (Id GUID PRIMARY KEY, TargetId TEXT NOT NULL, Name TEXT NOT NULL, Profile TEXT, Quality TEXT, Bitrate INT, Status TEXT NOT NULL, Progress FLOAT, UserId TEXT NOT NULL, ItemIds TEXT NOT NULL, Category TEXT, ParentId TEXT, UnwatchedOnly BIT, ItemLimit INT, SyncNewContent BIT, DateCreated DateTime, DateLastModified DateTime, ItemCount int)", "create index if not exists idx_SyncJobs on SyncJobs(Id)", - "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, ItemName TEXT, MediaSourceId TEXT, JobId TEXT, TemporaryPath TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT, AdditionalFiles TEXT, MediaSource TEXT, IsMarkedForRemoval BIT, JobItemIndex INT)", + "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, ItemName TEXT, MediaSourceId TEXT, JobId TEXT, TemporaryPath TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT, AdditionalFiles TEXT, MediaSource TEXT, IsMarkedForRemoval BIT, JobItemIndex INT, ItemDateModifiedTicks BIGINT)", "create index if not exists idx_SyncJobItems on SyncJobs(Id)", //pragmas @@ -63,6 +63,7 @@ namespace MediaBrowser.Server.Implementations.Sync _connection.AddColumn(Logger, "SyncJobs", "Profile", "TEXT"); _connection.AddColumn(Logger, "SyncJobs", "Bitrate", "INT"); + _connection.AddColumn(Logger, "SyncJobItems", "ItemDateModifiedTicks", "BIGINT"); PrepareStatements(); } @@ -678,6 +679,7 @@ namespace MediaBrowser.Server.Implementations.Sync cmd.GetParameter(index++).Value = jobItem.MediaSource == null ? null : _json.SerializeToString(jobItem.MediaSource); cmd.GetParameter(index++).Value = jobItem.IsMarkedForRemoval; cmd.GetParameter(index++).Value = jobItem.JobItemIndex; + cmd.GetParameter(index++).Value = jobItem.ItemDateModifiedTicks; cmd.Transaction = transaction; @@ -782,6 +784,11 @@ namespace MediaBrowser.Server.Implementations.Sync info.IsMarkedForRemoval = reader.GetBoolean(13); info.JobItemIndex = reader.GetInt32(14); + if (!reader.IsDBNull(15)) + { + info.ItemDateModifiedTicks = reader.GetInt64(15); + } + return info; } -- cgit v1.2.3 From d54f791159ecdf82e80c54ac663614eedf57f959 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 16:29:27 -0400 Subject: update resync --- MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs | 5 +++++ MediaBrowser.Server.Implementations/Sync/SyncRepository.cs | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index 0bec528bb..10b872753 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -149,6 +149,11 @@ namespace MediaBrowser.Server.Implementations.Sync { var job = _syncRepo.GetJob(id); + if (job == null) + { + return Task.FromResult(true); + } + var result = _syncManager.GetJobItems(new SyncJobItemQuery { JobId = job.Id, diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs index 249c4212e..965c081eb 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs @@ -128,7 +128,7 @@ namespace MediaBrowser.Server.Implementations.Sync // _insertJobItemCommand _insertJobItemCommand = _connection.CreateCommand(); - _insertJobItemCommand.CommandText = "insert into SyncJobItems (Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex) values (@Id, @ItemId, @ItemName, @MediaSourceId, @JobId, @TemporaryPath, @OutputPath, @Status, @TargetId, @DateCreated, @Progress, @AdditionalFiles, @MediaSource, @IsMarkedForRemoval, @JobItemIndex)"; + _insertJobItemCommand.CommandText = "insert into SyncJobItems (Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex, ItemDateModifiedTicks) values (@Id, @ItemId, @ItemName, @MediaSourceId, @JobId, @TemporaryPath, @OutputPath, @Status, @TargetId, @DateCreated, @Progress, @AdditionalFiles, @MediaSource, @IsMarkedForRemoval, @JobItemIndex, @ItemDateModifiedTicks)"; _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@Id"); _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@ItemId"); @@ -145,10 +145,11 @@ namespace MediaBrowser.Server.Implementations.Sync _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@MediaSource"); _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@IsMarkedForRemoval"); _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@JobItemIndex"); + _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@ItemDateModifiedTicks"); // _updateJobItemCommand _updateJobItemCommand = _connection.CreateCommand(); - _updateJobItemCommand.CommandText = "update SyncJobItems set ItemId=@ItemId,ItemName=@ItemName,MediaSourceId=@MediaSourceId,JobId=@JobId,TemporaryPath=@TemporaryPath,OutputPath=@OutputPath,Status=@Status,TargetId=@TargetId,DateCreated=@DateCreated,Progress=@Progress,AdditionalFiles=@AdditionalFiles,MediaSource=@MediaSource,IsMarkedForRemoval=@IsMarkedForRemoval,JobItemIndex=@JobItemIndex where Id=@Id"; + _updateJobItemCommand.CommandText = "update SyncJobItems set ItemId=@ItemId,ItemName=@ItemName,MediaSourceId=@MediaSourceId,JobId=@JobId,TemporaryPath=@TemporaryPath,OutputPath=@OutputPath,Status=@Status,TargetId=@TargetId,DateCreated=@DateCreated,Progress=@Progress,AdditionalFiles=@AdditionalFiles,MediaSource=@MediaSource,IsMarkedForRemoval=@IsMarkedForRemoval,JobItemIndex=@JobItemIndex,ItemDateModifiedTicks=@ItemDateModifiedTicks where Id=@Id"; _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@Id"); _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@ItemId"); @@ -165,10 +166,11 @@ namespace MediaBrowser.Server.Implementations.Sync _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@MediaSource"); _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@IsMarkedForRemoval"); _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@JobItemIndex"); + _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@ItemDateModifiedTicks"); } private const string BaseJobSelectText = "select Id, TargetId, Name, Profile, Quality, Bitrate, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount from SyncJobs"; - private const string BaseJobItemSelectText = "select Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex from SyncJobItems"; + private const string BaseJobItemSelectText = "select Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex, ItemDateModifiedTicks from SyncJobItems"; public SyncJob GetJob(string id) { -- cgit v1.2.3 From 747518decc3e59a9c6b01f31e5360ce194919d8d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 17:26:28 -0400 Subject: added option to preserve original audio when recording --- MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 1 + MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 6 ++++-- .../LiveTv/EmbyTV/EncodedRecorder.cs | 7 +++++-- 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index 46f630fe0..fc2b155ec 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -9,6 +9,7 @@ namespace MediaBrowser.Model.LiveTv public string RecordingPath { get; set; } public bool EnableAutoOrganize { get; set; } public bool EnableRecordingEncoding { get; set; } + public bool EnableOriginalAudioWithEncodedRecordings { get; set; } public List TunerHosts { get; set; } public List ListingProviders { get; set; } diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index d85e8ba3f..351bc05af 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -927,13 +927,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private async Task GetRecorder() { - if (GetConfiguration().EnableRecordingEncoding) + var config = GetConfiguration(); + + if (config.EnableRecordingEncoding) { var regInfo = await _security.GetRegistrationStatus("embytvrecordingconversion").ConfigureAwait(false); if (regInfo.IsValid) { - return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer); + return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, config); } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 442f151dd..63d0846fc 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -12,6 +12,7 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; @@ -23,6 +24,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private readonly IFileSystem _fileSystem; private readonly IMediaEncoder _mediaEncoder; private readonly IApplicationPaths _appPaths; + private readonly LiveTvOptions _liveTvOptions; private bool _hasExited; private Stream _logFileStream; private string _targetPath; @@ -30,13 +32,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private readonly IJsonSerializer _json; private readonly TaskCompletionSource _taskCompletionSource = new TaskCompletionSource(); - public EncodedRecorder(ILogger logger, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IApplicationPaths appPaths, IJsonSerializer json) + public EncodedRecorder(ILogger logger, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IApplicationPaths appPaths, IJsonSerializer json, LiveTvOptions liveTvOptions) { _logger = logger; _fileSystem = fileSystem; _mediaEncoder = mediaEncoder; _appPaths = appPaths; _json = json; + _liveTvOptions = liveTvOptions; } public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) @@ -129,7 +132,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { var copyAudio = new[] { "aac", "mp3" }; var mediaStreams = mediaSource.MediaStreams ?? new List(); - if (mediaStreams.Any(i => i.Type == MediaStreamType.Audio && copyAudio.Contains(i.Codec, StringComparer.OrdinalIgnoreCase))) + if (_liveTvOptions.EnableOriginalAudioWithEncodedRecordings || mediaStreams.Any(i => i.Type == MediaStreamType.Audio && copyAudio.Contains(i.Codec, StringComparer.OrdinalIgnoreCase))) { return "-codec:a:0 copy"; } -- cgit v1.2.3 From 87091b6196941fdbbb11408ef1480a6f4175af49 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 21:59:09 -0400 Subject: update providers --- MediaBrowser.Controller/Entities/Video.cs | 5 +++++ MediaBrowser.LocalMetadata/BaseXmlProvider.cs | 6 +++--- MediaBrowser.Providers/Manager/MetadataService.cs | 12 ++++++------ .../TV/TheTVDB/TvdbEpisodeImageProvider.cs | 6 +++--- MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs | 6 +++--- .../Photos/BaseDynamicImageProvider.cs | 4 ++-- MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs | 6 +++--- 7 files changed, 25 insertions(+), 20 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 2c7d3856b..d81e6f0ff 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -317,6 +317,11 @@ namespace MediaBrowser.Controller.Entities { return false; } + + if (newAsVideo.VideoType != VideoType) + { + return false; + } } return base.IsValidFromResolver(newItem); diff --git a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs index 4fc1d210d..4b64295ea 100644 --- a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs @@ -8,7 +8,7 @@ using CommonIO; namespace MediaBrowser.LocalMetadata { - public abstract class BaseXmlProvider : ILocalMetadataProvider, IHasChangeMonitor, IHasOrder + public abstract class BaseXmlProvider : ILocalMetadataProvider, IHasItemChangeMonitor, IHasOrder where T : IHasMetadata, new() { protected IFileSystem FileSystem; @@ -56,7 +56,7 @@ namespace MediaBrowser.LocalMetadata protected abstract FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService); - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { var file = GetXmlFile(new ItemInfo(item), directoryService); @@ -65,7 +65,7 @@ namespace MediaBrowser.LocalMetadata return false; } - return file.Exists && FileSystem.GetLastWriteTimeUtc(file) > date; + return file.Exists && FileSystem.GetLastWriteTimeUtc(file) > item.DateLastSaved; } public string Name diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index cb5e6c88f..ae48c996a 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -430,18 +430,18 @@ namespace MediaBrowser.Providers.Manager var providersWithChanges = providers .Where(i => { - var hasChangeMonitor = i as IHasChangeMonitor; - if (hasChangeMonitor != null) - { - return HasChanged(item, hasChangeMonitor, currentItem.DateLastSaved, options.DirectoryService); - } - var hasFileChangeMonitor = i as IHasItemChangeMonitor; if (hasFileChangeMonitor != null) { return HasChanged(item, hasFileChangeMonitor, options.DirectoryService); } + var hasChangeMonitor = i as IHasChangeMonitor; + if (hasChangeMonitor != null) + { + return HasChanged(item, hasChangeMonitor, currentItem.DateLastSaved, options.DirectoryService); + } + return false; }) .ToList(); diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs index 49d41e06c..ca3320cc6 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs @@ -17,7 +17,7 @@ using CommonIO; namespace MediaBrowser.Providers.TV { - public class TvdbEpisodeImageProvider : IRemoteImageProvider, IHasChangeMonitor + public class TvdbEpisodeImageProvider : IRemoteImageProvider, IHasItemChangeMonitor { private readonly IServerConfigurationManager _config; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); @@ -174,7 +174,7 @@ namespace MediaBrowser.Providers.TV }); } - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { var episode = (Episode)item; @@ -196,7 +196,7 @@ namespace MediaBrowser.Providers.TV // Process images var seriesXmlPath = TvdbSeriesProvider.Current.GetSeriesXmlPath(series.ProviderIds, series.GetPreferredMetadataLanguage()); - return _fileSystem.GetLastWriteTimeUtc(seriesXmlPath) > date; + return _fileSystem.GetLastWriteTimeUtc(seriesXmlPath) > item.DateLastRefreshed; } } diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs index 291214fcd..5c88c87d8 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs @@ -24,7 +24,7 @@ namespace MediaBrowser.Providers.TV /// /// Class RemoteEpisodeProvider /// - class TvdbEpisodeProvider : IRemoteMetadataProvider, IItemIdentityProvider, IHasChangeMonitor + class TvdbEpisodeProvider : IRemoteMetadataProvider, IItemIdentityProvider, IHasItemChangeMonitor { private static readonly string FullIdKey = MetadataProviders.Tvdb + "-Full"; @@ -144,7 +144,7 @@ namespace MediaBrowser.Providers.TV return result; } - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { // Only enable for virtual items if (item.LocationType != LocationType.Virtual) @@ -160,7 +160,7 @@ namespace MediaBrowser.Providers.TV // Process images var seriesXmlPath = TvdbSeriesProvider.Current.GetSeriesXmlPath(series.ProviderIds, series.GetPreferredMetadataLanguage()); - return _fileSystem.GetLastWriteTimeUtc(seriesXmlPath) > date; + return _fileSystem.GetLastWriteTimeUtc(seriesXmlPath) > item.DateLastRefreshed; } return false; diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index 4a69646f8..acb1227e4 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -17,7 +17,7 @@ using MediaBrowser.Model.Configuration; namespace MediaBrowser.Server.Implementations.Photos { - public abstract class BaseDynamicImageProvider : IHasChangeMonitor, IForcedProvider, ICustomMetadataProvider, IHasOrder + public abstract class BaseDynamicImageProvider : IHasItemChangeMonitor, IForcedProvider, ICustomMetadataProvider, IHasOrder where T : IHasMetadata { protected IFileSystem FileSystem { get; private set; } @@ -247,7 +247,7 @@ namespace MediaBrowser.Server.Implementations.Photos get { return 7; } } - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryServicee) { if (!Supports(item)) { diff --git a/MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs index 5ce8d30ad..c1dd92987 100644 --- a/MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs @@ -9,7 +9,7 @@ using CommonIO; namespace MediaBrowser.XbmcMetadata.Providers { - public abstract class BaseNfoProvider : ILocalMetadataProvider, IHasChangeMonitor + public abstract class BaseNfoProvider : ILocalMetadataProvider, IHasItemChangeMonitor where T : IHasMetadata, new() { protected IFileSystem FileSystem; @@ -57,7 +57,7 @@ namespace MediaBrowser.XbmcMetadata.Providers protected abstract FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService); - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { var file = GetXmlFile(new ItemInfo(item), directoryService); @@ -66,7 +66,7 @@ namespace MediaBrowser.XbmcMetadata.Providers return false; } - return file.Exists && FileSystem.GetLastWriteTimeUtc(file) > date; + return file.Exists && FileSystem.GetLastWriteTimeUtc(file) > item.DateLastSaved; } public string Name -- cgit v1.2.3 From 8537cbe6c2e1b6a5508d3f13bf0ec0224e88b452 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Apr 2016 12:54:26 -0400 Subject: add audio sync to converted recordings --- MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 63d0846fc..fa4f82136 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -143,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { audioChannels = audioStream.Channels ?? audioChannels; } - return "-codec:a:0 aac -strict experimental -ab 320000"; + return "-codec:a:0 aac -strict experimental -ab 320000 -af \"async=1000\""; } private bool EncodeVideo(MediaSourceInfo mediaSource) -- cgit v1.2.3 From 1a02365f781f01e1efe9b12241a7368ae1cd5ba8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Apr 2016 23:59:46 -0400 Subject: cinema mode fixes --- MediaBrowser.Controller/Entities/InternalItemsQuery.cs | 2 -- .../Intros/DefaultIntroProvider.cs | 7 +------ .../Library/LocalTrailerPostScanTask.cs | 11 +++++++---- .../Persistence/SqliteItemRepository.cs | 14 -------------- 4 files changed, 8 insertions(+), 26 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index fbf246b3a..f3b4f4053 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -123,7 +123,6 @@ namespace MediaBrowser.Controller.Entities public SourceType[] SourceTypes { get; set; } public SourceType[] ExcludeSourceTypes { get; set; } public TrailerType[] TrailerTypes { get; set; } - public TrailerType[] ExcludeTrailerTypes { get; set; } public DayOfWeek[] AirDays { get; set; } public SeriesStatus[] SeriesStatuses { get; set; } @@ -165,7 +164,6 @@ namespace MediaBrowser.Controller.Entities SourceTypes = new SourceType[] { }; ExcludeSourceTypes = new SourceType[] { }; TrailerTypes = new TrailerType[] { }; - ExcludeTrailerTypes = new TrailerType[] { }; AirDays = new DayOfWeek[] { }; SeriesStatuses = new SeriesStatus[] { }; } diff --git a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs index 9ebae5d91..49012c65a 100644 --- a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs +++ b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs @@ -102,15 +102,10 @@ namespace MediaBrowser.Server.Implementations.Intros if (trailerTypes.Count > 0) { - var excludeTrailerTypes = Enum.GetNames(typeof(TrailerType)) - .Select(i => (TrailerType)Enum.Parse(typeof(TrailerType), i, true)) - .Except(trailerTypes) - .ToArray(); - var trailerResult = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = new[] { typeof(Trailer).Name }, - ExcludeTrailerTypes = excludeTrailerTypes + TrailerTypes = trailerTypes.ToArray() }); candidates.AddRange(trailerResult.Select(i => new ItemWithTrailer diff --git a/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs index 96d570ef9..5fc9c3168 100644 --- a/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs +++ b/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs @@ -27,13 +27,16 @@ namespace MediaBrowser.Server.Implementations.Library .Cast() .ToList(); + var trailerTypes = Enum.GetNames(typeof(TrailerType)) + .Select(i => (TrailerType)Enum.Parse(typeof(TrailerType), i, true)) + .Except(new[] { TrailerType.LocalTrailer }) + .ToArray(); + var trailers = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = new[] { typeof(Trailer).Name }, - ExcludeTrailerTypes = new[] - { - TrailerType.LocalTrailer - } + TrailerTypes = trailerTypes + }).ToArray(); var numComplete = 0; diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 783bd5ff4..4f724fe40 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1961,20 +1961,6 @@ namespace MediaBrowser.Server.Implementations.Persistence whereClauses.Add(clause); } - if (query.ExcludeTrailerTypes.Length > 0) - { - var clauses = new List(); - var index = 0; - foreach (var type in query.ExcludeTrailerTypes) - { - clauses.Add("(TrailerTypes is null OR TrailerTypes not like @TrailerTypes" + index + ")"); - cmd.Parameters.Add(cmd, "@TrailerTypes" + index, DbType.String).Value = "%" + type + "%"; - index++; - } - var clause = "(" + string.Join(" AND ", clauses.ToArray()) + ")"; - whereClauses.Add(clause); - } - if (query.IsAiring.HasValue) { if (query.IsAiring.Value) -- cgit v1.2.3 From 5d28c65783f850db58ea990a04ec09da38c24442 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 00:00:28 -0400 Subject: update recordings --- .../LiveTv/EmbyTV/DirectRecorder.cs | 10 +++++++++- .../LiveTv/EmbyTV/EncodedRecorder.cs | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 98249f5ac..54443d9ca 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -42,8 +42,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV _logger.Info("Copying recording stream to file {0}", targetFile); - if (!mediaSource.RunTimeTicks.HasValue) + if (mediaSource.RunTimeTicks.HasValue) { + // The media source already has a fixed duration + // But add another stop 1 minute later just in case the recording gets stuck for any reason + var durationToken = new CancellationTokenSource(duration.Add(TimeSpan.FromMinutes(1))); + cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + } + else + { + // The media source if infinite so we need to handle stopping ourselves var durationToken = new CancellationTokenSource(duration); cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; } diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index fa4f82136..d589b2bc3 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -44,6 +44,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) { + if (mediaSource.RunTimeTicks.HasValue) + { + // The media source already has a fixed duration + // But add another stop 1 minute later just in case the recording gets stuck for any reason + var durationToken = new CancellationTokenSource(duration.Add(TimeSpan.FromMinutes(1))); + cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + } + else + { + // The media source if infinite so we need to handle stopping ourselves + var durationToken = new CancellationTokenSource(duration); + cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + } + _targetPath = targetFile; _fileSystem.CreateDirectory(Path.GetDirectoryName(targetFile)); -- cgit v1.2.3 From 04ba2d57aca90ade64fafac0f3cd474645c79154 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 14:22:54 -0400 Subject: fixes #1562 - Sync status included in BaseItemDto does not reflect actual sync status. --- MediaBrowser.Server.Implementations/Dto/DtoService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 2ee55edb9..7adde5c27 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -282,7 +282,7 @@ namespace MediaBrowser.Server.Implementations.Dto else if (dto.HasSyncJob.Value) { - dto.SyncStatus = SyncJobItemStatus.Queued; + dto.SyncStatus = syncProgress.Where(i => string.Equals(i.ItemId, dto.Id, StringComparison.OrdinalIgnoreCase)).Select(i => i.Status).Max(); } } } @@ -307,7 +307,7 @@ namespace MediaBrowser.Server.Implementations.Dto else if (dto.HasSyncJob.Value) { - dto.SyncStatus = SyncJobItemStatus.Queued; + dto.SyncStatus = syncProgress.Where(i => string.Equals(i.ItemId, dto.Id, StringComparison.OrdinalIgnoreCase)).Select(i => i.Status).Max(); } } } -- cgit v1.2.3 From a15a762ba114683ffcc4c6aab5974d24f8f32c02 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 15:16:43 -0400 Subject: fixes #1484 - (Feature request) Make emby choose output stream based on ffmpeg config --- MediaBrowser.Api/Playback/MediaInfoService.cs | 7 ++++-- .../MediaEncoding/IMediaEncoder.cs | 3 ++- .../ContentDirectory/ContentDirectory.cs | 8 +++++-- .../ContentDirectory/ControlHandler.cs | 7 ++++-- MediaBrowser.Dlna/Didl/DidlBuilder.cs | 9 +++++--- MediaBrowser.Dlna/Main/DlnaEntryPoint.cs | 8 +++++-- MediaBrowser.Dlna/PlayTo/PlayToController.cs | 11 +++++---- MediaBrowser.Dlna/PlayTo/PlayToManager.cs | 8 +++++-- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 26 ++++++++++++++++++++-- MediaBrowser.Model/Dlna/ILocalPlayer.cs | 13 +++++++++++ MediaBrowser.Model/Dlna/StreamBuilder.cs | 23 +++++++++++++++---- .../Sync/SyncJobProcessor.cs | 4 ++-- .../ApplicationHost.cs | 2 +- .../FFMpeg/FFmpegValidator.cs | 4 +++- 14 files changed, 105 insertions(+), 28 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index ffe7c50c8..2d9cc40c0 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -15,6 +15,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Controller.MediaEncoding; namespace MediaBrowser.Api.Playback { @@ -66,14 +67,16 @@ namespace MediaBrowser.Api.Playback private readonly ILibraryManager _libraryManager; private readonly IServerConfigurationManager _config; private readonly INetworkManager _networkManager; + private readonly IMediaEncoder _mediaEncoder; - public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager, IServerConfigurationManager config, INetworkManager networkManager) + public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager, IServerConfigurationManager config, INetworkManager networkManager, IMediaEncoder mediaEncoder) { _mediaSourceManager = mediaSourceManager; _deviceManager = deviceManager; _libraryManager = libraryManager; _config = config; _networkManager = networkManager; + _mediaEncoder = mediaEncoder; } public object Get(GetBitrateTestBytes request) @@ -241,7 +244,7 @@ namespace MediaBrowser.Api.Playback int? subtitleStreamIndex, string playSessionId) { - var streamBuilder = new StreamBuilder(Logger); + var streamBuilder = new StreamBuilder(_mediaEncoder, Logger); var options = new VideoOptions { diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index d2feb4116..7c3959f6e 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -4,13 +4,14 @@ using System; using System.IO; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Dlna; namespace MediaBrowser.Controller.MediaEncoding { /// /// Interface IMediaEncoder /// - public interface IMediaEncoder + public interface IMediaEncoder : ITranscoderSupport { /// /// Gets the encoder path. diff --git a/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs b/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs index 21289970e..093b37df3 100644 --- a/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs +++ b/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs @@ -12,6 +12,7 @@ using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; using System.Linq; +using MediaBrowser.Controller.MediaEncoding; namespace MediaBrowser.Dlna.ContentDirectory { @@ -27,6 +28,7 @@ namespace MediaBrowser.Dlna.ContentDirectory private readonly IChannelManager _channelManager; private readonly IMediaSourceManager _mediaSourceManager; private readonly IUserViewManager _userViewManager; + private readonly Func _mediaEncoder; public ContentDirectory(IDlnaManager dlna, IUserDataManager userDataManager, @@ -35,7 +37,7 @@ namespace MediaBrowser.Dlna.ContentDirectory IServerConfigurationManager config, IUserManager userManager, ILogger logger, - IHttpClient httpClient, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager) + IHttpClient httpClient, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager, Func mediaEncoder) : base(logger, httpClient) { _dlna = dlna; @@ -48,6 +50,7 @@ namespace MediaBrowser.Dlna.ContentDirectory _channelManager = channelManager; _mediaSourceManager = mediaSourceManager; _userViewManager = userViewManager; + _mediaEncoder = mediaEncoder; } private int SystemUpdateId @@ -89,7 +92,8 @@ namespace MediaBrowser.Dlna.ContentDirectory _localization, _channelManager, _mediaSourceManager, - _userViewManager) + _userViewManager, + _mediaEncoder()) .ProcessControlRequest(request); } diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs index 01c7c33b6..34fb2a6df 100644 --- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs +++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs @@ -23,6 +23,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; +using MediaBrowser.Controller.MediaEncoding; namespace MediaBrowser.Dlna.ContentDirectory { @@ -34,6 +35,7 @@ namespace MediaBrowser.Dlna.ContentDirectory private readonly IServerConfigurationManager _config; private readonly User _user; private readonly IUserViewManager _userViewManager; + private readonly IMediaEncoder _mediaEncoder; private const string NS_DC = "http://purl.org/dc/elements/1.1/"; private const string NS_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"; @@ -47,7 +49,7 @@ namespace MediaBrowser.Dlna.ContentDirectory private readonly DeviceProfile _profile; - public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, string accessToken, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager) + public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, string accessToken, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager, IMediaEncoder mediaEncoder) : base(config, logger) { _libraryManager = libraryManager; @@ -56,10 +58,11 @@ namespace MediaBrowser.Dlna.ContentDirectory _systemUpdateId = systemUpdateId; _channelManager = channelManager; _userViewManager = userViewManager; + _mediaEncoder = mediaEncoder; _profile = profile; _config = config; - _didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, mediaSourceManager, Logger, libraryManager); + _didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, mediaSourceManager, Logger, libraryManager, _mediaEncoder); } protected override IEnumerable> GetResult(string methodName, Headers methodParams) diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index 89d00eb32..af833a85c 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -19,6 +19,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Xml; +using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Configuration; namespace MediaBrowser.Dlna.Didl @@ -42,8 +43,9 @@ namespace MediaBrowser.Dlna.Didl private readonly IMediaSourceManager _mediaSourceManager; private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; + private readonly IMediaEncoder _mediaEncoder; - public DidlBuilder(DeviceProfile profile, User user, IImageProcessor imageProcessor, string serverAddress, string accessToken, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, ILogger logger, ILibraryManager libraryManager) + public DidlBuilder(DeviceProfile profile, User user, IImageProcessor imageProcessor, string serverAddress, string accessToken, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, ILogger logger, ILibraryManager libraryManager, IMediaEncoder mediaEncoder) { _profile = profile; _imageProcessor = imageProcessor; @@ -53,6 +55,7 @@ namespace MediaBrowser.Dlna.Didl _mediaSourceManager = mediaSourceManager; _logger = logger; _libraryManager = libraryManager; + _mediaEncoder = mediaEncoder; _accessToken = accessToken; _user = user; } @@ -142,7 +145,7 @@ namespace MediaBrowser.Dlna.Didl { var sources = _mediaSourceManager.GetStaticMediaSources(video, true, _user).ToList(); - streamInfo = new StreamBuilder(GetStreamBuilderLogger(options)).BuildVideoItem(new VideoOptions + streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildVideoItem(new VideoOptions { ItemId = GetClientId(video), MediaSources = sources, @@ -385,7 +388,7 @@ namespace MediaBrowser.Dlna.Didl { var sources = _mediaSourceManager.GetStaticMediaSources(audio, true, _user).ToList(); - streamInfo = new StreamBuilder(GetStreamBuilderLogger(options)).BuildAudioItem(new AudioOptions + streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildAudioItem(new AudioOptions { ItemId = GetClientId(audio), MediaSources = sources, diff --git a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs index 37584f006..733bda9ae 100644 --- a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs +++ b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs @@ -14,6 +14,7 @@ using MediaBrowser.Dlna.Ssdp; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; +using MediaBrowser.Controller.MediaEncoding; namespace MediaBrowser.Dlna.Main { @@ -34,6 +35,7 @@ namespace MediaBrowser.Dlna.Main private readonly IUserDataManager _userDataManager; private readonly ILocalizationManager _localization; private readonly IMediaSourceManager _mediaSourceManager; + private readonly IMediaEncoder _mediaEncoder; private readonly SsdpHandler _ssdpHandler; private readonly IDeviceDiscovery _deviceDiscovery; @@ -54,7 +56,7 @@ namespace MediaBrowser.Dlna.Main IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, - ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery) + ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery, IMediaEncoder mediaEncoder) { _config = config; _appHost = appHost; @@ -69,6 +71,7 @@ namespace MediaBrowser.Dlna.Main _localization = localization; _mediaSourceManager = mediaSourceManager; _deviceDiscovery = deviceDiscovery; + _mediaEncoder = mediaEncoder; _ssdpHandler = (SsdpHandler)ssdpHandler; _logger = logManager.GetLogger("Dlna"); } @@ -196,7 +199,8 @@ namespace MediaBrowser.Dlna.Main _config, _userDataManager, _localization, - _mediaSourceManager); + _mediaSourceManager, + _mediaEncoder); _manager.Start(); } diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index db5e0ee29..80bb756ef 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -18,6 +18,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.MediaEncoding; namespace MediaBrowser.Dlna.PlayTo { @@ -35,6 +36,7 @@ namespace MediaBrowser.Dlna.PlayTo private readonly ILocalizationManager _localization; private readonly IMediaSourceManager _mediaSourceManager; private readonly IConfigurationManager _config; + private readonly IMediaEncoder _mediaEncoder; private readonly IDeviceDiscovery _deviceDiscovery; private readonly string _serverAddress; @@ -74,7 +76,7 @@ namespace MediaBrowser.Dlna.PlayTo get { return IsSessionActive; } } - public PlayToController(SessionInfo session, ISessionManager sessionManager, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IImageProcessor imageProcessor, string serverAddress, string accessToken, IDeviceDiscovery deviceDiscovery, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IConfigurationManager config) + public PlayToController(SessionInfo session, ISessionManager sessionManager, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IImageProcessor imageProcessor, string serverAddress, string accessToken, IDeviceDiscovery deviceDiscovery, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IConfigurationManager config, IMediaEncoder mediaEncoder) { _session = session; _sessionManager = sessionManager; @@ -88,6 +90,7 @@ namespace MediaBrowser.Dlna.PlayTo _localization = localization; _mediaSourceManager = mediaSourceManager; _config = config; + _mediaEncoder = mediaEncoder; _accessToken = accessToken; _logger = logger; _creationTime = DateTime.UtcNow; @@ -478,7 +481,7 @@ namespace MediaBrowser.Dlna.PlayTo playlistItem.StreamUrl = playlistItem.StreamInfo.ToDlnaUrl(_serverAddress, _accessToken); - var itemXml = new DidlBuilder(profile, user, _imageProcessor, _serverAddress, _accessToken, _userDataManager, _localization, _mediaSourceManager, _logger, _libraryManager) + var itemXml = new DidlBuilder(profile, user, _imageProcessor, _serverAddress, _accessToken, _userDataManager, _localization, _mediaSourceManager, _logger, _libraryManager, _mediaEncoder) .GetItemDidl(_config.GetDlnaConfiguration(), item, null, _session.DeviceId, new Filter(), playlistItem.StreamInfo); playlistItem.Didl = itemXml; @@ -550,7 +553,7 @@ namespace MediaBrowser.Dlna.PlayTo { return new PlaylistItem { - StreamInfo = new StreamBuilder(GetStreamBuilderLogger()).BuildVideoItem(new VideoOptions + StreamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger()).BuildVideoItem(new VideoOptions { ItemId = item.Id.ToString("N"), MediaSources = mediaSources, @@ -570,7 +573,7 @@ namespace MediaBrowser.Dlna.PlayTo { return new PlaylistItem { - StreamInfo = new StreamBuilder(GetStreamBuilderLogger()).BuildAudioItem(new AudioOptions + StreamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger()).BuildAudioItem(new AudioOptions { ItemId = item.Id.ToString("N"), MediaSources = mediaSources, diff --git a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs index 18daef331..bbb9bf6de 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Net; +using MediaBrowser.Controller.MediaEncoding; namespace MediaBrowser.Dlna.PlayTo { @@ -32,11 +33,12 @@ namespace MediaBrowser.Dlna.PlayTo private readonly IDeviceDiscovery _deviceDiscovery; private readonly IMediaSourceManager _mediaSourceManager; + private readonly IMediaEncoder _mediaEncoder; private readonly List _nonRendererUrls = new List(); private DateTime _lastRendererClear; - public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager) + public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder) { _logger = logger; _sessionManager = sessionManager; @@ -51,6 +53,7 @@ namespace MediaBrowser.Dlna.PlayTo _userDataManager = userDataManager; _localization = localization; _mediaSourceManager = mediaSourceManager; + _mediaEncoder = mediaEncoder; } public void Start() @@ -132,7 +135,8 @@ namespace MediaBrowser.Dlna.PlayTo _userDataManager, _localization, _mediaSourceManager, - _config); + _config, + _mediaEncoder); controller.Init(device); diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 01fb31d0c..399fdead9 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -96,15 +96,23 @@ namespace MediaBrowser.MediaEncoding.Encoder FFMpegPath = ffMpegPath; } + private List _encoders = new List(); public void SetAvailableEncoders(List list) { - + _encoders = list.ToList(); + //_logger.Info("Supported encoders: {0}", string.Join(",", list.ToArray())); } private List _decoders = new List(); public void SetAvailableDecoders(List list) { _decoders = list.ToList(); + //_logger.Info("Supported decoders: {0}", string.Join(",", list.ToArray())); + } + + public bool SupportsEncoder(string decoder) + { + return _encoders.Contains(decoder, StringComparer.OrdinalIgnoreCase); } public bool SupportsDecoder(string decoder) @@ -112,6 +120,20 @@ namespace MediaBrowser.MediaEncoding.Encoder return _decoders.Contains(decoder, StringComparer.OrdinalIgnoreCase); } + public bool CanEncodeToAudioCodec(string codec) + { + if (string.Equals(codec, "opus", StringComparison.OrdinalIgnoreCase)) + { + codec = "libopus"; + } + else if (string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase)) + { + codec = "libmp3lame"; + } + + return SupportsEncoder(codec); + } + /// /// Gets the encoder path. /// @@ -296,7 +318,7 @@ namespace MediaBrowser.MediaEncoding.Encoder formats.Contains("ts", StringComparer.OrdinalIgnoreCase) || formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) || formats.Contains("wtv", StringComparer.OrdinalIgnoreCase); - + // If it's mpeg based, assume true if ((videoStream.Codec ?? string.Empty).IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) != -1) { diff --git a/MediaBrowser.Model/Dlna/ILocalPlayer.cs b/MediaBrowser.Model/Dlna/ILocalPlayer.cs index 55e11ec4b..9de360023 100644 --- a/MediaBrowser.Model/Dlna/ILocalPlayer.cs +++ b/MediaBrowser.Model/Dlna/ILocalPlayer.cs @@ -23,4 +23,17 @@ namespace MediaBrowser.Model.Dlna /// true if this instance [can access URL] the specified URL; otherwise, false. bool CanAccessUrl(string url, bool requiresCustomRequestHeaders); } + + public interface ITranscoderSupport + { + bool CanEncodeToAudioCodec(string codec); + } + + public class FullTranscoderSupport : ITranscoderSupport + { + public bool CanEncodeToAudioCodec(string codec) + { + return true; + } + } } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 98d246980..07a4b8995 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -13,15 +13,27 @@ namespace MediaBrowser.Model.Dlna { private readonly ILocalPlayer _localPlayer; private readonly ILogger _logger; + private readonly ITranscoderSupport _transcoderSupport; - public StreamBuilder(ILocalPlayer localPlayer, ILogger logger) + public StreamBuilder(ILocalPlayer localPlayer, ITranscoderSupport transcoderSupport, ILogger logger) { + _transcoderSupport = transcoderSupport; _localPlayer = localPlayer; _logger = logger; } + public StreamBuilder(ITranscoderSupport transcoderSupport, ILogger logger) + : this(new NullLocalPlayer(), transcoderSupport, logger) + { + } + + public StreamBuilder(ILocalPlayer localPlayer, ILogger logger) + : this(localPlayer, new FullTranscoderSupport(), logger) + { + } + public StreamBuilder(ILogger logger) - : this(new NullLocalPlayer(), logger) + : this(new NullLocalPlayer(), new FullTranscoderSupport(), logger) { } @@ -185,8 +197,11 @@ namespace MediaBrowser.Model.Dlna { if (i.Type == playlistItem.MediaType && i.Context == options.Context) { - transcodingProfile = i; - break; + if (_transcoderSupport.CanEncodeToAudioCodec(i.AudioCodec ?? i.Container)) + { + transcodingProfile = i; + break; + } } } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index 10b872753..d95a4fefb 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -582,7 +582,7 @@ namespace MediaBrowser.Server.Implementations.Sync conversionOptions.ItemId = item.Id.ToString("N"); conversionOptions.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList(); - var streamInfo = new StreamBuilder(_logger).BuildVideoItem(conversionOptions); + var streamInfo = new StreamBuilder(_mediaEncoder, _logger).BuildVideoItem(conversionOptions); var mediaSource = streamInfo.MediaSource; // No sense creating external subs if we're already burning one into the video @@ -786,7 +786,7 @@ namespace MediaBrowser.Server.Implementations.Sync conversionOptions.ItemId = item.Id.ToString("N"); conversionOptions.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList(); - var streamInfo = new StreamBuilder(_logger).BuildAudioItem(conversionOptions); + var streamInfo = new StreamBuilder(_mediaEncoder, _logger).BuildAudioItem(conversionOptions); var mediaSource = streamInfo.MediaSource; jobItem.MediaSourceId = streamInfo.MediaSourceId; diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 01575e71f..fd6dee0f6 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -515,7 +515,7 @@ namespace MediaBrowser.Server.Startup.Common UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, ServerConfigurationManager); RegisterSingleInstance(UserViewManager); - var contentDirectory = new ContentDirectory(dlnaManager, UserDataManager, ImageProcessor, LibraryManager, ServerConfigurationManager, UserManager, LogManager.GetLogger("UpnpContentDirectory"), HttpClient, LocalizationManager, ChannelManager, MediaSourceManager, UserViewManager); + var contentDirectory = new ContentDirectory(dlnaManager, UserDataManager, ImageProcessor, LibraryManager, ServerConfigurationManager, UserManager, LogManager.GetLogger("UpnpContentDirectory"), HttpClient, LocalizationManager, ChannelManager, MediaSourceManager, UserViewManager, () => MediaEncoder); RegisterSingleInstance(contentDirectory); var mediaRegistrar = new MediaReceiverRegistrar(LogManager.GetLogger("MediaReceiverRegistrar"), HttpClient, ServerConfigurationManager); diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs index 5ba5fb44a..0ae021407 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs @@ -42,6 +42,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg catch { } + //_logger.Debug("ffmpeg decoder query result: {0}", output ?? string.Empty); var found = new List(); var required = new[] @@ -78,6 +79,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg catch { } + //_logger.Debug("ffmpeg encoder query result: {0}", output ?? string.Empty); var found = new List(); var required = new[] @@ -89,8 +91,8 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg //"libvpx", //"libvpx-vp9", "aac", - "ac3", "libmp3lame", + "libopus", //"libvorbis", "srt" }; -- cgit v1.2.3 From d75cc21d37cfa3b1ce2ad9dc4c26de41286f35f8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 15:47:47 -0400 Subject: fixes #1571 - Search containing umlauts fails --- .../Persistence/SqliteItemRepository.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 4f724fe40..a44d66c73 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -18,6 +18,7 @@ using System.Linq; using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Playlists; using MediaBrowser.Model.LiveTv; @@ -80,7 +81,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - private const int LatestSchemaVersion = 64; + private const int LatestSchemaVersion = 65; /// /// Initializes a new instance of the class. @@ -226,6 +227,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(Logger, "TypedBaseItems", "CriticRatingSummary", "Text"); _connection.AddColumn(Logger, "TypedBaseItems", "DateModifiedDuringLastRefresh", "DATETIME"); _connection.AddColumn(Logger, "TypedBaseItems", "InheritedTags", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "CleanName", "Text"); PrepareStatements(); @@ -466,7 +468,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "CriticRating", "CriticRatingSummary", "DateModifiedDuringLastRefresh", - "InheritedTags" + "InheritedTags", + "CleanName" }; _saveItemCommand = _connection.CreateCommand(); _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -792,6 +795,15 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = null; } + if (string.IsNullOrWhiteSpace(item.Name)) + { + _saveItemCommand.GetParameter(index++).Value = null; + } + else + { + _saveItemCommand.GetParameter(index++).Value = item.Name.RemoveDiacritics(); + } + _saveItemCommand.Transaction = transaction; _saveItemCommand.ExecuteNonQuery(); @@ -1986,7 +1998,7 @@ namespace MediaBrowser.Server.Implementations.Persistence if (!string.IsNullOrWhiteSpace(query.NameContains)) { - whereClauses.Add("Name like @NameContains"); + whereClauses.Add("CleanName like @NameContains"); cmd.Parameters.Add(cmd, "@NameContains", DbType.String).Value = "%" + query.NameContains + "%"; } -- cgit v1.2.3 From 1f9d32afc52e9bd133ddf22d12bdc468adaf9ebe Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 18:05:13 -0400 Subject: limit use of GetUserDataKey --- MediaBrowser.Api/Movies/MoviesService.cs | 4 ++-- .../UserLibrary/BaseItemsByNameService.cs | 8 +++---- MediaBrowser.Api/UserLibrary/UserLibraryService.cs | 8 ++----- MediaBrowser.Controller/Entities/BaseItem.cs | 14 +++++------- MediaBrowser.Controller/Entities/Folder.cs | 2 +- .../Entities/UserViewBuilder.cs | 10 ++++----- .../Library/IUserDataManager.cs | 5 +++++ .../ContentDirectory/ControlHandler.cs | 2 +- .../Channels/ChannelManager.cs | 12 +++++------ .../Dto/DtoService.cs | 4 ++-- .../Library/MediaSourceManager.cs | 2 +- .../Library/UserDataManager.cs | 15 +++++++++++++ .../LiveTv/LiveTvManager.cs | 12 +++++------ .../Session/SessionManager.cs | 25 ++++++++-------------- .../Sorting/DatePlayedComparer.cs | 2 +- .../Sorting/PlayCountComparer.cs | 2 +- .../Sync/SyncManager.cs | 2 +- .../TV/TVSeriesManager.cs | 4 ++-- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 2 +- 19 files changed, 70 insertions(+), 65 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index 065f88268..bfbb3a6d7 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -247,7 +247,7 @@ namespace MediaBrowser.Api.Movies var recentlyPlayedMovies = allMoviesForCategories .Select(i => { - var userdata = _userDataRepository.GetUserData(user.Id, i.GetUserDataKey()); + var userdata = _userDataRepository.GetUserData(user, i); return new Tuple(i, userdata.Played, userdata.LastPlayedDate ?? DateTime.MinValue); }) .Where(i => i.Item2) @@ -260,7 +260,7 @@ namespace MediaBrowser.Api.Movies .Select(i => { var score = 0; - var userData = _userDataRepository.GetUserData(user.Id, i.GetUserDataKey()); + var userData = _userDataRepository.GetUserData(user, i); if (userData.IsFavorite) { diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs index 6ae2b0832..b3164ce3f 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs @@ -274,7 +274,7 @@ namespace MediaBrowser.Api.UserLibrary { items = items.Where(i => { - var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey()); + var userdata = UserDataRepository.GetUserData(user, i); return userdata != null && userdata.Likes.HasValue && !userdata.Likes.Value; }); @@ -284,7 +284,7 @@ namespace MediaBrowser.Api.UserLibrary { items = items.Where(i => { - var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey()); + var userdata = UserDataRepository.GetUserData(user, i); return userdata != null && userdata.Likes.HasValue && userdata.Likes.Value; }); @@ -294,7 +294,7 @@ namespace MediaBrowser.Api.UserLibrary { items = items.Where(i => { - var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey()); + var userdata = UserDataRepository.GetUserData(user, i); var likes = userdata.Likes ?? false; var favorite = userdata.IsFavorite; @@ -307,7 +307,7 @@ namespace MediaBrowser.Api.UserLibrary { items = items.Where(i => { - var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey()); + var userdata = UserDataRepository.GetUserData(user, i); return userdata != null && userdata.IsFavorite; }); diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs index c2c481cb6..8cc5cab35 100644 --- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs +++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs @@ -519,10 +519,8 @@ namespace MediaBrowser.Api.UserLibrary var item = string.IsNullOrEmpty(itemId) ? user.RootFolder : _libraryManager.GetItemById(itemId); - var key = item.GetUserDataKey(); - // Get the user data for this item - var data = _userDataRepository.GetUserData(user.Id, key); + var data = _userDataRepository.GetUserData(user, item); // Set favorite status data.IsFavorite = isFavorite; @@ -567,10 +565,8 @@ namespace MediaBrowser.Api.UserLibrary var item = string.IsNullOrEmpty(itemId) ? user.RootFolder : _libraryManager.GetItemById(itemId); - var key = item.GetUserDataKey(); - // Get the user data for this item - var data = _userDataRepository.GetUserData(user.Id, key); + var data = _userDataRepository.GetUserData(user, item); data.Likes = likes; diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 9171c2a71..4828426fd 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1617,9 +1617,7 @@ namespace MediaBrowser.Controller.Entities throw new ArgumentNullException(); } - var key = GetUserDataKey(); - - var data = UserDataManager.GetUserData(user.Id, key); + var data = UserDataManager.GetUserData(user, this); if (datePlayed.HasValue) { @@ -1654,9 +1652,7 @@ namespace MediaBrowser.Controller.Entities throw new ArgumentNullException(); } - var key = GetUserDataKey(); - - var data = UserDataManager.GetUserData(user.Id, key); + var data = UserDataManager.GetUserData(user, this); //I think it is okay to do this here. // if this is only called when a user is manually forcing something to un-played @@ -1987,14 +1983,14 @@ namespace MediaBrowser.Controller.Entities public virtual bool IsPlayed(User user) { - var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey()); + var userdata = UserDataManager.GetUserData(user, this); return userdata != null && userdata.Played; } public bool IsFavoriteOrLiked(User user) { - var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey()); + var userdata = UserDataManager.GetUserData(user, this); return userdata != null && (userdata.IsFavorite || (userdata.Likes ?? false)); } @@ -2006,7 +2002,7 @@ namespace MediaBrowser.Controller.Entities throw new ArgumentNullException("user"); } - var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey()); + var userdata = UserDataManager.GetUserData(user, this); return userdata == null || !userdata.Played; } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index f4cdc8fa1..41f0c02bd 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1635,7 +1635,7 @@ namespace MediaBrowser.Controller.Entities var isUnplayed = true; - var itemUserData = UserDataManager.GetUserData(user.Id, child.GetUserDataKey()); + var itemUserData = UserDataManager.GetUserData(user, child); // Incrememt totalPercentPlayed if (itemUserData != null) diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index db669ca37..5a0e0b614 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -348,7 +348,7 @@ namespace MediaBrowser.Controller.Entities .Where(i => !i.IsFolder) .OfType(); - var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite); + var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user, i).IsFavorite); return GetResult(artists, parent, query); } @@ -1218,7 +1218,7 @@ namespace MediaBrowser.Controller.Entities if (query.IsLiked.HasValue) { - userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + userData = userData ?? userDataManager.GetUserData(user, item); if (!userData.Likes.HasValue || userData.Likes != query.IsLiked.Value) { @@ -1228,7 +1228,7 @@ namespace MediaBrowser.Controller.Entities if (query.IsFavoriteOrLiked.HasValue) { - userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + userData = userData ?? userDataManager.GetUserData(user, item); var isFavoriteOrLiked = userData.IsFavorite || (userData.Likes ?? false); if (isFavoriteOrLiked != query.IsFavoriteOrLiked.Value) @@ -1239,7 +1239,7 @@ namespace MediaBrowser.Controller.Entities if (query.IsFavorite.HasValue) { - userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + userData = userData ?? userDataManager.GetUserData(user, item); if (userData.IsFavorite != query.IsFavorite.Value) { @@ -1249,7 +1249,7 @@ namespace MediaBrowser.Controller.Entities if (query.IsResumable.HasValue) { - userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + userData = userData ?? userDataManager.GetUserData(user, item); var isResumable = userData.PlaybackPositionTicks > 0; if (isResumable != query.IsResumable.Value) diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs index 56ac14e9d..4ff0f6439 100644 --- a/MediaBrowser.Controller/Library/IUserDataManager.cs +++ b/MediaBrowser.Controller/Library/IUserDataManager.cs @@ -45,6 +45,11 @@ namespace MediaBrowser.Controller.Library /// Task{UserItemData}. UserItemData GetUserData(Guid userId, string key); + UserItemData GetUserData(IHasUserData user, IHasUserData item); + + UserItemData GetUserData(string userId, IHasUserData item); + UserItemData GetUserData(Guid userId, IHasUserData item); + /// /// Gets the user data dto. /// diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs index 34fb2a6df..bc9fa1d7e 100644 --- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs +++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs @@ -111,7 +111,7 @@ namespace MediaBrowser.Dlna.ContentDirectory var newbookmark = int.Parse(sparams["PosSecond"], _usCulture); - var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + var userdata = _userDataManager.GetUserData(user, item); userdata.PlaybackPositionTicks = TimeSpan.FromSeconds(newbookmark).Ticks; diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index c9956c68a..6a9842cb2 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -133,7 +133,7 @@ namespace MediaBrowser.Server.Implementations.Channels if (query.IsFavorite.HasValue) { var val = query.IsFavorite.Value; - channels = channels.Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite == val) + channels = channels.Where(i => _userDataManager.GetUserData(user, i).IsFavorite == val) .ToList(); } @@ -1437,7 +1437,7 @@ namespace MediaBrowser.Server.Implementations.Channels case ItemFilter.IsFavoriteOrLikes: return items.Where(item => { - var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + var userdata = _userDataManager.GetUserData(user, item); if (userdata == null) { @@ -1453,7 +1453,7 @@ namespace MediaBrowser.Server.Implementations.Channels case ItemFilter.Likes: return items.Where(item => { - var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + var userdata = _userDataManager.GetUserData(user, item); return userdata != null && userdata.Likes.HasValue && userdata.Likes.Value; }); @@ -1461,7 +1461,7 @@ namespace MediaBrowser.Server.Implementations.Channels case ItemFilter.Dislikes: return items.Where(item => { - var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + var userdata = _userDataManager.GetUserData(user, item); return userdata != null && userdata.Likes.HasValue && !userdata.Likes.Value; }); @@ -1469,7 +1469,7 @@ namespace MediaBrowser.Server.Implementations.Channels case ItemFilter.IsFavorite: return items.Where(item => { - var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + var userdata = _userDataManager.GetUserData(user, item); return userdata != null && userdata.IsFavorite; }); @@ -1477,7 +1477,7 @@ namespace MediaBrowser.Server.Implementations.Channels case ItemFilter.IsResumable: return items.Where(item => { - var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + var userdata = _userDataManager.GetUserData(user, item); return userdata != null && userdata.PlaybackPositionTicks > 0; }); diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 7adde5c27..b19f5727c 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -487,7 +487,7 @@ namespace MediaBrowser.Server.Implementations.Dto { if (item.IsFolder) { - var userData = _userDataRepository.GetUserData(user.Id, item.GetUserDataKey()); + var userData = _userDataRepository.GetUserData(user, item); // Skip the user data manager because we've already looped through the recursive tree and don't want to do it twice // TODO: Improve in future @@ -1686,7 +1686,7 @@ namespace MediaBrowser.Server.Implementations.Dto dateLastMediaAdded = new[] { dateLastMediaAdded.Value, child.DateCreated }.Max(); } - var userdata = _userDataRepository.GetUserData(user.Id, child.GetUserDataKey()); + var userdata = _userDataRepository.GetUserData(user, child); recursiveItemCount++; diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs index 092b797ce..a47fcdf4f 100644 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -267,7 +267,7 @@ namespace MediaBrowser.Server.Implementations.Library private void SetUserProperties(IHasUserData item, MediaSourceInfo source, User user) { - var userData = item == null ? new UserItemData() : _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + var userData = item == null ? new UserItemData() : _userDataManager.GetUserData(user, item); var allowRememberingSelection = item == null || item.EnableRememberingTrackSelections; diff --git a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs index ae737d244..c16beed8c 100644 --- a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs @@ -172,6 +172,21 @@ namespace MediaBrowser.Server.Implementations.Library return userId + key; } + public UserItemData GetUserData(IHasUserData user, IHasUserData item) + { + return GetUserData(user.Id, item.GetUserDataKey()); + } + + public UserItemData GetUserData(string userId, IHasUserData item) + { + return GetUserData(userId, item.GetUserDataKey()); + } + + public UserItemData GetUserData(Guid userId, IHasUserData item) + { + return GetUserData(userId, item.GetUserDataKey()); + } + public UserItemDataDto GetUserDataDto(IHasUserData item, User user) { var userData = GetUserData(user.Id, item.GetUserDataKey()); diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index ab2b59d48..eec8328f8 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -164,7 +164,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv var val = query.IsFavorite.Value; channels = channels - .Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite == val); + .Where(i => _userDataManager.GetUserData(user, i).IsFavorite == val); } if (query.IsLiked.HasValue) @@ -174,7 +174,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv channels = channels .Where(i => { - var likes = _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).Likes; + var likes = _userDataManager.GetUserData(user, i).Likes; return likes.HasValue && likes.Value == val; }); @@ -187,7 +187,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv channels = channels .Where(i => { - var likes = _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).Likes; + var likes = _userDataManager.GetUserData(user, i).Likes; return likes.HasValue && likes.Value != val; }); @@ -200,7 +200,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { if (enableFavoriteSorting) { - var userData = _userDataManager.GetUserData(user.Id, i.GetUserDataKey()); + var userData = _userDataManager.GetUserData(user, i); if (userData.IsFavorite) { @@ -1005,7 +1005,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv var channel = GetInternalChannel(program.ChannelId); - var channelUserdata = _userDataManager.GetUserData(userId, channel.GetUserDataKey()); + var channelUserdata = _userDataManager.GetUserData(userId, channel); if (channelUserdata.Likes ?? false) { @@ -1036,7 +1036,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (genres.TryGetValue(i, out genre)) { - var genreUserdata = _userDataManager.GetUserData(userId, genre.GetUserDataKey()); + var genreUserdata = _userDataManager.GetUserData(userId, genre); if (genreUserdata.Likes ?? false) { diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 88f11c368..014e8babf 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -601,11 +601,9 @@ namespace MediaBrowser.Server.Implementations.Session if (libraryItem != null) { - var key = libraryItem.GetUserDataKey(); - foreach (var user in users) { - await OnPlaybackStart(user.Id, key, libraryItem).ConfigureAwait(false); + await OnPlaybackStart(user.Id, libraryItem).ConfigureAwait(false); } } @@ -632,12 +630,11 @@ namespace MediaBrowser.Server.Implementations.Session /// Called when [playback start]. /// /// The user identifier. - /// The user data key. /// The item. /// Task. - private async Task OnPlaybackStart(Guid userId, string userDataKey, IHasUserData item) + private async Task OnPlaybackStart(Guid userId, IHasUserData item) { - var data = _userDataRepository.GetUserData(userId, userDataKey); + var data = _userDataRepository.GetUserData(userId, item); data.PlayCount++; data.LastPlayedDate = DateTime.UtcNow; @@ -676,11 +673,9 @@ namespace MediaBrowser.Server.Implementations.Session if (libraryItem != null) { - var key = libraryItem.GetUserDataKey(); - foreach (var user in users) { - await OnPlaybackProgress(user, key, libraryItem, info).ConfigureAwait(false); + await OnPlaybackProgress(user, libraryItem, info).ConfigureAwait(false); } } @@ -714,9 +709,9 @@ namespace MediaBrowser.Server.Implementations.Session StartIdleCheckTimer(); } - private async Task OnPlaybackProgress(User user, string userDataKey, BaseItem item, PlaybackProgressInfo info) + private async Task OnPlaybackProgress(User user, BaseItem item, PlaybackProgressInfo info) { - var data = _userDataRepository.GetUserData(user.Id, userDataKey); + var data = _userDataRepository.GetUserData(user.Id, item); var positionTicks = info.PositionTicks; @@ -811,11 +806,9 @@ namespace MediaBrowser.Server.Implementations.Session if (libraryItem != null) { - var key = libraryItem.GetUserDataKey(); - foreach (var user in users) { - playedToCompletion = await OnPlaybackStopped(user.Id, key, libraryItem, info.PositionTicks, info.Failed).ConfigureAwait(false); + playedToCompletion = await OnPlaybackStopped(user.Id, libraryItem, info.PositionTicks, info.Failed).ConfigureAwait(false); } } @@ -848,13 +841,13 @@ namespace MediaBrowser.Server.Implementations.Session await SendPlaybackStoppedNotification(session, CancellationToken.None).ConfigureAwait(false); } - private async Task OnPlaybackStopped(Guid userId, string userDataKey, BaseItem item, long? positionTicks, bool playbackFailed) + private async Task OnPlaybackStopped(Guid userId, BaseItem item, long? positionTicks, bool playbackFailed) { bool playedToCompletion = false; if (!playbackFailed) { - var data = _userDataRepository.GetUserData(userId, userDataKey); + var data = _userDataRepository.GetUserData(userId, item); if (positionTicks.HasValue) { diff --git a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs index c881591be..3edf23020 100644 --- a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.Sorting /// DateTime. private DateTime GetDate(BaseItem x) { - var userdata = UserDataRepository.GetUserData(User.Id, x.GetUserDataKey()); + var userdata = UserDataRepository.GetUserData(User, x); if (userdata != null && userdata.LastPlayedDate.HasValue) { diff --git a/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs b/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs index 1bc5261b4..8b14efffc 100644 --- a/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs @@ -34,7 +34,7 @@ namespace MediaBrowser.Server.Implementations.Sorting /// DateTime. private int GetValue(BaseItem x) { - var userdata = UserDataRepository.GetUserData(User.Id, x.GetUserDataKey()); + var userdata = UserDataRepository.GetUserData(User, x); return userdata == null ? 0 : userdata.PlayCount; } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index fe1a7fb28..38edc3024 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -687,7 +687,7 @@ namespace MediaBrowser.Server.Implementations.Sync private Task ReportOfflinePlayedItem(UserAction action) { var item = _libraryManager.GetItemById(action.ItemId); - var userData = _userDataManager.GetUserData(new Guid(action.UserId), item.GetUserDataKey()); + var userData = _userDataManager.GetUserData(action.UserId, item); userData.LastPlayedDate = action.Date; _userDataManager.UpdatePlayState(item, userData, action.PositionTicks); diff --git a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs index 3e43ebe9b..dc880d84b 100644 --- a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs +++ b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs @@ -85,7 +85,7 @@ namespace MediaBrowser.Server.Implementations.TV { var episode = i.Item1; - var seriesUserData = _userDataManager.GetUserData(user.Id, episode.Series.GetUserDataKey()); + var seriesUserData = _userDataManager.GetUserData(user, episode.Series); if (seriesUserData.IsFavorite) { @@ -128,7 +128,7 @@ namespace MediaBrowser.Server.Implementations.TV // Go back starting with the most recent episodes foreach (var episode in allEpisodes) { - var userData = _userDataManager.GetUserData(user.Id, episode.GetUserDataKey()); + var userData = _userDataManager.GetUserData(user, episode); if (userData.Played) { diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 6d15d168d..d2e09d4eb 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -936,7 +936,7 @@ namespace MediaBrowser.XbmcMetadata.Savers return; } - var userdata = userDataRepo.GetUserData(user.Id, item.GetUserDataKey()); + var userdata = userDataRepo.GetUserData(user, item); writer.WriteElementString("isuserfavorite", userdata.IsFavorite.ToString().ToLower()); -- cgit v1.2.3 From 6330b13262bf24793f059a269fdba7ea2514efe0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 19:05:21 -0400 Subject: support multiple user data keys --- MediaBrowser.Controller/Entities/Audio/Audio.cs | 34 ++++++------- .../Entities/Audio/MusicAlbum.cs | 32 ++++++------ .../Entities/Audio/MusicArtist.cs | 19 +++---- .../Entities/Audio/MusicGenre.cs | 11 ++-- MediaBrowser.Controller/Entities/BaseItem.cs | 12 +++-- MediaBrowser.Controller/Entities/Game.cs | 7 +-- MediaBrowser.Controller/Entities/GameGenre.cs | 11 ++-- MediaBrowser.Controller/Entities/GameSystem.cs | 13 +++-- MediaBrowser.Controller/Entities/Genre.cs | 11 ++-- MediaBrowser.Controller/Entities/IHasUserData.cs | 5 +- MediaBrowser.Controller/Entities/Movies/Movie.cs | 28 ----------- MediaBrowser.Controller/Entities/MusicVideo.cs | 9 ---- MediaBrowser.Controller/Entities/Person.cs | 11 ++-- MediaBrowser.Controller/Entities/Studio.cs | 11 ++-- MediaBrowser.Controller/Entities/TV/Episode.cs | 22 +++++--- MediaBrowser.Controller/Entities/TV/Season.cs | 16 +++--- MediaBrowser.Controller/Entities/TV/Series.cs | 26 +++++----- MediaBrowser.Controller/Entities/Trailer.cs | 20 -------- MediaBrowser.Controller/Entities/Video.cs | 58 ++++++++++++++++++---- MediaBrowser.Controller/Entities/Year.cs | 11 ++-- .../Library/UserDataSaveEventArgs.cs | 7 +-- .../LiveTv/LiveTvAudioRecording.cs | 11 ---- MediaBrowser.Controller/LiveTv/LiveTvChannel.cs | 11 ++-- MediaBrowser.Controller/LiveTv/LiveTvProgram.cs | 28 ++++++----- .../LiveTv/LiveTvVideoRecording.cs | 26 ---------- .../Library/UserDataManager.cs | 27 +++++----- 26 files changed, 214 insertions(+), 263 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 929308ba0..fd56a6746 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Entities.Audio IArchivable { public List ChannelMediaSources { get; set; } - + public long? Size { get; set; } public string Container { get; set; } public int? TotalBitrate { get; set; } @@ -150,12 +150,10 @@ namespace MediaBrowser.Controller.Entities.Audio + (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name; } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { + var list = base.GetUserDataKeys(); + if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys) { var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty; @@ -165,7 +163,7 @@ namespace MediaBrowser.Controller.Entities.Audio { songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey; } - songKey+= Name; + songKey += Name; if (!string.IsNullOrWhiteSpace(Album)) { @@ -178,25 +176,25 @@ namespace MediaBrowser.Controller.Entities.Audio songKey = albumArtist + "-" + songKey; } - return songKey; + list.Insert(0, songKey); } - - var parent = AlbumEntity; - - if (parent != null) + else { - var parentKey = parent.GetUserDataKey(); + var parent = AlbumEntity; - if (IndexNumber.HasValue) + if (parent != null && IndexNumber.HasValue) { - var songKey = (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "") - + IndexNumber.Value.ToString("0000 - "); + list.InsertRange(0, parent.GetUserDataKeys().Select(i => + { + var songKey = (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "") + + IndexNumber.Value.ToString("0000 - "); - return parentKey + songKey; + return i + songKey; + })); } } - return base.CreateUserDataKey(); + return list; } public override UnratedItem GetBlockUnratedType() diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index e6178c183..5cb4e8c9d 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -96,36 +96,34 @@ namespace MediaBrowser.Controller.Entities.Audio public List Artists { get; set; } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - var id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); + var list = base.GetUserDataKeys(); - if (!string.IsNullOrWhiteSpace(id)) + if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys) { - return "MusicAlbum-MusicBrainzReleaseGroup-" + id; + var albumArtist = AlbumArtist; + if (!string.IsNullOrWhiteSpace(albumArtist)) + { + list.Insert(0, albumArtist + "-" + Name); + } } - id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum); + var id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum); if (!string.IsNullOrWhiteSpace(id)) { - return "MusicAlbum-Musicbrainz-" + id; + list.Insert(0, "MusicAlbum-Musicbrainz-" + id); } - if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys) + id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); + + if (!string.IsNullOrWhiteSpace(id)) { - var albumArtist = AlbumArtist; - if (!string.IsNullOrWhiteSpace(albumArtist)) - { - return albumArtist + "-" + Name; - } + list.Insert(0, "MusicAlbum-MusicBrainzReleaseGroup-" + id); } - return base.CreateUserDataKey(); + return list; } protected override bool GetBlockUnratedValue(UserPolicy config) diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index 02bcceada..2cca63217 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -80,13 +80,12 @@ namespace MediaBrowser.Controller.Entities.Audio ProductionLocations = new List(); } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return GetUserDataKey(this); + var list = base.GetUserDataKeys(); + + list.InsertRange(0, GetUserDataKeys(this)); + return list; } /// @@ -121,16 +120,18 @@ namespace MediaBrowser.Controller.Entities.Audio /// /// The item. /// System.String. - private static string GetUserDataKey(MusicArtist item) + private static List GetUserDataKeys(MusicArtist item) { + var list = new List(); var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist); if (!string.IsNullOrEmpty(id)) { - return "Artist-Musicbrainz-" + id; + list.Add("Artist-Musicbrainz-" + id); } - return "Artist-" + item.Name; + list.Add("Artist-" + item.Name); + return list; } protected override bool GetBlockUnratedValue(UserPolicy config) diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index 45304d47e..4d041264c 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -10,13 +10,12 @@ namespace MediaBrowser.Controller.Entities.Audio /// public class MusicGenre : BaseItem, IItemByName { - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return "MusicGenre-" + Name; + var list = base.GetUserDataKeys(); + + list.Insert(0, "MusicGenre-" + Name); + return list; } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 4828426fd..f91b6b31e 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1158,7 +1158,7 @@ namespace MediaBrowser.Controller.Entities { if (string.IsNullOrWhiteSpace(_userDataKey)) { - var key = CreateUserDataKey(); + var key = GetUserDataKeys().First(); _userDataKey = key; return key; } @@ -1166,16 +1166,20 @@ namespace MediaBrowser.Controller.Entities return _userDataKey; } - protected virtual string CreateUserDataKey() + public virtual List GetUserDataKeys() { + var list = new List(); + if (SourceType == SourceType.Channel) { if (!string.IsNullOrWhiteSpace(ExternalId)) { - return ExternalId; + list.Add(ExternalId); } } - return Id.ToString(); + + list.Add(Id.ToString()); + return list; } internal virtual bool IsValidFromResolver(BaseItem newItem) diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs index e597b2a15..9ed240046 100644 --- a/MediaBrowser.Controller/Entities/Game.cs +++ b/MediaBrowser.Controller/Entities/Game.cs @@ -76,15 +76,16 @@ namespace MediaBrowser.Controller.Entities /// public List MultiPartGameFiles { get; set; } - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { + var list = base.GetUserDataKeys(); var id = this.GetProviderId(MetadataProviders.Gamesdb); if (!string.IsNullOrEmpty(id)) { - return "Game-Gamesdb-" + id; + list.Insert(0, "Game-Gamesdb-" + id); } - return base.CreateUserDataKey(); + return list; } public override IEnumerable GetDeletePaths() diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs index d2b6b4856..71028d4cf 100644 --- a/MediaBrowser.Controller/Entities/GameGenre.cs +++ b/MediaBrowser.Controller/Entities/GameGenre.cs @@ -7,13 +7,12 @@ namespace MediaBrowser.Controller.Entities { public class GameGenre : BaseItem, IItemByName { - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return "GameGenre-" + Name; + var list = base.GetUserDataKeys(); + + list.Insert(0, "GameGenre-" + Name); + return list; } /// diff --git a/MediaBrowser.Controller/Entities/GameSystem.cs b/MediaBrowser.Controller/Entities/GameSystem.cs index bc35c4738..1c09ee507 100644 --- a/MediaBrowser.Controller/Entities/GameSystem.cs +++ b/MediaBrowser.Controller/Entities/GameSystem.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using System; +using System.Collections.Generic; using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.Entities @@ -31,17 +32,15 @@ namespace MediaBrowser.Controller.Entities /// The game system. public string GameSystemName { get; set; } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { + var list = base.GetUserDataKeys(); + if (!string.IsNullOrEmpty(GameSystemName)) { - return "GameSystem-" + GameSystemName; + list.Insert(0, "GameSystem-" + GameSystemName); } - return base.CreateUserDataKey(); + return list; } protected override bool GetBlockUnratedValue(UserPolicy config) diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index 233e1e0fd..fa890ad9e 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.Entities /// public class Genre : BaseItem, IItemByName { - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return "Genre-" + Name; + var list = base.GetUserDataKeys(); + + list.Insert(0, "Genre-" + Name); + return list; } /// diff --git a/MediaBrowser.Controller/Entities/IHasUserData.cs b/MediaBrowser.Controller/Entities/IHasUserData.cs index faddc3778..3e0fa3f1d 100644 --- a/MediaBrowser.Controller/Entities/IHasUserData.cs +++ b/MediaBrowser.Controller/Entities/IHasUserData.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Model.Dto; +using System.Collections.Generic; +using MediaBrowser.Model.Dto; namespace MediaBrowser.Controller.Entities { @@ -13,6 +14,8 @@ namespace MediaBrowser.Controller.Entities /// System.String. string GetUserDataKey(); + List GetUserDataKeys(); + /// /// Fills the user data dto values. /// diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 6004992cc..5882b5f4d 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -75,34 +75,6 @@ namespace MediaBrowser.Controller.Entities.Movies get { return TmdbCollectionName; } set { TmdbCollectionName = value; } } - - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() - { - var key = GetMovieUserDataKey(this); - - if (string.IsNullOrWhiteSpace(key)) - { - key = base.CreateUserDataKey(); - } - - return key; - } - - public static string GetMovieUserDataKey(BaseItem movie) - { - var key = movie.GetProviderId(MetadataProviders.Tmdb); - - if (string.IsNullOrWhiteSpace(key)) - { - key = movie.GetProviderId(MetadataProviders.Imdb); - } - - return key; - } protected override async Task RefreshedOwnedItems(MetadataRefreshOptions options, List fileSystemChildren, CancellationToken cancellationToken) { diff --git a/MediaBrowser.Controller/Entities/MusicVideo.cs b/MediaBrowser.Controller/Entities/MusicVideo.cs index b52f16a46..bf4c2559c 100644 --- a/MediaBrowser.Controller/Entities/MusicVideo.cs +++ b/MediaBrowser.Controller/Entities/MusicVideo.cs @@ -44,15 +44,6 @@ namespace MediaBrowser.Controller.Entities } } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() - { - return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.CreateUserDataKey(); - } - public override UnratedItem GetBlockUnratedType() { return UnratedItem.Music; diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index 560ea6e05..89581e967 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -18,13 +18,12 @@ namespace MediaBrowser.Controller.Entities /// The place of birth. public string PlaceOfBirth { get; set; } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return "Person-" + Name; + var list = base.GetUserDataKeys(); + + list.Insert(0, "Person-" + Name); + return list; } public PersonLookupInfo GetLookupInfo() diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index a55527f37..7ceefbc6e 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -10,13 +10,12 @@ namespace MediaBrowser.Controller.Entities /// public class Studio : BaseItem, IItemByName, IHasTags { - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return "Studio-" + Name; + var list = base.GetUserDataKeys(); + + list.Insert(0, "Studio-" + Name); + return list; } /// diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index e1a91086b..3ad6170a5 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -98,20 +98,26 @@ namespace MediaBrowser.Controller.Entities.TV } } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + [IgnoreDataMember] + protected override bool EnableDefaultVideoUserDataKeys { - var series = Series; + get + { + return false; + } + } + + public override List GetUserDataKeys() + { + var list = base.GetUserDataKeys(); + var series = Series; if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue) { - return series.GetUserDataKey() + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000"); + list.InsertRange(0, series.GetUserDataKeys().Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000"))); } - return base.CreateUserDataKey(); + return list; } /// diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index acd02e8ab..ebd22c6c4 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -53,19 +53,17 @@ namespace MediaBrowser.Controller.Entities.TV }; } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - if (Series != null) + var list = base.GetUserDataKeys(); + + var series = Series; + if (series != null) { - var seasonNo = IndexNumber ?? 0; - return Series.GetUserDataKey() + seasonNo.ToString("000"); + list.InsertRange(0, series.GetUserDataKeys().Select(i => i + (IndexNumber ?? 0).ToString("000"))); } - return base.CreateUserDataKey(); + return list; } /// diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index ad4ee436e..c03eed6c9 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -95,21 +95,23 @@ namespace MediaBrowser.Controller.Entities.TV /// Gets the user data key. /// /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - var key = this.GetProviderId(MetadataProviders.Tvdb); + var list = base.GetUserDataKeys(); - if (string.IsNullOrWhiteSpace(key)) + var key = this.GetProviderId(MetadataProviders.Imdb); + if (!string.IsNullOrWhiteSpace(key)) { - key = this.GetProviderId(MetadataProviders.Imdb); + list.Insert(0, key); } - if (string.IsNullOrWhiteSpace(key)) + key = this.GetProviderId(MetadataProviders.Tvdb); + if (!string.IsNullOrWhiteSpace(key)) { - key = base.CreateUserDataKey(); + list.Insert(0, key); } - return key; + return list; } /// @@ -126,8 +128,8 @@ namespace MediaBrowser.Controller.Entities.TV // Studio, Genre and Rating will all be the same so makes no sense to index by these protected override IEnumerable GetIndexByOptions() { - return new List { - {"None"}, + return new List { + {"None"}, {"Performer"}, {"Director"}, {"Year"}, @@ -280,9 +282,9 @@ namespace MediaBrowser.Controller.Entities.TV if (episode != null && refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh && !refreshOptions.ReplaceAllMetadata - && episode.IsMissingEpisode - && episode.LocationType == Model.Entities.LocationType.Virtual - && episode.PremiereDate.HasValue + && episode.IsMissingEpisode + && episode.LocationType == Model.Entities.LocationType.Virtual + && episode.PremiereDate.HasValue && (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30) { skipItem = true; diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index fe8bf3ed3..3be2fc624 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -56,26 +56,6 @@ namespace MediaBrowser.Controller.Entities /// The revenue. public double? Revenue { get; set; } - protected override string CreateUserDataKey() - { - var key = Movie.GetMovieUserDataKey(this); - - if (!string.IsNullOrWhiteSpace(key)) - { - key = key + "-trailer"; - - // Make sure different trailers have their own data. - if (RunTimeTicks.HasValue) - { - key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture); - } - - return key; - } - - return base.CreateUserDataKey(); - } - public override UnratedItem GetBlockUnratedType() { return UnratedItem.Trailer; diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index d81e6f0ff..cdabaa84e 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -131,27 +131,65 @@ namespace MediaBrowser.Controller.Entities return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video))); } - protected override string CreateUserDataKey() + [IgnoreDataMember] + protected virtual bool EnableDefaultVideoUserDataKeys { - if (ExtraType.HasValue) + get { - var key = this.GetProviderId(MetadataProviders.Imdb) ?? this.GetProviderId(MetadataProviders.Tmdb); + return true; + } + } + + public override List GetUserDataKeys() + { + var list = base.GetUserDataKeys(); - if (!string.IsNullOrWhiteSpace(key)) + if (EnableDefaultVideoUserDataKeys) + { + if (ExtraType.HasValue) { - key = key + "-" + ExtraType.ToString().ToLower(); + var key = this.GetProviderId(MetadataProviders.Tmdb); + if (!string.IsNullOrWhiteSpace(key)) + { + list.Insert(0, GetUserDataKey(key)); + } - // Make sure different trailers have their own data. - if (RunTimeTicks.HasValue) + key = this.GetProviderId(MetadataProviders.Imdb); + if (!string.IsNullOrWhiteSpace(key)) { - key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture); + list.Insert(0, GetUserDataKey(key)); + } + } + else + { + var key = this.GetProviderId(MetadataProviders.Imdb); + if (!string.IsNullOrWhiteSpace(key)) + { + list.Insert(0, key); } - return key; + key = this.GetProviderId(MetadataProviders.Tmdb); + if (!string.IsNullOrWhiteSpace(key)) + { + list.Insert(0, key); + } } } - return base.CreateUserDataKey(); + return list; + } + + private string GetUserDataKey(string providerId) + { + var key = providerId + "-" + ExtraType.ToString().ToLower(); + + // Make sure different trailers have their own data. + if (RunTimeTicks.HasValue) + { + key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture); + } + + return key; } /// diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index 163dcd667..f27ce79dd 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.Entities /// public class Year : BaseItem, IItemByName { - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return "Year-" + Name; + var list = base.GetUserDataKeys(); + + list.Insert(0, "Year-" + Name); + return list; } /// diff --git a/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs b/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs index ba328ff75..654c6b581 100644 --- a/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs +++ b/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Entities; using System; +using System.Collections.Generic; namespace MediaBrowser.Controller.Library { @@ -15,11 +16,7 @@ namespace MediaBrowser.Controller.Library /// The user id. public Guid UserId { get; set; } - /// - /// Gets or sets the key. - /// - /// The key. - public string Key { get; set; } + public List Keys { get; set; } /// /// Gets or sets the save reason. diff --git a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs index 17a27eac1..e6f472414 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs @@ -45,17 +45,6 @@ namespace MediaBrowser.Controller.LiveTv set { } } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() - { - var name = GetClientTypeName(); - - return name + "-" + Name + (EpisodeTitle ?? string.Empty); - } - /// /// Gets a value indicating whether this instance is owned item. /// diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index 2bb6cc182..50aeed27d 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.LiveTv { public class LiveTvChannel : BaseItem, IHasMediaSources { - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return GetClientTypeName() + "-" + Name; + var list = base.GetUserDataKeys(); + + list.Insert(0, GetClientTypeName() + "-" + Name); + return list; } public override UnratedItem GetBlockUnratedType() diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 59b921c6a..cc30709db 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -4,36 +4,40 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.LiveTv; using System; +using System.Collections.Generic; using System.Runtime.Serialization; +using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.LiveTv { public class LiveTvProgram : BaseItem, IHasLookupInfo, IHasStartDate, IHasProgramAttributes { - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - if (IsMovie) + var list = base.GetUserDataKeys(); + + if (!IsSeries) { - var key = Movie.GetMovieUserDataKey(this); + var key = this.GetProviderId(MetadataProviders.Imdb); + if (!string.IsNullOrWhiteSpace(key)) + { + list.Insert(0, key); + } + key = this.GetProviderId(MetadataProviders.Tmdb); if (!string.IsNullOrWhiteSpace(key)) { - return key; + list.Insert(0, key); } } - - if (IsSeries && !string.IsNullOrWhiteSpace(EpisodeTitle)) + else if (!string.IsNullOrWhiteSpace(EpisodeTitle)) { var name = GetClientTypeName(); - return name + "-" + Name + (EpisodeTitle ?? string.Empty); + list.Insert(0, name + "-" + Name + (EpisodeTitle ?? string.Empty)); } - return base.CreateUserDataKey(); + return list; } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs index f310a957c..a8c737673 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs @@ -45,32 +45,6 @@ namespace MediaBrowser.Controller.LiveTv set { } } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() - { - if (IsMovie) - { - var key = Movie.GetMovieUserDataKey(this); - - if (!string.IsNullOrWhiteSpace(key)) - { - return key; - } - } - - if (IsSeries && !string.IsNullOrWhiteSpace(EpisodeTitle)) - { - var name = GetClientTypeName(); - - return name + "-" + Name + (EpisodeTitle ?? string.Empty); - } - - return base.CreateUserDataKey(); - } - [IgnoreDataMember] public override string MediaType { diff --git a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs index c16beed8c..98f8abd40 100644 --- a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs @@ -56,27 +56,30 @@ namespace MediaBrowser.Server.Implementations.Library cancellationToken.ThrowIfCancellationRequested(); - var key = item.GetUserDataKey(); + var keys = item.GetUserDataKeys(); - try + foreach (var key in keys) { - await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false); + try + { + await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false); - var newValue = userData; + var newValue = userData; - // Once it succeeds, put it into the dictionary to make it available to everyone else - _userData.AddOrUpdate(GetCacheKey(userId, key), newValue, delegate { return newValue; }); - } - catch (Exception ex) - { - _logger.ErrorException("Error saving user data", ex); + // Once it succeeds, put it into the dictionary to make it available to everyone else + _userData.AddOrUpdate(GetCacheKey(userId, key), newValue, delegate { return newValue; }); + } + catch (Exception ex) + { + _logger.ErrorException("Error saving user data", ex); - throw; + throw; + } } EventHelper.FireEventIfNotNull(UserDataSaved, this, new UserDataSaveEventArgs { - Key = key, + Keys = keys, UserData = userData, SaveReason = reason, UserId = userId, -- cgit v1.2.3 From ad3965a76992fe13e92a244fd70c08bdfb8d5191 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 1 May 2016 16:56:06 -0400 Subject: update MediaSourceCount --- MediaBrowser.Server.Implementations/Dto/DtoService.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index b19f5727c..e8af0c3cb 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1363,9 +1363,10 @@ namespace MediaBrowser.Server.Implementations.Dto if (fields.Contains(ItemFields.MediaSourceCount)) { - if (video.MediaSourceCount != 1) + var mediaSourceCount = video.MediaSourceCount; + if (mediaSourceCount != 1) { - dto.MediaSourceCount = video.MediaSourceCount; + dto.MediaSourceCount = mediaSourceCount; } } -- cgit v1.2.3 From a4d1c9e6e48f63121cc51abda61ed46d7f6a72cf Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 1 May 2016 17:48:37 -0400 Subject: update sqlite --- .../Notifications/INotificationsRepository.cs | 6 - .../Persistence/IDisplayPreferencesRepository.cs | 6 - .../Persistence/IItemRepository.cs | 6 - .../Persistence/IUserDataRepository.cs | 6 - .../Providers/IProviderRepository.cs | 6 - .../Activity/ActivityRepository.cs | 4 +- .../MediaBrowser.Server.Implementations.csproj | 6 +- .../Notifications/SqliteNotificationsRepository.cs | 4 +- .../Persistence/DataExtensions.cs | 182 +++++++++++++++++ .../Persistence/IDbConnector.cs | 10 + .../SqliteDisplayPreferencesRepository.cs | 4 +- .../Persistence/SqliteExtensions.cs | 218 --------------------- .../SqliteFileOrganizationRepository.cs | 4 +- .../Persistence/SqliteProviderInfoRepository.cs | 4 +- .../Persistence/SqliteUserDataRepository.cs | 4 +- .../Persistence/SqliteUserRepository.cs | 6 +- .../Security/AuthenticationRepository.cs | 4 +- .../Social/SharingRepository.cs | 4 +- .../Sync/SyncRepository.cs | 4 +- .../MediaBrowser.Server.Mono.csproj | 5 + MediaBrowser.Server.Mono/Native/BaseMonoApp.cs | 11 +- MediaBrowser.Server.Mono/Native/NativeApp.cs | 7 +- .../Native/SqliteExtensions.cs | 62 ++++++ MediaBrowser.Server.Mono/Program.cs | 2 +- .../ApplicationHost.cs | 55 ++---- MediaBrowser.Server.Startup.Common/INativeApp.cs | 3 + .../MediaBrowser.ServerApplication.csproj | 25 +-- .../Native/SqliteExtensions.cs | 62 ++++++ .../Native/WindowsApp.cs | 6 + MediaBrowser.ServerApplication/packages.config | 2 +- 30 files changed, 401 insertions(+), 327 deletions(-) create mode 100644 MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs create mode 100644 MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs delete mode 100644 MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs create mode 100644 MediaBrowser.Server.Mono/Native/SqliteExtensions.cs create mode 100644 MediaBrowser.ServerApplication/Native/SqliteExtensions.cs (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Controller/Notifications/INotificationsRepository.cs b/MediaBrowser.Controller/Notifications/INotificationsRepository.cs index 6ad4a5377..cd587a509 100644 --- a/MediaBrowser.Controller/Notifications/INotificationsRepository.cs +++ b/MediaBrowser.Controller/Notifications/INotificationsRepository.cs @@ -19,12 +19,6 @@ namespace MediaBrowser.Controller.Notifications /// Occurs when [notifications marked read]. /// event EventHandler NotificationsMarkedRead; - - /// - /// Opens the connection to the repository - /// - /// Task. - Task Initialize(); /// /// Gets the notifications. diff --git a/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs b/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs index 17de730cb..abf96994f 100644 --- a/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs +++ b/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs @@ -11,12 +11,6 @@ namespace MediaBrowser.Controller.Persistence /// public interface IDisplayPreferencesRepository : IRepository { - /// - /// Opens the connection to the repository - /// - /// Task. - Task Initialize(); - /// /// Saves display preferences for an item /// diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 15df1f649..7bcc36958 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -13,12 +13,6 @@ namespace MediaBrowser.Controller.Persistence /// public interface IItemRepository : IRepository { - /// - /// Opens the connection to the repository - /// - /// Task. - Task Initialize(); - /// /// Saves an item /// diff --git a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs index 2a904be0d..2e165f416 100644 --- a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs +++ b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs @@ -11,12 +11,6 @@ namespace MediaBrowser.Controller.Persistence /// public interface IUserDataRepository : IRepository { - /// - /// Opens the connection to the repository - /// - /// Task. - Task Initialize(); - /// /// Saves the user data. /// diff --git a/MediaBrowser.Controller/Providers/IProviderRepository.cs b/MediaBrowser.Controller/Providers/IProviderRepository.cs index 1f77d0ca1..891275d77 100644 --- a/MediaBrowser.Controller/Providers/IProviderRepository.cs +++ b/MediaBrowser.Controller/Providers/IProviderRepository.cs @@ -21,11 +21,5 @@ namespace MediaBrowser.Controller.Providers /// The cancellation token. /// Task. Task SaveMetadataStatus(MetadataStatus status, CancellationToken cancellationToken); - - /// - /// Initializes this instance. - /// - /// Task. - Task Initialize(); } } diff --git a/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs b/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs index 85ab76182..b0e05a5bc 100644 --- a/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs +++ b/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs @@ -27,11 +27,11 @@ namespace MediaBrowser.Server.Implementations.Activity _appPaths = appPaths; } - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "activitylog.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 43f5d741b..aff3a5e16 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -78,9 +78,6 @@ - - ..\ThirdParty\System.Data.SQLite.ManagedOnly\1.0.94.0\System.Data.SQLite.dll - @@ -261,6 +258,8 @@ + + @@ -275,7 +274,6 @@ - diff --git a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs b/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs index 7302431e1..cecf03ddf 100644 --- a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs +++ b/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs @@ -32,11 +32,11 @@ namespace MediaBrowser.Server.Implementations.Notifications _appPaths = appPaths; } - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "notifications.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs new file mode 100644 index 000000000..103b75f84 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs @@ -0,0 +1,182 @@ +using System.Text; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Serialization; +using System; +using System.Data; +using System.IO; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Persistence +{ + static class DataExtensions + { + /// + /// Determines whether the specified conn is open. + /// + /// The conn. + /// true if the specified conn is open; otherwise, false. + public static bool IsOpen(this IDbConnection conn) + { + return conn.State == ConnectionState.Open; + } + + public static IDataParameter GetParameter(this IDbCommand cmd, int index) + { + return (IDataParameter)cmd.Parameters[index]; + } + + public static IDataParameter Add(this IDataParameterCollection paramCollection, IDbCommand cmd, string name, DbType type) + { + var param = cmd.CreateParameter(); + + param.ParameterName = name; + param.DbType = type; + + paramCollection.Add(param); + + return param; + } + + public static IDataParameter Add(this IDataParameterCollection paramCollection, IDbCommand cmd, string name) + { + var param = cmd.CreateParameter(); + + param.ParameterName = name; + + paramCollection.Add(param); + + return param; + } + + + /// + /// Gets a stream from a DataReader at a given ordinal + /// + /// The reader. + /// The ordinal. + /// Stream. + /// reader + public static Stream GetMemoryStream(this IDataReader reader, int ordinal) + { + if (reader == null) + { + throw new ArgumentNullException("reader"); + } + + var memoryStream = new MemoryStream(); + var num = 0L; + var array = new byte[4096]; + long bytes; + do + { + bytes = reader.GetBytes(ordinal, num, array, 0, array.Length); + memoryStream.Write(array, 0, (int)bytes); + num += bytes; + } + while (bytes > 0L); + memoryStream.Position = 0; + return memoryStream; + } + + /// + /// Runs the queries. + /// + /// The connection. + /// The queries. + /// The logger. + /// true if XXXX, false otherwise + /// queries + public static void RunQueries(this IDbConnection connection, string[] queries, ILogger logger) + { + if (queries == null) + { + throw new ArgumentNullException("queries"); + } + + using (var tran = connection.BeginTransaction()) + { + try + { + using (var cmd = connection.CreateCommand()) + { + foreach (var query in queries) + { + cmd.Transaction = tran; + cmd.CommandText = query; + cmd.ExecuteNonQuery(); + } + } + + tran.Commit(); + } + catch (Exception e) + { + logger.ErrorException("Error running queries", e); + tran.Rollback(); + throw; + } + } + } + + public static void Attach(IDbConnection db, string path, string alias) + { + using (var cmd = db.CreateCommand()) + { + cmd.CommandText = string.Format("attach '{0}' as {1};", path, alias); + cmd.ExecuteNonQuery(); + } + } + + /// + /// Serializes to bytes. + /// + /// The json. + /// The obj. + /// System.Byte[][]. + /// obj + public static byte[] SerializeToBytes(this IJsonSerializer json, object obj) + { + if (obj == null) + { + throw new ArgumentNullException("obj"); + } + + using (var stream = new MemoryStream()) + { + json.SerializeToStream(obj, stream); + return stream.ToArray(); + } + } + + public static void AddColumn(this IDbConnection connection, ILogger logger, string table, string columnName, string type) + { + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "PRAGMA table_info(" + table + ")"; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + if (!reader.IsDBNull(1)) + { + var name = reader.GetString(1); + + if (string.Equals(name, columnName, StringComparison.OrdinalIgnoreCase)) + { + return; + } + } + } + } + } + + var builder = new StringBuilder(); + + builder.AppendLine("alter table " + table); + builder.AppendLine("add column " + columnName + " " + type); + + connection.RunQueries(new[] { builder.ToString() }, logger); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs b/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs new file mode 100644 index 000000000..cac9fe983 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs @@ -0,0 +1,10 @@ +using System.Data; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Persistence +{ + public interface IDbConnector + { + Task Connect(string dbPath); + } +} diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs index 45e0304c1..6077cfdba 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs @@ -52,11 +52,11 @@ namespace MediaBrowser.Server.Implementations.Persistence /// Opens the connection to the database /// /// Task. - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "displaypreferences.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs deleted file mode 100644 index 4fb1e07dd..000000000 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs +++ /dev/null @@ -1,218 +0,0 @@ -using System.Text; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using System; -using System.Data; -using System.Data.SQLite; -using System.IO; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Persistence -{ - /// - /// Class SQLiteExtensions - /// - static class SqliteExtensions - { - /// - /// Determines whether the specified conn is open. - /// - /// The conn. - /// true if the specified conn is open; otherwise, false. - public static bool IsOpen(this IDbConnection conn) - { - return conn.State == ConnectionState.Open; - } - - public static IDataParameter GetParameter(this IDbCommand cmd, int index) - { - return (IDataParameter)cmd.Parameters[index]; - } - - public static IDataParameter Add(this IDataParameterCollection paramCollection, IDbCommand cmd, string name, DbType type) - { - var param = cmd.CreateParameter(); - - param.ParameterName = name; - param.DbType = type; - - paramCollection.Add(param); - - return param; - } - - public static IDataParameter Add(this IDataParameterCollection paramCollection, IDbCommand cmd, string name) - { - var param = cmd.CreateParameter(); - - param.ParameterName = name; - - paramCollection.Add(param); - - return param; - } - - - /// - /// Gets a stream from a DataReader at a given ordinal - /// - /// The reader. - /// The ordinal. - /// Stream. - /// reader - public static Stream GetMemoryStream(this IDataReader reader, int ordinal) - { - if (reader == null) - { - throw new ArgumentNullException("reader"); - } - - var memoryStream = new MemoryStream(); - var num = 0L; - var array = new byte[4096]; - long bytes; - do - { - bytes = reader.GetBytes(ordinal, num, array, 0, array.Length); - memoryStream.Write(array, 0, (int)bytes); - num += bytes; - } - while (bytes > 0L); - memoryStream.Position = 0; - return memoryStream; - } - - /// - /// Runs the queries. - /// - /// The connection. - /// The queries. - /// The logger. - /// true if XXXX, false otherwise - /// queries - public static void RunQueries(this IDbConnection connection, string[] queries, ILogger logger) - { - if (queries == null) - { - throw new ArgumentNullException("queries"); - } - - using (var tran = connection.BeginTransaction()) - { - try - { - using (var cmd = connection.CreateCommand()) - { - foreach (var query in queries) - { - cmd.Transaction = tran; - cmd.CommandText = query; - cmd.ExecuteNonQuery(); - } - } - - tran.Commit(); - } - catch (Exception e) - { - logger.ErrorException("Error running queries", e); - tran.Rollback(); - throw; - } - } - } - - /// - /// Connects to db. - /// - /// The db path. - /// The logger. - /// Task{IDbConnection}. - /// dbPath - public static async Task ConnectToDb(string dbPath, ILogger logger) - { - if (string.IsNullOrEmpty(dbPath)) - { - throw new ArgumentNullException("dbPath"); - } - - logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, dbPath); - - var connectionstr = new SQLiteConnectionStringBuilder - { - PageSize = 4096, - CacheSize = 2000, - SyncMode = SynchronizationModes.Full, - DataSource = dbPath, - JournalMode = SQLiteJournalModeEnum.Wal - }; - - var connection = new SQLiteConnection(connectionstr.ConnectionString); - - await connection.OpenAsync().ConfigureAwait(false); - - return connection; - } - - public static void Attach(IDbConnection db, string path, string alias) - { - using (var cmd = db.CreateCommand()) - { - cmd.CommandText = string.Format("attach '{0}' as {1};", path, alias); - cmd.ExecuteNonQuery(); - } - } - - /// - /// Serializes to bytes. - /// - /// The json. - /// The obj. - /// System.Byte[][]. - /// obj - public static byte[] SerializeToBytes(this IJsonSerializer json, object obj) - { - if (obj == null) - { - throw new ArgumentNullException("obj"); - } - - using (var stream = new MemoryStream()) - { - json.SerializeToStream(obj, stream); - return stream.ToArray(); - } - } - - public static void AddColumn(this IDbConnection connection, ILogger logger, string table, string columnName, string type) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(" + table + ")"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, columnName, StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table " + table); - builder.AppendLine("add column " + columnName + " " + type); - - connection.RunQueries(new[] { builder.ToString() }, logger); - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs index 2d5aad04d..037776997 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs @@ -35,11 +35,11 @@ namespace MediaBrowser.Server.Implementations.Persistence /// Opens the connection to the database /// /// Task. - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "fileorganization.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs index dbceda727..40d5c9586 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs @@ -39,11 +39,11 @@ namespace MediaBrowser.Server.Implementations.Persistence /// Opens the connection to the database /// /// Task. - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "refreshinfo.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs index 63c41c71f..33a2b1187 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs @@ -37,11 +37,11 @@ namespace MediaBrowser.Server.Implementations.Persistence /// Opens the connection to the database /// /// Task. - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "userdata_v2.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs index 9bd7e47f3..f7ca39a54 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs @@ -43,12 +43,12 @@ namespace MediaBrowser.Server.Implementations.Persistence /// Opens the connection to the database /// /// Task. - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "users.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); - + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); + string[] queries = { "create table if not exists users (guid GUID primary key, data BLOB)", diff --git a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs index b932f0cac..e8d9814ec 100644 --- a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs +++ b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs @@ -27,11 +27,11 @@ namespace MediaBrowser.Server.Implementations.Security _appPaths = appPaths; } - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "authentication.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/Social/SharingRepository.cs b/MediaBrowser.Server.Implementations/Social/SharingRepository.cs index d6d7f021a..317743eb1 100644 --- a/MediaBrowser.Server.Implementations/Social/SharingRepository.cs +++ b/MediaBrowser.Server.Implementations/Social/SharingRepository.cs @@ -26,11 +26,11 @@ namespace MediaBrowser.Server.Implementations.Social /// Opens the connection to the database /// /// Task. - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "shares.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs index 965c081eb..6d31663b9 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs @@ -39,11 +39,11 @@ namespace MediaBrowser.Server.Implementations.Sync _appPaths = appPaths; } - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "sync14.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj index 48d2df7ce..b71877e17 100644 --- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj +++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj @@ -76,12 +76,17 @@ ..\ThirdParty\MediaBrowser.IsoMounting.Linux\MediaBrowser.IsoMounting.Linux.dll + + + ..\ThirdParty\System.Data.SQLite.ManagedOnly\1.0.94.0\System.Data.SQLite.dll + Properties\SharedVersion.cs + diff --git a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs index fbfef9a34..a012a19a3 100644 --- a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs +++ b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Reflection; using System.Text.RegularExpressions; using MediaBrowser.Controller.Power; +using MediaBrowser.Server.Implementations.Persistence; using MediaBrowser.Server.Startup.Common.FFMpeg; using OperatingSystem = MediaBrowser.Server.Startup.Common.OperatingSystem; @@ -17,9 +18,12 @@ namespace MediaBrowser.Server.Mono.Native public abstract class BaseMonoApp : INativeApp { protected StartupOptions StartupOptions { get; private set; } - protected BaseMonoApp(StartupOptions startupOptions) + protected ILogger Logger { get; private set; } + + protected BaseMonoApp(StartupOptions startupOptions, ILogger logger) { StartupOptions = startupOptions; + Logger = logger; } /// @@ -227,6 +231,11 @@ namespace MediaBrowser.Server.Mono.Native throw new NotImplementedException(); } + public IDbConnector GetDbConnector() + { + return new DbConnector(Logger); + } + public static FFMpegInstallInfo GetInfo(NativeEnvironment environment) { var info = new FFMpegInstallInfo(); diff --git a/MediaBrowser.Server.Mono/Native/NativeApp.cs b/MediaBrowser.Server.Mono/Native/NativeApp.cs index c73a96497..c0874a1d8 100644 --- a/MediaBrowser.Server.Mono/Native/NativeApp.cs +++ b/MediaBrowser.Server.Mono/Native/NativeApp.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Server.Startup.Common; +using MediaBrowser.Model.Logging; +using MediaBrowser.Server.Startup.Common; namespace MediaBrowser.Server.Mono.Native { @@ -7,8 +8,8 @@ namespace MediaBrowser.Server.Mono.Native /// internal class NativeApp : BaseMonoApp { - public NativeApp(StartupOptions startupOptions) - : base(startupOptions) + public NativeApp(StartupOptions startupOptions, ILogger logger) + : base(startupOptions, logger) { } diff --git a/MediaBrowser.Server.Mono/Native/SqliteExtensions.cs b/MediaBrowser.Server.Mono/Native/SqliteExtensions.cs new file mode 100644 index 000000000..385a7d0c5 --- /dev/null +++ b/MediaBrowser.Server.Mono/Native/SqliteExtensions.cs @@ -0,0 +1,62 @@ +using System; +using System.Data; +using System.Data.SQLite; +using System.Threading.Tasks; +using MediaBrowser.Model.Logging; +using MediaBrowser.Server.Implementations.Persistence; + +namespace MediaBrowser.Server.Mono.Native +{ + /// + /// Class SQLiteExtensions + /// + static class SqliteExtensions + { + /// + /// Connects to db. + /// + /// The db path. + /// The logger. + /// Task{IDbConnection}. + /// dbPath + public static async Task ConnectToDb(string dbPath, ILogger logger) + { + if (string.IsNullOrEmpty(dbPath)) + { + throw new ArgumentNullException("dbPath"); + } + + logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, dbPath); + + var connectionstr = new SQLiteConnectionStringBuilder + { + PageSize = 4096, + CacheSize = 2000, + SyncMode = SynchronizationModes.Full, + DataSource = dbPath, + JournalMode = SQLiteJournalModeEnum.Wal + }; + + var connection = new SQLiteConnection(connectionstr.ConnectionString); + + await connection.OpenAsync().ConfigureAwait(false); + + return connection; + } + } + + public class DbConnector : IDbConnector + { + private readonly ILogger _logger; + + public DbConnector(ILogger logger) + { + _logger = logger; + } + + public Task Connect(string dbPath) + { + return SqliteExtensions.ConnectToDb(dbPath, _logger); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 2a0609449..32de45242 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Server.Mono var fileSystem = new ManagedFileSystem(new PatternsLogger(logManager.GetLogger("FileSystem")), false, false); fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); - var nativeApp = new NativeApp(options); + var nativeApp = new NativeApp(options, logManager.GetLogger("App")); _appHost = new ApplicationHost(appPaths, logManager, options, fileSystem, "emby.mono.zip", nativeApp); diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index fd6dee0f6..2d56a1575 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -410,13 +410,16 @@ namespace MediaBrowser.Server.Startup.Common UserRepository = await GetUserRepository().ConfigureAwait(false); RegisterSingleInstance(UserRepository); - DisplayPreferencesRepository = new SqliteDisplayPreferencesRepository(LogManager, JsonSerializer, ApplicationPaths); + var displayPreferencesRepo = new SqliteDisplayPreferencesRepository(LogManager, JsonSerializer, ApplicationPaths); + DisplayPreferencesRepository = displayPreferencesRepo; RegisterSingleInstance(DisplayPreferencesRepository); - ItemRepository = new SqliteItemRepository(ApplicationPaths, JsonSerializer, LogManager); + var itemRepo = new SqliteItemRepository(ServerConfigurationManager, JsonSerializer, LogManager); + ItemRepository = itemRepo; RegisterSingleInstance(ItemRepository); - ProviderRepository = new SqliteProviderInfoRepository(LogManager, ApplicationPaths); + var providerRepo = new SqliteProviderInfoRepository(LogManager, ApplicationPaths); + ProviderRepository = providerRepo; RegisterSingleInstance(ProviderRepository); FileOrganizationRepository = await GetFileOrganizationRepository().ConfigureAwait(false); @@ -541,7 +544,7 @@ namespace MediaBrowser.Server.Startup.Common RegisterSingleInstance(NativeApp.GetPowerManagement()); var sharingRepo = new SharingRepository(LogManager, ApplicationPaths); - await sharingRepo.Initialize().ConfigureAwait(false); + await sharingRepo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); RegisterSingleInstance(new SharingManager(sharingRepo, ServerConfigurationManager, LibraryManager, this)); RegisterSingleInstance(new SsdpHandler(LogManager.GetLogger("SsdpHandler"), ServerConfigurationManager, this)); @@ -557,9 +560,11 @@ namespace MediaBrowser.Server.Startup.Common SubtitleEncoder = new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager); RegisterSingleInstance(SubtitleEncoder); - - await ConfigureDisplayPreferencesRepositories().ConfigureAwait(false); - await ConfigureItemRepositories().ConfigureAwait(false); + + await displayPreferencesRepo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); + await itemRepo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); + await providerRepo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); + ((LibraryManager)LibraryManager).ItemRepository = ItemRepository; await ConfigureUserDataRepositories().ConfigureAwait(false); await ConfigureNotificationsRepository().ConfigureAwait(false); progress.Report(100); @@ -658,7 +663,7 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new SqliteUserRepository(LogManager, ApplicationPaths, JsonSerializer); - await repo.Initialize().ConfigureAwait(false); + await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); return repo; } @@ -677,7 +682,7 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new SqliteFileOrganizationRepository(LogManager, ServerConfigurationManager.ApplicationPaths); - await repo.Initialize().ConfigureAwait(false); + await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); return repo; } @@ -686,7 +691,7 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new AuthenticationRepository(LogManager, ServerConfigurationManager.ApplicationPaths); - await repo.Initialize().ConfigureAwait(false); + await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); return repo; } @@ -695,7 +700,7 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new ActivityRepository(LogManager, ServerConfigurationManager.ApplicationPaths); - await repo.Initialize().ConfigureAwait(false); + await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); return repo; } @@ -704,7 +709,7 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new SyncRepository(LogManager, JsonSerializer, ServerConfigurationManager.ApplicationPaths); - await repo.Initialize().ConfigureAwait(false); + await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); return repo; } @@ -717,35 +722,13 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new SqliteNotificationsRepository(LogManager, ApplicationPaths); - await repo.Initialize().ConfigureAwait(false); + await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); NotificationsRepository = repo; RegisterSingleInstance(NotificationsRepository); } - /// - /// Configures the repositories. - /// - /// Task. - private async Task ConfigureDisplayPreferencesRepositories() - { - await DisplayPreferencesRepository.Initialize().ConfigureAwait(false); - } - - /// - /// Configures the item repositories. - /// - /// Task. - private async Task ConfigureItemRepositories() - { - await ItemRepository.Initialize().ConfigureAwait(false); - - await ProviderRepository.Initialize().ConfigureAwait(false); - - ((LibraryManager)LibraryManager).ItemRepository = ItemRepository; - } - /// /// Configures the user data repositories. /// @@ -754,7 +737,7 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new SqliteUserDataRepository(LogManager, ApplicationPaths); - await repo.Initialize().ConfigureAwait(false); + await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); ((UserDataManager)UserDataManager).Repository = repo; } diff --git a/MediaBrowser.Server.Startup.Common/INativeApp.cs b/MediaBrowser.Server.Startup.Common/INativeApp.cs index c0758b47f..c13d3624e 100644 --- a/MediaBrowser.Server.Startup.Common/INativeApp.cs +++ b/MediaBrowser.Server.Startup.Common/INativeApp.cs @@ -3,6 +3,7 @@ using MediaBrowser.Model.Logging; using System.Collections.Generic; using System.Reflection; using MediaBrowser.Controller.Power; +using MediaBrowser.Server.Implementations.Persistence; using MediaBrowser.Server.Startup.Common.FFMpeg; namespace MediaBrowser.Server.Startup.Common @@ -104,5 +105,7 @@ namespace MediaBrowser.Server.Startup.Common FFMpegInstallInfo GetFfmpegInstallInfo(); void LaunchUrl(string url); + + IDbConnector GetDbConnector(); } } diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 291e63dac..f544a149d 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -13,6 +13,8 @@ 512 ..\ + + AnyCPU @@ -81,9 +83,9 @@ - - False - ..\packages\System.Data.SQLite.Core.1.0.94.0\lib\net45\System.Data.SQLite.dll + + ..\packages\System.Data.SQLite.Core.1.0.101.0\lib\net46\System.Data.SQLite.dll + True @@ -112,6 +114,7 @@ + @@ -156,14 +159,6 @@ - - x64\SQLite.Interop.dll - PreserveNewest - - - x86\SQLite.Interop.dll - PreserveNewest - MediaBrowser.InstallUtil.dll PreserveNewest @@ -1116,6 +1111,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/Native/SqliteExtensions.cs b/MediaBrowser.ServerApplication/Native/SqliteExtensions.cs new file mode 100644 index 000000000..1cde2ea13 --- /dev/null +++ b/MediaBrowser.ServerApplication/Native/SqliteExtensions.cs @@ -0,0 +1,62 @@ +using System; +using System.Data; +using System.Data.SQLite; +using System.Threading.Tasks; +using MediaBrowser.Model.Logging; +using MediaBrowser.Server.Implementations.Persistence; + +namespace MediaBrowser.ServerApplication.Native +{ + /// + /// Class SQLiteExtensions + /// + static class SqliteExtensions + { + /// + /// Connects to db. + /// + /// The db path. + /// The logger. + /// Task{IDbConnection}. + /// dbPath + public static async Task ConnectToDb(string dbPath, ILogger logger) + { + if (string.IsNullOrEmpty(dbPath)) + { + throw new ArgumentNullException("dbPath"); + } + + logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, dbPath); + + var connectionstr = new SQLiteConnectionStringBuilder + { + PageSize = 4096, + CacheSize = 2000, + SyncMode = SynchronizationModes.Full, + DataSource = dbPath, + JournalMode = SQLiteJournalModeEnum.Wal + }; + + var connection = new SQLiteConnection(connectionstr.ConnectionString); + + await connection.OpenAsync().ConfigureAwait(false); + + return connection; + } + } + + public class DbConnector : IDbConnector + { + private readonly ILogger _logger; + + public DbConnector(ILogger logger) + { + _logger = logger; + } + + public Task Connect(string dbPath) + { + return SqliteExtensions.ConnectToDb(dbPath, _logger); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index 10cd59436..808c7558e 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -10,6 +10,7 @@ using System.Reflection; using System.Windows.Forms; using CommonIO; using MediaBrowser.Controller.Power; +using MediaBrowser.Server.Implementations.Persistence; using MediaBrowser.Server.Startup.Common.FFMpeg; using OperatingSystem = MediaBrowser.Server.Startup.Common.OperatingSystem; @@ -191,6 +192,11 @@ namespace MediaBrowser.ServerApplication.Native } } + public IDbConnector GetDbConnector() + { + return new DbConnector(_logger); + } + /// /// Processes the exited. /// diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index 1c86a02ae..2d4baae25 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -3,5 +3,5 @@ - + \ No newline at end of file -- cgit v1.2.3 From 4ddde2cdc2ad3a951120853825df9f3588bc36e4 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 1 May 2016 18:11:24 -0400 Subject: introduce presentation unique key --- MediaBrowser.Api/Movies/MoviesService.cs | 7 +- MediaBrowser.Api/VideosService.cs | 14 +- MediaBrowser.Controller/Entities/BaseItem.cs | 6 + MediaBrowser.Controller/Entities/TV/Series.cs | 6 + MediaBrowser.Controller/Entities/Video.cs | 76 +++++++--- .../Configuration/ServerConfiguration.cs | 1 + .../Library/LibraryManager.cs | 24 +-- .../Persistence/CleanDatabaseScheduledTask.cs | 6 + .../Persistence/SqliteItemRepository.cs | 168 ++++++++++++++++----- 9 files changed, 212 insertions(+), 96 deletions(-) (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index bfbb3a6d7..1f0133e73 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -197,12 +197,7 @@ namespace MediaBrowser.Api.Movies var parentIds = new string[] { }; var list = _libraryManager.GetItemList(query, parentIds) - .Where(i => - { - // Strip out secondary versions - var v = i as Video; - return v != null && !v.PrimaryVersionId.HasValue; - }) + .DistinctBy(i => i.PresentationUniqueKey, StringComparer.OrdinalIgnoreCase) .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N")) .ToList(); diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs index c6ec69c85..6cefda3a3 100644 --- a/MediaBrowser.Api/VideosService.cs +++ b/MediaBrowser.Api/VideosService.cs @@ -130,6 +130,7 @@ namespace MediaBrowser.Api var items = request.Ids.Split(',') .Select(i => new Guid(i)) .Select(i => _libraryManager.GetItemById(i)) + .OfType