Browse Source

update recording database

Luke Pulverenti 10 years ago
parent
commit
418bb87878

+ 9 - 0
MediaBrowser.Controller/Entities/IHasId.cs

@@ -0,0 +1,9 @@
+using System;
+
+namespace MediaBrowser.Controller.Entities
+{
+    public interface IHasId
+    {
+        Guid Id { get; }
+    }
+}

+ 1 - 8
MediaBrowser.Controller/Entities/IHasImages.cs

@@ -1,13 +1,12 @@
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
-using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.IO;
 using System.IO;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Controller.Entities
 namespace MediaBrowser.Controller.Entities
 {
 {
-    public interface IHasImages : IHasProviderIds
+    public interface IHasImages : IHasProviderIds, IHasId
     {
     {
         /// <summary>
         /// <summary>
         /// Gets the name.
         /// Gets the name.
@@ -27,12 +26,6 @@ namespace MediaBrowser.Controller.Entities
         /// <value>The file name without extension.</value>
         /// <value>The file name without extension.</value>
         string FileNameWithoutExtension { get; }
         string FileNameWithoutExtension { get; }
 
 
-        /// <summary>
-        /// Gets the identifier.
-        /// </summary>
-        /// <value>The identifier.</value>
-        Guid Id { get; }
-
         /// <summary>
         /// <summary>
         /// Gets the type of the location.
         /// Gets the type of the location.
         /// </summary>
         /// </summary>

+ 1 - 8
MediaBrowser.Controller/Entities/IHasMediaSources.cs

@@ -1,17 +1,10 @@
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Dto;
-using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 
 
 namespace MediaBrowser.Controller.Entities
 namespace MediaBrowser.Controller.Entities
 {
 {
-    public interface IHasMediaSources
+    public interface IHasMediaSources : IHasId
     {
     {
-        /// <summary>
-        /// Gets the identifier.
-        /// </summary>
-        /// <value>The identifier.</value>
-        Guid Id { get; }
-
         /// <summary>
         /// <summary>
         /// Gets the media sources.
         /// Gets the media sources.
         /// </summary>
         /// </summary>

+ 11 - 1
MediaBrowser.Controller/Entities/IHasProgramAttributes.cs

@@ -1,9 +1,19 @@
-
+using MediaBrowser.Model.LiveTv;
+using System;
+
 namespace MediaBrowser.Controller.Entities
 namespace MediaBrowser.Controller.Entities
 {
 {
     public interface IHasProgramAttributes
     public interface IHasProgramAttributes
     {
     {
         bool IsMovie { get; set; }
         bool IsMovie { get; set; }
         bool IsSports { get; set; }
         bool IsSports { get; set; }
+        bool IsNews { get; set; }
+        bool IsKids { get; set; }
+        bool IsRepeat { get; set; }
+        bool? IsHD { get; set; }
+        bool IsLive { get; set; }
+        bool IsPremiere { get; set; }
+        ProgramAudio? Audio { get; set; }
+        DateTime? OriginalAirDate { get; set; }
     }
     }
 }
 }

+ 1 - 8
MediaBrowser.Controller/Entities/IHasUserData.cs

@@ -1,19 +1,12 @@
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Dto;
-using System;
 
 
 namespace MediaBrowser.Controller.Entities
 namespace MediaBrowser.Controller.Entities
 {
 {
     /// <summary>
     /// <summary>
     /// Interface IHasUserData
     /// Interface IHasUserData
     /// </summary>
     /// </summary>
-    public interface IHasUserData
+    public interface IHasUserData : IHasId
     {
     {
-        /// <summary>
-        /// Gets or sets the identifier.
-        /// </summary>
-        /// <value>The identifier.</value>
-        Guid Id { get; set; }
-
         /// <summary>
         /// <summary>
         /// Gets the user data key.
         /// Gets the user data key.
         /// </summary>
         /// </summary>

+ 2 - 3
MediaBrowser.Controller/LiveTv/ILiveTvItem.cs

@@ -1,10 +1,9 @@
-using System;
+using MediaBrowser.Controller.Entities;
 
 
 namespace MediaBrowser.Controller.LiveTv
 namespace MediaBrowser.Controller.LiveTv
 {
 {
-    public interface ILiveTvItem
+    public interface ILiveTvItem : IHasId
     {
     {
-        Guid Id { get; }
         string ServiceName { get; set; }
         string ServiceName { get; set; }
     }
     }
 }
 }

+ 17 - 3
MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs

@@ -2,19 +2,21 @@
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Library;
 using MediaBrowser.Model.Library;
+using MediaBrowser.Model.LiveTv;
+using System;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Controller.LiveTv
 namespace MediaBrowser.Controller.LiveTv
 {
 {
-    public interface ILiveTvRecording : IHasImages, IHasMediaSources, IHasUserData, ILiveTvItem
+    public interface ILiveTvRecording : IHasImages, IHasMediaSources, IHasUserData, ILiveTvItem, IHasStartDate, IHasProgramAttributes
     {
     {
+        string ChannelId { get; }
+        string ProgramId { get; set; }
         string MediaType { get; }
         string MediaType { get; }
 
 
         string Container { get; }
         string Container { get; }
 
 
-        RecordingInfo RecordingInfo { get; set; }
-
         long? RunTimeTicks { get; set; }
         long? RunTimeTicks { get; set; }
 
 
         string GetClientTypeName();
         string GetClientTypeName();
@@ -28,5 +30,17 @@ namespace MediaBrowser.Controller.LiveTv
         bool CanDelete();
         bool CanDelete();
 
 
         bool CanDelete(User user);
         bool CanDelete(User user);
+
+        string ProviderImagePath { get; set; }
+
+        string ProviderImageUrl { get; set; }
+
+        string ExternalId { get; set; }
+        string EpisodeTitle { get; set; }
+        bool IsSeries { get; set; }
+        string SeriesTimerId { get; set; }
+        RecordingStatus Status { get; set; }
+        DateTime? EndDate { get; set; }
+        ChannelType ChannelType { get; set; }
     }
     }
 }
 }

+ 23 - 0
MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs

@@ -3,7 +3,9 @@ using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.LiveTv;
 using MediaBrowser.Model.Users;
 using MediaBrowser.Model.Users;
+using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
 using System.Runtime.Serialization;
 using System.Runtime.Serialization;
@@ -12,6 +14,27 @@ namespace MediaBrowser.Controller.LiveTv
 {
 {
     public class LiveTvAudioRecording : Audio, ILiveTvRecording
     public class LiveTvAudioRecording : Audio, ILiveTvRecording
     {
     {
+        public string ExternalId { get; set; }
+        public string ProviderImagePath { get; set; }
+        public string ProviderImageUrl { get; set; }
+        public string EpisodeTitle { get; set; }
+        public bool IsSeries { get; set; }
+        public string SeriesTimerId { get; set; }
+        public DateTime StartDate { get; set; }
+        public RecordingStatus Status { get; set; }
+        public bool IsSports { get; set; }
+        public bool IsNews { get; set; }
+        public bool IsKids { get; set; }
+        public bool IsRepeat { get; set; }
+        public bool IsMovie { get; set; }
+        public bool? IsHD { get; set; }
+        public bool IsLive { get; set; }
+        public bool IsPremiere { get; set; }
+        public ChannelType ChannelType { get; set; }
+        public string ProgramId { get; set; }
+        public ProgramAudio? Audio { get; set; }
+        public DateTime? OriginalAirDate { get; set; }
+
         /// <summary>
         /// <summary>
         /// Gets the user data key.
         /// Gets the user data key.
         /// </summary>
         /// </summary>

+ 23 - 0
MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs

@@ -2,7 +2,9 @@
 using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.LiveTv;
 using MediaBrowser.Model.Users;
 using MediaBrowser.Model.Users;
+using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
 using System.Runtime.Serialization;
 using System.Runtime.Serialization;
@@ -11,6 +13,27 @@ namespace MediaBrowser.Controller.LiveTv
 {
 {
     public class LiveTvVideoRecording : Video, ILiveTvRecording
     public class LiveTvVideoRecording : Video, ILiveTvRecording
     {
     {
+        public string ExternalId { get; set; }
+        public string ProviderImagePath { get; set; }
+        public string ProviderImageUrl { get; set; }
+        public string EpisodeTitle { get; set; }
+        public bool IsSeries { get; set; }
+        public string SeriesTimerId { get; set; }
+        public DateTime StartDate { get; set; }
+        public RecordingStatus Status { get; set; }
+        public bool IsSports { get; set; }
+        public bool IsNews { get; set; }
+        public bool IsKids { get; set; }
+        public bool IsRepeat { get; set; }
+        public bool IsMovie { get; set; }
+        public bool? IsHD { get; set; }
+        public bool IsLive { get; set; }
+        public bool IsPremiere { get; set; }
+        public ChannelType ChannelType { get; set; }
+        public string ProgramId { get; set; }
+        public ProgramAudio? Audio { get; set; }
+        public DateTime? OriginalAirDate { get; set; }
+
         /// <summary>
         /// <summary>
         /// Gets the user data key.
         /// Gets the user data key.
         /// </summary>
         /// </summary>

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

@@ -142,6 +142,7 @@
     <Compile Include="Entities\IHasBudget.cs" />
     <Compile Include="Entities\IHasBudget.cs" />
     <Compile Include="Entities\IHasCriticRating.cs" />
     <Compile Include="Entities\IHasCriticRating.cs" />
     <Compile Include="Entities\IHasDisplayOrder.cs" />
     <Compile Include="Entities\IHasDisplayOrder.cs" />
+    <Compile Include="Entities\IHasId.cs" />
     <Compile Include="Entities\IHasImages.cs" />
     <Compile Include="Entities\IHasImages.cs" />
     <Compile Include="Entities\IHasKeywords.cs" />
     <Compile Include="Entities\IHasKeywords.cs" />
     <Compile Include="Entities\IHasMediaSources.cs" />
     <Compile Include="Entities\IHasMediaSources.cs" />

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

@@ -290,7 +290,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
 
 
         public Guid GetInternalRecordingId(string serviceName, string externalId)
         public Guid GetInternalRecordingId(string serviceName, string externalId)
         {
         {
-            var name = serviceName + externalId + InternalVersionNumber;
+            var name = serviceName + externalId + InternalVersionNumber + "0";
 
 
             return name.ToLower().GetMBId(typeof(ILiveTvRecording));
             return name.ToLower().GetMBId(typeof(ILiveTvRecording));
         }
         }

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

@@ -53,6 +53,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
         private readonly ConcurrentDictionary<string, LiveStreamData> _openStreams =
         private readonly ConcurrentDictionary<string, LiveStreamData> _openStreams =
             new ConcurrentDictionary<string, LiveStreamData>();
             new ConcurrentDictionary<string, LiveStreamData>();
 
 
+        private readonly SemaphoreSlim _refreshRecordingsLock = new SemaphoreSlim(1, 1);
+
         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)
         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)
         {
         {
             _config = config;
             _config = config;
@@ -359,8 +361,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                     isVideo = !string.Equals(recording.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase);
                     isVideo = !string.Equals(recording.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase);
                     var service = GetService(recording);
                     var service = GetService(recording);
 
 
-                    _logger.Info("Opening recording stream from {0}, external recording Id: {1}", service.Name, recording.RecordingInfo.Id);
-                    info = await service.GetRecordingStream(recording.RecordingInfo.Id, null, cancellationToken).ConfigureAwait(false);
+                    _logger.Info("Opening recording stream from {0}, external recording Id: {1}", service.Name, recording.ExternalId);
+                    info = await service.GetRecordingStream(recording.ExternalId, null, cancellationToken).ConfigureAwait(false);
                     info.RequiresClosing = true;
                     info.RequiresClosing = true;
 
 
                     if (info.RequiresClosing)
                     if (info.RequiresClosing)
@@ -618,7 +620,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             return item;
             return item;
         }
         }
 
 
-        private async Task<ILiveTvRecording> GetRecording(RecordingInfo info, string serviceName, CancellationToken cancellationToken)
+        private async Task<Guid> CreateRecordingRecord(RecordingInfo info, string serviceName, CancellationToken cancellationToken)
         {
         {
             var isNew = false;
             var isNew = false;
 
 
@@ -653,14 +655,36 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 isNew = true;
                 isNew = true;
             }
             }
 
 
+            item.ChannelId = _tvDtoService.GetInternalChannelId(serviceName, info.ChannelId).ToString("N");
             item.CommunityRating = info.CommunityRating;
             item.CommunityRating = info.CommunityRating;
             item.OfficialRating = info.OfficialRating;
             item.OfficialRating = info.OfficialRating;
             item.Overview = info.Overview;
             item.Overview = info.Overview;
             item.EndDate = info.EndDate;
             item.EndDate = info.EndDate;
+            item.Genres = info.Genres;
 
 
             var recording = (ILiveTvRecording)item;
             var recording = (ILiveTvRecording)item;
 
 
-            recording.RecordingInfo = info;
+            recording.ProgramId = _tvDtoService.GetInternalProgramId(serviceName, info.ProgramId).ToString("N");
+            recording.Audio = info.Audio;
+            recording.ChannelType = info.ChannelType;
+            recording.EndDate = info.EndDate;
+            recording.EpisodeTitle = info.EpisodeTitle;
+            recording.ProviderImagePath = info.ImagePath;
+            recording.ProviderImageUrl = info.ImageUrl;
+            recording.IsHD = info.IsHD;
+            recording.IsKids = info.IsKids;
+            recording.IsLive = info.IsLive;
+            recording.IsMovie = info.IsMovie;
+            recording.IsNews = info.IsNews;
+            recording.IsPremiere = info.IsPremiere;
+            recording.IsRepeat = info.IsRepeat;
+            recording.IsSeries = info.IsSeries;
+            recording.IsSports = info.IsSports;
+            recording.OriginalAirDate = info.OriginalAirDate;
+            recording.SeriesTimerId = info.SeriesTimerId;
+            recording.StartDate = info.StartDate;
+            recording.Status = info.Status;
+
             recording.ServiceName = serviceName;
             recording.ServiceName = serviceName;
 
 
             var originalPath = item.Path;
             var originalPath = item.Path;
@@ -676,15 +700,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv
 
 
             var pathChanged = !string.Equals(originalPath, item.Path);
             var pathChanged = !string.Equals(originalPath, item.Path);
 
 
-            await item.RefreshMetadata(new MetadataRefreshOptions
+            if (isNew)
             {
             {
-                ForceSave = isNew || pathChanged
-
-            }, cancellationToken);
+                await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
+            }
+            else if (pathChanged)
+            {
+                await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
+            }
 
 
-            _libraryManager.RegisterItem(item);
+            _providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions());
 
 
-            return recording;
+            return item.Id;
         }
         }
 
 
         public async Task<BaseItemDto> GetProgram(string id, CancellationToken cancellationToken, User user = null)
         public async Task<BaseItemDto> GetProgram(string id, CancellationToken cancellationToken, User user = null)
@@ -1006,8 +1033,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 progress.Report(100 * percent);
                 progress.Report(100 * percent);
             }
             }
 
 
-            await CleanDatabaseInternal(newChannelIdList, typeof(LiveTvChannel).Name, progress, cancellationToken).ConfigureAwait(false);
-            await CleanDatabaseInternal(newProgramIdList, typeof(LiveTvProgram).Name, progress, cancellationToken).ConfigureAwait(false);
+            await CleanDatabaseInternal(newChannelIdList, new[] { typeof(LiveTvChannel).Name }, progress, cancellationToken).ConfigureAwait(false);
+            await CleanDatabaseInternal(newProgramIdList, new[] { typeof(LiveTvProgram).Name }, progress, cancellationToken).ConfigureAwait(false);
 
 
             // Load these now which will prefetch metadata
             // Load these now which will prefetch metadata
             var dtoOptions = new DtoOptions();
             var dtoOptions = new DtoOptions();
@@ -1017,7 +1044,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             progress.Report(100);
             progress.Report(100);
         }
         }
 
 
-        private async Task<Tuple<List<Guid>,List<Guid>>> RefreshChannelsInternal(ILiveTvService service, IProgress<double> progress, CancellationToken cancellationToken)
+        private async Task<Tuple<List<Guid>, List<Guid>>> RefreshChannelsInternal(ILiveTvService service, IProgress<double> progress, CancellationToken cancellationToken)
         {
         {
             progress.Report(10);
             progress.Report(10);
 
 
@@ -1103,14 +1130,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             }
             }
             progress.Report(100);
             progress.Report(100);
 
 
-            return new Tuple<List<Guid>,List<Guid>>(channels, programs);
+            return new Tuple<List<Guid>, List<Guid>>(channels, programs);
         }
         }
 
 
-        private async Task CleanDatabaseInternal(List<Guid> currentIdList, string typeName, IProgress<double> progress, CancellationToken cancellationToken)
+        private async Task CleanDatabaseInternal(List<Guid> currentIdList, string[] validTypes, IProgress<double> progress, CancellationToken cancellationToken)
         {
         {
             var list = _itemRepo.GetItemIds(new InternalItemsQuery
             var list = _itemRepo.GetItemIds(new InternalItemsQuery
             {
             {
-                IncludeItemTypes = new[] { typeName }
+                IncludeItemTypes = validTypes
 
 
             }).Items.ToList();
             }).Items.ToList();
 
 
@@ -1163,64 +1190,103 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             return channels.Select(i => new Tuple<string, ChannelInfo>(service.Name, i));
             return channels.Select(i => new Tuple<string, ChannelInfo>(service.Name, i));
         }
         }
 
 
-        public async Task<QueryResult<BaseItem>> GetInternalRecordings(RecordingQuery query, CancellationToken cancellationToken)
+        private DateTime _lastRecordingRefreshTime;
+        private async Task RefreshRecordings(CancellationToken cancellationToken)
         {
         {
-            var tasks = _services.Select(async i =>
+            const int cacheMinutes = 5;
+
+            if ((DateTime.UtcNow - _lastRecordingRefreshTime).TotalMinutes < cacheMinutes)
             {
             {
-                try
+                return;
+            }
+
+            await _refreshRecordingsLock.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+            try
+            {
+                if ((DateTime.UtcNow - _lastRecordingRefreshTime).TotalMinutes < cacheMinutes)
                 {
                 {
-                    var recs = await i.GetRecordingsAsync(cancellationToken).ConfigureAwait(false);
-                    return recs.Select(r => new Tuple<RecordingInfo, ILiveTvService>(r, i));
+                    return;
                 }
                 }
-                catch (Exception ex)
+
+                var tasks = _services.Select(async i =>
                 {
                 {
-                    _logger.ErrorException("Error getting recordings", ex);
-                    return new List<Tuple<RecordingInfo, ILiveTvService>>();
-                }
-            });
-            var results = await Task.WhenAll(tasks).ConfigureAwait(false);
-            var recordings = results.SelectMany(i => i.ToList());
+                    try
+                    {
+                        var recs = await i.GetRecordingsAsync(cancellationToken).ConfigureAwait(false);
+                        return recs.Select(r => new Tuple<RecordingInfo, ILiveTvService>(r, i));
+                    }
+                    catch (Exception ex)
+                    {
+                        _logger.ErrorException("Error getting recordings", ex);
+                        return new List<Tuple<RecordingInfo, ILiveTvService>>();
+                    }
+                });
 
 
-            var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
+                var results = await Task.WhenAll(tasks).ConfigureAwait(false);
+
+                var recordingTasks = results.SelectMany(i => i.ToList()).Select(i => CreateRecordingRecord(i.Item1, i.Item2.Name, cancellationToken));
+
+                var idList = await Task.WhenAll(recordingTasks).ConfigureAwait(false);
+
+                CleanDatabaseInternal(idList.ToList(), new[] { typeof(LiveTvVideoRecording).Name, typeof(LiveTvAudioRecording).Name }, new Progress<double>(), cancellationToken).ConfigureAwait(false);
 
 
+                _lastRecordingRefreshTime = DateTime.UtcNow;
+            }
+            finally
+            {
+                _refreshRecordingsLock.Release();
+            }
+        }
+
+        public async Task<QueryResult<BaseItem>> GetInternalRecordings(RecordingQuery query, CancellationToken cancellationToken)
+        {
+            var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
             if (user != null && !IsLiveTvEnabled(user))
             if (user != null && !IsLiveTvEnabled(user))
             {
             {
-                recordings = new List<Tuple<RecordingInfo, ILiveTvService>>();
+                return new QueryResult<BaseItem>();
             }
             }
 
 
-            if (!string.IsNullOrEmpty(query.ChannelId))
+            await RefreshRecordings(cancellationToken).ConfigureAwait(false);
+
+            var internalQuery = new InternalItemsQuery
             {
             {
-                var guid = new Guid(query.ChannelId);
+                IncludeItemTypes = new[] { typeof(LiveTvVideoRecording).Name, typeof(LiveTvAudioRecording).Name }
+            };
 
 
-                recordings = recordings
-                    .Where(i => _tvDtoService.GetInternalChannelId(i.Item2.Name, i.Item1.ChannelId) == guid);
+            if (!string.IsNullOrEmpty(query.ChannelId))
+            {
+                internalQuery.ChannelIds = new[] { query.ChannelId };
             }
             }
 
 
+            var queryResult = _libraryManager.GetItems(internalQuery);
+            IEnumerable<ILiveTvRecording> recordings = queryResult.Items.Cast<ILiveTvRecording>();
+
             if (!string.IsNullOrEmpty(query.Id))
             if (!string.IsNullOrEmpty(query.Id))
             {
             {
                 var guid = new Guid(query.Id);
                 var guid = new Guid(query.Id);
 
 
                 recordings = recordings
                 recordings = recordings
-                    .Where(i => _tvDtoService.GetInternalRecordingId(i.Item2.Name, i.Item1.Id) == guid);
+                    .Where(i => i.Id == guid);
             }
             }
 
 
             if (!string.IsNullOrEmpty(query.GroupId))
             if (!string.IsNullOrEmpty(query.GroupId))
             {
             {
                 var guid = new Guid(query.GroupId);
                 var guid = new Guid(query.GroupId);
 
 
-                recordings = recordings.Where(i => GetRecordingGroupIds(i.Item1).Contains(guid));
+                recordings = recordings.Where(i => GetRecordingGroupIds(i).Contains(guid));
             }
             }
 
 
             if (query.IsInProgress.HasValue)
             if (query.IsInProgress.HasValue)
             {
             {
                 var val = query.IsInProgress.Value;
                 var val = query.IsInProgress.Value;
-                recordings = recordings.Where(i => (i.Item1.Status == RecordingStatus.InProgress) == val);
+                recordings = recordings.Where(i => (i.Status == RecordingStatus.InProgress) == val);
             }
             }
 
 
             if (query.Status.HasValue)
             if (query.Status.HasValue)
             {
             {
                 var val = query.Status.Value;
                 var val = query.Status.Value;
-                recordings = recordings.Where(i => (i.Item1.Status == val));
+                recordings = recordings.Where(i => (i.Status == val));
             }
             }
 
 
             if (!string.IsNullOrEmpty(query.SeriesTimerId))
             if (!string.IsNullOrEmpty(query.SeriesTimerId))
@@ -1228,21 +1294,19 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 var guid = new Guid(query.SeriesTimerId);
                 var guid = new Guid(query.SeriesTimerId);
 
 
                 recordings = recordings
                 recordings = recordings
-                    .Where(i => _tvDtoService.GetInternalSeriesTimerId(i.Item2.Name, i.Item1.SeriesTimerId) == guid);
+                    .Where(i => _tvDtoService.GetInternalSeriesTimerId(i.ServiceName, i.SeriesTimerId) == guid);
             }
             }
 
 
-            recordings = recordings.OrderByDescending(i => i.Item1.StartDate);
-
-            IEnumerable<ILiveTvRecording> entities = await GetEntities(recordings, cancellationToken).ConfigureAwait(false);
-
             if (user != null)
             if (user != null)
             {
             {
                 var currentUser = user;
                 var currentUser = user;
-                entities = entities.Where(i => i.IsParentalAllowed(currentUser));
+                recordings = recordings.Where(i => i.IsParentalAllowed(currentUser));
             }
             }
 
 
-            var entityList = entities.ToList();
-            entities = entityList;
+            recordings = recordings.OrderByDescending(i => i.StartDate);
+
+            var entityList = recordings.ToList();
+            IEnumerable<ILiveTvRecording> entities = entityList;
 
 
             if (query.StartIndex.HasValue)
             if (query.StartIndex.HasValue)
             {
             {
@@ -1270,7 +1334,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
 
 
             dto.Id = _tvDtoService.GetInternalProgramId(service.Name, program.ExternalId).ToString("N");
             dto.Id = _tvDtoService.GetInternalProgramId(service.Name, program.ExternalId).ToString("N");
 
 
-            dto.ChannelId = channel.Id.ToString("N");
+            dto.ChannelId = item.ChannelId;
 
 
             dto.StartDate = program.StartDate;
             dto.StartDate = program.StartDate;
             dto.IsRepeat = program.IsRepeat;
             dto.IsRepeat = program.IsRepeat;
@@ -1303,16 +1367,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             var recording = (ILiveTvRecording)item;
             var recording = (ILiveTvRecording)item;
             var service = GetService(recording);
             var service = GetService(recording);
 
 
-            var channel = string.IsNullOrEmpty(recording.RecordingInfo.ChannelId) ? null : GetInternalChannel(_tvDtoService.GetInternalChannelId(service.Name, recording.RecordingInfo.ChannelId));
+            var channel = string.IsNullOrWhiteSpace(recording.ChannelId) ? null : GetInternalChannel(recording.ChannelId);
 
 
-            var info = recording.RecordingInfo;
+            var info = recording;
 
 
-            dto.Id = _tvDtoService.GetInternalRecordingId(service.Name, info.Id).ToString("N");
+            dto.Id = item.Id.ToString("N");
             dto.SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId)
             dto.SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId)
                 ? null
                 ? null
                 : _tvDtoService.GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N");
                 : _tvDtoService.GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N");
 
 
-            dto.ChannelId = _tvDtoService.GetInternalChannelId(service.Name, info.ChannelId).ToString("N");
+            dto.ChannelId = item.ChannelId;
 
 
             dto.StartDate = info.StartDate;
             dto.StartDate = info.StartDate;
             dto.RecordingStatus = info.Status;
             dto.RecordingStatus = info.Status;
@@ -1344,11 +1408,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToList();
                 dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToList();
             }
             }
 
 
-            if (info.Status == RecordingStatus.InProgress)
+            if (info.Status == RecordingStatus.InProgress && info.EndDate.HasValue)
             {
             {
                 var now = DateTime.UtcNow.Ticks;
                 var now = DateTime.UtcNow.Ticks;
                 var start = info.StartDate.Ticks;
                 var start = info.StartDate.Ticks;
-                var end = info.EndDate.Ticks;
+                var end = info.EndDate.Value.Ticks;
 
 
                 var pct = now - start;
                 var pct = now - start;
                 pct /= end;
                 pct /= end;
@@ -1356,10 +1420,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 dto.CompletionPercentage = pct;
                 dto.CompletionPercentage = pct;
             }
             }
 
 
-            if (!string.IsNullOrEmpty(info.ProgramId))
-            {
-                dto.ProgramId = _tvDtoService.GetInternalProgramId(service.Name, info.ProgramId).ToString("N");
-            }
+            dto.ProgramId = info.ProgramId;
 
 
             if (channel != null)
             if (channel != null)
             {
             {
@@ -1394,13 +1455,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             };
             };
         }
         }
 
 
-        private Task<ILiveTvRecording[]> GetEntities(IEnumerable<Tuple<RecordingInfo, ILiveTvService>> recordings, CancellationToken cancellationToken)
-        {
-            var tasks = recordings.Select(i => GetRecording(i.Item1, i.Item2.Name, cancellationToken));
-
-            return Task.WhenAll(tasks);
-        }
-
         public async Task<QueryResult<TimerInfoDto>> GetTimers(TimerQuery query, CancellationToken cancellationToken)
         public async Task<QueryResult<TimerInfoDto>> GetTimers(TimerQuery query, CancellationToken cancellationToken)
         {
         {
             var tasks = _services.Select(async i =>
             var tasks = _services.Select(async i =>
@@ -1468,7 +1522,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
 
 
             var service = GetService(recording.ServiceName);
             var service = GetService(recording.ServiceName);
 
 
-            await service.DeleteRecordingAsync(recording.RecordingInfo.Id, CancellationToken.None).ConfigureAwait(false);
+            await service.DeleteRecordingAsync(recording.ExternalId, CancellationToken.None).ConfigureAwait(false);
+            _lastRecordingRefreshTime = DateTime.MinValue;
         }
         }
 
 
         public async Task CancelTimer(string id)
         public async Task CancelTimer(string id)
@@ -1483,6 +1538,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             var service = GetService(timer.ServiceName);
             var service = GetService(timer.ServiceName);
 
 
             await service.CancelTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false);
             await service.CancelTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false);
+            _lastRecordingRefreshTime = DateTime.MinValue;
         }
         }
 
 
         public async Task CancelSeriesTimer(string id)
         public async Task CancelSeriesTimer(string id)
@@ -1497,6 +1553,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             var service = GetService(timer.ServiceName);
             var service = GetService(timer.ServiceName);
 
 
             await service.CancelSeriesTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false);
             await service.CancelSeriesTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false);
+            _lastRecordingRefreshTime = DateTime.MinValue;
         }
         }
 
 
         public async Task<BaseItemDto> GetRecording(string id, DtoOptions options, CancellationToken cancellationToken, User user = null)
         public async Task<BaseItemDto> GetRecording(string id, DtoOptions options, CancellationToken cancellationToken, User user = null)
