Parcourir la source

Merge pull request #1832 from MediaBrowser/dev

Dev
Luke il y a 9 ans
Parent
commit
0dd43ed529

+ 85 - 1
MediaBrowser.Api/LiveTv/LiveTvService.cs

@@ -484,6 +484,30 @@ namespace MediaBrowser.Api.LiveTv
     {
     }
 
+    [Route("/LiveTv/ChannelMappingOptions")]
+    [Authenticated(AllowBeforeStartupWizard = true)]
+    public class GetChannelMappingOptions
+    {
+        [ApiMember(Name = "Id", Description = "Provider id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
+        public string ProviderId { get; set; }
+    }
+
+    public class ChannelMappingOptions
+    {
+        public List<TunerChannelMapping> TunerChannels { get; set; }
+        public List<NameIdPair> ProviderChannels { get; set; }
+        public List<NameValuePair> Mappings { get; set; }
+        public string ProviderName { get; set; }
+    }
+
+    public class TunerChannelMapping
+    {
+        public string Name { get; set; }
+        public string Number { get; set; }
+        public string ProviderChannelNumber { get; set; }
+        public string ProviderChannelName { get; set; }
+    }
+
     [Route("/LiveTv/Registration", "GET")]
     [Authenticated]
     public class GetLiveTvRegistrationInfo : IReturn<MBRegistrationRecord>
@@ -550,6 +574,66 @@ namespace MediaBrowser.Api.LiveTv
             return ToOptimizedResult(result);
         }
 
+        public async Task<object> Get(GetChannelMappingOptions request)
+        {
+            var config = GetConfiguration();
+
+            var listingProvider = config.ListingProviders.First(i => string.Equals(request.ProviderId, i.Id, StringComparison.OrdinalIgnoreCase));
+
+            var tunerChannels = await _liveTvManager.GetChannelsForListingsProvider(request.ProviderId, CancellationToken.None)
+                        .ConfigureAwait(false);
+
+            var providerChannels = await _liveTvManager.GetChannelsFromListingsProviderData(request.ProviderId, CancellationToken.None)
+                     .ConfigureAwait(false);
+
+            var mappings = listingProvider.ChannelMappings.ToList();
+
+            var result = new ChannelMappingOptions
+            {
+                TunerChannels = tunerChannels.Select(i => GetTunerChannelMapping(i, mappings, providerChannels)).ToList(),
+
+                ProviderChannels = providerChannels.Select(i => new NameIdPair
+                {
+                    Name = i.Name,
+                    Id = i.Number
+
+                }).ToList(),
+
+                Mappings = mappings,
+
+                ProviderName = "Schedules Direct"
+            };
+
+            return ToOptimizedResult(result);
+        }
+
+        private TunerChannelMapping GetTunerChannelMapping(ChannelInfo channel, List<NameValuePair> mappings, List<ChannelInfo> providerChannels)
+        {
+            var result = new TunerChannelMapping
+            {
+                Name = channel.Number + " " + channel.Name,
+                Number = channel.Number
+            };
+
+            var mapping = mappings.FirstOrDefault(i => string.Equals(i.Name, channel.Number, StringComparison.OrdinalIgnoreCase));
+            var providerChannelNumber = channel.Number;
+
+            if (mapping != null)
+            {
+                providerChannelNumber = mapping.Value;
+            }
+
+            var providerChannel = providerChannels.FirstOrDefault(i => string.Equals(i.Number, providerChannelNumber, StringComparison.OrdinalIgnoreCase));
+
+            if (providerChannel != null)
+            {
+                result.ProviderChannelNumber = providerChannel.Number;
+                result.ProviderChannelName = providerChannel.Name;
+            }
+
+            return result;
+        }
+
         public object Get(GetSatIniMappings request)
         {
             return ToOptimizedResult(_liveTvManager.GetSatIniMappings());
@@ -657,7 +741,7 @@ namespace MediaBrowser.Api.LiveTv
                 Items = returnArray,
                 TotalRecordCount = channelResult.TotalRecordCount
             };
-            
+
             return ToOptimizedSerializedResultUsingCache(result);
         }
 

