Merge branch 'dev'

Conflicts:
	MediaBrowser.Controller/Entities/BaseItem.cs
	MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-apiclient/.bower.json
	MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/.bower.json
	MediaBrowser.WebDashboard/dashboard-ui/bower_components/iron-icons/.bower.json
	MediaBrowser.WebDashboard/dashboard-ui/bower_components/iron-icons/bower.json
	MediaBrowser.WebDashboard/dashboard-ui/strings/html/kk.json
	MediaBrowser.WebDashboard/dashboard-ui/strings/html/ru.json
	MediaBrowser.WebDashboard/dashboard-ui/strings/javascript/kk.json
	MediaBrowser.WebDashboard/dashboard-ui/strings/javascript/ru.json
	SharedVersion.cs
This commit is contained in:
Luke Pulverenti 2016-01-11 21:55:52 -05:00
commit 8a2e023e28
170 changed files with 4559 additions and 2764 deletions

View File

@ -37,7 +37,7 @@
</Reference> </Reference>
<Reference Include="ImageMagickSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="ImageMagickSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ImageMagickSharp.1.0.0.16\lib\net45\ImageMagickSharp.dll</HintPath> <HintPath>..\packages\ImageMagickSharp.1.0.0.17\lib\net45\ImageMagickSharp.dll</HintPath>
</Reference> </Reference>
<Reference Include="Patterns.Logging"> <Reference Include="Patterns.Logging">
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath> <HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>

View File

@ -72,11 +72,16 @@ namespace Emby.Drawing.ImageMagick
private void LogVersion() private void LogVersion()
{ {
_logger.Info("ImageMagick version: " + Wand.VersionString); _logger.Info("ImageMagick version: " + GetVersion());
TestWebp(); TestWebp();
Wand.SetMagickThreadCount(1); Wand.SetMagickThreadCount(1);
} }
public static string GetVersion()
{
return Wand.VersionString;
}
private bool _webpAvailable = true; private bool _webpAvailable = true;
private void TestWebp() private void TestWebp()
{ {
@ -148,7 +153,7 @@ namespace Emby.Drawing.ImageMagick
DrawIndicator(originalImage, width, height, options); DrawIndicator(originalImage, width, height, options);
originalImage.CurrentImage.CompressionQuality = quality; originalImage.CurrentImage.CompressionQuality = quality;
//originalImage.CurrentImage.StripImage(); originalImage.CurrentImage.StripImage();
originalImage.SaveImage(outputPath); originalImage.SaveImage(outputPath);
} }
@ -165,7 +170,7 @@ namespace Emby.Drawing.ImageMagick
DrawIndicator(wand, width, height, options); DrawIndicator(wand, width, height, options);
wand.CurrentImage.CompressionQuality = quality; wand.CurrentImage.CompressionQuality = quality;
//wand.CurrentImage.StripImage(); wand.CurrentImage.StripImage();
wand.SaveImage(outputPath); wand.SaveImage(outputPath);
} }
@ -175,16 +180,15 @@ namespace Emby.Drawing.ImageMagick
} }
private void ScaleImage(MagickWand wand, int width, int height) private void ScaleImage(MagickWand wand, int width, int height)
{
if (_config.Configuration.EnableHighQualityImageScaling)
{ {
wand.CurrentImage.ResizeImage(width, height); wand.CurrentImage.ResizeImage(width, height);
//if (_config.Configuration.EnableHighQualityImageScaling) }
//{ else
// wand.CurrentImage.ResizeImage(width, height); {
//} wand.CurrentImage.ScaleImage(width, height);
//else }
//{
// wand.CurrentImage.ScaleImage(width, height);
//}
} }
/// <summary> /// <summary>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" /> <package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
<package id="ImageMagickSharp" version="1.0.0.16" targetFramework="net45" /> <package id="ImageMagickSharp" version="1.0.0.17" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" /> <package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
</packages> </packages>

View File

@ -198,50 +198,6 @@ namespace MediaBrowser.Api
return libraryManager.GetPerson(DeSlugPersonName(name, libraryManager)); return libraryManager.GetPerson(DeSlugPersonName(name, libraryManager));
} }
protected IList<BaseItem> GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func<BaseItem,bool> 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);
}
/// <summary> /// <summary>
/// Deslugs an artist name by finding the correct entry in the library /// Deslugs an artist name by finding the correct entry in the library
/// </summary> /// </summary>

View File

@ -102,12 +102,16 @@ namespace MediaBrowser.Api
/// <returns>System.Object.</returns> /// <returns>System.Object.</returns>
public object Get(GetGameSystemSummaries request) 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<GameSystem>() .Cast<GameSystem>()
.ToList(); .ToList();
var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
var result = gameSystems var result = gameSystems
.Select(i => GetSummary(i, user)) .Select(i => GetSummary(i, user))
.ToList(); .ToList();
@ -119,8 +123,15 @@ namespace MediaBrowser.Api
public object Get(GetPlayerIndex request) public object Get(GetPlayerIndex request)
{ {
var games = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, i => i is Game) var user = request.UserId == null ? null : _userManager.GetUserById(request.UserId);
.Cast<Game>(); var query = new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Game).Name }
};
var parentIds = new string[] { };
var games = _libraryManager.GetItems(query, parentIds)
.Cast<Game>()
.ToList();
var lookup = games var lookup = games
.ToLookup(i => i.PlayersSupported ?? -1) .ToLookup(i => i.PlayersSupported ?? -1)

View File

@ -416,7 +416,7 @@ namespace MediaBrowser.Api.Library
public object Get(GetMediaFolders request) 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) if (request.IsHidden.HasValue)
{ {
@ -610,7 +610,7 @@ namespace MediaBrowser.Api.Library
var dtoOptions = GetDtoOptions(request); var dtoOptions = GetDtoOptions(request);
BaseItem parent = item.Parent; BaseItem parent = item.GetParent();
while (parent != null) while (parent != null)
{ {
@ -621,7 +621,7 @@ namespace MediaBrowser.Api.Library
baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, dtoOptions, user)); baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, dtoOptions, user));
parent = parent.Parent; parent = parent.GetParent();
} }
return baseItemDtos.ToList(); return baseItemDtos.ToList();
@ -629,7 +629,7 @@ namespace MediaBrowser.Api.Library
private BaseItem TranslateParentItem(BaseItem item, User user) 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)); return user.RootFolder.GetChildren(user, true).FirstOrDefault(i => i.PhysicalLocations.Contains(item.Path));
} }
@ -677,6 +677,50 @@ namespace MediaBrowser.Api.Library
return ToOptimizedSerializedResultUsingCache(counts); return ToOptimizedSerializedResultUsingCache(counts);
} }
private IList<BaseItem> GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func<BaseItem, bool> 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) private bool FilterItem(BaseItem item, GetItemCounts request, string userId)
{ {
if (!string.IsNullOrWhiteSpace(userId)) if (!string.IsNullOrWhiteSpace(userId))
@ -817,9 +861,9 @@ namespace MediaBrowser.Api.Library
: (Folder)_libraryManager.RootFolder) : (Folder)_libraryManager.RootFolder)
: _libraryManager.GetItemById(request.Id); : _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); var dtoOptions = GetDtoOptions(request);
@ -860,9 +904,9 @@ namespace MediaBrowser.Api.Library
: (Folder)_libraryManager.RootFolder) : (Folder)_libraryManager.RootFolder)
: _libraryManager.GetItemById(request.Id); : _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); var dtoOptions = GetDtoOptions(request);

View File

@ -49,6 +49,9 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath> <HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
</Reference> </Reference>
<Reference Include="MoreLinq">
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
</Reference>
<Reference Include="Patterns.Logging"> <Reference Include="Patterns.Logging">
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath> <HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
</Reference> </Reference>
@ -63,9 +66,6 @@
<Reference Include="ServiceStack.Text"> <Reference Include="ServiceStack.Text">
<HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath> <HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath>
</Reference> </Reference>
<Reference Include="MoreLinq">
<HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\SharedVersion.cs"> <Compile Include="..\SharedVersion.cs">

View File

@ -117,10 +117,7 @@ namespace MediaBrowser.Api.Movies
public async Task<object> Get(GetSimilarMovies request) public async Task<object> Get(GetSimilarMovies request)
{ {
var result = await GetSimilarItemsResult( var result = await GetSimilarItemsResult(
// Strip out secondary versions request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
request, item => (item is Movie) && !((Video)item).PrimaryVersionId.HasValue,
SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result); return ToOptimizedSerializedResultUsingCache(result);
} }
@ -128,10 +125,7 @@ namespace MediaBrowser.Api.Movies
public async Task<object> Get(GetSimilarTrailers request) public async Task<object> Get(GetSimilarTrailers request)
{ {
var result = await GetSimilarItemsResult( var result = await GetSimilarItemsResult(
// Strip out secondary versions request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
request, item => (item is Movie) && !((Video)item).PrimaryVersionId.HasValue,
SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result); return ToOptimizedSerializedResultUsingCache(result);
} }
@ -140,8 +134,12 @@ namespace MediaBrowser.Api.Movies
{ {
var user = _userManager.GetUserById(request.UserId); var user = _userManager.GetUserById(request.UserId);
IEnumerable<BaseItem> movies = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, i => i is Movie); var query = new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Movie).Name }
};
var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
var movies = _libraryManager.GetItems(query, parentIds);
movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies); movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies);
var listEligibleForCategories = new List<BaseItem>(); var listEligibleForCategories = new List<BaseItem>();
@ -184,7 +182,7 @@ namespace MediaBrowser.Api.Movies
return ToOptimizedResult(result); return ToOptimizedResult(result);
} }
private async Task<ItemsResult> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, Func<BaseItem, bool> includeInSearch, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore) private async Task<ItemsResult> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
{ {
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null; var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
@ -192,13 +190,19 @@ namespace MediaBrowser.Api.Movies
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder : (!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id); _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
Func<BaseItem, bool> filter = i => i.Id != item.Id && includeInSearch(i); var query = new InternalItemsQuery(user)
{
var inputItems = user == null IncludeItemTypes = new[] { typeof(Movie).Name }
? _libraryManager.RootFolder.GetRecursiveChildren(filter) };
: user.RootFolder.GetRecursiveChildren(user, filter); var parentIds = new string[] { };
var list = _libraryManager.GetItems(query, parentIds)
var list = inputItems.ToList(); .Where(i =>
{
// Strip out secondary versions
var v = i as Video;
return v != null && !v.PrimaryVersionId.HasValue;
})
.ToList();
if (user != null && user.Configuration.IncludeTrailersInSuggestions) if (user != null && user.Configuration.IncludeTrailersInSuggestions)
{ {
@ -379,9 +383,10 @@ namespace MediaBrowser.Api.Movies
{ {
foreach (var name in names) foreach (var name in names)
{ {
var itemsWithActor = _libraryManager.GetItemIds(new InternalItemsQuery var itemsWithActor = _libraryManager.GetItemIds(new InternalItemsQuery(user)
{ {
Person = name Person = name
}); });
var items = allMovies var items = allMovies

View File

@ -233,7 +233,7 @@ namespace MediaBrowser.Api
throw new ResourceNotFoundException(string.Format("Package not found: {0}", request.Name)); throw new ResourceNotFoundException(string.Format("Package not found: {0}", request.Name));
} }
Task.Run(() => _installationManager.InstallPackage(package, new Progress<double>(), CancellationToken.None)); Task.Run(() => _installationManager.InstallPackage(package, true, new Progress<double>(), CancellationToken.None));
} }
/// <summary> /// <summary>

View File

@ -1562,6 +1562,13 @@ namespace MediaBrowser.Api.Playback
RequestedUrl = url RequestedUrl = url
}; };
//if ((Request.UserAgent ?? string.Empty).IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1 ||
// (Request.UserAgent ?? string.Empty).IndexOf("ipad", StringComparison.OrdinalIgnoreCase) != -1 ||
// (Request.UserAgent ?? string.Empty).IndexOf("ipod", StringComparison.OrdinalIgnoreCase) != -1)
//{
// state.SegmentLength = 6;
//}
if (!string.IsNullOrWhiteSpace(request.AudioCodec)) if (!string.IsNullOrWhiteSpace(request.AudioCodec))
{ {
state.SupportedAudioCodecs = request.AudioCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); state.SupportedAudioCodecs = request.AudioCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();

View File

@ -111,7 +111,8 @@ namespace MediaBrowser.Api.Playback.Hls
throw; throw;
} }
await WaitForMinimumSegmentCount(playlist, 3, cancellationTokenSource.Token).ConfigureAwait(false); var waitForSegments = state.SegmentLength >= 10 ? 2 : 3;
await WaitForMinimumSegmentCount(playlist, waitForSegments, cancellationTokenSource.Token).ConfigureAwait(false);
} }
} }
finally finally

View File

@ -283,7 +283,7 @@ namespace MediaBrowser.Api
private T GetParentWithImage<T>(BaseItem item, ImageType type) private T GetParentWithImage<T>(BaseItem item, ImageType type)
where T : BaseItem where T : BaseItem
{ {
return item.Parents.OfType<T>().FirstOrDefault(i => i.HasImage(type)); return item.GetParents().OfType<T>().FirstOrDefault(i => i.HasImage(type));
} }
} }
} }

View File

@ -68,11 +68,7 @@ namespace MediaBrowser.Api
_config.Configuration.EnableLocalizedGuids = true; _config.Configuration.EnableLocalizedGuids = true;
_config.Configuration.MergeMetadataAndImagesByName = true; _config.Configuration.MergeMetadataAndImagesByName = true;
_config.Configuration.EnableStandaloneMetadata = true; _config.Configuration.EnableStandaloneMetadata = true;
_config.Configuration.EnableLibraryMetadataSubFolder = true;
_config.Configuration.EnableCustomPathSubFolders = true; _config.Configuration.EnableCustomPathSubFolders = true;
_config.Configuration.DisableXmlSavers = true;
_config.Configuration.DisableStartupScan = true;
_config.Configuration.EnableUserViews = true;
_config.Configuration.EnableDateLastRefresh = true; _config.Configuration.EnableDateLastRefresh = true;
_config.SaveConfiguration(); _config.SaveConfiguration();
} }

View File

@ -13,6 +13,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommonIO; using CommonIO;
using MediaBrowser.Model.Net;
namespace MediaBrowser.Api.System namespace MediaBrowser.Api.System
{ {
@ -32,6 +33,12 @@ namespace MediaBrowser.Api.System
} }
[Route("/System/Ping", "POST")]
public class PingSystem : IReturnVoid
{
}
/// <summary> /// <summary>
/// Class RestartApplication /// Class RestartApplication
/// </summary> /// </summary>
@ -59,7 +66,7 @@ namespace MediaBrowser.Api.System
[Route("/System/Endpoint", "GET", Summary = "Gets information about the request endpoint")] [Route("/System/Endpoint", "GET", Summary = "Gets information about the request endpoint")]
[Authenticated] [Authenticated]
public class GetEndpointInfo : IReturn<EndpointInfo> public class GetEndpointInfo : IReturn<EndPointInfo>
{ {
public string Endpoint { get; set; } public string Endpoint { get; set; }
} }
@ -104,6 +111,11 @@ namespace MediaBrowser.Api.System
_security = security; _security = security;
} }
public object Post(PingSystem request)
{
return _appHost.Name;
}
public object Get(GetServerLogs request) public object Get(GetServerLogs request)
{ {
List<FileSystemMetadata> files; List<FileSystemMetadata> files;
@ -199,17 +211,11 @@ namespace MediaBrowser.Api.System
public object Get(GetEndpointInfo request) public object Get(GetEndpointInfo request)
{ {
return ToOptimizedResult(new EndpointInfo return ToOptimizedResult(new EndPointInfo
{ {
IsLocal = Request.IsLocal, IsLocal = Request.IsLocal,
IsInNetwork = _network.IsInLocalNetwork(request.Endpoint ?? Request.RemoteIp) IsInNetwork = _network.IsInLocalNetwork(request.Endpoint ?? Request.RemoteIp)
}); });
} }
} }
public class EndpointInfo
{
public bool IsLocal { get; set; }
public bool IsInNetwork { get; set; }
}
} }

View File

@ -273,29 +273,28 @@ namespace MediaBrowser.Api
{ {
var user = _userManager.GetUserById(request.UserId); var user = _userManager.GetUserById(request.UserId);
var items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, i => i is Episode);
var itemsList = _libraryManager
.Sort(items, user, new[] { "PremiereDate", "AirTime", "SortName" }, SortOrder.Ascending)
.Cast<Episode>()
.ToList();
var unairedEpisodes = itemsList.Where(i => i.IsUnaired).ToList();
var minPremiereDate = DateTime.Now.Date.AddDays(-1).ToUniversalTime(); var minPremiereDate = DateTime.Now.Date.AddDays(-1).ToUniversalTime();
var previousEpisodes = itemsList.Where(i => !i.IsUnaired && (i.PremiereDate ?? DateTime.MinValue) >= minPremiereDate).ToList();
previousEpisodes.AddRange(unairedEpisodes); var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
var pagedItems = ApplyPaging(previousEpisodes, request.StartIndex, request.Limit); var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Episode).Name },
SortBy = new[] { "PremiereDate", "AirTime", "SortName" },
SortOrder = SortOrder.Ascending,
MinPremiereDate = minPremiereDate,
StartIndex = request.StartIndex,
Limit = request.Limit
}, parentIds);
var options = GetDtoOptions(request); var options = GetDtoOptions(request);
var returnItems = _dtoService.GetBaseItemDtos(pagedItems, options, user).ToArray(); var returnItems = _dtoService.GetBaseItemDtos(itemsResult.Items, options, user).ToArray();
var result = new ItemsResult var result = new ItemsResult
{ {
TotalRecordCount = itemsList.Count, TotalRecordCount = itemsResult.TotalRecordCount,
Items = returnItems Items = returnItems
}; };

View File

