Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Tim Hobbs
2014-03-13 06:26:20 -07:00
160 changed files with 2743 additions and 1684 deletions

View File

@@ -0,0 +1,201 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Collections
{
public class CollectionManager : ICollectionManager
{
private readonly ILibraryManager _libraryManager;
private readonly IFileSystem _fileSystem;
private readonly ILibraryMonitor _iLibraryMonitor;
public CollectionManager(ILibraryManager libraryManager, IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor)
{
_libraryManager = libraryManager;
_fileSystem = fileSystem;
_iLibraryMonitor = iLibraryMonitor;
}
public async Task CreateCollection(CollectionCreationOptions options)
{
var name = options.Name;
// Need to use the [boxset] suffix
// If internet metadata is not found, or if xml saving is off there will be no collection.xml
// This could cause it to get re-resolved as a plain folder
var folderName = _fileSystem.GetValidFilename(name) + " [boxset]";
var parentFolder = GetParentFolder(options.ParentId);
if (parentFolder == null)
{
throw new ArgumentException();
}
var path = Path.Combine(parentFolder.Path, folderName);
_iLibraryMonitor.ReportFileSystemChangeBeginning(path);
try
{
Directory.CreateDirectory(path);
var collection = new BoxSet
{
Name = name,
Parent = parentFolder,
DisplayMediaType = "Collection",
Path = path,
DontFetchMeta = options.IsLocked,
ProviderIds = options.ProviderIds
};
await parentFolder.AddChild(collection, CancellationToken.None).ConfigureAwait(false);
await collection.RefreshMetadata(new MetadataRefreshOptions(), CancellationToken.None)
.ConfigureAwait(false);
}
finally
{
// Refresh handled internally
_iLibraryMonitor.ReportFileSystemChangeComplete(path, false);
}
}
private Folder GetParentFolder(Guid? parentId)
{
if (parentId.HasValue)
{
if (parentId.Value == Guid.Empty)
{
throw new ArgumentNullException("parentId");
}
var folder = _libraryManager.GetItemById(parentId.Value) as Folder;
// Find an actual physical folder
if (folder is CollectionFolder)
{
return _libraryManager.RootFolder.Children.OfType<Folder>().First(i => folder.PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase));
}
}
return _libraryManager.RootFolder.Children.OfType<ManualCollectionsFolder>().FirstOrDefault() ??
_libraryManager.RootFolder.GetHiddenChildren().OfType<ManualCollectionsFolder>().FirstOrDefault();
}
public async Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids)
{
var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
if (collection == null)
{
throw new ArgumentException("No collection exists with the supplied Id");
}
var list = new List<LinkedChild>();
foreach (var itemId in ids)
{
var item = _libraryManager.GetItemById(itemId);
if (item == null)
{
throw new ArgumentException("No item exists with the supplied Id");
}
if (collection.LinkedChildren.Any(i => i.ItemId.HasValue && i.ItemId == itemId))
{
throw new ArgumentException("Item already exists in collection");
}
list.Add(new LinkedChild
{
ItemName = item.Name,
ItemYear = item.ProductionYear,
ItemType = item.GetType().Name,
Type = LinkedChildType.Manual
});
}
collection.LinkedChildren.AddRange(list);
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
await collection.RefreshMetadata(CancellationToken.None).ConfigureAwait(false);
}
public async Task RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds)
{
var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
if (collection == null)
{
throw new ArgumentException("No collection exists with the supplied Id");
}
var list = new List<LinkedChild>();
foreach (var itemId in itemIds)
{
var child = collection.LinkedChildren.FirstOrDefault(i => i.ItemId.HasValue && i.ItemId.Value == itemId);
if (child == null)
{
throw new ArgumentException("No collection title exists with the supplied Id");
}
list.Add(child);
}
var shortcutFiles = Directory
.EnumerateFiles(collection.Path, "*", SearchOption.TopDirectoryOnly)
.Where(i => _fileSystem.IsShortcut(i))
.ToList();
var shortcutFilesToDelete = list.Where(child => !string.IsNullOrWhiteSpace(child.Path) && child.Type == LinkedChildType.Shortcut)
.Select(child => shortcutFiles.FirstOrDefault(i => string.Equals(child.Path, _fileSystem.ResolveShortcut(i), StringComparison.OrdinalIgnoreCase)))
.Where(i => !string.IsNullOrWhiteSpace(i))
.ToList();
foreach (var file in shortcutFilesToDelete)
{
_iLibraryMonitor.ReportFileSystemChangeBeginning(file);
}
try
{
foreach (var file in shortcutFilesToDelete)
{
File.Delete(file);
}
foreach (var child in list)
{
collection.LinkedChildren.Remove(child);
}
}
finally
{
foreach (var file in shortcutFilesToDelete)
{
_iLibraryMonitor.ReportFileSystemChangeComplete(file, false);
}
}
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
await collection.RefreshMetadata(CancellationToken.None).ConfigureAwait(false);
}
}
}

View File

@@ -0,0 +1,55 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Entities;
using System.IO;
using System.Linq;
namespace MediaBrowser.Server.Implementations.Collections
{
public class CollectionsDynamicFolder : IVirtualFolderCreator
{
private readonly IApplicationPaths _appPaths;
public CollectionsDynamicFolder(IApplicationPaths appPaths)
{
_appPaths = appPaths;
}
public BasePluginFolder GetFolder()
{
var path = Path.Combine(_appPaths.DataPath, "collections");
Directory.CreateDirectory(path);
return new ManualCollectionsFolder
{
Path = path
};
}
}
public class ManualCollectionsFolder : BasePluginFolder
{
public ManualCollectionsFolder()
{
Name = "Collections";
}
public override bool IsVisible(User user)
{
if (!GetChildren(user, true).Any())
{
return false;
}
return base.IsVisible(user);
}
public override bool IsHidden
{
get
{
return !ActualChildren.Any() || base.IsHidden;
}
}
}
}

View File

@@ -121,41 +121,51 @@ namespace MediaBrowser.Server.Implementations.Dto
}
}
var itemByName = item as IItemByName;
if (itemByName != null)
{
AttachItemByNameCounts(dto, itemByName, user);
}
return dto;
}
/// <summary>
/// Attaches the item by name counts.
/// </summary>
/// <param name="dto">The dto.</param>
/// <param name="item">The item.</param>
/// <param name="user">The user.</param>
private void AttachItemByNameCounts(BaseItemDto dto, IItemByName item, User user)
public BaseItemDto GetItemByNameDto<T>(T item, List<ItemFields> fields, User user = null)
where T : BaseItem, IItemByName
{
if (user == null)
var libraryItems = user != null ? user.RootFolder.GetRecursiveChildren(user) :
_libraryManager.RootFolder.RecursiveChildren;
return GetItemByNameDto(item, fields, item.GetTaggedItems(libraryItems).ToList(), user);
}
public BaseItemDto GetItemByNameDto<T>(T item, List<ItemFields> fields, List<BaseItem> taggedItems, User user = null)
where T : BaseItem, IItemByName
{
var dto = GetBaseItemDto(item, fields, user);
if (item is MusicArtist || item is MusicGenre)
{
return;
dto.AlbumCount = taggedItems.Count(i => i is MusicAlbum);
dto.MusicVideoCount = taggedItems.Count(i => i is MusicVideo);
dto.SongCount = taggedItems.Count(i => i is Audio);
}
else if (item is GameGenre)
{
dto.GameCount = taggedItems.Count(i => i is Game);
}
else
{
// This populates them all and covers Genre, Person, Studio, Year
dto.AdultVideoCount = taggedItems.Count(i => i is AdultVideo);
dto.AlbumCount = taggedItems.Count(i => i is MusicAlbum);
dto.EpisodeCount = taggedItems.Count(i => i is Episode);
dto.GameCount = taggedItems.Count(i => i is Game);
dto.MovieCount = taggedItems.Count(i => i is Movie);
dto.MusicVideoCount = taggedItems.Count(i => i is MusicVideo);
dto.SeriesCount = taggedItems.Count(i => i is Series);
dto.SongCount = taggedItems.Count(i => i is Audio);
dto.TrailerCount = taggedItems.Count(i => i is Trailer);
}
var counts = item.GetItemByNameCounts(user.Id) ?? new ItemByNameCounts();
dto.ChildCount = taggedItems.Count;
dto.ChildCount = counts.TotalCount;
dto.AdultVideoCount = counts.AdultVideoCount;
dto.AlbumCount = counts.AlbumCount;
dto.EpisodeCount = counts.EpisodeCount;
dto.GameCount = counts.GameCount;
dto.MovieCount = counts.MovieCount;
dto.MusicVideoCount = counts.MusicVideoCount;
dto.SeriesCount = counts.SeriesCount;
dto.SongCount = counts.SongCount;
dto.TrailerCount = counts.TrailerCount;
return dto;
}
/// <summary>
@@ -297,6 +307,57 @@ namespace MediaBrowser.Server.Implementations.Dto
info.PrimaryImageTag = GetImageCacheTag(item, ImageType.Primary);
var backropItem = item.HasImage(ImageType.Backdrop) ? item : null;
var thumbItem = item.HasImage(ImageType.Thumb) ? item : null;
if (thumbItem == null)
{
var episode = item as Episode;
if (episode != null)
{
var series = episode.Series;
if (series != null && series.HasImage(ImageType.Thumb))
{
thumbItem = series;
}
}
}
if (backropItem == null)
{
var episode = item as Episode;
if (episode != null)
{
var series = episode.Series;
if (series != null && series.HasImage(ImageType.Backdrop))
{
backropItem = series;
}
}
}
if (thumbItem == null)
{
thumbItem = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Thumb));
}
if (thumbItem != null)
{
info.ThumbImageTag = GetImageCacheTag(thumbItem, ImageType.Thumb);
info.ThumbItemId = GetDtoId(thumbItem);
}
if (thumbItem != null)
{
info.BackdropImageTag = GetImageCacheTag(backropItem, ImageType.Backdrop);
info.BackdropItemId = GetDtoId(backropItem);
}
return info;
}