+ 6 - 0
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -1236,6 +1236,12 @@ namespace MediaBrowser.Api.Playback
             {
                 var inputVideoCodec = videoStream == null ? null : videoStream.Codec;
                 bitrate = ResolutionNormalizer.ScaleBitrate(bitrate.Value, inputVideoCodec, outputVideoCodec);
+
+                // If a max bitrate was requested, don't let the scaled bitrate exceed it
+                if (request.VideoBitRate.HasValue)
+                {
+                    bitrate = Math.Min(bitrate.Value, request.VideoBitRate.Value);
+                }
             }
 
             return bitrate;

+ 2 - 1
MediaBrowser.Controller/LiveTv/ILiveTvManager.cs

@@ -387,7 +387,8 @@ namespace MediaBrowser.Controller.LiveTv
 
         Task<List<ChannelInfo>> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken);
 
-        Task<List<ChannelInfo>> GetChannelsFromListingsProvider(string id, CancellationToken cancellationToken);
+        Task<List<ChannelInfo>> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken);
+        Task<List<ChannelInfo>> GetChannelsFromListingsProviderData(string id, CancellationToken cancellationToken);
 
         event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled;
         event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled;

+ 19 - 0
MediaBrowser.Controller/LiveTv/ILiveTvService.cs

@@ -226,4 +226,23 @@ namespace MediaBrowser.Controller.LiveTv
         /// <returns>Task.</returns>
         Task ResetTuner(string id, CancellationToken cancellationToken);
     }
+
+    public interface ISupportsNewTimerIds
+    {
+        /// <summary>
+        /// Creates the timer asynchronous.
+        /// </summary>
+        /// <param name="info">The information.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task.</returns>
+        Task<string> CreateTimer(TimerInfo info, CancellationToken cancellationToken);
+
+        /// <summary>
+        /// Creates the series timer asynchronous.
+        /// </summary>
+        /// <param name="info">The information.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task.</returns>
+        Task<string> CreateSeriesTimer(SeriesTimerInfo info, CancellationToken cancellationToken);
+    }
 }

+ 9 - 9
MediaBrowser.Dlna/Didl/DidlBuilder.cs

@@ -1015,17 +1015,17 @@ namespace MediaBrowser.Dlna.Didl
             int? width = null;
             int? height = null;
 
-            //try
-            //{
-            //    var size = _imageProcessor.GetImageSize(imageInfo);
+            try
+            {
+                var size = _imageProcessor.GetImageSize(imageInfo);
 
-            //    width = Convert.ToInt32(size.Width);
-            //    height = Convert.ToInt32(size.Height);
-            //}
-            //catch
-            //{
+                width = Convert.ToInt32(size.Width);
+                height = Convert.ToInt32(size.Height);
+            }
+            catch
+            {
 
-            //}
+            }
 
             var inputFormat = (Path.GetExtension(imageInfo.Path) ?? string.Empty)
                 .TrimStart('.')

+ 6 - 0
MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs

@@ -425,6 +425,12 @@ namespace MediaBrowser.MediaEncoding.Encoder
             {
                 var inputVideoCodec = videoStream == null ? null : videoStream.Codec;
                 bitrate = ResolutionNormalizer.ScaleBitrate(bitrate.Value, inputVideoCodec, outputVideoCodec);
+
+                // If a max bitrate was requested, don't let the scaled bitrate exceed it
+                if (request.VideoBitRate.HasValue)
+                {
+                    bitrate = Math.Min(bitrate.Value, request.VideoBitRate.Value);
+                }
             }
 
             return bitrate;

+ 38 - 3
MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs

@@ -35,7 +35,7 @@ using Microsoft.Win32;
 
 namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
 {
-    public class EmbyTV : ILiveTvService, IHasRegistrationInfo, IDisposable
+    public class EmbyTV : ILiveTvService, ISupportsNewTimerIds, IHasRegistrationInfo, IDisposable
     {
         private readonly IApplicationHost _appHpst;
         private readonly ILogger _logger;
@@ -382,6 +382,29 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
             return list;
         }
 
+        public async Task<List<ChannelInfo>> GetChannelsForListingsProvider(ListingsProviderInfo listingsProvider, CancellationToken cancellationToken)
+        {
+            var list = new List<ChannelInfo>();
+
+            foreach (var hostInstance in _liveTvManager.TunerHosts)
+            {
+                try
+                {
+                    var channels = await hostInstance.GetChannels(cancellationToken).ConfigureAwait(false);
+
+                    list.AddRange(channels);
+                }
+                catch (Exception ex)
+                {
+                    _logger.ErrorException("Error getting channels", ex);
+                }
+            }
+
+            return list
+                .Where(i => IsListingProviderEnabledForTuner(listingsProvider, i.TunerHostId))
+                .ToList();
+        }
+
         public Task<IEnumerable<ChannelInfo>> GetChannelsAsync(CancellationToken cancellationToken)
         {
             return GetChannelsAsync(false, cancellationToken);
@@ -434,13 +457,23 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
         }
 
         public Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken)
+        {
+            return CreateTimer(info, cancellationToken);
+        }
+
+        public  Task CreateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken)
+        {
+            return CreateSeriesTimer(info, cancellationToken);
+        }
+
+        public Task<string> CreateTimer(TimerInfo info, CancellationToken cancellationToken)
         {
             info.Id = Guid.NewGuid().ToString("N");
             _timerProvider.Add(info);
-            return Task.FromResult(0);
+            return Task.FromResult(info.Id);
         }
 
-        public async Task CreateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken)
+        public async Task<string> CreateSeriesTimer(SeriesTimerInfo info, CancellationToken cancellationToken)
         {
             info.Id = Guid.NewGuid().ToString("N");
 
@@ -470,6 +503,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
 
             _seriesTimerProvider.Add(info);
             await UpdateTimersForSeriesTimer(epgData, info, false).ConfigureAwait(false);
+
+            return info.Id;
         }
 
         public async Task UpdateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken)

+ 106 - 48
MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs

@@ -506,8 +506,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
         }
 
         private async Task<List<ScheduleDirect.ShowImages>> GetImageForPrograms(
-			ListingsProviderInfo info,
-			List<string> programIds,
+            ListingsProviderInfo info,
+            List<string> programIds,
            CancellationToken cancellationToken)
         {
             var imageIdString = "[";
@@ -564,7 +564,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
 
             try
             {
-				using (Stream responce = await Get(options, false, info).ConfigureAwait(false))
+                using (Stream responce = await Get(options, false, info).ConfigureAwait(false))
                 {
                     var root = _jsonSerializer.DeserializeFromStream<List<ScheduleDirect.Headends>>(responce);
 
@@ -666,58 +666,60 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
             }
         }
 
-		private async Task<HttpResponseInfo> Post(HttpRequestOptions options, 
-			bool enableRetry,
-			ListingsProviderInfo providerInfo)
+        private async Task<HttpResponseInfo> Post(HttpRequestOptions options,
+            bool enableRetry,
+            ListingsProviderInfo providerInfo)
         {
             try
             {
                 return await _httpClient.Post(options).ConfigureAwait(false);
-			}
-			catch (HttpException ex)
-			{
-				_tokens.Clear();
-
-				if (!ex.StatusCode.HasValue || (int)ex.StatusCode.Value >= 500) 
-				{
-					enableRetry = false;
-				}
-
-				if (!enableRetry) {
-					throw;
-				}
-			}
-
-			var newToken = await GetToken (providerInfo, options.CancellationToken).ConfigureAwait (false);
-			options.RequestHeaders ["token"] = newToken;
-			return await Post (options, false, providerInfo).ConfigureAwait (false);
+            }
+            catch (HttpException ex)
+            {
+                _tokens.Clear();
+
+                if (!ex.StatusCode.HasValue || (int)ex.StatusCode.Value >= 500)
+                {
+                    enableRetry = false;
+                }
+
+                if (!enableRetry)
+                {
+                    throw;
+                }
+            }
+
+            var newToken = await GetToken(providerInfo, options.CancellationToken).ConfigureAwait(false);
+            options.RequestHeaders["token"] = newToken;
+            return await Post(options, false, providerInfo).ConfigureAwait(false);
         }
 