@ -206,6 +206,8 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "Genres", Description = "Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Genres", Description = "Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Genres { get; set; } public string Genres { get; set; }
public string GenreIds { get; set; }
[ApiMember(Name = "OfficialRatings", Description = "Optional. If specified, results will be filtered based on OfficialRating. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "OfficialRatings", Description = "Optional. If specified, results will be filtered based on OfficialRating. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string OfficialRatings { get; set; } public string OfficialRatings { get; set; }
@ -385,6 +387,11 @@ namespace MediaBrowser.Api.UserLibrary
return (StudioIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); return (StudioIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
} }
public string[] GetGenreIds()
{
return (GenreIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
}
public string[] GetPersonTypes() public string[] GetPersonTypes()
{ {
return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

View File

@ -112,6 +112,11 @@ namespace MediaBrowser.Api.UserLibrary
user == null ? _libraryManager.RootFolder : user.RootFolder : user == null ? _libraryManager.RootFolder : user.RootFolder :
parentItem; parentItem;
if (string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase))
{
item = user == null ? _libraryManager.RootFolder : user.RootFolder;
}
// Default list type = children // Default list type = children
if (!string.IsNullOrEmpty(request.Ids)) if (!string.IsNullOrEmpty(request.Ids))
@ -211,6 +216,7 @@ namespace MediaBrowser.Api.UserLibrary
Tags = request.GetTags(), Tags = request.GetTags(),
OfficialRatings = request.GetOfficialRatings(), OfficialRatings = request.GetOfficialRatings(),
Genres = request.GetGenres(), Genres = request.GetGenres(),
GenreIds = request.GetGenreIds(),
Studios = request.GetStudios(), Studios = request.GetStudios(),
StudioIds = request.GetStudioIds(), StudioIds = request.GetStudioIds(),
Person = request.Person, Person = request.Person,
@ -423,15 +429,6 @@ namespace MediaBrowser.Api.UserLibrary
return false; return false;
} }
// Min index number
if (request.MinIndexNumber.HasValue)
{
if (!(i.IndexNumber.HasValue && i.IndexNumber.Value >= request.MinIndexNumber.Value))
{
return false;
}
}
// Min official rating // Min official rating
if (!string.IsNullOrEmpty(request.MinOfficialRating)) if (!string.IsNullOrEmpty(request.MinOfficialRating))
{ {

View File

@ -26,6 +26,8 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "IncludeExternalContent", Description = "Whether or not to include external views such as channels or live tv", IsRequired = true, DataType = "boolean", ParameterType = "query", Verb = "POST")] [ApiMember(Name = "IncludeExternalContent", Description = "Whether or not to include external views such as channels or live tv", IsRequired = true, DataType = "boolean", ParameterType = "query", Verb = "POST")]
public bool? IncludeExternalContent { get; set; } public bool? IncludeExternalContent { get; set; }
public string PresetViews { get; set; }
} }
[Route("/Users/{UserId}/SpecialViewOptions", "GET")] [Route("/Users/{UserId}/SpecialViewOptions", "GET")]
@ -75,9 +77,24 @@ namespace MediaBrowser.Api.UserLibrary
query.IncludeExternalContent = request.IncludeExternalContent.Value; query.IncludeExternalContent = request.IncludeExternalContent.Value;
} }
if (!string.IsNullOrWhiteSpace(request.PresetViews))
{
query.PresetViews = request.PresetViews.Split(',');
}
var app = AuthorizationContext.GetAuthorizationInfo(Request).Client ?? string.Empty;
if (app.IndexOf("emby rt", StringComparison.OrdinalIgnoreCase) != -1)
{
query.PresetViews = new[] { CollectionType.Music, CollectionType.Movies, CollectionType.TvShows };
}
//query.PresetViews = new[] { CollectionType.Music, CollectionType.Movies, CollectionType.TvShows };
var folders = await _userViewManager.GetUserViews(query, CancellationToken.None).ConfigureAwait(false); var folders = await _userViewManager.GetUserViews(query, CancellationToken.None).ConfigureAwait(false);
var dtoOptions = GetDtoOptions(request); var dtoOptions = GetDtoOptions(request);
dtoOptions.Fields = new List<ItemFields>();
dtoOptions.Fields.Add(ItemFields.PrimaryImageAspectRatio);
dtoOptions.Fields.Add(ItemFields.DisplayPreferencesId);
var user = _userManager.GetUserById(request.UserId); var user = _userManager.GetUserById(request.UserId);
@ -123,7 +140,7 @@ namespace MediaBrowser.Api.UserLibrary
var views = user.RootFolder var views = user.RootFolder
.GetChildren(user, true) .GetChildren(user, true)
.OfType<Folder>() .OfType<Folder>()
.Where(i => !UserView.IsExcludedFromGrouping(i)) .Where(UserView.IsEligibleForGrouping)
.ToList(); .ToList();
var list = views var list = views
@ -141,9 +158,7 @@ namespace MediaBrowser.Api.UserLibrary
private bool IsEligibleForSpecialView(ICollectionFolder view) private bool IsEligibleForSpecialView(ICollectionFolder view)
{ {
var types = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Games, CollectionType.Music, CollectionType.Photos }; return UserView.IsEligibleForEnhancedView(view.CollectionType);
return types.Contains(view.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
} }
} }

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" /> <package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
<package id="morelinq" version="1.1.1" targetFramework="net45" /> <package id="morelinq" version="1.4.0" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" /> <package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
</packages> </packages>

View File

@ -133,7 +133,7 @@ namespace MediaBrowser.Common.Implementations
/// Gets the HTTP client. /// Gets the HTTP client.
/// </summary> /// </summary>
/// <value>The HTTP client.</value> /// <value>The HTTP client.</value>
protected IHttpClient HttpClient { get; private set; } public IHttpClient HttpClient { get; private set; }
/// <summary> /// <summary>
/// Gets the network manager. /// Gets the network manager.
/// </summary> /// </summary>

View File

@ -51,9 +51,11 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath> <HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
</Reference> </Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> <Reference Include="MoreLinq">
<SpecificVersion>False</SpecificVersion> <HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
<HintPath>..\packages\NLog.4.1.1\lib\net45\NLog.dll</HintPath> </Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.4.2.3\lib\net45\NLog.dll</HintPath>
</Reference> </Reference>
<Reference Include="Patterns.Logging"> <Reference Include="Patterns.Logging">
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath> <HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
@ -62,13 +64,14 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath> <HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
</Reference> </Reference>
<Reference Include="SimpleInjector, Version=2.8.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> <Reference Include="SimpleInjector">
<SpecificVersion>False</SpecificVersion> <HintPath>..\packages\SimpleInjector.3.1.2\lib\net45\SimpleInjector.dll</HintPath>
<HintPath>..\packages\SimpleInjector.3.0.5\lib\net45\SimpleInjector.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net" /> <Reference Include="System.Net" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="ServiceStack.Text"> <Reference Include="ServiceStack.Text">
@ -105,6 +108,7 @@
<Compile Include="Security\SuppporterInfoResponse.cs" /> <Compile Include="Security\SuppporterInfoResponse.cs" />
<Compile Include="Serialization\JsonSerializer.cs" /> <Compile Include="Serialization\JsonSerializer.cs" />
<Compile Include="Serialization\XmlSerializer.cs" /> <Compile Include="Serialization\XmlSerializer.cs" />
<Compile Include="Updates\GithubUpdater.cs" />
<Compile Include="Updates\InstallationManager.cs" /> <Compile Include="Updates\InstallationManager.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -7,6 +7,7 @@ using System.Net;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading; using System.Threading;
using MoreLinq;
namespace MediaBrowser.Common.Implementations.Networking namespace MediaBrowser.Common.Implementations.Networking
{ {
@ -31,14 +32,14 @@ namespace MediaBrowser.Common.Implementations.Networking
} }
} }
private volatile List<string> _localIpAddresses; private volatile List<IPAddress> _localIpAddresses;
private readonly object _localIpAddressSyncLock = new object(); private readonly object _localIpAddressSyncLock = new object();
/// <summary> /// <summary>
/// Gets the machine's local ip address /// Gets the machine's local ip address
/// </summary> /// </summary>
/// <returns>IPAddress.</returns> /// <returns>IPAddress.</returns>
public IEnumerable<string> GetLocalIpAddresses() public IEnumerable<IPAddress> GetLocalIpAddresses()
{ {
if (_localIpAddresses == null) if (_localIpAddresses == null)
{ {
@ -58,25 +59,24 @@ namespace MediaBrowser.Common.Implementations.Networking
return _localIpAddresses; return _localIpAddresses;
} }
private IEnumerable<string> GetLocalIpAddressesInternal() private IEnumerable<IPAddress> GetLocalIpAddressesInternal()
{ {
var list = GetIPsDefault() var list = GetIPsDefault()
.Where(i => !IPAddress.IsLoopback(i))
.Select(i => i.ToString())
.Where(FilterIpAddress)
.ToList(); .ToList();
if (list.Count > 0) if (list.Count == 0)
{ {
return list; list.AddRange(GetLocalIpAddressesFallback());
} }
return GetLocalIpAddressesFallback().Where(FilterIpAddress); return list.Where(FilterIpAddress).DistinctBy(i => i.ToString());
} }
private bool FilterIpAddress(string address) private bool FilterIpAddress(IPAddress address)
{ {
if (address.StartsWith("169.", StringComparison.OrdinalIgnoreCase)) var addressString = address.ToString ();
if (addressString.StartsWith("169.", StringComparison.OrdinalIgnoreCase))
{ {
return false; return false;
} }
@ -84,8 +84,16 @@ namespace MediaBrowser.Common.Implementations.Networking
return true; return true;
} }
private bool IsInPrivateAddressSpace(string endpoint) public bool IsInPrivateAddressSpace(string endpoint)
{ {
if (string.Equals(endpoint, "::1", StringComparison.OrdinalIgnoreCase))
{
return true;
}
// Handle ipv4 mapped to ipv6
endpoint = endpoint.Replace("::ffff:", string.Empty);
// Private address space: // Private address space:
// http://en.wikipedia.org/wiki/Private_network // http://en.wikipedia.org/wiki/Private_network
@ -96,9 +104,6 @@ namespace MediaBrowser.Common.Implementations.Networking
return return
// If url was requested with computer name, we may see this
endpoint.IndexOf("::", StringComparison.OrdinalIgnoreCase) != -1 ||
endpoint.StartsWith("localhost", StringComparison.OrdinalIgnoreCase) || endpoint.StartsWith("localhost", StringComparison.OrdinalIgnoreCase) ||
endpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) || endpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
endpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) || endpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) ||
@ -131,26 +136,41 @@ namespace MediaBrowser.Common.Implementations.Networking
throw new ArgumentNullException("endpoint"); throw new ArgumentNullException("endpoint");
} }
IPAddress address;
if (IPAddress.TryParse(endpoint, out address))
{
var addressString = address.ToString();
int lengthMatch = 100;
if (address.AddressFamily == AddressFamily.InterNetwork)
{
lengthMatch = 4;
if (IsInPrivateAddressSpace(addressString))
{
return true;
}
}
else if (address.AddressFamily == AddressFamily.InterNetworkV6)
{
lengthMatch = 10;
if (IsInPrivateAddressSpace(endpoint)) if (IsInPrivateAddressSpace(endpoint))
{ {
return true; return true;
} }
}
const int lengthMatch = 4; // Should be even be doing this with ipv6?
if (addressString.Length >= lengthMatch)
if (endpoint.Length >= lengthMatch)
{ {
var prefix = endpoint.Substring(0, lengthMatch); var prefix = addressString.Substring(0, lengthMatch);
if (GetLocalIpAddresses() if (GetLocalIpAddresses().Any(i => i.ToString().StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
.Any(i => i.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
{ {
return true; return true;
} }
} }
}
IPAddress address; else if (resolveHost)
if (resolveHost && !IPAddress.TryParse(endpoint, out address))
{ {
Uri uri; Uri uri;
if (Uri.TryCreate(endpoint, UriKind.RelativeOrAbsolute, out uri)) if (Uri.TryCreate(endpoint, UriKind.RelativeOrAbsolute, out uri))
@ -188,33 +208,45 @@ namespace MediaBrowser.Common.Implementations.Networking
return Dns.GetHostAddresses(hostName); return Dns.GetHostAddresses(hostName);
} }
private IEnumerable<IPAddress> GetIPsDefault() private List<IPAddress> GetIPsDefault()
{ {
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces()) NetworkInterface[] interfaces;
{
var props = adapter.GetIPProperties();
var gateways = from ga in props.GatewayAddresses
where !ga.Address.Equals(IPAddress.Any)
select true;
if (!gateways.Any()) try
{ {
continue; interfaces = NetworkInterface.GetAllNetworkInterfaces();
}
catch (Exception ex)
{
Logger.ErrorException("Error in GetAllNetworkInterfaces", ex);
return new List<IPAddress>();
} }
foreach (var uni in props.UnicastAddresses) return interfaces.SelectMany(network => {
try
{ {
var address = uni.Address; Logger.Debug("Querying interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus);
if (address.AddressFamily != AddressFamily.InterNetwork)
var properties = network.GetIPProperties();
return properties.UnicastAddresses
.Where(i => i.IsDnsEligible)
.Select(i => i.Address)
.Where(i => i.AddressFamily == AddressFamily.InterNetwork)
.ToList();
}
catch (Exception ex)
{ {
continue; Logger.ErrorException("Error querying network interface", ex);
} return new List<IPAddress>();
yield return address;
}
}
} }
private IEnumerable<string> GetLocalIpAddressesFallback() }).DistinctBy(i => i.ToString())
.ToList();
}
private IEnumerable<IPAddress> GetLocalIpAddressesFallback()
{ {
var host = Dns.GetHostEntry(Dns.GetHostName()); var host = Dns.GetHostEntry(Dns.GetHostName());
@ -222,7 +254,6 @@ namespace MediaBrowser.Common.Implementations.Networking
// It's not fool-proof so ultimately the consumer will have to examine them and decide // It's not fool-proof so ultimately the consumer will have to examine them and decide
return host.AddressList return host.AddressList
.Where(i => i.AddressFamily == AddressFamily.InterNetwork) .Where(i => i.AddressFamily == AddressFamily.InterNetwork)
.Select(i => i.ToString())
.Reverse(); .Reverse();
} }

View File

@ -0,0 +1,212 @@
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> 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<RootObject[]>(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))
.Where(i => i != null)
.OrderByDescending(i => Version.Parse(i.AvailableVersion))
.FirstOrDefault();
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<Asset>()).FirstOrDefault(i => IsAsset(i, assetFilename));
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
}
};
}
private bool IsAsset(Asset asset, string assetFilename)
{
var downloadFilename = Path.GetFileName(asset.browser_download_url) ?? string.Empty;
if (downloadFilename.IndexOf(assetFilename, StringComparison.OrdinalIgnoreCase) != -1)
{
return true;
}
return string.Equals(assetFilename, downloadFilename, StringComparison.OrdinalIgnoreCase);
}
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<Asset> assets { get; set; }
public string tarball_url { get; set; }
public string zipball_url { get; set; }
public string body { get; set; }
}
}
}

View File