@@ -1705,6 +1762,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             info.Priority = defaultValues.Priority;
             info.Priority = defaultValues.Priority;
 
 
             await service.CreateTimerAsync(info, cancellationToken).ConfigureAwait(false);
             await service.CreateTimerAsync(info, cancellationToken).ConfigureAwait(false);
+            _lastRecordingRefreshTime = DateTime.MinValue;
         }
         }
 
 
         public async Task CreateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken)
         public async Task CreateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken)
@@ -1718,6 +1776,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             info.Priority = defaultValues.Priority;
             info.Priority = defaultValues.Priority;
 
 
             await service.CreateSeriesTimerAsync(info, cancellationToken).ConfigureAwait(false);
             await service.CreateSeriesTimerAsync(info, cancellationToken).ConfigureAwait(false);
+            _lastRecordingRefreshTime = DateTime.MinValue;
         }
         }
 
 
         public async Task UpdateTimer(TimerInfoDto timer, CancellationToken cancellationToken)
         public async Task UpdateTimer(TimerInfoDto timer, CancellationToken cancellationToken)
@@ -1727,6 +1786,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             var service = GetService(timer.ServiceName);
             var service = GetService(timer.ServiceName);
 
 
             await service.UpdateTimerAsync(info, cancellationToken).ConfigureAwait(false);
             await service.UpdateTimerAsync(info, cancellationToken).ConfigureAwait(false);