-		private async Task<Stream> Get(HttpRequestOptions options, 
-			bool enableRetry,
-			ListingsProviderInfo providerInfo)
+        private async Task<Stream> Get(HttpRequestOptions options,
+            bool enableRetry,
+            ListingsProviderInfo providerInfo)
         {
             try
             {
                 return await _httpClient.Get(options).ConfigureAwait(false);
-			}
-			catch (HttpException ex)
-			{
-				_tokens.Clear();
-
-				if (!ex.StatusCode.HasValue || (int)ex.StatusCode.Value >= 500) 
-				{
-					enableRetry = false;
-				}
-
-				if (!enableRetry) {
-					throw;
-				}
-			}
-
-			var newToken = await GetToken (providerInfo, options.CancellationToken).ConfigureAwait (false);
-			options.RequestHeaders ["token"] = newToken;
-			return await Get (options, false, providerInfo).ConfigureAwait (false);
+            }
+            catch (HttpException ex)
+            {
+                _tokens.Clear();
+
+                if (!ex.StatusCode.HasValue || (int)ex.StatusCode.Value >= 500)
+                {
+                    enableRetry = false;
+                }
+
+                if (!enableRetry)
+                {
+                    throw;
+                }
+            }
+
+            var newToken = await GetToken(providerInfo, options.CancellationToken).ConfigureAwait(false);
+            options.RequestHeaders["token"] = newToken;
+            return await Get(options, false, providerInfo).ConfigureAwait(false);
         }
 
         private async Task<string> GetTokenInternal(string username, string password,
@@ -734,7 +736,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
             //_logger.Info("Obtaining token from Schedules Direct from addres: " + httpOptions.Url + " with body " +
             // httpOptions.RequestContent);
 
-			using (var responce = await Post(httpOptions, false, null).ConfigureAwait(false))
+            using (var responce = await Post(httpOptions, false, null).ConfigureAwait(false))
             {
                 var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Token>(responce.Content);
                 if (root.message == "OK")
@@ -816,7 +818,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
 
             try
             {
-				using (var response = await Get(options, false, null).ConfigureAwait(false))
+                using (var response = await Get(options, false, null).ConfigureAwait(false))
                 {
                     var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Lineups>(response);
 
@@ -871,7 +873,63 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
 
         public async Task<List<ChannelInfo>> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken)
         {
-            return new List<ChannelInfo>();
+            var listingsId = info.ListingsId;
+            if (string.IsNullOrWhiteSpace(listingsId))
+            {
+                throw new Exception("ListingsId required");
+            }
+
+            var token = await GetToken(info, cancellationToken);
+
+            if (string.IsNullOrWhiteSpace(token))
+            {
+                throw new Exception("token required");
+            }
+
+            ClearPairCache(listingsId);
+
+            var httpOptions = new HttpRequestOptions()
+            {
+                Url = ApiUrl + "/lineups/" + listingsId,
+                UserAgent = UserAgent,
+                CancellationToken = cancellationToken,
+                LogErrorResponseBody = true,
+                // The data can be large so give it some extra time
+                TimeoutMs = 60000
+            };
+
+            httpOptions.RequestHeaders["token"] = token;
+
+            var list = new List<ChannelInfo>();
+
+            using (var response = await Get(httpOptions, true, info).ConfigureAwait(false))
+            {
+                var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Channel>(response);
+                _logger.Info("Found " + root.map.Count + " channels on the lineup on ScheduleDirect");
+                _logger.Info("Mapping Stations to Channel");
+                foreach (ScheduleDirect.Map map in root.map)
+                {
+                    var channelNumber = map.logicalChannelNumber;
+
+                    if (string.IsNullOrWhiteSpace(channelNumber))
+                    {
+                        channelNumber = map.channel;
+                    }
+                    if (string.IsNullOrWhiteSpace(channelNumber))
+                    {
+                        channelNumber = map.atscMajor + "." + map.atscMinor;
+                    }
+                    channelNumber = channelNumber.TrimStart('0');
+
+                    list.Add(new ChannelInfo
+                    {
+                        Number = channelNumber,
+                        Name = map.channel
+                    });
+                }
+            }
+
+            return list;
         }
 
         public class ScheduleDirect

+ 35 - 5
MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs

@@ -2013,7 +2013,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             var defaultValues = await service.GetNewTimerDefaultsAsync(cancellationToken).ConfigureAwait(false);
             info.Priority = defaultValues.Priority;
 
-            await service.CreateTimerAsync(info, cancellationToken).ConfigureAwait(false);
+            string newTimerId = null;
+            var supportsNewTimerIds = service as ISupportsNewTimerIds;
+            if (supportsNewTimerIds != null)
+            {
+                newTimerId = await supportsNewTimerIds.CreateTimer(info, cancellationToken).ConfigureAwait(false);
+                newTimerId = _tvDtoService.GetInternalTimerId(timer.ServiceName, newTimerId).ToString("N");
+            }
+            else
+            {
+                await service.CreateTimerAsync(info, cancellationToken).ConfigureAwait(false);
+            }
+
             _lastRecordingRefreshTime = DateTime.MinValue;
             _logger.Info("New recording scheduled");
 
@@ -2021,7 +2032,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             {
                 Argument = new TimerEventInfo
                 {
-                    ProgramId = info.ProgramId
+                    ProgramId = _tvDtoService.GetInternalProgramId(timer.ServiceName, info.ProgramId).ToString("N"),
+                    Id = newTimerId
                 }
             }, _logger);
         }
@@ -2036,14 +2048,26 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             var defaultValues = await service.GetNewTimerDefaultsAsync(cancellationToken).ConfigureAwait(false);
             info.Priority = defaultValues.Priority;
 
-            await service.CreateSeriesTimerAsync(info, cancellationToken).ConfigureAwait(false);
+            string newTimerId = null;
+            var supportsNewTimerIds = service as ISupportsNewTimerIds;
+            if (supportsNewTimerIds != null)
+            {
+                newTimerId = await supportsNewTimerIds.CreateSeriesTimer(info, cancellationToken).ConfigureAwait(false);
+                newTimerId = _tvDtoService.GetInternalSeriesTimerId(timer.ServiceName, newTimerId).ToString("N");
+            }
+            else
+            {
+                await service.CreateSeriesTimerAsync(info, cancellationToken).ConfigureAwait(false);
+            }
+
             _lastRecordingRefreshTime = DateTime.MinValue;
 
             EventHelper.QueueEventIfNotNull(SeriesTimerCreated, this, new GenericEventArgs<TimerEventInfo>
             {
                 Argument = new TimerEventInfo
                 {
-                    ProgramId = info.ProgramId
+                    ProgramId = _tvDtoService.GetInternalProgramId(timer.ServiceName, info.ProgramId).ToString("N"),
+                    Id = newTimerId
                 }
             }, _logger);
         }
@@ -2561,7 +2585,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             return new TunerHosts.SatIp.ChannelScan(_logger).Scan(info, cancellationToken);
         }
 
-        public Task<List<ChannelInfo>> GetChannelsFromListingsProvider(string id, CancellationToken cancellationToken)
+        public Task<List<ChannelInfo>> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken)
+        {
+            var info = GetConfiguration().ListingProviders.First(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase));
+            return EmbyTV.EmbyTV.Current.GetChannelsForListingsProvider(info, cancellationToken);
+        }
+
+        public Task<List<ChannelInfo>> GetChannelsFromListingsProviderData(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));

+ 3 - 0
MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj

@@ -104,6 +104,9 @@
     <Content Include="dashboard-ui\components\apphost.js">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
+    <Content Include="dashboard-ui\components\channelmapper\channelmapper.js">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
     <Content Include="dashboard-ui\components\chromecasthelpers.js">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>