@ -438,11 +438,12 @@ namespace MediaBrowser.Common.Implementations.Updates
/// Installs the package. /// Installs the package.
/// </summary> /// </summary>
/// <param name="package">The package.</param> /// <param name="package">The package.</param>
/// <param name="isPlugin">if set to <c>true</c> [is plugin].</param>
/// <param name="progress">The progress.</param> /// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">package</exception> /// <exception cref="System.ArgumentNullException">package</exception>
public async Task InstallPackage(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken) public async Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken)
{ {
if (package == null) if (package == null)
{ {
@ -495,7 +496,7 @@ namespace MediaBrowser.Common.Implementations.Updates
try try
{ {
await InstallPackageInternal(package, innerProgress, linkedToken).ConfigureAwait(false); await InstallPackageInternal(package, isPlugin, innerProgress, linkedToken).ConfigureAwait(false);
lock (CurrentInstallations) lock (CurrentInstallations)
{ {
@ -551,18 +552,17 @@ namespace MediaBrowser.Common.Implementations.Updates
/// Installs the package internal. /// Installs the package internal.
/// </summary> /// </summary>
/// <param name="package">The package.</param> /// <param name="package">The package.</param>
/// <param name="isPlugin">if set to <c>true</c> [is plugin].</param>
/// <param name="progress">The progress.</param> /// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
private async Task InstallPackageInternal(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken) private async Task InstallPackageInternal(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken)
{ {
// Do the install // Do the install
await PerformPackageInstallation(progress, package, cancellationToken).ConfigureAwait(false); await PerformPackageInstallation(progress, package, cancellationToken).ConfigureAwait(false);
var extension = Path.GetExtension(package.targetFilename) ?? "";
// Do plugin-specific processing // 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 // Set last update time if we were installed before
var plugin = _applicationHost.Plugins.FirstOrDefault(p => string.Equals(p.Id.ToString(), package.guid, StringComparison.OrdinalIgnoreCase)) var plugin = _applicationHost.Plugins.FirstOrDefault(p => string.Equals(p.Id.ToString(), package.guid, StringComparison.OrdinalIgnoreCase))

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" /> <package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
<package id="NLog" version="4.1.0" targetFramework="net45" /> <package id="morelinq" version="1.4.0" targetFramework="net45" />
<package id="NLog" version="4.2.3" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" /> <package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
<package id="SimpleInjector" version="3.0.5" targetFramework="net45" /> <package id="SimpleInjector" version="3.1.2" targetFramework="net45" />
</packages> </packages>

View File

@ -11,7 +11,7 @@ namespace MediaBrowser.Common.Net
/// Gets the machine's local ip address /// Gets the machine's local ip address
/// </summary> /// </summary>
/// <returns>IPAddress.</returns> /// <returns>IPAddress.</returns>
IEnumerable<string> GetLocalIpAddresses(); IEnumerable<IPAddress> GetLocalIpAddresses();
/// <summary> /// <summary>
/// Gets a random port number that is currently available /// Gets a random port number that is currently available
@ -25,6 +25,13 @@ namespace MediaBrowser.Common.Net
/// <returns>[string] MAC Address</returns> /// <returns>[string] MAC Address</returns>
string GetMacAddress(); string GetMacAddress();
/// <summary>
/// Determines whether [is in private address space] [the specified endpoint].
/// </summary>
/// <param name="endpoint">The endpoint.</param>
/// <returns><c>true</c> if [is in private address space] [the specified endpoint]; otherwise, <c>false</c>.</returns>
bool IsInPrivateAddressSpace(string endpoint);
/// <summary> /// <summary>
/// Gets the network shares. /// Gets the network shares.
/// </summary> /// </summary>

View File

@ -105,11 +105,12 @@ namespace MediaBrowser.Common.Updates
/// Installs the package. /// Installs the package.
/// </summary> /// </summary>
/// <param name="package">The package.</param> /// <param name="package">The package.</param>
/// <param name="isPlugin">if set to <c>true</c> [is plugin].</param>
/// <param name="progress">The progress.</param> /// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">package</exception> /// <exception cref="System.ArgumentNullException">package</exception>
Task InstallPackage(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken); Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Uninstalls a plugin /// Uninstalls a plugin

View File

@ -18,9 +18,9 @@ namespace MediaBrowser.Controller.Channels
public List<ChannelMediaInfo> ChannelMediaSources { get; set; } public List<ChannelMediaInfo> 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() protected override string CreateUserDataKey()

View File

@ -6,6 +6,7 @@ using System;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Channels namespace MediaBrowser.Controller.Channels
@ -20,6 +21,11 @@ namespace MediaBrowser.Controller.Channels
return false; return false;
} }
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.ChannelContent;
}
[IgnoreDataMember] [IgnoreDataMember]
public override bool SupportsLocalMetadata public override bool SupportsLocalMetadata
{ {

View File

@ -42,9 +42,9 @@ namespace MediaBrowser.Controller.Channels
return ExternalId; return ExternalId;
} }
protected override bool GetBlockUnratedValue(UserPolicy config) public override UnratedItem GetBlockUnratedType()
{ {
return config.BlockUnratedItems.Contains(UnratedItem.ChannelContent); return UnratedItem.ChannelContent;
} }
[IgnoreDataMember] [IgnoreDataMember]

View File

@ -27,9 +27,22 @@ namespace MediaBrowser.Controller.Entities.Audio
public long? Size { get; set; } public long? Size { get; set; }
public string Container { get; set; } public string Container { get; set; }
public int? TotalBitrate { get; set; } public int? TotalBitrate { get; set; }
public List<string> Tags { get; set; }
public ExtraType? ExtraType { get; set; } public ExtraType? ExtraType { get; set; }
/// <summary>
/// Gets or sets the artist.
/// </summary>
/// <value>The artist.</value>
public List<string> Artists { get; set; }
public List<string> AlbumArtists { get; set; }
/// <summary>
/// Gets or sets the album.
/// </summary>
/// <value>The album.</value>
public string Album { get; set; }
[IgnoreDataMember] [IgnoreDataMember]
public bool IsThemeMedia public bool IsThemeMedia
{ {
@ -43,7 +56,6 @@ namespace MediaBrowser.Controller.Entities.Audio
{ {
Artists = new List<string>(); Artists = new List<string>();
AlbumArtists = new List<string>(); AlbumArtists = new List<string>();
Tags = new List<string>();
} }
[IgnoreDataMember] [IgnoreDataMember]
@ -92,14 +104,6 @@ namespace MediaBrowser.Controller.Entities.Audio
locationType != LocationType.Virtual; locationType != LocationType.Virtual;
} }
/// <summary>
/// Gets or sets the artist.
/// </summary>
/// <value>The artist.</value>
public List<string> Artists { get; set; }
public List<string> AlbumArtists { get; set; }
[IgnoreDataMember] [IgnoreDataMember]
public List<string> AllArtists public List<string> AllArtists
{ {
@ -114,12 +118,6 @@ namespace MediaBrowser.Controller.Entities.Audio
} }
} }
/// <summary>
/// Gets or sets the album.
/// </summary>
/// <value>The album.</value>
public string Album { get; set; }
[IgnoreDataMember] [IgnoreDataMember]
public MusicAlbum AlbumEntity public MusicAlbum AlbumEntity
{ {
@ -173,9 +171,9 @@ namespace MediaBrowser.Controller.Entities.Audio
return base.CreateUserDataKey(); 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() public SongInfo GetLookupInfo()

View File

@ -30,7 +30,7 @@ namespace MediaBrowser.Controller.Entities.Audio
{ {
get get
{ {
return Parents.OfType<MusicArtist>().FirstOrDefault(); return GetParents().OfType<MusicArtist>().FirstOrDefault();
} }
} }
@ -110,13 +110,18 @@ namespace MediaBrowser.Controller.Entities.Audio
return config.BlockUnratedItems.Contains(UnratedItem.Music); return config.BlockUnratedItems.Contains(UnratedItem.Music);
} }
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Music;
}
public AlbumInfo GetLookupInfo() public AlbumInfo GetLookupInfo()
{ {
var id = GetItemLookupInfo<AlbumInfo>(); var id = GetItemLookupInfo<AlbumInfo>();
id.AlbumArtists = AlbumArtists; id.AlbumArtists = AlbumArtists;
var artist = Parents.OfType<MusicArtist>().FirstOrDefault(); var artist = GetParents().OfType<MusicArtist>().FirstOrDefault();
if (artist != null) if (artist != null)
{ {

View File

@ -138,6 +138,11 @@ namespace MediaBrowser.Controller.Entities.Audio
return config.BlockUnratedItems.Contains(UnratedItem.Music); return config.BlockUnratedItems.Contains(UnratedItem.Music);
} }
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Music;
}
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken) public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
{ {
var items = GetRecursiveChildren().ToList(); var items = GetRecursiveChildren().ToList();

View File

@ -1,5 +1,4 @@
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
@ -24,6 +23,7 @@ using System.Runtime.Serialization;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommonIO; using CommonIO;
using MediaBrowser.Model.LiveTv;
namespace MediaBrowser.Controller.Entities namespace MediaBrowser.Controller.Entities
{ {
@ -34,6 +34,7 @@ namespace MediaBrowser.Controller.Entities
{ {
protected BaseItem() protected BaseItem()
{ {
Tags = new List<string>();
Genres = new List<string>(); Genres = new List<string>();
Studios = new List<string>(); Studios = new List<string>();
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
@ -44,7 +45,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary> /// <summary>
/// The supported image extensions /// The supported image extensions
/// </summary> /// </summary>
public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg" }; public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg", ".tbn", ".gif" };
public static readonly List<string> SupportedImageExtensionsList = SupportedImageExtensions.ToList(); public static readonly List<string> SupportedImageExtensionsList = SupportedImageExtensions.ToList();
@ -103,7 +104,8 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the name. /// Gets or sets the name.
/// </summary> /// </summary>
/// <value>The name.</value> /// <value>The name.</value>
public string Name [IgnoreDataMember]
public virtual string Name
{ {
get get
{ {
@ -122,14 +124,23 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the id. /// Gets or sets the id.
/// </summary> /// </summary>
/// <value>The id.</value> /// <value>The id.</value>
[IgnoreDataMember]
public Guid Id { get; set; } public Guid Id { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether this instance is hd. /// Gets or sets a value indicating whether this instance is hd.
/// </summary> /// </summary>
/// <value><c>true</c> if this instance is hd; otherwise, <c>false</c>.</value> /// <value><c>true</c> if this instance is hd; otherwise, <c>false</c>.</value>
[IgnoreDataMember]
public bool? IsHD { get; set; } public bool? IsHD { get; set; }
/// <summary>
/// Gets or sets the audio.
/// </summary>
/// <value>The audio.</value>
[IgnoreDataMember]
public ProgramAudio? Audio { get; set; }
/// <summary> /// <summary>
/// Return the id that should be used to key display prefs for this item. /// 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. /// 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. /// Gets or sets the path.
/// </summary> /// </summary>
/// <value>The path.</value> /// <value>The path.</value>
[IgnoreDataMember]
public virtual string Path { get; set; } public virtual string Path { get; set; }
[IgnoreDataMember] [IgnoreDataMember]
@ -173,7 +185,7 @@ namespace MediaBrowser.Controller.Entities
} }
/// <summary> /// <summary>
/// Id of the program. /// If this content came from an external service, the id of the content on that service
/// </summary> /// </summary>
[IgnoreDataMember] [IgnoreDataMember]
public string ExternalId public string ExternalId
@ -201,11 +213,6 @@ namespace MediaBrowser.Controller.Entities
} }
} }
public virtual bool IsHiddenFromUser(User user)
{
return false;
}
[IgnoreDataMember] [IgnoreDataMember]
public virtual bool IsOwnedItem public virtual bool IsOwnedItem
{ {
@ -325,12 +332,14 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the date created. /// Gets or sets the date created.
/// </summary> /// </summary>
/// <value>The date created.</value> /// <value>The date created.</value>
[IgnoreDataMember]
public DateTime DateCreated { get; set; } public DateTime DateCreated { get; set; }
/// <summary> /// <summary>
/// Gets or sets the date modified. /// Gets or sets the date modified.
/// </summary> /// </summary>
/// <value>The date modified.</value> /// <value>The date modified.</value>
[IgnoreDataMember]
public DateTime DateModified { get; set; } public DateTime DateModified { get; set; }
public DateTime DateLastSaved { get; set; } public DateTime DateLastSaved { get; set; }
@ -407,6 +416,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the name of the forced sort. /// Gets or sets the name of the forced sort.
/// </summary> /// </summary>
/// <value>The name of the forced sort.</value> /// <value>The name of the forced sort.</value>
[IgnoreDataMember]
public string ForcedSortName public string ForcedSortName
{ {
get { return _forcedSortName; } get { return _forcedSortName; }
@ -447,10 +457,7 @@ namespace MediaBrowser.Controller.Entities
{ {
var idString = Id.ToString("N"); 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); return System.IO.Path.Combine(basePath, idString.Substring(0, 2), idString);
} }
@ -493,6 +500,7 @@ namespace MediaBrowser.Controller.Entities
return sortable; return sortable;
} }
[IgnoreDataMember]
public Guid ParentId { get; set; } public Guid ParentId { get; set; }
/// <summary> /// <summary>
@ -502,15 +510,7 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember] [IgnoreDataMember]
public Folder Parent public Folder Parent
{ {
get get { return GetParent() as Folder; }
{
if (ParentId != Guid.Empty)
{
return LibraryManager.GetItemById(ParentId) as Folder;
}
return null;
}
set set
{ {
@ -525,16 +525,28 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember] [IgnoreDataMember]
public IEnumerable<Folder> Parents public IEnumerable<Folder> Parents
{ {
get get { return GetParents().OfType<Folder>(); }
}
public BaseItem GetParent()
{ {
var parent = Parent; if (ParentId != Guid.Empty)
{
return LibraryManager.GetItemById(ParentId);
}
return null;
}
public IEnumerable<BaseItem> GetParents()
{
var parent = GetParent();
while (parent != null) while (parent != null)
{ {
yield return parent; yield return parent;
parent = parent.Parent; parent = parent.GetParent();
}
} }
} }
@ -546,19 +558,20 @@ namespace MediaBrowser.Controller.Entities
public T FindParent<T>() public T FindParent<T>()
where T : Folder where T : Folder
{ {
return Parents.OfType<T>().FirstOrDefault(); return GetParents().OfType<T>().FirstOrDefault();
} }
[IgnoreDataMember] [IgnoreDataMember]
public virtual BaseItem DisplayParent public virtual BaseItem DisplayParent
{ {
get { return Parent; } get { return GetParent(); }
} }
/// <summary> /// <summary>
/// When the item first debuted. For movies this could be premiere date, episodes would be first aired /// When the item first debuted. For movies this could be premiere date, episodes would be first aired
/// </summary> /// </summary>
/// <value>The premiere date.</value> /// <value>The premiere date.</value>
[IgnoreDataMember]
public DateTime? PremiereDate { get; set; } public DateTime? PremiereDate { get; set; }
/// <summary> /// <summary>
@ -572,31 +585,35 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the display type of the media. /// Gets or sets the display type of the media.
/// </summary> /// </summary>
/// <value>The display type of the media.</value> /// <value>The display type of the media.</value>
[IgnoreDataMember]
public string DisplayMediaType { get; set; } public string DisplayMediaType { get; set; }
/// <summary> /// <summary>
/// Gets or sets the official rating. /// Gets or sets the official rating.
/// </summary> /// </summary>
/// <value>The official rating.</value> /// <value>The official rating.</value>
[IgnoreDataMember]
public string OfficialRating { get; set; } public string OfficialRating { get; set; }
/// <summary> /// <summary>
/// Gets or sets the official rating description. /// Gets or sets the official rating description.
/// </summary> /// </summary>
/// <value>The official rating description.</value> /// <value>The official rating description.</value>
[IgnoreDataMember]
public string OfficialRatingDescription { get; set; } public string OfficialRatingDescription { get; set; }
/// <summary> /// <summary>
/// Gets or sets the custom rating. /// Gets or sets the custom rating.
/// </summary> /// </summary>
/// <value>The custom rating.</value> /// <value>The custom rating.</value>
//[IgnoreDataMember] [IgnoreDataMember]
public string CustomRating { get; set; } public string CustomRating { get; set; }
/// <summary> /// <summary>
/// Gets or sets the overview. /// Gets or sets the overview.
/// </summary> /// </summary>
/// <value>The overview.</value> /// <value>The overview.</value>
[IgnoreDataMember]
public string Overview { get; set; } public string Overview { get; set; }
/// <summary> /// <summary>
@ -609,37 +626,48 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the genres. /// Gets or sets the genres.
/// </summary> /// </summary>
/// <value>The genres.</value> /// <value>The genres.</value>
[IgnoreDataMember]
public List<string> Genres { get; set; } public List<string> Genres { get; set; }
/// <summary>
/// Gets or sets the tags.
/// </summary>
/// <value>The tags.</value>
public List<string> Tags { get; set; }
/// <summary> /// <summary>
/// Gets or sets the home page URL. /// Gets or sets the home page URL.
/// </summary> /// </summary>
/// <value>The home page URL.</value> /// <value>The home page URL.</value>
[IgnoreDataMember]
public string HomePageUrl { get; set; } public string HomePageUrl { get; set; }
/// <summary> /// <summary>
/// Gets or sets the community rating. /// Gets or sets the community rating.
/// </summary> /// </summary>
/// <value>The community rating.</value> /// <value>The community rating.</value>
//[IgnoreDataMember] [IgnoreDataMember]
public float? CommunityRating { get; set; } public float? CommunityRating { get; set; }
/// <summary> /// <summary>
/// Gets or sets the community rating vote count. /// Gets or sets the community rating vote count.
/// </summary> /// </summary>
/// <value>The community rating vote count.</value> /// <value>The community rating vote count.</value>
[IgnoreDataMember]
public int? VoteCount { get; set; } public int? VoteCount { get; set; }
/// <summary> /// <summary>
/// Gets or sets the run time ticks. /// Gets or sets the run time ticks.
/// </summary> /// </summary>
/// <value>The run time ticks.</value> /// <value>The run time ticks.</value>
[IgnoreDataMember]
public long? RunTimeTicks { get; set; } public long? RunTimeTicks { get; set; }
/// <summary> /// <summary>
/// Gets or sets the production year. /// Gets or sets the production year.
/// </summary> /// </summary>
/// <value>The production year.</value> /// <value>The production year.</value>
[IgnoreDataMember]
public int? ProductionYear { get; set; } public int? ProductionYear { get; set; }
/// <summary> /// <summary>
@ -647,19 +675,34 @@ namespace MediaBrowser.Controller.Entities
/// This could be episode number, album track number, etc. /// This could be episode number, album track number, etc.
/// </summary> /// </summary>
/// <value>The index number.</value> /// <value>The index number.</value>
//[IgnoreDataMember] [IgnoreDataMember]
public int? IndexNumber { get; set; } public int? IndexNumber { get; set; }
/// <summary> /// <summary>
/// For an episode this could be the season number, or for a song this could be the disc number. /// For an episode this could be the season number, or for a song this could be the disc number.
/// </summary> /// </summary>
/// <value>The parent index number.</value> /// <value>The parent index number.</value>
[IgnoreDataMember]
public int? ParentIndexNumber { get; set; } public int? ParentIndexNumber { get; set; }
[IgnoreDataMember] [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] [IgnoreDataMember]
@ -821,7 +864,7 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember] [IgnoreDataMember]
protected virtual bool SupportsOwnedItems protected virtual bool SupportsOwnedItems
{ {
get { return IsFolder || Parent != null; } get { return IsFolder || GetParent() != null; }
} }
[IgnoreDataMember] [IgnoreDataMember]
@ -846,7 +889,7 @@ namespace MediaBrowser.Controller.Entities
var localTrailersChanged = false; var localTrailersChanged = false;
if (LocationType == LocationType.FileSystem && Parent != null) if (LocationType == LocationType.FileSystem && GetParent() != null)
{ {
var hasThemeMedia = this as IHasThemeMedia; var hasThemeMedia = this as IHasThemeMedia;
if (hasThemeMedia != null) if (hasThemeMedia != null)
@ -1008,7 +1051,7 @@ namespace MediaBrowser.Controller.Entities
if (string.IsNullOrWhiteSpace(lang)) if (string.IsNullOrWhiteSpace(lang))
{ {
lang = Parents lang = GetParents()
.Select(i => i.PreferredMetadataLanguage) .Select(i => i.PreferredMetadataLanguage)
.FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
} }
@ -1038,7 +1081,7 @@ namespace MediaBrowser.Controller.Entities
if (string.IsNullOrWhiteSpace(lang)) if (string.IsNullOrWhiteSpace(lang))
{ {
lang = Parents lang = GetParents()
.Select(i => i.PreferredMetadataCountryCode) .Select(i => i.PreferredMetadataCountryCode)
.FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
} }
@ -1119,6 +1162,23 @@ namespace MediaBrowser.Controller.Entities
} }
public int? GetParentalRatingValue() public int? GetParentalRatingValue()
{
var rating = CustomRating;
if (string.IsNullOrWhiteSpace(rating))
{
rating = OfficialRating;
}
if (string.IsNullOrWhiteSpace(rating))
{
return null;
}
return LocalizationManager.GetRatingLevel(rating);
}
public int? GetInheritedParentalRatingValue()
{ {
var rating = CustomRatingForComparison; var rating = CustomRatingForComparison;
@ -1156,6 +1216,11 @@ namespace MediaBrowser.Controller.Entities
return true; return true;
} }
public virtual UnratedItem GetBlockUnratedType()
{
return UnratedItem.Other;
}
/// <summary> /// <summary>
/// Gets the block unrated value. /// Gets the block unrated value.
/// </summary> /// </summary>
@ -1174,7 +1239,7 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
return config.BlockUnratedItems.Contains(UnratedItem.Other); return config.BlockUnratedItems.Contains(GetBlockUnratedType());
} }
/// <summary> /// <summary>
@ -1206,14 +1271,14 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
if (Parents.Any(i => !i.IsVisible(user))) if (GetParents().Any(i => !i.IsVisible(user)))
{ {
return false; return false;
} }
if (checkFolders) if (checkFolders)
{ {
var topParent = Parents.LastOrDefault() ?? this; var topParent = GetParents().LastOrDefault() ?? this;
if (string.IsNullOrWhiteSpace(topParent.Path)) if (string.IsNullOrWhiteSpace(topParent.Path))
{ {
@ -1307,15 +1372,6 @@ namespace MediaBrowser.Controller.Entities
return null; return null;
} }
/// <summary>
/// Adds a person to the item
/// </summary>
/// <param name="person">The person.</param>
/// <exception cref="System.ArgumentNullException"></exception>
public void AddPerson(PersonInfo person)
{
}
/// <summary> /// <summary>
/// Adds a studio to the item /// Adds a studio to the item
/// </summary> /// </summary>
@ -1875,5 +1931,54 @@ namespace MediaBrowser.Controller.Entities
DateLastSaved.Ticks.ToString(CultureInfo.InvariantCulture) DateLastSaved.Ticks.ToString(CultureInfo.InvariantCulture)
}; };
} }
public virtual IEnumerable<Guid> GetAncestorIds()
{
return GetParents().Select(i => i.Id).Concat(LibraryManager.GetCollectionFolders(this).Select(i => i.Id));
}
public BaseItem GetTopParent()
{
if (IsTopParent)
{
return this;
}
return GetParents().FirstOrDefault(i => i.IsTopParent);
}
[IgnoreDataMember]
public virtual bool IsTopParent
{
get
{
if (GetParent() is AggregateFolder || this is Channel || this is BasePluginFolder)
{
return true;
}
var view = this as UserView;
if (view != null && string.Equals(view.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
{
return true;
}
return false;
}
}
[IgnoreDataMember]
public virtual bool SupportsAncestors
{
get
{
return true;
}
}
public virtual IEnumerable<Guid> GetIdsForAncestorQuery()
{
return new[] { Id };
}
} }
} }

View File

@ -17,19 +17,8 @@ namespace MediaBrowser.Controller.Entities
} }
} }
/// <summary>
/// Gets or sets the tags.
/// </summary>
/// <value>The tags.</value>
public List<string> Tags { get; set; }
public string SeriesName { get; set; } public string SeriesName { get; set; }
public Book()
{
Tags = new List<string>();
}
public override bool CanDownload() public override bool CanDownload()
{ {
var locationType = LocationType; var locationType = LocationType;
@ -37,9 +26,9 @@ namespace MediaBrowser.Controller.Entities
locationType != LocationType.Virtual; locationType != LocationType.Virtual;
} }
protected override bool GetBlockUnratedValue(UserPolicy config) public override UnratedItem GetBlockUnratedType()
{ {
return config.BlockUnratedItems.Contains(UnratedItem.Book); return UnratedItem.Book;
} }
public BookInfo GetLookupInfo() public BookInfo GetLookupInfo()
@ -48,7 +37,7 @@ namespace MediaBrowser.Controller.Entities
if (string.IsNullOrEmpty(SeriesName)) if (string.IsNullOrEmpty(SeriesName))
{ {
info.SeriesName = Parents.Select(i => i.Name).FirstOrDefault(); info.SeriesName = GetParents().Select(i => i.Name).FirstOrDefault();
} }
else else
{ {

View File

@ -181,9 +181,7 @@ namespace MediaBrowser.Controller.Entities
} }
private List<LinkedChild> GetLinkedChildrenInternal() private List<LinkedChild> GetLinkedChildrenInternal()
{ {
return LibraryManager.RootFolder.Children return GetPhysicalParents()
.OfType<Folder>()
.Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase))
.SelectMany(c => c.LinkedChildren) .SelectMany(c => c.LinkedChildren)
.ToList(); .ToList();
} }
@ -199,11 +197,14 @@ namespace MediaBrowser.Controller.Entities
private IEnumerable<BaseItem> GetActualChildren() private IEnumerable<BaseItem> GetActualChildren()
{ {
return return GetPhysicalParents().SelectMany(c => c.Children);
LibraryManager.RootFolder.Children }
public IEnumerable<Folder> GetPhysicalParents()
{
return LibraryManager.RootFolder.Children
.OfType<Folder>() .OfType<Folder>()
.Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase)) .Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase));
.SelectMany(c => c.Children);
} }
[IgnoreDataMember] [IgnoreDataMember]