+            _lastRecordingRefreshTime = DateTime.MinValue;
         }
         }
 
 
         public async Task UpdateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken)
         public async Task UpdateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken)
@@ -1736,9 +1796,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             var service = GetService(timer.ServiceName);
             var service = GetService(timer.ServiceName);
 
 
             await service.UpdateSeriesTimerAsync(info, cancellationToken).ConfigureAwait(false);
             await service.UpdateSeriesTimerAsync(info, cancellationToken).ConfigureAwait(false);
+            _lastRecordingRefreshTime = DateTime.MinValue;
         }
         }
 
 
-        private IEnumerable<string> GetRecordingGroupNames(RecordingInfo recording)
+        private IEnumerable<string> GetRecordingGroupNames(ILiveTvRecording recording)
         {
         {
             var list = new List<string>();
             var list = new List<string>();
 
 
@@ -1775,7 +1836,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             return list;
             return list;
         }
         }
 
 
-        private List<Guid> GetRecordingGroupIds(RecordingInfo recording)
+        private List<Guid> GetRecordingGroupIds(ILiveTvRecording recording)
         {
         {
             return GetRecordingGroupNames(recording).Select(i => i.ToLower()
             return GetRecordingGroupNames(recording).Select(i => i.ToLower()
                 .GetMD5())
                 .GetMD5())
@@ -1795,7 +1856,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             var groups = new List<BaseItemDto>();
             var groups = new List<BaseItemDto>();
 
 
             var series = recordings
             var series = recordings
-                .Where(i => i.RecordingInfo.IsSeries)
+                .Where(i => i.IsSeries)
                 .ToLookup(i => i.Name, StringComparer.OrdinalIgnoreCase)
                 .ToLookup(i => i.Name, StringComparer.OrdinalIgnoreCase)
                 .ToList();
                 .ToList();
 
 
@@ -1808,31 +1869,31 @@ namespace MediaBrowser.Server.Implementations.LiveTv
             groups.Add(new BaseItemDto
             groups.Add(new BaseItemDto
             {
             {
                 Name = "Kids",
                 Name = "Kids",
-                RecordingCount = recordings.Count(i => i.RecordingInfo.IsKids)
+                RecordingCount = recordings.Count(i => i.IsKids)
             });
             });
 
 
             groups.Add(new BaseItemDto
             groups.Add(new BaseItemDto
             {
             {
                 Name = "Movies",
                 Name = "Movies",
-                RecordingCount = recordings.Count(i => i.RecordingInfo.IsMovie)
+                RecordingCount = recordings.Count(i => i.IsMovie)
             });
             });
 
 
             groups.Add(new BaseItemDto
             groups.Add(new BaseItemDto
             {
             {
                 Name = "News",
                 Name = "News",
-                RecordingCount = recordings.Count(i => i.RecordingInfo.IsNews)
+                RecordingCount = recordings.Count(i => i.IsNews)
             });
             });
 
 
             groups.Add(new BaseItemDto
             groups.Add(new BaseItemDto
             {
             {
                 Name = "Sports",
                 Name = "Sports",
-                RecordingCount = recordings.Count(i => i.RecordingInfo.IsSports)
+                RecordingCount = recordings.Count(i => i.IsSports)
             });
             });
 
 
             groups.Add(new BaseItemDto
             groups.Add(new BaseItemDto
             {
             {
                 Name = "Others",
                 Name = "Others",
-                RecordingCount = recordings.Count(i => !i.RecordingInfo.IsSports && !i.RecordingInfo.IsNews && !i.RecordingInfo.IsMovie && !i.RecordingInfo.IsKids && !i.RecordingInfo.IsSeries)
+                RecordingCount = recordings.Count(i => !i.IsSports && !i.IsNews && !i.IsMovie && !i.IsKids && !i.IsSeries)
             });
             });
 
 
             groups = groups
             groups = groups

+ 7 - 7
MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs

@@ -36,17 +36,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv
 
 
             var imageResponse = new DynamicImageResponse();
             var imageResponse = new DynamicImageResponse();
 
 
-            if (!string.IsNullOrEmpty(liveTvItem.RecordingInfo.ImagePath))
+            if (!string.IsNullOrEmpty(liveTvItem.ProviderImagePath))
             {
             {
-                imageResponse.Path = liveTvItem.RecordingInfo.ImagePath;
+                imageResponse.Path = liveTvItem.ProviderImagePath;
                 imageResponse.HasImage = true;
                 imageResponse.HasImage = true;
             }
             }
-            else if (!string.IsNullOrEmpty(liveTvItem.RecordingInfo.ImageUrl))
+            else if (!string.IsNullOrEmpty(liveTvItem.ProviderImageUrl))
             {
             {
                 var options = new HttpRequestOptions
                 var options = new HttpRequestOptions
                 {
                 {
                     CancellationToken = cancellationToken,
                     CancellationToken = cancellationToken,
-                    Url = liveTvItem.RecordingInfo.ImageUrl
+                    Url = liveTvItem.ProviderImageUrl
                 };
                 };
 
 
                 var response = await _httpClient.GetResponse(options).ConfigureAwait(false);
                 var response = await _httpClient.GetResponse(options).ConfigureAwait(false);
@@ -62,7 +62,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                     _logger.Error("Provider did not return an image content type.");
                     _logger.Error("Provider did not return an image content type.");
                 }
                 }
             }
             }