View File

@@ -3,6 +3,8 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Logging;
using Mono.Nat;
using Mono.Nat.Enums;
using Mono.Nat.EventArgs;
using System;
using System.IO;
using System.Text;

View File

@@ -171,12 +171,23 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
var fileExists = File.Exists(result.TargetPath);
var otherDuplicatePaths = GetOtherDuplicatePaths(result.TargetPath, series, seasonNumber, episodeNumber, endingEpiosdeNumber);
if (!overwriteExisting && (fileExists || otherDuplicatePaths.Count > 0))
if (!overwriteExisting)
{
result.Status = FileSortingStatus.SkippedExisting;
result.StatusMessage = string.Empty;
result.DuplicatePaths = otherDuplicatePaths;
return;
if (options.CopyOriginalFile && fileExists && IsSameEpisode(sourcePath, newPath))
{
_logger.Info("File {0} already copied to new path {1}, stopping organization", sourcePath, newPath);
result.Status = FileSortingStatus.SkippedExisting;
result.StatusMessage = string.Empty;
return;
}
if (fileExists || otherDuplicatePaths.Count > 0)
{
result.Status = FileSortingStatus.SkippedExisting;
result.StatusMessage = string.Empty;
result.DuplicatePaths = otherDuplicatePaths;
return;
}
}
PerformFileSorting(options, result);
@@ -266,7 +277,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
try
{
if (copy)
if (copy || options.CopyOriginalFile)
{
File.Copy(result.OriginalPath, result.TargetPath, true);
}
@@ -293,7 +304,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
_libraryMonitor.ReportFileSystemChangeComplete(result.TargetPath, true);
}
if (copy)
if (copy && !options.CopyOriginalFile)
{
try
{
@@ -439,5 +450,27 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
.Replace("%0e", episodeNumber.ToString("00", _usCulture))
.Replace("%00e", episodeNumber.ToString("000", _usCulture));
}
private bool IsSameEpisode(string sourcePath, string newPath)
{
FileInfo sourceFileInfo = new FileInfo(sourcePath);
FileInfo destinationFileInfo = new FileInfo(newPath);
try
{
if (sourceFileInfo.Length == destinationFileInfo.Length)
{
return true;
}
}
catch (FileNotFoundException)
{
return false;
}
return false;
}
}
}

View File

@@ -61,7 +61,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
var organizer = new EpisodeFileOrganizer(_organizationService, _config, _fileSystem, _logger, _libraryManager,
_libraryMonitor, _providerManager);
var result = await organizer.OrganizeEpisodeFile(file.FullName, options, false, cancellationToken).ConfigureAwait(false);
var result = await organizer.OrganizeEpisodeFile(file.FullName, options, options.OverwriteExistingEpisodes, cancellationToken).ConfigureAwait(false);
if (result.Status == FileSortingStatus.Success)
{

View File

@@ -306,6 +306,18 @@ namespace MediaBrowser.Server.Implementations.HttpServer
throw new ArgumentNullException("path");
}
return GetStaticFileResult(requestContext, path, MimeTypes.GetMimeType(path), fileShare, responseHeaders, isHeadRequest);
}
public object GetStaticFileResult(IRequest requestContext, string path, string contentType,
FileShare fileShare = FileShare.Read, IDictionary<string, string> responseHeaders = null,
bool isHeadRequest = false)
{
if (string.IsNullOrEmpty(path))
{
throw new ArgumentNullException("path");
}
if (fileShare != FileShare.Read && fileShare != FileShare.ReadWrite)
{
throw new ArgumentException("FileShare must be either Read or ReadWrite");
@@ -315,7 +327,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
var cacheKey = path + dateModified.Ticks;
return GetStaticResult(requestContext, cacheKey.GetMD5(), dateModified, null, MimeTypes.GetMimeType(path), () => Task.FromResult(GetFileStream(path, fileShare)), responseHeaders, isHeadRequest);
return GetStaticResult(requestContext, cacheKey.GetMD5(), dateModified, null, contentType, () => Task.FromResult(GetFileStream(path, fileShare)), responseHeaders, isHeadRequest);
}
/// <summary>

View File

@@ -449,7 +449,14 @@ namespace MediaBrowser.Server.Implementations.IO
var paths = _affectedPaths.Keys.ToList();
_affectedPaths.Clear();
await ProcessPathChanges(paths).ConfigureAwait(false);
try
{
await ProcessPathChanges(paths).ConfigureAwait(false);
}
catch (Exception ex)
{
Logger.ErrorException("Error processing directory changes", ex);
}
}
private void DisposeTimer()

View File

@@ -5,6 +5,7 @@ using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
@@ -484,6 +485,9 @@ namespace MediaBrowser.Server.Implementations.Library
await ItemRepository.DeleteItem(child.Id, CancellationToken.None).ConfigureAwait(false);
}
BaseItem removed;
_libraryItemsCache.TryRemove(item.Id, out removed);
ReportItemRemoved(item);
}
@@ -922,10 +926,10 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task.</returns>
public Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress)
{
// Ensure the location is unavailable.
// Ensure the location is available.
Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath);
return new PeopleValidator(this, _logger).ValidatePeople(cancellationToken, progress);
return new PeopleValidator(this, _logger).ValidatePeople(cancellationToken, new MetadataRefreshOptions(), progress);
}
/// <summary>
@@ -953,7 +957,7 @@ namespace MediaBrowser.Server.Implementations.Library
// Ensure the location is unavailable.
Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.MusicGenrePath);
return new MusicGenresValidator(this, _userManager, _logger).Run(progress, cancellationToken);
return new MusicGenresValidator(this, _logger).Run(progress, cancellationToken);
}
/// <summary>

View File

