Browse Source

Merge pull request #1830 from MediaBrowser/dev

Dev
Luke 9 năm trước cách đây
mục cha
commit
b6b5a0e6dc

+ 19 - 35
MediaBrowser.Controller/Entities/TV/Series.cs

@@ -402,47 +402,31 @@ namespace MediaBrowser.Controller.Entities.TV
         public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, Season parentSeason, bool includeSpecials)
         {
             var seasonNumber = parentSeason.IndexNumber;
-            if (!includeSpecials || (seasonNumber.HasValue && seasonNumber.Value == 0))
-            {
-                var seasonPresentationKey = parentSeason.PresentationUniqueKey;
+            var seasonPresentationKey = parentSeason.PresentationUniqueKey;
 
-                return episodes.Where(i =>
-                {
-                    if ((i.ParentIndexNumber ?? -1) == seasonNumber)
-                    {
-                        return true;
-                    }
-                    if (!i.ParentIndexNumber.HasValue)
-                    {
-                        var season = i.Season;
-                        return season != null && string.Equals(season.PresentationUniqueKey, seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
-                    }
-
-                    return false;
-                });
-            }
-            else
-            {
-                var seasonPresentationKey = parentSeason.PresentationUniqueKey;
+            var supportSpecialsInSeason = includeSpecials && seasonNumber.HasValue && seasonNumber.Value != 0;
 
-                return episodes.Where(episode =>
+            return episodes.Where(episode =>
+            {
+                var currentSeasonNumber = supportSpecialsInSeason ? episode.AiredSeasonNumber : episode.ParentIndexNumber;
+                if (currentSeasonNumber.HasValue && seasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber.Value)
                 {
-                    var currentSeasonNumber = episode.AiredSeasonNumber;
+                    return true;
+                }
 
-                    if (currentSeasonNumber.HasValue && seasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber.Value)
-                    {
-                        return true;
-                    }
+                if (!currentSeasonNumber.HasValue && !seasonNumber.HasValue && parentSeason.LocationType == LocationType.Virtual)
+                {
+                    return true;
+                }
 
-                    if (!episode.ParentIndexNumber.HasValue)
-                    {
-                        var season = episode.Season;
-                        return season != null && string.Equals(season.PresentationUniqueKey, seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
-                    }
+                if (!episode.ParentIndexNumber.HasValue)
+                {
+                    var season = episode.Season;
+                    return season != null && string.Equals(season.PresentationUniqueKey, seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
+                }
 
-                    return false;
-                });
-            }
+                return false;
+            });
         }
 
         protected override bool GetBlockUnratedValue(UserPolicy config)

+ 1 - 0
MediaBrowser.Controller/LiveTv/IListingsProvider.cs

@@ -15,5 +15,6 @@ namespace MediaBrowser.Controller.LiveTv
         Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken);
         Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings);
         Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location);
+        Task<List<ChannelInfo>> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken);
     }
 }

+ 8 - 0
MediaBrowser.Controller/LiveTv/ILiveTvManager.cs

@@ -8,6 +8,7 @@ using MediaBrowser.Model.Querying;
 using System.Collections.Generic;
 using System.Threading;
 using System.Threading.Tasks;
+using MediaBrowser.Model.Events;
 
 namespace MediaBrowser.Controller.LiveTv
 {
@@ -385,5 +386,12 @@ namespace MediaBrowser.Controller.LiveTv
         List<NameValuePair> GetSatIniMappings();
 
         Task<List<ChannelInfo>> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken);
+
+        Task<List<ChannelInfo>> GetChannelsFromListingsProvider(string id, CancellationToken cancellationToken);
+
+        event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled;
+        event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled;
+        event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCreated;
+        event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCreated;
     }
 }

+ 14 - 0
MediaBrowser.Controller/LiveTv/TimerEventInfo.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.LiveTv
+{
+    public class TimerEventInfo
+    {
+        public string Id { get; set; }
+        public string ProgramId { get; set; }
+    }
+}

+ 1 - 0
MediaBrowser.Controller/MediaBrowser.Controller.csproj

@@ -218,6 +218,7 @@
     <Compile Include="LiveTv\ProgramInfo.cs" />
     <Compile Include="LiveTv\RecordingInfo.cs" />
     <Compile Include="LiveTv\SeriesTimerInfo.cs" />
+    <Compile Include="LiveTv\TimerEventInfo.cs" />
     <Compile Include="LiveTv\TimerInfo.cs" />
     <Compile Include="Localization\ILocalizationManager.cs" />
     <Compile Include="MediaEncoding\ChapterImageRefreshOptions.cs" />

+ 13 - 0
MediaBrowser.Model/LiveTv/LiveTvOptions.cs

@@ -1,5 +1,6 @@
 using System.Collections.Generic;
 using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Extensions;
 
 namespace MediaBrowser.Model.LiveTv
 {
@@ -90,5 +91,17 @@ namespace MediaBrowser.Model.LiveTv
             EnableAllTuners = true;
             ChannelMappings = new NameValuePair[] {};
         }
