diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index a979848e2..7a40d5bd1 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -337,9 +337,9 @@ namespace MediaBrowser.Api.Playback /// Gets the video bitrate to specify on the command line /// /// The state. - /// The video codec. + /// The video codec. /// System.String. - protected string GetVideoQualityParam(StreamState state, string videoCodec) + protected string GetVideoQualityParam(StreamState state, string videoEncoder) { var param = string.Empty; @@ -348,7 +348,7 @@ namespace MediaBrowser.Api.Playback var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); - if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase)) { if (!string.IsNullOrWhiteSpace(encodingOptions.H264Preset)) { @@ -369,7 +369,7 @@ namespace MediaBrowser.Api.Playback } } - else if (string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase)) { param += "-preset fast"; @@ -377,20 +377,20 @@ namespace MediaBrowser.Api.Playback } // h264 (h264_qsv) - else if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase)) { param += "-preset 7 -look_ahead 0"; } // h264 (h264_nvenc) - else if (string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) { param += "-preset default"; } // webm - else if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase)) { // Values 0-3, 0 being highest quality but slower var profileScore = 0; @@ -417,23 +417,23 @@ namespace MediaBrowser.Api.Playback qmax); } - else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "mpeg4", StringComparison.OrdinalIgnoreCase)) { param += "-mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2"; } // asf/wmv - else if (string.Equals(videoCodec, "wmv2", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "wmv2", StringComparison.OrdinalIgnoreCase)) { param += "-qmin 2"; } - else if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "msmpeg4", StringComparison.OrdinalIgnoreCase)) { param += "-mbd 2"; } - param += GetVideoBitrateParam(state, videoCodec); + param += GetVideoBitrateParam(state, videoEncoder); var framerate = GetFramerateParam(state); if (framerate.HasValue) @@ -448,8 +448,8 @@ namespace MediaBrowser.Api.Playback if (!string.IsNullOrEmpty(state.VideoRequest.Profile)) { - if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { // not supported by h264_omx param += " -profile:v " + state.VideoRequest.Profile; @@ -458,11 +458,13 @@ namespace MediaBrowser.Api.Playback if (!string.IsNullOrEmpty(state.VideoRequest.Level)) { + var level = NormalizeTranscodingLevel(state.OutputVideoCodec, state.VideoRequest.Level); + // h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format - if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) || + string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) { - switch (state.VideoRequest.Level) + switch (level) { case "30": param += " -level 3"; @@ -492,20 +494,20 @@ namespace MediaBrowser.Api.Playback param += " -level 5.2"; break; default: - param += " -level " + state.VideoRequest.Level; + param += " -level " + level; break; } } - else if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase)) + else if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase)) { - param += " -level " + state.VideoRequest.Level; + param += " -level " + level; } } - if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { param = "-pix_fmt yuv420p " + param; } @@ -513,6 +515,25 @@ namespace MediaBrowser.Api.Playback return param; } + private string NormalizeTranscodingLevel(string videoCodec, string level) + { + double requestLevel; + + // Clients may direct play higher than level 41, but there's no reason to transcode higher + if (double.TryParse(level, NumberStyles.Any, UsCulture, out requestLevel)) + { + if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) + { + if (requestLevel > 41) + { + return "41"; + } + } + } + + return level; + } + protected string GetAudioFilterParam(StreamState state, bool isHls) { var volParam = string.Empty; @@ -1176,17 +1197,21 @@ namespace MediaBrowser.Api.Playback await Task.Delay(100, cancellationTokenSource.Token).ConfigureAwait(false); } - if (state.IsInputVideo && transcodingJob.Type == TranscodingJobType.Progressive) + if (state.IsInputVideo && transcodingJob.Type == TranscodingJobType.Progressive && !transcodingJob.HasExited) { await Task.Delay(1000, cancellationTokenSource.Token).ConfigureAwait(false); - if (state.ReadInputAtNativeFramerate) + if (state.ReadInputAtNativeFramerate && !transcodingJob.HasExited) { await Task.Delay(1500, cancellationTokenSource.Token).ConfigureAwait(false); } } - StartThrottler(state, transcodingJob); + if (!transcodingJob.HasExited) + { + StartThrottler(state, transcodingJob); + } + ReportUsage(state); return transcodingJob; diff --git a/MediaBrowser.Controller/Channels/IChannelManager.cs b/MediaBrowser.Controller/Channels/IChannelManager.cs index e3d2d0440..3c46247a7 100644 --- a/MediaBrowser.Controller/Channels/IChannelManager.cs +++ b/MediaBrowser.Controller/Channels/IChannelManager.cs @@ -31,6 +31,8 @@ namespace MediaBrowser.Controller.Channels /// ChannelFeatures. ChannelFeatures GetChannelFeatures(string id); + bool SupportsSync(string channelId); + /// /// Gets all channel features. /// diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index bf47ada0d..f1d8def4b 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1057,10 +1057,20 @@ namespace MediaBrowser.Controller.Entities /// IList{BaseItem}. public IList GetRecursiveChildren() { - return GetRecursiveChildren(i => true); + return GetRecursiveChildren(true); + } + + public IList GetRecursiveChildren(bool includeLinkedChildren) + { + return GetRecursiveChildren(i => true, includeLinkedChildren); } public IList GetRecursiveChildren(Func filter) + { + return GetRecursiveChildren(filter, true); + } + + public IList GetRecursiveChildren(Func filter, bool includeLinkedChildren) { var result = new Dictionary(); diff --git a/MediaBrowser.Dlna/PlayTo/Device.cs b/MediaBrowser.Dlna/PlayTo/Device.cs index 174ca871a..d1802b3ad 100644 --- a/MediaBrowser.Dlna/PlayTo/Device.cs +++ b/MediaBrowser.Dlna/PlayTo/Device.cs @@ -483,7 +483,9 @@ namespace MediaBrowser.Dlna.PlayTo { if (OnDeviceUnavailable != null) { + _logger.Debug("Disposing device due to loss of connection"); OnDeviceUnavailable(); + return; } } if (_successiveStopCount >= maxSuccessiveStopReturns) diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index ce00acb52..2ded8a66f 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -595,23 +595,23 @@ namespace MediaBrowser.MediaEncoding.Encoder /// Gets the video bitrate to specify on the command line /// /// The state. - /// The video codec. + /// The video codec. /// System.String. - protected string GetVideoQualityParam(EncodingJob state, string videoCodec) + protected string GetVideoQualityParam(EncodingJob state, string videoEncoder) { var param = string.Empty; var isVc1 = state.VideoStream != null && string.Equals(state.VideoStream.Codec, "vc1", StringComparison.OrdinalIgnoreCase); - if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase)) { param = "-preset superfast"; param += " -crf 23"; } - else if (string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase)) { param = "-preset fast"; @@ -619,20 +619,20 @@ namespace MediaBrowser.MediaEncoding.Encoder } // h264 (h264_qsv) - else if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase)) { param = "-preset 7 -look_ahead 0"; } // h264 (h264_nvenc) - else if (string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) { param = "-preset llhq"; } // webm - else if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase)) { // Values 0-3, 0 being highest quality but slower var profileScore = 0; @@ -659,23 +659,23 @@ namespace MediaBrowser.MediaEncoding.Encoder qmax); } - else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "mpeg4", StringComparison.OrdinalIgnoreCase)) { param = "-mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2"; } // asf/wmv - else if (string.Equals(videoCodec, "wmv2", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "wmv2", StringComparison.OrdinalIgnoreCase)) { param = "-qmin 2"; } - else if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "msmpeg4", StringComparison.OrdinalIgnoreCase)) { param = "-mbd 2"; } - param += GetVideoBitrateParam(state, videoCodec); + param += GetVideoBitrateParam(state, videoEncoder); var framerate = GetFramerateParam(state); if (framerate.HasValue) @@ -690,8 +690,8 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.IsNullOrEmpty(state.Options.Profile)) { - if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { // not supported by h264_omx param += " -profile:v " + state.Options.Profile; @@ -702,9 +702,11 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.IsNullOrEmpty(levelString)) { + levelString = NormalizeTranscodingLevel(state.OutputVideoCodec, levelString); + // h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format - if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) || + string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) { switch (levelString) { @@ -740,16 +742,16 @@ namespace MediaBrowser.MediaEncoding.Encoder break; } } - else if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase)) + else if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase)) { param += " -level " + levelString; } } - if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { param = "-pix_fmt yuv420p " + param; } @@ -757,6 +759,25 @@ namespace MediaBrowser.MediaEncoding.Encoder return param; } + private string NormalizeTranscodingLevel(string videoCodec, string level) + { + double requestLevel; + + // Clients may direct play higher than level 41, but there's no reason to transcode higher + if (double.TryParse(level, NumberStyles.Any, UsCulture, out requestLevel)) + { + if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) + { + if (requestLevel > 41) + { + return "41"; + } + } + } + + return level; + } + protected string GetVideoBitrateParam(EncodingJob state, string videoCodec) { var bitrate = state.OutputVideoBitrate; diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index 242a2d24e..ee7dd8b98 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -13,6 +13,7 @@ namespace MediaBrowser.Model.LiveTv public string SeriesRecordingPath { get; set; } public bool EnableAutoOrganize { get; set; } public bool EnableRecordingEncoding { get; set; } + public string RecordingEncodingFormat { get; set; } public bool EnableRecordingSubfolders { get; set; } public bool EnableOriginalAudioWithEncodedRecordings { get; set; } @@ -31,6 +32,7 @@ namespace MediaBrowser.Model.LiveTv TunerHosts = new List(); ListingProviders = new List(); MediaLocationsCreated = new string[] { }; + RecordingEncodingFormat = "mp4"; } } diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index bb7e142b6..b76cf46b0 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -530,6 +530,19 @@ namespace MediaBrowser.Server.Implementations.Channels return GetChannelFeaturesDto(channel, channelProvider, channelProvider.GetChannelFeatures()); } + public bool SupportsSync(string channelId) + { + if (string.IsNullOrWhiteSpace(channelId)) + { + throw new ArgumentNullException("channelId"); + } + + //var channel = GetChannel(channelId); + var channelProvider = GetChannelProvider(channelId); + + return channelProvider.GetChannelFeatures().SupportsContentDownloading; + } + public ChannelFeatures GetChannelFeaturesDto(Channel channel, IChannel provider, InternalChannelFeatures features) @@ -1450,6 +1463,24 @@ namespace MediaBrowser.Server.Implementations.Channels return result; } + internal IChannel GetChannelProvider(string internalChannelId) + { + if (internalChannelId == null) + { + throw new ArgumentNullException("internalChannelId"); + } + + var result = GetAllChannels() + .FirstOrDefault(i => string.Equals(GetInternalChannelId(i.Name).ToString("N"), internalChannelId, StringComparison.OrdinalIgnoreCase)); + + if (result == null) + { + throw new ResourceNotFoundException("No channel provider found for channel id " + internalChannelId); + } + + return result; + } + private IEnumerable ApplyFilters(IEnumerable items, IEnumerable filters, User user) { foreach (var filter in filters.OrderByDescending(f => (int)f)) diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 7758d690a..442e2ebe5 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -401,7 +401,7 @@ namespace MediaBrowser.Server.Implementations.Library var locationType = item.LocationType; var children = item.IsFolder - ? ((Folder)item).GetRecursiveChildren().ToList() + ? ((Folder)item).GetRecursiveChildren(false).ToList() : new List(); foreach (var metadataPath in GetMetadataPaths(item, children)) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 5e7e3a94f..75ad3de59 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -46,9 +46,24 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV _httpClient = httpClient; } + private string OutputFormat + { + get + { + var format = _liveTvOptions.RecordingEncodingFormat; + + if (string.Equals(format, "mkv", StringComparison.OrdinalIgnoreCase)) + { + return "mkv"; + } + + return "mp4"; + } + } + public string GetOutputPath(MediaSourceInfo mediaSource, string targetFile) { - return Path.ChangeExtension(targetFile, ".mp4"); + return Path.ChangeExtension(targetFile, "." + OutputFormat); } public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) @@ -233,15 +248,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private string GetAudioArgs(MediaSourceInfo mediaSource) { - // do not copy aac because many players have difficulty with aac_latm - var copyAudio = new[] { "mp3" }; var mediaStreams = mediaSource.MediaStreams ?? new List(); var inputAudioCodec = mediaStreams.Where(i => i.Type == MediaStreamType.Audio).Select(i => i.Codec).FirstOrDefault() ?? string.Empty; - if (copyAudio.Contains(inputAudioCodec, StringComparer.OrdinalIgnoreCase)) - { - return "-codec:a:0 copy"; - } + // do not copy aac because many players have difficulty with aac_latm if (_liveTvOptions.EnableOriginalAudioWithEncodedRecordings && !string.Equals(inputAudioCodec, "aac", StringComparison.OrdinalIgnoreCase)) { return "-codec:a:0 copy"; diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index e37109c14..206e90e40 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -785,9 +785,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings get { return "Schedules Direct"; } } + public static string TypeName = "SchedulesDirect"; public string Type { - get { return "SchedulesDirect"; } + get { return TypeName; } } private async Task HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken) diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index e76f95ab4..a135a188e 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -35,6 +35,7 @@ using MediaBrowser.Common.Security; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Model.Events; +using MediaBrowser.Server.Implementations.LiveTv.Listings; namespace MediaBrowser.Server.Implementations.LiveTv { @@ -1436,7 +1437,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { if (query.IsMovie.Value) { - includeItemTypes.Add(typeof (Movie).Name); + includeItemTypes.Add(typeof(Movie).Name); } else { @@ -2802,6 +2803,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv feature = "embytvseriesrecordings"; } + var config = GetConfiguration(); + if (config.TunerHosts.Count(i => i.IsEnabled) > 0 && + config.ListingProviders.Count(i => (i.EnableAllTuners || i.EnabledTuners.Length > 0) && string.Equals(i.Type, SchedulesDirect.TypeName, StringComparison.OrdinalIgnoreCase)) > 0) + { + return Task.FromResult(new MBRegistrationRecord + { + IsRegistered = true, + IsValid = true + }); + } + return _security.GetRegistrationStatus(feature); } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index ffba60af8..1278a40a4 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -541,6 +541,11 @@ namespace MediaBrowser.Server.Implementations.Sync return true; } + if (item.SourceType == SourceType.Channel) + { + return BaseItem.ChannelManager.SupportsSync(item.ChannelId); + } + return item.LocationType == LocationType.FileSystem || item is Season; } diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 2417c5b11..07659fdfc 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -363,7 +363,10 @@ namespace MediaBrowser.Server.Startup.Common private void PerformPreInitMigrations() { - var migrations = new List(); + var migrations = new List + { + new UpdateLevelMigration(ServerConfigurationManager, this, HttpClient, JsonSerializer, _releaseAssetFilename) + }; foreach (var task in migrations) { @@ -383,8 +386,7 @@ namespace MediaBrowser.Server.Startup.Common var migrations = new List { new MovieDbEpisodeProviderMigration(ServerConfigurationManager), - new DbMigration(ServerConfigurationManager, TaskManager), - new UpdateLevelMigration(ServerConfigurationManager, this, HttpClient, JsonSerializer, _releaseAssetFilename) + new DbMigration(ServerConfigurationManager, TaskManager) }; foreach (var task in migrations) diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index 8fb0e8f46..cdacdc81f 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -331,7 +331,7 @@ namespace MediaBrowser.ServerApplication Application.Run(); } - private static SplashForm _splash; + internal static SplashForm _splash; private static Thread _splashThread; private static void ShowSplashScreen(Version appVersion, Progress progress, ILogger logger) { diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index 3cd6c95d2..200e2d3ae 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -212,7 +212,12 @@ namespace MediaBrowser.ServerApplication.Native private bool Confirm() { - return MessageBox.Show("Emby has detected that Windows Firewall has been configured in a way that may prevent your other devices from accessing Emby Server. Click OK to remove this rule, or cancel to proceed anyway.", "Windows Firewall", MessageBoxButtons.OKCancel) == DialogResult.OK; + if (MainStartup._splash == null) + { + return false; + } + + return MessageBox.Show(MainStartup._splash, "Emby has detected that Windows Firewall has been configured in a way that may prevent your other devices from accessing Emby Server. Click OK to remove this rule, or cancel to proceed anyway.", "Windows Firewall", MessageBoxButtons.OKCancel) == DialogResult.OK; } public bool PortsRequireAuthorization(string applicationPath) @@ -242,7 +247,7 @@ namespace MediaBrowser.ServerApplication.Native if (data.IndexOf("Block", StringComparison.OrdinalIgnoreCase) != -1) { - _logger.Info("Found windows firewall rule: " + data); + _logger.Info("Found potential windows firewall rule blocking Emby Server: " + data); return Confirm(); }