@@ -48,7 +48,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
var collectionType = args.GetCollectionType();
// If there's a collection type and it's not music, it can't be a series
// If there's a collection type and it's not music, don't allow it.
if (!string.IsNullOrEmpty(collectionType) &&
!string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase))
{

View File

@@ -56,21 +56,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
{
return null;
}
// If the parent is not a boxset, the only other allowed parent type is Folder
if (!(args.Parent is BoxSet))
{
if (args.Parent.GetType() != typeof(Folder))
{
return null;
}
}
}
// Since the looping is expensive, this is an optimization to help us avoid it
if (args.Path.IndexOf("[tvdbid", StringComparison.OrdinalIgnoreCase) != -1)
{
return null;
}
var isDirectory = args.IsDirectory;
@@ -89,34 +74,31 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
// Find movies with their own folders
if (isDirectory)
{
if (args.Path.IndexOf("[trailers]", StringComparison.OrdinalIgnoreCase) != -1 ||
string.Equals(collectionType, CollectionType.Trailers, StringComparison.OrdinalIgnoreCase))
if (string.Equals(collectionType, CollectionType.Trailers, StringComparison.OrdinalIgnoreCase))
{
return FindMovie<Trailer>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService);
return FindMovie<Trailer>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, false);
}
if (args.Path.IndexOf("[musicvideos]", StringComparison.OrdinalIgnoreCase) != -1 ||
string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
{
return FindMovie<MusicVideo>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService);
return FindMovie<MusicVideo>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, false);
}
if (args.Path.IndexOf("[adultvideos]", StringComparison.OrdinalIgnoreCase) != -1 ||
string.Equals(collectionType, CollectionType.AdultVideos, StringComparison.OrdinalIgnoreCase))
if (string.Equals(collectionType, CollectionType.AdultVideos, StringComparison.OrdinalIgnoreCase))
{
return FindMovie<AdultVideo>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService);
return FindMovie<AdultVideo>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, true);
}
if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
{
return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService);
return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, true);
}
if (string.IsNullOrEmpty(collectionType) ||
string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) ||
string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
{
return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService);
return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, true);
}
return null;
@@ -202,8 +184,10 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
/// <param name="path">The path.</param>
/// <param name="parent">The parent.</param>
/// <param name="fileSystemEntries">The file system entries.</param>
/// <param name="directoryService">The directory service.</param>
/// <param name="supportMultiFileItems">if set to <c>true</c> [support multi file items].</param>
/// <returns>Movie.</returns>
private T FindMovie<T>(string path, Folder parent, IEnumerable<FileSystemInfo> fileSystemEntries, IDirectoryService directoryService)
private T FindMovie<T>(string path, Folder parent, IEnumerable<FileSystemInfo> fileSystemEntries, IDirectoryService directoryService, bool supportMultiFileItems)
where T : Video, new()
{
var movies = new List<T>();
@@ -264,7 +248,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
}
}
if (movies.Count > 1)
if (movies.Count > 1 && supportMultiFileItems)
{
return GetMultiFileMovie(movies);
}

View File