+
+        public string GetMappedChannel(string channelNumber)
+        {
+            foreach (NameValuePair mapping in ChannelMappings)
+            {
+                if (StringHelper.EqualsIgnoreCase(mapping.Name, channelNumber))
+                {
+                    return mapping.Value;
+                }
+            }
+            return channelNumber;
+        }
     }
 }

+ 83 - 0
MediaBrowser.Server.Implementations/EntryPoints/RecordingNotifier.cs

@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.Plugins;
+using MediaBrowser.Controller.Session;
+using MediaBrowser.Model.Logging;
+
+namespace MediaBrowser.Server.Implementations.EntryPoints
+{
+    public class RecordingNotifier : IServerEntryPoint
+    {
+        private readonly ILiveTvManager _liveTvManager;
+        private readonly ISessionManager _sessionManager;
+        private readonly IUserManager _userManager;
+        private readonly ILogger _logger;
+
+        public RecordingNotifier(ISessionManager sessionManager, IUserManager userManager, ILogger logger, ILiveTvManager liveTvManager)
+        {
+            _sessionManager = sessionManager;
+            _userManager = userManager;
+            _logger = logger;
+            _liveTvManager = liveTvManager;
+        }
+
+        public void Run()
+        {
+            _liveTvManager.TimerCancelled += _liveTvManager_TimerCancelled;
+            _liveTvManager.SeriesTimerCancelled += _liveTvManager_SeriesTimerCancelled;
+            _liveTvManager.TimerCreated += _liveTvManager_TimerCreated;
+            _liveTvManager.SeriesTimerCreated += _liveTvManager_SeriesTimerCreated;
+        }
+
+        private void _liveTvManager_SeriesTimerCreated(object sender, Model.Events.GenericEventArgs<TimerEventInfo> e)
+        {
+            SendMessage("SeriesTimerCreated", e.Argument);
+        }
+
+        private void _liveTvManager_TimerCreated(object sender, Model.Events.GenericEventArgs<TimerEventInfo> e)
+        {
+            SendMessage("TimerCreated", e.Argument);
+        }
+
+        private void _liveTvManager_SeriesTimerCancelled(object sender, Model.Events.GenericEventArgs<TimerEventInfo> e)
+        {
+            SendMessage("SeriesTimerCancelled", e.Argument);
+        }
+
+        private void _liveTvManager_TimerCancelled(object sender, Model.Events.GenericEventArgs<TimerEventInfo> e)
+        {
+            SendMessage("TimerCancelled", e.Argument);
+        }
+
+        private async void SendMessage(string name, TimerEventInfo info)
+        {
+            var users = _userManager.Users.Where(i => i.Policy.EnableLiveTvAccess).ToList();
+
+            foreach (var user in users)
+            {
+                try
+                {
+                    await _sessionManager.SendMessageToUserSessions<TimerEventInfo>(user.Id.ToString("N"), name, info, CancellationToken.None);
+                }
+                catch (Exception ex)
+                {
+                    _logger.ErrorException("Error sending message", ex);
+                }
+            }
+        }
+
+        public void Dispose()
+        {
+            _liveTvManager.TimerCancelled -= _liveTvManager_TimerCancelled;
+            _liveTvManager.SeriesTimerCancelled -= _liveTvManager_SeriesTimerCancelled;
+            _liveTvManager.TimerCreated -= _liveTvManager_TimerCreated;
+            _liveTvManager.SeriesTimerCreated -= _liveTvManager_SeriesTimerCreated;
+        }
+    }
+}

+ 1 - 1
MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs

@@ -1000,7 +1000,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
                         result.Item3.Release();
                     }
 
-                    _libraryMonitor.ReportFileSystemChangeComplete(recordPath, false);
+                    _libraryMonitor.ReportFileSystemChangeComplete(recordPath, true);
                 }
             }
             catch (OperationCanceledException)

+ 5 - 0
MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs

@@ -869,6 +869,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
             return GetHeadends(info, country, location, CancellationToken.None);
         }
 
