Преглед на файлове

updated live tv + nuget

Luke Pulverenti преди 11 години
родител
ревизия
7b6819846d

+ 14 - 14
MediaBrowser.Api/LiveTv/LiveTvService.cs

@@ -22,6 +22,12 @@ namespace MediaBrowser.Api.LiveTv
     {
         [ApiMember(Name = "ServiceName", Description = "Optional filter by service.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
         public string ServiceName { get; set; }
+
+        [ApiMember(Name = "Type", Description = "Optional filter by channel type.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+        public ChannelType? Type { get; set; }
+
+        [ApiMember(Name = "UserId", Description = "Optional filter by channel user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+        public string UserId { get; set; }
     }
 
     [Route("/LiveTv/Recordings", "GET")]
@@ -83,22 +89,16 @@ namespace MediaBrowser.Api.LiveTv
 
         public object Get(GetChannels request)
         {
-            var result = GetChannelsAsync(request).Result;
-
-            return ToOptimizedResult(result.ToList());
-        }
-
-        private async Task<IEnumerable<ChannelInfoDto>> GetChannelsAsync(GetChannels request)
-        {
-            var services = GetServices(request.ServiceName);
-
-            var tasks = services.Select(i => i.GetChannelsAsync(CancellationToken.None));
+            var result = _liveTvManager.GetChannels(new ChannelQuery
+            {
+                ChannelType = request.Type,
+                ServiceName = request.ServiceName,
+                UserId = request.UserId
 
-            var channelLists = await Task.WhenAll(tasks).ConfigureAwait(false);
+            })
+            .Select(_liveTvManager.GetChannelInfoDto);
 
-            // Aggregate all channels from all services
-            return channelLists.SelectMany(i => i)
-                .Select(_liveTvManager.GetChannelInfoDto);
+            return ToOptimizedResult(result.ToList());
         }
 
         public object Get(GetRecordings request)

+ 2 - 2
MediaBrowser.Controller/Entities/Genre.cs

@@ -1,7 +1,7 @@
-using System.Runtime.Serialization;
-using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Dto;
 using System;
 using System.Collections.Generic;
+using System.Runtime.Serialization;
 
 namespace MediaBrowser.Controller.Entities
 {

+ 65 - 0
MediaBrowser.Controller/LiveTv/Channel.cs

@@ -0,0 +1,65 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.LiveTv;
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+
+namespace MediaBrowser.Controller.LiveTv
+{
+    public class Channel : BaseItem, IItemByName
+    {
+        public Channel()
+        {
+            UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
+        }
+
+        /// <summary>
+        /// Gets the user data key.
+        /// </summary>
+        /// <returns>System.String.</returns>
+        public override string GetUserDataKey()
+        {
+            return "Channel-" + Name;
+        }
+
+        [IgnoreDataMember]
+        public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
+
+        /// <summary>
+        /// Gets or sets the number.
+        /// </summary>
+        /// <value>The number.</value>
+        public string ChannelNumber { get; set; }
+
+        /// <summary>
+        /// Get or sets the Id.
+        /// </summary>
+        /// <value>The id of the channel.</value>
+        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; }
+
+        /// <summary>
+        /// Gets or sets the type of the channel.
+        /// </summary>
+        /// <value>The type of the channel.</value>
+        public ChannelType ChannelType { get; set; }
+
+        protected override string CreateSortName()
+        {
+            double number = 0;
+
+            if (!string.IsNullOrEmpty(ChannelNumber))
+            {
+                double.TryParse(ChannelNumber, out number);
+            }
+
+            return number.ToString("000-") + (Name ?? string.Empty);
+        }
+    }
+}

+ 19 - 5
MediaBrowser.Controller/LiveTv/ILiveTvManager.cs

@@ -1,5 +1,4 @@
-using System.Threading.Tasks;
-using MediaBrowser.Model.LiveTv;
+using MediaBrowser.Model.LiveTv;
 using System.Collections.Generic;
 
 namespace MediaBrowser.Controller.LiveTv
@@ -22,10 +21,25 @@ namespace MediaBrowser.Controller.LiveTv
         void AddParts(IEnumerable<ILiveTvService> services);
 
         /// <summary>
-        /// Gets the channel info dto.
+        /// Gets the channels.
         /// </summary>
-        /// <param name="info">The info.</param>
+        /// <param name="query">The query.</param>
+        /// <returns>IEnumerable{Channel}.</returns>
+        IEnumerable<Channel> GetChannels(ChannelQuery query);
+
+        /// <summary>
+        /// Gets the channel information dto.
+        /// </summary>
+        /// <param name="info">The information.</param>
         /// <returns>ChannelInfoDto.</returns>
-        ChannelInfoDto GetChannelInfoDto(ChannelInfo info);
+        ChannelInfoDto GetChannelInfoDto(Channel info);
+
+        /// <summary>
+        /// Gets the channel.
+        /// </summary>
+        /// <param name="serviceName">Name of the service.</param>
+        /// <param name="channelId">The channel identifier.</param>
+        /// <returns>Channel.</returns>
+        Channel GetChannel(string serviceName, string channelId);
     }
 }

+ 3 - 3
MediaBrowser.Controller/LiveTv/ILiveTvService.cs

@@ -1,6 +1,6 @@
-using System;
-using System.IO;
+using MediaBrowser.Common.Net;
 using MediaBrowser.Model.LiveTv;
+using System;
 using System.Collections.Generic;
 using System.Threading;
 using System.Threading.Tasks;
@@ -50,7 +50,7 @@ namespace MediaBrowser.Controller.LiveTv
         /// <param name="channelId">The channel identifier.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{Stream}.</returns>
-        Task<Stream> GetChannelImageAsync(string channelId, CancellationToken cancellationToken);
+        Task<HttpResponseInfo> GetChannelImageAsync(string channelId, CancellationToken cancellationToken);
 
         /// <summary>
         /// Gets the recordings asynchronous.

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

@@ -104,6 +104,7 @@
     <Compile Include="Library\ItemUpdateType.cs" />
     <Compile Include="Library\IUserDataManager.cs" />
     <Compile Include="Library\UserDataSaveEventArgs.cs" />
+    <Compile Include="LiveTv\Channel.cs" />
     <Compile Include="LiveTv\ChannelInfo.cs" />
     <Compile Include="LiveTv\ILiveTvManager.cs" />
     <Compile Include="LiveTv\ILiveTvService.cs" />

+ 3 - 0
MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj

@@ -230,6 +230,9 @@
     <Compile Include="..\MediaBrowser.Model\LiveTv\ChannelInfoDto.cs">
       <Link>LiveTv\ChannelInfoDto.cs</Link>
     </Compile>
+    <Compile Include="..\MediaBrowser.Model\LiveTv\ChannelQuery.cs">
+      <Link>LiveTv\ChannelQuery.cs</Link>
+    </Compile>
     <Compile Include="..\MediaBrowser.Model\LiveTv\ChannelType.cs">
       <Link>LiveTv\ChannelType.cs</Link>
     </Compile>

+ 3 - 0
MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj

@@ -217,6 +217,9 @@
     <Compile Include="..\MediaBrowser.Model\LiveTv\ChannelInfoDto.cs">
       <Link>LiveTv\ChannelInfoDto.cs</Link>
     </Compile>
+    <Compile Include="..\MediaBrowser.Model\LiveTv\ChannelQuery.cs">
+      <Link>LiveTv\ChannelQuery.cs</Link>
+    </Compile>
     <Compile Include="..\MediaBrowser.Model\LiveTv\ChannelType.cs">
       <Link>LiveTv\ChannelType.cs</Link>
     </Compile>

+ 8 - 1
MediaBrowser.Model/LiveTv/ChannelInfoDto.cs

@@ -1,4 +1,5 @@
-
+using System;
+
 namespace MediaBrowser.Model.LiveTv
 {
     /// <summary>
@@ -18,6 +19,12 @@ namespace MediaBrowser.Model.LiveTv
         /// <value>The identifier.</value>
         public string Id { get; set; }
 
+        /// <summary>
+        /// Gets or sets the logo image tag.
+        /// </summary>
+        /// <value>The logo image tag.</value>
+        public Guid? PrimaryImageTag { get; set; }
+        
         /// <summary>
         /// Gets or sets the number.
         /// </summary>

+ 27 - 0
MediaBrowser.Model/LiveTv/ChannelQuery.cs

@@ -0,0 +1,27 @@
+
+namespace MediaBrowser.Model.LiveTv
+{
+    /// <summary>
+    /// Class ChannelQuery.
+    /// </summary>
+    public class ChannelQuery
+    {
+        /// <summary>
+        /// Gets or sets the name of the service.
+        /// </summary>
+        /// <value>The name of the service.</value>
+        public string ServiceName { get; set; }
+
+        /// <summary>
+        /// Gets or sets the type of the channel.
+        /// </summary>
+        /// <value>The type of the channel.</value>
+        public ChannelType? ChannelType { get; set; }
+
+        /// <summary>
+        /// Gets or sets the user identifier.
+        /// </summary>
+        /// <value>The user identifier.</value>
+        public string UserId { get; set; }
+    }
+}

+ 2 - 1
MediaBrowser.Model/MediaBrowser.Model.csproj

@@ -61,6 +61,8 @@
     <Compile Include="Dto\ItemIndex.cs" />
     <Compile Include="Entities\PackageReviewInfo.cs" />
     <Compile Include="LiveTv\ChannelGuide.cs" />
+    <Compile Include="LiveTv\ChannelInfoDto.cs" />
+    <Compile Include="LiveTv\ChannelQuery.cs" />
     <Compile Include="LiveTv\ProgramInfo.cs" />
     <Compile Include="LiveTv\RecordingQuery.cs" />
     <Compile Include="Providers\ImageProviderInfo.cs" />
@@ -76,7 +78,6 @@
     <Compile Include="IO\IIsoManager.cs" />
     <Compile Include="IO\IIsoMount.cs" />
     <Compile Include="IO\IIsoMounter.cs" />
-    <Compile Include="LiveTv\ChannelInfoDto.cs" />
     <Compile Include="LiveTv\ChannelType.cs" />
     <Compile Include="LiveTv\LiveTvServiceInfo.cs" />
     <Compile Include="LiveTv\RecordingInfo.cs" />

+ 100 - 0
MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs

@@ -0,0 +1,100 @@
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Net;
+using System;
+using System.Linq;
+using System.Net;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.LiveTv
+{
+    public class ChannelImageProvider : BaseMetadataProvider
+    {
+        private readonly ILiveTvManager _liveTvManager;
+        private readonly IProviderManager _providerManager;
+
+        public ChannelImageProvider(ILogManager logManager, IServerConfigurationManager configurationManager, ILiveTvManager liveTvManager, IProviderManager providerManager)
+            : base(logManager, configurationManager)
+        {
+            _liveTvManager = liveTvManager;
+            _providerManager = providerManager;
+        }
+
+        public override bool Supports(BaseItem item)
+        {
+            return item is Channel;
+        }
+
+        protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
+        {
+            if (item.HasImage(ImageType.Primary))
+            {
+                return false;
+            }
+
+            return base.NeedsRefreshInternal(item, providerInfo);
+        }
+
+        public override async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
+        {
+            if (item.HasImage(ImageType.Primary))
+            {
+                SetLastRefreshed(item, DateTime.UtcNow);
+                return true;
+            }
+
+            try
+            {
+                await DownloadImage(item, cancellationToken).ConfigureAwait(false);
+            }
+            catch (HttpException ex)
+            {
+                // Don't fail the provider on a 404
+                if (!ex.StatusCode.HasValue || ex.StatusCode.Value != HttpStatusCode.NotFound)
+                {
+                    throw;
+                }
+            }
+
+
+            SetLastRefreshed(item, DateTime.UtcNow);
+            return true;
+        }
+
+        private async Task DownloadImage(BaseItem item, CancellationToken cancellationToken)
+        {
+            var channel = (Channel)item;
+
+            var service = _liveTvManager.Services.FirstOrDefault(i => string.Equals(i.Name, channel.ServiceName, StringComparison.OrdinalIgnoreCase));
+
+            if (service != null)
+            {
+                var response = await service.GetChannelImageAsync(channel.ChannelId, cancellationToken).ConfigureAwait(false);
+
+                // Dummy up the original url
+                var url = channel.ServiceName + channel.ChannelId;
+
+                await _providerManager.SaveImage(channel, response.Content, response.ContentType, ImageType.Primary, null, url, cancellationToken).ConfigureAwait(false);
+            }
+        }
+
+        public override MetadataProviderPriority Priority
+        {
+            get { return MetadataProviderPriority.Second; }
+        }
+
+        public override ItemUpdateType ItemUpdateType
+        {
+            get
+            {
+                return ItemUpdateType.ImageUpdate;
+            }
+        }
+    }
+}

+ 165 - 4
MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs

@@ -1,6 +1,18 @@
-using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.LiveTv;
+using MediaBrowser.Model.Logging;
+using System;
 using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
 
 namespace MediaBrowser.Server.Implementations.LiveTv
 {
@@ -9,7 +21,25 @@ namespace MediaBrowser.Server.Implementations.LiveTv
     /// </summary>
     public class LiveTvManager : ILiveTvManager
     {
+        private readonly IServerApplicationPaths _appPaths;
+        private readonly IFileSystem _fileSystem;
+        private readonly ILogger _logger;
+        private readonly IItemRepository _itemRepo;
+        private readonly IImageProcessor _imageProcessor;
+
+        private List<Channel> _channels = new List<Channel>();
+
         private readonly List<ILiveTvService> _services = new List<ILiveTvService>();
+
+        public LiveTvManager(IServerApplicationPaths appPaths, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor)
+        {
+            _appPaths = appPaths;
+            _fileSystem = fileSystem;
+            _logger = logger;
+            _itemRepo = itemRepo;
+            _imageProcessor = imageProcessor;
+        }
+
         /// <summary>
         /// Gets the services.
         /// </summary>
@@ -33,16 +63,147 @@ namespace MediaBrowser.Server.Implementations.LiveTv
         /// </summary>
         /// <param name="info">The info.</param>
         /// <returns>ChannelInfoDto.</returns>
-        public ChannelInfoDto GetChannelInfoDto(ChannelInfo info)
+        public ChannelInfoDto GetChannelInfoDto(Channel info)
         {
             return new ChannelInfoDto
             {
                 Name = info.Name,
                 ServiceName = info.ServiceName,
                 ChannelType = info.ChannelType,
-                Id = info.Id,
-                Number = info.Number
+                Id = info.ChannelId,
+                Number = info.ChannelNumber,
+                PrimaryImageTag = GetLogoImageTag(info)
             };
         }
+
+        private Guid? GetLogoImageTag(Channel info)
+        {
+            var path = info.PrimaryImagePath;
+
+            if (string.IsNullOrEmpty(path))
+            {
+                return null;
+            }
+
+            try
+            {
+                return _imageProcessor.GetImageCacheTag(info, ImageType.Primary, path);
+            }
+            catch (Exception ex)
+            {
+                _logger.ErrorException("Error getting channel image info for {0}", ex, info.Name);
+            }
+
+            return null;
+        }
+
+        public IEnumerable<Channel> GetChannels(ChannelQuery query)
+        {
+            return _channels.OrderBy(i =>
+            {
+                double number = 0;
+
+                if (!string.IsNullOrEmpty(i.ChannelNumber))
+                {
+                    double.TryParse(i.ChannelNumber, out number);
+                }
+
+                return number;
+
+            }).ThenBy(i => i.Name);
+        }
+
+        public Channel GetChannel(string serviceName, string channelId)
+        {
+            return _channels.FirstOrDefault(i => string.Equals(i.ServiceName, serviceName, StringComparison.OrdinalIgnoreCase) && string.Equals(i.ChannelId, channelId, StringComparison.OrdinalIgnoreCase));
+        }
+
+        internal async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken)
+        {
+            // Avoid implicitly captured closure
+            var currentCancellationToken = cancellationToken;
+
+            var tasks = _services.Select(i => i.GetChannelsAsync(currentCancellationToken));
+
+            var results = await Task.WhenAll(tasks).ConfigureAwait(false);
+
+            var allChannels = results.SelectMany(i => i);
+
+            var channnelTasks = allChannels.Select(i => GetChannel(i, cancellationToken));
+
+            var channelEntities = await Task.WhenAll(channnelTasks).ConfigureAwait(false);
+
+            _channels = channelEntities.ToList();
+        }
+
+        private async Task<Channel> GetChannel(ChannelInfo channelInfo, CancellationToken cancellationToken)
+        {
+            try
+            {
+                return await GetChannelInternal(channelInfo, cancellationToken).ConfigureAwait(false);
+            }
+            catch (OperationCanceledException)
+            {
+                throw;
+            }
+            catch (Exception ex)
+            {
+                _logger.ErrorException("Error getting channel information for {0}", ex, channelInfo.Name);
+
+                return null;
+            }
+        }
+
+        private async Task<Channel> GetChannelInternal(ChannelInfo channelInfo, CancellationToken cancellationToken)
+        {
+            var path = Path.Combine(_appPaths.ItemsByNamePath, "channels", _fileSystem.GetValidFilename(channelInfo.ServiceName), _fileSystem.GetValidFilename(channelInfo.Name));
+
+            var fileInfo = new DirectoryInfo(path);
+
+            var isNew = false;
+
+            if (!fileInfo.Exists)
+            {
+                Directory.CreateDirectory(path);
+                fileInfo = new DirectoryInfo(path);
+
+                if (!fileInfo.Exists)
+                {
+                    throw new IOException("Path not created: " + path);
+                }
+
+                isNew = true;
+            }
+
+            var type = typeof(Channel);
+
+            var id = (path + channelInfo.Number).GetMBId(type);
+
+            var item = _itemRepo.RetrieveItem(id) as Channel;
+
+            if (item == null)
+            {
+                item = new Channel
+                {
+                    Name = channelInfo.Name,
+                    Id = id,
+                    DateCreated = _fileSystem.GetCreationTimeUtc(fileInfo),
+                    DateModified = _fileSystem.GetLastWriteTimeUtc(fileInfo),
+                    Path = path,
+                    ChannelId = channelInfo.Id,
+                    ChannelNumber = channelInfo.Number,
+                    ServiceName = channelInfo.ServiceName
+                };
+
+                isNew = true;
+            }
+
+            // Set this now so we don't cause additional file system access during provider executions
+            item.ResetResolveArgs(fileInfo);
+
+            await item.RefreshMetadata(cancellationToken, forceSave: isNew, resetResolveArgs: false);
+
+            return item;
+        }
     }
 }

+ 54 - 0
MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs

@@ -0,0 +1,54 @@
+using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Model.Tasks;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.LiveTv
+{
+    class RefreshChannelsScheduledTask : IScheduledTask
+    {
+        private readonly ILiveTvManager _liveTvManager;
+
+        public RefreshChannelsScheduledTask(ILiveTvManager liveTvManager)
+        {
+            _liveTvManager = liveTvManager;
+        }
+
+        public string Name
+        {
+            get { return "Refresh Channels"; }
+        }
+
+        public string Description
+        {
+            get { return "Downloads channel information from live tv services."; }
+        }
+
+        public string Category
+        {
+            get { return "Live TV"; }
+        }
+
+        public Task Execute(System.Threading.CancellationToken cancellationToken, IProgress<double> progress)
+        {
+            var manager = (LiveTvManager) _liveTvManager;
+
+            return manager.RefreshChannels(progress, cancellationToken);
+        }
+
+        public IEnumerable<ITaskTrigger> GetDefaultTriggers()
+        {
+            return new ITaskTrigger[] 
+            { 
+
+                new StartupTrigger(),
+
+                new SystemEventTrigger{ SystemEvent = SystemEvent.WakeFromSleep},
+
+                new IntervalTrigger{ Interval = TimeSpan.FromHours(4)}
+            };
+        }
+    }
+}

+ 0 - 5
MediaBrowser.Server.Implementations/Localization/Ratings/ca.txt

@@ -1,11 +1,6 @@
 CA-G,1
-GB-U,1
 CA-PG,5
-DE-0,5
 CA-14A,7
-DE-12,7
 CA-A,8
 CA-18A,9
-SE-11,9
-DE-16,9
 CA-R,10

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

@@ -167,7 +167,9 @@
     <Compile Include="Library\Validators\StudiosPostScanTask.cs" />
     <Compile Include="Library\Validators\StudiosValidator.cs" />
     <Compile Include="Library\Validators\YearsPostScanTask.cs" />
+    <Compile Include="LiveTv\ChannelImageProvider.cs" />
     <Compile Include="LiveTv\LiveTvManager.cs" />
+    <Compile Include="LiveTv\RefreshChannelsScheduledTask.cs" />
     <Compile Include="Localization\LocalizationManager.cs" />
     <Compile Include="MediaEncoder\MediaEncoder.cs" />
     <Compile Include="Persistence\SqliteChapterRepository.cs" />

+ 1 - 1
MediaBrowser.ServerApplication/ApplicationHost.cs

@@ -294,7 +294,7 @@ namespace MediaBrowser.ServerApplication
             DtoService = new DtoService(Logger, LibraryManager, UserManager, UserDataManager, ItemRepository, ImageProcessor);
             RegisterSingleInstance(DtoService);
 
-            LiveTvManager = new LiveTvManager();
+            LiveTvManager = new LiveTvManager(ApplicationPaths, FileSystemManager, Logger, ItemRepository, ImageProcessor);
             RegisterSingleInstance(LiveTvManager);
 
             var displayPreferencesTask = Task.Run(async () => await ConfigureDisplayPreferencesRepositories().ConfigureAwait(false));

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

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Common.Internal</id>
-        <version>3.0.245</version>
+        <version>3.0.246</version>
         <title>MediaBrowser.Common.Internal</title>
         <authors>Luke</authors>
         <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>
         <copyright>Copyright © Media Browser 2013</copyright>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.245" />
+            <dependency id="MediaBrowser.Common" version="3.0.246" />
             <dependency id="NLog" version="2.1.0" />
             <dependency id="ServiceStack.Text" version="3.9.58" />
             <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">
     <metadata>
         <id>MediaBrowser.Common</id>
-        <version>3.0.245</version>
+        <version>3.0.246</version>
         <title>MediaBrowser.Common</title>
         <authors>Media Browser Team</authors>
         <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">
     <metadata>
         <id>MediaBrowser.Server.Core</id>
-        <version>3.0.245</version>
+        <version>3.0.246</version>
         <title>Media Browser.Server.Core</title>
         <authors>Media Browser Team</authors>
         <owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
         <description>Contains core components required to build plugins for Media Browser Server.</description>
         <copyright>Copyright © Media Browser 2013</copyright>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.245" />
+            <dependency id="MediaBrowser.Common" version="3.0.246" />
         </dependencies>
     </metadata>
     <files>