View File

@ -28,7 +28,6 @@ namespace MediaBrowser.Controller.Entities
public List<Guid> ThemeSongIds { get; set; } public List<Guid> ThemeSongIds { get; set; }
public List<Guid> ThemeVideoIds { get; set; } public List<Guid> ThemeVideoIds { get; set; }
public List<string> Tags { get; set; }
public Folder() public Folder()
{ {
@ -36,7 +35,6 @@ namespace MediaBrowser.Controller.Entities
ThemeSongIds = new List<Guid>(); ThemeSongIds = new List<Guid>();
ThemeVideoIds = new List<Guid>(); ThemeVideoIds = new List<Guid>();
Tags = new List<string>();
} }
[IgnoreDataMember] [IgnoreDataMember]
@ -151,8 +149,16 @@ namespace MediaBrowser.Controller.Entities
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false); await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
if (!EnableNewFolderQuerying())
{
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false); await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
} }
}
private static bool EnableNewFolderQuerying()
{
return ConfigurationManager.Configuration.MigrationVersion >= 1;
}
protected void AddChildrenInternal(IEnumerable<BaseItem> children) protected void AddChildrenInternal(IEnumerable<BaseItem> children)
{ {
@ -196,21 +202,6 @@ namespace MediaBrowser.Controller.Entities
} }
} }
[IgnoreDataMember]
public override string OfficialRatingForComparison
{
get
{
// Never want folders to be blocked by "BlockNotRated"
if (this is Series)
{
return base.OfficialRatingForComparison;
}
return !string.IsNullOrWhiteSpace(base.OfficialRatingForComparison) ? base.OfficialRatingForComparison : "None";
}
}
/// <summary> /// <summary>
/// Removes the child. /// Removes the child.
/// </summary> /// </summary>
@ -224,9 +215,14 @@ namespace MediaBrowser.Controller.Entities
item.SetParent(null); item.SetParent(null);
if (!EnableNewFolderQuerying())
{
return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken); return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken);
} }
return Task.FromResult(true);
}
/// <summary> /// <summary>
/// Clears the children. /// Clears the children.
/// </summary> /// </summary>
@ -457,9 +453,7 @@ namespace MediaBrowser.Controller.Entities
{ {
BaseItem currentChild; BaseItem currentChild;
if (currentChildren.TryGetValue(child.Id, out currentChild)) if (currentChildren.TryGetValue(child.Id, out currentChild) && IsValidFromResolver(currentChild, child))
{
if (IsValidFromResolver(currentChild, child))
{ {
var currentChildLocationType = currentChild.LocationType; var currentChildLocationType = currentChild.LocationType;
if (currentChildLocationType != LocationType.Remote && if (currentChildLocationType != LocationType.Remote &&
@ -470,20 +464,15 @@ namespace MediaBrowser.Controller.Entities
await UpdateIsOffline(currentChild, false).ConfigureAwait(false); await UpdateIsOffline(currentChild, false).ConfigureAwait(false);
validChildren.Add(currentChild); validChildren.Add(currentChild);
continue;
} }
else
{
newItems.Add(child);
validChildren.Add(child);
}
}
else
{
// Brand new item - needs to be added // Brand new item - needs to be added
child.SetParent(this);
newItems.Add(child); newItems.Add(child);
validChildren.Add(child); validChildren.Add(child);
} }
}
// If any items were added or removed.... // If any items were added or removed....
if (newItems.Count > 0 || currentChildren.Count != validChildren.Count) if (newItems.Count > 0 || currentChildren.Count != validChildren.Count)
@ -508,7 +497,6 @@ namespace MediaBrowser.Controller.Entities
} }
else else
{ {
await UpdateIsOffline(item, false).ConfigureAwait(false);
actualRemovals.Add(item); actualRemovals.Add(item);
} }
} }
@ -519,6 +507,11 @@ namespace MediaBrowser.Controller.Entities
foreach (var item in actualRemovals) foreach (var item in actualRemovals)
{ {
Logger.Debug("Removed item: " + item.Path);
item.SetParent(null);
item.IsOffline = false;
await LibraryManager.DeleteItem(item, new DeleteOptions { DeleteFileLocation = false }).ConfigureAwait(false);
LibraryManager.ReportItemRemoved(item); LibraryManager.ReportItemRemoved(item);
} }
} }
@ -527,9 +520,12 @@ namespace MediaBrowser.Controller.Entities
AddChildrenInternal(newItems); AddChildrenInternal(newItems);
if (!EnableNewFolderQuerying())
{
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false); await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
} }
} }
}
progress.Report(10); progress.Report(10);
@ -721,7 +717,7 @@ namespace MediaBrowser.Controller.Entities
return true; return true;
} }
return ContainsPath(LibraryManager.GetVirtualFolders(), originalPath); return false;
} }
/// <summary> /// <summary>
@ -757,20 +753,17 @@ namespace MediaBrowser.Controller.Entities
/// <returns>IEnumerable{BaseItem}.</returns> /// <returns>IEnumerable{BaseItem}.</returns>
protected IEnumerable<BaseItem> GetCachedChildren() protected IEnumerable<BaseItem> GetCachedChildren()
{ {
if (ConfigurationManager.Configuration.DisableStartupScan) if (EnableNewFolderQuerying())
{ {
return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null); return ItemRepository.GetItemList(new InternalItemsQuery
//return ItemRepository.GetItems(new InternalItemsQuery {
//{ ParentId = Id
// ParentId = Id
//}).Items.Select(RetrieveChild).Where(i => i != null); }).Select(RetrieveChild).Where(i => i != null);
} }
else
{
return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null); return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null);
} }
}
private BaseItem RetrieveChild(BaseItem child) private BaseItem RetrieveChild(BaseItem child)
{ {
@ -832,19 +825,7 @@ namespace MediaBrowser.Controller.Entities
return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager); return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager);
} }
/// <summary>
/// Gets allowed children of an item
/// </summary>
/// <param name="user">The user.</param>
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
/// <returns>IEnumerable{BaseItem}.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren) public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
{
return GetChildren(user, includeLinkedChildren, false);
}
internal IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren, bool includeHidden)
{ {
if (user == null) if (user == null)
{ {
@ -856,7 +837,7 @@ namespace MediaBrowser.Controller.Entities
var result = new Dictionary<Guid, BaseItem>(); var result = new Dictionary<Guid, BaseItem>();
AddChildren(user, includeLinkedChildren, result, includeHidden, false, null); AddChildren(user, includeLinkedChildren, result, false, null);
return result.Values; return result.Values;
} }
@ -872,29 +853,25 @@ namespace MediaBrowser.Controller.Entities
/// <param name="user">The user.</param> /// <param name="user">The user.</param>
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param> /// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
/// <param name="result">The result.</param> /// <param name="result">The result.</param>
/// <param name="includeHidden">if set to <c>true</c> [include hidden].</param>
/// <param name="recursive">if set to <c>true</c> [recursive].</param> /// <param name="recursive">if set to <c>true</c> [recursive].</param>
/// <param name="filter">The filter.</param> /// <param name="filter">The filter.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool includeHidden, bool recursive, Func<BaseItem, bool> filter) private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, Func<BaseItem, bool> filter)
{ {
foreach (var child in GetEligibleChildrenForRecursiveChildren(user)) foreach (var child in GetEligibleChildrenForRecursiveChildren(user))
{ {
if (child.IsVisible(user)) if (child.IsVisible(user))
{
if (includeHidden || !child.IsHiddenFromUser(user))
{ {
if (filter == null || filter(child)) if (filter == null || filter(child))
{ {
result[child.Id] = child; result[child.Id] = child;
} }
}
if (recursive && child.IsFolder) if (recursive && child.IsFolder)
{ {
var folder = (Folder)child; var folder = (Folder)child;
folder.AddChildren(user, includeLinkedChildren, result, includeHidden, true, filter); folder.AddChildren(user, includeLinkedChildren, result, true, filter);
} }
} }
} }
@ -935,7 +912,7 @@ namespace MediaBrowser.Controller.Entities
var result = new Dictionary<Guid, BaseItem>(); var result = new Dictionary<Guid, BaseItem>();
AddChildren(user, true, result, false, true, filter); AddChildren(user, true, result, true, filter);
return result.Values; return result.Values;
} }
@ -1184,6 +1161,7 @@ namespace MediaBrowser.Controller.Entities
Recursive = true, Recursive = true,
IsFolder = false, IsFolder = false,
IsUnaired = false IsUnaired = false
}; };
if (!user.Configuration.DisplayMissingEpisodes) if (!user.Configuration.DisplayMissingEpisodes)

View File

@ -21,7 +21,6 @@ namespace MediaBrowser.Controller.Entities
RemoteTrailerIds = new List<Guid>(); RemoteTrailerIds = new List<Guid>();
ThemeSongIds = new List<Guid>(); ThemeSongIds = new List<Guid>();
ThemeVideoIds = new List<Guid>(); ThemeVideoIds = new List<Guid>();
Tags = new List<string>();
} }
public List<Guid> LocalTrailerIds { get; set; } public List<Guid> LocalTrailerIds { get; set; }
@ -34,12 +33,6 @@ namespace MediaBrowser.Controller.Entities
locationType != LocationType.Virtual; locationType != LocationType.Virtual;
} }
/// <summary>
/// Gets or sets the tags.
/// </summary>
/// <value>The tags.</value>
public List<string> Tags { get; set; }
/// <summary> /// <summary>
/// Gets or sets the remote trailers. /// Gets or sets the remote trailers.
/// </summary> /// </summary>
@ -105,9 +98,9 @@ namespace MediaBrowser.Controller.Entities
return base.GetDeletePaths(); return base.GetDeletePaths();
} }
protected override bool GetBlockUnratedValue(UserPolicy config) public override UnratedItem GetBlockUnratedType()
{ {
return config.BlockUnratedItems.Contains(UnratedItem.Game); return UnratedItem.Game;
} }
public GameInfo GetLookupInfo() public GameInfo GetLookupInfo()

View File

@ -50,6 +50,11 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Game;
}
public GameSystemInfo GetLookupInfo() public GameSystemInfo GetLookupInfo()
{ {
var id = GetItemLookupInfo<GameSystemInfo>(); var id = GetItemLookupInfo<GameSystemInfo>();

View File

@ -16,6 +16,11 @@ namespace MediaBrowser.Controller.Entities
IEnumerable<string> PhysicalLocations { get; } IEnumerable<string> PhysicalLocations { get; }
} }
public interface ISupportsUserSpecificView
{
bool EnableUserSpecificView { get; }
}
public static class CollectionFolderExtensions public static class CollectionFolderExtensions
{ {
public static string GetViewType(this ICollectionFolder folder, User user) public static string GetViewType(this ICollectionFolder folder, User user)

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Entities
{
public interface IHiddenFromDisplay
{
/// <summary>
/// Determines whether the specified user is hidden.
/// </summary>
/// <param name="user">The user.</param>
/// <returns><c>true</c> if the specified user is hidden; otherwise, <c>false</c>.</returns>
bool IsHiddenFromUser(User user);
}
}

View File

@ -1,6 +1,7 @@
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Controller.Entities namespace MediaBrowser.Controller.Entities
{ {
@ -30,6 +31,7 @@ namespace MediaBrowser.Controller.Entities
public string[] MediaTypes { get; set; } public string[] MediaTypes { get; set; }
public string[] IncludeItemTypes { get; set; } public string[] IncludeItemTypes { get; set; }
public string[] ExcludeItemTypes { get; set; } public string[] ExcludeItemTypes { get; set; }
public string[] ExcludeTags { get; set; }
public string[] Genres { get; set; } public string[] Genres { get; set; }
public bool? IsMissing { get; set; } public bool? IsMissing { get; set; }
@ -69,12 +71,15 @@ namespace MediaBrowser.Controller.Entities
public string[] Studios { get; set; } public string[] Studios { get; set; }
public string[] StudioIds { get; set; } public string[] StudioIds { get; set; }
public string[] GenreIds { get; set; }
public ImageType[] ImageTypes { get; set; } public ImageType[] ImageTypes { get; set; }
public VideoType[] VideoTypes { get; set; } public VideoType[] VideoTypes { get; set; }
public UnratedItem[] BlockUnratedItems { get; set; }
public int[] Years { get; set; } public int[] Years { get; set; }
public string[] Tags { get; set; } public string[] Tags { get; set; }
public string[] OfficialRatings { get; set; } public string[] OfficialRatings { get; set; }
public DateTime? MinPremiereDate { get; set; }
public DateTime? MinStartDate { get; set; } public DateTime? MinStartDate { get; set; }
public DateTime? MaxStartDate { get; set; } public DateTime? MaxStartDate { get; set; }
public DateTime? MinEndDate { get; set; } public DateTime? MinEndDate { get; set; }
@ -87,6 +92,7 @@ namespace MediaBrowser.Controller.Entities
public int? MinPlayers { get; set; } public int? MinPlayers { get; set; }
public int? MaxPlayers { get; set; } public int? MaxPlayers { get; set; }
public int? MinIndexNumber { get; set; }
public double? MinCriticRating { get; set; } public double? MinCriticRating { get; set; }
public double? MinCommunityRating { get; set; } public double? MinCommunityRating { get; set; }
@ -101,9 +107,14 @@ namespace MediaBrowser.Controller.Entities
public LocationType? LocationType { get; set; } public LocationType? LocationType { get; set; }
public Guid? ParentId { get; set; } public Guid? ParentId { get; set; }
public string[] AncestorIds { get; set; }
public string[] TopParentIds { get; set; }
public LocationType[] ExcludeLocationTypes { get; set; }
public InternalItemsQuery() public InternalItemsQuery()
{ {
BlockUnratedItems = new UnratedItem[] { };
Tags = new string[] { }; Tags = new string[] { };
OfficialRatings = new string[] { }; OfficialRatings = new string[] { };
SortBy = new string[] { }; SortBy = new string[] { };
@ -113,6 +124,7 @@ namespace MediaBrowser.Controller.Entities
Genres = new string[] { }; Genres = new string[] { };
Studios = new string[] { }; Studios = new string[] { };
StudioIds = new string[] { }; StudioIds = new string[] { };
GenreIds = new string[] { };
ImageTypes = new ImageType[] { }; ImageTypes = new ImageType[] { };
VideoTypes = new VideoType[] { }; VideoTypes = new VideoType[] { };
Years = new int[] { }; Years = new int[] { };
@ -120,6 +132,29 @@ namespace MediaBrowser.Controller.Entities
PersonIds = new string[] { }; PersonIds = new string[] { };
ChannelIds = new string[] { }; ChannelIds = new string[] { };
ItemIds = new string[] { }; ItemIds = new string[] { };
AncestorIds = new string[] { };
TopParentIds = new string[] { };
ExcludeTags = new string[] { };
ExcludeLocationTypes = new LocationType[] { };
}
public InternalItemsQuery(User user)
: this()
{
if (user != null)
{
var policy = user.Policy;
MaxParentalRating = policy.MaxParentalRating;
if (policy.MaxParentalRating.HasValue)
{
BlockUnratedItems = policy.BlockUnratedItems;
}
ExcludeTags = policy.BlockedTags;
User = user;
}
} }
} }
} }

View File

@ -8,15 +8,13 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Entities.Movies namespace MediaBrowser.Controller.Entities.Movies
{ {
/// <summary> /// <summary>
/// Class BoxSet /// Class BoxSet
/// </summary> /// </summary>
public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IMetadataContainer, IHasShares public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IHasShares
{ {
public List<Share> Shares { get; set; } public List<Share> Shares { get; set; }
@ -65,6 +63,11 @@ namespace MediaBrowser.Controller.Entities.Movies
return config.BlockUnratedItems.Contains(UnratedItem.Movie); return config.BlockUnratedItems.Contains(UnratedItem.Movie);
} }
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Movie;
}
[IgnoreDataMember] [IgnoreDataMember]
public override bool IsPreSorted public override bool IsPreSorted
{ {
@ -154,34 +157,6 @@ namespace MediaBrowser.Controller.Entities.Movies
return GetItemLookupInfo<BoxSetInfo>(); return GetItemLookupInfo<BoxSetInfo>();
} }
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
{
// Refresh bottom up, children first, then the boxset
// By then hopefully the movies within will have Tmdb collection values
var items = GetRecursiveChildren().ToList();
var totalItems = items.Count;
var numComplete = 0;
// Refresh songs
foreach (var item in items)
{
cancellationToken.ThrowIfCancellationRequested();
await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
numComplete++;
double percent = numComplete;
percent /= totalItems;
progress.Report(percent * 100);
}
// Refresh current item
await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
progress.Report(100);
}
public override bool IsVisible(User user) public override bool IsVisible(User user)
{ {
var userId = user.Id.ToString("N"); var userId = user.Id.ToString("N");

View File

@ -130,7 +130,7 @@ namespace MediaBrowser.Controller.Entities.Movies
// Must have a parent to have special features // Must have a parent to have special features
// In other words, it must be part of the Parent/Child tree // In other words, it must be part of the Parent/Child tree
if (LocationType == LocationType.FileSystem && Parent != null && !IsInMixedFolder) if (LocationType == LocationType.FileSystem && GetParent() != null && !IsInMixedFolder)
{ {
var specialFeaturesChanged = await RefreshSpecialFeatures(options, fileSystemChildren, cancellationToken).ConfigureAwait(false); var specialFeaturesChanged = await RefreshSpecialFeatures(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
@ -159,9 +159,9 @@ namespace MediaBrowser.Controller.Entities.Movies
return itemsChanged; return itemsChanged;
} }
protected override bool GetBlockUnratedValue(UserPolicy config) public override UnratedItem GetBlockUnratedType()
{ {
return config.BlockUnratedItems.Contains(UnratedItem.Movie); return UnratedItem.Movie;
} }
public MovieInfo GetLookupInfo() public MovieInfo GetLookupInfo()

View File

@ -56,9 +56,9 @@ namespace MediaBrowser.Controller.Entities
return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.CreateUserDataKey(); return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.CreateUserDataKey();
} }
protected override bool GetBlockUnratedValue(UserPolicy config) public override UnratedItem GetBlockUnratedType()
{ {
return config.BlockUnratedItems.Contains(UnratedItem.Music); return UnratedItem.Music;
} }
public MusicVideoInfo GetLookupInfo() public MusicVideoInfo GetLookupInfo()

View File

@ -101,6 +101,15 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
} }
[IgnoreDataMember]
public override bool SupportsAncestors
{
get
{
return false;
}
}
} }
/// <summary> /// <summary>