@@ -37,6 +37,12 @@ namespace MediaBrowser.Server.Implementations.Library
var results = await GetSearchHints(inputItems, query).ConfigureAwait(false);
// Include item types
if (query.IncludeItemTypes.Length > 0)
{
results = results.Where(f => query.IncludeItemTypes.Contains(f.Item.GetType().Name, StringComparer.OrdinalIgnoreCase));
}
var searchResultArray = results.ToArray();
results = searchResultArray;
@@ -96,7 +102,9 @@ namespace MediaBrowser.Server.Implementations.Library
if (query.IncludeArtists)
{
// Find artists
var artists = _libraryManager.GetAllArtists(items)
var artists = items.OfType<Audio>()
.SelectMany(i => i.AllArtists)
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
foreach (var item in artists)

View File

@@ -189,15 +189,10 @@ namespace MediaBrowser.Server.Implementations.Library
/// Refreshes metadata for each user
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="force">if set to <c>true</c> [force].</param>
/// <returns>Task.</returns>
public Task RefreshUsersMetadata(CancellationToken cancellationToken, bool force = false)
public Task RefreshUsersMetadata(CancellationToken cancellationToken)
{
var tasks = Users.Select(user => user.RefreshMetadata(new MetadataRefreshOptions
{
ReplaceAllMetadata = force
}, cancellationToken)).ToList();
var tasks = Users.Select(user => user.RefreshMetadata(new MetadataRefreshOptions(), cancellationToken)).ToList();
return Task.WhenAll(tasks);
}

View File

@@ -1,8 +1,6 @@
using MediaBrowser.Common.Progress;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
@@ -69,10 +67,6 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
var numComplete = 0;
var userLibraries = _userManager.Users
.Select(i => new Tuple<Guid, List<IHasArtist>>(i.Id, i.RootFolder.GetRecursiveChildren(i).OfType<IHasArtist>().ToList()))
.ToList();
var numArtists = allArtists.Count;
foreach (var artist in allArtists)
@@ -91,11 +85,6 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
.ToList();
}
foreach (var lib in userLibraries)
{
SetItemCounts(artist, lib.Item1, lib.Item2);
}
numComplete++;
double percent = numComplete;
percent /= numArtists;
@@ -107,37 +96,6 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
progress.Report(100);
}
/// <summary>
/// Sets the item counts.
/// </summary>
/// <param name="artist">The artist.</param>
/// <param name="userId">The user id.</param>
/// <param name="allItems">All items.</param>
private void SetItemCounts(MusicArtist artist, Guid? userId, IEnumerable<IHasArtist> allItems)
{
var name = artist.Name;
var items = allItems
.Where(i => i.HasArtist(name))
.ToList();
var counts = new ItemByNameCounts
{
TotalCount = items.Count,
SongCount = items.OfType<Audio>().Count(),
AlbumCount = items.OfType<MusicAlbum>().Count(),
MusicVideoCount = items.OfType<MusicVideo>().Count()
};
if (userId.HasValue)
{
artist.SetItemByNameCounts(userId.Value, counts);
}
}
/// <summary>
/// Gets all artists.
/// </summary>
@@ -147,7 +105,8 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// <returns>Task{Artist[]}.</returns>
private async Task<List<MusicArtist>> GetAllArtists(IEnumerable<Audio> allSongs, CancellationToken cancellationToken, IProgress<double> progress)
{
var allArtists = _libraryManager.GetAllArtists(allSongs)
var allArtists = allSongs.SelectMany(i => i.AllArtists)
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
var returnArtists = new List<MusicArtist>(allArtists.Count);

View File

@@ -2,7 +2,6 @@
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -41,38 +40,24 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// <returns>Task.</returns>
public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
{
var userLibraries = _userManager.Users
.Select(i => new Tuple<Guid, List<Game>>(i.Id, i.RootFolder.GetRecursiveChildren(i).OfType<Game>().ToList()))
var items = _libraryManager.RootFolder.RecursiveChildren.Where(i => (i is Game))
.SelectMany(i => i.Genres)
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
var masterDictionary = new Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>>(StringComparer.OrdinalIgnoreCase);
progress.Report(2);
var numComplete = 0;
var count = items.Count;
foreach (var lib in userLibraries)
foreach (var name in items)
{
SetItemCounts(lib.Item1, lib.Item2, masterDictionary);
cancellationToken.ThrowIfCancellationRequested();
numComplete++;
double percent = numComplete;
percent /= userLibraries.Count;
percent *= 8;
progress.Report(percent);
}
progress.Report(10);
var count = masterDictionary.Count;
numComplete = 0;
foreach (var name in masterDictionary.Keys)
{
try
{
await UpdateItemByNameCounts(name, cancellationToken, masterDictionary[name]).ConfigureAwait(false);
var itemByName = _libraryManager.GetGameGenre(name);
await itemByName.RefreshMetadata(cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
@@ -81,7 +66,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
}
catch (Exception ex)
{
_logger.ErrorException("Error updating counts for {0}", ex, name);
_logger.ErrorException("Error refreshing {0}", ex, name);
}
numComplete++;
@@ -94,32 +79,5 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
progress.Report(100);
}
private Task UpdateItemByNameCounts(string name, CancellationToken cancellationToken, Dictionary<Guid, Dictionary<CountType, int>> counts)
{
var itemByName = _libraryManager.GetGameGenre(name);
foreach (var libraryId in counts.Keys)
{
var itemCounts = CountHelpers.GetCounts(counts[libraryId]);
itemByName.SetItemByNameCounts(libraryId, itemCounts);
}
return itemByName.RefreshMetadata(cancellationToken);
}
private void SetItemCounts(Guid userId, IEnumerable<BaseItem> allItems, Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>> masterDictionary)
{
foreach (var media in allItems)
{
var names = media
.Genres
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
CountHelpers.SetItemCounts(userId, media, names, masterDictionary);
}
}
}
}

View File

@@ -3,7 +3,6 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -42,38 +41,24 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// <returns>Task.</returns>
public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
{
var userLibraries = _userManager.Users
.Select(i => new Tuple<Guid, IList<BaseItem>>(i.Id, i.RootFolder.GetRecursiveChildren(i, m => !(m is IHasMusicGenres) && !(m is Game))))
var items = _libraryManager.RootFolder.RecursiveChildren.Where(i => !(i is IHasMusicGenres) && !(i is Game))
.SelectMany(i => i.Genres)
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
var masterDictionary = new Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>>(StringComparer.OrdinalIgnoreCase);
progress.Report(2);
var numComplete = 0;
var count = items.Count;
foreach (var lib in userLibraries)
foreach (var name in items)
{
SetItemCounts(lib.Item1, lib.Item2, masterDictionary);
cancellationToken.ThrowIfCancellationRequested();
numComplete++;
double percent = numComplete;
percent /= userLibraries.Count;
percent *= 8;
progress.Report(percent);
}
progress.Report(10);
var count = masterDictionary.Count;
numComplete = 0;
foreach (var name in masterDictionary.Keys)
{
try
{
await UpdateItemByNameCounts(name, cancellationToken, masterDictionary[name]).ConfigureAwait(false);
var itemByName = _libraryManager.GetGenre(name);
await itemByName.RefreshMetadata(cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
@@ -82,7 +67,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
}
catch (Exception ex)
{
_logger.ErrorException("Error updating counts for {0}", ex, name);
_logger.ErrorException("Error refreshing {0}", ex, name);
}
numComplete++;
@@ -95,32 +80,5 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
progress.Report(100);
}
private Task UpdateItemByNameCounts(string name, CancellationToken cancellationToken, Dictionary<Guid, Dictionary<CountType, int>> counts)
{
var itemByName = _libraryManager.GetGenre(name);
foreach (var libraryId in counts.Keys)
{
var itemCounts = CountHelpers.GetCounts(counts[libraryId]);
itemByName.SetItemByNameCounts(libraryId, itemCounts);
}
return itemByName.RefreshMetadata(cancellationToken);
}
private void SetItemCounts(Guid userId, IEnumerable<BaseItem> allItems, Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>> masterDictionary)
{
foreach (var media in allItems)
{
var names = media
.Genres
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
CountHelpers.SetItemCounts(userId, media, names, masterDictionary);
}
}
}
}

View File

@@ -1,9 +1,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -17,20 +15,14 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// </summary>
private readonly ILibraryManager _libraryManager;
/// <summary>
/// The _user manager
/// </summary>
private readonly IUserManager _userManager;
/// <summary>
/// The _logger
/// </summary>
private readonly ILogger _logger;
public MusicGenresValidator(ILibraryManager libraryManager, IUserManager userManager, ILogger logger)
public MusicGenresValidator(ILibraryManager libraryManager, ILogger logger)
{
_libraryManager = libraryManager;
_userManager = userManager;
_logger = logger;
}
@@ -42,38 +34,24 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// <returns>Task.</returns>
public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
{
var userLibraries = _userManager.Users
.Select(i => new Tuple<Guid, IList<BaseItem>>(i.Id, i.RootFolder.GetRecursiveChildren(i, m => m is IHasMusicGenres)))
var items = _libraryManager.RootFolder.RecursiveChildren.Where(i => (i is IHasMusicGenres))
.SelectMany(i => i.Genres)
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
var masterDictionary = new Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>>(StringComparer.OrdinalIgnoreCase);
progress.Report(2);
var numComplete = 0;
var count = items.Count;
foreach (var lib in userLibraries)
foreach (var name in items)
{
SetItemCounts(lib.Item1, lib.Item2, masterDictionary);
cancellationToken.ThrowIfCancellationRequested();
numComplete++;
double percent = numComplete;
percent /= userLibraries.Count;
percent *= 8;
progress.Report(percent);
}
progress.Report(10);
var count = masterDictionary.Count;
numComplete = 0;
foreach (var name in masterDictionary.Keys)
{
try
{
await UpdateItemByNameCounts(name, cancellationToken, masterDictionary[name]).ConfigureAwait(false);
var itemByName = _libraryManager.GetMusicGenre(name);
await itemByName.RefreshMetadata(cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
@@ -82,7 +60,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
}
catch (Exception ex)
{
_logger.ErrorException("Error updating counts for {0}", ex, name);
_logger.ErrorException("Error refreshing {0}", ex, name);
}
numComplete++;
@@ -95,32 +73,5 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
progress.Report(100);
}
private Task UpdateItemByNameCounts(string name, CancellationToken cancellationToken, Dictionary<Guid, Dictionary<CountType, int>> counts)
{
var itemByName = _libraryManager.GetMusicGenre(name);
foreach (var libraryId in counts.Keys)
{
var itemCounts = CountHelpers.GetCounts(counts[libraryId]);
itemByName.SetItemByNameCounts(libraryId, itemCounts);
}
return itemByName.RefreshMetadata(cancellationToken);
}
private void SetItemCounts(Guid userId, IEnumerable<BaseItem> allItems, Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>> masterDictionary)
{
foreach (var media in allItems)
{
var names = media
.Genres
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
CountHelpers.SetItemCounts(userId, media, names, masterDictionary);
}
}
}
}

View File

@@ -1,10 +1,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -17,20 +14,14 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// </summary>
private readonly ILibraryManager _libraryManager;
/// <summary>
/// The _user manager
/// </summary>
private readonly IUserManager _userManager;
/// <summary>
/// The _logger
/// </summary>
private readonly ILogger _logger;
public PeoplePostScanTask(ILibraryManager libraryManager, IUserManager userManager, ILogger logger)
public PeoplePostScanTask(ILibraryManager libraryManager, ILogger logger)
{
_libraryManager = libraryManager;
_userManager = userManager;
_logger = logger;
}
@@ -42,94 +33,12 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// <returns>Task.</returns>
public Task Run(IProgress<double> progress, CancellationToken cancellationToken)
{
return RunInternal(progress, cancellationToken);
}
private async Task RunInternal(IProgress<double> progress, CancellationToken cancellationToken)
{
var userLibraries = _userManager.Users
.Select(i => new Tuple<Guid, IList<BaseItem>>(i.Id, i.RootFolder.GetRecursiveChildren(i, null)))
.ToList();
var masterDictionary = new Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>>(StringComparer.OrdinalIgnoreCase);
progress.Report(2);
var numComplete = 0;
foreach (var lib in userLibraries)
return new PeopleValidator(_libraryManager, _logger).ValidatePeople(cancellationToken, new MetadataRefreshOptions
{
cancellationToken.ThrowIfCancellationRequested();
ImageRefreshMode = ImageRefreshMode.ValidationOnly,
MetadataRefreshMode = MetadataRefreshMode.None
SetItemCounts(lib.Item1, lib.Item2, masterDictionary);
numComplete++;
double percent = numComplete;
percent /= userLibraries.Count;
percent *= 8;
progress.Report(percent);
}
progress.Report(10);
var count = masterDictionary.Count;
numComplete = 0;
foreach (var name in masterDictionary.Keys)
{
cancellationToken.ThrowIfCancellationRequested();
try
{
var counts = masterDictionary[name];
var itemByName = _libraryManager.GetPerson(name);
// The only purpose here is to be able to react to image changes without running the people task.
// All other metadata can wait for that.
await itemByName.RefreshMetadata(new MetadataRefreshOptions
{
ImageRefreshMode = ImageRefreshMode.ValidationOnly,
MetadataRefreshMode = MetadataRefreshMode.None
}, cancellationToken).ConfigureAwait(false);
foreach (var libraryId in counts.Keys)
{
var itemCounts = CountHelpers.GetCounts(counts[libraryId]);
itemByName.SetItemByNameCounts(libraryId, itemCounts);
}
}
catch (Exception ex)
{
_logger.ErrorException("Error updating counts for {0}", ex, name);
}
numComplete++;
double percent = numComplete;
percent /= count;
percent *= 90;
progress.Report(percent + 10);
}
progress.Report(100);
}, progress);
}
private void SetItemCounts(Guid userId, IEnumerable<BaseItem> allItems, Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>> masterDictionary)
{
foreach (var media in allItems)
{
var names = media
.People.Select(i => i.Name)
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
CountHelpers.SetItemCounts(userId, media, names, masterDictionary);
}
}
}
}

View File