-            else if (liveTvItem.RecordingInfo.HasImage ?? true)
+            else
             {
             {
                 var service = _liveTvManager.Services.FirstOrDefault(i => string.Equals(i.Name, liveTvItem.ServiceName, StringComparison.OrdinalIgnoreCase));
                 var service = _liveTvManager.Services.FirstOrDefault(i => string.Equals(i.Name, liveTvItem.ServiceName, StringComparison.OrdinalIgnoreCase));
 
 
@@ -70,7 +70,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 {
                 {
                     try
                     try
                     {
                     {
-                        var response = await service.GetRecordingImageAsync(liveTvItem.RecordingInfo.Id, cancellationToken).ConfigureAwait(false);
+                        var response = await service.GetRecordingImageAsync(liveTvItem.ExternalId, cancellationToken).ConfigureAwait(false);
 
 
                         if (response != null)
                         if (response != null)
                         {
                         {
@@ -109,7 +109,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
 
 
             if (liveTvItem != null)
             if (liveTvItem != null)
             {
             {
-                return !liveTvItem.HasImage(ImageType.Primary) && (liveTvItem.RecordingInfo.HasImage ?? true);
+                return !liveTvItem.HasImage(ImageType.Primary) && (!string.IsNullOrWhiteSpace(liveTvItem.ProviderImagePath) || !string.IsNullOrWhiteSpace(liveTvItem.ProviderImageUrl));
             }
             }
             return false;
             return false;
         }
         }

+ 17 - 11
MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs

@@ -759,14 +759,17 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 whereClauses.Add("IsSports=@IsSports");
                 whereClauses.Add("IsSports=@IsSports");
                 cmd.Parameters.Add(cmd, "@IsSports", DbType.Boolean).Value = query.IsSports;
                 cmd.Parameters.Add(cmd, "@IsSports", DbType.Boolean).Value = query.IsSports;
             }
             }
-            if (query.IncludeItemTypes.Length == 1)
+
+            var includeTypes = query.IncludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray();
+
+            if (includeTypes.Length == 1)
             {
             {
                 whereClauses.Add("type=@type");
                 whereClauses.Add("type=@type");
-                cmd.Parameters.Add(cmd, "@type", DbType.String).Value = MapIncludeItemType(query.IncludeItemTypes[0]);
+                cmd.Parameters.Add(cmd, "@type", DbType.String).Value = includeTypes[0];
             }
             }
-            if (query.IncludeItemTypes.Length > 1)
+            if (includeTypes.Length > 1)
             {
             {
-                var inClause = string.Join(",", query.IncludeItemTypes.Select(i => "'" + MapIncludeItemType(i) + "'").ToArray());
+                var inClause = string.Join(",", includeTypes.Select(i => "'" + i + "'").ToArray());
                 whereClauses.Add(string.Format("type in ({0})", inClause));
                 whereClauses.Add(string.Format("type in ({0})", inClause));
             }
             }
             if (query.ChannelIds.Length == 1)
             if (query.ChannelIds.Length == 1)
@@ -818,7 +821,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 {
                 {
                     whereClauses.Add("(StartDate>@IsAiringDate OR EndDate < @IsAiringDate)");
                     whereClauses.Add("(StartDate>@IsAiringDate OR EndDate < @IsAiringDate)");
                     cmd.Parameters.Add(cmd, "@IsAiringDate", DbType.Date).Value = DateTime.UtcNow;
                     cmd.Parameters.Add(cmd, "@IsAiringDate", DbType.Date).Value = DateTime.UtcNow;
-                } 
+                }
             }
             }
 
 
             if (addPaging)
             if (addPaging)
@@ -839,21 +842,24 @@ namespace MediaBrowser.Server.Implementations.Persistence
         }
         }
 
 
         // Not crazy about having this all the way down here, but at least it's in one place
         // Not crazy about having this all the way down here, but at least it's in one place