View File

@ -9,12 +9,10 @@ namespace MediaBrowser.Controller.Entities
{ {
public class Photo : BaseItem, IHasTags, IHasTaglines public class Photo : BaseItem, IHasTags, IHasTaglines
{ {
public List<string> Tags { get; set; }
public List<string> Taglines { get; set; } public List<string> Taglines { get; set; }
public Photo() public Photo()
{ {
Tags = new List<string>();
Taglines = new List<string>(); Taglines = new List<string>();
} }
@ -51,7 +49,7 @@ namespace MediaBrowser.Controller.Entities
{ {
get get
{ {
return Parents.OfType<PhotoAlbum>().FirstOrDefault(); return GetParents().OfType<PhotoAlbum>().FirstOrDefault();
} }
} }
@ -70,10 +68,5 @@ namespace MediaBrowser.Controller.Entities
public double? Longitude { get; set; } public double? Longitude { get; set; }
public double? Altitude { get; set; } public double? Altitude { get; set; }
public int? IsoSpeedRating { get; set; } public int? IsoSpeedRating { get; set; }
protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Other);
}
} }
} }

View File

@ -9,8 +9,9 @@ using System.Threading.Tasks;
namespace MediaBrowser.Controller.Entities namespace MediaBrowser.Controller.Entities
{ {
public class PhotoAlbum : Folder, IMetadataContainer public class PhotoAlbum : Folder
{ {
[IgnoreDataMember]
public override bool SupportsLocalMetadata public override bool SupportsLocalMetadata
{ {
get get
@ -32,31 +33,5 @@ namespace MediaBrowser.Controller.Entities
{ {
return config.BlockUnratedItems.Contains(UnratedItem.Other); return config.BlockUnratedItems.Contains(UnratedItem.Other);
} }
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
{
var items = GetRecursiveChildren().ToList();
var totalItems = items.Count;
var numComplete = 0;
// Refresh songs
foreach (var item in items)
{
cancellationToken.ThrowIfCancellationRequested();
await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
numComplete++;
double percent = numComplete;
percent /= totalItems;
progress.Report(percent * 100);
}
// Refresh current item
await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
progress.Report(100);
}
} }
} }

View File

@ -10,13 +10,6 @@ namespace MediaBrowser.Controller.Entities
/// </summary> /// </summary>
public class Studio : BaseItem, IItemByName, IHasTags public class Studio : BaseItem, IItemByName, IHasTags
{ {
public List<string> Tags { get; set; }
public Studio()
{
Tags = new List<string>();
}
/// <summary> /// <summary>
/// Gets the user data key. /// Gets the user data key.
/// </summary> /// </summary>

View File

@ -95,7 +95,7 @@ namespace MediaBrowser.Controller.Entities.TV
{ {
get get
{ {
return Season ?? Parent; return Season ?? GetParent();
} }
} }
@ -115,19 +115,6 @@ namespace MediaBrowser.Controller.Entities.TV
return base.CreateUserDataKey(); return base.CreateUserDataKey();
} }
/// <summary>
/// Our rating comes from our series
/// </summary>
[IgnoreDataMember]
public override string OfficialRatingForComparison
{
get
{
var series = Series;
return series != null ? series.OfficialRatingForComparison : base.OfficialRatingForComparison;
}
}
/// <summary> /// <summary>
/// This Episode's Series Instance /// This Episode's Series Instance
/// </summary> /// </summary>
@ -265,14 +252,28 @@ namespace MediaBrowser.Controller.Entities.TV
} }
} }
public override IEnumerable<Guid> GetAncestorIds()
{
var list = base.GetAncestorIds().ToList();
var seasonId = SeasonId;
if (seasonId.HasValue && !list.Contains(seasonId.Value))
{
list.Add(seasonId.Value);
}
return list;
}
public override IEnumerable<string> GetDeletePaths() public override IEnumerable<string> GetDeletePaths()
{ {
return new[] { Path }; return new[] { Path };
} }
protected override bool GetBlockUnratedValue(UserPolicy config) public override UnratedItem GetBlockUnratedType()
{ {
return config.BlockUnratedItems.Contains(UnratedItem.Series); return UnratedItem.Series;
} }
public EpisodeInfo GetLookupInfo() public EpisodeInfo GetLookupInfo()

View File

@ -6,6 +6,7 @@ using MoreLinq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Controller.Entities.TV namespace MediaBrowser.Controller.Entities.TV
{ {
@ -32,7 +33,7 @@ namespace MediaBrowser.Controller.Entities.TV
[IgnoreDataMember] [IgnoreDataMember]
public override BaseItem DisplayParent public override BaseItem DisplayParent
{ {
get { return Series ?? Parent; } get { return Series ?? GetParent(); }
} }
// Genre, Rating and Stuido will all be the same // Genre, Rating and Stuido will all be the same
@ -87,19 +88,6 @@ namespace MediaBrowser.Controller.Entities.TV
} }
} }
/// <summary>
/// Our rating comes from our series
/// </summary>
[IgnoreDataMember]
public override string OfficialRatingForComparison
{
get
{
var series = Series;
return series != null ? series.OfficialRatingForComparison : base.OfficialRatingForComparison;
}
}
/// <summary> /// <summary>
/// Creates the name of the sort. /// Creates the name of the sort.
/// </summary> /// </summary>
@ -234,6 +222,11 @@ namespace MediaBrowser.Controller.Entities.TV
return false; return false;
} }
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Series;
}
[IgnoreDataMember] [IgnoreDataMember]
public string SeriesName public string SeriesName
{ {

View File

@ -333,6 +333,11 @@ namespace MediaBrowser.Controller.Entities.TV
return config.BlockUnratedItems.Contains(UnratedItem.Series); return config.BlockUnratedItems.Contains(UnratedItem.Series);
} }
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Series;
}
public SeriesInfo GetLookupInfo() public SeriesInfo GetLookupInfo()
{ {
var info = GetItemLookupInfo<SeriesInfo>(); var info = GetItemLookupInfo<SeriesInfo>();

View File

@ -73,7 +73,7 @@ namespace MediaBrowser.Controller.Entities
get get
{ {
// Local trailers are not part of children // Local trailers are not part of children
return Parent == null; return GetParent() == null;
} }
} }
@ -97,9 +97,9 @@ namespace MediaBrowser.Controller.Entities
return base.CreateUserDataKey(); return base.CreateUserDataKey();
} }
protected override bool GetBlockUnratedValue(UserPolicy config) public override UnratedItem GetBlockUnratedType()
{ {
return config.BlockUnratedItems.Contains(UnratedItem.Trailer); return UnratedItem.Trailer;
} }
public TrailerInfo GetLookupInfo() public TrailerInfo GetLookupInfo()

View File

@ -20,7 +20,6 @@ namespace MediaBrowser.Controller.Entities
{ {
public static IUserManager UserManager { get; set; } public static IUserManager UserManager { get; set; }
public static IXmlSerializer XmlSerializer { get; set; } public static IXmlSerializer XmlSerializer { get; set; }
public bool EnableUserViews { get; set; }
/// <summary> /// <summary>
/// From now on all user paths will be Id-based. /// From now on all user paths will be Id-based.
@ -58,6 +57,26 @@ namespace MediaBrowser.Controller.Entities
} }
} }
private string _name;
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
public override string Name
{
get
{
return _name;
}
set
{
_name = value;
// lazy load this again
SortName = null;
}
}
/// <summary> /// <summary>
/// Returns the folder containing the item. /// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself /// If the item is a folder, it returns the folder itself

View File

@ -55,13 +55,21 @@ namespace MediaBrowser.Controller.Entities
} }
} }
protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
{
var list = base.GetEligibleChildrenForRecursiveChildren(user).ToList();
list.AddRange(LibraryManager.RootFolder.VirtualChildren);
return list;
}
/// <summary> /// <summary>
/// Get the children of this folder from the actual file system /// Get the children of this folder from the actual file system
/// </summary> /// </summary>
/// <returns>IEnumerable{BaseItem}.</returns> /// <returns>IEnumerable{BaseItem}.</returns>
protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService) protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
{ {
return base.GetNonCachedChildren(directoryService).Concat(LibraryManager.RootFolder.VirtualChildren); return base.GetNonCachedChildren(directoryService);
} }
public override bool BeforeMetadataRefresh() public override bool BeforeMetadataRefresh()

View File

@ -6,6 +6,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Linq;
namespace MediaBrowser.Controller.Entities namespace MediaBrowser.Controller.Entities
{ {
@ -25,6 +26,25 @@ namespace MediaBrowser.Controller.Entities
return true; return true;
} }
public override IEnumerable<Guid> GetIdsForAncestorQuery()
{
var list = new List<Guid>();
if (DisplayParentId != Guid.Empty)
{
list.Add(DisplayParentId);
}
else if (ParentId != Guid.Empty)
{
list.Add(ParentId);
}
else
{
list.Add(Id);
}
return list;
}
public override Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query) public override Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
{ {
var parent = this as Folder; var parent = this as Folder;
@ -81,34 +101,11 @@ namespace MediaBrowser.Controller.Entities
return GetChildren(user, false); return GetChildren(user, false);
} }
public static bool IsExcludedFromGrouping(Folder folder)
{
var standaloneTypes = new List<string>
{
CollectionType.Books,
CollectionType.HomeVideos,
CollectionType.Photos,
CollectionType.Playlists,
CollectionType.BoxSets,
CollectionType.MusicVideos
};
var collectionFolder = folder as ICollectionFolder;
if (collectionFolder == null)
{
return false;
}
return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty);
}
public static bool IsUserSpecific(Folder folder) public static bool IsUserSpecific(Folder folder)
{ {
var standaloneTypes = new List<string> var standaloneTypes = new List<string>
{ {
CollectionType.Playlists, CollectionType.Playlists
CollectionType.BoxSets
}; };
var collectionFolder = folder as ICollectionFolder; var collectionFolder = folder as ICollectionFolder;
@ -118,9 +115,65 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
var supportsUserSpecific = folder as ISupportsUserSpecificView;
if (supportsUserSpecific != null && supportsUserSpecific.EnableUserSpecificView)
{
return true;
}
return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty); return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty);
} }
public static bool IsEligibleForGrouping(Folder folder)
{
var collectionFolder = folder as ICollectionFolder;
return collectionFolder != null && IsEligibleForGrouping(collectionFolder.CollectionType);
}
public static bool IsEligibleForGrouping(string viewType)
{
var types = new[]
{
CollectionType.Movies,
CollectionType.TvShows,
string.Empty
};
return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
}
public static bool IsEligibleForEnhancedView(string viewType)
{
var types = new[]
{
CollectionType.Movies,
CollectionType.TvShows
};
return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
}
public static bool EnableOriginalFolder(string viewType)
{
var types = new[]
{
CollectionType.Games,
CollectionType.Books,
CollectionType.MusicVideos,
CollectionType.HomeVideos,
CollectionType.Photos,
CollectionType.Music,
CollectionType.BoxSets
};
return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
}
protected override Task ValidateChildrenInternal(IProgress<double> progress, System.Threading.CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, Providers.MetadataRefreshOptions refreshOptions, Providers.IDirectoryService directoryService)
{
return Task.FromResult(true);
}
[IgnoreDataMember] [IgnoreDataMember]
public override bool SupportsPeople public override bool SupportsPeople
{ {

View File

@ -120,59 +120,34 @@ namespace MediaBrowser.Controller.Entities
return await GetLiveTvView(queryParent, user, query).ConfigureAwait(false); return await GetLiveTvView(queryParent, user, query).ConfigureAwait(false);
} }
case CollectionType.Photos:
case CollectionType.Books: case CollectionType.Books:
case CollectionType.HomeVideos: case CollectionType.HomeVideos:
case CollectionType.Games:
case CollectionType.MusicVideos: case CollectionType.MusicVideos:
{
if (query.Recursive)
{
return GetResult(queryParent.GetRecursiveChildren(user, true), queryParent, query);
}
return GetResult(queryParent.GetChildren(user, true), queryParent, query); return GetResult(queryParent.GetChildren(user, true), queryParent, query);
}
case CollectionType.Folders: case CollectionType.Folders:
return GetResult(user.RootFolder.GetChildren(user, true), queryParent, query); return GetResult(user.RootFolder.GetChildren(user, true), queryParent, query);
case CollectionType.Games:
return await GetGameView(user, queryParent, query).ConfigureAwait(false);
case CollectionType.Playlists: case CollectionType.Playlists:
return await GetPlaylistsView(queryParent, user, query).ConfigureAwait(false); return await GetPlaylistsView(queryParent, user, query).ConfigureAwait(false);
case CollectionType.BoxSets: case CollectionType.BoxSets:
return await GetBoxsetView(queryParent, user, query).ConfigureAwait(false); return await GetBoxsetView(queryParent, user, query).ConfigureAwait(false);
case CollectionType.Photos:
return await GetPhotosView(queryParent, user, query).ConfigureAwait(false);
case CollectionType.TvShows: case CollectionType.TvShows:
return await GetTvView(queryParent, user, query).ConfigureAwait(false); return await GetTvView(queryParent, user, query).ConfigureAwait(false);
case CollectionType.Music:
return await GetMusicFolders(queryParent, user, query).ConfigureAwait(false);
case CollectionType.Movies: case CollectionType.Movies:
return await GetMovieFolders(queryParent, user, query).ConfigureAwait(false); return await GetMovieFolders(queryParent, user, query).ConfigureAwait(false);
case SpecialFolder.MusicGenres:
return await GetMusicGenres(queryParent, user, query).ConfigureAwait(false);
case SpecialFolder.MusicGenre:
return await GetMusicGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
case SpecialFolder.GameGenres:
return await GetGameGenres(queryParent, user, query).ConfigureAwait(false);
case SpecialFolder.GameGenre:
return await GetGameGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
case SpecialFolder.GameSystems:
return GetGameSystems(queryParent, user, query);
case SpecialFolder.LatestGames:
return GetLatestGames(queryParent, user, query);
case SpecialFolder.RecentlyPlayedGames:
return GetRecentlyPlayedGames(queryParent, user, query);
case SpecialFolder.GameFavorites:
return GetFavoriteGames(queryParent, user, query);
case SpecialFolder.TvShowSeries: case SpecialFolder.TvShowSeries:
return GetTvSeries(queryParent, user, query); return GetTvSeries(queryParent, user, query);
@ -212,6 +187,21 @@ namespace MediaBrowser.Controller.Entities
case SpecialFolder.MovieCollections: case SpecialFolder.MovieCollections:
return GetMovieCollections(queryParent, user, query); return GetMovieCollections(queryParent, user, query);
case SpecialFolder.TvFavoriteEpisodes:
return GetFavoriteEpisodes(queryParent, user, query);
case SpecialFolder.TvFavoriteSeries:
return GetFavoriteSeries(queryParent, user, query);
case CollectionType.Music:
return await GetMusicFolders(queryParent, user, query).ConfigureAwait(false);
case SpecialFolder.MusicGenres:
return await GetMusicGenres(queryParent, user, query).ConfigureAwait(false);
case SpecialFolder.MusicGenre:
return await GetMusicGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
case SpecialFolder.MusicLatest: case SpecialFolder.MusicLatest:
return GetMusicLatest(queryParent, user, query); return GetMusicLatest(queryParent, user, query);
@ -230,12 +220,6 @@ namespace MediaBrowser.Controller.Entities
case SpecialFolder.MusicSongs: case SpecialFolder.MusicSongs:
return GetMusicSongs(queryParent, user, query); return GetMusicSongs(queryParent, user, query);
case SpecialFolder.TvFavoriteEpisodes:
return GetFavoriteEpisodes(queryParent, user, query);
case SpecialFolder.TvFavoriteSeries:
return GetFavoriteSeries(queryParent, user, query);
case SpecialFolder.MusicFavorites: case SpecialFolder.MusicFavorites:
return await GetMusicFavorites(queryParent, user, query).ConfigureAwait(false); return await GetMusicFavorites(queryParent, user, query).ConfigureAwait(false);
@ -262,18 +246,6 @@ namespace MediaBrowser.Controller.Entities
} }
} }
private async Task<QueryResult<BaseItem>> FindPlaylists(Folder parent, User user, InternalItemsQuery query)
{
var list = _playlistManager.GetPlaylists(user.Id.ToString("N"));
return GetResult(list, parent, query);
}
private int GetSpecialItemsLimit()
{
return 50;
}
private async Task<QueryResult<BaseItem>> GetMusicFolders(Folder parent, User user, InternalItemsQuery query) private async Task<QueryResult<BaseItem>> GetMusicFolders(Folder parent, User user, InternalItemsQuery query)
{ {
if (query.Recursive) if (query.Recursive)
@ -289,7 +261,7 @@ namespace MediaBrowser.Controller.Entities
list.Add(await GetUserView(SpecialFolder.MusicPlaylists, "1", parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.MusicPlaylists, "1", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.MusicAlbums, "2", parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.MusicAlbums, "2", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.MusicAlbumArtists, "3", parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.MusicAlbumArtists, "3", parent).ConfigureAwait(false));
//list.Add(await GetUserView(SpecialFolder.MusicArtists, user, "4", parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.MusicArtists, "4", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.MusicSongs, "5", parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.MusicSongs, "5", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.MusicGenres, "6", parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.MusicGenres, "6", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.MusicFavorites, "7", parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.MusicFavorites, "7", parent).ConfigureAwait(false));
@ -422,6 +394,36 @@ namespace MediaBrowser.Controller.Entities
return PostFilterAndSort(items, parent, null, query); return PostFilterAndSort(items, parent, null, query);
} }
private QueryResult<BaseItem> GetFavoriteSongs(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is Audio.Audio) && FilterItem(i, query));
return PostFilterAndSort(items, parent, null, query);
}
private QueryResult<BaseItem> GetFavoriteAlbums(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is MusicAlbum) && FilterItem(i, query));
return PostFilterAndSort(items, parent, null, query);
}
private async Task<QueryResult<BaseItem>> FindPlaylists(Folder parent, User user, InternalItemsQuery query)
{
var list = _playlistManager.GetPlaylists(user.Id.ToString("N"));
return GetResult(list, parent, query);
}
private int GetSpecialItemsLimit()
{
return 50;
}
private async Task<QueryResult<BaseItem>> GetMovieFolders(Folder parent, User user, InternalItemsQuery query) private async Task<QueryResult<BaseItem>> GetMovieFolders(Folder parent, User user, InternalItemsQuery query)
{ {
if (query.Recursive) if (query.Recursive)
@ -480,24 +482,6 @@ namespace MediaBrowser.Controller.Entities
return PostFilterAndSort(items, parent, null, query); return PostFilterAndSort(items, parent, null, query);
} }
private QueryResult<BaseItem> GetFavoriteSongs(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is Audio.Audio) && FilterItem(i, query));
return PostFilterAndSort(items, parent, null, query);
}
private QueryResult<BaseItem> GetFavoriteAlbums(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => (i is MusicAlbum) && FilterItem(i, query));
return PostFilterAndSort(items, parent, null, query);
}
private QueryResult<BaseItem> GetMovieMovies(Folder parent, User user, InternalItemsQuery query) private QueryResult<BaseItem> GetMovieMovies(Folder parent, User user, InternalItemsQuery query)
{ {
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => (i is Movie) && FilterItem(i, query)); var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => (i is Movie) && FilterItem(i, query));
@ -617,54 +601,6 @@ namespace MediaBrowser.Controller.Entities
return GetResult(list, parent, query); return GetResult(list, parent, query);
} }
private async Task<QueryResult<BaseItem>> GetGameView(User user, Folder parent, InternalItemsQuery query)
{
if (query.Recursive)
{
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => FilterItem(i, query));
return PostFilterAndSort(items, parent, null, query);
}
var list = new List<BaseItem>();
list.Add(await GetUserView(SpecialFolder.LatestGames, "0", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.RecentlyPlayedGames, "1", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.GameFavorites, "2", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.GameSystems, "3", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.GameGenres, "4", parent).ConfigureAwait(false));
return GetResult(list, parent, query);
}
private QueryResult<BaseItem> GetLatestGames(Folder parent, User user, InternalItemsQuery query)
{
query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
query.SortOrder = SortOrder.Descending;
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query));
return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query);
}
private QueryResult<BaseItem> GetRecentlyPlayedGames(Folder parent, User user, InternalItemsQuery query)
{
query.IsPlayed = true;
query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName };
query.SortOrder = SortOrder.Descending;
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query));
return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query);
}
private QueryResult<BaseItem> GetFavoriteGames(Folder parent, User user, InternalItemsQuery query)
{
query.IsFavorite = true;
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is Game && FilterItem(i, query));
return PostFilterAndSort(items, parent, null, query);
}
private QueryResult<BaseItem> GetTvLatest(Folder parent, User user, InternalItemsQuery query) private QueryResult<BaseItem> GetTvLatest(Folder parent, User user, InternalItemsQuery query)
{ {
query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
@ -745,49 +681,6 @@ namespace MediaBrowser.Controller.Entities
return GetResult(items, queryParent, query); return GetResult(items, queryParent, query);
} }
private QueryResult<BaseItem> GetGameSystems(Folder parent, User user, InternalItemsQuery query)
{
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Games }, i => i is GameSystem && FilterItem(i, query));
return PostFilterAndSort(items, parent, null, query);
}
private async Task<QueryResult<BaseItem>> GetGameGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
{
var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Games },
i => i is Game && i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase));
return GetResult(items, queryParent, query);
}
private async Task<QueryResult<BaseItem>> GetGameGenres(Folder parent, User user, InternalItemsQuery query)
{
var tasks = GetRecursiveChildren(parent, user, new[] { CollectionType.Games })
.OfType<Game>()
.SelectMany(i => i.Genres)
.DistinctNames()
.Select(i =>
{
try
{
return _libraryManager.GetGameGenre(i);
}
catch
{
// Full exception logged at lower levels
_logger.Error("Error getting game genre");
return null;
}
})
.Where(i => i != null)
.Select(i => GetUserView(i.Name, SpecialFolder.GameGenre, i.SortName, parent));
var genres = await Task.WhenAll(tasks).ConfigureAwait(false);
return GetResult(genres, parent, query);
}
private QueryResult<BaseItem> GetResult<T>(QueryResult<T> result) private QueryResult<BaseItem> GetResult<T>(QueryResult<T> result)
where T : BaseItem where T : BaseItem
{ {
@ -1061,6 +954,11 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
if (request.GenreIds.Length > 0)
{
return false;
}
if (request.VideoTypes.Length > 0) if (request.VideoTypes.Length > 0)
{ {
return false; return false;
@ -1101,10 +999,15 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
if (request.MinIndexNumber.HasValue)
{
return false;
}
return true; return true;
} }
public static IEnumerable<BaseItem> FilterVirtualEpisodes( private static IEnumerable<BaseItem> FilterVirtualEpisodes(
IEnumerable<BaseItem> items, IEnumerable<BaseItem> items,
bool? isMissing, bool? isMissing,
bool? isVirtualUnaired, bool? isVirtualUnaired,
@ -1374,7 +1277,7 @@ namespace MediaBrowser.Controller.Entities
if (query.IsInBoxSet.HasValue) if (query.IsInBoxSet.HasValue)
{ {
var val = query.IsInBoxSet.Value; var val = query.IsInBoxSet.Value;
if (item.Parents.OfType<BoxSet>().Any() != val) if (item.GetParents().OfType<BoxSet>().Any() != val)
{ {
return false; return false;
} }
@ -1657,6 +1560,16 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
// Apply genre filter
if (query.GenreIds.Length > 0 && !query.GenreIds.Any(id =>
{
var genreItem = libraryManager.GetItemById(id);
return genreItem != null && item.Genres.Contains(genreItem.Name, StringComparer.OrdinalIgnoreCase);
}))
{
return false;
}
// Apply year filter // Apply year filter
if (query.Years.Length > 0) if (query.Years.Length > 0)
{ {
@ -1779,6 +1692,16 @@ namespace MediaBrowser.Controller.Entities
} }
} }
if (query.MinIndexNumber.HasValue)
{
var val = query.MinIndexNumber.Value;
if (!(item.IndexNumber.HasValue && item.IndexNumber.Value >= val))
{
return false;
}
}
return true; return true;
} }
@ -1789,12 +1712,12 @@ namespace MediaBrowser.Controller.Entities
return _libraryManager.RootFolder return _libraryManager.RootFolder
.Children .Children
.OfType<Folder>() .OfType<Folder>()
.Where(i => !UserView.IsExcludedFromGrouping(i)); .Where(UserView.IsEligibleForGrouping);
} }
return user.RootFolder return user.RootFolder
.GetChildren(user, true, true) .GetChildren(user, true)
.OfType<Folder>() .OfType<Folder>()
.Where(i => user.IsFolderGrouped(i.Id) && !UserView.IsExcludedFromGrouping(i)); .Where(i => user.IsFolderGrouped(i.Id) && UserView.IsEligibleForGrouping(i));
} }
private IEnumerable<Folder> GetMediaFolders(User user, IEnumerable<string> viewTypes) private IEnumerable<Folder> GetMediaFolders(User user, IEnumerable<string> viewTypes)