@@ -1,5 +1,6 @@
using MediaBrowser.Common.Progress;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
using MoreLinq;
using System;
@@ -38,9 +39,10 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// Validates the people.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="options">The options.</param>
/// <param name="progress">The progress.</param>
/// <returns>Task.</returns>
public async Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress)
public async Task ValidatePeople(CancellationToken cancellationToken, MetadataRefreshOptions options, IProgress<double> progress)
{
var innerProgress = new ActionableProgress<double>();
@@ -61,7 +63,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
{
var item = _libraryManager.GetPerson(person.Name);
await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
await item.RefreshMetadata(options, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{

View File

@@ -1,8 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -41,38 +39,24 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// <returns>Task.</returns>
public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
{
var userLibraries = _userManager.Users
.Select(i => new Tuple<Guid, IList<BaseItem>>(i.Id, i.RootFolder.GetRecursiveChildren(i, null)))
var items = _libraryManager.RootFolder.RecursiveChildren
.SelectMany(i => i.Studios)
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
var masterDictionary = new Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>>(StringComparer.OrdinalIgnoreCase);
progress.Report(2);
var numComplete = 0;
var count = items.Count;
foreach (var lib in userLibraries)
foreach (var name in items)
{
SetItemCounts(lib.Item1, lib.Item2, masterDictionary);
cancellationToken.ThrowIfCancellationRequested();
numComplete++;
double percent = numComplete;
percent /= userLibraries.Count;
percent *= 8;
progress.Report(percent);
}
progress.Report(10);
var count = masterDictionary.Count;
numComplete = 0;
foreach (var name in masterDictionary.Keys)
{
try
{
await UpdateItemByNameCounts(name, cancellationToken, masterDictionary[name]).ConfigureAwait(false);
var itemByName = _libraryManager.GetStudio(name);
await itemByName.RefreshMetadata(cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
@@ -81,7 +65,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
}
catch (Exception ex)
{
_logger.ErrorException("Error updating counts for {0}", ex, name);
_logger.ErrorException("Error refreshing {0}", ex, name);
}
numComplete++;
@@ -94,32 +78,5 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
progress.Report(100);
}
private Task UpdateItemByNameCounts(string name, CancellationToken cancellationToken, Dictionary<Guid, Dictionary<CountType, int>> counts)
{
var itemByName = _libraryManager.GetStudio(name);
foreach (var libraryId in counts.Keys)
{
var itemCounts = CountHelpers.GetCounts(counts[libraryId]);
itemByName.SetItemByNameCounts(libraryId, itemCounts);
}
return itemByName.RefreshMetadata(cancellationToken);
}
private void SetItemCounts(Guid userId, IEnumerable<BaseItem> allItems, Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>> masterDictionary)
{
foreach (var media in allItems)
{
var names = media
.Studios
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
CountHelpers.SetItemCounts(userId, media, names, masterDictionary);
}
}
}
}

View File

@@ -105,7 +105,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date)
{
return !item.HasImage(ImageType.Primary) && (DateTime.UtcNow - date).TotalDays >= 1;
var liveTvItem = item as LiveTvChannel;
if (liveTvItem != null)
{
return !liveTvItem.HasImage(ImageType.Primary) && (liveTvItem.HasProviderImage ?? true) && (DateTime.UtcNow - date).TotalHours >= 6;
}
return false;
}
}
}

View File

@@ -47,6 +47,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private List<Guid> _channelIdList = new List<Guid>();
private Dictionary<Guid, LiveTvProgram> _programs = new Dictionary<Guid, LiveTvProgram>();
private readonly ConcurrentDictionary<Guid, bool> _refreshedPrograms = new ConcurrentDictionary<Guid, bool>();
private readonly SemaphoreSlim _refreshSemaphore = new SemaphoreSlim(1, 1);
@@ -106,7 +107,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
_taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>();
}
public Task<QueryResult<ChannelInfoDto>> GetChannels(ChannelQuery query, CancellationToken cancellationToken)
public async Task<QueryResult<ChannelInfoDto>> GetChannels(ChannelQuery query, CancellationToken cancellationToken)
{
var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(new Guid(query.UserId));
@@ -161,17 +162,22 @@ namespace MediaBrowser.Server.Implementations.LiveTv
allEnumerable = allEnumerable.Take(query.Limit.Value);
}
var returnChannels = allEnumerable
.Select(i => _tvDtoService.GetChannelInfoDto(i, GetCurrentProgram(i.ExternalId), user))
.ToArray();
var returnList = new List<ChannelInfoDto>();
foreach (var channel in allEnumerable)
{
var currentProgram = await GetCurrentProgram(channel.ExternalId, cancellationToken).ConfigureAwait(false);
returnList.Add(_tvDtoService.GetChannelInfoDto(channel, currentProgram, user));
}
var result = new QueryResult<ChannelInfoDto>
{
Items = returnChannels,
Items = returnList.ToArray(),
TotalRecordCount = allChannels.Count
};
return Task.FromResult(result);
return result;
}
public LiveTvChannel GetInternalChannel(string id)
@@ -184,16 +190,41 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return _libraryManager.GetItemById(id) as LiveTvChannel;
}
public LiveTvProgram GetInternalProgram(string id)
public async Task<LiveTvProgram> GetInternalProgram(string id, CancellationToken cancellationToken)
{
var guid = new Guid(id);
LiveTvProgram obj = null;
_programs.TryGetValue(guid, out obj);
if (obj != null)
{
await RefreshIfNeeded(obj, cancellationToken).ConfigureAwait(false);
}
return obj;
}
private async Task RefreshIfNeeded(IEnumerable<LiveTvProgram> programs, CancellationToken cancellationToken)
{
foreach (var program in programs)
{
await RefreshIfNeeded(program, cancellationToken).ConfigureAwait(false);
}
}
private async Task RefreshIfNeeded(LiveTvProgram program, CancellationToken cancellationToken)
{
if (_refreshedPrograms.ContainsKey(program.Id))
{
return;
}
await program.RefreshMetadata(CancellationToken.None).ConfigureAwait(false);
_refreshedPrograms.TryAdd(program.Id, true);
}
public async Task<ILiveTvRecording> GetInternalRecording(string id, CancellationToken cancellationToken)
{
var service = ActiveService;
@@ -336,10 +367,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return item;
}
private async Task<LiveTvProgram> GetProgram(ProgramInfo info, ChannelType channelType, string serviceName, CancellationToken cancellationToken)
private LiveTvProgram GetProgram(ProgramInfo info, ChannelType channelType, string serviceName, CancellationToken cancellationToken)
{
var isNew = false;
var id = _tvDtoService.GetInternalProgramId(serviceName, info.Id);
var item = _itemRepo.RetrieveItem(id) as LiveTvProgram;
@@ -353,8 +382,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
DateCreated = DateTime.UtcNow,
DateModified = DateTime.UtcNow
};
isNew = true;
}
item.ChannelType = channelType;
@@ -386,12 +413,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
item.RunTimeTicks = (info.EndDate - info.StartDate).Ticks;
item.StartDate = info.StartDate;
await item.RefreshMetadata(new MetadataRefreshOptions
{
ForceSave = isNew
}, cancellationToken);
return item;
}
@@ -464,7 +485,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
public async Task<ProgramInfoDto> GetProgram(string id, CancellationToken cancellationToken, User user = null)
{
var program = GetInternalProgram(id);
var program = await GetInternalProgram(id, cancellationToken).ConfigureAwait(false);
var channel = GetChannel(program);
@@ -531,7 +552,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
programs = programs.Where(i => i.IsParentalAllowed(currentUser));
}
var returnArray = programs
var programList = programs.ToList();
var returnArray = programList
.Select(i =>
{
var channel = GetChannel(i);
@@ -540,6 +563,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
})
.ToArray();
await RefreshIfNeeded(programList, cancellationToken).ConfigureAwait(false);
await AddRecordingInfo(returnArray, cancellationToken).ConfigureAwait(false);
var result = new QueryResult<ProgramInfoDto>
@@ -582,7 +607,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
.Select(i => _libraryManager.GetGenre(i))
.ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
programs = programList.OrderByDescending(i => GetRecommendationScore(i, user.Id, serviceName, genres))
programs = programList.OrderBy(i => i.HasImage(ImageType.Primary) ? 0 : 1)
.ThenByDescending(i => GetRecommendationScore(i, user.Id, serviceName, genres))
.ThenBy(i => i.StartDate);
if (query.Limit.HasValue)
@@ -591,7 +617,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
.OrderBy(i => i.StartDate);
}
var returnArray = programs
programList = programs.ToList();
await RefreshIfNeeded(programList, cancellationToken).ConfigureAwait(false);
var returnArray = programList
.Select(i =>
{
var channel = GetChannel(i);
@@ -790,8 +820,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var channelPrograms = await service.GetProgramsAsync(currentChannel.ExternalId, start, end, cancellationToken).ConfigureAwait(false);
var programTasks = channelPrograms.Select(program => GetProgram(program, currentChannel.ChannelType, service.Name, cancellationToken));
var programEntities = await Task.WhenAll(programTasks).ConfigureAwait(false);
var programEntities = channelPrograms.Select(program => GetProgram(program, currentChannel.ChannelType, service.Name, cancellationToken));
programs.AddRange(programEntities);
}
@@ -812,6 +841,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
_programs = programs.ToDictionary(i => i.Id);
_refreshedPrograms.Clear();
progress.Report(90);
// Load these now which will prefetch metadata
@@ -955,6 +985,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
entities = entities.Where(i => i.IsParentalAllowed(currentUser));
}
var entityList = entities.ToList();
entities = entityList;
if (query.StartIndex.HasValue)
{
entities = entities.Skip(query.StartIndex.Value);
@@ -976,7 +1009,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return new QueryResult<RecordingInfoDto>
{
Items = returnArray,
TotalRecordCount = returnArray.Length
TotalRecordCount = entityList.Count
};
}
@@ -1030,14 +1063,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv
.Where(i => _tvDtoService.GetInternalSeriesTimerId(currentServiceName, i.SeriesTimerId) == guid);
}
var returnArray = timers
.Select(i =>
{
var program = string.IsNullOrEmpty(i.ProgramId) ? null : GetInternalProgram(_tvDtoService.GetInternalProgramId(service.Name, i.ProgramId).ToString("N"));
var channel = string.IsNullOrEmpty(i.ChannelId) ? null : GetInternalChannel(_tvDtoService.GetInternalChannelId(service.Name, i.ChannelId));
var returnList = new List<TimerInfoDto>();
return _tvDtoService.GetTimerInfoDto(i, service, program, channel);
})
foreach (var i in timers)
{
var program = string.IsNullOrEmpty(i.ProgramId) ?
null :
await GetInternalProgram(_tvDtoService.GetInternalProgramId(service.Name, i.ProgramId).ToString("N"), cancellationToken).ConfigureAwait(false);
var channel = string.IsNullOrEmpty(i.ChannelId) ? null : GetInternalChannel(_tvDtoService.GetInternalChannelId(service.Name, i.ChannelId));
returnList.Add(_tvDtoService.GetTimerInfoDto(i, service, program, channel));
}
var returnArray = returnList
.OrderBy(i => i.StartDate)
.ToArray();
@@ -1162,24 +1201,33 @@ namespace MediaBrowser.Server.Implementations.LiveTv
};
}
public Task<ChannelInfoDto> GetChannel(string id, CancellationToken cancellationToken, User user = null)
public async Task<ChannelInfoDto> GetChannel(string id, CancellationToken cancellationToken, User user = null)
{
var channel = GetInternalChannel(id);
var dto = _tvDtoService.GetChannelInfoDto(channel, GetCurrentProgram(channel.ExternalId), user);
var currentProgram = await GetCurrentProgram(channel.ExternalId, cancellationToken).ConfigureAwait(false);
return Task.FromResult(dto);
var dto = _tvDtoService.GetChannelInfoDto(channel, currentProgram, user);
return dto;
}
private LiveTvProgram GetCurrentProgram(string externalChannelId)
private async Task<LiveTvProgram> GetCurrentProgram(string externalChannelId, CancellationToken cancellationToken)
{
var now = DateTime.UtcNow;
return _programs.Values
var program = _programs.Values
.Where(i => string.Equals(externalChannelId, i.ExternalChannelId, StringComparison.OrdinalIgnoreCase))
.OrderBy(i => i.StartDate)
.SkipWhile(i => now >= (i.EndDate ?? DateTime.MinValue))
.FirstOrDefault();
if (program != null)
{
await RefreshIfNeeded(program, cancellationToken).ConfigureAwait(false);
}
return program;
}
private async Task<SeriesTimerInfo> GetNewTimerDefaultsInternal(CancellationToken cancellationToken, LiveTvProgram program = null)
@@ -1235,7 +1283,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
public async Task<SeriesTimerInfoDto> GetNewTimerDefaults(string programId, CancellationToken cancellationToken)
{
var program = GetInternalProgram(programId);
var program = await GetInternalProgram(programId, cancellationToken).ConfigureAwait(false);
var programDto = await GetProgram(programId, cancellationToken).ConfigureAwait(false);
var defaults = await GetNewTimerDefaultsInternal(cancellationToken, program).ConfigureAwait(false);

View File

@@ -105,7 +105,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date)
{
return !item.HasImage(ImageType.Primary) && (DateTime.UtcNow - date).TotalHours >= 6;
var liveTvItem = item as LiveTvProgram;
if (liveTvItem != null)
{
return !liveTvItem.HasImage(ImageType.Primary) && (liveTvItem.HasProviderImage ?? true) && (DateTime.UtcNow - date).TotalHours >= 6;
}
return false;
}
}
}