-        readonly Dictionary<string, string> _types = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
+        readonly Dictionary<string, string[]> _types = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase)
             {
             {
-                {typeof(LiveTvProgram).Name, typeof(LiveTvProgram).FullName},
-                {typeof(LiveTvChannel).Name, typeof(LiveTvChannel).FullName}
+                {typeof(LiveTvProgram).Name, new []{typeof(LiveTvProgram).FullName}},
+                {typeof(LiveTvChannel).Name, new []{typeof(LiveTvChannel).FullName}},
+                {typeof(LiveTvVideoRecording).Name, new []{typeof(LiveTvVideoRecording).FullName}},
+                {typeof(LiveTvAudioRecording).Name, new []{typeof(LiveTvAudioRecording).FullName}},
+                {"Recording", new []{typeof(LiveTvAudioRecording).FullName, typeof(LiveTvVideoRecording).FullName}}
             };
             };
 
 
-        private string MapIncludeItemType(string value)
+        private IEnumerable<string> MapIncludeItemTypes(string value)
         {
         {
-            string result;
+            string[] result;
             if (_types.TryGetValue(value, out result))
             if (_types.TryGetValue(value, out result))
             {
             {
                 return result;
                 return result;
             }
             }
 
 
-            return value;
+            return new[] { value };
         }
         }
 
 
         public IEnumerable<Guid> GetItemIdsOfType(Type type)
         public IEnumerable<Guid> GetItemIdsOfType(Type type)

