소스 검색

updated nuget for live tv

Luke Pulverenti 11 년 전
부모
커밋
e05a84c789

+ 17 - 5
MediaBrowser.Api/LiveTv/LiveTvService.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.LiveTv;
+using System.Threading;
+using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Model.LiveTv;
 using MediaBrowser.Model.LiveTv;
 using MediaBrowser.Model.Querying;
 using MediaBrowser.Model.Querying;
 using ServiceStack.ServiceHost;
 using ServiceStack.ServiceHost;
@@ -49,8 +50,13 @@ namespace MediaBrowser.Api.LiveTv
     [Api(Description = "Gets live tv recordings")]
     [Api(Description = "Gets live tv recordings")]
     public class GetRecordings : IReturn<QueryResult<RecordingInfoDto>>
     public class GetRecordings : IReturn<QueryResult<RecordingInfoDto>>
     {
     {
+        [ApiMember(Name = "ServiceName", Description = "Optional filter by service.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+        public string ServiceName { get; set; }
+
+        [ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+        public string ChannelId { get; set; }
     }
     }
-    
+
     [Route("/LiveTv/Programs", "GET")]
     [Route("/LiveTv/Programs", "GET")]
     [Api(Description = "Gets available live tv epgs..")]
     [Api(Description = "Gets available live tv epgs..")]
     public class GetPrograms : IReturn<QueryResult<ProgramInfoDto>>
     public class GetPrograms : IReturn<QueryResult<ProgramInfoDto>>
@@ -80,7 +86,7 @@ namespace MediaBrowser.Api.LiveTv
 
 
             if (!string.IsNullOrEmpty(serviceName))
             if (!string.IsNullOrEmpty(serviceName))
             {
             {
-                services = services.Where(i => string.Equals(i.Name, serviceName, System.StringComparison.OrdinalIgnoreCase));
+                services = services.Where(i => string.Equals(i.Name, serviceName, StringComparison.OrdinalIgnoreCase));
             }
             }
 
 
             return services;
             return services;
@@ -130,14 +136,20 @@ namespace MediaBrowser.Api.LiveTv
                 ServiceName = request.ServiceName,
                 ServiceName = request.ServiceName,
                 ChannelIdList = (request.ChannelIds ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToArray(),
                 ChannelIdList = (request.ChannelIds ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToArray(),
                 UserId = request.UserId
                 UserId = request.UserId
-            });
+
+            }, CancellationToken.None).Result;
 
 
             return ToOptimizedResult(result);
             return ToOptimizedResult(result);
         }
         }
 
 
         public object Get(GetRecordings request)
         public object Get(GetRecordings request)
         {
         {
-            var result = _liveTvManager.GetRecordings();
+            var result = _liveTvManager.GetRecordings(new RecordingQuery
+            {
+                ChannelId = request.ChannelId,
+                ServiceName = request.ServiceName
+
+            }, CancellationToken.None).Result;
 
 
             return ToOptimizedResult(result);
             return ToOptimizedResult(result);
         }
         }

+ 14 - 1
MediaBrowser.Controller/Entities/Audio/MusicArtist.cs

@@ -3,6 +3,8 @@ using MediaBrowser.Model.Entities;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Runtime.Serialization;
 using System.Runtime.Serialization;
+using System.Threading;
+using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Controller.Entities.Audio
 namespace MediaBrowser.Controller.Entities.Audio
 {
 {
@@ -30,13 +32,24 @@ namespace MediaBrowser.Controller.Entities.Audio
             {
             {
                 if (IsAccessedByName)
                 if (IsAccessedByName)
                 {
                 {
-                    throw new InvalidOperationException("Artists accessed by name do not have children.");
+                    return new List<BaseItem>();
                 }
                 }
 
 
                 return base.ActualChildren;
                 return base.ActualChildren;
             }
             }
         }
         }
 
 