View File

@ -185,12 +185,6 @@ namespace MediaBrowser.Controller.Entities
public bool IsShortcut { get; set; } public bool IsShortcut { get; set; }
public string ShortcutPath { get; set; } public string ShortcutPath { get; set; }
/// <summary>
/// Gets or sets the tags.
/// </summary>
/// <value>The tags.</value>
public List<string> Tags { get; set; }
/// <summary> /// <summary>
/// Gets or sets the video bit rate. /// Gets or sets the video bit rate.
/// </summary> /// </summary>
@ -356,7 +350,7 @@ namespace MediaBrowser.Controller.Entities
// Must have a parent to have additional parts or alternate versions // Must have a parent to have additional parts or alternate versions
// In other words, it must be part of the Parent/Child tree // In other words, it must be part of the Parent/Child tree
// The additional parts won't have additional parts themselves // The additional parts won't have additional parts themselves
if (LocationType == LocationType.FileSystem && Parent != null) if (LocationType == LocationType.FileSystem && GetParent() != null)
{ {
if (!IsStacked) if (!IsStacked)
{ {

View File

@ -1,6 +1,8 @@
using MediaBrowser.Common; using MediaBrowser.Common;
using MediaBrowser.Model.System; using MediaBrowser.Model.System;
using System; using System;
using System.Collections.Generic;
using System.Net;
namespace MediaBrowser.Controller namespace MediaBrowser.Controller
{ {
@ -63,7 +65,7 @@ namespace MediaBrowser.Controller
/// Gets the local ip address. /// Gets the local ip address.
/// </summary> /// </summary>
/// <value>The local ip address.</value> /// <value>The local ip address.</value>
string LocalIpAddress { get; } List<IPAddress> LocalIpAddresses { get; }
/// <summary> /// <summary>
/// Gets the local API URL. /// Gets the local API URL.

View File

@ -337,7 +337,6 @@ namespace MediaBrowser.Controller.Library
string parentId, string parentId,
string viewType, string viewType,
string sortName, string sortName,
string uniqueId,
CancellationToken cancellationToken); CancellationToken cancellationToken);
/// <summary> /// <summary>
@ -391,13 +390,11 @@ namespace MediaBrowser.Controller.Library
/// <param name="parent">The parent.</param> /// <param name="parent">The parent.</param>
/// <param name="viewType">Type of the view.</param> /// <param name="viewType">Type of the view.</param>
/// <param name="sortName">Name of the sort.</param> /// <param name="sortName">Name of the sort.</param>
/// <param name="uniqueId">The unique identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;UserView&gt;.</returns> /// <returns>Task&lt;UserView&gt;.</returns>
Task<UserView> GetShadowView(BaseItem parent, Task<UserView> GetShadowView(BaseItem parent,
string viewType, string viewType,
string sortName, string sortName,
string uniqueId,
CancellationToken cancellationToken); CancellationToken cancellationToken);
/// <summary> /// <summary>
@ -543,5 +540,29 @@ namespace MediaBrowser.Controller.Library
/// <param name="imageIndex">Index of the image.</param> /// <param name="imageIndex">Index of the image.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
Task<ItemImageInfo> ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex); Task<ItemImageInfo> ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex);
/// <summary>
/// Gets the items.
/// </summary>
/// <param name="query">The query.</param>
/// <param name="parentIds">The parent ids.</param>
/// <returns>List&lt;BaseItem&gt;.</returns>
IEnumerable<BaseItem> GetItems(InternalItemsQuery query, IEnumerable<string> parentIds);
/// <summary>
/// Gets the items result.
/// </summary>
/// <param name="query">The query.</param>
/// <param name="parentIds">The parent ids.</param>
/// <returns>QueryResult&lt;BaseItem&gt;.</returns>
QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query, IEnumerable<string> parentIds);
/// <summary>
/// Ignores the file.
/// </summary>
/// <param name="file">The file.</param>
/// <param name="parent">The parent.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
bool IgnoreFile(FileSystemMetadata file, BaseItem parent);
} }
} }

View File

@ -155,7 +155,7 @@ namespace MediaBrowser.Controller.Library
// Not officially supported but in some cases we can handle it. // Not officially supported but in some cases we can handle it.
if (item == null) if (item == null)
{ {
item = parent.Parents.OfType<T>().FirstOrDefault(); item = parent.GetParents().OfType<T>().FirstOrDefault();
} }
return item != null; return item != null;

View File

@ -36,7 +36,6 @@ namespace MediaBrowser.Controller.LiveTv
public bool IsLive { get; set; } public bool IsLive { get; set; }
[IgnoreDataMember] [IgnoreDataMember]
public bool IsPremiere { get; set; } public bool IsPremiere { get; set; }
public ProgramAudio? Audio { get; set; }
/// <summary> /// <summary>
/// Gets the user data key. /// Gets the user data key.
@ -106,9 +105,9 @@ namespace MediaBrowser.Controller.LiveTv
} }
} }
protected override bool GetBlockUnratedValue(UserPolicy config) public override UnratedItem GetBlockUnratedType()
{ {
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram); return UnratedItem.LiveTvProgram;
} }
protected override string GetInternalMetadataPath(string basePath) protected override string GetInternalMetadataPath(string basePath)
@ -140,5 +139,10 @@ namespace MediaBrowser.Controller.LiveTv
return list; return list;
} }
public override bool IsVisibleStandalone(User user)
{
return IsVisible(user);
}
} }
} }

View File

@ -22,9 +22,9 @@ namespace MediaBrowser.Controller.LiveTv
return GetClientTypeName() + "-" + Name; return GetClientTypeName() + "-" + Name;
} }
protected override bool GetBlockUnratedValue(UserPolicy config) public override UnratedItem GetBlockUnratedType()
{ {
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvChannel); return UnratedItem.LiveTvChannel;
} }
/// <summary> /// <summary>

View File

@ -40,10 +40,11 @@ namespace MediaBrowser.Controller.LiveTv
} }
/// <summary> /// <summary>
/// Gets or sets the type of the channel. /// Gets or sets the name.
/// </summary> /// </summary>
/// <value>The type of the channel.</value> /// <value>The name.</value>
public ChannelType ChannelType { get; set; } [IgnoreDataMember]
public string ServiceName { get; set; }
/// <summary> /// <summary>
/// The start date of the program, in UTC. /// The start date of the program, in UTC.
@ -51,12 +52,6 @@ namespace MediaBrowser.Controller.LiveTv
[IgnoreDataMember] [IgnoreDataMember]
public DateTime StartDate { get; set; } public DateTime StartDate { get; set; }
/// <summary>
/// Gets or sets the audio.
/// </summary>
/// <value>The audio.</value>
public ProgramAudio? Audio { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether this instance is repeat. /// Gets or sets a value indicating whether this instance is repeat.
/// </summary> /// </summary>
@ -71,12 +66,6 @@ namespace MediaBrowser.Controller.LiveTv
[IgnoreDataMember] [IgnoreDataMember]
public string EpisodeTitle { get; set; } public string EpisodeTitle { get; set; }
/// <summary>
/// Gets or sets the name of the service.
/// </summary>
/// <value>The name of the service.</value>
public string ServiceName { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether this instance is movie. /// Gets or sets a value indicating whether this instance is movie.
/// </summary> /// </summary>
@ -153,14 +142,14 @@ namespace MediaBrowser.Controller.LiveTv
} }
} }
[IgnoreDataMember] //[IgnoreDataMember]
public override string MediaType //public override string MediaType
{ //{
get // get
{ // {
return ChannelType == ChannelType.TV ? Model.Entities.MediaType.Video : Model.Entities.MediaType.Audio; // return ChannelType == ChannelType.TV ? Model.Entities.MediaType.Video : Model.Entities.MediaType.Audio;
} // }
} //}
[IgnoreDataMember] [IgnoreDataMember]
public bool IsAiring public bool IsAiring
@ -189,9 +178,9 @@ namespace MediaBrowser.Controller.LiveTv
return "Program"; return "Program";
} }
protected override bool GetBlockUnratedValue(UserPolicy config) public override UnratedItem GetBlockUnratedType()
{ {
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram); return UnratedItem.LiveTvProgram;
} }
protected override string GetInternalMetadataPath(string basePath) protected override string GetInternalMetadataPath(string basePath)
@ -236,5 +225,14 @@ namespace MediaBrowser.Controller.LiveTv
return base.SupportsPeople; return base.SupportsPeople;
} }
} }
[IgnoreDataMember]
public override bool SupportsAncestors
{
get
{
return false;
}
}
} }
} }

View File

@ -36,7 +36,6 @@ namespace MediaBrowser.Controller.LiveTv
public bool IsLive { get; set; } public bool IsLive { get; set; }
[IgnoreDataMember] [IgnoreDataMember]
public bool IsPremiere { get; set; } public bool IsPremiere { get; set; }
public ProgramAudio? Audio { get; set; }
/// <summary> /// <summary>
/// Gets the user data key. /// Gets the user data key.
@ -121,9 +120,9 @@ namespace MediaBrowser.Controller.LiveTv
} }
} }
protected override bool GetBlockUnratedValue(UserPolicy config) public override UnratedItem GetBlockUnratedType()
{ {
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram); return UnratedItem.LiveTvProgram;
} }
protected override string GetInternalMetadataPath(string basePath) protected override string GetInternalMetadataPath(string basePath)
@ -155,5 +154,10 @@ namespace MediaBrowser.Controller.LiveTv
return list; return list;
} }
public override bool IsVisibleStandalone(User user)
{
return IsVisible(user);
}
} }
} }

View File

@ -1,4 +1,5 @@
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Users; using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.LiveTv namespace MediaBrowser.Controller.LiveTv
@ -11,6 +12,11 @@ namespace MediaBrowser.Controller.LiveTv
return false; return false;
} }
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.LiveTvProgram;
}
public override bool SupportsLocalMetadata public override bool SupportsLocalMetadata
{ {
get get

View File

@ -51,6 +51,9 @@
<Reference Include="Interfaces.IO"> <Reference Include="Interfaces.IO">
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath> <HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
</Reference> </Reference>
<Reference Include="MoreLinq">
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
</Reference>
<Reference Include="Patterns.Logging"> <Reference Include="Patterns.Logging">
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath> <HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
</Reference> </Reference>
@ -65,9 +68,6 @@
<Reference Include="ServiceStack.Interfaces"> <Reference Include="ServiceStack.Interfaces">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath> <HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
</Reference> </Reference>
<Reference Include="MoreLinq">
<HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\SharedVersion.cs"> <Compile Include="..\SharedVersion.cs">
@ -162,6 +162,7 @@
<Compile Include="Entities\IHasThemeMedia.cs" /> <Compile Include="Entities\IHasThemeMedia.cs" />
<Compile Include="Entities\IHasTrailers.cs" /> <Compile Include="Entities\IHasTrailers.cs" />
<Compile Include="Entities\IHasUserData.cs" /> <Compile Include="Entities\IHasUserData.cs" />
<Compile Include="Entities\IHiddenFromDisplay.cs" />
<Compile Include="Entities\IItemByName.cs" /> <Compile Include="Entities\IItemByName.cs" />
<Compile Include="Entities\ILibraryItem.cs" /> <Compile Include="Entities\ILibraryItem.cs" />
<Compile Include="Entities\ImageSourceInfo.cs" /> <Compile Include="Entities\ImageSourceInfo.cs" />

View File

@ -35,9 +35,10 @@ namespace MediaBrowser.Controller.MediaEncoding
/// Extracts the audio image. /// Extracts the audio image.
/// </summary> /// </summary>
/// <param name="path">The path.</param> /// <param name="path">The path.</param>
/// <param name="imageStreamIndex">Index of the image stream.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns> /// <returns>Task{Stream}.</returns>
Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken); Task<Stream> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Extracts the video image. /// Extracts the video image.

View File

@ -15,7 +15,6 @@ namespace MediaBrowser.Controller.MediaEncoding
public IIsoMount MountedIso { get; set; } public IIsoMount MountedIso { get; set; }
public VideoType VideoType { get; set; } public VideoType VideoType { get; set; }
public List<string> PlayableStreamFileNames { get; set; } public List<string> PlayableStreamFileNames { get; set; }
public bool ExtractKeyFrameInterval { get; set; }
public MediaInfoRequest() public MediaInfoRequest()
{ {

View File

@ -28,12 +28,6 @@ namespace MediaBrowser.Controller.Net
/// the ssl certificate localtion on the file system.</param> /// the ssl certificate localtion on the file system.</param>
void StartServer(IEnumerable<string> urlPrefixes, string certificatePath); void StartServer(IEnumerable<string> urlPrefixes, string certificatePath);
/// <summary>
/// Gets the local end points.
/// </summary>
/// <value>The local end points.</value>
IEnumerable<string> LocalEndPoints { get; }
/// <summary> /// <summary>
/// Stops this instance. /// Stops this instance.
/// </summary> /// </summary>

View File

@ -176,6 +176,20 @@ namespace MediaBrowser.Controller.Persistence
/// <param name="query">The query.</param> /// <param name="query">The query.</param>
/// <returns>QueryResult&lt;Tuple&lt;Guid, System.String&gt;&gt;.</returns> /// <returns>QueryResult&lt;Tuple&lt;Guid, System.String&gt;&gt;.</returns>
QueryResult<Tuple<Guid, string>> GetItemIdsWithPath(InternalItemsQuery query); QueryResult<Tuple<Guid, string>> GetItemIdsWithPath(InternalItemsQuery query);
/// <summary>
/// Gets the item list.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>List&lt;BaseItem&gt;.</returns>
IEnumerable<BaseItem> GetItemList(InternalItemsQuery query);
/// <summary>
/// Updates the inherited values.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task UpdateInheritedValues(CancellationToken cancellationToken);
} }
} }

