Merge branch 'dev'
This commit is contained in:
commit
4f791d6ee1
|
@ -80,7 +80,7 @@ namespace MediaBrowser.Api
|
||||||
.OrderBy(i => i)
|
.OrderBy(i => i)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
result.Tags = items.OfType<IHasTags>()
|
result.Tags = items
|
||||||
.SelectMany(i => i.Tags)
|
.SelectMany(i => i.Tags)
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
.OrderBy(i => i)
|
.OrderBy(i => i)
|
||||||
|
|
|
@ -10,6 +10,7 @@ using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
|
@ -187,18 +188,40 @@ namespace MediaBrowser.Api
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetSimilarGames request)
|
public object Get(GetSimilarGames request)
|
||||||
{
|
{
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var result = GetSimilarItemsResult(request);
|
||||||
|
|
||||||
var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager,
|
|
||||||
_itemRepo,
|
|
||||||
_libraryManager,
|
|
||||||
_userDataRepository,
|
|
||||||
_dtoService,
|
|
||||||
Logger,
|
|
||||||
request, new[] { typeof(Game) },
|
|
||||||
SimilarItemsHelper.GetSimiliarityScore);
|
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private QueryResult<BaseItemDto> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request)
|
||||||
|
{
|
||||||
|
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
||||||
|
|
||||||
|
var item = string.IsNullOrEmpty(request.Id) ?
|
||||||
|
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
||||||
|
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
|
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
Limit = request.Limit,
|
||||||
|
IncludeItemTypes = new[]
|
||||||
|
{
|
||||||
|
typeof(Game).Name
|
||||||
|
},
|
||||||
|
SimilarTo = item
|
||||||
|
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
|
var result = new QueryResult<BaseItemDto>
|
||||||
|
{
|
||||||
|
Items = _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user).ToArray(),
|
||||||
|
|
||||||
|
TotalRecordCount = itemsResult.Count
|
||||||
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,11 +280,7 @@ namespace MediaBrowser.Api
|
||||||
episode.AbsoluteEpisodeNumber = request.AbsoluteEpisodeNumber;
|
episode.AbsoluteEpisodeNumber = request.AbsoluteEpisodeNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasTags = item as IHasTags;
|
item.Tags = request.Tags;
|
||||||
if (hasTags != null)
|
|
||||||
{
|
|
||||||
hasTags.Tags = request.Tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasTaglines = item as IHasTaglines;
|
var hasTaglines = item as IHasTaglines;
|
||||||
if (hasTaglines != null)
|
if (hasTaglines != null)
|
||||||
|
@ -298,11 +294,7 @@ namespace MediaBrowser.Api
|
||||||
hasShortOverview.ShortOverview = request.ShortOverview;
|
hasShortOverview.ShortOverview = request.ShortOverview;
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasKeywords = item as IHasKeywords;
|
item.Keywords = request.Keywords;
|
||||||
if (hasKeywords != null)
|
|
||||||
{
|
|
||||||
hasKeywords.Keywords = request.Keywords;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.Studios != null)
|
if (request.Studios != null)
|
||||||
{
|
{
|
||||||
|
@ -427,11 +419,6 @@ namespace MediaBrowser.Api
|
||||||
series.Status = request.SeriesStatus;
|
series.Status = request.SeriesStatus;
|
||||||
series.AirDays = request.AirDays;
|
series.AirDays = request.AirDays;
|
||||||
series.AirTime = request.AirTime;
|
series.AirTime = request.AirTime;
|
||||||
|
|
||||||
if (request.DisplaySpecialsWithSeasons.HasValue)
|
|
||||||
{
|
|
||||||
series.DisplaySpecialsWithSeasons = request.DisplaySpecialsWithSeasons.Value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -439,6 +439,12 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/ListingProviders/Default", "GET")]
|
||||||
|
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||||
|
public class GetDefaultListingProvider : ListingsProviderInfo, IReturn<ListingsProviderInfo>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/ListingProviders", "POST", Summary = "Adds a listing provider")]
|
[Route("/LiveTv/ListingProviders", "POST", Summary = "Adds a listing provider")]
|
||||||
[Authenticated(AllowBeforeStartupWizard = true)]
|
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||||
public class AddListingProvider : ListingsProviderInfo, IReturn<ListingsProviderInfo>
|
public class AddListingProvider : ListingsProviderInfo, IReturn<ListingsProviderInfo>
|
||||||
|
@ -478,6 +484,40 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/ChannelMappingOptions")]
|
||||||
|
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||||
|
public class GetChannelMappingOptions
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "Id", Description = "Provider id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string ProviderId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/ChannelMappings")]
|
||||||
|
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||||
|
public class SetChannelMapping
|
||||||
|
{
|
||||||
|
[ApiMember(Name = "Id", Description = "Provider id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
public string ProviderId { get; set; }
|
||||||
|
public string TunerChannelNumber { get; set; }
|
||||||
|
public string ProviderChannelNumber { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ChannelMappingOptions
|
||||||
|
{
|
||||||
|
public List<TunerChannelMapping> TunerChannels { get; set; }
|
||||||
|
public List<NameIdPair> ProviderChannels { get; set; }
|
||||||
|
public List<NameValuePair> Mappings { get; set; }
|
||||||
|
public string ProviderName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TunerChannelMapping
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Number { get; set; }
|
||||||
|
public string ProviderChannelNumber { get; set; }
|
||||||
|
public string ProviderChannelName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Registration", "GET")]
|
[Route("/LiveTv/Registration", "GET")]
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class GetLiveTvRegistrationInfo : IReturn<MBRegistrationRecord>
|
public class GetLiveTvRegistrationInfo : IReturn<MBRegistrationRecord>
|
||||||
|
@ -525,6 +565,11 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
_dtoService = dtoService;
|
_dtoService = dtoService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object Get(GetDefaultListingProvider request)
|
||||||
|
{
|
||||||
|
return ToOptimizedResult(new ListingsProviderInfo());
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetSatChannnelScanResult request)
|
public async Task<object> Get(GetSatChannnelScanResult request)
|
||||||
{
|
{
|
||||||
var result = await _liveTvManager.GetSatChannelScanResult(request, CancellationToken.None).ConfigureAwait(false);
|
var result = await _liveTvManager.GetSatChannelScanResult(request, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
@ -539,6 +584,102 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<object> Post(SetChannelMapping request)
|
||||||
|
{
|
||||||
|
var config = GetConfiguration();
|
||||||
|
|
||||||
|
var listingsProviderInfo = config.ListingProviders.First(i => string.Equals(request.ProviderId, i.Id, StringComparison.OrdinalIgnoreCase));
|
||||||
|
listingsProviderInfo.ChannelMappings = listingsProviderInfo.ChannelMappings.Where(i => !string.Equals(i.Name, request.TunerChannelNumber, StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||||
|
|
||||||
|
if (!string.Equals(request.TunerChannelNumber, request.ProviderChannelNumber, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
var list = listingsProviderInfo.ChannelMappings.ToList();
|
||||||
|
list.Add(new NameValuePair
|
||||||
|
{
|
||||||
|
Name = request.TunerChannelNumber,
|
||||||
|
Value = request.ProviderChannelNumber
|
||||||
|
});
|
||||||
|
listingsProviderInfo.ChannelMappings = list.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateConfiguration(config);
|
||||||
|
|
||||||
|
var tunerChannels = await _liveTvManager.GetChannelsForListingsProvider(request.ProviderId, CancellationToken.None)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
var providerChannels = await _liveTvManager.GetChannelsFromListingsProviderData(request.ProviderId, CancellationToken.None)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
var mappings = listingsProviderInfo.ChannelMappings.ToList();
|
||||||
|
|
||||||
|
var tunerChannelMappings =
|
||||||
|
tunerChannels.Select(i => GetTunerChannelMapping(i, mappings, providerChannels)).ToList();
|
||||||
|
|
||||||
|
return tunerChannelMappings.First(i => string.Equals(i.Number, request.TunerChannelNumber, StringComparison.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<object> Get(GetChannelMappingOptions request)
|
||||||
|
{
|
||||||
|
var config = GetConfiguration();
|
||||||
|
|
||||||
|
var listingsProviderInfo = config.ListingProviders.First(i => string.Equals(request.ProviderId, i.Id, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
var listingsProviderName = _liveTvManager.ListingProviders.First(i => string.Equals(i.Type, listingsProviderInfo.Type, StringComparison.OrdinalIgnoreCase)).Name;
|
||||||
|
|
||||||
|
var tunerChannels = await _liveTvManager.GetChannelsForListingsProvider(request.ProviderId, CancellationToken.None)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
var providerChannels = await _liveTvManager.GetChannelsFromListingsProviderData(request.ProviderId, CancellationToken.None)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
var mappings = listingsProviderInfo.ChannelMappings.ToList();
|
||||||
|
|
||||||
|
var result = new ChannelMappingOptions
|
||||||
|
{
|
||||||
|
TunerChannels = tunerChannels.Select(i => GetTunerChannelMapping(i, mappings, providerChannels)).ToList(),
|
||||||
|
|
||||||
|
ProviderChannels = providerChannels.Select(i => new NameIdPair
|
||||||
|
{
|
||||||
|
Name = i.Name,
|
||||||
|
Id = i.Number
|
||||||
|
|
||||||
|
}).ToList(),
|
||||||
|
|
||||||
|
Mappings = mappings,
|
||||||
|
|
||||||
|
ProviderName = listingsProviderName
|
||||||
|
};
|
||||||
|
|
||||||
|
return ToOptimizedResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TunerChannelMapping GetTunerChannelMapping(ChannelInfo channel, List<NameValuePair> mappings, List<ChannelInfo> providerChannels)
|
||||||
|
{
|
||||||
|
var result = new TunerChannelMapping
|
||||||
|
{
|
||||||
|
Name = channel.Number + " " + channel.Name,
|
||||||
|
Number = channel.Number
|
||||||
|
};
|
||||||
|
|
||||||
|
var mapping = mappings.FirstOrDefault(i => string.Equals(i.Name, channel.Number, StringComparison.OrdinalIgnoreCase));
|
||||||
|
var providerChannelNumber = channel.Number;
|
||||||
|
|
||||||
|
if (mapping != null)
|
||||||
|
{
|
||||||
|
providerChannelNumber = mapping.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
var providerChannel = providerChannels.FirstOrDefault(i => string.Equals(i.Number, providerChannelNumber, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
if (providerChannel != null)
|
||||||
|
{
|
||||||
|
result.ProviderChannelNumber = providerChannel.Number;
|
||||||
|
result.ProviderChannelName = providerChannel.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public object Get(GetSatIniMappings request)
|
public object Get(GetSatIniMappings request)
|
||||||
{
|
{
|
||||||
return ToOptimizedResult(_liveTvManager.GetSatIniMappings());
|
return ToOptimizedResult(_liveTvManager.GetSatIniMappings());
|
||||||
|
@ -550,9 +691,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
|
|
||||||
var response = await _httpClient.Get(new HttpRequestOptions
|
var response = await _httpClient.Get(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
Url = "https://json.schedulesdirect.org/20141201/available/countries",
|
Url = "https://json.schedulesdirect.org/20141201/available/countries"
|
||||||
CacheLength = TimeSpan.FromDays(1),
|
|
||||||
CacheMode = CacheMode.Unconditional
|
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -609,6 +748,11 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
return _config.GetConfiguration<LiveTvOptions>("livetv");
|
return _config.GetConfiguration<LiveTvOptions>("livetv");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateConfiguration(LiveTvOptions options)
|
||||||
|
{
|
||||||
|
_config.SaveConfiguration("livetv", options);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetLineups request)
|
public async Task<object> Get(GetLineups request)
|
||||||
{
|
{
|
||||||
var info = await _liveTvManager.GetLineups(request.Type, request.Id, request.Country, request.Location).ConfigureAwait(false);
|
var info = await _liveTvManager.GetLineups(request.Type, request.Id, request.Country, request.Location).ConfigureAwait(false);
|
||||||
|
@ -648,7 +792,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
Items = returnArray,
|
Items = returnArray,
|
||||||
TotalRecordCount = channelResult.TotalRecordCount
|
TotalRecordCount = channelResult.TotalRecordCount
|
||||||
};
|
};
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.LiveTv;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Movies
|
namespace MediaBrowser.Api.Movies
|
||||||
{
|
{
|
||||||
|
@ -110,18 +111,16 @@ namespace MediaBrowser.Api.Movies
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public async Task<object> Get(GetSimilarMovies request)
|
public object Get(GetSimilarMovies request)
|
||||||
{
|
{
|
||||||
var result = await GetSimilarItemsResult(
|
var result = GetSimilarItemsResult(request);
|
||||||
request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetSimilarTrailers request)
|
public object Get(GetSimilarTrailers request)
|
||||||
{
|
{
|
||||||
var result = await GetSimilarItemsResult(
|
var result = GetSimilarItemsResult(request);
|
||||||
request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
@ -130,148 +129,85 @@ namespace MediaBrowser.Api.Movies
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
|
|
||||||
var query = new InternalItemsQuery(user)
|
|
||||||
{
|
|
||||||
IncludeItemTypes = new[] { typeof(Movie).Name }
|
|
||||||
};
|
|
||||||
|
|
||||||
if (user.Configuration.IncludeTrailersInSuggestions)
|
|
||||||
{
|
|
||||||
var includeList = query.IncludeItemTypes.ToList();
|
|
||||||
includeList.Add(typeof(Trailer).Name);
|
|
||||||
query.IncludeItemTypes = includeList.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
|
|
||||||
var movies = _libraryManager.GetItemList(query, parentIds)
|
|
||||||
.OrderBy(i => (int)i.SourceType);
|
|
||||||
|
|
||||||
var listEligibleForCategories = new List<BaseItem>();
|
|
||||||
var listEligibleForSuggestion = new List<BaseItem>();
|
|
||||||
|
|
||||||
var list = movies.ToList();
|
|
||||||
|
|
||||||
listEligibleForCategories.AddRange(list);
|
|
||||||
listEligibleForSuggestion.AddRange(list);
|
|
||||||
|
|
||||||
listEligibleForCategories = listEligibleForCategories
|
|
||||||
// Exclude trailers from the suggestion categories
|
|
||||||
.Where(i => i is Movie)
|
|
||||||
.DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
|
|
||||||
.DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
listEligibleForSuggestion = listEligibleForSuggestion
|
|
||||||
.DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
|
|
||||||
.DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
dtoOptions.Fields = request.GetItemFields().ToList();
|
dtoOptions.Fields = request.GetItemFields().ToList();
|
||||||
|
|
||||||
var result = GetRecommendationCategories(user, listEligibleForCategories, listEligibleForSuggestion, request.CategoryLimit, request.ItemLimit, dtoOptions);
|
var result = GetRecommendationCategories(user, request.ParentId, request.CategoryLimit, request.ItemLimit, dtoOptions);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<ItemsResult> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
|
private QueryResult<BaseItemDto> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request)
|
||||||
{
|
{
|
||||||
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
||||||
|
|
||||||
var item = string.IsNullOrEmpty(request.Id) ?
|
var item = string.IsNullOrEmpty(request.Id) ?
|
||||||
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
||||||
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
var query = new InternalItemsQuery(user)
|
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Movie).Name }
|
Limit = request.Limit,
|
||||||
};
|
IncludeItemTypes = new[]
|
||||||
|
|
||||||
if (user == null || user.Configuration.IncludeTrailersInSuggestions)
|
|
||||||
{
|
|
||||||
var includeList = query.IncludeItemTypes.ToList();
|
|
||||||
includeList.Add(typeof(Trailer).Name);
|
|
||||||
query.IncludeItemTypes = includeList.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
var list = _libraryManager.GetItemList(query)
|
|
||||||
.OrderBy(i => (int)i.SourceType)
|
|
||||||
.DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (item is Video)
|
|
||||||
{
|
|
||||||
var imdbId = item.GetProviderId(MetadataProviders.Imdb);
|
|
||||||
|
|
||||||
// Use imdb id to try to filter duplicates of the same item
|
|
||||||
if (!string.IsNullOrWhiteSpace(imdbId))
|
|
||||||
{
|
{
|
||||||
list = list
|
typeof(Movie).Name,
|
||||||
.Where(i => !string.Equals(imdbId, i.GetProviderId(MetadataProviders.Imdb), StringComparison.OrdinalIgnoreCase))
|
typeof(Trailer).Name,
|
||||||
.ToList();
|
typeof(LiveTvProgram).Name
|
||||||
}
|
},
|
||||||
}
|
IsMovie = true,
|
||||||
|
SimilarTo = item
|
||||||
var items = SimilarItemsHelper.GetSimilaritems(item, _libraryManager, list, getSimilarityScore).ToList();
|
}).ToList();
|
||||||
|
|
||||||
IEnumerable<BaseItem> returnItems = items;
|
|
||||||
|
|
||||||
if (request.Limit.HasValue)
|
|
||||||
{
|
|
||||||
returnItems = returnItems.Take(request.Limit.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
var result = new ItemsResult
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
Items = _dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ToArray(),
|
Items = _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user).ToArray(),
|
||||||
|
|
||||||
TotalRecordCount = items.Count
|
TotalRecordCount = itemsResult.Count
|
||||||
};
|
};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<RecommendationDto> GetRecommendationCategories(User user, List<BaseItem> allMoviesForCategories, List<BaseItem> allMovies, int categoryLimit, int itemLimit, DtoOptions dtoOptions)
|
private IEnumerable<RecommendationDto> GetRecommendationCategories(User user, string parentId, int categoryLimit, int itemLimit, DtoOptions dtoOptions)
|
||||||
{
|
{
|
||||||
var categories = new List<RecommendationDto>();
|
var categories = new List<RecommendationDto>();
|
||||||
|
|
||||||
var recentlyPlayedMovies = allMoviesForCategories
|
var parentIds = string.IsNullOrWhiteSpace(parentId) ? new string[] { } : new[] { parentId };
|
||||||
.Select(i =>
|
var query = new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
IncludeItemTypes = new[]
|
||||||
{
|
{
|
||||||
var userdata = _userDataRepository.GetUserData(user, i);
|
typeof(Movie).Name,
|
||||||
return new Tuple<BaseItem, bool, DateTime>(i, userdata.Played, userdata.LastPlayedDate ?? DateTime.MinValue);
|
//typeof(Trailer).Name,
|
||||||
})
|
//typeof(LiveTvProgram).Name
|
||||||
.Where(i => i.Item2)
|
},
|
||||||
.OrderByDescending(i => i.Item3)
|
// IsMovie = true
|
||||||
.Select(i => i.Item1)
|
SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.Random },
|
||||||
.ToList();
|
SortOrder = SortOrder.Descending,
|
||||||
|
Limit = 7
|
||||||
|
};
|
||||||
|
|
||||||
var excludeFromLiked = recentlyPlayedMovies.Take(10);
|
var recentlyPlayedMovies = _libraryManager.GetItemList(query, parentIds).ToList();
|
||||||
var likedMovies = allMovies
|
|
||||||
.Select(i =>
|
var likedMovies = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
IncludeItemTypes = new[]
|
||||||
{
|
{
|
||||||
var score = 0;
|
typeof(Movie).Name,
|
||||||
var userData = _userDataRepository.GetUserData(user, i);
|
typeof(Trailer).Name,
|
||||||
|
typeof(LiveTvProgram).Name
|
||||||
|
},
|
||||||
|
IsMovie = true,
|
||||||
|
SortBy = new[] { ItemSortBy.Random },
|
||||||
|
SortOrder = SortOrder.Descending,
|
||||||
|
Limit = 10,
|
||||||
|
IsFavoriteOrLiked = true,
|
||||||
|
ExcludeItemIds = recentlyPlayedMovies.Select(i => i.Id.ToString("N")).ToArray()
|
||||||
|
|
||||||
if (userData.IsFavorite)
|
}, parentIds).ToList();
|
||||||
{
|
|
||||||
score = 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
score = userData.Likes.HasValue ? userData.Likes.Value ? 1 : -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Tuple<BaseItem, int>(i, score);
|
|
||||||
})
|
|
||||||
.OrderByDescending(i => i.Item2)
|
|
||||||
.ThenBy(i => Guid.NewGuid())
|
|
||||||
.Where(i => i.Item2 > 0)
|
|
||||||
.Select(i => i.Item1)
|
|
||||||
.Where(i => !excludeFromLiked.Contains(i));
|
|
||||||
|
|
||||||
var mostRecentMovies = recentlyPlayedMovies.Take(6).ToList();
|
var mostRecentMovies = recentlyPlayedMovies.Take(6).ToList();
|
||||||
// Get recently played directors
|
// Get recently played directors
|
||||||
|
@ -284,11 +220,11 @@ namespace MediaBrowser.Api.Movies
|
||||||
.OrderBy(i => Guid.NewGuid())
|
.OrderBy(i => Guid.NewGuid())
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var similarToRecentlyPlayed = GetSimilarTo(user, allMovies, recentlyPlayedMovies.Take(7).OrderBy(i => Guid.NewGuid()), itemLimit, dtoOptions, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator();
|
var similarToRecentlyPlayed = GetSimilarTo(user, recentlyPlayedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator();
|
||||||
var similarToLiked = GetSimilarTo(user, allMovies, likedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToLikedItem).GetEnumerator();
|
var similarToLiked = GetSimilarTo(user, likedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToLikedItem).GetEnumerator();
|
||||||
|
|
||||||
var hasDirectorFromRecentlyPlayed = GetWithDirector(user, allMovies, recentDirectors, itemLimit, dtoOptions, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator();
|
var hasDirectorFromRecentlyPlayed = GetWithDirector(user, recentDirectors, itemLimit, dtoOptions, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator();
|
||||||
var hasActorFromRecentlyPlayed = GetWithActor(user, allMovies, recentActors, itemLimit, dtoOptions, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator();
|
var hasActorFromRecentlyPlayed = GetWithActor(user, recentActors, itemLimit, dtoOptions, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator();
|
||||||
|
|
||||||
var categoryTypes = new List<IEnumerator<RecommendationDto>>
|
var categoryTypes = new List<IEnumerator<RecommendationDto>>
|
||||||
{
|
{
|
||||||
|
@ -331,44 +267,27 @@ namespace MediaBrowser.Api.Movies
|
||||||
return categories.OrderBy(i => i.RecommendationType).ThenBy(i => Guid.NewGuid());
|
return categories.OrderBy(i => i.RecommendationType).ThenBy(i => Guid.NewGuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<RecommendationDto> GetWithDirector(User user, List<BaseItem> allMovies, IEnumerable<string> directors, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
|
private IEnumerable<RecommendationDto> GetWithDirector(User user, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
|
||||||
{
|
|
||||||
var userId = user.Id;
|
|
||||||
|
|
||||||
foreach (var director in directors)
|
|
||||||
{
|
|
||||||
var items = allMovies
|
|
||||||
.Where(i => _libraryManager.GetPeople(i).Any(p => string.Equals(p.Type, PersonType.Director, StringComparison.OrdinalIgnoreCase) && string.Equals(p.Name, director, StringComparison.OrdinalIgnoreCase)))
|
|
||||||
.Take(itemLimit)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (items.Count > 0)
|
|
||||||
{
|
|
||||||
yield return new RecommendationDto
|
|
||||||
{
|
|
||||||
BaselineItemName = director,
|
|
||||||
CategoryId = director.GetMD5().ToString("N"),
|
|
||||||
RecommendationType = type,
|
|
||||||
Items = _dtoService.GetBaseItemDtos(items, dtoOptions, user).ToArray()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<RecommendationDto> GetWithActor(User user, List<BaseItem> allMovies, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
|
|
||||||
{
|
{
|
||||||
foreach (var name in names)
|
foreach (var name in names)
|
||||||
{
|
{
|
||||||
var itemsWithActor = _libraryManager.GetItemIds(new InternalItemsQuery(user)
|
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Person = name
|
Person = name,
|
||||||
|
// Account for duplicates by imdb id, since the database doesn't support this yet
|
||||||
|
Limit = itemLimit + 2,
|
||||||
|
PersonTypes = new[] { PersonType.Director },
|
||||||
|
IncludeItemTypes = new[]
|
||||||
|
{
|
||||||
|
typeof(Movie).Name,
|
||||||
|
typeof(Trailer).Name,
|
||||||
|
typeof(LiveTvProgram).Name
|
||||||
|
},
|
||||||
|
IsMovie = true
|
||||||
|
|
||||||
});
|
}).DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
|
||||||
|
.Take(itemLimit)
|
||||||
var items = allMovies
|
.ToList();
|
||||||
.Where(i => itemsWithActor.Contains(i.Id))
|
|
||||||
.Take(itemLimit)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (items.Count > 0)
|
if (items.Count > 0)
|
||||||
{
|
{
|
||||||
|
@ -383,14 +302,57 @@ namespace MediaBrowser.Api.Movies
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<RecommendationDto> GetSimilarTo(User user, List<BaseItem> allMovies, IEnumerable<BaseItem> baselineItems, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
|
private IEnumerable<RecommendationDto> GetWithActor(User user, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
|
||||||
|
{
|
||||||
|
foreach (var name in names)
|
||||||
|
{
|
||||||
|
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
Person = name,
|
||||||
|
// Account for duplicates by imdb id, since the database doesn't support this yet
|
||||||
|
Limit = itemLimit + 2,
|
||||||
|
IncludeItemTypes = new[]
|
||||||
|
{
|
||||||
|
typeof(Movie).Name,
|
||||||
|
typeof(Trailer).Name,
|
||||||
|
typeof(LiveTvProgram).Name
|
||||||
|
},
|
||||||
|
IsMovie = true
|
||||||
|
|
||||||
|
}).DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
|
||||||
|
.Take(itemLimit)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (items.Count > 0)
|
||||||
|
{
|
||||||
|
yield return new RecommendationDto
|
||||||
|
{
|
||||||
|
BaselineItemName = name,
|
||||||
|
CategoryId = name.GetMD5().ToString("N"),
|
||||||
|
RecommendationType = type,
|
||||||
|
Items = _dtoService.GetBaseItemDtos(items, dtoOptions, user).ToArray()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<RecommendationDto> GetSimilarTo(User user, List<BaseItem> baselineItems, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
|
||||||
{
|
{
|
||||||
foreach (var item in baselineItems)
|
foreach (var item in baselineItems)
|
||||||
{
|
{
|
||||||
var similar = SimilarItemsHelper
|
var similar = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
.GetSimilaritems(item, _libraryManager, allMovies, SimilarItemsHelper.GetSimiliarityScore)
|
{
|
||||||
.Take(itemLimit)
|
Limit = itemLimit,
|
||||||
.ToList();
|
IncludeItemTypes = new[]
|
||||||
|
{
|
||||||
|
typeof(Movie).Name,
|
||||||
|
typeof(Trailer).Name,
|
||||||
|
typeof(LiveTvProgram).Name
|
||||||
|
},
|
||||||
|
IsMovie = true,
|
||||||
|
SimilarTo = item
|
||||||
|
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
if (similar.Count > 0)
|
if (similar.Count > 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -846,7 +846,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
if (MediaEncoder.SupportsDecoder("h264_qsv"))
|
if (MediaEncoder.SupportsDecoder("h264_qsv"))
|
||||||
{
|
{
|
||||||
// Seeing stalls and failures with decoding. Not worth it compared to encoding.
|
// Seeing stalls and failures with decoding. Not worth it compared to encoding.
|
||||||
//return "-c:v h264_qsv ";
|
return "-c:v h264_qsv ";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "mpeg2video":
|
case "mpeg2video":
|
||||||
|
@ -980,11 +980,6 @@ namespace MediaBrowser.Api.Playback
|
||||||
var transcodingId = Guid.NewGuid().ToString("N");
|
var transcodingId = Guid.NewGuid().ToString("N");
|
||||||
var commandLineArgs = GetCommandLineArguments(outputPath, state, true);
|
var commandLineArgs = GetCommandLineArguments(outputPath, state, true);
|
||||||
|
|
||||||
if (ApiEntryPoint.Instance.GetEncodingOptions().EnableDebugLogging)
|
|
||||||
{
|
|
||||||
commandLineArgs = "-loglevel debug " + commandLineArgs;
|
|
||||||
}
|
|
||||||
|
|
||||||
var process = new Process
|
var process = new Process
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
StartInfo = new ProcessStartInfo
|
||||||
|
@ -1212,7 +1207,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int? GetVideoBitrateParamValue(VideoStreamRequest request, MediaStream videoStream)
|
private int? GetVideoBitrateParamValue(VideoStreamRequest request, MediaStream videoStream, string outputVideoCodec)
|
||||||
{
|
{
|
||||||
var bitrate = request.VideoBitRate;
|
var bitrate = request.VideoBitRate;
|
||||||
|
|
||||||
|
@ -1237,6 +1232,18 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bitrate.HasValue)
|
||||||
|
{
|
||||||
|
var inputVideoCodec = videoStream == null ? null : videoStream.Codec;
|
||||||
|
bitrate = ResolutionNormalizer.ScaleBitrate(bitrate.Value, inputVideoCodec, outputVideoCodec);
|
||||||
|
|
||||||
|
// If a max bitrate was requested, don't let the scaled bitrate exceed it
|
||||||
|
if (request.VideoBitRate.HasValue)
|
||||||
|
{
|
||||||
|
bitrate = Math.Min(bitrate.Value, request.VideoBitRate.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return bitrate;
|
return bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1518,6 +1525,13 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (i == 25)
|
else if (i == 25)
|
||||||
|
{
|
||||||
|
if (videoRequest != null)
|
||||||
|
{
|
||||||
|
videoRequest.ForceLiveStream = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (i == 26)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(val) && videoRequest != null)
|
if (!string.IsNullOrWhiteSpace(val) && videoRequest != null)
|
||||||
{
|
{
|
||||||
|
@ -1528,7 +1542,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (i == 26)
|
else if (i == 27)
|
||||||
{
|
{
|
||||||
request.TranscodingMaxAudioChannels = int.Parse(val, UsCulture);
|
request.TranscodingMaxAudioChannels = int.Parse(val, UsCulture);
|
||||||
}
|
}
|
||||||
|
@ -1690,7 +1704,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
if (videoRequest != null)
|
if (videoRequest != null)
|
||||||
{
|
{
|
||||||
state.OutputVideoCodec = state.VideoRequest.VideoCodec;
|
state.OutputVideoCodec = state.VideoRequest.VideoCodec;
|
||||||
state.OutputVideoBitrate = GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream);
|
state.OutputVideoBitrate = GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec);
|
||||||
|
|
||||||
if (state.OutputVideoBitrate.HasValue)
|
if (state.OutputVideoBitrate.HasValue)
|
||||||
{
|
{
|
||||||
|
|
|
@ -96,7 +96,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
public long? InputFileSize { get; set; }
|
public long? InputFileSize { get; set; }
|
||||||
|
|
||||||
public string OutputAudioSync = "1";
|
public string OutputAudioSync = "1";
|
||||||
public string OutputVideoSync = "vfr";
|
public string OutputVideoSync = "-1";
|
||||||
|
|
||||||
public List<string> SupportedAudioCodecs { get; set; }
|
public List<string> SupportedAudioCodecs { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,6 @@ namespace MediaBrowser.Api.Reports
|
||||||
NameStartsWith = request.NameStartsWith,
|
NameStartsWith = request.NameStartsWith,
|
||||||
NameStartsWithOrGreater = request.NameStartsWithOrGreater,
|
NameStartsWithOrGreater = request.NameStartsWithOrGreater,
|
||||||
HasImdbId = request.HasImdbId,
|
HasImdbId = request.HasImdbId,
|
||||||
IsYearMismatched = request.IsYearMismatched,
|
|
||||||
IsPlaceHolder = request.IsPlaceHolder,
|
IsPlaceHolder = request.IsPlaceHolder,
|
||||||
IsLocked = request.IsLocked,
|
IsLocked = request.IsLocked,
|
||||||
IsInBoxSet = request.IsInBoxSet,
|
IsInBoxSet = request.IsInBoxSet,
|
||||||
|
|
|
@ -116,24 +116,12 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
private static IEnumerable<string> GetTags(BaseItem item)
|
private static IEnumerable<string> GetTags(BaseItem item)
|
||||||
{
|
{
|
||||||
var hasTags = item as IHasTags;
|
return item.Tags;
|
||||||
if (hasTags != null)
|
|
||||||
{
|
|
||||||
return hasTags.Tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new List<string>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<string> GetKeywords(BaseItem item)
|
private static IEnumerable<string> GetKeywords(BaseItem item)
|
||||||
{
|
{
|
||||||
var hasTags = item as IHasKeywords;
|
return item.Keywords;
|
||||||
if (hasTags != null)
|
|
||||||
{
|
|
||||||
return hasTags.Keywords;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new List<string>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -111,10 +111,10 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
config.EnableLocalizedGuids = true;
|
config.EnableLocalizedGuids = true;
|
||||||
config.EnableCustomPathSubFolders = true;
|
config.EnableCustomPathSubFolders = true;
|
||||||
config.EnableDateLastRefresh = true;
|
|
||||||
config.EnableStandaloneMusicKeys = true;
|
config.EnableStandaloneMusicKeys = true;
|
||||||
config.EnableCaseSensitiveItemIds = true;
|
config.EnableCaseSensitiveItemIds = true;
|
||||||
config.SchemaVersion = 79;
|
config.EnableFolderView = true;
|
||||||
|
config.SchemaVersion = 92;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(UpdateStartupConfiguration request)
|
public void Post(UpdateStartupConfiguration request)
|
||||||
|
|
|
@ -98,6 +98,10 @@ namespace MediaBrowser.Api.Subtitles
|
||||||
|
|
||||||
[ApiMember(Name = "EndPositionTicks", Description = "EndPositionTicks", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "EndPositionTicks", Description = "EndPositionTicks", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public long? EndPositionTicks { get; set; }
|
public long? EndPositionTicks { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "CopyTimestamps", Description = "CopyTimestamps", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
|
public bool CopyTimestamps { get; set; }
|
||||||
|
public bool AddVttTimeMap { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/subtitles.m3u8", "GET", Summary = "Gets an HLS subtitle playlist.")]
|
[Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/subtitles.m3u8", "GET", Summary = "Gets an HLS subtitle playlist.")]
|
||||||
|
@ -175,7 +179,7 @@ namespace MediaBrowser.Api.Subtitles
|
||||||
|
|
||||||
var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks);
|
var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks);
|
||||||
|
|
||||||
var url = string.Format("stream.vtt?StartPositionTicks={0}&EndPositionTicks={1}&api_key={2}",
|
var url = string.Format("stream.vtt?CopyTimestamps=true&AddVttTimeMap=true&StartPositionTicks={0}&EndPositionTicks={1}&api_key={2}",
|
||||||
positionTicks.ToString(CultureInfo.InvariantCulture),
|
positionTicks.ToString(CultureInfo.InvariantCulture),
|
||||||
endPositionTicks.ToString(CultureInfo.InvariantCulture),
|
endPositionTicks.ToString(CultureInfo.InvariantCulture),
|
||||||
accessToken);
|
accessToken);
|
||||||
|
@ -190,7 +194,7 @@ namespace MediaBrowser.Api.Subtitles
|
||||||
return ResultFactory.GetResult(builder.ToString(), MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
|
return ResultFactory.GetResult(builder.ToString(), MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetSubtitle request)
|
public async Task<object> Get(GetSubtitle request)
|
||||||
{
|
{
|
||||||
if (string.Equals(request.Format, "js", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(request.Format, "js", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
|
@ -209,20 +213,32 @@ namespace MediaBrowser.Api.Subtitles
|
||||||
return ToStaticFileResult(subtitleStream.Path);
|
return ToStaticFileResult(subtitleStream.Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
var stream = GetSubtitles(request).Result;
|
using (var stream = await GetSubtitles(request).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
using (var reader = new StreamReader(stream))
|
||||||
|
{
|
||||||
|
var text = reader.ReadToEnd();
|
||||||
|
|
||||||
return ResultFactory.GetResult(stream, MimeTypes.GetMimeType("file." + request.Format));
|
if (string.Equals(request.Format, "vtt", StringComparison.OrdinalIgnoreCase) && request.AddVttTimeMap)
|
||||||
|
{
|
||||||
|
text = text.Replace("WEBVTT", "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultFactory.GetResult(text, MimeTypes.GetMimeType("file." + request.Format));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Stream> GetSubtitles(GetSubtitle request)
|
private Task<Stream> GetSubtitles(GetSubtitle request)
|
||||||
{
|
{
|
||||||
return await _subtitleEncoder.GetSubtitles(request.Id,
|
return _subtitleEncoder.GetSubtitles(request.Id,
|
||||||
request.MediaSourceId,
|
request.MediaSourceId,
|
||||||
request.Index,
|
request.Index,
|
||||||
request.Format,
|
request.Format,
|
||||||
request.StartPositionTicks,
|
request.StartPositionTicks,
|
||||||
request.EndPositionTicks,
|
request.EndPositionTicks,
|
||||||
CancellationToken.None).ConfigureAwait(false);
|
request.CopyTimestamps,
|
||||||
|
CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(SearchRemoteSubtitles request)
|
public object Get(SearchRemoteSubtitles request)
|
||||||
|
|
|
@ -12,6 +12,7 @@ using ServiceStack;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
|
@ -273,20 +274,42 @@ namespace MediaBrowser.Api
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetSimilarShows request)
|
public object Get(GetSimilarShows request)
|
||||||
{
|
{
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var result = GetSimilarItemsResult(request);
|
||||||
|
|
||||||
var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager,
|
|
||||||
_itemRepo,
|
|
||||||
_libraryManager,
|
|
||||||
_userDataManager,
|
|
||||||
_dtoService,
|
|
||||||
Logger,
|
|
||||||
request, new[] { typeof(Series) },
|
|
||||||
SimilarItemsHelper.GetSimiliarityScore);
|
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private QueryResult<BaseItemDto> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request)
|
||||||
|
{
|
||||||
|
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
||||||
|
|
||||||
|
var item = string.IsNullOrEmpty(request.Id) ?
|
||||||
|
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
||||||
|
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
|
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
Limit = request.Limit,
|
||||||
|
IncludeItemTypes = new[]
|
||||||
|
{
|
||||||
|
typeof(Series).Name
|
||||||
|
},
|
||||||
|
SimilarTo = item
|
||||||
|
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
|
var result = new QueryResult<BaseItemDto>
|
||||||
|
{
|
||||||
|
Items = _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user).ToArray(),
|
||||||
|
|
||||||
|
TotalRecordCount = itemsResult.Count
|
||||||
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public object Get(GetUpcomingEpisodes request)
|
public object Get(GetUpcomingEpisodes request)
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
|
|
|
@ -333,12 +333,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
var tags = request.GetTags();
|
var tags = request.GetTags();
|
||||||
if (tags.Length > 0)
|
if (tags.Length > 0)
|
||||||
{
|
{
|
||||||
var hasTags = i as IHasTags;
|
if (!tags.Any(v => i.Tags.Contains(v, StringComparer.OrdinalIgnoreCase)))
|
||||||
if (hasTags == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!tags.Any(v => hasTags.Tags.Contains(v, StringComparer.OrdinalIgnoreCase)))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,9 +100,6 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
[ApiMember(Name = "HasTvdbId", Description = "Optional filter by items that have a tvdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "HasTvdbId", Description = "Optional filter by items that have a tvdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
public bool? HasTvdbId { get; set; }
|
public bool? HasTvdbId { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "IsYearMismatched", Description = "Optional filter by items that are potentially misidentified.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
|
||||||
public bool? IsYearMismatched { get; set; }
|
|
||||||
|
|
||||||
[ApiMember(Name = "IsInBoxSet", Description = "Optional filter by items that are in boxsets, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "IsInBoxSet", Description = "Optional filter by items that are in boxsets, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
public bool? IsInBoxSet { get; set; }
|
public bool? IsInBoxSet { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -187,7 +187,6 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
NameStartsWith = request.NameStartsWith,
|
NameStartsWith = request.NameStartsWith,
|
||||||
NameStartsWithOrGreater = request.NameStartsWithOrGreater,
|
NameStartsWithOrGreater = request.NameStartsWithOrGreater,
|
||||||
HasImdbId = request.HasImdbId,
|
HasImdbId = request.HasImdbId,
|
||||||
IsYearMismatched = request.IsYearMismatched,
|
|
||||||
IsPlaceHolder = request.IsPlaceHolder,
|
IsPlaceHolder = request.IsPlaceHolder,
|
||||||
IsLocked = request.IsLocked,
|
IsLocked = request.IsLocked,
|
||||||
IsInBoxSet = request.IsInBoxSet,
|
IsInBoxSet = request.IsInBoxSet,
|
||||||
|
|
|
@ -385,7 +385,7 @@ namespace MediaBrowser.Api
|
||||||
throw new ResourceNotFoundException("User not found");
|
throw new ResourceNotFoundException("User not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
await _sessionMananger.RevokeUserTokens(user.Id.ToString("N")).ConfigureAwait(false);
|
await _sessionMananger.RevokeUserTokens(user.Id.ToString("N"), null).ConfigureAwait(false);
|
||||||
|
|
||||||
await _userManager.DeleteUser(user).ConfigureAwait(false);
|
await _userManager.DeleteUser(user).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -465,6 +465,10 @@ namespace MediaBrowser.Api
|
||||||
}
|
}
|
||||||
|
|
||||||
await _userManager.ChangePassword(user, request.NewPassword).ConfigureAwait(false);
|
await _userManager.ChangePassword(user, request.NewPassword).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var currentToken = AuthorizationContext.GetAuthorizationInfo(Request).Token;
|
||||||
|
|
||||||
|
await _sessionMananger.RevokeUserTokens(user.Id.ToString("N"), currentToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,7 +606,8 @@ namespace MediaBrowser.Api
|
||||||
throw new ArgumentException("There must be at least one enabled user in the system.");
|
throw new ArgumentException("There must be at least one enabled user in the system.");
|
||||||
}
|
}
|
||||||
|
|
||||||
await _sessionMananger.RevokeUserTokens(user.Id.ToString("N")).ConfigureAwait(false);
|
var currentToken = AuthorizationContext.GetAuthorizationInfo(Request).Token;
|
||||||
|
await _sessionMananger.RevokeUserTokens(user.Id.ToString("N"), currentToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _userManager.UpdateUserPolicy(request.Id, request).ConfigureAwait(false);
|
await _userManager.UpdateUserPolicy(request.Id, request).ConfigureAwait(false);
|
||||||
|
|
|
@ -552,7 +552,7 @@ namespace MediaBrowser.Common.Implementations
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.Error("Error creating {0}", ex, type.Name);
|
Logger.ErrorException("Error creating {0}", ex, type.Name);
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
@ -571,7 +571,7 @@ namespace MediaBrowser.Common.Implementations
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.Error("Error creating {0}", ex, type.Name);
|
Logger.ErrorException("Error creating {0}", ex, type.Name);
|
||||||
// Don't blow up in release mode
|
// Don't blow up in release mode
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private WebRequest GetRequest(HttpRequestOptions options, string method, bool enableHttpCompression)
|
private WebRequest GetRequest(HttpRequestOptions options, string method)
|
||||||
{
|
{
|
||||||
var request = CreateWebRequest(options.Url);
|
var request = CreateWebRequest(options.Url);
|
||||||
var httpWebRequest = request as HttpWebRequest;
|
var httpWebRequest = request as HttpWebRequest;
|
||||||
|
@ -154,7 +154,9 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
|
|
||||||
AddRequestHeaders(httpWebRequest, options);
|
AddRequestHeaders(httpWebRequest, options);
|
||||||
|
|
||||||
httpWebRequest.AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None;
|
httpWebRequest.AutomaticDecompression = options.EnableHttpCompression ?
|
||||||
|
(options.DecompressionMethod ?? DecompressionMethods.Deflate) :
|
||||||
|
DecompressionMethods.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
|
request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
|
||||||
|
@ -366,7 +368,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var httpWebRequest = GetRequest(options, httpMethod, options.EnableHttpCompression);
|
var httpWebRequest = GetRequest(options, httpMethod);
|
||||||
|
|
||||||
if (options.RequestContentBytes != null ||
|
if (options.RequestContentBytes != null ||
|
||||||
!string.IsNullOrEmpty(options.RequestContent) ||
|
!string.IsNullOrEmpty(options.RequestContent) ||
|
||||||
|
@ -556,7 +558,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
|
|
||||||
options.CancellationToken.ThrowIfCancellationRequested();
|
options.CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var httpWebRequest = GetRequest(options, "GET", options.EnableHttpCompression);
|
var httpWebRequest = GetRequest(options, "GET");
|
||||||
|
|
||||||
if (options.ResourcePool != null)
|
if (options.ResourcePool != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -65,8 +65,8 @@
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
|
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SimpleInjector, Version=3.1.4.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
<Reference Include="SimpleInjector, Version=3.1.5.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\SimpleInjector.3.1.4\lib\net45\SimpleInjector.dll</HintPath>
|
<HintPath>..\packages\SimpleInjector.3.1.5\lib\net45\SimpleInjector.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
|
|
@ -4,5 +4,5 @@
|
||||||
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
||||||
<package id="NLog" version="4.3.4" targetFramework="net45" />
|
<package id="NLog" version="4.3.4" 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.1.4" targetFramework="net45" />
|
<package id="SimpleInjector" version="3.1.5" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Net
|
namespace MediaBrowser.Common.Net
|
||||||
|
@ -16,6 +17,8 @@ namespace MediaBrowser.Common.Net
|
||||||
/// <value>The URL.</value>
|
/// <value>The URL.</value>
|
||||||
public string Url { get; set; }
|
public string Url { get; set; }
|
||||||
|
|
||||||
|
public DecompressionMethods? DecompressionMethod { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the accept header.
|
/// Gets or sets the accept header.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -53,6 +53,8 @@ namespace MediaBrowser.Controller.Channels
|
||||||
|
|
||||||
public bool IsInfiniteStream { get; set; }
|
public bool IsInfiniteStream { get; set; }
|
||||||
|
|
||||||
|
public string HomePageUrl { get; set; }
|
||||||
|
|
||||||
public ChannelItemInfo()
|
public ChannelItemInfo()
|
||||||
{
|
{
|
||||||
MediaSources = new List<ChannelMediaInfo>();
|
MediaSources = new List<ChannelMediaInfo>();
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace MediaBrowser.Controller.Chapters
|
||||||
/// <param name="chapters">The chapters.</param>
|
/// <param name="chapters">The chapters.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task SaveChapters(string itemId, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken);
|
Task SaveChapters(string itemId, List<ChapterInfo> chapters, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Searches the specified video.
|
/// Searches the specified video.
|
||||||
|
|
|
@ -20,7 +20,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
IHasArtist,
|
IHasArtist,
|
||||||
IHasMusicGenres,
|
IHasMusicGenres,
|
||||||
IHasLookupInfo<SongInfo>,
|
IHasLookupInfo<SongInfo>,
|
||||||
IHasTags,
|
|
||||||
IHasMediaSources,
|
IHasMediaSources,
|
||||||
IThemeMedia,
|
IThemeMedia,
|
||||||
IArchivable
|
IArchivable
|
||||||
|
|
|
@ -179,17 +179,13 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
{
|
{
|
||||||
var items = GetRecursiveChildren().ToList();
|
var items = GetRecursiveChildren().ToList();
|
||||||
|
|
||||||
var songs = items.OfType<Audio>().ToList();
|
var totalItems = items.Count;
|
||||||
|
|
||||||
var others = items.Except(songs).ToList();
|
|
||||||
|
|
||||||
var totalItems = songs.Count + others.Count;
|
|
||||||
var numComplete = 0;
|
var numComplete = 0;
|
||||||
|
|
||||||
var childUpdateType = ItemUpdateType.None;
|
var childUpdateType = ItemUpdateType.None;
|
||||||
|
|
||||||
// Refresh songs
|
// Refresh songs
|
||||||
foreach (var item in songs)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
@ -199,7 +195,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
numComplete++;
|
numComplete++;
|
||||||
double percent = numComplete;
|
double percent = numComplete;
|
||||||
percent /= totalItems;
|
percent /= totalItems;
|
||||||
progress.Report(percent * 100);
|
progress.Report(percent * 95);
|
||||||
}
|
}
|
||||||
|
|
||||||
var parentRefreshOptions = refreshOptions;
|
var parentRefreshOptions = refreshOptions;
|
||||||
|
@ -212,19 +208,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
// Refresh current item
|
// Refresh current item
|
||||||
await RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false);
|
await RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
// Refresh all non-songs
|
|
||||||
foreach (var item in others)
|
|
||||||
{
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
var updateType = await item.RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
numComplete++;
|
|
||||||
double percent = numComplete;
|
|
||||||
percent /= totalItems;
|
|
||||||
progress.Report(percent * 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
progress.Report(100);
|
progress.Report(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,13 +62,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
query.ArtistNames = new[] { Name };
|
query.ArtistNames = new[] { Name };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need this for now since the artist filter isn't yet supported by the db
|
|
||||||
if (ConfigurationManager.Configuration.SchemaVersion < 79)
|
|
||||||
{
|
|
||||||
var filter = GetItemFilter();
|
|
||||||
return LibraryManager.GetItemList(query).Where(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
return LibraryManager.GetItemList(query);
|
return LibraryManager.GetItemList(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
using MediaBrowser.Controller.Sorting;
|
using MediaBrowser.Controller.Sorting;
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
using MediaBrowser.Model.Providers;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
|
@ -36,6 +37,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
protected BaseItem()
|
protected BaseItem()
|
||||||
{
|
{
|
||||||
|
Keywords = new List<string>();
|
||||||
Tags = new List<string>();
|
Tags = new List<string>();
|
||||||
Genres = new List<string>();
|
Genres = new List<string>();
|
||||||
Studios = new List<string>();
|
Studios = new List<string>();
|
||||||
|
@ -69,10 +71,14 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public List<ItemImageInfo> ImageInfos { get; set; }
|
public List<ItemImageInfo> ImageInfos { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool IsVirtualItem { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the album.
|
/// Gets or sets the album.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The album.</value>
|
/// <value>The album.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public string Album { get; set; }
|
public string Album { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -810,6 +816,8 @@ namespace MediaBrowser.Controller.Entities
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public List<string> Tags { get; set; }
|
public List<string> Tags { get; set; }
|
||||||
|
|
||||||
|
public List<string> Keywords { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the home page URL.
|
/// Gets or sets the home page URL.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1031,9 +1039,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
: options;
|
: options;
|
||||||
|
|
||||||
var result = await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
|
return await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -1394,15 +1400,10 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
private bool IsVisibleViaTags(User user)
|
private bool IsVisibleViaTags(User user)
|
||||||
{
|
{
|
||||||
var hasTags = this as IHasTags;
|
var policy = user.Policy;
|
||||||
|
if (policy.BlockedTags.Any(i => Tags.Contains(i, StringComparer.OrdinalIgnoreCase)))
|
||||||
if (hasTags != null)
|
|
||||||
{
|
{
|
||||||
var policy = user.Policy;
|
return false;
|
||||||
if (policy.BlockedTags.Any(i => hasTags.Tags.Contains(i, StringComparer.OrdinalIgnoreCase)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -2214,5 +2215,10 @@ namespace MediaBrowser.Controller.Entities
|
||||||
DeleteFileLocation = false
|
DeleteFileLocation = false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual List<ExternalUrl> GetRelatedUrls()
|
||||||
|
{
|
||||||
|
return new List<ExternalUrl>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,7 +6,7 @@ using MediaBrowser.Model.Entities;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public class Book : BaseItem, IHasTags, IHasLookupInfo<BookInfo>, IHasSeries
|
public class Book : BaseItem, IHasLookupInfo<BookInfo>, IHasSeries
|
||||||
{
|
{
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override string MediaType
|
public override string MediaType
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Folder
|
/// Class Folder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Folder : BaseItem, IHasThemeMedia, IHasTags
|
public class Folder : BaseItem, IHasThemeMedia
|
||||||
{
|
{
|
||||||
public static IUserManager UserManager { get; set; }
|
public static IUserManager UserManager { get; set; }
|
||||||
public static IUserViewManager UserViewManager { get; set; }
|
public static IUserViewManager UserViewManager { get; set; }
|
||||||
|
@ -164,49 +164,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
item.DateModified = DateTime.UtcNow;
|
item.DateModified = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddChildInternal(item.Id);
|
|
||||||
|
|
||||||
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void AddChildrenInternal(List<Guid> children)
|
|
||||||
{
|
|
||||||
lock (_childrenSyncLock)
|
|
||||||
{
|
|
||||||
var newChildren = ChildIds.ToList();
|
|
||||||
newChildren.AddRange(children);
|
|
||||||
_children = newChildren.ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
protected void AddChildInternal(Guid child)
|
|
||||||
{
|
|
||||||
lock (_childrenSyncLock)
|
|
||||||
{
|
|
||||||
var childIds = ChildIds.ToList();
|
|
||||||
if (!childIds.Contains(child))
|
|
||||||
{
|
|
||||||
childIds.Add(child);
|
|
||||||
_children = childIds.ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void RemoveChildrenInternal(List<Guid> children)
|
|
||||||
{
|
|
||||||
lock (_childrenSyncLock)
|
|
||||||
{
|
|
||||||
_children = ChildIds.Except(children).ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes the child.
|
/// Removes the child.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
public void RemoveChild(BaseItem item)
|
public void RemoveChild(BaseItem item)
|
||||||
{
|
{
|
||||||
RemoveChildrenInternal(new[] { item.Id }.ToList());
|
|
||||||
|
|
||||||
item.SetParent(null);
|
item.SetParent(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,33 +207,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The children
|
|
||||||
/// </summary>
|
|
||||||
private IReadOnlyList<Guid> _children;
|
|
||||||
/// <summary>
|
|
||||||
/// The _children sync lock
|
|
||||||
/// </summary>
|
|
||||||
private readonly object _childrenSyncLock = new object();
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the actual children.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The actual children.</value>
|
|
||||||
protected virtual IEnumerable<Guid> ChildIds
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
lock (_childrenSyncLock)
|
|
||||||
{
|
|
||||||
if (_children == null)
|
|
||||||
{
|
|
||||||
_children = LoadChildren().ToList();
|
|
||||||
}
|
|
||||||
return _children.ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the actual children.
|
/// Gets the actual children.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -277,7 +216,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ChildIds.Select(LibraryManager.GetItemById).Where(i => i != null);
|
return LoadChildren().Select(LibraryManager.GetItemById).Where(i => i != null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,17 +400,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
foreach (var item in itemsRemoved)
|
foreach (var item in itemsRemoved)
|
||||||
{
|
{
|
||||||
if (item.LocationType == LocationType.Virtual ||
|
var itemLocationType = item.LocationType;
|
||||||
item.LocationType == LocationType.Remote)
|
if (itemLocationType == LocationType.Virtual ||
|
||||||
|
itemLocationType == LocationType.Remote)
|
||||||
{
|
{
|
||||||
// Don't remove these because there's no way to accurately validate them.
|
|
||||||
validChildren.Add(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (!string.IsNullOrEmpty(item.Path) && IsPathOffline(item.Path))
|
else if (!string.IsNullOrEmpty(item.Path) && IsPathOffline(item.Path))
|
||||||
{
|
{
|
||||||
await UpdateIsOffline(item, true).ConfigureAwait(false);
|
await UpdateIsOffline(item, true).ConfigureAwait(false);
|
||||||
validChildren.Add(item);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -481,8 +418,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
if (actualRemovals.Count > 0)
|
if (actualRemovals.Count > 0)
|
||||||
{
|
{
|
||||||
RemoveChildrenInternal(actualRemovals.Select(i => i.Id).ToList());
|
|
||||||
|
|
||||||
foreach (var item in actualRemovals)
|
foreach (var item in actualRemovals)
|
||||||
{
|
{
|
||||||
Logger.Debug("Removed item: " + item.Path);
|
Logger.Debug("Removed item: " + item.Path);
|
||||||
|
@ -495,8 +430,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
|
|
||||||
await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false);
|
await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
AddChildrenInternal(newItems.Select(i => i.Id).ToList());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -733,6 +666,27 @@ namespace MediaBrowser.Controller.Entities
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual int GetChildCount(User user)
|
||||||
|
{
|
||||||
|
if (LinkedChildren.Count > 0)
|
||||||
|
{
|
||||||
|
if (!(this is ICollectionFolder))
|
||||||
|
{
|
||||||
|
return GetChildren(user, true).Count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = GetItems(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
Recursive = false,
|
||||||
|
Limit = 0,
|
||||||
|
ParentId = Id
|
||||||
|
|
||||||
|
}).Result;
|
||||||
|
|
||||||
|
return result.TotalRecordCount;
|
||||||
|
}
|
||||||
|
|
||||||
public QueryResult<BaseItem> QueryRecursive(InternalItemsQuery query)
|
public QueryResult<BaseItem> QueryRecursive(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
var user = query.User;
|
var user = query.User;
|
||||||
|
@ -768,58 +722,13 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
if (!(this is ICollectionFolder))
|
if (!(this is ICollectionFolder))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to LinkedChildren");
|
Logger.Debug("Query requires post-filtering due to LinkedChildren. Type: " + GetType().Name);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var supportsUserDataQueries = ConfigurationManager.Configuration.SchemaVersion >= 76;
|
|
||||||
|
|
||||||
if (query.SortBy != null && query.SortBy.Length > 0)
|
if (query.SortBy != null && query.SortBy.Length > 0)
|
||||||
{
|
{
|
||||||
if (!supportsUserDataQueries)
|
|
||||||
{
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.PlayCount");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsPlayed");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsUnplayed");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ConfigurationManager.Configuration.SchemaVersion < 79)
|
|
||||||
{
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.Artist, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.Artist");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
|
if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
|
||||||
|
@ -840,11 +749,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.Metascore");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Metascore");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (query.SortBy.Contains(ItemSortBy.OfficialRating, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.OfficialRating");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.Players, StringComparer.OrdinalIgnoreCase))
|
if (query.SortBy.Contains(ItemSortBy.Players, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.Players");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Players");
|
||||||
|
@ -860,11 +764,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.SeriesSortName");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.SeriesSortName");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (query.SortBy.Contains(ItemSortBy.Studio, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.Studio");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.VideoBitRate, StringComparer.OrdinalIgnoreCase))
|
if (query.SortBy.Contains(ItemSortBy.VideoBitRate, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.VideoBitRate");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.VideoBitRate");
|
||||||
|
@ -884,39 +783,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!supportsUserDataQueries)
|
|
||||||
{
|
|
||||||
if (query.IsLiked.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to IsLiked");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.IsFavoriteOrLiked.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to IsFavoriteOrLiked");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.IsFavorite.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to IsFavorite");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.IsResumable.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to IsResumable");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.IsPlayed.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to IsPlayed");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.IsInBoxSet.HasValue)
|
if (query.IsInBoxSet.HasValue)
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to IsInBoxSet");
|
Logger.Debug("Query requires post-filtering due to IsInBoxSet");
|
||||||
|
@ -930,30 +796,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.HasImdbId.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to HasImdbId");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.HasTmdbId.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to HasTmdbId");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.HasTvdbId.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to HasTvdbId");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.IsYearMismatched.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to IsYearMismatched");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.HasOfficialRating.HasValue)
|
if (query.HasOfficialRating.HasValue)
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to HasOfficialRating");
|
Logger.Debug("Query requires post-filtering due to HasOfficialRating");
|
||||||
|
@ -1003,12 +845,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.ImageTypes.Length > 0)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ImageTypes");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply studio filter
|
// Apply studio filter
|
||||||
if (query.StudioIds.Length > 0)
|
if (query.StudioIds.Length > 0)
|
||||||
{
|
{
|
||||||
|
@ -1042,12 +878,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.OfficialRatings.Length > 0)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to OfficialRatings");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.IsMissing.HasValue)
|
if (query.IsMissing.HasValue)
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to IsMissing");
|
Logger.Debug("Query requires post-filtering due to IsMissing");
|
||||||
|
@ -1066,7 +896,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UserViewBuilder.CollapseBoxSetItems(query, this, query.User))
|
if (UserViewBuilder.CollapseBoxSetItems(query, this, query.User, ConfigurationManager))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to CollapseBoxSetItems");
|
Logger.Debug("Query requires post-filtering due to CollapseBoxSetItems");
|
||||||
return true;
|
return true;
|
||||||
|
@ -1102,15 +932,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConfigurationManager.Configuration.SchemaVersion < 79)
|
|
||||||
{
|
|
||||||
if (query.ArtistNames.Length > 0)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ArtistNames");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1183,7 +1004,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)
|
protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager);
|
return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager, ConfigurationManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
||||||
|
@ -1613,60 +1434,36 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var recursiveItemCount = 0;
|
var unplayedQueryResult = GetItems(new InternalItemsQuery(user)
|
||||||
var unplayed = 0;
|
|
||||||
|
|
||||||
double totalPercentPlayed = 0;
|
|
||||||
|
|
||||||
var itemsResult = GetItems(new InternalItemsQuery(user)
|
|
||||||
{
|
{
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
IsFolder = false,
|
IsFolder = false,
|
||||||
ExcludeLocationTypes = new[] { LocationType.Virtual },
|
IsVirtualItem = false,
|
||||||
EnableTotalRecordCount = false
|
EnableTotalRecordCount = true,
|
||||||
|
Limit = 0,
|
||||||
|
IsPlayed = false
|
||||||
|
|
||||||
}).Result;
|
}).Result;
|
||||||
|
|
||||||
var children = itemsResult.Items;
|
var allItemsQueryResult = GetItems(new InternalItemsQuery(user)
|
||||||
|
|
||||||
// Loop through each recursive child
|
|
||||||
foreach (var child in children)
|
|
||||||
{
|
{
|
||||||
recursiveItemCount++;
|
Recursive = true,
|
||||||
|
IsFolder = false,
|
||||||
|
IsVirtualItem = false,
|
||||||
|
EnableTotalRecordCount = true,
|
||||||
|
Limit = 0
|
||||||
|
|
||||||
var isUnplayed = true;
|
}).Result;
|
||||||
|
|
||||||
var itemUserData = UserDataManager.GetUserData(user, child);
|
double recursiveItemCount = allItemsQueryResult.TotalRecordCount;
|
||||||
|
double unplayedCount = unplayedQueryResult.TotalRecordCount;
|
||||||
// Incrememt totalPercentPlayed
|
|
||||||
if (itemUserData != null)
|
|
||||||
{
|
|
||||||
if (itemUserData.Played)
|
|
||||||
{
|
|
||||||
totalPercentPlayed += 100;
|
|
||||||
|
|
||||||
isUnplayed = false;
|
|
||||||
}
|
|
||||||
else if (itemUserData.PlaybackPositionTicks > 0 && child.RunTimeTicks.HasValue && child.RunTimeTicks.Value > 0)
|
|
||||||
{
|
|
||||||
double itemPercent = itemUserData.PlaybackPositionTicks;
|
|
||||||
itemPercent /= child.RunTimeTicks.Value;
|
|
||||||
totalPercentPlayed += itemPercent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isUnplayed)
|
|
||||||
{
|
|
||||||
unplayed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dto.UnplayedItemCount = unplayed;
|
|
||||||
|
|
||||||
if (recursiveItemCount > 0)
|
if (recursiveItemCount > 0)
|
||||||
{
|
{
|
||||||
dto.PlayedPercentage = totalPercentPlayed / recursiveItemCount;
|
var unplayedPercentage = (unplayedCount / recursiveItemCount) * 100;
|
||||||
|
dto.PlayedPercentage = 100 - unplayedPercentage;
|
||||||
dto.Played = dto.PlayedPercentage.Value >= 100;
|
dto.Played = dto.PlayedPercentage.Value >= 100;
|
||||||
|
dto.UnplayedItemCount = unplayedQueryResult.TotalRecordCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ using System.Linq;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public class Game : BaseItem, IHasTrailers, IHasThemeMedia, IHasTags, IHasScreenshots, ISupportsPlaceHolders, IHasLookupInfo<GameInfo>
|
public class Game : BaseItem, IHasTrailers, IHasThemeMedia, IHasScreenshots, ISupportsPlaceHolders, IHasLookupInfo<GameInfo>
|
||||||
{
|
{
|
||||||
public List<Guid> ThemeSongIds { get; set; }
|
public List<Guid> ThemeSongIds { get; set; }
|
||||||
public List<Guid> ThemeVideoIds { get; set; }
|
public List<Guid> ThemeVideoIds { get; set; }
|
||||||
|
|
|
@ -19,6 +19,8 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public User User { get; set; }
|
public User User { get; set; }
|
||||||
|
|
||||||
|
public BaseItem SimilarTo { get; set; }
|
||||||
|
|
||||||
public bool? IsFolder { get; set; }
|
public bool? IsFolder { get; set; }
|
||||||
public bool? IsFavorite { get; set; }
|
public bool? IsFavorite { get; set; }
|
||||||
public bool? IsFavoriteOrLiked { get; set; }
|
public bool? IsFavoriteOrLiked { get; set; }
|
||||||
|
@ -33,6 +35,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public string[] ExcludeTags { get; set; }
|
public string[] ExcludeTags { get; set; }
|
||||||
public string[] ExcludeInheritedTags { get; set; }
|
public string[] ExcludeInheritedTags { get; set; }
|
||||||
public string[] Genres { get; set; }
|
public string[] Genres { get; set; }
|
||||||
|
public string[] Keywords { get; set; }
|
||||||
|
|
||||||
public bool? IsMissing { get; set; }
|
public bool? IsMissing { get; set; }
|
||||||
public bool? IsUnaired { get; set; }
|
public bool? IsUnaired { get; set; }
|
||||||
|
@ -52,6 +55,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public string Person { get; set; }
|
public string Person { get; set; }
|
||||||
public string[] PersonIds { get; set; }
|
public string[] PersonIds { get; set; }
|
||||||
public string[] ItemIds { get; set; }
|
public string[] ItemIds { get; set; }
|
||||||
|
public string[] ExcludeItemIds { get; set; }
|
||||||
public string AdjacentTo { get; set; }
|
public string AdjacentTo { get; set; }
|
||||||
public string[] PersonTypes { get; set; }
|
public string[] PersonTypes { get; set; }
|
||||||
|
|
||||||
|
@ -60,7 +64,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public bool? IsInBoxSet { get; set; }
|
public bool? IsInBoxSet { get; set; }
|
||||||
public bool? IsLocked { get; set; }
|
public bool? IsLocked { get; set; }
|
||||||
public bool? IsPlaceHolder { get; set; }
|
public bool? IsPlaceHolder { get; set; }
|
||||||
public bool? IsYearMismatched { get; set; }
|
|
||||||
|
|
||||||
public bool? HasImdbId { get; set; }
|
public bool? HasImdbId { get; set; }
|
||||||
public bool? HasOverview { get; set; }
|
public bool? HasOverview { get; set; }
|
||||||
|
@ -107,6 +110,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
internal List<Guid> ItemIdsFromPersonFilters { get; set; }
|
internal List<Guid> ItemIdsFromPersonFilters { get; set; }
|
||||||
public int? ParentIndexNumber { get; set; }
|
public int? ParentIndexNumber { get; set; }
|
||||||
|
public int? ParentIndexNumberNotEquals { get; set; }
|
||||||
public int? IndexNumber { get; set; }
|
public int? IndexNumber { get; set; }
|
||||||
public int? MinParentalRating { get; set; }
|
public int? MinParentalRating { get; set; }
|
||||||
public int? MaxParentalRating { get; set; }
|
public int? MaxParentalRating { get; set; }
|
||||||
|
@ -114,6 +118,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public bool? IsCurrentSchema { get; set; }
|
public bool? IsCurrentSchema { get; set; }
|
||||||
public bool? HasDeadParentId { get; set; }
|
public bool? HasDeadParentId { get; set; }
|
||||||
public bool? IsOffline { get; set; }
|
public bool? IsOffline { get; set; }
|
||||||
|
public bool? IsVirtualItem { get; set; }
|
||||||
|
|
||||||
public Guid? ParentId { get; set; }
|
public Guid? ParentId { get; set; }
|
||||||
public string[] AncestorIds { get; set; }
|
public string[] AncestorIds { get; set; }
|
||||||
|
@ -137,6 +142,8 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public bool GroupByPresentationUniqueKey { get; set; }
|
public bool GroupByPresentationUniqueKey { get; set; }
|
||||||
public bool EnableTotalRecordCount { get; set; }
|
public bool EnableTotalRecordCount { get; set; }
|
||||||
public bool ForceDirect { get; set; }
|
public bool ForceDirect { get; set; }
|
||||||
|
public Dictionary<string, string> ExcludeProviderIds { get; set; }
|
||||||
|
public string GroupByAncestorOfType { get; set; }
|
||||||
|
|
||||||
public InternalItemsQuery()
|
public InternalItemsQuery()
|
||||||
{
|
{
|
||||||
|
@ -145,12 +152,14 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
AlbumNames = new string[] { };
|
AlbumNames = new string[] { };
|
||||||
ArtistNames = new string[] { };
|
ArtistNames = new string[] { };
|
||||||
|
ExcludeProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
BlockUnratedItems = new UnratedItem[] { };
|
BlockUnratedItems = new UnratedItem[] { };
|
||||||
Tags = new string[] { };
|
Tags = new string[] { };
|
||||||
OfficialRatings = new string[] { };
|
OfficialRatings = new string[] { };
|
||||||
SortBy = new string[] { };
|
SortBy = new string[] { };
|
||||||
MediaTypes = new string[] { };
|
MediaTypes = new string[] { };
|
||||||
|
Keywords = new string[] { };
|
||||||
IncludeItemTypes = new string[] { };
|
IncludeItemTypes = new string[] { };
|
||||||
ExcludeItemTypes = new string[] { };
|
ExcludeItemTypes = new string[] { };
|
||||||
Genres = new string[] { };
|
Genres = new string[] { };
|
||||||
|
@ -164,6 +173,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
PersonIds = new string[] { };
|
PersonIds = new string[] { };
|
||||||
ChannelIds = new string[] { };
|
ChannelIds = new string[] { };
|
||||||
ItemIds = new string[] { };
|
ItemIds = new string[] { };
|
||||||
|
ExcludeItemIds = new string[] { };
|
||||||
AncestorIds = new string[] { };
|
AncestorIds = new string[] { };
|
||||||
TopParentIds = new string[] { };
|
TopParentIds = new string[] { };
|
||||||
ExcludeTags = new string[] { };
|
ExcludeTags = new string[] { };
|
||||||
|
|
|
@ -1,21 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public interface IHasKeywords
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the keywords.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The keywords.</value>
|
|
||||||
List<string> Keywords { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class KeywordExtensions
|
public static class KeywordExtensions
|
||||||
{
|
{
|
||||||
public static void AddKeyword(this IHasKeywords item, string name)
|
public static void AddKeyword(this BaseItem item, string name)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
{
|
{
|
|
@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class BoxSet
|
/// Class BoxSet
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IHasShares
|
public class BoxSet : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IHasShares
|
||||||
{
|
{
|
||||||
public List<Share> Shares { get; set; }
|
public List<Share> Shares { get; set; }
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
RemoteTrailerIds = new List<Guid>();
|
RemoteTrailerIds = new List<Guid>();
|
||||||
|
|
||||||
DisplayOrder = ItemSortBy.PremiereDate;
|
DisplayOrder = ItemSortBy.PremiereDate;
|
||||||
Keywords = new List<string>();
|
|
||||||
Shares = new List<Share>();
|
Shares = new List<Share>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,12 +46,6 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
/// <value>The remote trailers.</value>
|
/// <value>The remote trailers.</value>
|
||||||
public List<MediaUrl> RemoteTrailers { get; set; }
|
public List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the tags.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The tags.</value>
|
|
||||||
public List<string> Keywords { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the display order.
|
/// Gets or sets the display order.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -8,13 +8,14 @@ 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.Providers;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.Movies
|
namespace MediaBrowser.Controller.Entities.Movies
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Movie
|
/// Class Movie
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Movie : Video, IHasCriticRating, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping, IHasOriginalTitle
|
public class Movie : Video, IHasCriticRating, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping, IHasOriginalTitle
|
||||||
{
|
{
|
||||||
public List<Guid> SpecialFeatureIds { get; set; }
|
public List<Guid> SpecialFeatureIds { get; set; }
|
||||||
|
|
||||||
|
@ -31,7 +32,6 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
ThemeSongIds = new List<Guid>();
|
ThemeSongIds = new List<Guid>();
|
||||||
ThemeVideoIds = new List<Guid>();
|
ThemeVideoIds = new List<Guid>();
|
||||||
Taglines = new List<string>();
|
Taglines = new List<string>();
|
||||||
Keywords = new List<string>();
|
|
||||||
ProductionLocations = new List<string>();
|
ProductionLocations = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,6 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
|
|
||||||
public List<Guid> LocalTrailerIds { get; set; }
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
public List<Guid> RemoteTrailerIds { get; set; }
|
public List<Guid> RemoteTrailerIds { get; set; }
|
||||||
public List<string> Keywords { get; set; }
|
|
||||||
|
|
||||||
public List<MediaUrl> RemoteTrailers { get; set; }
|
public List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
|
|
||||||
|
@ -163,5 +162,22 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
|
|
||||||
return hasChanges;
|
return hasChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override List<ExternalUrl> GetRelatedUrls()
|
||||||
|
{
|
||||||
|
var list = base.GetRelatedUrls();
|
||||||
|
|
||||||
|
var imdbId = this.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
if (!string.IsNullOrWhiteSpace(imdbId))
|
||||||
|
{
|
||||||
|
list.Add(new ExternalUrl
|
||||||
|
{
|
||||||
|
Name = "Trakt",
|
||||||
|
Url = string.Format("https://trakt.tv/movies/{0}", imdbId)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public class Photo : BaseItem, IHasTags, IHasTaglines
|
public class Photo : BaseItem, IHasTaglines
|
||||||
{
|
{
|
||||||
public List<string> Taglines { get; set; }
|
public List<string> Taglines { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Studio
|
/// Class Studio
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Studio : BaseItem, IItemByName, IHasTags
|
public class Studio : BaseItem, IItemByName
|
||||||
{
|
{
|
||||||
public override List<string> GetUserDataKeys()
|
public override List<string> GetUserDataKeys()
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,13 +11,25 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Episode
|
/// Class Episode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Episode : Video, IHasLookupInfo<EpisodeInfo>, IHasSeries
|
public class Episode : Video, IHasTrailers, IHasLookupInfo<EpisodeInfo>, IHasSeries
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Gets the season in which it aired.
|
public Episode()
|
||||||
/// </summary>
|
{
|
||||||
/// <value>The aired season.</value>
|
RemoteTrailers = new List<MediaUrl>();
|
||||||
public int? AirsBeforeSeasonNumber { get; set; }
|
LocalTrailerIds = new List<Guid>();
|
||||||
|
RemoteTrailerIds = new List<Guid>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
|
public List<Guid> RemoteTrailerIds { get; set; }
|
||||||
|
public List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the season in which it aired.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The aired season.</value>
|
||||||
|
public int? AirsBeforeSeasonNumber { get; set; }
|
||||||
public int? AirsAfterSeasonNumber { get; set; }
|
public int? AirsAfterSeasonNumber { get; set; }
|
||||||
public int? AirsBeforeEpisodeNumber { get; set; }
|
public int? AirsBeforeEpisodeNumber { get; set; }
|
||||||
|
|
||||||
|
@ -96,7 +108,13 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
var series = Series;
|
var series = Series;
|
||||||
if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
|
if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
|
||||||
{
|
{
|
||||||
list.InsertRange(0, series.GetUserDataKeys().Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000")));
|
var seriesUserDataKeys = series.GetUserDataKeys();
|
||||||
|
var take = seriesUserDataKeys.Count;
|
||||||
|
if (seriesUserDataKeys.Count > 1)
|
||||||
|
{
|
||||||
|
take--;
|
||||||
|
}
|
||||||
|
list.InsertRange(0, seriesUserDataKeys.Take(take).Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000")));
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
|
|
|
@ -75,6 +75,11 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int GetChildCount(User user)
|
||||||
|
{
|
||||||
|
return GetChildren(user, true).Count();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This Episode's Series Instance
|
/// This Episode's Series Instance
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -128,39 +133,16 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
|
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool RequiresRefresh()
|
|
||||||
{
|
|
||||||
var result = base.RequiresRefresh();
|
|
||||||
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
if (!IsVirtualItem.HasValue)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public bool? IsVirtualItem { get; set; }
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsMissingSeason
|
public bool IsMissingSeason
|
||||||
{
|
{
|
||||||
get { return (IsVirtualItem ?? DetectIsVirtualItem()) && !IsUnaired; }
|
get { return (IsVirtualItem) && !IsUnaired; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsVirtualUnaired
|
public bool IsVirtualUnaired
|
||||||
{
|
{
|
||||||
get { return (IsVirtualItem ?? DetectIsVirtualItem()) && IsUnaired; }
|
get { return (IsVirtualItem) && IsUnaired; }
|
||||||
}
|
|
||||||
|
|
||||||
private bool DetectIsVirtualItem()
|
|
||||||
{
|
|
||||||
return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.LocationType == LocationType.Virtual);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -196,52 +178,17 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
{
|
{
|
||||||
var config = user.Configuration;
|
var config = user.Configuration;
|
||||||
|
|
||||||
return GetEpisodes(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
|
return GetEpisodes(Series, user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Episode> GetEpisodes(User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
public IEnumerable<Episode> GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
||||||
{
|
{
|
||||||
var series = Series;
|
return GetEpisodes(series, user, includeMissingEpisodes, includeVirtualUnairedEpisodes, null);
|
||||||
|
}
|
||||||
|
|
||||||
if (IndexNumber.HasValue && series != null)
|
public IEnumerable<Episode> GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes)
|
||||||
{
|
{
|
||||||
return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes);
|
return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes, allSeriesEpisodes);
|
||||||
}
|
|
||||||
|
|
||||||
var episodes = GetRecursiveChildren(user)
|
|
||||||
.OfType<Episode>();
|
|
||||||
|
|
||||||
if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
|
|
||||||
{
|
|
||||||
var seasonNumber = IndexNumber;
|
|
||||||
var list = episodes.ToList();
|
|
||||||
|
|
||||||
if (seasonNumber.HasValue)
|
|
||||||
{
|
|
||||||
list.AddRange(series.GetRecursiveChildren(user).OfType<Episode>()
|
|
||||||
.Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
list.AddRange(series.GetRecursiveChildren(user).OfType<Episode>()
|
|
||||||
.Where(i => !i.ParentIndexNumber.HasValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
episodes = list.DistinctBy(i => i.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!includeMissingEpisodes)
|
|
||||||
{
|
|
||||||
episodes = episodes.Where(i => !i.IsMissingEpisode);
|
|
||||||
}
|
|
||||||
if (!includeVirtualUnairedEpisodes)
|
|
||||||
{
|
|
||||||
episodes = episodes.Where(i => !i.IsVirtualUnaired);
|
|
||||||
}
|
|
||||||
|
|
||||||
return LibraryManager
|
|
||||||
.Sort(episodes, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending)
|
|
||||||
.Cast<Episode>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Episode> GetEpisodes()
|
public IEnumerable<Episode> GetEpisodes()
|
||||||
|
|
|
@ -9,6 +9,7 @@ using System.Linq;
|
||||||
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.Providers;
|
||||||
using MoreLinq;
|
using MoreLinq;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.TV
|
namespace MediaBrowser.Controller.Entities.TV
|
||||||
|
@ -30,7 +31,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
RemoteTrailers = new List<MediaUrl>();
|
RemoteTrailers = new List<MediaUrl>();
|
||||||
LocalTrailerIds = new List<Guid>();
|
LocalTrailerIds = new List<Guid>();
|
||||||
RemoteTrailerIds = new List<Guid>();
|
RemoteTrailerIds = new List<Guid>();
|
||||||
DisplaySpecialsWithSeasons = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -57,8 +57,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DisplaySpecialsWithSeasons { get; set; }
|
|
||||||
|
|
||||||
public List<Guid> LocalTrailerIds { get; set; }
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
public List<Guid> RemoteTrailerIds { get; set; }
|
public List<Guid> RemoteTrailerIds { get; set; }
|
||||||
|
|
||||||
|
@ -94,10 +92,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return GetRecursiveChildren(i => i is Episode)
|
return DateLastMediaAdded ?? DateTime.MinValue;
|
||||||
.Select(i => i.DateCreated)
|
|
||||||
.OrderByDescending(i => i)
|
|
||||||
.FirstOrDefault();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,14 +101,30 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (EnablePooling())
|
var userdatakeys = GetUserDataKeys();
|
||||||
|
|
||||||
|
if (userdatakeys.Count > 1)
|
||||||
{
|
{
|
||||||
return GetUserDataKeys().First();
|
return userdatakeys[0];
|
||||||
}
|
}
|
||||||
return base.PresentationUniqueKey;
|
return base.PresentationUniqueKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int GetChildCount(User user)
|
||||||
|
{
|
||||||
|
var result = LibraryManager.GetItemsResult(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
AncestorWithPresentationUniqueKey = PresentationUniqueKey,
|
||||||
|
IncludeItemTypes = new[] { typeof(Season).Name },
|
||||||
|
SortBy = new[] { ItemSortBy.SortName },
|
||||||
|
IsVirtualItem = false,
|
||||||
|
Limit = 0
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.TotalRecordCount;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user data key.
|
/// Gets the user data key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -182,27 +193,32 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
|
|
||||||
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
|
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
|
if (query.User == null)
|
||||||
|
{
|
||||||
|
return base.GetItemsInternal(query);
|
||||||
|
}
|
||||||
|
|
||||||
var user = query.User;
|
var user = query.User;
|
||||||
|
|
||||||
|
if (query.Recursive)
|
||||||
|
{
|
||||||
|
query.AncestorWithPresentationUniqueKey = PresentationUniqueKey;
|
||||||
|
if (query.SortBy.Length == 0)
|
||||||
|
{
|
||||||
|
query.SortBy = new[] { ItemSortBy.SortName };
|
||||||
|
}
|
||||||
|
if (query.IncludeItemTypes.Length == 0)
|
||||||
|
{
|
||||||
|
query.IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name };
|
||||||
|
}
|
||||||
|
query.IsVirtualItem = false;
|
||||||
|
return Task.FromResult(LibraryManager.GetItemsResult(query));
|
||||||
|
}
|
||||||
|
|
||||||
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
|
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
|
||||||
|
|
||||||
IEnumerable<BaseItem> items;
|
var items = GetSeasons(user).Where(filter);
|
||||||
|
|
||||||
if (query.User == null)
|
|
||||||
{
|
|
||||||
items = query.Recursive
|
|
||||||
? GetRecursiveChildren(filter)
|
|
||||||
: Children.Where(filter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
items = query.Recursive
|
|
||||||
? GetSeasons(user).Cast<BaseItem>().Concat(GetEpisodes(user)).Where(filter)
|
|
||||||
: GetSeasons(user).Where(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = PostFilterAndSort(items, query);
|
var result = PostFilterAndSort(items, query);
|
||||||
|
|
||||||
return Task.FromResult(result);
|
return Task.FromResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,33 +226,13 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
{
|
{
|
||||||
IEnumerable<Season> seasons;
|
IEnumerable<Season> seasons;
|
||||||
|
|
||||||
if (EnablePooling())
|
seasons = LibraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user)
|
AncestorWithPresentationUniqueKey = PresentationUniqueKey,
|
||||||
{
|
IncludeItemTypes = new[] { typeof(Season).Name },
|
||||||
PresentationUniqueKey = PresentationUniqueKey,
|
SortBy = new[] { ItemSortBy.SortName }
|
||||||
IncludeItemTypes = new[] { typeof(Series).Name }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (seriesIds.Count > 1)
|
}).Cast<Season>();
|
||||||
{
|
|
||||||
seasons = LibraryManager.GetItemList(new InternalItemsQuery(user)
|
|
||||||
{
|
|
||||||
AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(),
|
|
||||||
IncludeItemTypes = new[] { typeof(Season).Name },
|
|
||||||
SortBy = new[] { ItemSortBy.SortName }
|
|
||||||
|
|
||||||
}).Cast<Season>();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
seasons = LibraryManager.Sort(base.GetChildren(user, true), user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).OfType<Season>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
seasons = LibraryManager.Sort(base.GetChildren(user, true), user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).OfType<Season>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!includeMissingSeasons)
|
if (!includeMissingSeasons)
|
||||||
{
|
{
|
||||||
|
@ -259,8 +255,18 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
|
|
||||||
public IEnumerable<Episode> GetEpisodes(User user, bool includeMissing, bool includeVirtualUnaired)
|
public IEnumerable<Episode> GetEpisodes(User user, bool includeMissing, bool includeVirtualUnaired)
|
||||||
{
|
{
|
||||||
var allEpisodes = GetSeasons(user, true, true)
|
var allItems = LibraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
.SelectMany(i => i.GetEpisodes(user, includeMissing, includeVirtualUnaired))
|
{
|
||||||
|
AncestorWithPresentationUniqueKey = PresentationUniqueKey,
|
||||||
|
IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name },
|
||||||
|
SortBy = new[] { ItemSortBy.SortName }
|
||||||
|
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
var allSeriesEpisodes = allItems.OfType<Episode>().ToList();
|
||||||
|
|
||||||
|
var allEpisodes = allItems.OfType<Season>()
|
||||||
|
.SelectMany(i => i.GetEpisodes(this, user, includeMissing, includeVirtualUnaired, allSeriesEpisodes))
|
||||||
.Reverse()
|
.Reverse()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
@ -283,9 +289,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
var totalItems = seasons.Count + otherItems.Count;
|
var totalItems = seasons.Count + otherItems.Count;
|
||||||
var numComplete = 0;
|
var numComplete = 0;
|
||||||
|
|
||||||
refreshOptions = new MetadataRefreshOptions(refreshOptions);
|
|
||||||
refreshOptions.IsPostRecursiveRefresh = true;
|
|
||||||
|
|
||||||
// Refresh current item
|
// Refresh current item
|
||||||
await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -315,7 +318,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
&& refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh
|
&& refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh
|
||||||
&& !refreshOptions.ReplaceAllMetadata
|
&& !refreshOptions.ReplaceAllMetadata
|
||||||
&& episode.IsMissingEpisode
|
&& episode.IsMissingEpisode
|
||||||
&& episode.LocationType == Model.Entities.LocationType.Virtual
|
&& episode.LocationType == LocationType.Virtual
|
||||||
&& episode.PremiereDate.HasValue
|
&& episode.PremiereDate.HasValue
|
||||||
&& (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30)
|
&& (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30)
|
||||||
{
|
{
|
||||||
|
@ -333,6 +336,8 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
progress.Report(percent * 100);
|
progress.Report(percent * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refreshOptions = new MetadataRefreshOptions(refreshOptions);
|
||||||
|
refreshOptions.IsPostRecursiveRefresh = true;
|
||||||
await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
|
await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
progress.Report(100);
|
progress.Report(100);
|
||||||
|
@ -345,50 +350,32 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
return GetEpisodes(user, season, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
|
return GetEpisodes(user, season, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool EnablePooling()
|
private IEnumerable<Episode> GetAllEpisodes(User user)
|
||||||
{
|
{
|
||||||
return false;
|
return LibraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
AncestorWithPresentationUniqueKey = PresentationUniqueKey,
|
||||||
|
IncludeItemTypes = new[] { typeof(Episode).Name },
|
||||||
|
SortBy = new[] { ItemSortBy.SortName }
|
||||||
|
|
||||||
|
}).Cast<Episode>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
||||||
{
|
{
|
||||||
IEnumerable<Episode> episodes;
|
IEnumerable<Episode> episodes = GetAllEpisodes(user);
|
||||||
|
|
||||||
if (EnablePooling())
|
return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes)
|
||||||
|
{
|
||||||
|
if (allSeriesEpisodes == null)
|
||||||
{
|
{
|
||||||
var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user)
|
return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes);
|
||||||
{
|
|
||||||
PresentationUniqueKey = PresentationUniqueKey,
|
|
||||||
IncludeItemTypes = new[] { typeof(Series).Name }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (seriesIds.Count > 1)
|
|
||||||
{
|
|
||||||
episodes = LibraryManager.GetItemList(new InternalItemsQuery(user)
|
|
||||||
{
|
|
||||||
AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(),
|
|
||||||
IncludeItemTypes = new[] { typeof(Episode).Name },
|
|
||||||
SortBy = new[] { ItemSortBy.SortName }
|
|
||||||
|
|
||||||
}).Cast<Episode>();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
episodes = GetRecursiveChildren(user, new InternalItemsQuery(user)
|
|
||||||
{
|
|
||||||
IncludeItemTypes = new[] { typeof(Episode).Name }
|
|
||||||
}).Cast<Episode>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
episodes = GetRecursiveChildren(user, new InternalItemsQuery(user)
|
|
||||||
{
|
|
||||||
IncludeItemTypes = new[] { typeof(Episode).Name }
|
|
||||||
}).Cast<Episode>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
episodes = FilterEpisodesBySeason(episodes, parentSeason, DisplaySpecialsWithSeasons);
|
var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons);
|
||||||
|
|
||||||
if (!includeMissingEpisodes)
|
if (!includeMissingEpisodes)
|
||||||
{
|
{
|
||||||
|
@ -436,38 +423,31 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, Season parentSeason, bool includeSpecials)
|
public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, Season parentSeason, bool includeSpecials)
|
||||||
{
|
{
|
||||||
var seasonNumber = parentSeason.IndexNumber;
|
var seasonNumber = parentSeason.IndexNumber;
|
||||||
if (!includeSpecials || (seasonNumber.HasValue && seasonNumber.Value == 0))
|
var seasonPresentationKey = parentSeason.PresentationUniqueKey;
|
||||||
|
|
||||||
|
var supportSpecialsInSeason = includeSpecials && seasonNumber.HasValue && seasonNumber.Value != 0;
|
||||||
|
|
||||||
|
return episodes.Where(episode =>
|
||||||
{
|
{
|
||||||
var seasonPresentationKey = parentSeason.PresentationUniqueKey;
|
var currentSeasonNumber = supportSpecialsInSeason ? episode.AiredSeasonNumber : episode.ParentIndexNumber;
|
||||||
|
if (currentSeasonNumber.HasValue && seasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber.Value)
|
||||||
return episodes.Where(i =>
|
|
||||||
{
|
{
|
||||||
if ((i.ParentIndexNumber ?? -1) == seasonNumber)
|
return true;
|
||||||
{
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var season = i.Season;
|
if (!currentSeasonNumber.HasValue && !seasonNumber.HasValue && parentSeason.LocationType == LocationType.Virtual)
|
||||||
return season != null && string.Equals(season.PresentationUniqueKey, seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var seasonPresentationKey = parentSeason.PresentationUniqueKey;
|
|
||||||
|
|
||||||
return episodes.Where(episode =>
|
|
||||||
{
|
{
|
||||||
var currentSeasonNumber = episode.AiredSeasonNumber;
|
return true;
|
||||||
|
}
|
||||||
if (currentSeasonNumber.HasValue && seasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber.Value)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!episode.ParentIndexNumber.HasValue)
|
||||||
|
{
|
||||||
var season = episode.Season;
|
var season = episode.Season;
|
||||||
return season != null && string.Equals(season.PresentationUniqueKey, seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
|
return season != null && string.Equals(season.PresentationUniqueKey, seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||||
|
@ -508,5 +488,22 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
|
|
||||||
return hasChanges;
|
return hasChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override List<ExternalUrl> GetRelatedUrls()
|
||||||
|
{
|
||||||
|
var list = base.GetRelatedUrls();
|
||||||
|
|
||||||
|
var imdbId = this.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
if (!string.IsNullOrWhiteSpace(imdbId))
|
||||||
|
{
|
||||||
|
list.Add(new ExternalUrl
|
||||||
|
{
|
||||||
|
Name = "Trakt",
|
||||||
|
Url = string.Format("https://trakt.tv/shows/{0}", imdbId)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Interface IHasTags
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasTags
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the tags.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The tags.</value>
|
|
||||||
List<string> Tags { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TagExtensions
|
public static class TagExtensions
|
||||||
{
|
{
|
||||||
public static void AddTag(this IHasTags item, string name)
|
public static void AddTag(this BaseItem item, string name)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
{
|
{
|
|
@ -5,13 +5,14 @@ using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
|
using MediaBrowser.Model.Providers;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Trailer
|
/// Class Trailer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasOriginalTitle, IHasLookupInfo<TrailerInfo>
|
public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasTaglines, IHasMetascore, IHasOriginalTitle, IHasLookupInfo<TrailerInfo>
|
||||||
{
|
{
|
||||||
public List<string> ProductionLocations { get; set; }
|
public List<string> ProductionLocations { get; set; }
|
||||||
|
|
||||||
|
@ -30,8 +31,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public List<MediaUrl> RemoteTrailers { get; set; }
|
public List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
|
|
||||||
public List<string> Keywords { get; set; }
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsLocalTrailer
|
public bool IsLocalTrailer
|
||||||
{
|
{
|
||||||
|
@ -110,5 +109,22 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
return hasChanges;
|
return hasChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override List<ExternalUrl> GetRelatedUrls()
|
||||||
|
{
|
||||||
|
var list = base.GetRelatedUrls();
|
||||||
|
|
||||||
|
var imdbId = this.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
if (!string.IsNullOrWhiteSpace(imdbId))
|
||||||
|
{
|
||||||
|
list.Add(new ExternalUrl
|
||||||
|
{
|
||||||
|
Name = "Trakt",
|
||||||
|
Url = string.Format("https://trakt.tv/movies/{0}", imdbId)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,11 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return PostFilterAndSort(result.Where(filter), query);
|
return PostFilterAndSort(result.Where(filter), query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int GetChildCount(User user)
|
||||||
|
{
|
||||||
|
return GetChildren(user, true).Count();
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
protected override bool SupportsShortcutChildren
|
protected override bool SupportsShortcutChildren
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,6 +45,11 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int GetChildCount(User user)
|
||||||
|
{
|
||||||
|
return GetChildren(user, true).Count();
|
||||||
|
}
|
||||||
|
|
||||||
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
|
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
var parent = this as Folder;
|
var parent = this as Folder;
|
||||||
|
@ -58,7 +63,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
parent = LibraryManager.GetItemById(ParentId) as Folder ?? parent;
|
parent = LibraryManager.GetItemById(ParentId) as Folder ?? parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, CollectionManager, PlaylistManager)
|
return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, ConfigurationManager, PlaylistManager)
|
||||||
.GetUserItems(parent, this, ViewType, query);
|
.GetUserItems(parent, this, ViewType, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Model.Configuration;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
|
@ -30,10 +32,10 @@ namespace MediaBrowser.Controller.Entities
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IUserDataManager _userDataManager;
|
private readonly IUserDataManager _userDataManager;
|
||||||
private readonly ITVSeriesManager _tvSeriesManager;
|
private readonly ITVSeriesManager _tvSeriesManager;
|
||||||
private readonly ICollectionManager _collectionManager;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IPlaylistManager _playlistManager;
|
private readonly IPlaylistManager _playlistManager;
|
||||||
|
|
||||||
public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, ICollectionManager collectionManager, IPlaylistManager playlistManager)
|
public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, IServerConfigurationManager config, IPlaylistManager playlistManager)
|
||||||
{
|
{
|
||||||
_userViewManager = userViewManager;
|
_userViewManager = userViewManager;
|
||||||
_liveTvManager = liveTvManager;
|
_liveTvManager = liveTvManager;
|
||||||
|
@ -42,7 +44,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_userDataManager = userDataManager;
|
_userDataManager = userDataManager;
|
||||||
_tvSeriesManager = tvSeriesManager;
|
_tvSeriesManager = tvSeriesManager;
|
||||||
_collectionManager = collectionManager;
|
_config = config;
|
||||||
_playlistManager = playlistManager;
|
_playlistManager = playlistManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +161,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return await GetTvGenres(queryParent, user, query).ConfigureAwait(false);
|
return await GetTvGenres(queryParent, user, query).ConfigureAwait(false);
|
||||||
|
|
||||||
case SpecialFolder.TvGenre:
|
case SpecialFolder.TvGenre:
|
||||||
return await GetTvGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
|
return GetTvGenreItems(queryParent, displayParent, user, query);
|
||||||
|
|
||||||
case SpecialFolder.TvResume:
|
case SpecialFolder.TvResume:
|
||||||
return GetTvResume(queryParent, user, query);
|
return GetTvResume(queryParent, user, query);
|
||||||
|
@ -332,13 +334,14 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
var items = parent.QueryRecursive(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
ParentId = parent.Id,
|
ParentId = parent.Id,
|
||||||
IncludeItemTypes = new[] { typeof(Audio.Audio).Name }
|
IncludeItemTypes = new[] { typeof(Audio.Audio).Name },
|
||||||
|
EnableTotalRecordCount = false
|
||||||
|
|
||||||
}).Cast<IHasAlbumArtist>();
|
}).Items.Cast<IHasAlbumArtist>();
|
||||||
|
|
||||||
var artists = _libraryManager.GetAlbumArtists(items);
|
var artists = _libraryManager.GetAlbumArtists(items);
|
||||||
|
|
||||||
|
@ -347,13 +350,14 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
private QueryResult<BaseItem> GetMusicArtists(Folder parent, User user, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetMusicArtists(Folder parent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
var items = parent.QueryRecursive(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
ParentId = parent.Id,
|
ParentId = parent.Id,
|
||||||
IncludeItemTypes = new[] { typeof(Audio.Audio).Name, typeof(MusicVideo).Name }
|
IncludeItemTypes = new[] { typeof(Audio.Audio).Name, typeof(MusicVideo).Name },
|
||||||
|
EnableTotalRecordCount = false
|
||||||
|
|
||||||
}).Cast<IHasArtist>();
|
}).Items.Cast<IHasArtist>();
|
||||||
|
|
||||||
var artists = _libraryManager.GetArtists(items);
|
var artists = _libraryManager.GetArtists(items);
|
||||||
|
|
||||||
|
@ -362,13 +366,14 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
private QueryResult<BaseItem> GetFavoriteArtists(Folder parent, User user, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetFavoriteArtists(Folder parent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
var items = parent.QueryRecursive(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
ParentId = parent.Id,
|
ParentId = parent.Id,
|
||||||
IncludeItemTypes = new[] { typeof(Audio.Audio).Name }
|
IncludeItemTypes = new[] { typeof(Audio.Audio).Name },
|
||||||
|
EnableTotalRecordCount = false
|
||||||
|
|
||||||
}).Cast<IHasAlbumArtist>();
|
}).Items.Cast<IHasAlbumArtist>();
|
||||||
|
|
||||||
var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user, i).IsFavorite);
|
var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user, i).IsFavorite);
|
||||||
|
|
||||||
|
@ -660,6 +665,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
query.Limit = GetSpecialItemsLimit();
|
query.Limit = GetSpecialItemsLimit();
|
||||||
query.IncludeItemTypes = new[] { typeof(Episode).Name };
|
query.IncludeItemTypes = new[] { typeof(Episode).Name };
|
||||||
|
query.ExcludeLocationTypes = new[] { LocationType.Virtual };
|
||||||
|
|
||||||
return _libraryManager.GetItemsResult(query);
|
return _libraryManager.GetItemsResult(query);
|
||||||
}
|
}
|
||||||
|
@ -737,7 +743,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return GetResult(genres, parent, query);
|
return GetResult(genres, parent, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<QueryResult<BaseItem>> GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
query.Recursive = true;
|
query.Recursive = true;
|
||||||
query.ParentId = queryParent.Id;
|
query.ParentId = queryParent.Id;
|
||||||
|
@ -766,7 +772,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager));
|
items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager));
|
||||||
|
|
||||||
return PostFilterAndSort(items, queryParent, null, query, _libraryManager);
|
return PostFilterAndSort(items, queryParent, null, query, _libraryManager, _config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool FilterItem(BaseItem item, InternalItemsQuery query)
|
public static bool FilterItem(BaseItem item, InternalItemsQuery query)
|
||||||
|
@ -779,14 +785,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
int? totalRecordLimit,
|
int? totalRecordLimit,
|
||||||
InternalItemsQuery query)
|
InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
return PostFilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager);
|
return PostFilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager, _config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items,
|
public static QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items,
|
||||||
BaseItem queryParent,
|
BaseItem queryParent,
|
||||||
int? totalRecordLimit,
|
int? totalRecordLimit,
|
||||||
InternalItemsQuery query,
|
InternalItemsQuery query,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager,
|
||||||
|
IServerConfigurationManager configurationManager)
|
||||||
{
|
{
|
||||||
var user = query.User;
|
var user = query.User;
|
||||||
|
|
||||||
|
@ -795,7 +802,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
query.IsVirtualUnaired,
|
query.IsVirtualUnaired,
|
||||||
query.IsUnaired);
|
query.IsUnaired);
|
||||||
|
|
||||||
items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user);
|
items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user, configurationManager);
|
||||||
|
|
||||||
// This must be the last filter
|
// This must be the last filter
|
||||||
if (!string.IsNullOrEmpty(query.AdjacentTo))
|
if (!string.IsNullOrEmpty(query.AdjacentTo))
|
||||||
|
@ -809,14 +816,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(IEnumerable<BaseItem> items,
|
public static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(IEnumerable<BaseItem> items,
|
||||||
InternalItemsQuery query,
|
InternalItemsQuery query,
|
||||||
BaseItem queryParent,
|
BaseItem queryParent,
|
||||||
User user)
|
User user,
|
||||||
|
IServerConfigurationManager configurationManager)
|
||||||
{
|
{
|
||||||
if (items == null)
|
if (items == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException("items");
|
throw new ArgumentNullException("items");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CollapseBoxSetItems(query, queryParent, user))
|
if (CollapseBoxSetItems(query, queryParent, user, configurationManager))
|
||||||
{
|
{
|
||||||
items = BaseItem.CollectionManager.CollapseItemsWithinBoxSets(items, user);
|
items = BaseItem.CollectionManager.CollapseItemsWithinBoxSets(items, user);
|
||||||
}
|
}
|
||||||
|
@ -849,7 +857,8 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public static bool CollapseBoxSetItems(InternalItemsQuery query,
|
public static bool CollapseBoxSetItems(InternalItemsQuery query,
|
||||||
BaseItem queryParent,
|
BaseItem queryParent,
|
||||||
User user)
|
User user,
|
||||||
|
IServerConfigurationManager configurationManager)
|
||||||
{
|
{
|
||||||
// Could end up stuck in a loop like this
|
// Could end up stuck in a loop like this
|
||||||
if (queryParent is BoxSet)
|
if (queryParent is BoxSet)
|
||||||
|
@ -861,7 +870,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
if (!param.HasValue)
|
if (!param.HasValue)
|
||||||
{
|
{
|
||||||
if (user != null && !user.Configuration.GroupMoviesIntoBoxSets)
|
if (user != null && !configurationManager.Configuration.EnableGroupingIntoCollections)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -992,11 +1001,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.IsYearMismatched.HasValue)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(request.Person))
|
if (!string.IsNullOrWhiteSpace(request.Person))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -1415,16 +1419,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.IsYearMismatched.HasValue)
|
|
||||||
{
|
|
||||||
var filterValue = query.IsYearMismatched.Value;
|
|
||||||
|
|
||||||
if (IsYearMismatched(item, libraryManager) != filterValue)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.HasOfficialRating.HasValue)
|
if (query.HasOfficialRating.HasValue)
|
||||||
{
|
{
|
||||||
var filterValue = query.HasOfficialRating.Value;
|
var filterValue = query.HasOfficialRating.Value;
|
||||||
|
@ -1658,12 +1652,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
var tags = query.Tags;
|
var tags = query.Tags;
|
||||||
if (tags.Length > 0)
|
if (tags.Length > 0)
|
||||||
{
|
{
|
||||||
var hasTags = item as IHasTags;
|
if (!tags.Any(v => item.Tags.Contains(v, StringComparer.OrdinalIgnoreCase)))
|
||||||
if (hasTags == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!tags.Any(v => hasTags.Tags.Contains(v, StringComparer.OrdinalIgnoreCase)))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1976,34 +1965,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, sortName, CancellationToken.None);
|
return _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, sortName, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsYearMismatched(BaseItem item, ILibraryManager libraryManager)
|
|
||||||
{
|
|
||||||
if (item.ProductionYear.HasValue)
|
|
||||||
{
|
|
||||||
var path = item.Path;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(path))
|
|
||||||
{
|
|
||||||
var info = libraryManager.ParseName(Path.GetFileName(path));
|
|
||||||
var yearInName = info.Year;
|
|
||||||
|
|
||||||
// Go up a level if we didn't get a year
|
|
||||||
if (!yearInName.HasValue)
|
|
||||||
{
|
|
||||||
info = libraryManager.ParseName(Path.GetFileName(Path.GetDirectoryName(path)));
|
|
||||||
yearInName = info.Year;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (yearInName.HasValue)
|
|
||||||
{
|
|
||||||
return yearInName.Value != item.ProductionYear.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEnumerable<BaseItem> FilterForAdjacency(IEnumerable<BaseItem> items, string adjacentToId)
|
public static IEnumerable<BaseItem> FilterForAdjacency(IEnumerable<BaseItem> items, string adjacentToId)
|
||||||
{
|
{
|
||||||
var list = items.ToList();
|
var list = items.ToList();
|
||||||
|
|
|
@ -21,7 +21,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Video : BaseItem,
|
public class Video : BaseItem,
|
||||||
IHasAspectRatio,
|
IHasAspectRatio,
|
||||||
IHasTags,
|
|
||||||
ISupportsPlaceHolders,
|
ISupportsPlaceHolders,
|
||||||
IHasMediaSources,
|
IHasMediaSources,
|
||||||
IHasShortOverview,
|
IHasShortOverview,
|
||||||
|
|
|
@ -150,13 +150,6 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// <returns>BaseItem.</returns>
|
/// <returns>BaseItem.</returns>
|
||||||
BaseItem GetItemById(Guid id);
|
BaseItem GetItemById(Guid id);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the memory item by identifier.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identifier.</param>
|
|
||||||
/// <returns>BaseItem.</returns>
|
|
||||||
BaseItem GetMemoryItemById(Guid id);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the intros.
|
/// Gets the intros.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -15,5 +15,6 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken);
|
Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken);
|
||||||
Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings);
|
Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings);
|
||||||
Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location);
|
Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location);
|
||||||
|
Task<List<ChannelInfo>> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ using MediaBrowser.Model.Querying;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Events;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
|
@ -385,5 +386,15 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
List<NameValuePair> GetSatIniMappings();
|
List<NameValuePair> GetSatIniMappings();
|
||||||
|
|
||||||
Task<List<ChannelInfo>> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken);
|
Task<List<ChannelInfo>> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task<List<ChannelInfo>> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken);
|
||||||
|
Task<List<ChannelInfo>> GetChannelsFromListingsProviderData(string id, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
List<IListingsProvider> ListingProviders { get;}
|
||||||
|
|
||||||
|
event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled;
|
||||||
|
event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled;
|
||||||
|
event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCreated;
|
||||||
|
event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCreated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,4 +226,23 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task ResetTuner(string id, CancellationToken cancellationToken);
|
Task ResetTuner(string id, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ISupportsNewTimerIds
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates the timer asynchronous.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info">The information.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task.</returns>
|
||||||
|
Task<string> CreateTimer(TimerInfo info, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates the series timer asynchronous.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info">The information.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>Task.</returns>
|
||||||
|
Task<string> CreateSeriesTimer(SeriesTimerInfo info, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.Providers;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
|
@ -235,5 +236,25 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override List<ExternalUrl> GetRelatedUrls()
|
||||||
|
{
|
||||||
|
var list = base.GetRelatedUrls();
|
||||||
|
|
||||||
|
var imdbId = this.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
if (!string.IsNullOrWhiteSpace(imdbId))
|
||||||
|
{
|
||||||
|
if (IsMovie)
|
||||||
|
{
|
||||||
|
list.Add(new ExternalUrl
|
||||||
|
{
|
||||||
|
Name = "Trakt",
|
||||||
|
Url = string.Format("https://trakt.tv/movies/{0}", imdbId)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
MediaBrowser.Controller/LiveTv/TimerEventInfo.cs
Normal file
14
MediaBrowser.Controller/LiveTv/TimerEventInfo.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
|
{
|
||||||
|
public class TimerEventInfo
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string ProgramId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -142,7 +142,7 @@
|
||||||
<Compile Include="Entities\IHasDisplayOrder.cs" />
|
<Compile Include="Entities\IHasDisplayOrder.cs" />
|
||||||
<Compile Include="Entities\IHasId.cs" />
|
<Compile Include="Entities\IHasId.cs" />
|
||||||
<Compile Include="Entities\IHasImages.cs" />
|
<Compile Include="Entities\IHasImages.cs" />
|
||||||
<Compile Include="Entities\IHasKeywords.cs" />
|
<Compile Include="Entities\KeywordExtensions.cs" />
|
||||||
<Compile Include="Entities\IHasMediaSources.cs" />
|
<Compile Include="Entities\IHasMediaSources.cs" />
|
||||||
<Compile Include="Entities\IHasMetascore.cs" />
|
<Compile Include="Entities\IHasMetascore.cs" />
|
||||||
<Compile Include="Entities\IHasOriginalTitle.cs" />
|
<Compile Include="Entities\IHasOriginalTitle.cs" />
|
||||||
|
@ -154,7 +154,6 @@
|
||||||
<Compile Include="Entities\IHasSpecialFeatures.cs" />
|
<Compile Include="Entities\IHasSpecialFeatures.cs" />
|
||||||
<Compile Include="Entities\IHasStartDate.cs" />
|
<Compile Include="Entities\IHasStartDate.cs" />
|
||||||
<Compile Include="Entities\IHasTaglines.cs" />
|
<Compile Include="Entities\IHasTaglines.cs" />
|
||||||
<Compile Include="Entities\IHasTags.cs" />
|
|
||||||
<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" />
|
||||||
|
@ -177,6 +176,7 @@
|
||||||
<Compile Include="Entities\PhotoAlbum.cs" />
|
<Compile Include="Entities\PhotoAlbum.cs" />
|
||||||
<Compile Include="Entities\Share.cs" />
|
<Compile Include="Entities\Share.cs" />
|
||||||
<Compile Include="Entities\SourceType.cs" />
|
<Compile Include="Entities\SourceType.cs" />
|
||||||
|
<Compile Include="Entities\TagExtensions.cs" />
|
||||||
<Compile Include="Entities\UserView.cs" />
|
<Compile Include="Entities\UserView.cs" />
|
||||||
<Compile Include="Entities\UserViewBuilder.cs" />
|
<Compile Include="Entities\UserViewBuilder.cs" />
|
||||||
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
|
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
|
||||||
|
@ -218,6 +218,7 @@
|
||||||
<Compile Include="LiveTv\ProgramInfo.cs" />
|
<Compile Include="LiveTv\ProgramInfo.cs" />
|
||||||
<Compile Include="LiveTv\RecordingInfo.cs" />
|
<Compile Include="LiveTv\RecordingInfo.cs" />
|
||||||
<Compile Include="LiveTv\SeriesTimerInfo.cs" />
|
<Compile Include="LiveTv\SeriesTimerInfo.cs" />
|
||||||
|
<Compile Include="LiveTv\TimerEventInfo.cs" />
|
||||||
<Compile Include="LiveTv\TimerInfo.cs" />
|
<Compile Include="LiveTv\TimerInfo.cs" />
|
||||||
<Compile Include="Localization\ILocalizationManager.cs" />
|
<Compile Include="Localization\ILocalizationManager.cs" />
|
||||||
<Compile Include="MediaEncoding\ChapterImageRefreshOptions.cs" />
|
<Compile Include="MediaEncoding\ChapterImageRefreshOptions.cs" />
|
||||||
|
@ -290,14 +291,11 @@
|
||||||
<Compile Include="Providers\IImageFileSaver.cs" />
|
<Compile Include="Providers\IImageFileSaver.cs" />
|
||||||
<Compile Include="Providers\IImageProvider.cs" />
|
<Compile Include="Providers\IImageProvider.cs" />
|
||||||
<Compile Include="Providers\IImageSaver.cs" />
|
<Compile Include="Providers\IImageSaver.cs" />
|
||||||
<Compile Include="Providers\IItemIdentityConverter.cs" />
|
|
||||||
<Compile Include="Providers\IItemIdentityProvider.cs" />
|
|
||||||
<Compile Include="Providers\ILocalImageFileProvider.cs" />
|
<Compile Include="Providers\ILocalImageFileProvider.cs" />
|
||||||
<Compile Include="Providers\ILocalMetadataProvider.cs" />
|
<Compile Include="Providers\ILocalMetadataProvider.cs" />
|
||||||
<Compile Include="Providers\ImageRefreshMode.cs" />
|
<Compile Include="Providers\ImageRefreshMode.cs" />
|
||||||
<Compile Include="Providers\ImageRefreshOptions.cs" />
|
<Compile Include="Providers\ImageRefreshOptions.cs" />
|
||||||
<Compile Include="Providers\IPreRefreshProvider.cs" />
|
<Compile Include="Providers\IPreRefreshProvider.cs" />
|
||||||
<Compile Include="Providers\IProviderRepository.cs" />
|
|
||||||
<Compile Include="Providers\IRemoteImageProvider.cs" />
|
<Compile Include="Providers\IRemoteImageProvider.cs" />
|
||||||
<Compile Include="Providers\ILocalImageProvider.cs" />
|
<Compile Include="Providers\ILocalImageProvider.cs" />
|
||||||
<Compile Include="Providers\IMetadataProvider.cs" />
|
<Compile Include="Providers\IMetadataProvider.cs" />
|
||||||
|
@ -330,11 +328,8 @@
|
||||||
<Compile Include="Sorting\SortHelper.cs" />
|
<Compile Include="Sorting\SortHelper.cs" />
|
||||||
<Compile Include="Subtitles\ISubtitleManager.cs" />
|
<Compile Include="Subtitles\ISubtitleManager.cs" />
|
||||||
<Compile Include="Subtitles\ISubtitleProvider.cs" />
|
<Compile Include="Subtitles\ISubtitleProvider.cs" />
|
||||||
<Compile Include="Providers\ItemIdentifier.cs" />
|
|
||||||
<Compile Include="Providers\ItemIdentities.cs" />
|
|
||||||
<Compile Include="Providers\ItemLookupInfo.cs" />
|
<Compile Include="Providers\ItemLookupInfo.cs" />
|
||||||
<Compile Include="Providers\MetadataRefreshOptions.cs" />
|
<Compile Include="Providers\MetadataRefreshOptions.cs" />
|
||||||
<Compile Include="Providers\MetadataStatus.cs" />
|
|
||||||
<Compile Include="Providers\ISeriesOrderManager.cs" />
|
<Compile Include="Providers\ISeriesOrderManager.cs" />
|
||||||
<Compile Include="Session\ISessionManager.cs" />
|
<Compile Include="Session\ISessionManager.cs" />
|
||||||
<Compile Include="Entities\AggregateFolder.cs" />
|
<Compile Include="Entities\AggregateFolder.cs" />
|
||||||
|
|
|
@ -10,13 +10,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the subtitles.
|
/// Gets the subtitles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="itemId">The item identifier.</param>
|
|
||||||
/// <param name="mediaSourceId">The media source identifier.</param>
|
|
||||||
/// <param name="subtitleStreamIndex">Index of the subtitle stream.</param>
|
|
||||||
/// <param name="outputFormat">The output format.</param>
|
|
||||||
/// <param name="startTimeTicks">The start time ticks.</param>
|
|
||||||
/// <param name="endTimeTicks">The end time ticks.</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task{Stream}.</returns>
|
/// <returns>Task{Stream}.</returns>
|
||||||
Task<Stream> GetSubtitles(string itemId,
|
Task<Stream> GetSubtitles(string itemId,
|
||||||
string mediaSourceId,
|
string mediaSourceId,
|
||||||
|
@ -24,6 +17,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
string outputFormat,
|
string outputFormat,
|
||||||
long startTimeTicks,
|
long startTimeTicks,
|
||||||
long? endTimeTicks,
|
long? endTimeTicks,
|
||||||
|
bool preserveOriginalTimestamps,
|
||||||
CancellationToken cancellationToken);
|
CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace MediaBrowser.Controller.Persistence
|
||||||
/// <param name="chapters">The chapters.</param>
|
/// <param name="chapters">The chapters.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task SaveChapters(Guid id, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken);
|
Task SaveChapters(Guid id, List<ChapterInfo> chapters, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the media streams.
|
/// Gets the media streams.
|
||||||
|
@ -97,7 +97,7 @@ namespace MediaBrowser.Controller.Persistence
|
||||||
/// <param name="streams">The streams.</param>
|
/// <param name="streams">The streams.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task SaveMediaStreams(Guid id, IEnumerable<MediaStream> streams, CancellationToken cancellationToken);
|
Task SaveMediaStreams(Guid id, List<MediaStream> streams, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the item ids.
|
/// Gets the item ids.
|
||||||
|
|
|
@ -29,6 +29,8 @@ namespace MediaBrowser.Controller.Persistence
|
||||||
/// <returns>Task{UserItemData}.</returns>
|
/// <returns>Task{UserItemData}.</returns>
|
||||||
UserItemData GetUserData(Guid userId, string key);
|
UserItemData GetUserData(Guid userId, string key);
|
||||||
|
|
||||||
|
UserItemData GetUserData(Guid userId, List<string> keys);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return all user data associated with the given user
|
/// Return all user data associated with the given user
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -803,11 +803,7 @@ namespace MediaBrowser.Controller.Providers
|
||||||
{
|
{
|
||||||
using (var subtree = reader.ReadSubtree())
|
using (var subtree = reader.ReadSubtree())
|
||||||
{
|
{
|
||||||
var hasTags = item as IHasTags;
|
FetchFromTagsNode(subtree, item);
|
||||||
if (hasTags != null)
|
|
||||||
{
|
|
||||||
FetchFromTagsNode(subtree, hasTags);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -816,11 +812,7 @@ namespace MediaBrowser.Controller.Providers
|
||||||
{
|
{
|
||||||
using (var subtree = reader.ReadSubtree())
|
using (var subtree = reader.ReadSubtree())
|
||||||
{
|
{
|
||||||
var hasTags = item as IHasKeywords;
|
FetchFromKeywordsNode(subtree, item);
|
||||||
if (hasTags != null)
|
|
||||||
{
|
|
||||||
FetchFromKeywordsNode(subtree, hasTags);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1070,7 +1062,7 @@ namespace MediaBrowser.Controller.Providers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FetchFromTagsNode(XmlReader reader, IHasTags item)
|
private void FetchFromTagsNode(XmlReader reader, BaseItem item)
|
||||||
{
|
{
|
||||||
reader.MoveToContent();
|
reader.MoveToContent();
|
||||||
|
|
||||||
|
@ -1099,7 +1091,7 @@ namespace MediaBrowser.Controller.Providers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FetchFromKeywordsNode(XmlReader reader, IHasKeywords item)
|
private void FetchFromKeywordsNode(XmlReader reader, BaseItem item)
|
||||||
{
|
{
|
||||||
reader.MoveToContent();
|
reader.MoveToContent();
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
namespace MediaBrowser.Controller.Providers
|
|
||||||
{
|
|
||||||
public interface IItemIdentityConverter { }
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
namespace MediaBrowser.Controller.Providers
|
|
||||||
{
|
|
||||||
public interface IItemIdentityProvider { }
|
|
||||||
}
|
|
|
@ -97,13 +97,11 @@ namespace MediaBrowser.Controller.Providers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="imageProviders">The image providers.</param>
|
/// <param name="imageProviders">The image providers.</param>
|
||||||
/// <param name="metadataServices">The metadata services.</param>
|
/// <param name="metadataServices">The metadata services.</param>
|
||||||
/// <param name="identityProviders">The identity providers.</param>
|
|
||||||
/// <param name="identityConverters">The identity converters.</param>
|
|
||||||
/// <param name="metadataProviders">The metadata providers.</param>
|
/// <param name="metadataProviders">The metadata providers.</param>
|
||||||
/// <param name="savers">The savers.</param>
|
/// <param name="savers">The savers.</param>
|
||||||
/// <param name="imageSavers">The image savers.</param>
|
/// <param name="imageSavers">The image savers.</param>
|
||||||
/// <param name="externalIds">The external ids.</param>
|
/// <param name="externalIds">The external ids.</param>
|
||||||
void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IItemIdentityProvider> identityProviders, IEnumerable<IItemIdentityConverter> identityConverters, IEnumerable<IMetadataProvider> metadataProviders,
|
void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders,
|
||||||
IEnumerable<IMetadataSaver> savers,
|
IEnumerable<IMetadataSaver> savers,
|
||||||
IEnumerable<IImageSaver> imageSavers,
|
IEnumerable<IImageSaver> imageSavers,
|
||||||
IEnumerable<IExternalId> externalIds);
|
IEnumerable<IExternalId> externalIds);
|
||||||
|
@ -135,7 +133,7 @@ namespace MediaBrowser.Controller.Providers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
/// <returns>IEnumerable{ExternalUrl}.</returns>
|
/// <returns>IEnumerable{ExternalUrl}.</returns>
|
||||||
IEnumerable<ExternalUrl> GetExternalUrls(IHasProviderIds item);
|
IEnumerable<ExternalUrl> GetExternalUrls(BaseItem item);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the external identifier infos.
|
/// Gets the external identifier infos.
|
||||||
|
@ -190,21 +188,5 @@ namespace MediaBrowser.Controller.Providers
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{HttpResponseInfo}.</returns>
|
/// <returns>Task{HttpResponseInfo}.</returns>
|
||||||
Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken);
|
Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the item identity providers.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TLookupInfo">The type of the t lookup information.</typeparam>
|
|
||||||
/// <returns>IEnumerable<IItemIdentityProvider<TLookupInfo, TIdentity>>.</returns>
|
|
||||||
IEnumerable<IItemIdentityProvider<TLookupInfo>> GetItemIdentityProviders<TLookupInfo>()
|
|
||||||
where TLookupInfo : ItemLookupInfo;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the item identity converters.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TLookupInfo">The type of the t lookup information.</typeparam>
|
|
||||||
/// <returns>IEnumerable<IItemIdentityConverter<TIdentity>>.</returns>
|
|
||||||
IEnumerable<IItemIdentityConverter<TLookupInfo>> GetItemIdentityConverters<TLookupInfo>()
|
|
||||||
where TLookupInfo : ItemLookupInfo;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,25 +0,0 @@
|
||||||
using MediaBrowser.Controller.Persistence;
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Providers
|
|
||||||
{
|
|
||||||
public interface IProviderRepository : IRepository
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the metadata status.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemId">The item identifier.</param>
|
|
||||||
/// <returns>MetadataStatus.</returns>
|
|
||||||
MetadataStatus GetMetadataStatus(Guid itemId);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Saves the metadata status.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="status">The status.</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task.</returns>
|
|
||||||
Task SaveMetadataStatus(MetadataStatus status, CancellationToken cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Providers
|
|
||||||
{
|
|
||||||
public static class ItemIdentifier<TLookupInfo>
|
|
||||||
where TLookupInfo : ItemLookupInfo
|
|
||||||
{
|
|
||||||
public static async Task FindIdentities(TLookupInfo item, IProviderManager providerManager, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var providers = providerManager.GetItemIdentityProviders<TLookupInfo>();
|
|
||||||
var converters = providerManager.GetItemIdentityConverters<TLookupInfo>().ToList();
|
|
||||||
|
|
||||||
foreach (var provider in providers)
|
|
||||||
{
|
|
||||||
await provider.Identify(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool changesMade = true;
|
|
||||||
|
|
||||||
while (changesMade)
|
|
||||||
{
|
|
||||||
changesMade = false;
|
|
||||||
|
|
||||||
foreach (var converter in converters)
|
|
||||||
{
|
|
||||||
if (await converter.Convert(item))
|
|
||||||
{
|
|
||||||
changesMade = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Providers
|
|
||||||
{
|
|
||||||
public interface IItemIdentityProvider<in TLookupInfo> : IItemIdentityProvider
|
|
||||||
where TLookupInfo : ItemLookupInfo
|
|
||||||
{
|
|
||||||
Task Identify(TLookupInfo info);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IItemIdentityConverter<in TLookupInfo> : IItemIdentityConverter
|
|
||||||
where TLookupInfo : ItemLookupInfo
|
|
||||||
{
|
|
||||||
Task<bool> Convert(TLookupInfo info);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
|
||||||
|
@ -5,10 +6,6 @@ namespace MediaBrowser.Controller.Providers
|
||||||
{
|
{
|
||||||
public class ItemInfo
|
public class ItemInfo
|
||||||
{
|
{
|
||||||
public ItemInfo()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemInfo(IHasMetadata item)
|
public ItemInfo(IHasMetadata item)
|
||||||
{
|
{
|
||||||
Path = item.Path;
|
Path = item.Path;
|
||||||
|
@ -21,8 +18,11 @@ namespace MediaBrowser.Controller.Providers
|
||||||
VideoType = video.VideoType;
|
VideoType = video.VideoType;
|
||||||
IsPlaceHolder = video.IsPlaceHolder;
|
IsPlaceHolder = video.IsPlaceHolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ItemType = item.GetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Type ItemType { get; set; }
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
public string ContainingFolderPath { get; set; }
|
public string ContainingFolderPath { get; set; }
|
||||||
public VideoType VideoType { get; set; }
|
public VideoType VideoType { get; set; }
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Providers
|
|
||||||
{
|
|
||||||
public class MetadataStatus
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the item identifier.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The item identifier.</value>
|
|
||||||
public Guid ItemId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the date last metadata refresh.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The date last metadata refresh.</value>
|
|
||||||
public DateTime? DateLastMetadataRefresh { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the date last images refresh.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The date last images refresh.</value>
|
|
||||||
public DateTime? DateLastImagesRefresh { get; set; }
|
|
||||||
|
|
||||||
public DateTime? ItemDateModified { get; set; }
|
|
||||||
|
|
||||||
public bool IsDirty { get; private set; }
|
|
||||||
|
|
||||||
public void SetDateLastMetadataRefresh(DateTime? date)
|
|
||||||
{
|
|
||||||
if (date != DateLastMetadataRefresh)
|
|
||||||
{
|
|
||||||
IsDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DateLastMetadataRefresh = date;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetDateLastImagesRefresh(DateTime? date)
|
|
||||||
{
|
|
||||||
if (date != DateLastImagesRefresh)
|
|
||||||
{
|
|
||||||
IsDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DateLastImagesRefresh = date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -315,9 +315,8 @@ namespace MediaBrowser.Controller.Session
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Revokes the user tokens.
|
/// Revokes the user tokens.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId">The user identifier.</param>
|
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task RevokeUserTokens(string userId);
|
Task RevokeUserTokens(string userId, string currentAccessToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Revokes the token.
|
/// Revokes the token.
|
||||||
|
|
|
@ -1015,17 +1015,17 @@ namespace MediaBrowser.Dlna.Didl
|
||||||
int? width = null;
|
int? width = null;
|
||||||
int? height = null;
|
int? height = null;
|
||||||
|
|
||||||
//try
|
try
|
||||||
//{
|
{
|
||||||
// var size = _imageProcessor.GetImageSize(imageInfo);
|
var size = _imageProcessor.GetImageSize(imageInfo);
|
||||||
|
|
||||||
// width = Convert.ToInt32(size.Width);
|
width = Convert.ToInt32(size.Width);
|
||||||
// height = Convert.ToInt32(size.Height);
|
height = Convert.ToInt32(size.Height);
|
||||||
//}
|
}
|
||||||
//catch
|
catch
|
||||||
//{
|
{
|
||||||
|
|
||||||
//}
|
}
|
||||||
|
|
||||||
var inputFormat = (Path.GetExtension(imageInfo.Path) ?? string.Empty)
|
var inputFormat = (Path.GetExtension(imageInfo.Path) ?? string.Empty)
|
||||||
.TrimStart('.')
|
.TrimStart('.')
|
||||||
|
|
|
@ -101,6 +101,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
|
|
||||||
var uri = new Uri(location);
|
var uri = new Uri(location);
|
||||||
|
_logger.Debug("Attempting to create PlayToController from location {0}", location);
|
||||||
var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger).ConfigureAwait(false);
|
var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger).ConfigureAwait(false);
|
||||||
|
|
||||||
if (device.RendererCommands == null)
|
if (device.RendererCommands == null)
|
||||||
|
@ -112,6 +113,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.Debug("Logging session activity from location {0}", location);
|
||||||
var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null)
|
var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,8 @@ namespace MediaBrowser.Dlna.Profiles
|
||||||
new HttpHeaderInfo
|
new HttpHeaderInfo
|
||||||
{
|
{
|
||||||
Name = "User-Agent",
|
Name = "User-Agent",
|
||||||
Value = @"SEC_",
|
Value = @".*(SEC_HHP_\[TV\] [A-Z]{2}\d{2}J[A-Z]?\d{3,4})*.",
|
||||||
Match = HeaderMatchType.Substring
|
Match = HeaderMatchType.Regex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<Identification>
|
<Identification>
|
||||||
<ModelUrl>samsung.com</ModelUrl>
|
<ModelUrl>samsung.com</ModelUrl>
|
||||||
<Headers>
|
<Headers>
|
||||||
<HttpHeaderInfo name="User-Agent" value="SEC_" match="Substring" />
|
<HttpHeaderInfo name="User-Agent" value=".*(SEC_HHP_\[TV\] [A-Z]{2}\d{2}J[A-Z]?\d{3,4})*." match="Regex" />
|
||||||
</Headers>
|
</Headers>
|
||||||
</Identification>
|
</Identification>
|
||||||
<Manufacturer>Emby</Manufacturer>
|
<Manufacturer>Emby</Manufacturer>
|
||||||
|
|
|
@ -593,36 +593,28 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
builder.Append("</Studios>");
|
builder.Append("</Studios>");
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasTags = item as IHasTags;
|
if (item.Tags.Count > 0)
|
||||||
if (hasTags != null)
|
|
||||||
{
|
{
|
||||||
if (hasTags.Tags.Count > 0)
|
builder.Append("<Tags>");
|
||||||
|
|
||||||
|
foreach (var tag in item.Tags)
|
||||||
{
|
{
|
||||||
builder.Append("<Tags>");
|
builder.Append("<Tag>" + SecurityElement.Escape(tag) + "</Tag>");
|
||||||
|
|
||||||
foreach (var tag in hasTags.Tags)
|
|
||||||
{
|
|
||||||
builder.Append("<Tag>" + SecurityElement.Escape(tag) + "</Tag>");
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Append("</Tags>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder.Append("</Tags>");
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasKeywords = item as IHasKeywords;
|
if (item.Keywords.Count > 0)
|
||||||
if (hasKeywords != null)
|
|
||||||
{
|
{
|
||||||
if (hasKeywords.Keywords.Count > 0)
|
builder.Append("<PlotKeywords>");
|
||||||
|
|
||||||
|
foreach (var tag in item.Keywords)
|
||||||
{
|
{
|
||||||
builder.Append("<PlotKeywords>");
|
builder.Append("<PlotKeyword>" + SecurityElement.Escape(tag) + "</PlotKeyword>");
|
||||||
|
|
||||||
foreach (var tag in hasKeywords.Keywords)
|
|
||||||
{
|
|
||||||
builder.Append("<PlotKeyword>" + SecurityElement.Escape(tag) + "</PlotKeyword>");
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Append("</PlotKeywords>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder.Append("</PlotKeywords>");
|
||||||
}
|
}
|
||||||
|
|
||||||
var people = libraryManager.GetPeople(item);
|
var people = libraryManager.GetPeople(item);
|
||||||
|
|
|
@ -73,11 +73,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
var commandLineArgs = GetCommandLineArguments(encodingJob);
|
var commandLineArgs = GetCommandLineArguments(encodingJob);
|
||||||
|
|
||||||
if (GetEncodingOptions().EnableDebugLogging)
|
|
||||||
{
|
|
||||||
commandLineArgs = "-loglevel debug " + commandLineArgs;
|
|
||||||
}
|
|
||||||
|
|
||||||
var process = new Process
|
var process = new Process
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
StartInfo = new ProcessStartInfo
|
||||||
|
|
|
@ -99,7 +99,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
if (videoRequest != null)
|
if (videoRequest != null)
|
||||||
{
|
{
|
||||||
state.OutputVideoCodec = state.Options.VideoCodec;
|
state.OutputVideoCodec = state.Options.VideoCodec;
|
||||||
state.OutputVideoBitrate = GetVideoBitrateParamValue(state.Options, state.VideoStream);
|
state.OutputVideoBitrate = GetVideoBitrateParamValue(state.Options, state.VideoStream, state.OutputVideoCodec);
|
||||||
|
|
||||||
if (state.OutputVideoBitrate.HasValue)
|
if (state.OutputVideoBitrate.HasValue)
|
||||||
{
|
{
|
||||||
|
@ -396,7 +396,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
return request.AudioChannels;
|
return request.AudioChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int? GetVideoBitrateParamValue(EncodingJobOptions request, MediaStream videoStream)
|
private int? GetVideoBitrateParamValue(EncodingJobOptions request, MediaStream videoStream, string outputVideoCodec)
|
||||||
{
|
{
|
||||||
var bitrate = request.VideoBitRate;
|
var bitrate = request.VideoBitRate;
|
||||||
|
|
||||||
|
@ -421,6 +421,18 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bitrate.HasValue)
|
||||||
|
{
|
||||||
|
var inputVideoCodec = videoStream == null ? null : videoStream.Codec;
|
||||||
|
bitrate = ResolutionNormalizer.ScaleBitrate(bitrate.Value, inputVideoCodec, outputVideoCodec);
|
||||||
|
|
||||||
|
// If a max bitrate was requested, don't let the scaled bitrate exceed it
|
||||||
|
if (request.VideoBitRate.HasValue)
|
||||||
|
{
|
||||||
|
bitrate = Math.Min(bitrate.Value, request.VideoBitRate.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return bitrate;
|
return bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -408,7 +408,9 @@ namespace MediaBrowser.MediaEncoding.Probing
|
||||||
Level = streamInfo.level,
|
Level = streamInfo.level,
|
||||||
Index = streamInfo.index,
|
Index = streamInfo.index,
|
||||||
PixelFormat = streamInfo.pix_fmt,
|
PixelFormat = streamInfo.pix_fmt,
|
||||||
NalLengthSize = streamInfo.nal_length_size
|
NalLengthSize = streamInfo.nal_length_size,
|
||||||
|
TimeBase = streamInfo.time_base,
|
||||||
|
CodecTimeBase = streamInfo.codec_time_base
|
||||||
};
|
};
|
||||||
|
|
||||||
if (string.Equals(streamInfo.is_avc, "true", StringComparison.OrdinalIgnoreCase) ||
|
if (string.Equals(streamInfo.is_avc, "true", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
|
|
@ -58,6 +58,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
string outputFormat,
|
string outputFormat,
|
||||||
long startTimeTicks,
|
long startTimeTicks,
|
||||||
long? endTimeTicks,
|
long? endTimeTicks,
|
||||||
|
bool preserveOriginalTimestamps,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var ms = new MemoryStream();
|
var ms = new MemoryStream();
|
||||||
|
@ -68,7 +69,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
|
|
||||||
var trackInfo = reader.Parse(stream, cancellationToken);
|
var trackInfo = reader.Parse(stream, cancellationToken);
|
||||||
|
|
||||||
FilterEvents(trackInfo, startTimeTicks, endTimeTicks, false);
|
FilterEvents(trackInfo, startTimeTicks, endTimeTicks, preserveOriginalTimestamps);
|
||||||
|
|
||||||
var writer = GetWriter(outputFormat);
|
var writer = GetWriter(outputFormat);
|
||||||
|
|
||||||
|
@ -116,6 +117,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
string outputFormat,
|
string outputFormat,
|
||||||
long startTimeTicks,
|
long startTimeTicks,
|
||||||
long? endTimeTicks,
|
long? endTimeTicks,
|
||||||
|
bool preserveOriginalTimestamps,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var subtitle = await GetSubtitleStream(itemId, mediaSourceId, subtitleStreamIndex, cancellationToken)
|
var subtitle = await GetSubtitleStream(itemId, mediaSourceId, subtitleStreamIndex, cancellationToken)
|
||||||
|
@ -130,7 +132,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
|
|
||||||
using (var stream = 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, preserveOriginalTimestamps, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -230,12 +230,6 @@
|
||||||
<Compile Include="..\MediaBrowser.Model\Configuration\SubtitlePlaybackMode.cs">
|
<Compile Include="..\MediaBrowser.Model\Configuration\SubtitlePlaybackMode.cs">
|
||||||
<Link>Configuration\SubtitlePlaybackMode.cs</Link>
|
<Link>Configuration\SubtitlePlaybackMode.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\Configuration\TheMovieDbOptions.cs">
|
|
||||||
<Link>Configuration\TheMovieDbOptions.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\MediaBrowser.Model\Configuration\TvdbOptions.cs">
|
|
||||||
<Link>Configuration\TvdbOptions.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\MediaBrowser.Model\Configuration\UnratedItem.cs">
|
<Compile Include="..\MediaBrowser.Model\Configuration\UnratedItem.cs">
|
||||||
<Link>Configuration\UnratedItem.cs</Link>
|
<Link>Configuration\UnratedItem.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
|
@ -204,12 +204,6 @@
|
||||||
<Compile Include="..\MediaBrowser.Model\Configuration\SubtitlePlaybackMode.cs">
|
<Compile Include="..\MediaBrowser.Model\Configuration\SubtitlePlaybackMode.cs">
|
||||||
<Link>Configuration\SubtitlePlaybackMode.cs</Link>
|
<Link>Configuration\SubtitlePlaybackMode.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\MediaBrowser.Model\Configuration\TheMovieDbOptions.cs">
|
|
||||||
<Link>Configuration\TheMovieDbOptions.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\MediaBrowser.Model\Configuration\TvdbOptions.cs">
|
|
||||||
<Link>Configuration\TvdbOptions.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\MediaBrowser.Model\Configuration\UnratedItem.cs">
|
<Compile Include="..\MediaBrowser.Model\Configuration\UnratedItem.cs">
|
||||||
<Link>Configuration\UnratedItem.cs</Link>
|
<Link>Configuration\UnratedItem.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
|
@ -57,6 +57,10 @@ namespace MediaBrowser.Model.ApiClient
|
||||||
{
|
{
|
||||||
existing.RemoteAddress = server.RemoteAddress;
|
existing.RemoteAddress = server.RemoteAddress;
|
||||||
}
|
}
|
||||||
|
if (!string.IsNullOrEmpty(server.ConnectServerId))
|
||||||
|
{
|
||||||
|
existing.ConnectServerId = server.ConnectServerId;
|
||||||
|
}
|
||||||
if (!string.IsNullOrEmpty(server.LocalAddress))
|
if (!string.IsNullOrEmpty(server.LocalAddress))
|
||||||
{
|
{
|
||||||
existing.LocalAddress = server.LocalAddress;
|
existing.LocalAddress = server.LocalAddress;
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace MediaBrowser.Model.ApiClient
|
||||||
|
|
||||||
public String Name { get; set; }
|
public String Name { get; set; }
|
||||||
public String Id { get; set; }
|
public String Id { get; set; }
|
||||||
|
public String ConnectServerId { get; set; }
|
||||||
public String LocalAddress { get; set; }
|
public String LocalAddress { get; set; }
|
||||||
public String RemoteAddress { get; set; }
|
public String RemoteAddress { get; set; }
|
||||||
public String ManualAddress { get; set; }
|
public String ManualAddress { get; set; }
|
||||||
|
|
|
@ -6,7 +6,6 @@ namespace MediaBrowser.Model.Configuration
|
||||||
public int EncodingThreadCount { get; set; }
|
public int EncodingThreadCount { get; set; }
|
||||||
public string TranscodingTempPath { get; set; }
|
public string TranscodingTempPath { get; set; }
|
||||||
public double DownMixAudioBoost { get; set; }
|
public double DownMixAudioBoost { get; set; }
|
||||||
public bool EnableDebugLogging { get; set; }
|
|
||||||
public bool EnableThrottling { get; set; }
|
public bool EnableThrottling { get; set; }
|
||||||
public int ThrottleDelaySeconds { get; set; }
|
public int ThrottleDelaySeconds { get; set; }
|
||||||
public string HardwareAccelerationType { get; set; }
|
public string HardwareAccelerationType { get; set; }
|
||||||
|
|
|
@ -3,11 +3,6 @@ namespace MediaBrowser.Model.Configuration
|
||||||
{
|
{
|
||||||
public class FanartOptions
|
public class FanartOptions
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether [enable automatic updates].
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if [enable automatic updates]; otherwise, <c>false</c>.</value>
|
|
||||||
public bool EnableAutomaticUpdates { get; set; }
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the user API key.
|
/// Gets or sets the user API key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -67,7 +67,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value><c>true</c> if [enable case sensitive item ids]; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if [enable case sensitive item ids]; otherwise, <c>false</c>.</value>
|
||||||
public bool EnableCaseSensitiveItemIds { get; set; }
|
public bool EnableCaseSensitiveItemIds { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the metadata path.
|
/// Gets or sets the metadata path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -86,12 +86,6 @@ namespace MediaBrowser.Model.Configuration
|
||||||
/// <value><c>true</c> if [save local meta]; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if [save local meta]; otherwise, <c>false</c>.</value>
|
||||||
public bool SaveLocalMeta { get; set; }
|
public bool SaveLocalMeta { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether [enable localized guids].
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if [enable localized guids]; otherwise, <c>false</c>.</value>
|
|
||||||
public bool EnableLocalizedGuids { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the preferred metadata language.
|
/// Gets or sets the preferred metadata language.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -161,7 +155,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The dashboard source path.</value>
|
/// <value>The dashboard source path.</value>
|
||||||
public string DashboardSourcePath { get; set; }
|
public string DashboardSourcePath { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the image saving convention.
|
/// Gets or sets the image saving convention.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -190,14 +184,10 @@ namespace MediaBrowser.Model.Configuration
|
||||||
public bool EnableVideoArchiveFiles { get; set; }
|
public bool EnableVideoArchiveFiles { get; set; }
|
||||||
public int RemoteClientBitrateLimit { get; set; }
|
public int RemoteClientBitrateLimit { get; set; }
|
||||||
|
|
||||||
public bool DenyIFrameEmbedding { get; set; }
|
|
||||||
|
|
||||||
public AutoOnOff EnableLibraryMonitor { get; set; }
|
public AutoOnOff EnableLibraryMonitor { get; set; }
|
||||||
|
|
||||||
public int SharingExpirationDays { get; set; }
|
public int SharingExpirationDays { get; set; }
|
||||||
|
|
||||||
public bool EnableDateLastRefresh { get; set; }
|
|
||||||
|
|
||||||
public string[] Migrations { get; set; }
|
public string[] Migrations { get; set; }
|
||||||
|
|
||||||
public int MigrationVersion { get; set; }
|
public int MigrationVersion { get; set; }
|
||||||
|
@ -207,16 +197,24 @@ namespace MediaBrowser.Model.Configuration
|
||||||
|
|
||||||
public bool EnableAnonymousUsageReporting { get; set; }
|
public bool EnableAnonymousUsageReporting { get; set; }
|
||||||
public bool EnableStandaloneMusicKeys { get; set; }
|
public bool EnableStandaloneMusicKeys { get; set; }
|
||||||
|
public bool EnableLocalizedGuids { get; set; }
|
||||||
|
public bool EnableFolderView { get; set; }
|
||||||
|
public bool EnableGroupingIntoCollections { get; set; }
|
||||||
|
public bool DisplaySpecialsWithinSeasons { get; set; }
|
||||||
|
public bool DisplayCollectionsView { get; set; }
|
||||||
|
public string[] LocalNetworkAddresses { 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>
|
||||||
public ServerConfiguration()
|
public ServerConfiguration()
|
||||||
{
|
{
|
||||||
|
LocalNetworkAddresses = new string[] { };
|
||||||
Migrations = new string[] { };
|
Migrations = new string[] { };
|
||||||
|
|
||||||
EnableLocalizedGuids = true;
|
|
||||||
EnableCustomPathSubFolders = true;
|
EnableCustomPathSubFolders = true;
|
||||||
|
EnableLocalizedGuids = true;
|
||||||
|
DisplaySpecialsWithinSeasons = true;
|
||||||
|
|
||||||
ImageSavingConvention = ImageSavingConvention.Compatible;
|
ImageSavingConvention = ImageSavingConvention.Compatible;
|
||||||
PublicPort = 8096;
|
PublicPort = 8096;
|
||||||
|
@ -229,10 +227,8 @@ namespace MediaBrowser.Model.Configuration
|
||||||
EnableAnonymousUsageReporting = true;
|
EnableAnonymousUsageReporting = true;
|
||||||
|
|
||||||
EnableAutomaticRestart = true;
|
EnableAutomaticRestart = true;
|
||||||
DenyIFrameEmbedding = true;
|
|
||||||
|
|
||||||
EnableUPnP = true;
|
EnableUPnP = true;
|
||||||
|
|
||||||
SharingExpirationDays = 30;
|
SharingExpirationDays = 30;
|
||||||
MinResumePct = 5;
|
MinResumePct = 5;
|
||||||
MaxResumePct = 90;
|
MaxResumePct = 90;
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Configuration
|
|
||||||
{
|
|
||||||
public class TheMovieDbOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether [enable automatic updates].
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if [enable automatic updates]; otherwise, <c>false</c>.</value>
|
|
||||||
public bool EnableAutomaticUpdates { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Configuration
|
|
||||||
{
|
|
||||||
public class TvdbOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether [enable automatic updates].
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if [enable automatic updates]; otherwise, <c>false</c>.</value>
|
|
||||||
public bool EnableAutomaticUpdates { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -34,14 +34,11 @@ namespace MediaBrowser.Model.Configuration
|
||||||
|
|
||||||
public SubtitlePlaybackMode SubtitleMode { get; set; }
|
public SubtitlePlaybackMode SubtitleMode { get; set; }
|
||||||
public bool DisplayCollectionsView { get; set; }
|
public bool DisplayCollectionsView { get; set; }
|
||||||
public bool DisplayFoldersView { get; set; }
|
|
||||||
|
|
||||||
public bool EnableLocalPassword { get; set; }
|
public bool EnableLocalPassword { get; set; }
|
||||||
|
|
||||||
public string[] OrderedViews { get; set; }
|
public string[] OrderedViews { get; set; }
|
||||||
|
|
||||||
public bool IncludeTrailersInSuggestions { get; set; }
|
|
||||||
|
|
||||||
public string[] LatestItemsExcludes { get; set; }
|
public string[] LatestItemsExcludes { get; set; }
|
||||||
public string[] PlainFolderViews { get; set; }
|
public string[] PlainFolderViews { get; set; }
|
||||||
|
|
||||||
|
@ -51,7 +48,8 @@ namespace MediaBrowser.Model.Configuration
|
||||||
public bool RememberAudioSelections { get; set; }
|
public bool RememberAudioSelections { get; set; }
|
||||||
public bool RememberSubtitleSelections { get; set; }
|
public bool RememberSubtitleSelections { get; set; }
|
||||||
public bool EnableNextEpisodeAutoPlay { get; set; }
|
public bool EnableNextEpisodeAutoPlay { get; set; }
|
||||||
|
public bool DisplayFoldersView { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="UserConfiguration" /> class.
|
/// Initializes a new instance of the <see cref="UserConfiguration" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -69,8 +67,6 @@ namespace MediaBrowser.Model.Configuration
|
||||||
|
|
||||||
PlainFolderViews = new string[] { };
|
PlainFolderViews = new string[] { };
|
||||||
|
|
||||||
IncludeTrailersInSuggestions = true;
|
|
||||||
|
|
||||||
GroupedFolders = new string[] { };
|
GroupedFolders = new string[] { };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,5 +56,25 @@ namespace MediaBrowser.Model.Dlna
|
||||||
MaxHeight = maxHeight
|
MaxHeight = maxHeight
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static double GetVideoBitrateScaleFactor(string codec)
|
||||||
|
{
|
||||||
|
if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return .5;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int ScaleBitrate(int bitrate, string inputVideoCodec, string outputVideoCodec)
|
||||||
|
{
|
||||||
|
var inputScaleFactor = GetVideoBitrateScaleFactor(inputVideoCodec);
|
||||||
|
var outputScaleFactor = GetVideoBitrateScaleFactor(outputVideoCodec);
|
||||||
|
var scaleFactor = outputScaleFactor/inputScaleFactor;
|
||||||
|
var newBitrate = scaleFactor*bitrate;
|
||||||
|
|
||||||
|
return Convert.ToInt32(newBitrate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -335,7 +335,8 @@ namespace MediaBrowser.Model.Dlna
|
||||||
Name = stream.Language ?? "Unknown",
|
Name = stream.Language ?? "Unknown",
|
||||||
Format = subtitleProfile.Format,
|
Format = subtitleProfile.Format,
|
||||||
Index = stream.Index,
|
Index = stream.Index,
|
||||||
DeliveryMethod = subtitleProfile.Method
|
DeliveryMethod = subtitleProfile.Method,
|
||||||
|
DisplayTitle = stream.DisplayTitle
|
||||||
};
|
};
|
||||||
|
|
||||||
if (info.DeliveryMethod == SubtitleDeliveryMethod.External)
|
if (info.DeliveryMethod == SubtitleDeliveryMethod.External)
|
||||||
|
|
|
@ -7,6 +7,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public bool IsForced { get; set; }
|
public bool IsForced { get; set; }
|
||||||
public string Format { get; set; }
|
public string Format { get; set; }
|
||||||
|
public string DisplayTitle { get; set; }
|
||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
public SubtitleDeliveryMethod DeliveryMethod { get; set; }
|
public SubtitleDeliveryMethod DeliveryMethod { get; set; }
|
||||||
public bool IsExternalUrl { get; set; }
|
public bool IsExternalUrl { get; set; }
|
||||||
|
|
|
@ -9,50 +9,50 @@ namespace MediaBrowser.Model.Entities
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The primary
|
/// The primary
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Primary,
|
Primary = 0,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The art
|
/// The art
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Art,
|
Art = 1,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The backdrop
|
/// The backdrop
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Backdrop,
|
Backdrop = 2,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The banner
|
/// The banner
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Banner,
|
Banner = 3,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The logo
|
/// The logo
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Logo,
|
Logo = 4,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The thumb
|
/// The thumb
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Thumb,
|
Thumb = 5,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The disc
|
/// The disc
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Disc,
|
Disc = 6,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The box
|
/// The box
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Box,
|
Box = 7,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The screenshot
|
/// The screenshot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Screenshot,
|
Screenshot = 8,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The menu
|
/// The menu
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Menu,
|
Menu = 9,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The chapter image
|
/// The chapter image
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Chapter,
|
Chapter = 10,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The box rear
|
/// The box rear
|
||||||
/// </summary>
|
/// </summary>
|
||||||
BoxRear
|
BoxRear = 11
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,9 @@ namespace MediaBrowser.Model.Entities
|
||||||
/// <value>The comment.</value>
|
/// <value>The comment.</value>
|
||||||
public string Comment { get; set; }
|
public string Comment { get; set; }
|
||||||
|
|
||||||
|
public string TimeBase { get; set; }
|
||||||
|
public string CodecTimeBase { get; set; }
|
||||||
|
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
|
||||||
public string DisplayTitle
|
public string DisplayTitle
|
||||||
|
@ -89,7 +92,7 @@ namespace MediaBrowser.Model.Entities
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Language))
|
if (!string.IsNullOrEmpty(Language))
|
||||||
{
|
{
|
||||||
attributes.Add(Language);
|
attributes.Add(StringHelper.FirstToUpper(Language));
|
||||||
}
|
}
|
||||||
if (!string.IsNullOrEmpty(Codec))
|
if (!string.IsNullOrEmpty(Codec))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
using MediaBrowser.Model.Extensions;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.LiveTv
|
namespace MediaBrowser.Model.LiveTv
|
||||||
{
|
{
|
||||||
|
@ -73,11 +75,33 @@ namespace MediaBrowser.Model.LiveTv
|
||||||
|
|
||||||
public string[] EnabledTuners { get; set; }
|
public string[] EnabledTuners { get; set; }
|
||||||
public bool EnableAllTuners { get; set; }
|
public bool EnableAllTuners { get; set; }
|
||||||
|
public string[] NewsCategories { get; set; }
|
||||||
|
public string[] SportsCategories { get; set; }
|
||||||
|
public string[] KidsCategories { get; set; }
|
||||||
|
public string[] MovieCategories { get; set; }
|
||||||
|
public NameValuePair[] ChannelMappings { get; set; }
|
||||||
|
|
||||||
public ListingsProviderInfo()
|
public ListingsProviderInfo()
|
||||||
{
|
{
|
||||||
|
NewsCategories = new string[] { "news", "journalism", "documentary", "current affairs" };
|
||||||
|
SportsCategories = new string[] { "sports", "basketball", "baseball", "football" };
|
||||||
|
KidsCategories = new string[] { "kids", "family", "children", "childrens", "disney" };
|
||||||
|
MovieCategories = new string[] { "movie" };
|
||||||
EnabledTuners = new string[] { };
|
EnabledTuners = new string[] { };
|
||||||
EnableAllTuners = true;
|
EnableAllTuners = true;
|
||||||
|
ChannelMappings = new NameValuePair[] {};
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetMappedChannel(string channelNumber)
|
||||||
|
{
|
||||||
|
foreach (NameValuePair mapping in ChannelMappings)
|
||||||
|
{
|
||||||
|
if (StringHelper.EqualsIgnoreCase(mapping.Name, channelNumber))
|
||||||
|
{
|
||||||
|
return mapping.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return channelNumber;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,8 +97,6 @@
|
||||||
<Compile Include="Configuration\FanartOptions.cs" />
|
<Compile Include="Configuration\FanartOptions.cs" />
|
||||||
<Compile Include="Configuration\MetadataConfiguration.cs" />
|
<Compile Include="Configuration\MetadataConfiguration.cs" />
|
||||||
<Compile Include="Configuration\PeopleMetadataOptions.cs" />
|
<Compile Include="Configuration\PeopleMetadataOptions.cs" />
|
||||||
<Compile Include="Configuration\TheMovieDbOptions.cs" />
|
|
||||||
<Compile Include="Configuration\TvdbOptions.cs" />
|
|
||||||
<Compile Include="Configuration\XbmcMetadataOptions.cs" />
|
<Compile Include="Configuration\XbmcMetadataOptions.cs" />
|
||||||
<Compile Include="Configuration\SubtitlePlaybackMode.cs" />
|
<Compile Include="Configuration\SubtitlePlaybackMode.cs" />
|
||||||
<Compile Include="Connect\ConnectAuthenticationExchangeResult.cs" />
|
<Compile Include="Connect\ConnectAuthenticationExchangeResult.cs" />
|
||||||
|
|
|
@ -85,5 +85,6 @@ namespace MediaBrowser.Model.Querying
|
||||||
public const string GameSystem = "GameSystem";
|
public const string GameSystem = "GameSystem";
|
||||||
public const string IsFavoriteOrLiked = "IsFavoriteOrLiked";
|
public const string IsFavoriteOrLiked = "IsFavoriteOrLiked";
|
||||||
public const string DateLastContentAdded = "DateLastContentAdded";
|
public const string DateLastContentAdded = "DateLastContentAdded";
|
||||||
|
public const string SeriesDatePlayed = "SeriesDatePlayed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,6 @@ namespace MediaBrowser.Providers.Books
|
||||||
{
|
{
|
||||||
public class BookMetadataService : MetadataService<Book, BookInfo>
|
public class BookMetadataService : MetadataService<Book, BookInfo>
|
||||||
{
|
{
|
||||||
public BookMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager, libraryManager)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void MergeData(MetadataResult<Book> source, MetadataResult<Book> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
|
protected override void MergeData(MetadataResult<Book> source, MetadataResult<Book> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
|
||||||
{
|
{
|
||||||
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
|
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
|
||||||
|
@ -25,5 +21,9 @@ namespace MediaBrowser.Providers.Books
|
||||||
target.Item.SeriesName = source.Item.SeriesName;
|
target.Item.SeriesName = source.Item.SeriesName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BookMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,6 @@ namespace MediaBrowser.Providers.BoxSets
|
||||||
{
|
{
|
||||||
public class BoxSetMetadataService : MetadataService<BoxSet, BoxSetInfo>
|
public class BoxSetMetadataService : MetadataService<BoxSet, BoxSetInfo>
|
||||||
{
|
{
|
||||||
public BoxSetMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager, libraryManager)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task<ItemUpdateType> BeforeSave(BoxSet item, bool isFullRefresh, ItemUpdateType currentUpdateType)
|
protected override async Task<ItemUpdateType> BeforeSave(BoxSet item, bool isFullRefresh, ItemUpdateType currentUpdateType)
|
||||||
{
|
{
|
||||||
var updateType = await base.BeforeSave(item, isFullRefresh, currentUpdateType).ConfigureAwait(false);
|
var updateType = await base.BeforeSave(item, isFullRefresh, currentUpdateType).ConfigureAwait(false);
|
||||||
|
@ -54,5 +50,9 @@ namespace MediaBrowser.Providers.BoxSets
|
||||||
targetItem.Shares = sourceItem.Shares;
|
targetItem.Shares = sourceItem.Shares;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BoxSetMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,13 +12,13 @@ namespace MediaBrowser.Providers.Channels
|
||||||
{
|
{
|
||||||
public class ChannelMetadataService : MetadataService<Channel, ItemLookupInfo>
|
public class ChannelMetadataService : MetadataService<Channel, ItemLookupInfo>
|
||||||
{
|
{
|
||||||
public ChannelMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager, libraryManager)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void MergeData(MetadataResult<Channel> source, MetadataResult<Channel> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
|
protected override void MergeData(MetadataResult<Channel> source, MetadataResult<Channel> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
|
||||||
{
|
{
|
||||||
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
|
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ChannelMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,7 +259,7 @@ namespace MediaBrowser.Providers.Chapters
|
||||||
return _itemRepo.GetChapters(new Guid(itemId));
|
return _itemRepo.GetChapters(new Guid(itemId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SaveChapters(string itemId, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken)
|
public Task SaveChapters(string itemId, List<ChapterInfo> chapters, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _itemRepo.SaveChapters(new Guid(itemId), chapters, cancellationToken);
|
return _itemRepo.SaveChapters(new Guid(itemId), chapters, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,14 +16,13 @@ namespace MediaBrowser.Providers.Folders
|
||||||
{
|
{
|
||||||
public class CollectionFolderMetadataService : MetadataService<CollectionFolder, ItemLookupInfo>
|
public class CollectionFolderMetadataService : MetadataService<CollectionFolder, ItemLookupInfo>
|
||||||
{
|
{
|
||||||
public CollectionFolderMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager)
|
|
||||||
: base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager, libraryManager)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void MergeData(MetadataResult<CollectionFolder> source, MetadataResult<CollectionFolder> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
|
protected override void MergeData(MetadataResult<CollectionFolder> source, MetadataResult<CollectionFolder> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
|
||||||
{
|
{
|
||||||
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
|
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CollectionFolderMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,165 +0,0 @@
|
||||||
using MediaBrowser.Common.Net;
|
|
||||||
using MediaBrowser.Controller.Entities;
|
|
||||||
using MediaBrowser.Controller.Providers;
|
|
||||||
using MediaBrowser.Model.Entities;
|
|
||||||
using MediaBrowser.Model.Providers;
|
|
||||||
using MediaBrowser.Providers.Genres;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Providers.Folders
|
|
||||||
{
|
|
||||||
public class DefaultImageProvider : IRemoteImageProvider, IHasItemChangeMonitor
|
|
||||||
{
|
|
||||||
private readonly IHttpClient _httpClient;
|
|
||||||
|
|
||||||
public DefaultImageProvider(IHttpClient httpClient)
|
|
||||||
{
|
|
||||||
_httpClient = httpClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
|
|
||||||
{
|
|
||||||
return new List<ImageType>
|
|
||||||
{
|
|
||||||
ImageType.Primary
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var view = item as UserView;
|
|
||||||
|
|
||||||
if (view != null)
|
|
||||||
{
|
|
||||||
return GetImages(view.ViewType, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
var folder = (ICollectionFolder)item;
|
|
||||||
return GetImages(folder.CollectionType, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task<IEnumerable<RemoteImageInfo>> GetImages(string viewType, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var url = GetImageUrl(viewType);
|
|
||||||
|
|
||||||
var list = new List<RemoteImageInfo>();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(url))
|
|
||||||
{
|
|
||||||
list.AddRange(new List<RemoteImageInfo>{
|
|
||||||
new RemoteImageInfo
|
|
||||||
{
|
|
||||||
ProviderName = Name,
|
|
||||||
Url = url,
|
|
||||||
Type = ImageType.Primary
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.FromResult<IEnumerable<RemoteImageInfo>>(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetImageUrl(string viewType)
|
|
||||||
{
|
|
||||||
const string urlPrefix = "https://raw.githubusercontent.com/MediaBrowser/Emby.Resources/master/images/folders/";
|
|
||||||
|
|
||||||
if (string.Equals(viewType, CollectionType.Books, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return urlPrefix + "books.jpg";
|
|
||||||
}
|
|
||||||
if (string.Equals(viewType, CollectionType.Games, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return urlPrefix + "games.jpg";
|
|
||||||
}
|
|
||||||
if (string.Equals(viewType, CollectionType.Music, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
//return urlPrefix + "music.jpg";
|
|
||||||
}
|
|
||||||
if (string.Equals(viewType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
//return urlPrefix + "photos.png";
|
|
||||||
}
|
|
||||||
if (string.Equals(viewType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
//return urlPrefix + "tv.jpg";
|
|
||||||
}
|
|
||||||
if (string.Equals(viewType, CollectionType.Channels, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return urlPrefix + "channels.jpg";
|
|
||||||
}
|
|
||||||
if (string.Equals(viewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return urlPrefix + "livetv.png";
|
|
||||||
}
|
|
||||||
if (string.Equals(viewType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
//return urlPrefix + "movies.jpg";
|
|
||||||
}
|
|
||||||
if (string.Equals(viewType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return urlPrefix + "playlists.jpg";
|
|
||||||
}
|
|
||||||
if (string.Equals(viewType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
//return urlPrefix + "homevideos.jpg";
|
|
||||||
}
|
|
||||||
if (string.Equals(viewType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return urlPrefix + "musicvideos.jpg";
|
|
||||||
}
|
|
||||||
if (string.Equals(viewType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
//return urlPrefix + "collections.jpg";
|
|
||||||
}
|
|
||||||
if (string.IsNullOrWhiteSpace(viewType))
|
|
||||||
{
|
|
||||||
//return urlPrefix + "generic.jpg";
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Name
|
|
||||||
{
|
|
||||||
get { return "Default Image Provider"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Supports(IHasImages item)
|
|
||||||
{
|
|
||||||
var view = item as UserView;
|
|
||||||
|
|
||||||
if (view != null)
|
|
||||||
{
|
|
||||||
return !string.IsNullOrWhiteSpace(GetImageUrl(view.ViewType));
|
|
||||||
}
|
|
||||||
|
|
||||||
var folder = item as ICollectionFolder;
|
|
||||||
|
|
||||||
if (folder != null)
|
|
||||||
{
|
|
||||||
return !string.IsNullOrWhiteSpace(GetImageUrl(folder.CollectionType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
|
||||||
{
|
|
||||||
CancellationToken = cancellationToken,
|
|
||||||
Url = url,
|
|
||||||
ResourcePool = GenreImageProvider.ImageDownloadResourcePool
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
|
|
||||||
{
|
|
||||||
return GetSupportedImages(item).Any(i => !item.HasImage(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,10 +12,6 @@ namespace MediaBrowser.Providers.Folders
|
||||||
{
|
{
|
||||||
public class FolderMetadataService : MetadataService<Folder, ItemLookupInfo>
|
public class FolderMetadataService : MetadataService<Folder, ItemLookupInfo>
|
||||||
{
|
{
|
||||||
public FolderMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager, libraryManager)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int Order
|
public override int Order
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -29,5 +25,9 @@ namespace MediaBrowser.Providers.Folders
|
||||||
{
|
{
|
||||||
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
|
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FolderMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,13 +12,13 @@ namespace MediaBrowser.Providers.Folders
|
||||||
{
|
{
|
||||||
public class UserViewMetadataService : MetadataService<UserView, ItemLookupInfo>
|
public class UserViewMetadataService : MetadataService<UserView, ItemLookupInfo>
|
||||||
{
|
{
|
||||||
public UserViewMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager, libraryManager)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void MergeData(MetadataResult<UserView> source, MetadataResult<UserView> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
|
protected override void MergeData(MetadataResult<UserView> source, MetadataResult<UserView> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
|
||||||
{
|
{
|
||||||
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
|
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UserViewMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user