+        protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool? recursive = null, bool forceRefreshMetadata = false)
+        {
+            if (IsAccessedByName)
+            {
+                // Should never get in here anyway
+                return Task.FromResult(true);
+            }
+
+            return base.ValidateChildrenInternal(progress, cancellationToken, recursive, forceRefreshMetadata);
+        }
+
         public override string GetClientTypeName()
         public override string GetClientTypeName()
         {
         {
             if (IsAccessedByName)
             if (IsAccessedByName)

+ 0 - 6
MediaBrowser.Controller/LiveTv/ChannelInfo.cs

@@ -25,12 +25,6 @@ namespace MediaBrowser.Controller.LiveTv
         /// <value>The id of the channel.</value>
         /// <value>The id of the channel.</value>
         public string Id { get; set; }
         public string Id { get; set; }
 
 
-        /// <summary>
-        /// Gets or sets the name of the service.
-        /// </summary>
-        /// <value>The name of the service.</value>
-        public string ServiceName { get; set; }
-
         /// <summary>
         /// <summary>
         /// Gets or sets the type of the channel.
         /// Gets or sets the type of the channel.
         /// </summary>
         /// </summary>

+ 15 - 3
MediaBrowser.Controller/LiveTv/ILiveTvManager.cs

@@ -1,6 +1,8 @@
-using MediaBrowser.Model.LiveTv;
+using System.Threading;
+using MediaBrowser.Model.LiveTv;
 using MediaBrowser.Model.Querying;
 using MediaBrowser.Model.Querying;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Controller.LiveTv
 namespace MediaBrowser.Controller.LiveTv
 {
 {
@@ -15,6 +17,13 @@ namespace MediaBrowser.Controller.LiveTv
         /// <value>The services.</value>
         /// <value>The services.</value>
         IReadOnlyList<ILiveTvService> Services { get; }
         IReadOnlyList<ILiveTvService> Services { get; }
 
 
+        /// <summary>
+        /// Schedules the recording.
+        /// </summary>
+        /// <param name="programId">The program identifier.</param>
+        /// <returns>Task.</returns>
+        Task ScheduleRecording(string programId);
+
         /// <summary>
         /// <summary>
         /// Adds the parts.
         /// Adds the parts.
         /// </summary>
         /// </summary>
@@ -31,8 +40,10 @@ namespace MediaBrowser.Controller.LiveTv
         /// <summary>
         /// <summary>
         /// Gets the recordings.
         /// Gets the recordings.
         /// </summary>
         /// </summary>
+        /// <param name="query">The query.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>QueryResult{RecordingInfoDto}.</returns>
         /// <returns>QueryResult{RecordingInfoDto}.</returns>
-        QueryResult<RecordingInfoDto> GetRecordings();
+        Task<QueryResult<RecordingInfoDto>> GetRecordings(RecordingQuery query, CancellationToken cancellationToken);
 
 
         /// <summary>
         /// <summary>
         /// Gets the channel.
         /// Gets the channel.
@@ -53,7 +64,8 @@ namespace MediaBrowser.Controller.LiveTv
         /// Gets the programs.
         /// Gets the programs.
         /// </summary>
         /// </summary>
         /// <param name="query">The query.</param>
         /// <param name="query">The query.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>IEnumerable{ProgramInfo}.</returns>
         /// <returns>IEnumerable{ProgramInfo}.</returns>
-        QueryResult<ProgramInfoDto> GetPrograms(ProgramQuery query);
+        Task<QueryResult<ProgramInfoDto>> GetPrograms(ProgramQuery query, CancellationToken cancellationToken);
     }
     }
 }
 }

+ 22 - 11
MediaBrowser.Controller/LiveTv/ILiveTvService.cs

@@ -1,5 +1,4 @@
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Net;
-using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
@@ -25,12 +24,12 @@ namespace MediaBrowser.Controller.LiveTv
         Task<IEnumerable<ChannelInfo>> GetChannelsAsync(CancellationToken cancellationToken);
         Task<IEnumerable<ChannelInfo>> GetChannelsAsync(CancellationToken cancellationToken);
 
 
         /// <summary>
         /// <summary>
-        /// Cancels the recording asynchronous.
+        /// Cancels the timer asynchronous.
         /// </summary>
         /// </summary>
-        /// <param name="recordingId">The recording identifier.</param>
+        /// <param name="timerId">The timer identifier.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
         /// <returns>Task.</returns>
-        Task CancelRecordingAsync(string recordingId, CancellationToken cancellationToken);
+        Task CancelTimerAsync(string timerId, CancellationToken cancellationToken);
 
 
         /// <summary>
         /// <summary>
         /// Deletes the recording asynchronous.
         /// Deletes the recording asynchronous.