View File

@ -144,6 +144,7 @@ namespace MediaBrowser.Controller.Playlists
public string PlaylistMediaType { get; set; } public string PlaylistMediaType { get; set; }
[IgnoreDataMember]
public override string MediaType public override string MediaType
{ {
get get

View File

@ -10,24 +10,6 @@ namespace MediaBrowser.Controller.Providers
/// <value>The item identifier.</value> /// <value>The item identifier.</value>
public Guid ItemId { get; set; } public Guid ItemId { get; set; }
/// <summary>
/// Gets or sets the name of the item.
/// </summary>
/// <value>The name of the item.</value>
public string ItemName { get; set; }
/// <summary>
/// Gets or sets the type of the item.
/// </summary>
/// <value>The type of the item.</value>
public string ItemType { get; set; }
/// <summary>
/// Gets or sets the name of the series.
/// </summary>
/// <value>The name of the series.</value>
public string SeriesName { get; set; }
/// <summary> /// <summary>
/// Gets or sets the date last metadata refresh. /// Gets or sets the date last metadata refresh.
/// </summary> /// </summary>
@ -40,22 +22,8 @@ namespace MediaBrowser.Controller.Providers
/// <value>The date last images refresh.</value> /// <value>The date last images refresh.</value>
public DateTime? DateLastImagesRefresh { get; set; } public DateTime? DateLastImagesRefresh { get; set; }
/// <summary>
/// Gets or sets the last result error message.
/// </summary>
/// <value>The last result error message.</value>
public string LastErrorMessage { get; set; }
public DateTime? ItemDateModified { get; set; } public DateTime? ItemDateModified { get; set; }
public void AddStatus(string errorMessage)
{
if (string.IsNullOrEmpty(LastErrorMessage))
{
LastErrorMessage = errorMessage;
}
}
public bool IsDirty { get; private set; } public bool IsDirty { get; private set; }
public void SetDateLastMetadataRefresh(DateTime? date) public void SetDateLastMetadataRefresh(DateTime? date)

View File

@ -1,4 +1,5 @@
using MediaBrowser.Controller.Library; using CommonIO;
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Resolvers namespace MediaBrowser.Controller.Resolvers
{ {
@ -7,6 +8,6 @@ namespace MediaBrowser.Controller.Resolvers
/// </summary> /// </summary>
public interface IResolverIgnoreRule public interface IResolverIgnoreRule
{ {
bool ShouldIgnore(ItemResolveArgs args); bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent);
} }
} }

View File

@ -2,6 +2,6 @@
<packages> <packages>
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" /> <package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
<package id="Interfaces.IO" version="1.0.0.5" targetFramework="net45" /> <package id="Interfaces.IO" version="1.0.0.5" targetFramework="net45" />
<package id="morelinq" version="1.1.1" targetFramework="net45" /> <package id="morelinq" version="1.4.0" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" /> <package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
</packages> </packages>

View File

@ -26,6 +26,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
private readonly ILocalizationManager _localization; private readonly ILocalizationManager _localization;
private readonly IChannelManager _channelManager; private readonly IChannelManager _channelManager;
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
private readonly IUserViewManager _userViewManager;
public ContentDirectory(IDlnaManager dlna, public ContentDirectory(IDlnaManager dlna,
IUserDataManager userDataManager, IUserDataManager userDataManager,
@ -34,7 +35,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
IServerConfigurationManager config, IServerConfigurationManager config,
IUserManager userManager, IUserManager userManager,
ILogger logger, ILogger logger,
IHttpClient httpClient, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager) IHttpClient httpClient, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager)
: base(logger, httpClient) : base(logger, httpClient)
{ {
_dlna = dlna; _dlna = dlna;
@ -46,6 +47,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
_localization = localization; _localization = localization;
_channelManager = channelManager; _channelManager = channelManager;
_mediaSourceManager = mediaSourceManager; _mediaSourceManager = mediaSourceManager;
_userViewManager = userViewManager;
} }
private int SystemUpdateId private int SystemUpdateId
@ -86,7 +88,8 @@ namespace MediaBrowser.Dlna.ContentDirectory
_config, _config,
_localization, _localization,
_channelManager, _channelManager,
_mediaSourceManager) _mediaSourceManager,
_userViewManager)
.ProcessControlRequest(request); .ProcessControlRequest(request);
} }

View File

@ -24,6 +24,7 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml; using System.Xml;
using MediaBrowser.Model.Library;
namespace MediaBrowser.Dlna.ContentDirectory namespace MediaBrowser.Dlna.ContentDirectory
{ {
@ -34,6 +35,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
private readonly IUserDataManager _userDataManager; private readonly IUserDataManager _userDataManager;
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
private readonly User _user; private readonly User _user;
private readonly IUserViewManager _userViewManager;
private const string NS_DC = "http://purl.org/dc/elements/1.1/"; private const string NS_DC = "http://purl.org/dc/elements/1.1/";
private const string NS_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"; private const string NS_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
@ -47,7 +49,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
private readonly DeviceProfile _profile; private readonly DeviceProfile _profile;
public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, string accessToken, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager) public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, string accessToken, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager)
: base(config, logger) : base(config, logger)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;
@ -55,6 +57,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
_user = user; _user = user;
_systemUpdateId = systemUpdateId; _systemUpdateId = systemUpdateId;
_channelManager = channelManager; _channelManager = channelManager;
_userViewManager = userViewManager;
_profile = profile; _profile = profile;
_config = config; _config = config;
@ -450,7 +453,22 @@ namespace MediaBrowser.Dlna.ContentDirectory
sortOrders.Add(ItemSortBy.SortName); sortOrders.Add(ItemSortBy.SortName);
} }
var queryResult = await folder.GetItems(new InternalItemsQuery QueryResult<BaseItem> queryResult;
if (folder is UserRootFolder)
{
var views = await _userViewManager.GetUserViews(new UserViewQuery { UserId = user.Id.ToString("N"), PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Music } }, CancellationToken.None)
.ConfigureAwait(false);
queryResult = new QueryResult<BaseItem>
{
Items = views.Cast<BaseItem>().ToArray()
};
queryResult.TotalRecordCount = queryResult.Items.Length;
}
else
{
queryResult = await folder.GetItems(new InternalItemsQuery
{ {
Limit = limit, Limit = limit,
StartIndex = startIndex, StartIndex = startIndex,
@ -460,6 +478,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
Filter = FilterUnsupportedContent Filter = FilterUnsupportedContent
}).ConfigureAwait(false); }).ConfigureAwait(false);
}
var options = _config.GetDlnaConfiguration(); var options = _config.GetDlnaConfiguration();
@ -481,23 +500,17 @@ namespace MediaBrowser.Dlna.ContentDirectory
private QueryResult<ServerItem> GetItemsFromPerson(Person person, User user, int? startIndex, int? limit) private QueryResult<ServerItem> GetItemsFromPerson(Person person, User user, int? startIndex, int? limit)
{ {
var itemsWithPerson = _libraryManager.GetItems(new InternalItemsQuery var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
{ {
Person = person.Name Person = person.Name,
IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name, typeof(ChannelVideoItem).Name },
SortBy = new[] { ItemSortBy.SortName },
Limit = limit,
StartIndex = startIndex
}).Items; }, new string[] { });
var items = itemsWithPerson var serverItems = itemsResult.Items.Select(i => new ServerItem
.Where(i => i is Movie || i is Series || i is IChannelItem)
.Where(i => i.IsVisibleStandalone(user))
.ToList();
items = _libraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending)
.Skip(startIndex ?? 0)
.Take(limit ?? int.MaxValue)
.ToList();
var serverItems = items.Select(i => new ServerItem
{ {
Item = i, Item = i,
StubType = null StubType = null
@ -506,7 +519,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
return new QueryResult<ServerItem> return new QueryResult<ServerItem>
{ {
TotalRecordCount = serverItems.Length, TotalRecordCount = itemsResult.TotalRecordCount,
Items = serverItems Items = serverItems
}; };
} }

View File

@ -966,7 +966,7 @@ namespace MediaBrowser.Dlna.Didl
} }
} }
item = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Primary)); item = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Primary));
if (item != null) if (item != null)
{ {

View File

@ -148,13 +148,20 @@ namespace MediaBrowser.Dlna.Main
private void RegisterServerEndpoints() private void RegisterServerEndpoints()
{ {
foreach (var address in _network.GetLocalIpAddresses()) foreach (var address in _appHost.LocalIpAddresses)
{ {
var guid = address.GetMD5(); //if (IPAddress.IsLoopback(address))
//{
// // Should we allow this?
// continue;
//}
var addressString = address.ToString();
var guid = addressString.GetMD5();
var descriptorURI = "/dlna/" + guid.ToString("N") + "/description.xml"; var descriptorURI = "/dlna/" + guid.ToString("N") + "/description.xml";
var uri = new Uri(_appHost.GetLocalApiUrl(address) + descriptorURI); var uri = new Uri(_appHost.GetLocalApiUrl(addressString) + descriptorURI);
var services = new List<string> var services = new List<string>
{ {
@ -166,7 +173,7 @@ namespace MediaBrowser.Dlna.Main
"uuid:" + guid.ToString("N") "uuid:" + guid.ToString("N")
}; };
_ssdpHandler.RegisterNotification(guid, uri, IPAddress.Parse(address), services); _ssdpHandler.RegisterNotification(guid, uri, address, services);
_registeredServerIds.Add(guid.ToString("N")); _registeredServerIds.Add(guid.ToString("N"));
} }

View File

@ -44,6 +44,9 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath> <HintPath>..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll</HintPath>
</Reference> </Reference>
<Reference Include="MoreLinq">
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
</Reference>
<Reference Include="Patterns.Logging"> <Reference Include="Patterns.Logging">
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath> <HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
</Reference> </Reference>

View File

@ -92,7 +92,7 @@ namespace MediaBrowser.Dlna.Profiles
{ {
Container = "ts", Container = "ts",
VideoCodec = "h264", VideoCodec = "h264",
AudioCodec = "mp3", AudioCodec = "ac3,aac,mp3",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
}, },
new TranscodingProfile new TranscodingProfile

View File

@ -48,7 +48,7 @@
</DirectPlayProfiles> </DirectPlayProfiles>
<TranscodingProfiles> <TranscodingProfiles>
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" /> <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" /> <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3,aac,mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" /> <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
</TranscodingProfiles> </TranscodingProfiles>
<ContainerProfiles> <ContainerProfiles>

View File

@ -11,6 +11,8 @@ using System.Net.NetworkInformation;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Common.Net;
using MoreLinq;
namespace MediaBrowser.Dlna.Ssdp namespace MediaBrowser.Dlna.Ssdp
{ {
@ -26,14 +28,21 @@ namespace MediaBrowser.Dlna.Ssdp
public event EventHandler<SsdpMessageEventArgs> DeviceDiscovered; public event EventHandler<SsdpMessageEventArgs> DeviceDiscovered;
public event EventHandler<SsdpMessageEventArgs> DeviceLeft; public event EventHandler<SsdpMessageEventArgs> DeviceLeft;
private readonly INetworkManager _networkManager;
public DeviceDiscovery(ILogger logger, IServerConfigurationManager config, IServerApplicationHost appHost) public DeviceDiscovery(ILogger logger, IServerConfigurationManager config, IServerApplicationHost appHost, INetworkManager networkManager)
{ {
_tokenSource = new CancellationTokenSource(); _tokenSource = new CancellationTokenSource();
_logger = logger; _logger = logger;
_config = config; _config = config;
_appHost = appHost; _appHost = appHost;
_networkManager = networkManager;
}
private List<IPAddress> GetLocalIpAddresses()
{
return _networkManager.GetLocalIpAddresses().ToList();
} }
public void Start(SsdpHandler ssdpHandler) public void Start(SsdpHandler ssdpHandler)
@ -41,24 +50,7 @@ namespace MediaBrowser.Dlna.Ssdp
_ssdpHandler = ssdpHandler; _ssdpHandler = ssdpHandler;
_ssdpHandler.MessageReceived += _ssdpHandler_MessageReceived; _ssdpHandler.MessageReceived += _ssdpHandler_MessageReceived;
foreach (var network in GetNetworkInterfaces()) foreach (var localIp in GetLocalIpAddresses())
{
_logger.Debug("Found interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus);
if (!network.SupportsMulticast || OperationalStatus.Up != network.OperationalStatus || !network.GetIPProperties().MulticastAddresses.Any())
continue;
var properties = network.GetIPProperties();
var ipV4 = properties.GetIPv4Properties();
if (null == ipV4)
continue;
var localIps = properties.UnicastAddresses
.Where(i => i.Address.AddressFamily == AddressFamily.InterNetwork)
.Select(i => i.Address)
.ToList();
foreach (var localIp in localIps)
{ {
try try
{ {
@ -70,7 +62,6 @@ namespace MediaBrowser.Dlna.Ssdp
} }
} }
} }
}
void _ssdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e) void _ssdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e)
{ {
@ -89,8 +80,11 @@ namespace MediaBrowser.Dlna.Ssdp
{ {
if (e.LocalEndPoint == null) if (e.LocalEndPoint == null)
{ {
var ip = _appHost.LocalIpAddress; var ip = _appHost.LocalIpAddresses.FirstOrDefault(i => !IPAddress.IsLoopback(i));
e.LocalEndPoint = new IPEndPoint(IPAddress.Parse(ip), 0); if (ip != null)
{
e.LocalEndPoint = new IPEndPoint(ip, 0);
}
} }
if (e.LocalEndPoint != null) if (e.LocalEndPoint != null)
@ -107,30 +101,18 @@ namespace MediaBrowser.Dlna.Ssdp
} }
} }
private IEnumerable<NetworkInterface> GetNetworkInterfaces()
{
try
{
return NetworkInterface.GetAllNetworkInterfaces();
}
catch (Exception ex)
{
_logger.ErrorException("Error in GetAllNetworkInterfaces", ex);
return new List<NetworkInterface>();
}
}
private void CreateListener(IPAddress localIp) private void CreateListener(IPAddress localIp)
{ {
Task.Factory.StartNew(async (o) => Task.Factory.StartNew(async (o) =>
{ {
try try
{ {
_logger.Info("Creating SSDP listener on {0}", localIp);
var endPoint = new IPEndPoint(localIp, 1900); var endPoint = new IPEndPoint(localIp, 1900);
var socket = GetMulticastSocket(localIp, endPoint); var socket = GetMulticastSocket(localIp, endPoint);
_logger.Info("Creating SSDP listener on {0}", localIp);
var receiveBuffer = new byte[64000]; var receiveBuffer = new byte[64000];
CreateNotifier(localIp); CreateNotifier(localIp);

View File

@ -15,6 +15,7 @@ using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Win32;
namespace MediaBrowser.Dlna.Ssdp namespace MediaBrowser.Dlna.Ssdp
{ {
@ -112,7 +113,9 @@ namespace MediaBrowser.Dlna.Ssdp
{ {
get get
{ {
return _devices.Values.SelectMany(i => i).ToList(); var devices = _devices.Values.ToList();
return devices.SelectMany(i => i).ToList();
} }
} }
@ -121,6 +124,15 @@ namespace MediaBrowser.Dlna.Ssdp
RestartSocketListener(); RestartSocketListener();
ReloadAliveNotifier(); ReloadAliveNotifier();
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
}
void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
if (e.Mode == PowerModes.Resume)
{
NotifyAll();
}
} }
public void SendSearchMessage(EndPoint localIp) public void SendSearchMessage(EndPoint localIp)
@ -433,6 +445,7 @@ namespace MediaBrowser.Dlna.Ssdp
public void Dispose() public void Dispose()
{ {
_config.NamedConfigurationUpdated -= _config_ConfigurationUpdated; _config.NamedConfigurationUpdated -= _config_ConfigurationUpdated;
SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
_isDisposed = true; _isDisposed = true;
while (_messageQueue.Count != 0) while (_messageQueue.Count != 0)

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="CommonIO" version="1.0.0.5" targetFramework="net45" /> <package id="CommonIO" version="1.0.0.5" targetFramework="net45" />
<package id="morelinq" version="1.4.0" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" /> <package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
</packages> </packages>

View File

@ -79,14 +79,11 @@
<Compile Include="Providers\SeriesXmlProvider.cs" /> <Compile Include="Providers\SeriesXmlProvider.cs" />
<Compile Include="Providers\VideoXmlProvider.cs" /> <Compile Include="Providers\VideoXmlProvider.cs" />
<Compile Include="Savers\BoxSetXmlSaver.cs" /> <Compile Include="Savers\BoxSetXmlSaver.cs" />
<Compile Include="Savers\EpisodeXmlSaver.cs" />
<Compile Include="Savers\FolderXmlSaver.cs" /> <Compile Include="Savers\FolderXmlSaver.cs" />
<Compile Include="Savers\GameSystemXmlSaver.cs" /> <Compile Include="Savers\GameSystemXmlSaver.cs" />
<Compile Include="Savers\GameXmlSaver.cs" /> <Compile Include="Savers\GameXmlSaver.cs" />
<Compile Include="Savers\MovieXmlSaver.cs" />
<Compile Include="Savers\PersonXmlSaver.cs" /> <Compile Include="Savers\PersonXmlSaver.cs" />
<Compile Include="Savers\PlaylistXmlSaver.cs" /> <Compile Include="Savers\PlaylistXmlSaver.cs" />
<Compile Include="Savers\SeriesXmlSaver.cs" />
<Compile Include="Savers\XmlSaverHelpers.cs" /> <Compile Include="Savers\XmlSaverHelpers.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -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;
}
/// <summary>
/// Determines whether [is enabled for] [the specified item].
/// </summary>
/// <param name="item">The item.</param>
/// <param name="updateType">Type of the update.</param>
/// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
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; }
}
/// <summary>
/// Saves the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public void Save(IHasMetadata item, CancellationToken cancellationToken)
{
var episode = (Episode)item;
var builder = new StringBuilder();
builder.Append("<Item>");
if (!string.IsNullOrEmpty(item.Name))
{
builder.Append("<EpisodeName>" + SecurityElement.Escape(episode.Name) + "</EpisodeName>");
}
if (episode.IndexNumber.HasValue)
{
builder.Append("<EpisodeNumber>" + SecurityElement.Escape(episode.IndexNumber.Value.ToString(_usCulture)) + "</EpisodeNumber>");
}
if (episode.IndexNumberEnd.HasValue)
{
builder.Append("<EpisodeNumberEnd>" + SecurityElement.Escape(episode.IndexNumberEnd.Value.ToString(_usCulture)) + "</EpisodeNumberEnd>");
}
if (episode.AirsAfterSeasonNumber.HasValue)
{
builder.Append("<airsafter_season>" + SecurityElement.Escape(episode.AirsAfterSeasonNumber.Value.ToString(_usCulture)) + "</airsafter_season>");
}
if (episode.AirsBeforeEpisodeNumber.HasValue)
{
builder.Append("<airsbefore_episode>" + SecurityElement.Escape(episode.AirsBeforeEpisodeNumber.Value.ToString(_usCulture)) + "</airsbefore_episode>");
}
if (episode.AirsBeforeSeasonNumber.HasValue)
{
builder.Append("<airsbefore_season>" + SecurityElement.Escape(episode.AirsBeforeSeasonNumber.Value.ToString(_usCulture)) + "</airsbefore_season>");
}
if (episode.ParentIndexNumber.HasValue)
{
builder.Append("<SeasonNumber>" + SecurityElement.Escape(episode.ParentIndexNumber.Value.ToString(_usCulture)) + "</SeasonNumber>");
}
if (episode.AbsoluteEpisodeNumber.HasValue)
{
builder.Append("<absolute_number>" + SecurityElement.Escape(episode.AbsoluteEpisodeNumber.Value.ToString(_usCulture)) + "</absolute_number>");
}
if (episode.DvdEpisodeNumber.HasValue)
{
builder.Append("<DVD_episodenumber>" + SecurityElement.Escape(episode.DvdEpisodeNumber.Value.ToString(_usCulture)) + "</DVD_episodenumber>");
}
if (episode.DvdSeasonNumber.HasValue)
{
builder.Append("<DVD_season>" + SecurityElement.Escape(episode.DvdSeasonNumber.Value.ToString(_usCulture)) + "</DVD_season>");
}
if (episode.PremiereDate.HasValue)
{
builder.Append("<FirstAired>" + SecurityElement.Escape(episode.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + "</FirstAired>");
}
XmlSaverHelpers.AddCommonNodes(episode, _libraryManager, builder);
XmlSaverHelpers.AddMediaInfo(episode, builder, _itemRepository);
builder.Append("</Item>");
var xmlFilePath = GetSavePath(item);
XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>
{
"FirstAired",
"SeasonNumber",
"EpisodeNumber",
"EpisodeName",
"EpisodeNumberEnd",
"airsafter_season",
"airsbefore_episode",
"airsbefore_season",
"DVD_episodenumber",
"DVD_season",
"absolute_number"
}, _config, _fileSystem);
}
/// <summary>
/// Gets the save path.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
public string GetSavePath(IHasMetadata item)
{
var filename = Path.ChangeExtension(Path.GetFileName(item.Path), ".xml");
return Path.Combine(Path.GetDirectoryName(item.Path), "metadata", filename);
}
}
}

View File

@ -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
{
/// <summary>
/// Saves movie.xml for movies, trailers and music videos
/// </summary>
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; }
}
/// <summary>
/// Determines whether [is enabled for] [the specified item].
/// </summary>
/// <param name="item">The item.</param>
/// <param name="updateType">Type of the update.</param>
/// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
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;
}
/// <summary>
/// Saves the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public void Save(IHasMetadata item, CancellationToken cancellationToken)
{
var video = (Video)item;
var builder = new StringBuilder();
builder.Append("<Title>");
XmlSaverHelpers.AddCommonNodes(video, _libraryManager, builder);
var musicVideo = item as MusicVideo;
if (musicVideo != null)
{
if (musicVideo.Artists.Count > 0)
{
builder.Append("<Artist>" + SecurityElement.Escape(string.Join(";", musicVideo.Artists.ToArray())) + "</Artist>");
}
if (!string.IsNullOrEmpty(musicVideo.Album))
{
builder.Append("<Album>" + SecurityElement.Escape(musicVideo.Album) + "</Album>");
}
}
var movie = item as Movie;
if (movie != null)
{
if (!string.IsNullOrEmpty(movie.TmdbCollectionName))
{
builder.Append("<TmdbCollectionName>" + SecurityElement.Escape(movie.TmdbCollectionName) + "</TmdbCollectionName>");
}
}
XmlSaverHelpers.AddMediaInfo(video, builder, _itemRepository);
builder.Append("</Title>");
var xmlFilePath = GetSavePath(item);
XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>
{
// 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");
}
}
}

View File

@ -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;
}
}
/// <summary>
/// Determines whether [is enabled for] [the specified item].
/// </summary>
/// <param name="item">The item.</param>
/// <param name="updateType">Type of the update.</param>
/// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
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");
/// <summary>
/// Saves the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public void Save(IHasMetadata item, CancellationToken cancellationToken)
{
var series = (Series)item;
var builder = new StringBuilder();
builder.Append("<Series>");
var tvdb = item.GetProviderId(MetadataProviders.Tvdb);
if (!string.IsNullOrEmpty(tvdb))
{
builder.Append("<id>" + SecurityElement.Escape(tvdb) + "</id>");
}
if (series.Status.HasValue)
{
builder.Append("<Status>" + SecurityElement.Escape(series.Status.Value.ToString()) + "</Status>");
}
if (series.Studios.Count > 0)
{
builder.Append("<Network>" + SecurityElement.Escape(series.Studios[0]) + "</Network>");
}
if (!string.IsNullOrEmpty(series.AirTime))
{
builder.Append("<Airs_Time>" + SecurityElement.Escape(series.AirTime) + "</Airs_Time>");
}
if (series.AirDays != null)
{
if (series.AirDays.Count == 7)
{
builder.Append("<Airs_DayOfWeek>" + SecurityElement.Escape("Daily") + "</Airs_DayOfWeek>");
}
else if (series.AirDays.Count > 0)
{
builder.Append("<Airs_DayOfWeek>" + SecurityElement.Escape(series.AirDays[0].ToString()) + "</Airs_DayOfWeek>");
}
}
if (series.PremiereDate.HasValue)
{
builder.Append("<FirstAired>" + SecurityElement.Escape(series.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + "</FirstAired>");
}
if (series.AnimeSeriesIndex.HasValue)
{
builder.Append("<AnimeSeriesIndex>" + SecurityElement.Escape(series.AnimeSeriesIndex.Value.ToString(UsCulture)) + "</AnimeSeriesIndex>");
}
XmlSaverHelpers.AddCommonNodes(series, _libraryManager, builder);
builder.Append("</Series>");
var xmlFilePath = GetSavePath(item);
XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>
{
"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);
}
/// <summary>
/// Gets the save path.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
public string GetSavePath(IHasMetadata item)
{
return Path.Combine(item.Path, "series.xml");
}
}
}

View File

@ -505,7 +505,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
{ {
return "libx264"; return "libx264";
} }
if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase)) if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase))
{ {
return "libx265"; return "libx265";
} }