+        public async Task<List<ChannelInfo>> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken)
+        {
+            return new List<ChannelInfo>();
+        }
+
         public class ScheduleDirect
         {
             public class Token

+ 9 - 2
MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs

@@ -107,11 +107,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
             var reader = new XmlTvReader(info.Path, GetLanguage(), null);
             var results = reader.GetChannels().ToList();
 
-            if (channels != null && channels.Count > 0)
+            if (channels != null)
             {
                 channels.ForEach(c =>
                 {
-                    var match = results.FirstOrDefault(r => r.Id == c.Id);
+                    var channelNumber = info.GetMappedChannel(c.Number);
+                    var match = results.FirstOrDefault(r => string.Equals(r.Id, channelNumber, StringComparison.OrdinalIgnoreCase));
+
                     if (match != null && match.Icon != null && !String.IsNullOrEmpty(match.Icon.Source))
                     {
                         c.ImageUrl = match.Icon.Source;
@@ -142,5 +144,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
             // Should this method be async?
             return Task.FromResult(results.Select(c => new NameIdPair() { Id = c.Id, Name = c.DisplayName }).ToList());
         }
+
+        public async Task<List<ChannelInfo>> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken)
+        {
+            return new List<ChannelInfo>();
+        }
     }
 }

+ 46 - 0
MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs

@@ -30,6 +30,8 @@ using System.Threading.Tasks;
 using CommonIO;
 using IniParser;
 using IniParser.Model;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Model.Events;
 
 namespace MediaBrowser.Server.Implementations.LiveTv
 {
@@ -64,6 +66,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
         private readonly List<IListingsProvider> _listingProviders = new List<IListingsProvider>();
         private readonly IFileSystem _fileSystem;
 
+        public event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled;
+        public event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled;
+        public event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCreated;
+        public event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCreated;
+
         public LiveTvManager(IApplicationHost appHost, IServerConfigurationManager config, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, ILocalizationManager localization, IJsonSerializer jsonSerializer, IProviderManager providerManager, IFileSystem fileSystem)
         {
             _config = config;
@@ -1759,6 +1766,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv
 
             await service.CancelTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false);
             _lastRecordingRefreshTime = DateTime.MinValue;
+
+            EventHelper.QueueEventIfNotNull(TimerCancelled, this, new GenericEventArgs<TimerEventInfo>
+            {
+                Argument = new TimerEventInfo
+                {
+                    Id = id
+                }
+            }, _logger);
         }
 
         public async Task CancelSeriesTimer(string id)
@@ -1774,6 +1789,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv
 
             await service.CancelSeriesTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false);
             _lastRecordingRefreshTime = DateTime.MinValue;
+
+            EventHelper.QueueEventIfNotNull(SeriesTimerCancelled, this, new GenericEventArgs<TimerEventInfo>
+            {
+                Argument = new TimerEventInfo
+                {
+                    Id = id
+                }
+            }, _logger);
         }
 
         public async Task<BaseItemDto> GetRecording(string id, DtoOptions options, CancellationToken cancellationToken, User user = null)
@@ -1993,6 +2016,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             await service.CreateTimerAsync(info, cancellationToken).ConfigureAwait(false);
             _lastRecordingRefreshTime = DateTime.MinValue;
             _logger.Info("New recording scheduled");
+
+            EventHelper.QueueEventIfNotNull(TimerCreated, this, new GenericEventArgs<TimerEventInfo>
+            {
+                Argument = new TimerEventInfo
+                {
+                    ProgramId = info.ProgramId
+                }
+            }, _logger);
         }
 
         public async Task CreateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken)
@@ -2007,6 +2038,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv
 
             await service.CreateSeriesTimerAsync(info, cancellationToken).ConfigureAwait(false);
             _lastRecordingRefreshTime = DateTime.MinValue;
+
+            EventHelper.QueueEventIfNotNull(SeriesTimerCreated, this, new GenericEventArgs<TimerEventInfo>
+            {
+                Argument = new TimerEventInfo
+                {
+                    ProgramId = info.ProgramId
+                }
+            }, _logger);
         }
 
         public async Task UpdateTimer(TimerInfoDto timer, CancellationToken cancellationToken)
@@ -2521,5 +2560,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
         {
             return new TunerHosts.SatIp.ChannelScan(_logger).Scan(info, cancellationToken);
         }
+
+        public Task<List<ChannelInfo>> GetChannelsFromListingsProvider(string id, CancellationToken cancellationToken)
+        {
+            var info = GetConfiguration().ListingProviders.First(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase));
+            var provider = _listingProviders.First(i => string.Equals(i.Type, info.Type, StringComparison.OrdinalIgnoreCase));
+            return provider.GetChannels(info, cancellationToken);
+        }
     }
 }

+ 1 - 0
MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj

@@ -142,6 +142,7 @@
     <Compile Include="EntryPoints\LoadRegistrations.cs" />
     <Compile Include="EntryPoints\Notifications\Notifications.cs" />
     <Compile Include="EntryPoints\Notifications\WebSocketNotifier.cs" />
+    <Compile Include="EntryPoints\RecordingNotifier.cs" />
     <Compile Include="EntryPoints\RefreshUsersMetadata.cs" />
     <Compile Include="EntryPoints\UsageEntryPoint.cs" />
     <Compile Include="Connect\ConnectEntryPoint.cs" />

+ 2 - 1
MediaBrowser.Server.Startup.Common/ApplicationHost.cs

@@ -381,7 +381,8 @@ namespace MediaBrowser.Server.Startup.Common
                 new OmdbEpisodeProviderMigration(ServerConfigurationManager),
                 new MovieDbEpisodeProviderMigration(ServerConfigurationManager),
                 new DbMigration(ServerConfigurationManager, TaskManager),
-                new FolderViewSettingMigration(ServerConfigurationManager, UserManager)
+                new FolderViewSettingMigration(ServerConfigurationManager, UserManager),
+                new CollectionGroupingMigration(ServerConfigurationManager, UserManager)
             };
 
             foreach (var task in migrations)