@@ -39,18 +38,23 @@ namespace MediaBrowser.Controller.LiveTv
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
         /// <returns>Task.</returns>
         Task DeleteRecordingAsync(string recordingId, CancellationToken cancellationToken);
         Task DeleteRecordingAsync(string recordingId, CancellationToken cancellationToken);
-        
+
         /// <summary>
         /// <summary>
-        /// Schedules the recording asynchronous.
+        /// Creates the timer asynchronous.
         /// </summary>
         /// </summary>
-        /// <param name="name">The name for the recording</param>
-        /// <param name="channelId">The channel identifier.</param>
-        /// <param name="startTime">The start time.</param>
-        /// <param name="duration">The duration.</param>
+        /// <param name="info">The information.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
         /// <returns>Task.</returns>
-        Task ScheduleRecordingAsync(string name, string channelId, DateTime startTime, TimeSpan duration, CancellationToken cancellationToken);
+        Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken);
 
 
+        /// <summary>
+        /// Updates the timer asynchronous.
+        /// </summary>
+        /// <param name="info">The information.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task.</returns>
+        Task UpdateTimerAsync(TimerInfo info, CancellationToken cancellationToken);
+        
         /// <summary>
         /// <summary>
         /// Gets the channel image asynchronous.
         /// Gets the channel image asynchronous.
         /// </summary>
         /// </summary>
@@ -66,6 +70,13 @@ namespace MediaBrowser.Controller.LiveTv
         /// <returns>Task{IEnumerable{RecordingInfo}}.</returns>
         /// <returns>Task{IEnumerable{RecordingInfo}}.</returns>
         Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(CancellationToken cancellationToken);
         Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(CancellationToken cancellationToken);
 
 
+        /// <summary>
+        /// Gets the recordings asynchronous.
+        /// </summary>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task{IEnumerable{RecordingInfo}}.</returns>
+        Task<IEnumerable<TimerInfo>> GetTimersAsync(CancellationToken cancellationToken);
+        
         /// <summary>
         /// <summary>
         /// Gets the programs asynchronous.
         /// Gets the programs asynchronous.
         /// </summary>
         /// </summary>

+ 6 - 0
MediaBrowser.Controller/LiveTv/ProgramInfo.cs

@@ -43,6 +43,12 @@ namespace MediaBrowser.Controller.LiveTv
         /// </summary>
         /// </summary>
         public DateTime EndDate { get; set; }
         public DateTime EndDate { get; set; }
 
 
+        /// <summary>
+        /// Gets or sets the aspect ratio.
+        /// </summary>
+        /// <value>The aspect ratio.</value>
+        public string AspectRatio { get; set; }
+
         /// <summary>
         /// <summary>
         /// Genre of the program.
         /// Genre of the program.
         /// </summary>
         /// </summary>

+ 0 - 33
MediaBrowser.Controller/LiveTv/RecordingInfo.cs

@@ -1,6 +1,5 @@
 using MediaBrowser.Model.LiveTv;
 using MediaBrowser.Model.LiveTv;
 using System;
 using System;
-using System.Collections.Generic;
 
 
 namespace MediaBrowser.Controller.LiveTv
 namespace MediaBrowser.Controller.LiveTv
 {
 {
@@ -20,12 +19,6 @@ namespace MediaBrowser.Controller.LiveTv
         /// ChannelName of the recording.
         /// ChannelName of the recording.
         /// </summary>
         /// </summary>
         public string ChannelName { get; set; }
         public string ChannelName { get; set; }
-
-        /// <summary>
-        /// Gets or sets the program identifier.
-        /// </summary>
-        /// <value>The program identifier.</value>
-        public string ProgramId { get; set; }
         
         
         /// <summary>
         /// <summary>
         /// Name of the recording.
         /// Name of the recording.
@@ -52,31 +45,5 @@ namespace MediaBrowser.Controller.LiveTv
         /// </summary>
         /// </summary>
         /// <value>The status.</value>
         /// <value>The status.</value>
         public RecordingStatus Status { get; set; }
         public RecordingStatus Status { get; set; }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether this instance is recurring.
-        /// </summary>
-        /// <value><c>true</c> if this instance is recurring; otherwise, <c>false</c>.</value>
-        public bool IsRecurring { get; set; }
-
-        /// <summary>
-        /// Parent recurring.
-        /// </summary>
-        public string RecurringParent { get; set; }
-
-        /// <summary>
-        /// Start date for the recurring, in UTC.
-        /// </summary>
-        public DateTime RecurrringStartDate { get; set; }
-
-        /// <summary>
-        /// End date for the recurring, in UTC
-        /// </summary>
-        public DateTime RecurringEndDate { get; set; }
-
-        /// <summary>
-        /// When do we need the recording?
-        /// </summary>
-        public List<string> DayMask { get; set; }
     }
     }
 }
 }