View File

@ -258,17 +258,17 @@ namespace MediaBrowser.MediaEncoding.Encoder
var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol);
//var videoStream = mediaInfo.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); var videoStream = mediaInfo.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
//if (videoStream != null) if (videoStream != null)
//{ {
// var isInterlaced = await DetectInterlaced(mediaInfo, videoStream, inputPath, probeSizeArgument).ConfigureAwait(false); var isInterlaced = await DetectInterlaced(mediaInfo, videoStream, inputPath, probeSizeArgument).ConfigureAwait(false);
// if (isInterlaced) if (isInterlaced)
// { {
// videoStream.IsInterlaced = true; videoStream.IsInterlaced = true;
// } }
//} }
return mediaInfo; return mediaInfo;
} }
@ -292,9 +292,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
return false; return false;
} }
// If the video codec is not some form of mpeg, then take a shortcut and limit this to containers that are likely to have interlaced content
if ((videoStream.Codec ?? string.Empty).IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) == -1)
{
var formats = (video.Container ?? string.Empty).Split(',').ToList(); var formats = (video.Container ?? string.Empty).Split(',').ToList();
// Take a shortcut and limit this to containers that are likely to have interlaced content
if (!formats.Contains("vob", StringComparer.OrdinalIgnoreCase) && if (!formats.Contains("vob", StringComparer.OrdinalIgnoreCase) &&
!formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) && !formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) &&
!formats.Contains("ts", StringComparer.OrdinalIgnoreCase) && !formats.Contains("ts", StringComparer.OrdinalIgnoreCase) &&
@ -303,6 +305,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
{ {
return false; return false;
} }
}
var args = "{0} -i {1} -map 0:v:{2} -filter:v idet -frames:v 500 -an -f null /dev/null"; var args = "{0} -i {1} -map 0:v:{2} -filter:v idet -frames:v 500 -an -f null /dev/null";
@ -469,18 +472,18 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// </summary> /// </summary>
protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
public Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken) public Task<Stream> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken)
{ {
return ExtractImage(new[] { path }, MediaProtocol.File, true, null, null, cancellationToken); return ExtractImage(new[] { path }, imageStreamIndex, MediaProtocol.File, true, null, null, cancellationToken);
} }
public Task<Stream> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, public Task<Stream> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat,
TimeSpan? offset, CancellationToken cancellationToken) TimeSpan? offset, CancellationToken cancellationToken)
{ {
return ExtractImage(inputFiles, protocol, false, threedFormat, offset, cancellationToken); return ExtractImage(inputFiles, null, protocol, false, threedFormat, offset, cancellationToken);
} }
private async Task<Stream> ExtractImage(string[] inputFiles, MediaProtocol protocol, bool isAudio, private async Task<Stream> ExtractImage(string[] inputFiles, int? imageStreamIndex, MediaProtocol protocol, bool isAudio,
Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken)
{ {
var resourcePool = isAudio ? _audioImageResourcePool : _videoImageResourcePool; var resourcePool = isAudio ? _audioImageResourcePool : _videoImageResourcePool;
@ -491,7 +494,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
{ {
try try
{ {
return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false); return await ExtractImageInternal(inputArgument, imageStreamIndex, protocol, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false);
} }
catch (ArgumentException) catch (ArgumentException)
{ {
@ -503,10 +506,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
} }
} }
return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, false, resourcePool, cancellationToken).ConfigureAwait(false); return await ExtractImageInternal(inputArgument, imageStreamIndex, protocol, threedFormat, offset, false, resourcePool, cancellationToken).ConfigureAwait(false);
} }
private async Task<Stream> ExtractImageInternal(string inputPath, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken) private async Task<Stream> ExtractImageInternal(string inputPath, int? imageStreamIndex, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
{ {
if (string.IsNullOrEmpty(inputPath)) if (string.IsNullOrEmpty(inputPath))
{ {

View File

@ -141,6 +141,7 @@ namespace MediaBrowser.MediaEncoding.Probing
if (streamInfo.tags != null) if (streamInfo.tags != null)
{ {
stream.Language = GetDictionaryValue(streamInfo.tags, "language"); stream.Language = GetDictionaryValue(streamInfo.tags, "language");
stream.Comment = GetDictionaryValue(streamInfo.tags, "comment");
} }
if (string.Equals(streamInfo.codec_type, "audio", StringComparison.OrdinalIgnoreCase)) if (string.Equals(streamInfo.codec_type, "audio", StringComparison.OrdinalIgnoreCase))
@ -864,7 +865,7 @@ namespace MediaBrowser.MediaEncoding.Probing
} }
} }
private void ExtractTimestamp(Model.MediaInfo.MediaInfo video) private void ExtractTimestamp(MediaInfo video)
{ {
if (video.VideoType == VideoType.VideoFile) if (video.VideoType == VideoType.VideoFile)
{ {

View File

@ -122,10 +122,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles
var subtitle = await GetSubtitleStream(itemId, mediaSourceId, subtitleStreamIndex, cancellationToken) var subtitle = await GetSubtitleStream(itemId, mediaSourceId, subtitleStreamIndex, cancellationToken)
.ConfigureAwait(false); .ConfigureAwait(false);
using (var stream = subtitle.Item1)
{
var inputFormat = subtitle.Item2; var inputFormat = subtitle.Item2;
if (string.Equals(inputFormat, outputFormat, StringComparison.OrdinalIgnoreCase) && TryGetWriter(outputFormat) == null)
{
return subtitle.Item1;
}
using (var stream = subtitle.Item1)
{
return await ConvertSubtitles(stream, inputFormat, outputFormat, startTimeTicks, endTimeTicks, cancellationToken).ConfigureAwait(false); return await ConvertSubtitles(stream, inputFormat, outputFormat, startTimeTicks, endTimeTicks, cancellationToken).ConfigureAwait(false);
} }
} }
@ -288,7 +293,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
return null; return null;
} }
private ISubtitleWriter GetWriter(string format) private ISubtitleWriter TryGetWriter(string format)
{ {
if (string.IsNullOrEmpty(format)) if (string.IsNullOrEmpty(format))
{ {
@ -312,6 +317,18 @@ namespace MediaBrowser.MediaEncoding.Subtitles
return new TtmlWriter(); 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); throw new ArgumentException("Unsupported format: " + format);
} }

View File

@ -827,6 +827,9 @@
<Compile Include="..\MediaBrowser.Model\MediaInfo\VideoCodec.cs"> <Compile Include="..\MediaBrowser.Model\MediaInfo\VideoCodec.cs">
<Link>MediaInfo\VideoCodec.cs</Link> <Link>MediaInfo\VideoCodec.cs</Link>
</Compile> </Compile>
<Compile Include="..\MediaBrowser.Model\Net\EndPointInfo.cs">
<Link>Net\EndPointInfo.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Net\HttpException.cs"> <Compile Include="..\MediaBrowser.Model\Net\HttpException.cs">
<Link>Net\HttpException.cs</Link> <Link>Net\HttpException.cs</Link>
</Compile> </Compile>

View File

@ -783,6 +783,9 @@
<Compile Include="..\MediaBrowser.Model\MediaInfo\VideoCodec.cs"> <Compile Include="..\MediaBrowser.Model\MediaInfo\VideoCodec.cs">
<Link>MediaInfo\VideoCodec.cs</Link> <Link>MediaInfo\VideoCodec.cs</Link>
</Compile> </Compile>
<Compile Include="..\MediaBrowser.Model\Net\EndPointInfo.cs">
<Link>Net\EndPointInfo.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Net\HttpException.cs"> <Compile Include="..\MediaBrowser.Model\Net\HttpException.cs">
<Link>Net\HttpException.cs</Link> <Link>Net\HttpException.cs</Link>
</Compile> </Compile>

View File

@ -11,16 +11,19 @@ namespace MediaBrowser.Model.Configuration
public bool EnableIntrosParentalControl { get; set; } public bool EnableIntrosParentalControl { get; set; }
public bool EnableIntrosFromSimilarMovies { get; set; } public bool EnableIntrosFromSimilarMovies { get; set; }
public string CustomIntroPath { get; set; } public string CustomIntroPath { get; set; }
public string MediaInfoIntroPath { get; set; }
public bool EnableIntrosFromUpcomingDvdMovies { get; set; } public bool EnableIntrosFromUpcomingDvdMovies { get; set; }
public bool EnableIntrosFromUpcomingStreamingMovies { get; set; } public bool EnableIntrosFromUpcomingStreamingMovies { get; set; }
public int TrailerLimit { get; set; } public int TrailerLimit { get; set; }
public string[] Tags { get; set; }
public CinemaModeConfiguration() public CinemaModeConfiguration()
{ {
EnableIntrosParentalControl = true; EnableIntrosParentalControl = true;
EnableIntrosFromSimilarMovies = true; EnableIntrosFromSimilarMovies = true;
TrailerLimit = 2; TrailerLimit = 2;
Tags = new[] { "thx" };
} }
} }
} }

View File

@ -62,6 +62,12 @@ namespace MediaBrowser.Model.Configuration
/// <value><c>true</c> if this instance is port authorized; otherwise, <c>false</c>.</value> /// <value><c>true</c> if this instance is port authorized; otherwise, <c>false</c>.</value>
public bool IsPortAuthorized { get; set; } public bool IsPortAuthorized { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [enable high quality image scaling].
/// </summary>
/// <value><c>true</c> if [enable high quality image scaling]; otherwise, <c>false</c>.</value>
public bool EnableHighQualityImageScaling { get; set; }
/// <summary> /// <summary>
/// Gets or sets the item by name path. /// Gets or sets the item by name path.
/// </summary> /// </summary>
@ -92,24 +98,6 @@ namespace MediaBrowser.Model.Configuration
/// <value><c>true</c> if [enable localized guids]; otherwise, <c>false</c>.</value> /// <value><c>true</c> if [enable localized guids]; otherwise, <c>false</c>.</value>
public bool EnableLocalizedGuids { get; set; } public bool EnableLocalizedGuids { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [disable startup scan].
/// </summary>
/// <value><c>true</c> if [disable startup scan]; otherwise, <c>false</c>.</value>
public bool DisableStartupScan { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [enable user views].
/// </summary>
/// <value><c>true</c> if [enable user views]; otherwise, <c>false</c>.</value>
public bool EnableUserViews { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [enable library metadata sub folder].
/// </summary>
/// <value><c>true</c> if [enable library metadata sub folder]; otherwise, <c>false</c>.</value>
public bool EnableLibraryMetadataSubFolder { get; set; }
/// <summary> /// <summary>
/// Gets or sets the preferred metadata language. /// Gets or sets the preferred metadata language.
/// </summary> /// </summary>
@ -219,15 +207,14 @@ namespace MediaBrowser.Model.Configuration
public int SharingExpirationDays { get; set; } public int SharingExpirationDays { get; set; }
public bool DisableXmlSavers { get; set; }
public bool EnableWindowsShortcuts { get; set; } public bool EnableWindowsShortcuts { get; set; }
public bool EnableVideoFrameByFrameAnalysis { get; set; }
public bool EnableDateLastRefresh { get; set; } public bool EnableDateLastRefresh { get; set; }
public string[] Migrations { get; set; } public string[] Migrations { get; set; }
public int MigrationVersion { get; set; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class. /// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
/// </summary> /// </summary>

View File

@ -8,5 +8,6 @@ namespace MediaBrowser.Model.Connect
public string Email { get; set; } public string Email { get; set; }
public bool IsActive { get; set; } public bool IsActive { get; set; }
public string ImageUrl { get; set; } public string ImageUrl { get; set; }
public bool IsSupporter { get; set; }
} }
} }

View File

@ -30,6 +30,12 @@ namespace MediaBrowser.Model.Entities
/// <value>The language.</value> /// <value>The language.</value>
public string Language { get; set; } public string Language { get; set; }
/// <summary>
/// Gets or sets the comment.
/// </summary>
/// <value>The comment.</value>
public string Comment { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether this instance is interlaced. /// Gets or sets a value indicating whether this instance is interlaced.
/// </summary> /// </summary>

View File

@ -162,6 +162,7 @@
<Compile Include="MediaInfo\MediaProtocol.cs" /> <Compile Include="MediaInfo\MediaProtocol.cs" />
<Compile Include="MediaInfo\SubtitleTrackEvent.cs" /> <Compile Include="MediaInfo\SubtitleTrackEvent.cs" />
<Compile Include="MediaInfo\SubtitleTrackInfo.cs" /> <Compile Include="MediaInfo\SubtitleTrackInfo.cs" />
<Compile Include="Net\EndPointInfo.cs" />
<Compile Include="Net\HttpResponse.cs" /> <Compile Include="Net\HttpResponse.cs" />
<Compile Include="Net\MimeTypes.cs" /> <Compile Include="Net\MimeTypes.cs" />
<Compile Include="Notifications\NotificationOption.cs" /> <Compile Include="Notifications\NotificationOption.cs" />

Some files were not shown because too many files have changed in this diff Show More