+ 5 - 5
MediaBrowser.Server.Implementations/Session/SessionManager.cs

@@ -1528,16 +1528,16 @@ namespace MediaBrowser.Server.Implementations.Session
             }
             }
 
 
             var recording = item as ILiveTvRecording;
             var recording = item as ILiveTvRecording;
-            if (recording != null && recording.RecordingInfo != null)
+            if (recording != null)
             {
             {
-                if (recording.RecordingInfo.IsSeries)
+                if (recording.IsSeries)
                 {
                 {
-                    info.Name = recording.RecordingInfo.EpisodeTitle;
-                    info.SeriesName = recording.RecordingInfo.Name;
+                    info.Name = recording.EpisodeTitle;
+                    info.SeriesName = recording.Name;
 
 
                     if (string.IsNullOrWhiteSpace(info.Name))
                     if (string.IsNullOrWhiteSpace(info.Name))
                     {
                     {
-                        info.Name = recording.RecordingInfo.Name;
+                        info.Name = recording.Name;
                     }
                     }
                 }
                 }
             }
             }

+ 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.622</version>
+        <version>3.0.624</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 Emby Theater and Emby Server. Not intended for plugin developer consumption.</description>
         <description>Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.</description>
         <copyright>Copyright © Emby 2013</copyright>
         <copyright>Copyright © Emby 2013</copyright>
         <dependencies>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.622" />