+ 67 - 0
MediaBrowser.Controller/LiveTv/TimerInfo.cs

@@ -0,0 +1,67 @@
+using MediaBrowser.Model.LiveTv;
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.LiveTv
+{
+    public class TimerInfo
+    {
+        /// <summary>
+        /// Id of the recording.
+        /// </summary>
+        public string Id { get; set; }
+
+        /// <summary>
+        /// ChannelId of the recording.
+        /// </summary>
+        public string ChannelId { get; set; }
+
+        /// <summary>
+        /// ChannelName of the recording.
+        /// </summary>
+        public string ChannelName { get; set; }
+
+        /// <summary>
+        /// Name of the recording.
+        /// </summary>
+        public string Name { get; set; }
+
+        /// <summary>
+        /// Description of the recording.
+        /// </summary>
+        public string Description { get; set; }
+
+        /// <summary>
+        /// The start date of the recording, in UTC.
+        /// </summary>
+        public DateTime StartDate { get; set; }
+
+        /// <summary>
+        /// The end date of the recording, in UTC.
+        /// </summary>
+        public DateTime EndDate { get; set; }
+
+        /// <summary>
+        /// Gets or sets the status.
+        /// </summary>
+        /// <value>The status.</value>
+        public RecordingStatus Status { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this instance is recurring.
+        /// </summary>
+        /// <value><c>true</c> if this instance is recurring; otherwise, <c>false</c>.</value>
+        public bool IsRecurring { get; set; }
+
+        /// <summary>
+        /// Gets or sets the recurring days.
+        /// </summary>
+        /// <value>The recurring days.</value>
+        public List<DayOfWeek> RecurringDays { get; set; }
+
+        public TimerInfo()
+        {
+            RecurringDays = new List<DayOfWeek>();
+        }
+    }
+}

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

@@ -110,6 +110,7 @@
     <Compile Include="LiveTv\ILiveTvService.cs" />
     <Compile Include="LiveTv\ILiveTvService.cs" />
     <Compile Include="LiveTv\ProgramInfo.cs" />
     <Compile Include="LiveTv\ProgramInfo.cs" />
     <Compile Include="LiveTv\RecordingInfo.cs" />
     <Compile Include="LiveTv\RecordingInfo.cs" />
+    <Compile Include="LiveTv\TimerInfo.cs" />
     <Compile Include="Localization\ILocalizationManager.cs" />
     <Compile Include="Localization\ILocalizationManager.cs" />
     <Compile Include="Notifications\INotificationsRepository.cs" />
     <Compile Include="Notifications\INotificationsRepository.cs" />
     <Compile Include="Notifications\NotificationUpdateEventArgs.cs" />
     <Compile Include="Notifications\NotificationUpdateEventArgs.cs" />

+ 17 - 5
MediaBrowser.Model/LiveTv/ProgramInfoDto.cs

@@ -27,13 +27,13 @@ namespace MediaBrowser.Model.LiveTv
         /// </summary>
         /// </summary>
         /// <value>The community rating.</value>
         /// <value>The community rating.</value>
         public float? CommunityRating { get; set; }
         public float? CommunityRating { get; set; }
-        
+
         /// <summary>
         /// <summary>
-        /// Gets or sets the recording identifier.
+        /// Gets or sets the aspect ratio.
         /// </summary>
         /// </summary>
-        /// <value>The recording identifier.</value>
-        public string RecordingId { get; set; }
-
+        /// <value>The aspect ratio.</value>
+        public string AspectRatio { get; set; }
+        
         /// <summary>
         /// <summary>
         /// Gets or sets the official rating.
         /// Gets or sets the official rating.
         /// </summary>
         /// </summary>
@@ -88,6 +88,18 @@ namespace MediaBrowser.Model.LiveTv
         /// </summary>
         /// </summary>
         /// <value>The original air date.</value>
         /// <value>The original air date.</value>
         public DateTime? OriginalAirDate { get; set; }
         public DateTime? OriginalAirDate { get; set; }
+
+        /// <summary>
+        /// Gets or sets the recording identifier.
+        /// </summary>
+        /// <value>The recording identifier.</value>
+        public string RecordingId { get; set; }
+
+        /// <summary>
+        /// Gets or sets the recording status.
+        /// </summary>
+        /// <value>The recording status.</value>
+        public RecordingStatus? RecordingStatus { get; set; }
         
         
         public ProgramInfoDto()
         public ProgramInfoDto()
         {
         {

+ 0 - 5
MediaBrowser.Model/LiveTv/RecordingInfoDto.cs

@@ -51,11 +51,6 @@ namespace MediaBrowser.Model.LiveTv
         /// </summary>
         /// </summary>
         public DateTime EndDate { get; set; }
         public DateTime EndDate { get; set; }
 
 
-        /// <summary>
-        /// IsRecurring recording?
-        /// </summary>
-        public bool IsRecurring { get; set; }
-
         /// <summary>
         /// <summary>
         /// Gets or sets the status.
         /// Gets or sets the status.
         /// </summary>
         /// </summary>

+ 10 - 0
MediaBrowser.Model/LiveTv/RecordingQuery.cs

@@ -5,6 +5,16 @@
     /// </summary>
     /// </summary>
     public class RecordingQuery
     public class RecordingQuery
     {
     {
+        /// <summary>
+        /// Gets or sets the channel identifier.
+        /// </summary>
+        /// <value>The channel identifier.</value>
         public string ChannelId { get; set; }
         public string ChannelId { get; set; }
+
+        /// <summary>
+        /// Gets or sets the name of the service.
+        /// </summary>
+        /// <value>The name of the service.</value>
+        public string ServiceName { get; set; }
     }
     }
 }
 }

+ 2 - 8
MediaBrowser.Server.Implementations/Dto/DtoService.cs

@@ -207,7 +207,7 @@ namespace MediaBrowser.Server.Implementations.Dto
 
 
             if (!string.IsNullOrEmpty(image))
             if (!string.IsNullOrEmpty(image))
             {
             {
-                dto.PrimaryImageTag = _imageProcessor.GetImageCacheTag(user, ImageType.Primary, image);
+                dto.PrimaryImageTag = GetImageCacheTag(user, ImageType.Primary, image);
 
 
                 try
                 try
                 {
                 {
@@ -285,13 +285,7 @@ namespace MediaBrowser.Server.Implementations.Dto
 
 
             if (!string.IsNullOrEmpty(imagePath))
             if (!string.IsNullOrEmpty(imagePath))
             {
             {
-                try
-                {
-                    info.PrimaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary, imagePath);
-                }
-                catch (IOException)
-                {
-                }
+                info.PrimaryImageTag = GetImageCacheTag(item, ImageType.Primary, imagePath);
             }
             }
 
 
             return info;
             return info;

+ 73 - 67
MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs

@@ -41,9 +41,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
 
 
         private List<Channel> _channels = new List<Channel>();
         private List<Channel> _channels = new List<Channel>();
         private List<ProgramInfoDto> _programs = new List<ProgramInfoDto>();
         private List<ProgramInfoDto> _programs = new List<ProgramInfoDto>();
-        private List<RecordingInfoDto> _recordings = new List<RecordingInfoDto>();
-
-        private readonly SemaphoreSlim _updateSemaphore = new SemaphoreSlim(1, 1);
 
 
         public LiveTvManager(IServerApplicationPaths appPaths, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserManager userManager, ILocalizationManager localization, IUserDataManager userDataManager, IDtoService dtoService)
         public LiveTvManager(IServerApplicationPaths appPaths, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserManager userManager, ILocalizationManager localization, IUserDataManager userDataManager, IDtoService dtoService)
         {
         {
@@ -104,11 +101,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             return dto;
             return dto;
         }
         }
 
 
-        private ILiveTvService GetService(ChannelInfo channel)
-        {
-            return _services.FirstOrDefault(i => string.Equals(channel.ServiceName, i.Name, StringComparison.OrdinalIgnoreCase));
-        }
-
         private Guid? GetLogoImageTag(Channel info)
         private Guid? GetLogoImageTag(Channel info)
         {
         {
             var path = info.PrimaryImagePath;
             var path = info.PrimaryImagePath;
@@ -210,7 +202,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 Quality = program.Quality,
                 Quality = program.Quality,
                 OriginalAirDate = program.OriginalAirDate,
                 OriginalAirDate = program.OriginalAirDate,
                 Audio = program.Audio,
                 Audio = program.Audio,
-                CommunityRating = program.CommunityRating
+                CommunityRating = program.CommunityRating,
+                AspectRatio = program.AspectRatio
             };
             };
         }
         }
 
 
@@ -228,9 +221,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             return name.ToLower().GetMD5();
             return name.ToLower().GetMD5();
         }
         }
 
 
