diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index 9eb96873b7..e9ac45fa25 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -72,6 +72,7 @@ namespace MediaBrowser.Api _config.Configuration.EnableUserSpecificUserViews = true; _config.Configuration.EnableCustomPathSubFolders = true; _config.Configuration.DisableXmlSavers = true; + _config.Configuration.DisableStartupScan = true; _config.SaveConfiguration(); } diff --git a/MediaBrowser.Common/ScheduledTasks/IntervalTrigger.cs b/MediaBrowser.Common/ScheduledTasks/IntervalTrigger.cs index 15109be4f0..b615adf816 100644 --- a/MediaBrowser.Common/ScheduledTasks/IntervalTrigger.cs +++ b/MediaBrowser.Common/ScheduledTasks/IntervalTrigger.cs @@ -30,6 +30,17 @@ namespace MediaBrowser.Common.ScheduledTasks /// public TaskExecutionOptions TaskOptions { get; set; } + /// + /// Gets or sets the first run delay. + /// + /// The first run delay. + public TimeSpan FirstRunDelay { get; set; } + + public IntervalTrigger() + { + FirstRunDelay = TimeSpan.FromHours(1); + } + /// /// Stars waiting for the trigger action /// @@ -41,7 +52,7 @@ namespace MediaBrowser.Common.ScheduledTasks var triggerDate = lastResult != null ? lastResult.EndTimeUtc.Add(Interval) : - DateTime.UtcNow.Add(Interval); + DateTime.UtcNow.Add(FirstRunDelay); if (DateTime.UtcNow > triggerDate) { diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index cd5c391730..a333fc6e99 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -142,7 +142,7 @@ namespace MediaBrowser.Controller.Entities public virtual string Path { get; set; } [IgnoreDataMember] - protected internal bool IsOffline { get; set; } + public bool IsOffline { get; set; } /// /// Returns the folder containing the item. diff --git a/MediaBrowser.Dlna/DlnaManager.cs b/MediaBrowser.Dlna/DlnaManager.cs index 9ce62034b4..124d0e6758 100644 --- a/MediaBrowser.Dlna/DlnaManager.cs +++ b/MediaBrowser.Dlna/DlnaManager.cs @@ -547,7 +547,8 @@ namespace MediaBrowser.Dlna new DefaultProfile(), new PopcornHourProfile(), new VlcProfile(), - new BubbleUpnpProfile() + new BubbleUpnpProfile(), + new KodiProfile() }; foreach (var item in list) diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj index 2a495638a9..055173a7ce 100644 --- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj +++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj @@ -166,7 +166,9 @@ - + + Designer + diff --git a/MediaBrowser.Dlna/Profiles/KodiProfile.cs b/MediaBrowser.Dlna/Profiles/KodiProfile.cs new file mode 100644 index 0000000000..75c323a1ad --- /dev/null +++ b/MediaBrowser.Dlna/Profiles/KodiProfile.cs @@ -0,0 +1,97 @@ +using MediaBrowser.Model.Dlna; +using System.Xml.Serialization; + +namespace MediaBrowser.Dlna.Profiles +{ + [XmlRoot("Profile")] + public class KodiProfile : DefaultProfile + { + public KodiProfile() + { + Name = "Kodi"; + + MaxStreamingBitrate = 100000000; + MaxStaticBitrate = 100000000; + MusicStreamingTranscodingBitrate = 1280000; + MusicSyncBitrate = 1280000; + + TimelineOffsetSeconds = 5; + + Identification = new DeviceIdentification + { + ModelName = "Kodi", + + Headers = new[] + { + new HttpHeaderInfo {Name = "User-Agent", Value = "Kodi", Match = HeaderMatchType.Substring} + } + }; + + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + AudioCodec = "mp3", + Type = DlnaProfileType.Audio + }, + + new TranscodingProfile + { + Container = "ts", + Type = DlnaProfileType.Video, + AudioCodec = "aac", + VideoCodec = "h264" + }, + + new TranscodingProfile + { + Container = "jpeg", + Type = DlnaProfileType.Photo + } + }; + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Container = "", + Type = DlnaProfileType.Video + }, + + new DirectPlayProfile + { + Container = "", + Type = DlnaProfileType.Audio + }, + + new DirectPlayProfile + { + Container = "", + Type = DlnaProfileType.Photo, + } + }; + + ResponseProfiles = new ResponseProfile[] { }; + + ContainerProfiles = new ContainerProfile[] { }; + + CodecProfiles = new CodecProfile[] { }; + + SubtitleProfiles = new[] + { + new SubtitleProfile + { + Format = "srt", + Method = SubtitleDeliveryMethod.External, + }, + + new SubtitleProfile + { + Format = "sub", + Method = SubtitleDeliveryMethod.External, + } + }; + } + } +} diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 46f9db580c..07d5905c69 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -98,6 +98,12 @@ namespace MediaBrowser.Model.Configuration /// true if [enable localized guids]; otherwise, false. public bool EnableLocalizedGuids { get; set; } + /// + /// Gets or sets a value indicating whether [disable startup scan]. + /// + /// true if [disable startup scan]; otherwise, false. + public bool DisableStartupScan { get; set; } + /// /// Gets or sets a value indicating whether [enable library metadata sub folder]. /// diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs index 0f092b5545..4953621f5a 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs @@ -131,7 +131,7 @@ namespace MediaBrowser.Providers.MediaInfo { return new ITaskTrigger[] { - new DailyTrigger { TimeOfDay = TimeSpan.FromHours(3) }, + new IntervalTrigger{ Interval = TimeSpan.FromHours(8)} }; } } diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index e1c5291870..5bd26ce187 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -3,6 +3,7 @@ using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Logging; using MediaBrowser.Server.Implementations.ScheduledTasks; @@ -700,4 +701,23 @@ namespace MediaBrowser.Server.Implementations.IO } } } + + public class LibraryMonitorStartup : IServerEntryPoint + { + private readonly ILibraryMonitor _monitor; + + public LibraryMonitorStartup(ILibraryMonitor monitor) + { + _monitor = monitor; + } + + public void Run() + { + _monitor.Start(); + } + + public void Dispose() + { + } + } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 708891e687..cb5a374010 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -438,8 +438,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings return lineups; } - _logger.Info("Headends on account "); - var options = new HttpRequestOptions() { Url = ApiUrl + "/headends?country=" + country + "&postalcode=" + location, @@ -454,16 +452,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings using (Stream responce = await _httpClient.Get(options).ConfigureAwait(false)) { var root = _jsonSerializer.DeserializeFromStream>(responce); - _logger.Info("Lineups on account "); + if (root != null) { foreach (ScheduleDirect.Headends headend in root) { - _logger.Info("Headend: " + headend.headend); foreach (ScheduleDirect.Lineup lineup in headend.lineups) { - _logger.Info("Headend: " + lineup.uri); - lineups.Add(new NameIdPair { Name = string.IsNullOrWhiteSpace(lineup.name) ? lineup.lineup : lineup.name, @@ -474,7 +469,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings } else { - _logger.Info("No lineups on account"); + _logger.Info("No lineups available"); } } } diff --git a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs index 69e04c072b..7a993b7dbe 100644 --- a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs @@ -1,14 +1,15 @@ using MediaBrowser.Common.Progress; using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Logging; namespace MediaBrowser.Server.Implementations.Persistence { @@ -17,12 +18,14 @@ namespace MediaBrowser.Server.Implementations.Persistence private readonly ILibraryManager _libraryManager; private readonly IItemRepository _itemRepo; private readonly ILogger _logger; + private readonly IServerConfigurationManager _config; - public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger) + public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config) { _libraryManager = libraryManager; _itemRepo = itemRepo; _logger = logger; + _config = config; } public string Name @@ -53,7 +56,6 @@ namespace MediaBrowser.Server.Implementations.Persistence var itemIds = _libraryManager.GetItemIds(new InternalItemsQuery { IsCurrentSchema = false, - Limit = 100000, // These are constantly getting regenerated so don't bother with them here ExcludeItemTypes = new[] { typeof(LiveTvProgram).Name } @@ -81,6 +83,12 @@ namespace MediaBrowser.Server.Implementations.Persistence progress.Report(percent * 100); } + if (!_config.Configuration.DisableStartupScan) + { + _config.Configuration.DisableStartupScan = true; + _config.SaveConfiguration(); + } + progress.Report(100); } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 71578d1e09..806e86a5ad 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -72,7 +72,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _deletePeopleCommand; private IDbCommand _savePersonCommand; - private const int LatestSchemaVersion = 4; + private const int LatestSchemaVersion = 6; /// /// Initializes a new instance of the class. @@ -173,6 +173,9 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(_logger, "TypedBaseItems", "DateCreated", "DATETIME"); _connection.AddColumn(_logger, "TypedBaseItems", "DateModified", "DATETIME"); + _connection.AddColumn(_logger, "TypedBaseItems", "ForcedSortName", "Text"); + _connection.AddColumn(_logger, "TypedBaseItems", "IsOffline", "BIT"); + PrepareStatements(); _mediaStreamsRepository.Initialize(); @@ -223,7 +226,9 @@ namespace MediaBrowser.Server.Implementations.Persistence "VoteCount", "DisplayMediaType", "DateCreated", - "DateModified" + "DateModified", + "ForcedSortName", + "IsOffline" }; _saveItemCommand = _connection.CreateCommand(); _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -391,6 +396,9 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = item.DateCreated; _saveItemCommand.GetParameter(index++).Value = item.DateModified; + _saveItemCommand.GetParameter(index++).Value = item.ForcedSortName; + _saveItemCommand.GetParameter(index++).Value = item.IsOffline; + _saveItemCommand.Transaction = transaction; _saveItemCommand.ExecuteNonQuery(); @@ -948,7 +956,6 @@ namespace MediaBrowser.Server.Implementations.Persistence } var includeTypes = query.IncludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray(); - if (includeTypes.Length == 1) { whereClauses.Add("type=@type"); @@ -959,6 +966,19 @@ namespace MediaBrowser.Server.Implementations.Persistence var inClause = string.Join(",", includeTypes.Select(i => "'" + i + "'").ToArray()); whereClauses.Add(string.Format("type in ({0})", inClause)); } + + var excludeTypes = query.ExcludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray(); + if (excludeTypes.Length == 1) + { + whereClauses.Add("type<>@type"); + cmd.Parameters.Add(cmd, "@type", DbType.String).Value = excludeTypes[0]; + } + else if (excludeTypes.Length > 1) + { + var inClause = string.Join(",", excludeTypes.Select(i => "'" + i + "'").ToArray()); + whereClauses.Add(string.Format("type not in ({0})", inClause)); + } + if (query.ChannelIds.Length == 1) { whereClauses.Add("ChannelId=@ChannelId"); diff --git a/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs b/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs index ed284a90d1..8cb76393e6 100644 --- a/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs +++ b/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs @@ -1,4 +1,6 @@ -using MediaBrowser.Common.ScheduledTasks; +using System.Linq; +using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Server.Implementations.Library; using System; @@ -17,14 +19,16 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks /// The _library manager /// private readonly ILibraryManager _libraryManager; + private readonly IServerConfigurationManager _config; /// /// Initializes a new instance of the class. /// /// The library manager. - public RefreshMediaLibraryTask(ILibraryManager libraryManager) + public RefreshMediaLibraryTask(ILibraryManager libraryManager, IServerConfigurationManager config) { _libraryManager = libraryManager; + _config = config; } /// @@ -33,12 +37,18 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks /// IEnumerable{BaseTaskTrigger}. public IEnumerable GetDefaultTriggers() { - return new ITaskTrigger[] { - - new StartupTrigger(), + var list = new ITaskTrigger[] { new IntervalTrigger{ Interval = TimeSpan.FromHours(8)} - }; + + }.ToList(); + + if (!_config.Configuration.DisableStartupScan) + { + list.Add(new StartupTrigger()); + } + + return list; } ///