View File

@@ -105,7 +105,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date)
{
return !item.HasImage(ImageType.Primary) && (DateTime.UtcNow - date).TotalHours >= 3;
var liveTvItem = item as ILiveTvRecording;
if (liveTvItem != null)
{
return !liveTvItem.HasImage(ImageType.Primary) && (liveTvItem.RecordingInfo.HasImage ?? true) && (DateTime.UtcNow - date).TotalHours >= 6;
}
return false;
}
}
}

View File

@@ -56,20 +56,18 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll</HintPath>
</Reference>
<Reference Include="Mono.Nat">
<HintPath>..\packages\Mono.Nat.1.1.13\lib\Net40\Mono.Nat.dll</HintPath>
<Reference Include="Mono.Nat, Version=1.2.3.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Mono.Nat.1.2.3\lib\Net40\Mono.Nat.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Api.Swagger">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SQLite, Version=1.0.90.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86" Condition=" '$(ConfigurationName)' != 'Release Mono' ">
<Reference Include="System.Data.SQLite, Version=1.0.91.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\System.Data.SQLite.x86.1.0.90.0\lib\net45\System.Data.SQLite.dll</HintPath>
</Reference>
<Reference Include="System.Data.SQLite.Linq" Condition=" '$(ConfigurationName)' != 'Release Mono' ">
<HintPath>..\packages\System.Data.SQLite.x86.1.0.90.0\lib\net45\System.Data.SQLite.Linq.dll</HintPath>
<HintPath>..\packages\System.Data.SQLite.Core.1.0.91.3\lib\net45\System.Data.SQLite.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="Microsoft.CSharp" />
@@ -108,6 +106,8 @@
<Link>Properties\SharedVersion.cs</Link>
</Compile>
<Compile Include="BdInfo\BdInfoExaminer.cs" />
<Compile Include="Collections\CollectionManager.cs" />
<Compile Include="Collections\CollectionsDynamicFolder.cs" />
<Compile Include="Configuration\ServerConfigurationManager.cs" />
<Compile Include="Drawing\ImageHeader.cs" />
<Compile Include="Drawing\PercentPlayedDrawer.cs" />
@@ -216,7 +216,6 @@
<Compile Include="Sorting\AirTimeComparer.cs" />
<Compile Include="Sorting\AlbumArtistComparer.cs" />
<Compile Include="Sorting\AlbumComparer.cs" />
<Compile Include="Sorting\AlbumCountComparer.cs" />
<Compile Include="Sorting\AlphanumComparator.cs" />
<Compile Include="Sorting\ArtistComparer.cs" />
<Compile Include="Sorting\BudgetComparer.cs" />
@@ -224,29 +223,26 @@
<Compile Include="Sorting\CriticRatingComparer.cs" />
<Compile Include="Sorting\DateCreatedComparer.cs" />
<Compile Include="Sorting\DatePlayedComparer.cs" />
<Compile Include="Sorting\EpisodeCountComparer.cs" />
<Compile Include="Sorting\GameSystemComparer.cs" />
<Compile Include="Sorting\IsFolderComparer.cs" />
<Compile Include="Sorting\IsUnplayedComparer.cs" />
<Compile Include="Sorting\MetascoreComparer.cs" />
<Compile Include="Sorting\MovieCountComparer.cs" />
<Compile Include="Sorting\MusicVideoCountComparer.cs" />
<Compile Include="Sorting\NameComparer.cs" />
<Compile Include="Sorting\OfficialRatingComparer.cs" />
<Compile Include="Sorting\PlayCountComparer.cs" />
<Compile Include="Sorting\PlayersComparer.cs" />
<Compile Include="Sorting\PremiereDateComparer.cs" />
<Compile Include="Sorting\ProductionYearComparer.cs" />
<Compile Include="Sorting\RandomComparer.cs" />
<Compile Include="Sorting\RevenueComparer.cs" />
<Compile Include="Sorting\RuntimeComparer.cs" />
<Compile Include="Sorting\SeriesCountComparer.cs" />
<Compile Include="Sorting\SeriesSortNameComparer.cs" />
<Compile Include="Sorting\SongCountComparer.cs" />
<Compile Include="Sorting\SortNameComparer.cs" />
<Compile Include="Persistence\SqliteDisplayPreferencesRepository.cs" />
<Compile Include="Persistence\SqliteItemRepository.cs" />
<Compile Include="Persistence\SqliteUserDataRepository.cs" />
<Compile Include="Persistence\SqliteUserRepository.cs" />
<Compile Include="Sorting\TrailerCountComparer.cs" />
<Compile Include="Sorting\StudioComparer.cs" />
<Compile Include="Sorting\VideoBitRateComparer.cs" />
<Compile Include="Themes\AppThemeManager.cs" />
<Compile Include="Udp\UdpMessageReceivedEventArgs.cs" />
@@ -376,6 +372,12 @@
<Link>swagger-ui\swagger-ui.min.js</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="x64\SQLite.Interop.dll" Condition=" '$(ConfigurationName)' != 'Release Mono' ">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="x86\SQLite.Interop.dll" Condition=" '$(ConfigurationName)' != 'Release Mono' ">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<EmbeddedResource Include="Localization\Ratings\be.txt" />
</ItemGroup>
<ItemGroup>