-        private async Task<Channel> GetChannel(ChannelInfo channelInfo, CancellationToken cancellationToken)
+        private async Task<Channel> GetChannel(ChannelInfo channelInfo, string serviceName, CancellationToken cancellationToken)
         {
         {
-            var path = Path.Combine(_appPaths.ItemsByNamePath, "channels", _fileSystem.GetValidFilename(channelInfo.ServiceName), _fileSystem.GetValidFilename(channelInfo.Name));
+            var path = Path.Combine(_appPaths.ItemsByNamePath, "channels", _fileSystem.GetValidFilename(serviceName), _fileSystem.GetValidFilename(channelInfo.Name));
 
 
             var fileInfo = new DirectoryInfo(path);
             var fileInfo = new DirectoryInfo(path);
 
 
@@ -249,7 +242,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 isNew = true;
                 isNew = true;
             }
             }
 
 
-            var id = GetInternalChannelId(channelInfo.ServiceName, channelInfo.Id);
+            var id = GetInternalChannelId(serviceName, channelInfo.Id);
 
 
             var item = _itemRepo.RetrieveItem(id) as Channel;
             var item = _itemRepo.RetrieveItem(id) as Channel;
 
 
@@ -264,7 +257,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                     Path = path,
                     Path = path,
                     ChannelId = channelInfo.Id,
                     ChannelId = channelInfo.Id,
                     ChannelNumber = channelInfo.Number,
                     ChannelNumber = channelInfo.Number,
