diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj
index e9911a12d9..6cda8b5d05 100644
--- a/Emby.Drawing/Emby.Drawing.csproj
+++ b/Emby.Drawing/Emby.Drawing.csproj
@@ -37,7 +37,7 @@
False
- ..\packages\ImageMagickSharp.1.0.0.16\lib\net45\ImageMagickSharp.dll
+ ..\packages\ImageMagickSharp.1.0.0.17\lib\net45\ImageMagickSharp.dll
..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll
diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs
index 64ddf7e884..12a98edffa 100644
--- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs
+++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs
@@ -72,11 +72,16 @@ namespace Emby.Drawing.ImageMagick
private void LogVersion()
{
- _logger.Info("ImageMagick version: " + Wand.VersionString);
+ _logger.Info("ImageMagick version: " + GetVersion());
TestWebp();
Wand.SetMagickThreadCount(1);
}
+ public static string GetVersion()
+ {
+ return Wand.VersionString;
+ }
+
private bool _webpAvailable = true;
private void TestWebp()
{
@@ -148,7 +153,7 @@ namespace Emby.Drawing.ImageMagick
DrawIndicator(originalImage, width, height, options);
originalImage.CurrentImage.CompressionQuality = quality;
- //originalImage.CurrentImage.StripImage();
+ originalImage.CurrentImage.StripImage();
originalImage.SaveImage(outputPath);
}
@@ -165,7 +170,7 @@ namespace Emby.Drawing.ImageMagick
DrawIndicator(wand, width, height, options);
wand.CurrentImage.CompressionQuality = quality;
- //wand.CurrentImage.StripImage();
+ wand.CurrentImage.StripImage();
wand.SaveImage(outputPath);
}
@@ -176,15 +181,14 @@ namespace Emby.Drawing.ImageMagick
private void ScaleImage(MagickWand wand, int width, int height)
{
- wand.CurrentImage.ResizeImage(width, height);
- //if (_config.Configuration.EnableHighQualityImageScaling)
- //{
- // wand.CurrentImage.ResizeImage(width, height);
- //}
- //else
- //{
- // wand.CurrentImage.ScaleImage(width, height);
- //}
+ if (_config.Configuration.EnableHighQualityImageScaling)
+ {
+ wand.CurrentImage.ResizeImage(width, height);
+ }
+ else
+ {
+ wand.CurrentImage.ScaleImage(width, height);
+ }
}
///
diff --git a/Emby.Drawing/packages.config b/Emby.Drawing/packages.config
index 0fcdc278e3..3b8dbcab7c 100644
--- a/Emby.Drawing/packages.config
+++ b/Emby.Drawing/packages.config
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs
index 7a14ace777..ecab943491 100644
--- a/MediaBrowser.Api/BaseApiService.cs
+++ b/MediaBrowser.Api/BaseApiService.cs
@@ -198,50 +198,6 @@ namespace MediaBrowser.Api
return libraryManager.GetPerson(DeSlugPersonName(name, libraryManager));
}
- protected IList GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func filter)
- {
- if (!string.IsNullOrEmpty(parentId))
- {
- var folder = (Folder)libraryManager.GetItemById(new Guid(parentId));
-
- if (!string.IsNullOrWhiteSpace(userId))
- {
- var user = userManager.GetUserById(userId);
-
- if (user == null)
- {
- throw new ArgumentException("User not found");
- }
-
- return folder
- .GetRecursiveChildren(user, filter)
- .ToList();
- }
-
- return folder
- .GetRecursiveChildren(filter);
- }
- if (!string.IsNullOrWhiteSpace(userId))
- {
- var user = userManager.GetUserById(userId);
-
- if (user == null)
- {
- throw new ArgumentException("User not found");
- }
-
- return userManager
- .GetUserById(userId)
- .RootFolder
- .GetRecursiveChildren(user, filter)
- .ToList();
- }
-
- return libraryManager
- .RootFolder
- .GetRecursiveChildren(filter);
- }
-
///
/// Deslugs an artist name by finding the correct entry in the library
///
diff --git a/MediaBrowser.Api/GamesService.cs b/MediaBrowser.Api/GamesService.cs
index 93cc010793..a27c872f15 100644
--- a/MediaBrowser.Api/GamesService.cs
+++ b/MediaBrowser.Api/GamesService.cs
@@ -102,12 +102,16 @@ namespace MediaBrowser.Api
/// System.Object.
public object Get(GetGameSystemSummaries request)
{
- var gameSystems = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, i => i is GameSystem)
+ var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
+ var query = new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[] { typeof(GameSystem).Name }
+ };
+ var parentIds = new string[] { } ;
+ var gameSystems = _libraryManager.GetItems(query, parentIds)
.Cast()
.ToList();
- var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
-
var result = gameSystems
.Select(i => GetSummary(i, user))
.ToList();
@@ -119,8 +123,15 @@ namespace MediaBrowser.Api
public object Get(GetPlayerIndex request)
{
- var games = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, i => i is Game)
- .Cast();
+ var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
+ var query = new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[] { typeof(Game).Name }
+ };
+ var parentIds = new string[] { };
+ var games = _libraryManager.GetItems(query, parentIds)
+ .Cast()
+ .ToList();
var lookup = games
.ToLookup(i => i.PlayersSupported ?? -1)
diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs
index 319bc13fd2..80076d0736 100644
--- a/MediaBrowser.Api/Library/LibraryService.cs
+++ b/MediaBrowser.Api/Library/LibraryService.cs
@@ -416,7 +416,7 @@ namespace MediaBrowser.Api.Library
public object Get(GetMediaFolders request)
{
- var items = _libraryManager.GetUserRootFolder().Children.OrderBy(i => i.SortName).ToList();
+ var items = _libraryManager.GetUserRootFolder().Children.Concat(_libraryManager.RootFolder.VirtualChildren).OrderBy(i => i.SortName).ToList();
if (request.IsHidden.HasValue)
{
@@ -610,7 +610,7 @@ namespace MediaBrowser.Api.Library
var dtoOptions = GetDtoOptions(request);
- BaseItem parent = item.Parent;
+ BaseItem parent = item.GetParent();
while (parent != null)
{
@@ -621,7 +621,7 @@ namespace MediaBrowser.Api.Library
baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, dtoOptions, user));
- parent = parent.Parent;
+ parent = parent.GetParent();
}
return baseItemDtos.ToList();
@@ -629,7 +629,7 @@ namespace MediaBrowser.Api.Library
private BaseItem TranslateParentItem(BaseItem item, User user)
{
- if (item.Parent is AggregateFolder)
+ if (item.GetParent() is AggregateFolder)
{
return user.RootFolder.GetChildren(user, true).FirstOrDefault(i => i.PhysicalLocations.Contains(item.Path));
}
@@ -677,6 +677,50 @@ namespace MediaBrowser.Api.Library
return ToOptimizedSerializedResultUsingCache(counts);
}
+ private IList GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func filter)
+ {
+ if (!string.IsNullOrEmpty(parentId))
+ {
+ var folder = (Folder)libraryManager.GetItemById(new Guid(parentId));
+
+ if (!string.IsNullOrWhiteSpace(userId))
+ {
+ var user = userManager.GetUserById(userId);
+
+ if (user == null)
+ {
+ throw new ArgumentException("User not found");
+ }
+
+ return folder
+ .GetRecursiveChildren(user, filter)
+ .ToList();
+ }
+
+ return folder
+ .GetRecursiveChildren(filter);
+ }
+ if (!string.IsNullOrWhiteSpace(userId))
+ {
+ var user = userManager.GetUserById(userId);
+
+ if (user == null)
+ {
+ throw new ArgumentException("User not found");
+ }
+
+ return userManager
+ .GetUserById(userId)
+ .RootFolder
+ .GetRecursiveChildren(user, filter)
+ .ToList();
+ }
+
+ return libraryManager
+ .RootFolder
+ .GetRecursiveChildren(filter);
+ }
+
private bool FilterItem(BaseItem item, GetItemCounts request, string userId)
{
if (!string.IsNullOrWhiteSpace(userId))
@@ -817,9 +861,9 @@ namespace MediaBrowser.Api.Library
: (Folder)_libraryManager.RootFolder)
: _libraryManager.GetItemById(request.Id);
- while (GetThemeSongIds(item).Count == 0 && request.InheritFromParent && item.Parent != null)
+ while (GetThemeSongIds(item).Count == 0 && request.InheritFromParent && item.GetParent() != null)
{
- item = item.Parent;
+ item = item.GetParent();
}
var dtoOptions = GetDtoOptions(request);
@@ -860,9 +904,9 @@ namespace MediaBrowser.Api.Library
: (Folder)_libraryManager.RootFolder)
: _libraryManager.GetItemById(request.Id);
- while (GetThemeVideoIds(item).Count == 0 && request.InheritFromParent && item.Parent != null)
+ while (GetThemeVideoIds(item).Count == 0 && request.InheritFromParent && item.GetParent() != null)
{
- item = item.Parent;
+ item = item.GetParent();
}
var dtoOptions = GetDtoOptions(request);
diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs
index fe8bae1a51..36cbc6ffa6 100644
--- a/MediaBrowser.Api/Movies/MoviesService.cs
+++ b/MediaBrowser.Api/Movies/MoviesService.cs
@@ -117,10 +117,7 @@ namespace MediaBrowser.Api.Movies
public async Task
+
@@ -107,6 +108,7 @@
+
diff --git a/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs b/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs
new file mode 100644
index 0000000000..3239d7b95b
--- /dev/null
+++ b/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs
@@ -0,0 +1,196 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Model.Serialization;
+using MediaBrowser.Model.Updates;
+
+namespace MediaBrowser.Common.Implementations.Updates
+{
+ public class GithubUpdater
+ {
+ private readonly IHttpClient _httpClient;
+ private readonly IJsonSerializer _jsonSerializer;
+ private TimeSpan _cacheLength;
+
+ public GithubUpdater(IHttpClient httpClient, IJsonSerializer jsonSerializer, TimeSpan cacheLength)
+ {
+ _httpClient = httpClient;
+ _jsonSerializer = jsonSerializer;
+ _cacheLength = cacheLength;
+ }
+
+ public async Task CheckForUpdateResult(string organzation, string repository, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename, CancellationToken cancellationToken)
+ {
+ var url = string.Format("https://api.github.com/repos/{0}/{1}/releases", organzation, repository);
+
+ var options = new HttpRequestOptions
+ {
+ Url = url,
+ EnableKeepAlive = false,
+ CancellationToken = cancellationToken,
+ UserAgent = "Emby/3.0"
+
+ };
+
+ if (_cacheLength.Ticks > 0)
+ {
+ options.CacheMode = CacheMode.Unconditional;
+ options.CacheLength = _cacheLength;
+ }
+
+ using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
+ {
+ var obj = _jsonSerializer.DeserializeFromStream(stream);
+
+ return CheckForUpdateResult(obj, minVersion, updateLevel, assetFilename, packageName, targetFilename);
+ }
+ }
+
+ private CheckForUpdateResult CheckForUpdateResult(RootObject[] obj, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename)
+ {
+ if (updateLevel == PackageVersionClass.Release)
+ {
+ obj = obj.Where(i => !i.prerelease).ToArray();
+ }
+ else if (updateLevel == PackageVersionClass.Beta)
+ {
+ obj = obj.Where(i => !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase)).ToArray();
+ }
+ else if (updateLevel == PackageVersionClass.Dev)
+ {
+ obj = obj.Where(i => !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) || i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase)).ToArray();
+ }
+
+ var availableUpdate = obj.Select(i => CheckForUpdateResult(i, minVersion, assetFilename, packageName, targetFilename)).FirstOrDefault(i => i != null);
+
+ return availableUpdate ?? new CheckForUpdateResult
+ {
+ IsUpdateAvailable = false
+ };
+ }
+
+ private CheckForUpdateResult CheckForUpdateResult(RootObject obj, Version minVersion, string assetFilename, string packageName, string targetFilename)
+ {
+ Version version;
+ if (!Version.TryParse(obj.tag_name, out version))
+ {
+ return null;
+ }
+
+ if (version < minVersion)
+ {
+ return null;
+ }
+
+ var asset = (obj.assets ?? new List()).FirstOrDefault(i => string.Equals(assetFilename, Path.GetFileName(i.browser_download_url), StringComparison.OrdinalIgnoreCase));
+
+ if (asset == null)
+ {
+ return null;
+ }
+
+ return new CheckForUpdateResult
+ {
+ AvailableVersion = version.ToString(),
+ IsUpdateAvailable = version > minVersion,
+ Package = new PackageVersionInfo
+ {
+ classification = obj.prerelease ?
+ (obj.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase) ? PackageVersionClass.Dev : PackageVersionClass.Beta) :
+ PackageVersionClass.Release,
+ name = packageName,
+ sourceUrl = asset.browser_download_url,
+ targetFilename = targetFilename,
+ versionStr = version.ToString(),
+ requiredVersionStr = "1.0.0",
+ description = obj.body
+ }
+ };
+ }
+
+ public class Uploader
+ {
+ public string login { get; set; }
+ public int id { get; set; }
+ public string avatar_url { get; set; }
+ public string gravatar_id { get; set; }
+ public string url { get; set; }
+ public string html_url { get; set; }
+ public string followers_url { get; set; }
+ public string following_url { get; set; }
+ public string gists_url { get; set; }
+ public string starred_url { get; set; }
+ public string subscriptions_url { get; set; }
+ public string organizations_url { get; set; }
+ public string repos_url { get; set; }
+ public string events_url { get; set; }
+ public string received_events_url { get; set; }
+ public string type { get; set; }
+ public bool site_admin { get; set; }
+ }
+
+ public class Asset
+ {
+ public string url { get; set; }
+ public int id { get; set; }
+ public string name { get; set; }
+ public object label { get; set; }
+ public Uploader uploader { get; set; }
+ public string content_type { get; set; }
+ public string state { get; set; }
+ public int size { get; set; }
+ public int download_count { get; set; }
+ public string created_at { get; set; }
+ public string updated_at { get; set; }
+ public string browser_download_url { get; set; }
+ }
+
+ public class Author
+ {
+ public string login { get; set; }
+ public int id { get; set; }
+ public string avatar_url { get; set; }
+ public string gravatar_id { get; set; }
+ public string url { get; set; }
+ public string html_url { get; set; }
+ public string followers_url { get; set; }
+ public string following_url { get; set; }
+ public string gists_url { get; set; }
+ public string starred_url { get; set; }
+ public string subscriptions_url { get; set; }
+ public string organizations_url { get; set; }
+ public string repos_url { get; set; }
+ public string events_url { get; set; }
+ public string received_events_url { get; set; }
+ public string type { get; set; }
+ public bool site_admin { get; set; }
+ }
+
+ public class RootObject
+ {
+ public string url { get; set; }
+ public string assets_url { get; set; }
+ public string upload_url { get; set; }
+ public string html_url { get; set; }
+ public int id { get; set; }
+ public string tag_name { get; set; }
+ public string target_commitish { get; set; }
+ public string name { get; set; }
+ public bool draft { get; set; }
+ public Author author { get; set; }
+ public bool prerelease { get; set; }
+ public string created_at { get; set; }
+ public string published_at { get; set; }
+ public List assets { get; set; }
+ public string tarball_url { get; set; }
+ public string zipball_url { get; set; }
+ public string body { get; set; }
+ }
+ }
+}
diff --git a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
index 0142753314..d155f11c73 100644
--- a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
+++ b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
@@ -438,11 +438,12 @@ namespace MediaBrowser.Common.Implementations.Updates
/// Installs the package.
///
/// The package.
+ /// if set to true [is plugin].
/// The progress.
/// The cancellation token.
/// Task.
/// package
- public async Task InstallPackage(PackageVersionInfo package, IProgress progress, CancellationToken cancellationToken)
+ public async Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress progress, CancellationToken cancellationToken)
{
if (package == null)
{
@@ -495,7 +496,7 @@ namespace MediaBrowser.Common.Implementations.Updates
try
{
- await InstallPackageInternal(package, innerProgress, linkedToken).ConfigureAwait(false);
+ await InstallPackageInternal(package, isPlugin, innerProgress, linkedToken).ConfigureAwait(false);
lock (CurrentInstallations)
{
@@ -551,18 +552,17 @@ namespace MediaBrowser.Common.Implementations.Updates
/// Installs the package internal.
///
/// The package.
+ /// if set to true [is plugin].
/// The progress.
/// The cancellation token.
/// Task.
- private async Task InstallPackageInternal(PackageVersionInfo package, IProgress progress, CancellationToken cancellationToken)
+ private async Task InstallPackageInternal(PackageVersionInfo package, bool isPlugin, IProgress progress, CancellationToken cancellationToken)
{
// Do the install
await PerformPackageInstallation(progress, package, cancellationToken).ConfigureAwait(false);
- var extension = Path.GetExtension(package.targetFilename) ?? "";
-
// Do plugin-specific processing
- if (!string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase) && !string.Equals(extension, ".rar", StringComparison.OrdinalIgnoreCase) && !string.Equals(extension, ".7z", StringComparison.OrdinalIgnoreCase))
+ if (isPlugin)
{
// Set last update time if we were installed before
var plugin = _applicationHost.Plugins.FirstOrDefault(p => string.Equals(p.Id.ToString(), package.guid, StringComparison.OrdinalIgnoreCase))
diff --git a/MediaBrowser.Common/Updates/IInstallationManager.cs b/MediaBrowser.Common/Updates/IInstallationManager.cs
index 7d721da6f0..68853f05e7 100644
--- a/MediaBrowser.Common/Updates/IInstallationManager.cs
+++ b/MediaBrowser.Common/Updates/IInstallationManager.cs
@@ -105,11 +105,12 @@ namespace MediaBrowser.Common.Updates
/// Installs the package.
///
/// The package.
+ /// if set to true [is plugin].
/// The progress.
/// The cancellation token.
/// Task.
/// package
- Task InstallPackage(PackageVersionInfo package, IProgress progress, CancellationToken cancellationToken);
+ Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress progress, CancellationToken cancellationToken);
///
/// Uninstalls a plugin
diff --git a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
index 653cec9016..17dcf138bf 100644
--- a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
@@ -18,9 +18,9 @@ namespace MediaBrowser.Controller.Channels
public List ChannelMediaSources { get; set; }
- protected override bool GetBlockUnratedValue(UserPolicy config)
+ public override UnratedItem GetBlockUnratedType()
{
- return config.BlockUnratedItems.Contains(UnratedItem.ChannelContent);
+ return UnratedItem.ChannelContent;
}
protected override string CreateUserDataKey()
diff --git a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
index 9010470f8f..f662020bbf 100644
--- a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
@@ -6,6 +6,7 @@ using System;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Channels
@@ -20,6 +21,11 @@ namespace MediaBrowser.Controller.Channels
return false;
}
+ public override UnratedItem GetBlockUnratedType()
+ {
+ return UnratedItem.ChannelContent;
+ }
+
[IgnoreDataMember]
public override bool SupportsLocalMetadata
{
diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
index fb545e57aa..79ad4b36b1 100644
--- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
@@ -42,9 +42,9 @@ namespace MediaBrowser.Controller.Channels
return ExternalId;
}
- protected override bool GetBlockUnratedValue(UserPolicy config)
+ public override UnratedItem GetBlockUnratedType()
{
- return config.BlockUnratedItems.Contains(UnratedItem.ChannelContent);
+ return UnratedItem.ChannelContent;
}
[IgnoreDataMember]
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs
index 43b980c20d..766f1e5ed8 100644
--- a/MediaBrowser.Controller/Entities/Audio/Audio.cs
+++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs
@@ -27,9 +27,22 @@ namespace MediaBrowser.Controller.Entities.Audio
public long? Size { get; set; }
public string Container { get; set; }
public int? TotalBitrate { get; set; }
- public List Tags { get; set; }
public ExtraType? ExtraType { get; set; }
+ ///
+ /// Gets or sets the artist.
+ ///
+ /// The artist.
+ public List Artists { get; set; }
+
+ public List AlbumArtists { get; set; }
+
+ ///
+ /// Gets or sets the album.
+ ///
+ /// The album.
+ public string Album { get; set; }
+
[IgnoreDataMember]
public bool IsThemeMedia
{
@@ -43,7 +56,6 @@ namespace MediaBrowser.Controller.Entities.Audio
{
Artists = new List();
AlbumArtists = new List();
- Tags = new List();
}
[IgnoreDataMember]
@@ -92,14 +104,6 @@ namespace MediaBrowser.Controller.Entities.Audio
locationType != LocationType.Virtual;
}
- ///
- /// Gets or sets the artist.
- ///
- /// The artist.
- public List Artists { get; set; }
-
- public List AlbumArtists { get; set; }
-
[IgnoreDataMember]
public List AllArtists
{
@@ -114,12 +118,6 @@ namespace MediaBrowser.Controller.Entities.Audio
}
}
- ///
- /// Gets or sets the album.
- ///
- /// The album.
- public string Album { get; set; }
-
[IgnoreDataMember]
public MusicAlbum AlbumEntity
{
@@ -173,9 +171,9 @@ namespace MediaBrowser.Controller.Entities.Audio
return base.CreateUserDataKey();
}
- protected override bool GetBlockUnratedValue(UserPolicy config)
+ public override UnratedItem GetBlockUnratedType()
{
- return config.BlockUnratedItems.Contains(UnratedItem.Music);
+ return UnratedItem.Music;
}
public SongInfo GetLookupInfo()
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index 98d1eb4ce2..9a38912ea0 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -30,7 +30,7 @@ namespace MediaBrowser.Controller.Entities.Audio
{
get
{
- return Parents.OfType().FirstOrDefault();
+ return GetParents().OfType().FirstOrDefault();
}
}
@@ -110,13 +110,18 @@ namespace MediaBrowser.Controller.Entities.Audio
return config.BlockUnratedItems.Contains(UnratedItem.Music);
}
+ public override UnratedItem GetBlockUnratedType()
+ {
+ return UnratedItem.Music;
+ }
+
public AlbumInfo GetLookupInfo()
{
var id = GetItemLookupInfo();
id.AlbumArtists = AlbumArtists;
- var artist = Parents.OfType().FirstOrDefault();
+ var artist = GetParents().OfType().FirstOrDefault();
if (artist != null)
{
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
index f6d1d32a4c..02bcceada4 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
@@ -138,6 +138,11 @@ namespace MediaBrowser.Controller.Entities.Audio
return config.BlockUnratedItems.Contains(UnratedItem.Music);
}
+ public override UnratedItem GetBlockUnratedType()
+ {
+ return UnratedItem.Music;
+ }
+
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress progress, CancellationToken cancellationToken)
{
var items = GetRecursiveChildren().ToList();
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 0fbe516221..379697b816 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Configuration;
@@ -24,6 +23,7 @@ using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
+using MediaBrowser.Model.LiveTv;
namespace MediaBrowser.Controller.Entities
{
@@ -34,6 +34,7 @@ namespace MediaBrowser.Controller.Entities
{
protected BaseItem()
{
+ Tags = new List();
Genres = new List();
Studios = new List();
ProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase);
@@ -44,7 +45,7 @@ namespace MediaBrowser.Controller.Entities
///
/// The supported image extensions
///
- public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg" };
+ public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg", ".tbn", ".gif" };
public static readonly List SupportedImageExtensionsList = SupportedImageExtensions.ToList();
@@ -103,7 +104,8 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the name.
///
/// The name.
- public string Name
+ [IgnoreDataMember]
+ public virtual string Name
{
get
{
@@ -122,14 +124,23 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the id.
///
/// The id.
+ [IgnoreDataMember]
public Guid Id { get; set; }
///
/// Gets or sets a value indicating whether this instance is hd.
///
/// true if this instance is hd; otherwise, false.
+ [IgnoreDataMember]
public bool? IsHD { get; set; }
+ ///
+ /// Gets or sets the audio.
+ ///
+ /// The audio.
+ [IgnoreDataMember]
+ public ProgramAudio? Audio { get; set; }
+
///
/// Return the id that should be used to key display prefs for this item.
/// Default is based on the type for everything except actual generic folders.
@@ -149,6 +160,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the path.
///
/// The path.
+ [IgnoreDataMember]
public virtual string Path { get; set; }
[IgnoreDataMember]
@@ -173,7 +185,7 @@ namespace MediaBrowser.Controller.Entities
}
///
- /// Id of the program.
+ /// If this content came from an external service, the id of the content on that service
///
[IgnoreDataMember]
public string ExternalId
@@ -201,11 +213,6 @@ namespace MediaBrowser.Controller.Entities
}
}
- public virtual bool IsHiddenFromUser(User user)
- {
- return false;
- }
-
[IgnoreDataMember]
public virtual bool IsOwnedItem
{
@@ -325,12 +332,14 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the date created.
///
/// The date created.
+ [IgnoreDataMember]
public DateTime DateCreated { get; set; }
///
/// Gets or sets the date modified.
///
/// The date modified.
+ [IgnoreDataMember]
public DateTime DateModified { get; set; }
public DateTime DateLastSaved { get; set; }
@@ -407,6 +416,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the name of the forced sort.
///
/// The name of the forced sort.
+ [IgnoreDataMember]
public string ForcedSortName
{
get { return _forcedSortName; }
@@ -447,10 +457,7 @@ namespace MediaBrowser.Controller.Entities
{
var idString = Id.ToString("N");
- if (ConfigurationManager.Configuration.EnableLibraryMetadataSubFolder)
- {
- basePath = System.IO.Path.Combine(basePath, "library");
- }
+ basePath = System.IO.Path.Combine(basePath, "library");
return System.IO.Path.Combine(basePath, idString.Substring(0, 2), idString);
}
@@ -493,6 +500,7 @@ namespace MediaBrowser.Controller.Entities
return sortable;
}
+ [IgnoreDataMember]
public Guid ParentId { get; set; }
///
@@ -502,15 +510,7 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public Folder Parent
{
- get
- {
- if (ParentId != Guid.Empty)
- {
- return LibraryManager.GetItemById(ParentId) as Folder;
- }
-
- return null;
- }
+ get { return GetParent() as Folder; }
set
{
@@ -525,16 +525,28 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public IEnumerable Parents
{
- get
+ get { return GetParents().OfType(); }
+ }
+
+ public BaseItem GetParent()
+ {
+ if (ParentId != Guid.Empty)
{
- var parent = Parent;
+ return LibraryManager.GetItemById(ParentId);
+ }
- while (parent != null)
- {
- yield return parent;
+ return null;
+ }
- parent = parent.Parent;
- }
+ public IEnumerable GetParents()
+ {
+ var parent = GetParent();
+
+ while (parent != null)
+ {
+ yield return parent;
+
+ parent = parent.GetParent();
}
}
@@ -546,19 +558,20 @@ namespace MediaBrowser.Controller.Entities
public T FindParent()
where T : Folder
{
- return Parents.OfType().FirstOrDefault();
+ return GetParents().OfType().FirstOrDefault();
}
[IgnoreDataMember]
public virtual BaseItem DisplayParent
{
- get { return Parent; }
+ get { return GetParent(); }
}
///
/// When the item first debuted. For movies this could be premiere date, episodes would be first aired
///
/// The premiere date.
+ [IgnoreDataMember]
public DateTime? PremiereDate { get; set; }
///
@@ -572,31 +585,35 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the display type of the media.
///
/// The display type of the media.
+ [IgnoreDataMember]
public string DisplayMediaType { get; set; }
///
/// Gets or sets the official rating.
///
/// The official rating.
+ [IgnoreDataMember]
public string OfficialRating { get; set; }
///
/// Gets or sets the official rating description.
///
/// The official rating description.
+ [IgnoreDataMember]
public string OfficialRatingDescription { get; set; }
///
/// Gets or sets the custom rating.
///
/// The custom rating.
- //[IgnoreDataMember]
+ [IgnoreDataMember]
public string CustomRating { get; set; }
///
/// Gets or sets the overview.
///
/// The overview.
+ [IgnoreDataMember]
public string Overview { get; set; }
///
@@ -609,37 +626,48 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the genres.
///
/// The genres.
+ [IgnoreDataMember]
public List Genres { get; set; }
+ ///
+ /// Gets or sets the tags.
+ ///
+ /// The tags.
+ public List Tags { get; set; }
+
///
/// Gets or sets the home page URL.
///
/// The home page URL.
+ [IgnoreDataMember]
public string HomePageUrl { get; set; }
///
/// Gets or sets the community rating.
///
/// The community rating.
- //[IgnoreDataMember]
+ [IgnoreDataMember]
public float? CommunityRating { get; set; }
///
/// Gets or sets the community rating vote count.
///
/// The community rating vote count.
+ [IgnoreDataMember]
public int? VoteCount { get; set; }
///
/// Gets or sets the run time ticks.
///
/// The run time ticks.
+ [IgnoreDataMember]
public long? RunTimeTicks { get; set; }
///
/// Gets or sets the production year.
///
/// The production year.
+ [IgnoreDataMember]
public int? ProductionYear { get; set; }
///
@@ -647,19 +675,34 @@ namespace MediaBrowser.Controller.Entities
/// This could be episode number, album track number, etc.
///
/// The index number.
- //[IgnoreDataMember]
+ [IgnoreDataMember]
public int? IndexNumber { get; set; }
///
/// For an episode this could be the season number, or for a song this could be the disc number.
///
/// The parent index number.
+ [IgnoreDataMember]
public int? ParentIndexNumber { get; set; }
[IgnoreDataMember]
- public virtual string OfficialRatingForComparison
+ public string OfficialRatingForComparison
{
- get { return OfficialRating; }
+ get
+ {
+ if (!string.IsNullOrWhiteSpace(OfficialRating))
+ {
+ return OfficialRating;
+ }
+
+ var parent = DisplayParent;
+ if (parent != null)
+ {
+ return parent.OfficialRatingForComparison;
+ }
+
+ return null;
+ }
}
[IgnoreDataMember]
@@ -721,21 +764,21 @@ namespace MediaBrowser.Controller.Entities
return LibraryManager.ResolvePaths(files, directoryService, null)
.OfType()
.Select(audio =>
- {
- // Try to retrieve it from the db. If we don't find it, use the resolved version
- var dbItem = LibraryManager.GetItemById(audio.Id) as Audio.Audio;
-
- if (dbItem != null)
{
- audio = dbItem;
- }
+ // Try to retrieve it from the db. If we don't find it, use the resolved version
+ var dbItem = LibraryManager.GetItemById(audio.Id) as Audio.Audio;
- audio.ExtraType = ExtraType.ThemeSong;
+ if (dbItem != null)
+ {
+ audio = dbItem;
+ }
- return audio;
+ audio.ExtraType = ExtraType.ThemeSong;
- // Sort them so that the list can be easily compared for changes
- }).OrderBy(i => i.Path).ToList();
+ return audio;
+
+ // Sort them so that the list can be easily compared for changes
+ }).OrderBy(i => i.Path).ToList();
}
///
@@ -751,21 +794,21 @@ namespace MediaBrowser.Controller.Entities
return LibraryManager.ResolvePaths(files, directoryService, null)
.OfType
diff --git a/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs
deleted file mode 100644
index dc8a16cd8b..0000000000
--- a/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs
+++ /dev/null
@@ -1,166 +0,0 @@
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Persistence;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Security;
-using System.Text;
-using System.Threading;
-using CommonIO;
-using MediaBrowser.Common.IO;
-
-namespace MediaBrowser.LocalMetadata.Savers
-{
- public class EpisodeXmlProvider : IMetadataFileSaver, IConfigurableProvider
- {
- private readonly IItemRepository _itemRepository;
-
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- private readonly IServerConfigurationManager _config;
- private readonly ILibraryManager _libraryManager;
- private IFileSystem _fileSystem;
-
- public EpisodeXmlProvider(IItemRepository itemRepository, IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
- {
- _itemRepository = itemRepository;
- _config = config;
- _libraryManager = libraryManager;
- _fileSystem = fileSystem;
- }
-
- ///
- /// Determines whether [is enabled for] [the specified item].
- ///
- /// The item.
- /// Type of the update.
- /// true if [is enabled for] [the specified item]; otherwise, false.
- public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
- {
- if (!item.SupportsLocalMetadata)
- {
- return false;
- }
-
- return item is Episode && updateType >= ItemUpdateType.MetadataDownload;
- }
-
- public string Name
- {
- get
- {
- return XmlProviderUtils.Name;
- }
- }
-
- public bool IsEnabled
- {
- get { return !_config.Configuration.DisableXmlSavers; }
- }
-
- ///
- /// Saves the specified item.
- ///
- /// The item.
- /// The cancellation token.
- /// Task.
- public void Save(IHasMetadata item, CancellationToken cancellationToken)
- {
- var episode = (Episode)item;
-
- var builder = new StringBuilder();
-
- builder.Append("- ");
-
- if (!string.IsNullOrEmpty(item.Name))
- {
- builder.Append("" + SecurityElement.Escape(episode.Name) + "");
- }
-
- if (episode.IndexNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.IndexNumber.Value.ToString(_usCulture)) + "");
- }
-
- if (episode.IndexNumberEnd.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.IndexNumberEnd.Value.ToString(_usCulture)) + "");
- }
-
- if (episode.AirsAfterSeasonNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.AirsAfterSeasonNumber.Value.ToString(_usCulture)) + "");
- }
- if (episode.AirsBeforeEpisodeNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.AirsBeforeEpisodeNumber.Value.ToString(_usCulture)) + "");
- }
- if (episode.AirsBeforeSeasonNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.AirsBeforeSeasonNumber.Value.ToString(_usCulture)) + "");
- }
-
- if (episode.ParentIndexNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.ParentIndexNumber.Value.ToString(_usCulture)) + "");
- }
-
- if (episode.AbsoluteEpisodeNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.AbsoluteEpisodeNumber.Value.ToString(_usCulture)) + "");
- }
-
- if (episode.DvdEpisodeNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.DvdEpisodeNumber.Value.ToString(_usCulture)) + "");
- }
-
- if (episode.DvdSeasonNumber.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.DvdSeasonNumber.Value.ToString(_usCulture)) + "");
- }
-
- if (episode.PremiereDate.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(episode.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + "");
- }
-
- XmlSaverHelpers.AddCommonNodes(episode, _libraryManager, builder);
- XmlSaverHelpers.AddMediaInfo(episode, builder, _itemRepository);
-
- builder.Append("
");
-
- var xmlFilePath = GetSavePath(item);
-
- XmlSaverHelpers.Save(builder, xmlFilePath, new List
- {
- "FirstAired",
- "SeasonNumber",
- "EpisodeNumber",
- "EpisodeName",
- "EpisodeNumberEnd",
- "airsafter_season",
- "airsbefore_episode",
- "airsbefore_season",
- "DVD_episodenumber",
- "DVD_season",
- "absolute_number"
-
- }, _config, _fileSystem);
- }
-
- ///
- /// Gets the save path.
- ///
- /// The item.
- /// System.String.
- public string GetSavePath(IHasMetadata item)
- {
- var filename = Path.ChangeExtension(Path.GetFileName(item.Path), ".xml");
-
- return Path.Combine(Path.GetDirectoryName(item.Path), "metadata", filename);
- }
- }
-}
diff --git a/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs
deleted file mode 100644
index 2e3e7aaa1e..0000000000
--- a/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs
+++ /dev/null
@@ -1,147 +0,0 @@
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Persistence;
-using System.Collections.Generic;
-using System.IO;
-using System.Security;
-using System.Text;
-using System.Threading;
-using CommonIO;
-using MediaBrowser.Common.IO;
-
-namespace MediaBrowser.LocalMetadata.Savers
-{
- ///
- /// Saves movie.xml for movies, trailers and music videos
- ///
- public class MovieXmlProvider : IMetadataFileSaver, IConfigurableProvider
- {
- private readonly IItemRepository _itemRepository;
- private readonly IServerConfigurationManager _config;
- private readonly ILibraryManager _libraryManager;
- private IFileSystem _fileSystem;
-
- public MovieXmlProvider(IItemRepository itemRepository, IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
- {
- _itemRepository = itemRepository;
- _config = config;
- _libraryManager = libraryManager;
- _fileSystem = fileSystem;
- }
-
- public string Name
- {
- get
- {
- return XmlProviderUtils.Name;
- }
- }
-
- public bool IsEnabled
- {
- get { return !_config.Configuration.DisableXmlSavers; }
- }
-
- ///
- /// Determines whether [is enabled for] [the specified item].
- ///
- /// The item.
- /// Type of the update.
- /// true if [is enabled for] [the specified item]; otherwise, false.
- public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
- {
- if (!item.SupportsLocalMetadata)
- {
- return false;
- }
-
- var video = item as Video;
-
- // Check parent for null to avoid running this against things like video backdrops
- if (video != null && !(item is Episode) && !video.IsOwnedItem)
- {
- return updateType >= ItemUpdateType.MetadataDownload;
- }
-
- return false;
- }
-
- ///
- /// Saves the specified item.
- ///
- /// The item.
- /// The cancellation token.
- /// Task.
- public void Save(IHasMetadata item, CancellationToken cancellationToken)
- {
- var video = (Video)item;
-
- var builder = new StringBuilder();
-
- builder.Append("");
-
- XmlSaverHelpers.AddCommonNodes(video, _libraryManager, builder);
-
- var musicVideo = item as MusicVideo;
-
- if (musicVideo != null)
- {
- if (musicVideo.Artists.Count > 0)
- {
- builder.Append("" + SecurityElement.Escape(string.Join(";", musicVideo.Artists.ToArray())) + "");
- }
- if (!string.IsNullOrEmpty(musicVideo.Album))
- {
- builder.Append("" + SecurityElement.Escape(musicVideo.Album) + "");
- }
- }
-
- var movie = item as Movie;
-
- if (movie != null)
- {
- if (!string.IsNullOrEmpty(movie.TmdbCollectionName))
- {
- builder.Append("" + SecurityElement.Escape(movie.TmdbCollectionName) + "");
- }
- }
-
- XmlSaverHelpers.AddMediaInfo(video, builder, _itemRepository);
-
- builder.Append("");
-
- var xmlFilePath = GetSavePath(item);
-
- XmlSaverHelpers.Save(builder, xmlFilePath, new List
- {
- // Deprecated. No longer saving in this field.
- "IMDBrating",
-
- // Deprecated. No longer saving in this field.
- "Description",
-
- "Artist",
- "Album",
- "TmdbCollectionName"
- }, _config, _fileSystem);
- }
-
- public string GetSavePath(IHasMetadata item)
- {
- return GetMovieSavePath((Video)item);
- }
-
- public static string GetMovieSavePath(Video item)
- {
- if (item.IsInMixedFolder)
- {
- return Path.ChangeExtension(item.Path, ".xml");
- }
-
- return Path.Combine(item.ContainingFolderPath, "movie.xml");
- }
- }
-}
diff --git a/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs
deleted file mode 100644
index 9806c4216e..0000000000
--- a/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs
+++ /dev/null
@@ -1,154 +0,0 @@
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Model.Entities;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Security;
-using System.Text;
-using System.Threading;
-using CommonIO;
-using MediaBrowser.Common.IO;
-
-namespace MediaBrowser.LocalMetadata.Savers
-{
- public class SeriesXmlProvider : IMetadataFileSaver, IConfigurableProvider
- {
- private readonly IServerConfigurationManager _config;
- private readonly ILibraryManager _libraryManager;
- private IFileSystem _fileSystem;
-
- public SeriesXmlProvider(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
- {
- _config = config;
- _libraryManager = libraryManager;
- _fileSystem = fileSystem;
- }
-
- public string Name
- {
- get
- {
- return XmlProviderUtils.Name;
- }
- }
-
- ///
- /// Determines whether [is enabled for] [the specified item].
- ///
- /// The item.
- /// Type of the update.
- /// true if [is enabled for] [the specified item]; otherwise, false.
- public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
- {
- if (!item.SupportsLocalMetadata)
- {
- return false;
- }
-
- return item is Series && updateType >= ItemUpdateType.MetadataDownload;
- }
-
- public bool IsEnabled
- {
- get { return !_config.Configuration.DisableXmlSavers; }
- }
-
- private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
-
- ///
- /// Saves the specified item.
- ///
- /// The item.
- /// The cancellation token.
- /// Task.
- public void Save(IHasMetadata item, CancellationToken cancellationToken)
- {
- var series = (Series)item;
-
- var builder = new StringBuilder();
-
- builder.Append("");
-
- var tvdb = item.GetProviderId(MetadataProviders.Tvdb);
-
- if (!string.IsNullOrEmpty(tvdb))
- {
- builder.Append("" + SecurityElement.Escape(tvdb) + "");
- }
-
- if (series.Status.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(series.Status.Value.ToString()) + "");
- }
-
- if (series.Studios.Count > 0)
- {
- builder.Append("" + SecurityElement.Escape(series.Studios[0]) + "");
- }
-
- if (!string.IsNullOrEmpty(series.AirTime))
- {
- builder.Append("" + SecurityElement.Escape(series.AirTime) + "");
- }
-
- if (series.AirDays != null)
- {
- if (series.AirDays.Count == 7)
- {
- builder.Append("" + SecurityElement.Escape("Daily") + "");
- }
- else if (series.AirDays.Count > 0)
- {
- builder.Append("" + SecurityElement.Escape(series.AirDays[0].ToString()) + "");
- }
- }
-
- if (series.PremiereDate.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(series.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + "");
- }
-
- if (series.AnimeSeriesIndex.HasValue)
- {
- builder.Append("" + SecurityElement.Escape(series.AnimeSeriesIndex.Value.ToString(UsCulture)) + "");
- }
-
- XmlSaverHelpers.AddCommonNodes(series, _libraryManager, builder);
-
- builder.Append("");
-
- var xmlFilePath = GetSavePath(item);
-
- XmlSaverHelpers.Save(builder, xmlFilePath, new List
- {
- "id",
- "Status",
- "Network",
- "Airs_Time",
- "Airs_DayOfWeek",
- "FirstAired",
-
- // Don't preserve old series node
- "Series",
-
- "SeriesName",
-
- // Deprecated. No longer saving in this field.
- "AnimeSeriesIndex"
- }, _config, _fileSystem);
- }
-
- ///
- /// Gets the save path.
- ///
- /// The item.
- /// System.String.
- public string GetSavePath(IHasMetadata item)
- {
- return Path.Combine(item.Path, "series.xml");
- }
- }
-}
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
index ba44ed7dd4..882b2e1c24 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
@@ -122,10 +122,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles
var subtitle = await GetSubtitleStream(itemId, mediaSourceId, subtitleStreamIndex, cancellationToken)
.ConfigureAwait(false);
+ var inputFormat = subtitle.Item2;
+
+ if (string.Equals(inputFormat, outputFormat, StringComparison.OrdinalIgnoreCase) && TryGetWriter(outputFormat) == null)
+ {
+ return subtitle.Item1;
+ }
+
using (var stream = subtitle.Item1)
{
- var inputFormat = subtitle.Item2;
-
return await ConvertSubtitles(stream, inputFormat, outputFormat, startTimeTicks, endTimeTicks, cancellationToken).ConfigureAwait(false);
}
}
@@ -288,7 +293,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
return null;
}
- private ISubtitleWriter GetWriter(string format)
+ private ISubtitleWriter TryGetWriter(string format)
{
if (string.IsNullOrEmpty(format))
{
@@ -312,6 +317,18 @@ namespace MediaBrowser.MediaEncoding.Subtitles
return new TtmlWriter();
}
+ return null;
+ }
+
+ private ISubtitleWriter GetWriter(string format)
+ {
+ var writer = TryGetWriter(format);
+
+ if (writer != null)
+ {
+ return writer;
+ }
+
throw new ArgumentException("Unsupported format: " + format);
}
diff --git a/MediaBrowser.Model/Configuration/CinemaModeConfiguration.cs b/MediaBrowser.Model/Configuration/CinemaModeConfiguration.cs
index 764a7222f6..dd6c77e66d 100644
--- a/MediaBrowser.Model/Configuration/CinemaModeConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/CinemaModeConfiguration.cs
@@ -11,16 +11,19 @@ namespace MediaBrowser.Model.Configuration
public bool EnableIntrosParentalControl { get; set; }
public bool EnableIntrosFromSimilarMovies { get; set; }
public string CustomIntroPath { get; set; }
+ public string MediaInfoIntroPath { get; set; }
public bool EnableIntrosFromUpcomingDvdMovies { get; set; }
public bool EnableIntrosFromUpcomingStreamingMovies { get; set; }
public int TrailerLimit { get; set; }
+ public string[] Tags { get; set; }
public CinemaModeConfiguration()
{
EnableIntrosParentalControl = true;
EnableIntrosFromSimilarMovies = true;
TrailerLimit = 2;
+ Tags = new[] { "thx" };
}
}
}
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 7208ccb1d9..08f7f89e30 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -62,6 +62,12 @@ namespace MediaBrowser.Model.Configuration
/// true if this instance is port authorized; otherwise, false.
public bool IsPortAuthorized { get; set; }
+ ///
+ /// Gets or sets a value indicating whether [enable high quality image scaling].
+ ///
+ /// true if [enable high quality image scaling]; otherwise, false.
+ public bool EnableHighQualityImageScaling { get; set; }
+
///
/// Gets or sets the item by name path.
///
@@ -92,24 +98,6 @@ namespace MediaBrowser.Model.Configuration
/// true if [enable localized guids]; otherwise, false.
public bool EnableLocalizedGuids { get; set; }
- ///
- /// Gets or sets a value indicating whether [disable startup scan].
- ///
- /// true if [disable startup scan]; otherwise, false.
- public bool DisableStartupScan { get; set; }
-
- ///
- /// Gets or sets a value indicating whether [enable user views].
- ///
- /// true if [enable user views]; otherwise, false.
- public bool EnableUserViews { get; set; }
-
- ///
- /// Gets or sets a value indicating whether [enable library metadata sub folder].
- ///
- /// true if [enable library metadata sub folder]; otherwise, false.
- public bool EnableLibraryMetadataSubFolder { get; set; }
-
///
/// Gets or sets the preferred metadata language.
///
@@ -219,21 +207,20 @@ namespace MediaBrowser.Model.Configuration
public int SharingExpirationDays { get; set; }
- public bool DisableXmlSavers { get; set; }
public bool EnableWindowsShortcuts { get; set; }
- public bool EnableVideoFrameByFrameAnalysis { get; set; }
-
public bool EnableDateLastRefresh { get; set; }
public string[] Migrations { get; set; }
+ public int MigrationVersion { get; set; }
+
///
/// Initializes a new instance of the class.
///
public ServerConfiguration()
{
- Migrations = new string[] {};
+ Migrations = new string[] { };
ImageSavingConvention = ImageSavingConvention.Compatible;
PublicPort = 8096;
diff --git a/MediaBrowser.Providers/Folders/DefaultImageProvider.cs b/MediaBrowser.Providers/Folders/DefaultImageProvider.cs
index 1f36c09761..a5a2e1e724 100644
--- a/MediaBrowser.Providers/Folders/DefaultImageProvider.cs
+++ b/MediaBrowser.Providers/Folders/DefaultImageProvider.cs
@@ -170,4 +170,4 @@ namespace MediaBrowser.Providers.Folders
return GetSupportedImages(item).Any(i => !item.HasImage(i));
}
}
-}
+}
\ No newline at end of file
diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
index 19f575d0d6..f99aa967fb 100644
--- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs
+++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
@@ -359,12 +359,13 @@ namespace MediaBrowser.Providers.Manager
private void ClearImages(IHasImages item, ImageType type)
{
var deleted = false;
+ var deletedImages = new List();
foreach (var image in item.GetImages(type).ToList())
{
if (!image.IsLocalFile)
{
- // TODO: Need to get this image removed
+ deletedImages.Add(image);
continue;
}
@@ -384,6 +385,11 @@ namespace MediaBrowser.Providers.Manager
}
}
+ foreach (var image in deletedImages)
+ {
+ item.RemoveImage(image);
+ }
+
if (deleted)
{
item.ValidateImages(new DirectoryService(_logger, _fileSystem));
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index 580e9c4ac3..477ff167ce 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -1038,7 +1038,7 @@ namespace MediaBrowser.Providers.Manager
.ToList();
var musicArtists = albums
- .Select(i => i.Parent)
+ .Select(i => i.GetParent())
.OfType()
.ToList();
diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
index f0c5cbbd3a..a575daacb2 100644
--- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
+++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
@@ -15,6 +15,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Text;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
@@ -130,6 +131,8 @@ namespace MediaBrowser.Providers.Subtitles
try
{
+ //var isText = MediaStream.IsTextFormat(response.Format);
+
using (var fs = _fileSystem.GetFileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
await stream.CopyToAsync(fs).ConfigureAwait(false);
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
index b115c3bfdc..fe13d8cef0 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
@@ -104,6 +104,11 @@ namespace MediaBrowser.Server.Implementations.Channels
.OrderBy(i => i.Name);
}
+ public IEnumerable GetInstalledChannelIds()
+ {
+ return GetAllChannels().Select(i => GetInternalChannelId(i.Name));
+ }
+
public Task> GetChannelsInternal(ChannelQuery query, CancellationToken cancellationToken)
{
var user = string.IsNullOrWhiteSpace(query.UserId)
@@ -408,25 +413,15 @@ namespace MediaBrowser.Server.Implementations.Channels
private async Task GetChannel(IChannel channelInfo, CancellationToken cancellationToken)
{
+ var parentFolder = await GetInternalChannelFolder(cancellationToken).ConfigureAwait(false);
+ var parentFolderId = parentFolder.Id;
+
var id = GetInternalChannelId(channelInfo.Name);
var path = Channel.GetInternalMetadataPath(_config.ApplicationPaths.InternalMetadataPath, id);
var isNew = false;
-
- if (!_fileSystem.DirectoryExists(path))
- {
- _logger.Debug("Creating directory {0}", path);
-
- _fileSystem.CreateDirectory(path);
-
- if (!_fileSystem.DirectoryExists(path))
- {
- throw new IOException("Path not created: " + path);
- }
-
- isNew = true;
- }
+ var forceUpdate = false;
var item = _libraryManager.GetItemById(id) as Channel;
var channelId = channelInfo.Name.GetMD5().ToString("N");
@@ -438,18 +433,29 @@ namespace MediaBrowser.Server.Implementations.Channels
Name = channelInfo.Name,
Id = id,
DateCreated = _fileSystem.GetCreationTimeUtc(path),
- DateModified = _fileSystem.GetLastWriteTimeUtc(path),
- Path = path,
- ChannelId = channelId
+ DateModified = _fileSystem.GetLastWriteTimeUtc(path)
};
isNew = true;
}
- if (!string.Equals(item.ChannelId, channelId, StringComparison.OrdinalIgnoreCase))
+ if (!string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase))
{
isNew = true;
}
+ item.Path = path;
+
+ if (!string.Equals(item.ChannelId, channelId, StringComparison.OrdinalIgnoreCase))
+ {
+ forceUpdate = true;
+ }
+ item.ChannelId = channelId;
+
+ if (item.ParentId != parentFolderId)
+ {
+ forceUpdate = true;
+ }
+ item.ParentId = parentFolderId;
item.OfficialRating = GetOfficialRating(channelInfo.ParentalRating);
item.Overview = channelInfo.Description;
@@ -459,13 +465,17 @@ namespace MediaBrowser.Server.Implementations.Channels
{
item.Name = channelInfo.Name;
}
-
- await item.RefreshMetadata(new MetadataRefreshOptions(_fileSystem)
+
+ if (isNew)
{
- ForceSave = isNew
-
- }, cancellationToken);
+ await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
+ }
+ else if (forceUpdate)
+ {
+ await item.UpdateToRepository(ItemUpdateType.None, cancellationToken).ConfigureAwait(false);
+ }
+ await item.RefreshMetadata(new MetadataRefreshOptions(_fileSystem), cancellationToken);
return item;
}
@@ -1225,6 +1235,7 @@ namespace MediaBrowser.Server.Implementations.Channels
{
BaseItem item;
bool isNew;
+ bool forceUpdate = false;
if (info.Type == ChannelItemType.Folder)
{
@@ -1254,25 +1265,26 @@ namespace MediaBrowser.Server.Implementations.Channels
item.ProductionYear = info.ProductionYear;
item.ProviderIds = info.ProviderIds;
item.OfficialRating = info.OfficialRating;
-
item.DateCreated = info.DateCreated ?? DateTime.UtcNow;
+ item.Tags = info.Tags;
}
var channelItem = (IChannelItem)item;
channelItem.ChannelId = internalChannelId.ToString("N");
+ if (item.ParentId != internalChannelId)
+ {
+ forceUpdate = true;
+ }
+ item.ParentId = internalChannelId;
+
if (!string.Equals(channelItem.ExternalId, info.Id, StringComparison.OrdinalIgnoreCase))
{
- isNew = true;
+ forceUpdate = true;
}
channelItem.ExternalId = info.Id;
- if (isNew)
- {
- channelItem.Tags = info.Tags;
- }
-
var channelMediaItem = item as IChannelMediaItem;
if (channelMediaItem != null)
@@ -1300,6 +1312,10 @@ namespace MediaBrowser.Server.Implementations.Channels
await _libraryManager.UpdatePeople(item, info.People ?? new List()).ConfigureAwait(false);
}
}
+ else if (forceUpdate)
+ {
+ await item.UpdateToRepository(ItemUpdateType.None, cancellationToken).ConfigureAwait(false);
+ }
return item;
}
@@ -1573,4 +1589,4 @@ namespace MediaBrowser.Server.Implementations.Channels
}
}
}
-}
+}
\ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs
index 2e9d42f49e..da4a72cd49 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs
@@ -123,15 +123,15 @@ namespace MediaBrowser.Server.Implementations.Channels
private async Task CleanDatabase(CancellationToken cancellationToken)
{
- var allChannels = await _channelManager.GetChannelsInternal(new ChannelQuery { }, cancellationToken);
+ var installedChannelIds = ((ChannelManager)_channelManager).GetInstalledChannelIds();
- var allIds = _libraryManager.GetItemIds(new InternalItemsQuery
+ var databaseIds = _libraryManager.GetItemIds(new InternalItemsQuery
{
IncludeItemTypes = new[] { typeof(Channel).Name }
});
- var invalidIds = allIds
- .Except(allChannels.Items.Select(i => i.Id).ToList())
+ var invalidIds = databaseIds
+ .Except(installedChannelIds)
.ToList();
foreach (var id in invalidIds)
diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs b/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs
index 9ea4572847..7ed0d43b14 100644
--- a/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs
@@ -59,7 +59,7 @@ namespace MediaBrowser.Server.Implementations.Collections
return subItem;
}
- var parent = subItem.Parent;
+ var parent = subItem.GetParent();
if (parent != null && parent.HasImage(ImageType.Primary))
{
@@ -78,24 +78,9 @@ namespace MediaBrowser.Server.Implementations.Collections
return Task.FromResult(GetFinalItems(items, 2));
}
- protected override async Task CreateImage(IHasImages item, List itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex)
+ protected override Task CreateImage(IHasImages item, List itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex)
{
- var image = itemsWithImages
- .Where(i => i.HasImage(ImageType.Primary) && i.GetImageInfo(ImageType.Primary, 0).IsLocalFile && Path.HasExtension(i.GetImagePath(ImageType.Primary)))
- .Select(i => i.GetImagePath(ImageType.Primary))
- .FirstOrDefault();
-
- if (string.IsNullOrWhiteSpace(image))
- {
- return null;
- }
-
- var ext = Path.GetExtension(image);
-
- var outputPath = Path.ChangeExtension(outputPathWithoutExtension, ext);
- File.Copy(image, outputPath);
-
- return outputPath;
+ return CreateSingleImage(itemsWithImages, outputPathWithoutExtension, ImageType.Primary);
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
index 5c98e401f4..4e742ca7a2 100644
--- a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
+++ b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
@@ -40,6 +40,7 @@ namespace MediaBrowser.Server.Implementations.Collections
public Folder GetCollectionsFolder(string userId)
{
return _libraryManager.RootFolder.Children.OfType()
+ .FirstOrDefault() ?? _libraryManager.GetUserRootFolder().Children.OfType()
.FirstOrDefault();
}
diff --git a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
index d62918d567..7a1d860475 100644
--- a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
+++ b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
@@ -3,7 +3,7 @@ using System.Linq;
namespace MediaBrowser.Server.Implementations.Collections
{
- public class ManualCollectionsFolder : BasePluginFolder
+ public class ManualCollectionsFolder : BasePluginFolder, IHiddenFromDisplay
{
public ManualCollectionsFolder()
{
@@ -11,11 +11,6 @@ namespace MediaBrowser.Server.Implementations.Collections
DisplayMediaType = "CollectionFolder";
}
- public override bool IsVisible(User user)
- {
- return base.IsVisible(user) && GetChildren(user, false).Any();
- }
-
public override bool IsHidden
{
get
@@ -24,7 +19,7 @@ namespace MediaBrowser.Server.Implementations.Collections
}
}
- public override bool IsHiddenFromUser(User user)
+ public bool IsHiddenFromUser(User user)
{
return !user.Configuration.DisplayCollectionsView;
}
@@ -36,7 +31,7 @@ namespace MediaBrowser.Server.Implementations.Collections
public override string GetClientTypeName()
{
- return typeof (CollectionFolder).Name;
+ return typeof(CollectionFolder).Name;
}
}
}
\ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
index a7d3854e71..2f4c3f5eed 100644
--- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
+++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
@@ -171,12 +171,36 @@ namespace MediaBrowser.Server.Implementations.Configuration
ValidateItemByNamePath(newConfig);
ValidatePathSubstitutions(newConfig);
ValidateMetadataPath(newConfig);
+ ValidateSslCertificate(newConfig);
EventHelper.FireEventIfNotNull(ConfigurationUpdating, this, new GenericEventArgs { Argument = newConfig }, Logger);
base.ReplaceConfiguration(newConfiguration);
}
+
+ ///
+ /// Validates the SSL certificate.
+ ///
+ /// The new configuration.
+ ///
+ private void ValidateSslCertificate(BaseApplicationConfiguration newConfig)
+ {
+ var serverConfig = (ServerConfiguration)newConfig;
+
+ var newPath = serverConfig.CertificatePath;
+
+ if (!string.IsNullOrWhiteSpace(newPath)
+ && !string.Equals(Configuration.CertificatePath ?? string.Empty, newPath))
+ {
+ // Validate
+ if (!FileSystem.FileExists(newPath))
+ {
+ throw new FileNotFoundException(string.Format("Certificate file '{0}' does not exist.", newPath));
+ }
+ }
+ }
+
private void ValidatePathSubstitutions(ServerConfiguration newConfig)
{
foreach (var map in newConfig.PathSubstitutions)
diff --git a/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs b/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs
index 6d7265972f..9479335614 100644
--- a/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs
+++ b/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs
@@ -3,12 +3,15 @@ using MediaBrowser.Controller.Entities;
using System;
using System.IO;
using System.Linq;
+using System.Runtime.Serialization;
+using System.Threading;
+using System.Threading.Tasks;
using CommonIO;
-using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Providers;
namespace MediaBrowser.Server.Implementations.Devices
{
- public class CameraUploadsFolder : BasePluginFolder
+ public class CameraUploadsFolder : BasePluginFolder, ISupportsUserSpecificView
{
public CameraUploadsFolder()
{
@@ -21,22 +24,8 @@ namespace MediaBrowser.Server.Implementations.Devices
{
return false;
}
-
- return GetChildren(user, true).Any() &&
- base.IsVisible(user);
- }
- public override bool IsHidden
- {
- get
- {
- return base.IsHidden || !Children.Any();
- }
- }
-
- public override bool IsHiddenFromUser(User user)
- {
- return false;
+ return base.IsVisible(user) && HasChildren();
}
public override string CollectionType
@@ -48,6 +37,29 @@ namespace MediaBrowser.Server.Implementations.Devices
{
return typeof(CollectionFolder).Name;
}
+
+ private bool? _hasChildren;
+ private bool HasChildren()
+ {
+ if (!_hasChildren.HasValue)
+ {
+ _hasChildren = LibraryManager.GetItemIds(new InternalItemsQuery { ParentId = Id }).Count > 0;
+ }
+
+ return _hasChildren.Value;
+ }
+
+ protected override Task ValidateChildrenInternal(IProgress progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
+ {
+ _hasChildren = null;
+ return base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService);
+ }
+
+ [IgnoreDataMember]
+ public bool EnableUserSpecificView
+ {
+ get { return true; }
+ }
}
public class CameraUploadsDynamicFolder : IVirtualFolderCreator
@@ -65,7 +77,7 @@ namespace MediaBrowser.Server.Implementations.Devices
{
var path = Path.Combine(_appPaths.DataPath, "camerauploads");
- _fileSystem.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
return new CameraUploadsFolder
{
diff --git a/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs b/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs
index 0b2c082a85..6b1af8d2d9 100644
--- a/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs
+++ b/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs
@@ -1,6 +1,5 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Events;
-using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Library;
@@ -18,6 +17,7 @@ using System.IO;
using System.Linq;
using System.Threading.Tasks;
using CommonIO;
+using MediaBrowser.Controller.Configuration;
namespace MediaBrowser.Server.Implementations.Devices
{
@@ -27,7 +27,7 @@ namespace MediaBrowser.Server.Implementations.Devices
private readonly IUserManager _userManager;
private readonly IFileSystem _fileSystem;
private readonly ILibraryMonitor _libraryMonitor;
- private readonly IConfigurationManager _config;
+ private readonly IServerConfigurationManager _config;
private readonly ILogger _logger;
private readonly INetworkManager _network;
@@ -38,7 +38,7 @@ namespace MediaBrowser.Server.Implementations.Devices
///
public event EventHandler> DeviceOptionsUpdated;
- public DeviceManager(IDeviceRepository repo, IUserManager userManager, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IConfigurationManager config, ILogger logger, INetworkManager network)
+ public DeviceManager(IDeviceRepository repo, IUserManager userManager, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IServerConfigurationManager config, ILogger logger, INetworkManager network)
{
_repo = repo;
_userManager = userManager;
@@ -187,11 +187,6 @@ namespace MediaBrowser.Server.Implementations.Devices
}
}
- private string GetUploadPath(string deviceId)
- {
- return GetUploadPath(GetDevice(deviceId));
- }
-
private string GetUploadPath(DeviceInfo device)
{
if (!string.IsNullOrWhiteSpace(device.CameraUploadPath))
@@ -205,7 +200,7 @@ namespace MediaBrowser.Server.Implementations.Devices
return config.CameraUploadPath;
}
- var path = Path.Combine(_config.CommonApplicationPaths.DataPath, "camerauploads");
+ var path = DefaultCameraUploadsPath;
if (config.EnableCameraUploadSubfolders)
{
@@ -215,6 +210,11 @@ namespace MediaBrowser.Server.Implementations.Devices
return path;
}
+ private string DefaultCameraUploadsPath
+ {
+ get { return Path.Combine(_config.CommonApplicationPaths.DataPath, "camerauploads"); }
+ }
+
public async Task UpdateDeviceInfo(string id, DeviceOptions options)
{
var device = GetDevice(id);
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index bb7f818bad..ccca6414a7 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -163,16 +163,11 @@ namespace MediaBrowser.Server.Implementations.Dto
if (person != null)
{
- var items = _libraryManager.GetItems(new InternalItemsQuery
+ var items = _libraryManager.GetItems(new InternalItemsQuery(user)
{
Person = byName.Name
- }).Items;
-
- if (user != null)
- {
- return items.Where(i => i.IsVisibleStandalone(user)).ToList();
- }
+ }, new string[] { });
return items.ToList();
}
@@ -361,6 +356,8 @@ namespace MediaBrowser.Server.Implementations.Dto
var collectionFolder = item as ICollectionFolder;
if (collectionFolder != null)
{
+ dto.OriginalCollectionType = collectionFolder.CollectionType;
+
dto.CollectionType = user == null ?
collectionFolder.CollectionType :
collectionFolder.GetViewType(user);
@@ -468,13 +465,15 @@ namespace MediaBrowser.Server.Implementations.Dto
var folder = (Folder)item;
- dto.ChildCount = GetChildCount(folder, user);
-
- // These are just far too slow.
- // TODO: Disable for CollectionFolder
- if (!(folder is UserRootFolder) && !(folder is UserView))
+ if (!(folder is IChannelItem) && !(folder is Channel))
{
- SetSpecialCounts(folder, user, dto, fields, syncProgress);
+ dto.ChildCount = GetChildCount(folder, user);
+
+ // These are just far too slow.
+ if (!(folder is UserRootFolder) && !(folder is UserView) && !(folder is ICollectionFolder))
+ {
+ SetSpecialCounts(folder, user, dto, fields, syncProgress);
+ }
}
dto.UserData.Played = dto.UserData.PlayedPercentage.HasValue && dto.UserData.PlayedPercentage.Value >= 100;
@@ -815,7 +814,7 @@ namespace MediaBrowser.Server.Implementations.Dto
/// BaseItem.
private BaseItem GetParentBackdropItem(BaseItem item, BaseItem owner)
{
- var parent = item.Parent ?? owner;
+ var parent = item.GetParent() ?? owner;
while (parent != null)
{
@@ -824,7 +823,7 @@ namespace MediaBrowser.Server.Implementations.Dto
return parent;
}
- parent = parent.Parent;
+ parent = parent.GetParent();
}
return null;
@@ -839,7 +838,7 @@ namespace MediaBrowser.Server.Implementations.Dto
/// BaseItem.
private BaseItem GetParentImageItem(BaseItem item, ImageType type, BaseItem owner)
{
- var parent = item.Parent ?? owner;
+ var parent = item.GetParent() ?? owner;
while (parent != null)
{
@@ -848,7 +847,7 @@ namespace MediaBrowser.Server.Implementations.Dto
return parent;
}
- parent = parent.Parent;
+ parent = parent.GetParent();
}
return null;
@@ -1042,7 +1041,11 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.IsFolder = item.IsFolder;
dto.MediaType = item.MediaType;
dto.LocationType = item.LocationType;
- dto.IsHD = item.IsHD;
+ if (item.IsHD.HasValue && item.IsHD.Value)
+ {
+ dto.IsHD = item.IsHD;
+ }
+ dto.Audio = item.Audio;
dto.PreferredMetadataCountryCode = item.PreferredMetadataCountryCode;
dto.PreferredMetadataLanguage = item.PreferredMetadataLanguage;
@@ -1209,15 +1212,15 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.VoteCount = item.VoteCount;
}
- if (item.IsFolder)
- {
- var folder = (Folder)item;
+ //if (item.IsFolder)
+ //{
+ // var folder = (Folder)item;
- if (fields.Contains(ItemFields.IndexOptions))
- {
- dto.IndexOptions = folder.IndexByOptionStrings.ToArray();
- }
- }
+ // if (fields.Contains(ItemFields.IndexOptions))
+ // {
+ // dto.IndexOptions = folder.IndexByOptionStrings.ToArray();
+ // }
+ //}
var supportsPlaceHolders = item as ISupportsPlaceHolders;
if (supportsPlaceHolders != null)
@@ -1520,7 +1523,7 @@ namespace MediaBrowser.Server.Implementations.Dto
}
dto.ChannelId = item.ChannelId;
-
+
var channelItem = item as IChannelItem;
if (channelItem != null)
{
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
index 008363ca4e..b059e41440 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
@@ -74,7 +74,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
// Go up one level for indicators
if (baseItem != null)
{
- var parent = baseItem.Parent;
+ var parent = baseItem.GetParent();
if (parent != null)
{
diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
index e107ea9f13..edc6b14ab6 100644
--- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
+++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
@@ -217,7 +217,7 @@ namespace MediaBrowser.Server.Implementations.IO
/// The instance containing the event data.
void LibraryManager_ItemRemoved(object sender, ItemChangeEventArgs e)
{
- if (e.Item.Parent is AggregateFolder)
+ if (e.Item.GetParent() is AggregateFolder)
{
StopWatchingPath(e.Item.Path);
}
@@ -230,7 +230,7 @@ namespace MediaBrowser.Server.Implementations.IO
/// The instance containing the event data.
void LibraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
{
- if (e.Item.Parent is AggregateFolder)
+ if (e.Item.GetParent() is AggregateFolder)
{
StartWatchingPath(e.Item.Path);
}
@@ -532,9 +532,16 @@ namespace MediaBrowser.Server.Implementations.IO
return false;
}
+ // In order to determine if the file is being written to, we have to request write access
+ // But if the server only has readonly access, this is going to cause this entire algorithm to fail
+ // So we'll take a best guess about our access level
+ var requestedFileAccess = ConfigurationManager.Configuration.SaveLocalMeta
+ ? FileAccess.ReadWrite
+ : FileAccess.Read;
+
try
{
- using (_fileSystem.GetFileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
+ using (_fileSystem.GetFileStream(path, FileMode.Open, requestedFileAccess, FileShare.ReadWrite))
{
if (_updateTimer != null)
{
@@ -651,7 +658,7 @@ namespace MediaBrowser.Server.Implementations.IO
// If the item has been deleted find the first valid parent that still exists
while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path))
{
- item = item.Parent;
+ item = item.GetParent();
if (item == null)
{
diff --git a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs
index 37131ad2c7..edc329ec42 100644
--- a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs
+++ b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs
@@ -78,13 +78,11 @@ namespace MediaBrowser.Server.Implementations.Intros
if (config.EnableIntrosFromMoviesInLibrary)
{
- var inputItems = _libraryManager.GetItems(new InternalItemsQuery
+ var inputItems = _libraryManager.GetItems(new InternalItemsQuery(user)
{
- IncludeItemTypes = new[] { typeof(Movie).Name },
+ IncludeItemTypes = new[] { typeof(Movie).Name }
- User = user
-
- }).Items;
+ }, new string[]{});
var itemsWithTrailers = inputItems
.Where(i =>
@@ -163,7 +161,7 @@ namespace MediaBrowser.Server.Implementations.Intros
private IEnumerable GetResult(BaseItem item, IEnumerable candidates, CinemaModeConfiguration config, int? ratingLevel)
{
var customIntros = !string.IsNullOrWhiteSpace(config.CustomIntroPath) ?
- GetCustomIntros(item) :
+ GetCustomIntros(config) :
new List();
var trailerLimit = config.TrailerLimit;
@@ -212,11 +210,11 @@ namespace MediaBrowser.Server.Implementations.Intros
return _serverConfig.GetConfiguration("cinemamode");
}
- private List GetCustomIntros(BaseItem item)
+ private List GetCustomIntros(CinemaModeConfiguration options)
{
try
{
- return GetCustomIntroFiles()
+ return GetCustomIntroFiles(options, true, false)
.OrderBy(i => Guid.NewGuid())
.Select(i => new IntroInfo
{
@@ -230,17 +228,23 @@ namespace MediaBrowser.Server.Implementations.Intros
}
}
- private IEnumerable GetCustomIntroFiles(CinemaModeConfiguration options = null)
+ private IEnumerable GetCustomIntroFiles(CinemaModeConfiguration options, bool enableCustomIntros, bool enableMediaInfoIntros)
{
- options = options ?? GetOptions();
+ var list = new List();
- if (string.IsNullOrWhiteSpace(options.CustomIntroPath))
+ if (enableCustomIntros && !string.IsNullOrWhiteSpace(options.CustomIntroPath))
{
- return new List();
+ list.AddRange(_fileSystem.GetFilePaths(options.CustomIntroPath, true)
+ .Where(_libraryManager.IsVideoFile));
}
- return _fileSystem.GetFilePaths(options.CustomIntroPath, true)
- .Where(_libraryManager.IsVideoFile);
+ if (enableMediaInfoIntros && !string.IsNullOrWhiteSpace(options.MediaInfoIntroPath))
+ {
+ list.AddRange(_fileSystem.GetFilePaths(options.MediaInfoIntroPath, true)
+ .Where(_libraryManager.IsVideoFile));
+ }
+
+ return list.Distinct(StringComparer.OrdinalIgnoreCase);
}
private bool FilterByParentalRating(int? ratingLevel, BaseItem item)
@@ -341,7 +345,7 @@ namespace MediaBrowser.Server.Implementations.Intros
public IEnumerable GetAllIntroFiles()
{
- return GetCustomIntroFiles();
+ return GetCustomIntroFiles(GetOptions(), true, true);
}
private bool IsSupporter
diff --git a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
index 9035d6479f..402fa439da 100644
--- a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
+++ b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
@@ -47,11 +47,14 @@ namespace MediaBrowser.Server.Implementations.Library
///
/// Shoulds the ignore.
///
- /// The args.
+ /// The file information.
+ /// The parent.
/// true if XXXX, false otherwise
- public bool ShouldIgnore(ItemResolveArgs args)
+ public bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent)
{
- var filename = args.FileInfo.Name;
+ var filename = fileInfo.Name;
+ var isHidden = (fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden;
+ var path = fileInfo.FullName;
// Handle mac .DS_Store
// https://github.com/MediaBrowser/MediaBrowser/issues/427
@@ -61,21 +64,24 @@ namespace MediaBrowser.Server.Implementations.Library
}
// Ignore hidden files and folders
- if (args.IsHidden)
+ if (isHidden)
{
- var parentFolderName = Path.GetFileName(Path.GetDirectoryName(args.Path));
+ if (parent == null)
+ {
+ var parentFolderName = Path.GetFileName(Path.GetDirectoryName(path));
- if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
- if (string.Equals(parentFolderName, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
- {
- return false;
+ if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+ if (string.Equals(parentFolderName, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
+ {
+ return false;
+ }
}
// Sometimes these are marked hidden
- if (_fileSystem.IsRootPath(args.Path))
+ if (_fileSystem.IsRootPath(path))
{
return false;
}
@@ -83,7 +89,7 @@ namespace MediaBrowser.Server.Implementations.Library
return true;
}
- if (args.IsDirectory)
+ if (fileInfo.IsDirectory)
{
// Ignore any folders in our list
if (IgnoreFolders.Contains(filename, StringComparer.OrdinalIgnoreCase))
@@ -91,26 +97,29 @@ namespace MediaBrowser.Server.Implementations.Library
return true;
}
- // Ignore trailer folders but allow it at the collection level
- if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) &&
- !(args.Parent is AggregateFolder) && !(args.Parent is UserRootFolder))
+ if (parent != null)
{
- return true;
- }
+ // Ignore trailer folders but allow it at the collection level
+ if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) &&
+ !(parent is AggregateFolder) && !(parent is UserRootFolder))
+ {
+ return true;
+ }
- if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
+ if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
- if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
- {
- return true;
+ if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
}
}
else
{
- if (args.Parent != null)
+ if (parent != null)
{
// Don't resolve these into audio files
if (string.Equals(_fileSystem.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && _libraryManager.IsAudioFile(filename))
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index f27f35c486..9e19ffbe0c 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -27,6 +27,7 @@ using MediaBrowser.Server.Implementations.Library.Validators;
using MediaBrowser.Server.Implementations.Logging;
using MediaBrowser.Server.Implementations.ScheduledTasks;
using System;
+using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
@@ -36,6 +37,7 @@ using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Model.Extensions;
+using MediaBrowser.Model.Library;
using MoreLinq;
using SortOrder = MediaBrowser.Model.Entities.SortOrder;
@@ -140,6 +142,7 @@ namespace MediaBrowser.Server.Implementations.Library
private readonly Func _libraryMonitorFactory;
private readonly Func _providerManagerFactory;
+ private readonly Func _userviewManager;
///
/// The _library items cache
@@ -167,7 +170,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// The user manager.
/// The configuration manager.
/// The user data repository.
- public LibraryManager(ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager, IUserDataManager userDataRepository, Func libraryMonitorFactory, IFileSystem fileSystem, Func providerManagerFactory)
+ public LibraryManager(ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager, IUserDataManager userDataRepository, Func libraryMonitorFactory, IFileSystem fileSystem, Func providerManagerFactory, Func userviewManager)
{
_logger = logger;
_taskManager = taskManager;
@@ -177,6 +180,7 @@ namespace MediaBrowser.Server.Implementations.Library
_libraryMonitorFactory = libraryMonitorFactory;
_fileSystem = fileSystem;
_providerManagerFactory = providerManagerFactory;
+ _userviewManager = userviewManager;
ByReferenceItems = new ConcurrentDictionary();
_libraryItemsCache = new ConcurrentDictionary();
@@ -401,12 +405,12 @@ namespace MediaBrowser.Server.Implementations.Library
{
foreach (var path in item.GetDeletePaths().ToList())
{
- if (_fileSystem.DirectoryExists(path))
+ if (_fileSystem.DirectoryExists(path))
{
_logger.Debug("Deleting path {0}", path);
_fileSystem.DeleteDirectory(path, true);
}
- else if (_fileSystem.FileExists(path))
+ else if (_fileSystem.FileExists(path))
{
_logger.Debug("Deleting path {0}", path);
_fileSystem.DeleteFile(path);
@@ -580,7 +584,7 @@ namespace MediaBrowser.Server.Implementations.Library
};
// Return null if ignore rules deem that we should do so
- if (EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(args)))
+ if (IgnoreFile(args.FileInfo, args.Parent))
{
return null;
}
@@ -616,6 +620,11 @@ namespace MediaBrowser.Server.Implementations.Library
return ResolveItem(args);
}
+ public bool IgnoreFile(FileSystemMetadata file, BaseItem parent)
+ {
+ return EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(file, parent));
+ }
+
public IEnumerable NormalizeRootPathList(IEnumerable paths)
{
var originalList = paths.ToList();
@@ -651,7 +660,7 @@ namespace MediaBrowser.Server.Implementations.Library
public IEnumerable ResolvePaths(IEnumerable files, IDirectoryService directoryService, Folder parent, string collectionType)
{
- var fileList = files.ToList();
+ var fileList = files.Where(i => !IgnoreFile(i, parent)).ToList();
if (parent != null)
{
@@ -702,7 +711,7 @@ namespace MediaBrowser.Server.Implementations.Library
{
var rootFolderPath = ConfigurationManager.ApplicationPaths.RootFolderPath;
- _fileSystem.CreateDirectory(rootFolderPath);
+ _fileSystem.CreateDirectory(rootFolderPath);
var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath));
@@ -732,6 +741,13 @@ namespace MediaBrowser.Server.Implementations.Library
folder = dbItem;
}
+ if (folder.ParentId != rootFolder.Id)
+ {
+ folder.ParentId = rootFolder.Id;
+ var task = folder.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None);
+ Task.WaitAll(task);
+ }
+
rootFolder.AddVirtualChild(folder);
RegisterItem(folder);
@@ -753,7 +769,7 @@ namespace MediaBrowser.Server.Implementations.Library
{
var userRootPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath;
- _fileSystem.CreateDirectory(userRootPath);
+ _fileSystem.CreateDirectory(userRootPath);
var tmpItem = GetItemById(GetNewItemId(userRootPath, typeof(UserRootFolder))) as UserRootFolder;
@@ -1005,9 +1021,9 @@ namespace MediaBrowser.Server.Implementations.Library
private void SetPropertiesFromSongs(MusicArtist artist, IEnumerable items)
{
-
+
}
-
+
///
/// Validate and refresh the People sub-set of the IBN.
/// The items are stored in the db but not loaded into memory until actually requested by an operation.
@@ -1018,7 +1034,7 @@ namespace MediaBrowser.Server.Implementations.Library
public Task ValidatePeople(CancellationToken cancellationToken, IProgress progress)
{
// Ensure the location is available.
- _fileSystem.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath);
+ _fileSystem.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath);
return new PeopleValidator(this, _logger, ConfigurationManager, _fileSystem).ValidatePeople(cancellationToken, progress);
}
@@ -1265,6 +1281,11 @@ namespace MediaBrowser.Server.Implementations.Library
public QueryResult GetItems(InternalItemsQuery query)
{
+ if (query.User != null)
+ {
+ AddUserToQuery(query, query.User);
+ }
+
var result = ItemRepository.GetItemIdsList(query);
var items = result.Select(GetItemById).Where(i => i != null).ToArray();
@@ -1277,14 +1298,140 @@ namespace MediaBrowser.Server.Implementations.Library
public QueryResult QueryItems(InternalItemsQuery query)
{
+ if (query.User != null)
+ {
+ AddUserToQuery(query, query.User);
+ }
+
return ItemRepository.GetItems(query);
}
public List GetItemIds(InternalItemsQuery query)
{
+ if (query.User != null)
+ {
+ AddUserToQuery(query, query.User);
+ }
+
return ItemRepository.GetItemIdsList(query);
}
+ public IEnumerable GetItems(InternalItemsQuery query, IEnumerable parentIds)
+ {
+ var parents = parentIds.Select(i => GetItemById(new Guid(i))).ToList();
+
+ SetTopParentIdsOrAncestors(query, parents);
+
+ return GetItemIds(query).Select(GetItemById);
+ }
+
+ public QueryResult GetItemsResult(InternalItemsQuery query, IEnumerable parentIds)
+ {
+ var parents = parentIds.Select(i => GetItemById(new Guid(i))).ToList();
+
+ SetTopParentIdsOrAncestors(query, parents);
+
+ return GetItems(query);
+ }
+
+ private void SetTopParentIdsOrAncestors(InternalItemsQuery query, List parents)
+ {
+ if (parents.All(i =>
+ {
+ if ((i is ICollectionFolder) || (i is UserView))
+ {
+ return true;
+ }
+
+ _logger.Debug("Query requires ancestor query due to type: " + i.GetType().Name);
+ return false;
+
+ }))
+ {
+ // Optimize by querying against top level views
+ query.TopParentIds = parents.SelectMany(i => GetTopParentsForQuery(i, query.User)).Select(i => i.Id.ToString("N")).ToArray();
+ }
+ else
+ {
+ // We need to be able to query from any arbitrary ancestor up the tree
+ query.AncestorIds = parents.SelectMany(i => i.GetIdsForAncestorQuery()).Select(i => i.ToString("N")).ToArray();
+ }
+ }
+
+ private void AddUserToQuery(InternalItemsQuery query, User user)
+ {
+ if (query.AncestorIds.Length == 0 && !query.ParentId.HasValue && query.ChannelIds.Length == 0 && query.TopParentIds.Length == 0)
+ {
+ var userViews = _userviewManager().GetUserViews(new UserViewQuery
+ {
+ UserId = user.Id.ToString("N"),
+ IncludeHidden = true
+
+ }, CancellationToken.None).Result.ToList();
+
+ query.TopParentIds = userViews.SelectMany(i => GetTopParentsForQuery(i, user)).Select(i => i.Id.ToString("N")).ToArray();
+ }
+ }
+
+ private IEnumerable GetTopParentsForQuery(BaseItem item, User user)
+ {
+ var view = item as UserView;
+
+ if (view != null)
+ {
+ if (string.Equals(view.ViewType, CollectionType.LiveTv))
+ {
+ return new[] { view };
+ }
+ if (string.Equals(view.ViewType, CollectionType.Channels))
+ {
+ // TODO: Return channels
+ return new[] { view };
+ }
+
+ // Translate view into folders
+ if (view.DisplayParentId != Guid.Empty)
+ {
+ var displayParent = GetItemById(view.DisplayParentId);
+ if (displayParent != null)
+ {
+ return GetTopParentsForQuery(displayParent, user);
+ }
+ return new BaseItem[] { };
+ }
+ if (view.ParentId != Guid.Empty)
+ {
+ var displayParent = GetItemById(view.ParentId);
+ if (displayParent != null)
+ {
+ return GetTopParentsForQuery(displayParent, user);
+ }
+ return new BaseItem[] { };
+ }
+
+ // Handle grouping
+ if (user != null && !string.IsNullOrWhiteSpace(view.ViewType) && UserView.IsEligibleForGrouping(view.ViewType))
+ {
+ var collectionFolders = user.RootFolder.GetChildren(user, true).OfType().Where(i => string.IsNullOrWhiteSpace(i.CollectionType) || string.Equals(i.CollectionType, view.ViewType, StringComparison.OrdinalIgnoreCase));
+ return collectionFolders.SelectMany(i => GetTopParentsForQuery(i, user));
+ }
+ return new BaseItem[] { };
+ }
+
+ var collectionFolder = item as CollectionFolder;
+ if (collectionFolder != null)
+ {
+ return collectionFolder.GetPhysicalParents();
+ }
+
+ var topParent = item.GetTopParent();
+ if (topParent != null)
+ {
+ return new[] { topParent };
+ }
+ return new BaseItem[] { };
+ }
+
///
/// Gets the intros.
///
@@ -1577,9 +1724,9 @@ namespace MediaBrowser.Server.Implementations.Library
public IEnumerable GetCollectionFolders(BaseItem item)
{
- while (!(item.Parent is AggregateFolder) && item.Parent != null)
+ while (!(item.GetParent() is AggregateFolder) && item.GetParent() != null)
{
- item = item.Parent;
+ item = item.GetParent();
}
if (item == null)
@@ -1616,7 +1763,7 @@ namespace MediaBrowser.Server.Implementations.Library
return type;
}
- return item.Parents
+ return item.GetParents()
.Select(GetConfiguredContentType)
.LastOrDefault(i => !string.IsNullOrWhiteSpace(i));
}
@@ -1653,16 +1800,16 @@ namespace MediaBrowser.Server.Implementations.Library
private string GetTopFolderContentType(BaseItem item)
{
- while (!(item.Parent is AggregateFolder) && item.Parent != null)
- {
- item = item.Parent;
- }
-
if (item == null)
{
return null;
}
+ while (!(item.GetParent() is AggregateFolder) && item.GetParent() != null)
+ {
+ item = item.GetParent();
+ }
+
return GetUserRootFolder().Children
.OfType()
.Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path))
@@ -1679,7 +1826,7 @@ namespace MediaBrowser.Server.Implementations.Library
string sortName,
CancellationToken cancellationToken)
{
- return GetNamedViewInternal(user, name, null, viewType, sortName, null, cancellationToken);
+ return GetNamedView(user, name, null, viewType, sortName, cancellationToken);
}
public async Task GetNamedView(string name,
@@ -1697,10 +1844,9 @@ namespace MediaBrowser.Server.Implementations.Library
var refresh = false;
- if (item == null ||
- !string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase))
+ if (item == null || !string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase))
{
- _fileSystem.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
item = new UserView
{
@@ -1717,12 +1863,6 @@ namespace MediaBrowser.Server.Implementations.Library
refresh = true;
}
- if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
- {
- item.ViewType = viewType;
- await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
- }
-
if (!refresh)
{
refresh = (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval;
@@ -1748,40 +1888,14 @@ namespace MediaBrowser.Server.Implementations.Library
return item;
}
- public Task GetNamedView(User user,
+ public async Task GetNamedView(User user,
string name,
string parentId,
string viewType,
string sortName,
- string uniqueId,
CancellationToken cancellationToken)
{
- if (string.IsNullOrWhiteSpace(parentId))
- {
- throw new ArgumentNullException("parentId");
- }
-
- return GetNamedViewInternal(user, name, parentId, viewType, sortName, uniqueId, cancellationToken);
- }
-
- private async Task GetNamedViewInternal(User user,
- string name,
- string parentId,
- string viewType,
- string sortName,
- string uniqueId,
- CancellationToken cancellationToken)
- {
- if (string.IsNullOrWhiteSpace(name))
- {
- throw new ArgumentNullException("name");
- }
-
- var idValues = "37_namedview_" + name + user.Id.ToString("N") + (parentId ?? string.Empty);
- if (!string.IsNullOrWhiteSpace(uniqueId))
- {
- idValues += uniqueId;
- }
+ var idValues = "38_namedview_" + name + user.Id.ToString("N") + (parentId ?? string.Empty) + (viewType ?? string.Empty);
var id = GetNewItemId(idValues, typeof(UserView));
@@ -1793,7 +1907,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (item == null)
{
- _fileSystem.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
item = new UserView
{
@@ -1816,18 +1930,6 @@ namespace MediaBrowser.Server.Implementations.Library
isNew = true;
}
- if (!item.UserId.HasValue)
- {
- item.UserId = user.Id;
- await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
- }
-
- if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
- {
- item.ViewType = viewType;
- await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
- }
-
var refresh = isNew || (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval;
if (!refresh && item.DisplayParentId != Guid.Empty)
@@ -1851,7 +1953,6 @@ namespace MediaBrowser.Server.Implementations.Library
public async Task GetShadowView(BaseItem parent,
string viewType,
string sortName,
- string uniqueId,
CancellationToken cancellationToken)
{
if (parent == null)
@@ -1862,11 +1963,7 @@ namespace MediaBrowser.Server.Implementations.Library
var name = parent.Name;
var parentId = parent.Id;
- var idValues = "37_namedview_" + name + parentId + (viewType ?? string.Empty);
- if (!string.IsNullOrWhiteSpace(uniqueId))
- {
- idValues += uniqueId;
- }
+ var idValues = "38_namedview_" + name + parentId + (viewType ?? string.Empty);
var id = GetNewItemId(idValues, typeof(UserView));
@@ -1897,12 +1994,6 @@ namespace MediaBrowser.Server.Implementations.Library
isNew = true;
}
- if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
- {
- item.ViewType = viewType;
- await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
- }
-
var refresh = isNew || (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval;
if (!refresh && item.DisplayParentId != Guid.Empty)
@@ -1922,7 +2013,7 @@ namespace MediaBrowser.Server.Implementations.Library
return item;
}
-
+
public async Task GetNamedView(string name,
string parentId,
string viewType,
@@ -1951,7 +2042,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (item == null)
{
- _fileSystem.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
item = new UserView
{
@@ -2198,21 +2289,21 @@ namespace MediaBrowser.Server.Implementations.Library
return ResolvePaths(files, directoryService, null, null)
.OfType