View File

@@ -69,6 +69,8 @@ namespace MediaBrowser.Server.Implementations.Session
private IEnumerable<ISessionControllerFactory> _sessionFactories = new List<ISessionControllerFactory>();
private readonly SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1);
/// <summary>
/// Initializes a new instance of the <see cref="SessionManager" /> class.
/// </summary>
@@ -146,7 +148,7 @@ namespace MediaBrowser.Server.Implementations.Session
var userId = user == null ? (Guid?)null : user.Id;
var username = user == null ? null : user.Name;
var session = GetSessionInfo(clientType, appVersion, deviceId, deviceName, remoteEndPoint, userId, username);
var session = await GetSessionInfo(clientType, appVersion, deviceId, deviceName, remoteEndPoint, userId, username).ConfigureAwait(false);
session.LastActivityDate = activityDate;
@@ -171,6 +173,46 @@ namespace MediaBrowser.Server.Implementations.Session
return session;
}
public async Task ReportSessionEnded(Guid sessionId)
{
await _sessionLock.WaitAsync(CancellationToken.None).ConfigureAwait(false);
try
{
var session = GetSession(sessionId);
if (session == null)
{
throw new ArgumentException("Session not found");
}
var key = GetSessionKey(session.Client, session.ApplicationVersion, session.DeviceId);
SessionInfo removed;
if (_activeConnections.TryRemove(key, out removed))
{
var disposable = removed.SessionController as IDisposable;
if (disposable != null)
{
try
{
disposable.Dispose();
}
catch (Exception ex)
{
_logger.ErrorException("Error disposing session controller", ex);
}
}
}
}
finally
{
_sessionLock.Release();
}
}
/// <summary>
/// Updates the now playing item id.
/// </summary>
@@ -207,6 +249,11 @@ namespace MediaBrowser.Server.Implementations.Session
}
}
private string GetSessionKey(string clientType, string appVersion, string deviceId)
{
return clientType + deviceId + appVersion;
}
/// <summary>
/// Gets the connection.
/// </summary>
@@ -218,36 +265,45 @@ namespace MediaBrowser.Server.Implementations.Session
/// <param name="userId">The user identifier.</param>
/// <param name="username">The username.</param>
/// <returns>SessionInfo.</returns>
private SessionInfo GetSessionInfo(string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint, Guid? userId, string username)
private async Task<SessionInfo> GetSessionInfo(string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint, Guid? userId, string username)
{
var key = clientType + deviceId + appVersion;
var key = GetSessionKey(clientType, appVersion, deviceId);
var connection = _activeConnections.GetOrAdd(key, keyName => new SessionInfo
await _sessionLock.WaitAsync(CancellationToken.None).ConfigureAwait(false);
try
{
Client = clientType,
DeviceId = deviceId,
ApplicationVersion = appVersion,
Id = Guid.NewGuid()
});
var connection = _activeConnections.GetOrAdd(key, keyName => new SessionInfo
{
Client = clientType,
DeviceId = deviceId,
ApplicationVersion = appVersion,
Id = Guid.NewGuid()
});
connection.DeviceName = deviceName;
connection.UserId = userId;
connection.UserName = username;
connection.RemoteEndPoint = remoteEndPoint;
connection.DeviceName = deviceName;
connection.UserId = userId;
connection.UserName = username;
connection.RemoteEndPoint = remoteEndPoint;
if (!userId.HasValue)
{
connection.AdditionalUsers.Clear();
if (!userId.HasValue)
{
connection.AdditionalUsers.Clear();
}
if (connection.SessionController == null)
{
connection.SessionController = _sessionFactories
.Select(i => i.GetSessionController(connection))
.FirstOrDefault(i => i != null);
}
return connection;
}
if (connection.SessionController == null)
finally
{
connection.SessionController = _sessionFactories
.Select(i => i.GetSessionController(connection))
.FirstOrDefault(i => i != null);
_sessionLock.Release();
}
return connection;
}
private List<User> GetUsers(SessionInfo session)

View File