-                    ServiceName = channelInfo.ServiceName
+                    ServiceName = serviceName
                 };
                 };
 
 
                 isNew = true;
                 isNew = true;
@@ -278,7 +271,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             return item;
             return item;
         }
         }
 
 
-        public QueryResult<ProgramInfoDto> GetPrograms(ProgramQuery query)
+        public async Task<QueryResult<ProgramInfoDto>> GetPrograms(ProgramQuery query, CancellationToken cancellationToken)
         {
         {
             IEnumerable<ProgramInfoDto> programs = _programs
             IEnumerable<ProgramInfoDto> programs = _programs
                 .OrderBy(i => i.StartDate)
                 .OrderBy(i => i.StartDate)
@@ -298,35 +291,34 @@ namespace MediaBrowser.Server.Implementations.LiveTv
 
 
             var returnArray = programs.ToArray();
             var returnArray = programs.ToArray();
 
 
-            return new QueryResult<ProgramInfoDto>
+            var recordings = await GetRecordings(new RecordingQuery
             {
             {
-                Items = returnArray,
-                TotalRecordCount = returnArray.Length
-            };
-        }
 
 
-        internal async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken)
-        {
-            await _updateSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
 
 
-            try
-            {
-                await RefreshChannelsInternal(progress, cancellationToken).ConfigureAwait(false);
-            }
-            finally
+            }, cancellationToken).ConfigureAwait(false);
+
+            foreach (var program in returnArray)
             {
             {
-                _updateSemaphore.Release();
+                var recording = recordings.Items
+                    .FirstOrDefault(i => string.Equals(i.ProgramId, program.Id));
+
+                program.RecordingId = recording == null ? null : recording.Id;
+                program.RecordingStatus = recording == null ? (RecordingStatus?)null : recording.Status;
             }
             }
 
 
-            await RefreshRecordings(new Progress<double>(), cancellationToken).ConfigureAwait(false);
+            return new QueryResult<ProgramInfoDto>
+            {
+                Items = returnArray,
+                TotalRecordCount = returnArray.Length
+            };
         }
         }
 
 