+            <dependency id="MediaBrowser.Common" version="3.0.624" />
             <dependency id="NLog" version="3.2.1" />
             <dependency id="NLog" version="3.2.1" />
             <dependency id="SimpleInjector" version="2.8.0" />
             <dependency id="SimpleInjector" version="2.8.0" />
         </dependencies>
         </dependencies>

+ 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.622</version>
+        <version>3.0.624</version>
         <title>MediaBrowser.Common</title>
         <title>MediaBrowser.Common</title>
         <authors>Emby Team</authors>
         <authors>Emby Team</authors>
         <owners>ebr,Luke,scottisafool</owners>
         <owners>ebr,Luke,scottisafool</owners>

+ 1 - 1
Nuget/MediaBrowser.Model.Signed.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.Model.Signed</id>
         <id>MediaBrowser.Model.Signed</id>
-        <version>3.0.622</version>
+        <version>3.0.624</version>
         <title>MediaBrowser.Model - Signed Edition</title>
         <title>MediaBrowser.Model - Signed Edition</title>
         <authors>Emby Team</authors>
         <authors>Emby 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.622</version>
+        <version>3.0.624</version>
         <title>Media Browser.Server.Core</title>
         <title>Media Browser.Server.Core</title>
         <authors>Emby Team</authors>
         <authors>Emby 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 Emby Server.</description>
         <description>Contains core components required to build plugins for Emby Server.</description>
         <copyright>Copyright © Emby 2013</copyright>
         <copyright>Copyright © Emby 2013</copyright>
         <dependencies>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.622" />
+            <dependency id="MediaBrowser.Common" version="3.0.624" />
 			<dependency id="Interfaces.IO" version="1.0.0.5" />
 			<dependency id="Interfaces.IO" version="1.0.0.5" />
         </dependencies>
         </dependencies>
     </metadata>
     </metadata>