@@ -1,71 +0,0 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.Querying;
namespace MediaBrowser.Server.Implementations.Sorting
{
class AlbumCountComparer : IUserBaseItemComparer
{
/// <summary>
/// Gets or sets the user.
/// </summary>
/// <value>The user.</value>
public User User { get; set; }
/// <summary>
/// Gets or sets the user manager.
/// </summary>
/// <value>The user manager.</value>
public IUserManager UserManager { get; set; }
/// <summary>
/// Gets or sets the user data repository.
/// </summary>
/// <value>The user data repository.</value>
public IUserDataManager UserDataRepository { get; set; }
/// <summary>
/// Compares the specified x.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>System.Int32.</returns>
public int Compare(BaseItem x, BaseItem y)
{
return GetValue(x).CompareTo(GetValue(y));
}
/// <summary>
/// Gets the date.
/// </summary>
/// <param name="x">The x.</param>
/// <returns>DateTime.</returns>
private int GetValue(BaseItem x)
{
var itemByName = x as IItemByName;
if (itemByName != null)
{
var counts = itemByName.GetItemByNameCounts(User.Id);
if (counts != null)
{
return counts.AlbumCount;
}
}
return 0;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
public string Name
{
get { return ItemSortBy.AlbumCount; }
}
}
}

View File

@@ -1,71 +0,0 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.Querying;
namespace MediaBrowser.Server.Implementations.Sorting
{
class EpisodeCountComparer : IUserBaseItemComparer
{
/// <summary>
/// Gets or sets the user.
/// </summary>
/// <value>The user.</value>
public User User { get; set; }
/// <summary>
/// Gets or sets the user manager.
/// </summary>
/// <value>The user manager.</value>
public IUserManager UserManager { get; set; }
/// <summary>
/// Gets or sets the user data repository.
/// </summary>
/// <value>The user data repository.</value>
public IUserDataManager UserDataRepository { get; set; }
/// <summary>
/// Compares the specified x.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>System.Int32.</returns>
public int Compare(BaseItem x, BaseItem y)
{
return GetValue(x).CompareTo(GetValue(y));
}
/// <summary>
/// Gets the date.
/// </summary>
/// <param name="x">The x.</param>
/// <returns>DateTime.</returns>
private int GetValue(BaseItem x)
{
var itemByName = x as IItemByName;
if (itemByName != null)
{
var counts = itemByName.GetItemByNameCounts(User.Id);
if (counts != null)
{
return counts.EpisodeCount;
}
}
return 0;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
public string Name
{
get { return ItemSortBy.EpisodeCount; }
}
}
}

View File

@@ -0,0 +1,54 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.Querying;
using System;
namespace MediaBrowser.Server.Implementations.Sorting
{
public class GameSystemComparer : IBaseItemComparer
{
/// <summary>
/// Compares the specified x.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>System.Int32.</returns>
public int Compare(BaseItem x, BaseItem y)
{
return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase);
}
/// <summary>
/// Gets the value.
/// </summary>
/// <param name="x">The x.</param>
/// <returns>System.String.</returns>
private string GetValue(BaseItem x)
{
var game = x as Game;
if (game != null)
{
return game.GameSystem;
}
var system = x as GameSystem;
if (system != null)
{
return system.GameSystemName;
}
return string.Empty;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
public string Name
{
get { return ItemSortBy.GameSystem; }
}
}
}

View File

@@ -1,71 +0,0 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.Querying;
namespace MediaBrowser.Server.Implementations.Sorting
{
public class MovieCountComparer : IUserBaseItemComparer
{
/// <summary>
/// Gets or sets the user.
/// </summary>
/// <value>The user.</value>
public User User { get; set; }
/// <summary>
/// Gets or sets the user manager.
/// </summary>
/// <value>The user manager.</value>
public IUserManager UserManager { get; set; }
/// <summary>
/// Gets or sets the user data repository.
/// </summary>
/// <value>The user data repository.</value>
public IUserDataManager UserDataRepository { get; set; }
/// <summary>
/// Compares the specified x.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>System.Int32.</returns>
public int Compare(BaseItem x, BaseItem y)
{
return GetValue(x).CompareTo(GetValue(y));
}
/// <summary>
/// Gets the date.
/// </summary>
/// <param name="x">The x.</param>
/// <returns>DateTime.</returns>
private int GetValue(BaseItem x)
{
var itemByName = x as IItemByName;
if (itemByName != null)
{
var counts = itemByName.GetItemByNameCounts(User.Id);
if (counts != null)
{
return counts.MovieCount;
}
}
return 0;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
public string Name
{
get { return ItemSortBy.MovieCount; }
}
}
}

View File

@@ -1,71 +0,0 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.Querying;
namespace MediaBrowser.Server.Implementations.Sorting
{
class MusicVideoCountComparer : IUserBaseItemComparer
{
/// <summary>
/// Gets or sets the user.
/// </summary>
/// <value>The user.</value>
public User User { get; set; }
/// <summary>
/// Gets or sets the user manager.
/// </summary>
/// <value>The user manager.</value>
public IUserManager UserManager { get; set; }
/// <summary>
/// Gets or sets the user data repository.
/// </summary>
/// <value>The user data repository.</value>
public IUserDataManager UserDataRepository { get; set; }
/// <summary>
/// Compares the specified x.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>System.Int32.</returns>
public int Compare(BaseItem x, BaseItem y)
{
return GetValue(x).CompareTo(GetValue(y));
}
/// <summary>
/// Gets the date.
/// </summary>
/// <param name="x">The x.</param>
/// <returns>DateTime.</returns>
private int GetValue(BaseItem x)
{
var itemByName = x as IItemByName;
if (itemByName != null)
{
var counts = itemByName.GetItemByNameCounts(User.Id);
if (counts != null)
{
return counts.MusicVideoCount;
}
}
return 0;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
public string Name
{
get { return ItemSortBy.MusicVideoCount; }
}
}
}

View File

@@ -0,0 +1,46 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.Querying;
namespace MediaBrowser.Server.Implementations.Sorting
{
public class PlayersComparer : IBaseItemComparer
{
/// <summary>
/// Compares the specified x.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>System.Int32.</returns>
public int Compare(BaseItem x, BaseItem y)
{
return GetValue(x).CompareTo(GetValue(y));
}
/// <summary>
/// Gets the value.
/// </summary>
/// <param name="x">The x.</param>
/// <returns>System.String.</returns>
private int GetValue(BaseItem x)
{
var game = x as Game;
if (game != null)
{
return game.PlayersSupported ?? 0;
}
return 0;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
public string Name
{
get { return ItemSortBy.Players; }
}
}
}

View File

@@ -1,71 +0,0 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.Querying;
namespace MediaBrowser.Server.Implementations.Sorting
{
class SeriesCountComparer : IUserBaseItemComparer
{
/// <summary>
/// Gets or sets the user.
/// </summary>
/// <value>The user.</value>
public User User { get; set; }
/// <summary>
/// Gets or sets the user manager.
/// </summary>
/// <value>The user manager.</value>
public IUserManager UserManager { get; set; }
/// <summary>
/// Gets or sets the user data repository.
/// </summary>
/// <value>The user data repository.</value>
public IUserDataManager UserDataRepository { get; set; }
/// <summary>
/// Compares the specified x.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>System.Int32.</returns>
public int Compare(BaseItem x, BaseItem y)
{
return GetValue(x).CompareTo(GetValue(y));
}
/// <summary>
/// Gets the date.
/// </summary>
/// <param name="x">The x.</param>
/// <returns>DateTime.</returns>
private int GetValue(BaseItem x)
{
var itemByName = x as IItemByName;
if (itemByName != null)
{
var counts = itemByName.GetItemByNameCounts(User.Id);
if (counts != null)
{
return counts.SeriesCount;
}
}
return 0;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
public string Name
{
get { return ItemSortBy.SeriesCount; }
}
}
}

View File

@@ -1,71 +0,0 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.Querying;
namespace MediaBrowser.Server.Implementations.Sorting
{
class SongCountComparer : IUserBaseItemComparer
{
/// <summary>
/// Gets or sets the user.
/// </summary>
/// <value>The user.</value>
public User User { get; set; }
/// <summary>
/// Gets or sets the user manager.
/// </summary>
/// <value>The user manager.</value>
public IUserManager UserManager { get; set; }
/// <summary>
/// Gets or sets the user data repository.
/// </summary>
/// <value>The user data repository.</value>
public IUserDataManager UserDataRepository { get; set; }
/// <summary>
/// Compares the specified x.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>System.Int32.</returns>
public int Compare(BaseItem x, BaseItem y)
{
return GetValue(x).CompareTo(GetValue(y));
}
/// <summary>
/// Gets the date.
/// </summary>
/// <param name="x">The x.</param>
/// <returns>DateTime.</returns>
private int GetValue(BaseItem x)
{
var itemByName = x as IItemByName;
if (itemByName != null)
{
var counts = itemByName.GetItemByNameCounts(User.Id);
if (counts != null)
{
return counts.SongCount;
}
}
return 0;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
public string Name
{
get { return ItemSortBy.SongCount; }
}
}
}

View File

@@ -0,0 +1,30 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.Querying;
using System.Linq;
namespace MediaBrowser.Server.Implementations.Sorting
{
public class StudioComparer : IBaseItemComparer
{
/// <summary>
/// Compares the specified x.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>System.Int32.</returns>
public int Compare(BaseItem x, BaseItem y)
{
return AlphanumComparator.CompareValues(x.Studios.FirstOrDefault() ?? string.Empty, y.Studios.FirstOrDefault() ?? string.Empty);
}
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
public string Name
{
get { return ItemSortBy.Studio; }
}
}
}

View File

@@ -1,71 +0,0 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.Querying;
namespace MediaBrowser.Server.Implementations.Sorting
{
public class TrailerCountComparer : IUserBaseItemComparer
{
/// <summary>
/// Gets or sets the user.
/// </summary>
/// <value>The user.</value>
public User User { get; set; }
/// <summary>
/// Gets or sets the user manager.
/// </summary>
/// <value>The user manager.</value>
public IUserManager UserManager { get; set; }
/// <summary>
/// Gets or sets the user data repository.
/// </summary>
/// <value>The user data repository.</value>
public IUserDataManager UserDataRepository { get; set; }
/// <summary>
/// Compares the specified x.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>System.Int32.</returns>
public int Compare(BaseItem x, BaseItem y)
{
return GetValue(x).CompareTo(GetValue(y));
}
/// <summary>
/// Gets the date.
/// </summary>
/// <param name="x">The x.</param>
/// <returns>DateTime.</returns>
private int GetValue(BaseItem x)
{
var itemByName = x as IItemByName;
if (itemByName != null)
{
var counts = itemByName.GetItemByNameCounts(User.Id);
if (counts != null)
{
return counts.TrailerCount;
}
}
return 0;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
public string Name
{
get { return ItemSortBy.TrailerCount; }
}
}
}

View File

@@ -2,7 +2,7 @@
<packages>
<package id="Alchemy" version="2.2.1" targetFramework="net45" />
<package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" />
<package id="Mono.Nat" version="1.1.13" targetFramework="net45" />
<package id="Mono.Nat" version="1.2.3" targetFramework="net45" />
<package id="morelinq" version="1.0.16006" targetFramework="net45" />
<package id="System.Data.SQLite.x86" version="1.0.90.0" targetFramework="net45" />
<package id="System.Data.SQLite.Core" version="1.0.91.3" targetFramework="net45" />
</packages>