-        private async Task RefreshChannelsInternal(IProgress<double> progress, CancellationToken cancellationToken)
+        internal async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken)
         {
         {
             // Avoid implicitly captured closure
             // Avoid implicitly captured closure
             var currentCancellationToken = cancellationToken;
             var currentCancellationToken = cancellationToken;
 
 
-            var channelTasks = _services.Select(i => i.GetChannelsAsync(currentCancellationToken));
+            var channelTasks = _services.Select(i => GetChannels(i, currentCancellationToken));
 
 
             progress.Report(10);
             progress.Report(10);
 
 
@@ -343,11 +335,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             {
             {
                 try
                 try
                 {
                 {
-                    var item = await GetChannel(channelInfo, cancellationToken).ConfigureAwait(false);
+                    var item = await GetChannel(channelInfo.Item2, channelInfo.Item1, cancellationToken).ConfigureAwait(false);
 
 
-                    var service = GetService(channelInfo);
+                    var service = _services.First(i => string.Equals(channelInfo.Item1, i.Name, StringComparison.OrdinalIgnoreCase));
 
 
-                    var channelPrograms = await service.GetProgramsAsync(channelInfo.Id, cancellationToken).ConfigureAwait(false);
+                    var channelPrograms = await service.GetProgramsAsync(channelInfo.Item2.Id, cancellationToken).ConfigureAwait(false);
 
 
                     programs.AddRange(channelPrograms.Select(program => GetProgramInfoDto(program, item)));
                     programs.AddRange(channelPrograms.Select(program => GetProgramInfoDto(program, item)));
 
 
@@ -359,7 +351,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 }
                 }
                 catch (Exception ex)
                 catch (Exception ex)
                 {
                 {
-                    _logger.ErrorException("Error getting channel information for {0}", ex, channelInfo.Name);
+                    _logger.ErrorException("Error getting channel information for {0}", ex, channelInfo.Item2.Name);
                 }
                 }
 
 
                 numComplete++;
                 numComplete++;
@@ -373,32 +365,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             _channels = list;
             _channels = list;
         }
         }
 
 
-        internal async Task RefreshRecordings(IProgress<double> progress, CancellationToken cancellationToken)
-        {
-            await _updateSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
-
-            try
-            {
-                await RefreshRecordingsInternal(progress, cancellationToken).ConfigureAwait(false);
-            }
-            finally
-            {
-                _updateSemaphore.Release();
-            }
-        }
-
-        private async Task RefreshRecordingsInternal(IProgress<double> progress, CancellationToken cancellationToken)
+        private async Task<IEnumerable<Tuple<string, ChannelInfo>>> GetChannels(ILiveTvService service, CancellationToken cancellationToken)
         {
         {
-            var list = new List<RecordingInfoDto>();
-
-            foreach (var service in _services)
-            {
-                var recordings = await GetRecordings(service, cancellationToken).ConfigureAwait(false);
-
-                list.AddRange(recordings);
-            }
+            var channels = await service.GetChannelsAsync(cancellationToken).ConfigureAwait(false);
 
 
-            _recordings = list;
+            return channels.Select(i => new Tuple<string, ChannelInfo>(service.Name, i));
         }
         }
 
 
         private async Task<IEnumerable<RecordingInfoDto>> GetRecordings(ILiveTvService service, CancellationToken cancellationToken)
         private async Task<IEnumerable<RecordingInfoDto>> GetRecordings(ILiveTvService service, CancellationToken cancellationToken)
@@ -419,7 +390,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 Description = info.Description,
                 Description = info.Description,
                 EndDate = info.EndDate,
                 EndDate = info.EndDate,
                 Name = info.Name,
                 Name = info.Name,
-                IsRecurring = info.IsRecurring,
                 StartDate = info.StartDate,
                 StartDate = info.StartDate,
                 Id = id,
                 Id = id,
                 ExternalId = info.Id,
                 ExternalId = info.Id,
@@ -427,17 +397,27 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 Status = info.Status
                 Status = info.Status
             };
             };
 
 
-            if (!string.IsNullOrEmpty(info.ProgramId))
-            {
-                dto.ProgramId = GetInternalProgramIdId(service.Name, info.ProgramId).ToString("N");
-            }
-
             return dto;
             return dto;
         }
         }
 
 
-        public QueryResult<RecordingInfoDto> GetRecordings()
+        public async Task<QueryResult<RecordingInfoDto>> GetRecordings(RecordingQuery query, CancellationToken cancellationToken)
         {
         {
-            var returnArray = _recordings.ToArray();
+            var list = new List<RecordingInfoDto>();
+
+            foreach (var service in GetServices(query.ServiceName, query.ChannelId))
+            {
+                var recordings = await GetRecordings(service, cancellationToken).ConfigureAwait(false);
+
+                list.AddRange(recordings);
+            }
+
+            if (!string.IsNullOrEmpty(query.ChannelId))
+            {
+                list = list.Where(i => string.Equals(i.ChannelId, query.ChannelId))
+                    .ToList();
+            }
+
+            var returnArray = list.ToArray();
 
 
             return new QueryResult<RecordingInfoDto>
             return new QueryResult<RecordingInfoDto>
             {
             {
@@ -445,5 +425,31 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 TotalRecordCount = returnArray.Length
                 TotalRecordCount = returnArray.Length
             };
             };
         }
         }
+
+        private IEnumerable<ILiveTvService> GetServices(string serviceName, string channelId)
+        {
+            IEnumerable<ILiveTvService> services = _services;
+
+            if (string.IsNullOrEmpty(serviceName) && !string.IsNullOrEmpty(channelId))
+            {
+                var channelIdGuid = new Guid(channelId);
+
+                serviceName = _channels.Where(i => i.Id == channelIdGuid)
+                    .Select(i => i.ServiceName)
+                    .FirstOrDefault();
+            }
+
+            if (!string.IsNullOrEmpty(serviceName))
+            {
+                services = services.Where(i => string.Equals(i.Name, serviceName, StringComparison.OrdinalIgnoreCase));
+            }
+
+            return services;
+        }
+
+        public Task ScheduleRecording(string programId)
+        {
+            throw new NotImplementedException();
+        }
     }
     }
 }
 }

+ 2 - 2
Nuget/MediaBrowser.Common.Internal.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
     <metadata>
         <id>MediaBrowser.Common.Internal</id>
         <id>MediaBrowser.Common.Internal</id>
-        <version>3.0.250</version>
+        <version>3.0.251</version>
         <title>MediaBrowser.Common.Internal</title>
         <title>MediaBrowser.Common.Internal</title>
         <authors>Luke</authors>
         <authors>Luke</authors>
         <owners>ebr,Luke,scottisafool</owners>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
         <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
         <copyright>Copyright © Media Browser 2013</copyright>
         <copyright>Copyright © Media Browser 2013</copyright>
         <dependencies>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.250" />
+            <dependency id="MediaBrowser.Common" version="3.0.251" />
             <dependency id="NLog" version="2.1.0" />
             <dependency id="NLog" version="2.1.0" />
             <dependency id="ServiceStack.Text" version="3.9.58" />
             <dependency id="ServiceStack.Text" version="3.9.58" />
             <dependency id="SimpleInjector" version="2.3.6" />
             <dependency id="SimpleInjector" version="2.3.6" />

+ 1 - 1
Nuget/MediaBrowser.Common.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
     <metadata>
         <id>MediaBrowser.Common</id>
         <id>MediaBrowser.Common</id>
-        <version>3.0.250</version>
+        <version>3.0.251</version>
         <title>MediaBrowser.Common</title>
         <title>MediaBrowser.Common</title>
         <authors>Media Browser Team</authors>
         <authors>Media Browser Team</authors>
         <owners>ebr,Luke,scottisafool</owners>
         <owners>ebr,Luke,scottisafool</owners>

+ 2 - 2
Nuget/MediaBrowser.Server.Core.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
 <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
     <metadata>
     <metadata>
         <id>MediaBrowser.Server.Core</id>
         <id>MediaBrowser.Server.Core</id>
-        <version>3.0.250</version>
+        <version>3.0.251</version>
         <title>Media Browser.Server.Core</title>
         <title>Media Browser.Server.Core</title>
         <authors>Media Browser Team</authors>
         <authors>Media Browser Team</authors>
         <owners>ebr,Luke,scottisafool</owners>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains core components required to build plugins for Media Browser Server.</description>
         <description>Contains core components required to build plugins for Media Browser Server.</description>
         <copyright>Copyright © Media Browser 2013</copyright>
         <copyright>Copyright © Media Browser 2013</copyright>
         <dependencies>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.250" />
+            <dependency id="MediaBrowser.Common" version="3.0.251" />
         </dependencies>
         </dependencies>
     </metadata>
     </metadata>
     <files>
     <files>