Merge branch 'dev'

This commit is contained in:
Luke Pulverenti 2016-06-16 14:10:58 -04:00
commit 4f791d6ee1
241 changed files with 5430 additions and 6464 deletions

View File

@ -80,7 +80,7 @@ namespace MediaBrowser.Api
.OrderBy(i => i)
.ToArray();
result.Tags = items.OfType<IHasTags>()
result.Tags = items
.SelectMany(i => i.Tags)
.Distinct(StringComparer.OrdinalIgnoreCase)
.OrderBy(i => i)

View File

@ -10,6 +10,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using MediaBrowser.Model.Querying;
namespace MediaBrowser.Api
{
@ -187,18 +188,40 @@ namespace MediaBrowser.Api
/// <returns>System.Object.</returns>
public object Get(GetSimilarGames request)
{
var dtoOptions = GetDtoOptions(request);
var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager,
_itemRepo,
_libraryManager,
_userDataRepository,
_dtoService,
Logger,
request, new[] { typeof(Game) },
SimilarItemsHelper.GetSimiliarityScore);
var result = GetSimilarItemsResult(request);
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;
}
}
}

View File

@ -280,11 +280,7 @@ namespace MediaBrowser.Api
episode.AbsoluteEpisodeNumber = request.AbsoluteEpisodeNumber;
}
var hasTags = item as IHasTags;
if (hasTags != null)
{
hasTags.Tags = request.Tags;
}
item.Tags = request.Tags;
var hasTaglines = item as IHasTaglines;
if (hasTaglines != null)
@ -298,11 +294,7 @@ namespace MediaBrowser.Api
hasShortOverview.ShortOverview = request.ShortOverview;
}
var hasKeywords = item as IHasKeywords;
if (hasKeywords != null)
{
hasKeywords.Keywords = request.Keywords;
}
item.Keywords = request.Keywords;
if (request.Studios != null)
{
@ -427,11 +419,6 @@ namespace MediaBrowser.Api
series.Status = request.SeriesStatus;
series.AirDays = request.AirDays;
series.AirTime = request.AirTime;
if (request.DisplaySpecialsWithSeasons.HasValue)
{
series.DisplaySpecialsWithSeasons = request.DisplaySpecialsWithSeasons.Value;
}
}
}

View File

@ -439,6 +439,12 @@ namespace MediaBrowser.Api.LiveTv
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")]
[Authenticated(AllowBeforeStartupWizard = true)]
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")]
[Authenticated]
public class GetLiveTvRegistrationInfo : IReturn<MBRegistrationRecord>
@ -525,6 +565,11 @@ namespace MediaBrowser.Api.LiveTv
_dtoService = dtoService;
}
public object Get(GetDefaultListingProvider request)
{
return ToOptimizedResult(new ListingsProviderInfo());
}
public async Task<object> Get(GetSatChannnelScanResult request)
{
var result = await _liveTvManager.GetSatChannelScanResult(request, CancellationToken.None).ConfigureAwait(false);
@ -539,6 +584,102 @@ namespace MediaBrowser.Api.LiveTv
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)
{
return ToOptimizedResult(_liveTvManager.GetSatIniMappings());
@ -550,9 +691,7 @@ namespace MediaBrowser.Api.LiveTv
var response = await _httpClient.Get(new HttpRequestOptions
{
Url = "https://json.schedulesdirect.org/20141201/available/countries",
CacheLength = TimeSpan.FromDays(1),
CacheMode = CacheMode.Unconditional
Url = "https://json.schedulesdirect.org/20141201/available/countries"
}).ConfigureAwait(false);
@ -609,6 +748,11 @@ namespace MediaBrowser.Api.LiveTv
return _config.GetConfiguration<LiveTvOptions>("livetv");
}
private void UpdateConfiguration(LiveTvOptions options)
{
_config.SaveConfiguration("livetv", options);
}
public async Task<object> Get(GetLineups request)
{
var info = await _liveTvManager.GetLineups(request.Type, request.Id, request.Country, request.Location).ConfigureAwait(false);

View File

@ -14,6 +14,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MediaBrowser.Controller.LiveTv;
namespace MediaBrowser.Api.Movies
{
@ -110,18 +111,16 @@ namespace MediaBrowser.Api.Movies
/// </summary>
/// <param name="request">The request.</param>
/// <returns>System.Object.</returns>
public async Task<object> Get(GetSimilarMovies request)
public object Get(GetSimilarMovies request)
{
var result = await GetSimilarItemsResult(
request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
var result = GetSimilarItemsResult(request);
return ToOptimizedSerializedResultUsingCache(result);
}
public async Task<object> Get(GetSimilarTrailers request)
public object Get(GetSimilarTrailers request)
{
var result = await GetSimilarItemsResult(
request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false);
var result = GetSimilarItemsResult(request);
return ToOptimizedSerializedResultUsingCache(result);
}
@ -130,52 +129,16 @@ namespace MediaBrowser.Api.Movies
{
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);
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);
}
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;
@ -183,95 +146,68 @@ namespace MediaBrowser.Api.Movies
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
var query = new InternalItemsQuery(user)
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Movie).Name }
};
if (user == null || user.Configuration.IncludeTrailersInSuggestions)
Limit = request.Limit,
IncludeItemTypes = new[]
{
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
.Where(i => !string.Equals(imdbId, i.GetProviderId(MetadataProviders.Imdb), StringComparison.OrdinalIgnoreCase))
.ToList();
}
}
var items = SimilarItemsHelper.GetSimilaritems(item, _libraryManager, list, getSimilarityScore).ToList();
IEnumerable<BaseItem> returnItems = items;
if (request.Limit.HasValue)
{
returnItems = returnItems.Take(request.Limit.Value);
}
typeof(Movie).Name,
typeof(Trailer).Name,
typeof(LiveTvProgram).Name
},
IsMovie = true,
SimilarTo = item
}).ToList();
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;
}
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 recentlyPlayedMovies = allMoviesForCategories
.Select(i =>
var parentIds = string.IsNullOrWhiteSpace(parentId) ? new string[] { } : new[] { parentId };
var query = new InternalItemsQuery(user)
{
var userdata = _userDataRepository.GetUserData(user, i);
return new Tuple<BaseItem, bool, DateTime>(i, userdata.Played, userdata.LastPlayedDate ?? DateTime.MinValue);
})
.Where(i => i.Item2)
.OrderByDescending(i => i.Item3)
.Select(i => i.Item1)
.ToList();
IncludeItemTypes = new[]
{
typeof(Movie).Name,
//typeof(Trailer).Name,
//typeof(LiveTvProgram).Name
},
// IsMovie = true
SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.Random },
SortOrder = SortOrder.Descending,
Limit = 7
};
var excludeFromLiked = recentlyPlayedMovies.Take(10);
var likedMovies = allMovies
.Select(i =>
{
var score = 0;
var userData = _userDataRepository.GetUserData(user, i);
var recentlyPlayedMovies = _libraryManager.GetItemList(query, parentIds).ToList();
if (userData.IsFavorite)
var likedMovies = _libraryManager.GetItemList(new InternalItemsQuery(user)
{
score = 2;
}
else
IncludeItemTypes = new[]
{
score = userData.Likes.HasValue ? userData.Likes.Value ? 1 : -1 : 0;
}
typeof(Movie).Name,
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()
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));
}, parentIds).ToList();
var mostRecentMovies = recentlyPlayedMovies.Take(6).ToList();
// Get recently played directors
@ -284,11 +220,11 @@ namespace MediaBrowser.Api.Movies
.OrderBy(i => Guid.NewGuid())
.ToList();
var similarToRecentlyPlayed = GetSimilarTo(user, allMovies, recentlyPlayedMovies.Take(7).OrderBy(i => Guid.NewGuid()), itemLimit, dtoOptions, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator();
var similarToLiked = GetSimilarTo(user, allMovies, likedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToLikedItem).GetEnumerator();
var similarToRecentlyPlayed = GetSimilarTo(user, recentlyPlayedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator();
var similarToLiked = GetSimilarTo(user, likedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToLikedItem).GetEnumerator();
var hasDirectorFromRecentlyPlayed = GetWithDirector(user, allMovies, recentDirectors, itemLimit, dtoOptions, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator();
var hasActorFromRecentlyPlayed = GetWithActor(user, allMovies, recentActors, itemLimit, dtoOptions, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator();
var hasDirectorFromRecentlyPlayed = GetWithDirector(user, recentDirectors, itemLimit, dtoOptions, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator();
var hasActorFromRecentlyPlayed = GetWithActor(user, recentActors, itemLimit, dtoOptions, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator();
var categoryTypes = new List<IEnumerator<RecommendationDto>>
{
@ -331,42 +267,25 @@ namespace MediaBrowser.Api.Movies
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)
{
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)
private IEnumerable<RecommendationDto> GetWithDirector(User user, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
{
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
});
var items = allMovies
.Where(i => itemsWithActor.Contains(i.Id))
}).DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
.Take(itemLimit)
.ToList();
@ -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)
{
var similar = SimilarItemsHelper
.GetSimilaritems(item, _libraryManager, allMovies, SimilarItemsHelper.GetSimiliarityScore)
.Take(itemLimit)
.ToList();
var similar = _libraryManager.GetItemList(new InternalItemsQuery(user)
{
Limit = itemLimit,
IncludeItemTypes = new[]
{
typeof(Movie).Name,
typeof(Trailer).Name,
typeof(LiveTvProgram).Name
},
IsMovie = true,
SimilarTo = item
}).ToList();
if (similar.Count > 0)
{

View File

@ -846,7 +846,7 @@ namespace MediaBrowser.Api.Playback
if (MediaEncoder.SupportsDecoder("h264_qsv"))
{
// Seeing stalls and failures with decoding. Not worth it compared to encoding.
//return "-c:v h264_qsv ";
return "-c:v h264_qsv ";
}
break;
case "mpeg2video":
@ -980,11 +980,6 @@ namespace MediaBrowser.Api.Playback
var transcodingId = Guid.NewGuid().ToString("N");
var commandLineArgs = GetCommandLineArguments(outputPath, state, true);
if (ApiEntryPoint.Instance.GetEncodingOptions().EnableDebugLogging)
{
commandLineArgs = "-loglevel debug " + commandLineArgs;
}
var process = new Process
{
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;
@ -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;
}
@ -1518,6 +1525,13 @@ namespace MediaBrowser.Api.Playback
}
}
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)
{
@ -1528,7 +1542,7 @@ namespace MediaBrowser.Api.Playback
}
}
}
else if (i == 26)
else if (i == 27)
{
request.TranscodingMaxAudioChannels = int.Parse(val, UsCulture);
}
@ -1690,7 +1704,7 @@ namespace MediaBrowser.Api.Playback
if (videoRequest != null)
{
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)
{

View File

@ -96,7 +96,7 @@ namespace MediaBrowser.Api.Playback
public long? InputFileSize { get; set; }
public string OutputAudioSync = "1";
public string OutputVideoSync = "vfr";
public string OutputVideoSync = "-1";
public List<string> SupportedAudioCodecs { get; set; }

View File

@ -213,7 +213,6 @@ namespace MediaBrowser.Api.Reports
NameStartsWith = request.NameStartsWith,
NameStartsWithOrGreater = request.NameStartsWithOrGreater,
HasImdbId = request.HasImdbId,
IsYearMismatched = request.IsYearMismatched,
IsPlaceHolder = request.IsPlaceHolder,
IsLocked = request.IsLocked,
IsInBoxSet = request.IsInBoxSet,

View File

@ -116,24 +116,12 @@ namespace MediaBrowser.Api
private static IEnumerable<string> GetTags(BaseItem item)
{
var hasTags = item as IHasTags;
if (hasTags != null)
{
return hasTags.Tags;
}
return new List<string>();
return item.Tags;
}
private static IEnumerable<string> GetKeywords(BaseItem item)
{
var hasTags = item as IHasKeywords;
if (hasTags != null)
{
return hasTags.Keywords;
}
return new List<string>();
return item.Keywords;
}
/// <summary>

View File

@ -111,10 +111,10 @@ namespace MediaBrowser.Api
{
config.EnableLocalizedGuids = true;
config.EnableCustomPathSubFolders = true;
config.EnableDateLastRefresh = true;
config.EnableStandaloneMusicKeys = true;
config.EnableCaseSensitiveItemIds = true;
config.SchemaVersion = 79;
config.EnableFolderView = true;
config.SchemaVersion = 92;
}
public void Post(UpdateStartupConfiguration request)

View File

@ -98,6 +98,10 @@ namespace MediaBrowser.Api.Subtitles
[ApiMember(Name = "EndPositionTicks", Description = "EndPositionTicks", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
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.")]
@ -175,7 +179,7 @@ namespace MediaBrowser.Api.Subtitles
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),
endPositionTicks.ToString(CultureInfo.InvariantCulture),
accessToken);
@ -190,7 +194,7 @@ namespace MediaBrowser.Api.Subtitles
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))
{
@ -209,20 +213,32 @@ namespace MediaBrowser.Api.Subtitles
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");
}
private async Task<Stream> GetSubtitles(GetSubtitle request)
return ResultFactory.GetResult(text, MimeTypes.GetMimeType("file." + request.Format));
}
}
}
private Task<Stream> GetSubtitles(GetSubtitle request)
{
return await _subtitleEncoder.GetSubtitles(request.Id,
return _subtitleEncoder.GetSubtitles(request.Id,
request.MediaSourceId,
request.Index,
request.Format,
request.StartPositionTicks,
request.EndPositionTicks,
CancellationToken.None).ConfigureAwait(false);
request.CopyTimestamps,
CancellationToken.None);
}
public object Get(SearchRemoteSubtitles request)

View File

@ -12,6 +12,7 @@ using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;
using MediaBrowser.Model.Dto;
namespace MediaBrowser.Api
{
@ -273,20 +274,42 @@ namespace MediaBrowser.Api
/// <returns>System.Object.</returns>
public object Get(GetSimilarShows request)
{
var dtoOptions = GetDtoOptions(request);
var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager,
_itemRepo,
_libraryManager,
_userDataManager,
_dtoService,
Logger,
request, new[] { typeof(Series) },
SimilarItemsHelper.GetSimiliarityScore);
var result = GetSimilarItemsResult(request);
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)
{
var user = _userManager.GetUserById(request.UserId);

View File

@ -333,12 +333,7 @@ namespace MediaBrowser.Api.UserLibrary
var tags = request.GetTags();
if (tags.Length > 0)
{
var hasTags = i as IHasTags;
if (hasTags == null)
{
return false;
}
if (!tags.Any(v => hasTags.Tags.Contains(v, StringComparer.OrdinalIgnoreCase)))
if (!tags.Any(v => i.Tags.Contains(v, StringComparer.OrdinalIgnoreCase)))
{
return false;
}

View File

@ -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")]
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")]
public bool? IsInBoxSet { get; set; }

View File

@ -187,7 +187,6 @@ namespace MediaBrowser.Api.UserLibrary
NameStartsWith = request.NameStartsWith,
NameStartsWithOrGreater = request.NameStartsWithOrGreater,
HasImdbId = request.HasImdbId,
IsYearMismatched = request.IsYearMismatched,
IsPlaceHolder = request.IsPlaceHolder,
IsLocked = request.IsLocked,
IsInBoxSet = request.IsInBoxSet,

View File

@ -385,7 +385,7 @@ namespace MediaBrowser.Api
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);
}
@ -465,6 +465,10 @@ namespace MediaBrowser.Api
}
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.");
}
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);

View File

@ -552,7 +552,7 @@ namespace MediaBrowser.Common.Implementations
}
catch (Exception ex)
{
Logger.Error("Error creating {0}", ex, type.Name);
Logger.ErrorException("Error creating {0}", ex, type.Name);
throw;
}
@ -571,7 +571,7 @@ namespace MediaBrowser.Common.Implementations
}
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
return null;
}

View File

@ -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 httpWebRequest = request as HttpWebRequest;
@ -154,7 +154,9 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
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);
@ -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 ||
!string.IsNullOrEmpty(options.RequestContent) ||
@ -556,7 +558,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
options.CancellationToken.ThrowIfCancellationRequested();
var httpWebRequest = GetRequest(options, "GET", options.EnableHttpCompression);
var httpWebRequest = GetRequest(options, "GET");
if (options.ResourcePool != null)
{

View File

@ -65,8 +65,8 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
</Reference>
<Reference Include="SimpleInjector, Version=3.1.4.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
<HintPath>..\packages\SimpleInjector.3.1.4\lib\net45\SimpleInjector.dll</HintPath>
<Reference Include="SimpleInjector, Version=3.1.5.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
<HintPath>..\packages\SimpleInjector.3.1.5\lib\net45\SimpleInjector.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />

View File

@ -4,5 +4,5 @@
<package id="morelinq" version="1.4.0" targetFramework="net45" />
<package id="NLog" version="4.3.4" 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>

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
namespace MediaBrowser.Common.Net
@ -16,6 +17,8 @@ namespace MediaBrowser.Common.Net
/// <value>The URL.</value>
public string Url { get; set; }
public DecompressionMethods? DecompressionMethod { get; set; }
/// <summary>
/// Gets or sets the accept header.
/// </summary>

View File

@ -53,6 +53,8 @@ namespace MediaBrowser.Controller.Channels
public bool IsInfiniteStream { get; set; }
public string HomePageUrl { get; set; }
public ChannelItemInfo()
{
MediaSources = new List<ChannelMediaInfo>();

View File

@ -33,7 +33,7 @@ namespace MediaBrowser.Controller.Chapters
/// <param name="chapters">The chapters.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SaveChapters(string itemId, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken);
Task SaveChapters(string itemId, List<ChapterInfo> chapters, CancellationToken cancellationToken);
/// <summary>
/// Searches the specified video.

View File

@ -20,7 +20,6 @@ namespace MediaBrowser.Controller.Entities.Audio
IHasArtist,
IHasMusicGenres,
IHasLookupInfo<SongInfo>,
IHasTags,
IHasMediaSources,
IThemeMedia,
IArchivable

View File

@ -179,17 +179,13 @@ namespace MediaBrowser.Controller.Entities.Audio
{
var items = GetRecursiveChildren().ToList();
var songs = items.OfType<Audio>().ToList();
var others = items.Except(songs).ToList();
var totalItems = songs.Count + others.Count;
var totalItems = items.Count;
var numComplete = 0;
var childUpdateType = ItemUpdateType.None;
// Refresh songs
foreach (var item in songs)
foreach (var item in items)
{
cancellationToken.ThrowIfCancellationRequested();
@ -199,7 +195,7 @@ namespace MediaBrowser.Controller.Entities.Audio
numComplete++;
double percent = numComplete;
percent /= totalItems;
progress.Report(percent * 100);
progress.Report(percent * 95);
}
var parentRefreshOptions = refreshOptions;
@ -212,19 +208,6 @@ namespace MediaBrowser.Controller.Entities.Audio
// Refresh current item
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);
}
}

View File

@ -62,13 +62,6 @@ namespace MediaBrowser.Controller.Entities.Audio
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);
}

View File

@ -26,6 +26,7 @@ using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Providers;
namespace MediaBrowser.Controller.Entities
{
@ -36,6 +37,7 @@ namespace MediaBrowser.Controller.Entities
{
protected BaseItem()
{
Keywords = new List<string>();
Tags = new List<string>();
Genres = new List<string>();
Studios = new List<string>();
@ -69,10 +71,14 @@ namespace MediaBrowser.Controller.Entities
public List<ItemImageInfo> ImageInfos { get; set; }
[IgnoreDataMember]
public bool IsVirtualItem { get; set; }
/// <summary>
/// Gets or sets the album.
/// </summary>
/// <value>The album.</value>
[IgnoreDataMember]
public string Album { get; set; }
/// <summary>
@ -810,6 +816,8 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public List<string> Tags { get; set; }
public List<string> Keywords { get; set; }
/// <summary>
/// Gets or sets the home page URL.
/// </summary>
@ -1031,9 +1039,7 @@ namespace MediaBrowser.Controller.Entities
}
: options;
var result = await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
return result;
return await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
}
[IgnoreDataMember]
@ -1393,17 +1399,12 @@ namespace MediaBrowser.Controller.Entities
}
private bool IsVisibleViaTags(User user)
{
var hasTags = this as IHasTags;
if (hasTags != null)
{
var policy = user.Policy;
if (policy.BlockedTags.Any(i => hasTags.Tags.Contains(i, StringComparer.OrdinalIgnoreCase)))
if (policy.BlockedTags.Any(i => Tags.Contains(i, StringComparer.OrdinalIgnoreCase)))
{
return false;
}
}
return true;
}
@ -2214,5 +2215,10 @@ namespace MediaBrowser.Controller.Entities
DeleteFileLocation = false
});
}
public virtual List<ExternalUrl> GetRelatedUrls()
{
return new List<ExternalUrl>();
}
}
}

View File

@ -6,7 +6,7 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Entities
{
public class Book : BaseItem, IHasTags, IHasLookupInfo<BookInfo>, IHasSeries
public class Book : BaseItem, IHasLookupInfo<BookInfo>, IHasSeries
{
[IgnoreDataMember]
public override string MediaType

View File

@ -20,7 +20,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Class Folder
/// </summary>
public class Folder : BaseItem, IHasThemeMedia, IHasTags
public class Folder : BaseItem, IHasThemeMedia
{
public static IUserManager UserManager { get; set; }
public static IUserViewManager UserViewManager { get; set; }
@ -164,49 +164,15 @@ namespace MediaBrowser.Controller.Entities
item.DateModified = DateTime.UtcNow;
}
AddChildInternal(item.Id);
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>
/// Removes the child.
/// </summary>
/// <param name="item">The item.</param>
public void RemoveChild(BaseItem item)
{
RemoveChildrenInternal(new[] { item.Id }.ToList());
item.SetParent(null);
}
@ -241,33 +207,6 @@ namespace MediaBrowser.Controller.Entities
#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>
/// Gets the actual children.
/// </summary>
@ -277,7 +216,7 @@ namespace MediaBrowser.Controller.Entities
{
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)
{
if (item.LocationType == LocationType.Virtual ||
item.LocationType == LocationType.Remote)
var itemLocationType = item.LocationType;
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))
{
await UpdateIsOffline(item, true).ConfigureAwait(false);
validChildren.Add(item);
}
else
{
@ -481,8 +418,6 @@ namespace MediaBrowser.Controller.Entities
if (actualRemovals.Count > 0)
{
RemoveChildrenInternal(actualRemovals.Select(i => i.Id).ToList());
foreach (var item in actualRemovals)
{
Logger.Debug("Removed item: " + item.Path);
@ -495,8 +430,6 @@ namespace MediaBrowser.Controller.Entities
}
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)
{
var user = query.User;
@ -768,58 +722,13 @@ namespace MediaBrowser.Controller.Entities
{
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;
}
}
var supportsUserDataQueries = ConfigurationManager.Configuration.SchemaVersion >= 76;
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))
{
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");
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))
{
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");
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))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.VideoBitRate");
@ -884,39 +783,6 @@ namespace MediaBrowser.Controller.Entities
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)
{
Logger.Debug("Query requires post-filtering due to IsInBoxSet");
@ -930,30 +796,6 @@ namespace MediaBrowser.Controller.Entities
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)
{
Logger.Debug("Query requires post-filtering due to HasOfficialRating");
@ -1003,12 +845,6 @@ namespace MediaBrowser.Controller.Entities
return true;
}
if (query.ImageTypes.Length > 0)
{
Logger.Debug("Query requires post-filtering due to ImageTypes");
return true;
}
// Apply studio filter
if (query.StudioIds.Length > 0)
{
@ -1042,12 +878,6 @@ namespace MediaBrowser.Controller.Entities
return true;
}
if (query.OfficialRatings.Length > 0)
{
Logger.Debug("Query requires post-filtering due to OfficialRatings");
return true;
}
if (query.IsMissing.HasValue)
{
Logger.Debug("Query requires post-filtering due to IsMissing");
@ -1066,7 +896,7 @@ namespace MediaBrowser.Controller.Entities
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");
return true;
@ -1102,15 +932,6 @@ namespace MediaBrowser.Controller.Entities
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;
}
@ -1183,7 +1004,7 @@ namespace MediaBrowser.Controller.Entities
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)
@ -1613,60 +1434,36 @@ namespace MediaBrowser.Controller.Entities
return;
}
var recursiveItemCount = 0;
var unplayed = 0;
double totalPercentPlayed = 0;
var itemsResult = GetItems(new InternalItemsQuery(user)
var unplayedQueryResult = GetItems(new InternalItemsQuery(user)
{
Recursive = true,
IsFolder = false,
ExcludeLocationTypes = new[] { LocationType.Virtual },
EnableTotalRecordCount = false
IsVirtualItem = false,
EnableTotalRecordCount = true,
Limit = 0,
IsPlayed = false
}).Result;
var children = itemsResult.Items;
// Loop through each recursive child
foreach (var child in children)
var allItemsQueryResult = GetItems(new InternalItemsQuery(user)
{
recursiveItemCount++;
Recursive = true,
IsFolder = false,
IsVirtualItem = false,
EnableTotalRecordCount = true,
Limit = 0
var isUnplayed = true;
}).Result;
var itemUserData = UserDataManager.GetUserData(user, child);
// 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;
double recursiveItemCount = allItemsQueryResult.TotalRecordCount;
double unplayedCount = unplayedQueryResult.TotalRecordCount;
if (recursiveItemCount > 0)
{
dto.PlayedPercentage = totalPercentPlayed / recursiveItemCount;
var unplayedPercentage = (unplayedCount / recursiveItemCount) * 100;
dto.PlayedPercentage = 100 - unplayedPercentage;
dto.Played = dto.PlayedPercentage.Value >= 100;
dto.UnplayedItemCount = unplayedQueryResult.TotalRecordCount;
}
}
}

View File

@ -7,7 +7,7 @@ using System.Linq;
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> ThemeVideoIds { get; set; }

View File

@ -19,6 +19,8 @@ namespace MediaBrowser.Controller.Entities
public User User { get; set; }
public BaseItem SimilarTo { get; set; }
public bool? IsFolder { get; set; }
public bool? IsFavorite { get; set; }
public bool? IsFavoriteOrLiked { get; set; }
@ -33,6 +35,7 @@ namespace MediaBrowser.Controller.Entities
public string[] ExcludeTags { get; set; }
public string[] ExcludeInheritedTags { get; set; }
public string[] Genres { get; set; }
public string[] Keywords { get; set; }
public bool? IsMissing { get; set; }
public bool? IsUnaired { get; set; }
@ -52,6 +55,7 @@ namespace MediaBrowser.Controller.Entities
public string Person { get; set; }
public string[] PersonIds { get; set; }
public string[] ItemIds { get; set; }
public string[] ExcludeItemIds { get; set; }
public string AdjacentTo { get; set; }
public string[] PersonTypes { get; set; }
@ -60,7 +64,6 @@ namespace MediaBrowser.Controller.Entities
public bool? IsInBoxSet { get; set; }
public bool? IsLocked { get; set; }
public bool? IsPlaceHolder { get; set; }
public bool? IsYearMismatched { get; set; }
public bool? HasImdbId { get; set; }
public bool? HasOverview { get; set; }
@ -107,6 +110,7 @@ namespace MediaBrowser.Controller.Entities
internal List<Guid> ItemIdsFromPersonFilters { get; set; }
public int? ParentIndexNumber { get; set; }
public int? ParentIndexNumberNotEquals { get; set; }
public int? IndexNumber { get; set; }
public int? MinParentalRating { get; set; }
public int? MaxParentalRating { get; set; }
@ -114,6 +118,7 @@ namespace MediaBrowser.Controller.Entities
public bool? IsCurrentSchema { get; set; }
public bool? HasDeadParentId { get; set; }
public bool? IsOffline { get; set; }
public bool? IsVirtualItem { get; set; }
public Guid? ParentId { get; set; }
public string[] AncestorIds { get; set; }
@ -137,6 +142,8 @@ namespace MediaBrowser.Controller.Entities
public bool GroupByPresentationUniqueKey { get; set; }
public bool EnableTotalRecordCount { get; set; }
public bool ForceDirect { get; set; }
public Dictionary<string, string> ExcludeProviderIds { get; set; }
public string GroupByAncestorOfType { get; set; }
public InternalItemsQuery()
{
@ -145,12 +152,14 @@ namespace MediaBrowser.Controller.Entities
AlbumNames = new string[] { };
ArtistNames = new string[] { };
ExcludeProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
BlockUnratedItems = new UnratedItem[] { };
Tags = new string[] { };
OfficialRatings = new string[] { };
SortBy = new string[] { };
MediaTypes = new string[] { };
Keywords = new string[] { };
IncludeItemTypes = new string[] { };
ExcludeItemTypes = new string[] { };
Genres = new string[] { };
@ -164,6 +173,7 @@ namespace MediaBrowser.Controller.Entities
PersonIds = new string[] { };
ChannelIds = new string[] { };
ItemIds = new string[] { };
ExcludeItemIds = new string[] { };
AncestorIds = new string[] { };
TopParentIds = new string[] { };
ExcludeTags = new string[] { };

View File

@ -1,21 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
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 void AddKeyword(this IHasKeywords item, string name)
public static void AddKeyword(this BaseItem item, string name)
{
if (string.IsNullOrWhiteSpace(name))
{

View File

@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Entities.Movies
/// <summary>
/// Class BoxSet
/// </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; }
@ -26,7 +26,6 @@ namespace MediaBrowser.Controller.Entities.Movies
RemoteTrailerIds = new List<Guid>();
DisplayOrder = ItemSortBy.PremiereDate;
Keywords = new List<string>();
Shares = new List<Share>();
}
@ -47,12 +46,6 @@ namespace MediaBrowser.Controller.Entities.Movies
/// <value>The remote trailers.</value>
public List<MediaUrl> RemoteTrailers { get; set; }
/// <summary>
/// Gets or sets the tags.
/// </summary>
/// <value>The tags.</value>
public List<string> Keywords { get; set; }
/// <summary>
/// Gets or sets the display order.
/// </summary>

View File

@ -8,13 +8,14 @@ using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Model.Providers;
namespace MediaBrowser.Controller.Entities.Movies
{
/// <summary>
/// Class Movie
/// </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; }
@ -31,7 +32,6 @@ namespace MediaBrowser.Controller.Entities.Movies
ThemeSongIds = new List<Guid>();
ThemeVideoIds = new List<Guid>();
Taglines = new List<string>();
Keywords = 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> RemoteTrailerIds { get; set; }
public List<string> Keywords { get; set; }
public List<MediaUrl> RemoteTrailers { get; set; }
@ -163,5 +162,22 @@ namespace MediaBrowser.Controller.Entities.Movies
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;
}
}
}

View File

@ -5,7 +5,7 @@ using System.Runtime.Serialization;
namespace MediaBrowser.Controller.Entities
{
public class Photo : BaseItem, IHasTags, IHasTaglines
public class Photo : BaseItem, IHasTaglines
{
public List<string> Taglines { get; set; }

View File

@ -8,7 +8,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Class Studio
/// </summary>
public class Studio : BaseItem, IItemByName, IHasTags
public class Studio : BaseItem, IItemByName
{
public override List<string> GetUserDataKeys()
{

View File

@ -11,8 +11,20 @@ namespace MediaBrowser.Controller.Entities.TV
/// <summary>
/// Class Episode
/// </summary>
public class Episode : Video, IHasLookupInfo<EpisodeInfo>, IHasSeries
public class Episode : Video, IHasTrailers, IHasLookupInfo<EpisodeInfo>, IHasSeries
{
public Episode()
{
RemoteTrailers = new List<MediaUrl>();
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>
@ -96,7 +108,13 @@ namespace MediaBrowser.Controller.Entities.TV
var series = Series;
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;

View File

@ -75,6 +75,11 @@ namespace MediaBrowser.Controller.Entities.TV
return list;
}
public override int GetChildCount(User user)
{
return GetChildren(user, true).Count();
}
/// <summary>
/// This Episode's Series Instance
/// </summary>
@ -128,39 +133,16 @@ namespace MediaBrowser.Controller.Entities.TV
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]
public bool IsMissingSeason
{
get { return (IsVirtualItem ?? DetectIsVirtualItem()) && !IsUnaired; }
get { return (IsVirtualItem) && !IsUnaired; }
}
[IgnoreDataMember]
public bool IsVirtualUnaired
{
get { return (IsVirtualItem ?? DetectIsVirtualItem()) && IsUnaired; }
}
private bool DetectIsVirtualItem()
{
return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.LocationType == LocationType.Virtual);
get { return (IsVirtualItem) && IsUnaired; }
}
[IgnoreDataMember]
@ -196,52 +178,17 @@ namespace MediaBrowser.Controller.Entities.TV
{
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;
if (IndexNumber.HasValue && series != null)
{
return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes);
return GetEpisodes(series, user, includeMissingEpisodes, includeVirtualUnairedEpisodes, null);
}
var episodes = GetRecursiveChildren(user)
.OfType<Episode>();
if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
public IEnumerable<Episode> GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes)
{
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>();
return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes, allSeriesEpisodes);
}
public IEnumerable<Episode> GetEpisodes()

View File

@ -9,6 +9,7 @@ using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Providers;
using MoreLinq;
namespace MediaBrowser.Controller.Entities.TV
@ -30,7 +31,6 @@ namespace MediaBrowser.Controller.Entities.TV
RemoteTrailers = new List<MediaUrl>();
LocalTrailerIds = new List<Guid>();
RemoteTrailerIds = new List<Guid>();
DisplaySpecialsWithSeasons = true;
}
[IgnoreDataMember]
@ -57,8 +57,6 @@ namespace MediaBrowser.Controller.Entities.TV
}
}
public bool DisplaySpecialsWithSeasons { get; set; }
public List<Guid> LocalTrailerIds { get; set; }
public List<Guid> RemoteTrailerIds { get; set; }
@ -94,10 +92,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
get
{
return GetRecursiveChildren(i => i is Episode)
.Select(i => i.DateCreated)
.OrderByDescending(i => i)
.FirstOrDefault();
return DateLastMediaAdded ?? DateTime.MinValue;
}
}
@ -106,14 +101,30 @@ namespace MediaBrowser.Controller.Entities.TV
{
get
{
if (EnablePooling())
var userdatakeys = GetUserDataKeys();
if (userdatakeys.Count > 1)
{
return GetUserDataKeys().First();
return userdatakeys[0];
}
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>
/// Gets the user data key.
/// </summary>
@ -182,27 +193,32 @@ namespace MediaBrowser.Controller.Entities.TV
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
{
if (query.User == null)
{
return base.GetItemsInternal(query);
}
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);
IEnumerable<BaseItem> items;
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 items = GetSeasons(user).Where(filter);
var result = PostFilterAndSort(items, query);
return Task.FromResult(result);
}
@ -210,33 +226,13 @@ namespace MediaBrowser.Controller.Entities.TV
{
IEnumerable<Season> seasons;
if (EnablePooling())
{
var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user)
{
PresentationUniqueKey = PresentationUniqueKey,
IncludeItemTypes = new[] { typeof(Series).Name }
});
if (seriesIds.Count > 1)
{
seasons = LibraryManager.GetItemList(new InternalItemsQuery(user)
{
AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(),
AncestorWithPresentationUniqueKey = PresentationUniqueKey,
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)
{
@ -259,8 +255,18 @@ namespace MediaBrowser.Controller.Entities.TV
public IEnumerable<Episode> GetEpisodes(User user, bool includeMissing, bool includeVirtualUnaired)
{
var allEpisodes = GetSeasons(user, true, true)
.SelectMany(i => i.GetEpisodes(user, includeMissing, includeVirtualUnaired))
var allItems = LibraryManager.GetItemList(new InternalItemsQuery(user)
{
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()
.ToList();
@ -283,9 +289,6 @@ namespace MediaBrowser.Controller.Entities.TV
var totalItems = seasons.Count + otherItems.Count;
var numComplete = 0;
refreshOptions = new MetadataRefreshOptions(refreshOptions);
refreshOptions.IsPostRecursiveRefresh = true;
// Refresh current item
await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
@ -315,7 +318,7 @@ namespace MediaBrowser.Controller.Entities.TV
&& refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh
&& !refreshOptions.ReplaceAllMetadata
&& episode.IsMissingEpisode
&& episode.LocationType == Model.Entities.LocationType.Virtual
&& episode.LocationType == LocationType.Virtual
&& episode.PremiereDate.HasValue
&& (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30)
{
@ -333,6 +336,8 @@ namespace MediaBrowser.Controller.Entities.TV
progress.Report(percent * 100);
}
refreshOptions = new MetadataRefreshOptions(refreshOptions);
refreshOptions.IsPostRecursiveRefresh = true;
await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
progress.Report(100);
@ -345,50 +350,32 @@ namespace MediaBrowser.Controller.Entities.TV
return GetEpisodes(user, season, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
}
private bool EnablePooling()
private IEnumerable<Episode> GetAllEpisodes(User user)
{
return false;
}
public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
return LibraryManager.GetItemList(new InternalItemsQuery(user)
{
IEnumerable<Episode> episodes;
if (EnablePooling())
{
var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user)
{
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(),
AncestorWithPresentationUniqueKey = PresentationUniqueKey,
IncludeItemTypes = new[] { typeof(Episode).Name },
SortBy = new[] { ItemSortBy.SortName }
}).Cast<Episode>();
}
else
public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
{
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>();
IEnumerable<Episode> episodes = GetAllEpisodes(user);
return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes);
}
episodes = FilterEpisodesBySeason(episodes, parentSeason, DisplaySpecialsWithSeasons);
public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes)
{
if (allSeriesEpisodes == null)
{
return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes);
}
var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons);
if (!includeMissingEpisodes)
{
@ -436,38 +423,31 @@ namespace MediaBrowser.Controller.Entities.TV
public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, Season parentSeason, bool includeSpecials)
{
var seasonNumber = parentSeason.IndexNumber;
if (!includeSpecials || (seasonNumber.HasValue && seasonNumber.Value == 0))
{
var seasonPresentationKey = parentSeason.PresentationUniqueKey;
return episodes.Where(i =>
{
if ((i.ParentIndexNumber ?? -1) == seasonNumber)
{
return true;
}
var season = i.Season;
return season != null && string.Equals(season.PresentationUniqueKey, seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
});
}
else
{
var seasonPresentationKey = parentSeason.PresentationUniqueKey;
var supportSpecialsInSeason = includeSpecials && seasonNumber.HasValue && seasonNumber.Value != 0;
return episodes.Where(episode =>
{
var currentSeasonNumber = episode.AiredSeasonNumber;
var currentSeasonNumber = supportSpecialsInSeason ? episode.AiredSeasonNumber : episode.ParentIndexNumber;
if (currentSeasonNumber.HasValue && seasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber.Value)
{
return true;
}
if (!currentSeasonNumber.HasValue && !seasonNumber.HasValue && parentSeason.LocationType == LocationType.Virtual)
{
return true;
}
if (!episode.ParentIndexNumber.HasValue)
{
var season = episode.Season;
return season != null && string.Equals(season.PresentationUniqueKey, seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
});
}
return false;
});
}
protected override bool GetBlockUnratedValue(UserPolicy config)
@ -508,5 +488,22 @@ namespace MediaBrowser.Controller.Entities.TV
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;
}
}
}

View File

@ -1,24 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
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 void AddTag(this IHasTags item, string name)
public static void AddTag(this BaseItem item, string name)
{
if (string.IsNullOrWhiteSpace(name))
{

View File

@ -5,13 +5,14 @@ using System.Collections.Generic;
using System.Globalization;
using System.Runtime.Serialization;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Model.Providers;
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Class Trailer
/// </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; }
@ -30,8 +31,6 @@ namespace MediaBrowser.Controller.Entities
public List<MediaUrl> RemoteTrailers { get; set; }
public List<string> Keywords { get; set; }
[IgnoreDataMember]
public bool IsLocalTrailer
{
@ -110,5 +109,22 @@ namespace MediaBrowser.Controller.Entities
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;
}
}
}

View File

@ -38,6 +38,11 @@ namespace MediaBrowser.Controller.Entities
return PostFilterAndSort(result.Where(filter), query);
}
public override int GetChildCount(User user)
{
return GetChildren(user, true).Count();
}
[IgnoreDataMember]
protected override bool SupportsShortcutChildren
{

View File

@ -45,6 +45,11 @@ namespace MediaBrowser.Controller.Entities
return list;
}
public override int GetChildCount(User user)
{
return GetChildren(user, true).Count();
}
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
{
var parent = this as Folder;
@ -58,7 +63,7 @@ namespace MediaBrowser.Controller.Entities
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);
}

View File

@ -18,6 +18,8 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Controller.Entities
{
@ -30,10 +32,10 @@ namespace MediaBrowser.Controller.Entities
private readonly ILogger _logger;
private readonly IUserDataManager _userDataManager;
private readonly ITVSeriesManager _tvSeriesManager;
private readonly ICollectionManager _collectionManager;
private readonly IServerConfigurationManager _config;
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;
_liveTvManager = liveTvManager;
@ -42,7 +44,7 @@ namespace MediaBrowser.Controller.Entities
_logger = logger;
_userDataManager = userDataManager;
_tvSeriesManager = tvSeriesManager;
_collectionManager = collectionManager;
_config = config;
_playlistManager = playlistManager;
}
@ -159,7 +161,7 @@ namespace MediaBrowser.Controller.Entities
return await GetTvGenres(queryParent, user, query).ConfigureAwait(false);
case SpecialFolder.TvGenre:
return await GetTvGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
return GetTvGenreItems(queryParent, displayParent, user, query);
case SpecialFolder.TvResume:
return GetTvResume(queryParent, user, query);
@ -332,13 +334,14 @@ namespace MediaBrowser.Controller.Entities
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,
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);
@ -347,13 +350,14 @@ namespace MediaBrowser.Controller.Entities
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,
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);
@ -362,13 +366,14 @@ namespace MediaBrowser.Controller.Entities
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,
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);
@ -660,6 +665,7 @@ namespace MediaBrowser.Controller.Entities
query.SetUser(user);
query.Limit = GetSpecialItemsLimit();
query.IncludeItemTypes = new[] { typeof(Episode).Name };
query.ExcludeLocationTypes = new[] { LocationType.Virtual };
return _libraryManager.GetItemsResult(query);
}
@ -737,7 +743,7 @@ namespace MediaBrowser.Controller.Entities
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.ParentId = queryParent.Id;
@ -766,7 +772,7 @@ namespace MediaBrowser.Controller.Entities
{
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)
@ -779,14 +785,15 @@ namespace MediaBrowser.Controller.Entities
int? totalRecordLimit,
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,
BaseItem queryParent,
int? totalRecordLimit,
InternalItemsQuery query,
ILibraryManager libraryManager)
ILibraryManager libraryManager,
IServerConfigurationManager configurationManager)
{
var user = query.User;
@ -795,7 +802,7 @@ namespace MediaBrowser.Controller.Entities
query.IsVirtualUnaired,
query.IsUnaired);
items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user);
items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user, configurationManager);
// This must be the last filter
if (!string.IsNullOrEmpty(query.AdjacentTo))
@ -809,14 +816,15 @@ namespace MediaBrowser.Controller.Entities
public static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(IEnumerable<BaseItem> items,
InternalItemsQuery query,
BaseItem queryParent,
User user)
User user,
IServerConfigurationManager configurationManager)
{
if (items == null)
{
throw new ArgumentNullException("items");
}
if (CollapseBoxSetItems(query, queryParent, user))
if (CollapseBoxSetItems(query, queryParent, user, configurationManager))
{
items = BaseItem.CollectionManager.CollapseItemsWithinBoxSets(items, user);
}
@ -849,7 +857,8 @@ namespace MediaBrowser.Controller.Entities
public static bool CollapseBoxSetItems(InternalItemsQuery query,
BaseItem queryParent,
User user)
User user,
IServerConfigurationManager configurationManager)
{
// Could end up stuck in a loop like this
if (queryParent is BoxSet)
@ -861,7 +870,7 @@ namespace MediaBrowser.Controller.Entities
if (!param.HasValue)
{
if (user != null && !user.Configuration.GroupMoviesIntoBoxSets)
if (user != null && !configurationManager.Configuration.EnableGroupingIntoCollections)
{
return false;
}
@ -992,11 +1001,6 @@ namespace MediaBrowser.Controller.Entities
return false;
}
if (request.IsYearMismatched.HasValue)
{
return false;
}
if (!string.IsNullOrWhiteSpace(request.Person))
{
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)
{
var filterValue = query.HasOfficialRating.Value;
@ -1658,12 +1652,7 @@ namespace MediaBrowser.Controller.Entities
var tags = query.Tags;
if (tags.Length > 0)
{
var hasTags = item as IHasTags;
if (hasTags == null)
{
return false;
}
if (!tags.Any(v => hasTags.Tags.Contains(v, StringComparer.OrdinalIgnoreCase)))
if (!tags.Any(v => item.Tags.Contains(v, StringComparer.OrdinalIgnoreCase)))
{
return false;
}
@ -1976,34 +1965,6 @@ namespace MediaBrowser.Controller.Entities
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)
{
var list = items.ToList();

View File

@ -21,7 +21,6 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class Video : BaseItem,
IHasAspectRatio,
IHasTags,
ISupportsPlaceHolders,
IHasMediaSources,
IHasShortOverview,

View File

@ -150,13 +150,6 @@ namespace MediaBrowser.Controller.Library
/// <returns>BaseItem.</returns>
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>
/// Gets the intros.
/// </summary>

View File

@ -15,5 +15,6 @@ namespace MediaBrowser.Controller.LiveTv
Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken);
Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings);
Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location);
Task<List<ChannelInfo>> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken);
}
}

View File

@ -8,6 +8,7 @@ using MediaBrowser.Model.Querying;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Events;
namespace MediaBrowser.Controller.LiveTv
{
@ -385,5 +386,15 @@ namespace MediaBrowser.Controller.LiveTv
List<NameValuePair> GetSatIniMappings();
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;
}
}

View File

@ -226,4 +226,23 @@ namespace MediaBrowser.Controller.LiveTv
/// <returns>Task.</returns>
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);
}
}

View File

@ -7,6 +7,7 @@ using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace MediaBrowser.Controller.LiveTv
{
@ -235,5 +236,25 @@ namespace MediaBrowser.Controller.LiveTv
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;
}
}
}

View 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; }
}
}

View File

@ -142,7 +142,7 @@
<Compile Include="Entities\IHasDisplayOrder.cs" />
<Compile Include="Entities\IHasId.cs" />
<Compile Include="Entities\IHasImages.cs" />
<Compile Include="Entities\IHasKeywords.cs" />
<Compile Include="Entities\KeywordExtensions.cs" />
<Compile Include="Entities\IHasMediaSources.cs" />
<Compile Include="Entities\IHasMetascore.cs" />
<Compile Include="Entities\IHasOriginalTitle.cs" />
@ -154,7 +154,6 @@
<Compile Include="Entities\IHasSpecialFeatures.cs" />
<Compile Include="Entities\IHasStartDate.cs" />
<Compile Include="Entities\IHasTaglines.cs" />
<Compile Include="Entities\IHasTags.cs" />
<Compile Include="Entities\IHasThemeMedia.cs" />
<Compile Include="Entities\IHasTrailers.cs" />
<Compile Include="Entities\IHasUserData.cs" />
@ -177,6 +176,7 @@
<Compile Include="Entities\PhotoAlbum.cs" />
<Compile Include="Entities\Share.cs" />
<Compile Include="Entities\SourceType.cs" />
<Compile Include="Entities\TagExtensions.cs" />
<Compile Include="Entities\UserView.cs" />
<Compile Include="Entities\UserViewBuilder.cs" />
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
@ -218,6 +218,7 @@
<Compile Include="LiveTv\ProgramInfo.cs" />
<Compile Include="LiveTv\RecordingInfo.cs" />
<Compile Include="LiveTv\SeriesTimerInfo.cs" />
<Compile Include="LiveTv\TimerEventInfo.cs" />
<Compile Include="LiveTv\TimerInfo.cs" />
<Compile Include="Localization\ILocalizationManager.cs" />
<Compile Include="MediaEncoding\ChapterImageRefreshOptions.cs" />
@ -290,14 +291,11 @@
<Compile Include="Providers\IImageFileSaver.cs" />
<Compile Include="Providers\IImageProvider.cs" />
<Compile Include="Providers\IImageSaver.cs" />
<Compile Include="Providers\IItemIdentityConverter.cs" />
<Compile Include="Providers\IItemIdentityProvider.cs" />
<Compile Include="Providers\ILocalImageFileProvider.cs" />
<Compile Include="Providers\ILocalMetadataProvider.cs" />
<Compile Include="Providers\ImageRefreshMode.cs" />
<Compile Include="Providers\ImageRefreshOptions.cs" />
<Compile Include="Providers\IPreRefreshProvider.cs" />
<Compile Include="Providers\IProviderRepository.cs" />
<Compile Include="Providers\IRemoteImageProvider.cs" />
<Compile Include="Providers\ILocalImageProvider.cs" />
<Compile Include="Providers\IMetadataProvider.cs" />
@ -330,11 +328,8 @@
<Compile Include="Sorting\SortHelper.cs" />
<Compile Include="Subtitles\ISubtitleManager.cs" />
<Compile Include="Subtitles\ISubtitleProvider.cs" />
<Compile Include="Providers\ItemIdentifier.cs" />
<Compile Include="Providers\ItemIdentities.cs" />
<Compile Include="Providers\ItemLookupInfo.cs" />
<Compile Include="Providers\MetadataRefreshOptions.cs" />
<Compile Include="Providers\MetadataStatus.cs" />
<Compile Include="Providers\ISeriesOrderManager.cs" />
<Compile Include="Session\ISessionManager.cs" />
<Compile Include="Entities\AggregateFolder.cs" />

View File

@ -10,13 +10,6 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <summary>
/// Gets the subtitles.
/// </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>
Task<Stream> GetSubtitles(string itemId,
string mediaSourceId,
@ -24,6 +17,7 @@ namespace MediaBrowser.Controller.MediaEncoding
string outputFormat,
long startTimeTicks,
long? endTimeTicks,
bool preserveOriginalTimestamps,
CancellationToken cancellationToken);
/// <summary>

View File

@ -81,7 +81,7 @@ namespace MediaBrowser.Controller.Persistence
/// <param name="chapters">The chapters.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SaveChapters(Guid id, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken);
Task SaveChapters(Guid id, List<ChapterInfo> chapters, CancellationToken cancellationToken);
/// <summary>
/// Gets the media streams.
@ -97,7 +97,7 @@ namespace MediaBrowser.Controller.Persistence
/// <param name="streams">The streams.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SaveMediaStreams(Guid id, IEnumerable<MediaStream> streams, CancellationToken cancellationToken);
Task SaveMediaStreams(Guid id, List<MediaStream> streams, CancellationToken cancellationToken);
/// <summary>
/// Gets the item ids.

View File

@ -29,6 +29,8 @@ namespace MediaBrowser.Controller.Persistence
/// <returns>Task{UserItemData}.</returns>
UserItemData GetUserData(Guid userId, string key);
UserItemData GetUserData(Guid userId, List<string> keys);
/// <summary>
/// Return all user data associated with the given user
/// </summary>

View File

@ -803,11 +803,7 @@ namespace MediaBrowser.Controller.Providers
{
using (var subtree = reader.ReadSubtree())
{
var hasTags = item as IHasTags;
if (hasTags != null)
{
FetchFromTagsNode(subtree, hasTags);
}
FetchFromTagsNode(subtree, item);
}
break;
}
@ -816,11 +812,7 @@ namespace MediaBrowser.Controller.Providers
{
using (var subtree = reader.ReadSubtree())
{
var hasTags = item as IHasKeywords;
if (hasTags != null)
{
FetchFromKeywordsNode(subtree, hasTags);
}
FetchFromKeywordsNode(subtree, item);
}
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();
@ -1099,7 +1091,7 @@ namespace MediaBrowser.Controller.Providers
}
}
private void FetchFromKeywordsNode(XmlReader reader, IHasKeywords item)
private void FetchFromKeywordsNode(XmlReader reader, BaseItem item)
{
reader.MoveToContent();

View File

@ -1,4 +0,0 @@
namespace MediaBrowser.Controller.Providers
{
public interface IItemIdentityConverter { }
}

View File

@ -1,4 +0,0 @@
namespace MediaBrowser.Controller.Providers
{
public interface IItemIdentityProvider { }
}

View File

@ -97,13 +97,11 @@ namespace MediaBrowser.Controller.Providers
/// </summary>
/// <param name="imageProviders">The image providers.</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="savers">The savers.</param>
/// <param name="imageSavers">The image savers.</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<IImageSaver> imageSavers,
IEnumerable<IExternalId> externalIds);
@ -135,7 +133,7 @@ namespace MediaBrowser.Controller.Providers
/// </summary>
/// <param name="item">The item.</param>
/// <returns>IEnumerable{ExternalUrl}.</returns>
IEnumerable<ExternalUrl> GetExternalUrls(IHasProviderIds item);
IEnumerable<ExternalUrl> GetExternalUrls(BaseItem item);
/// <summary>
/// Gets the external identifier infos.
@ -190,21 +188,5 @@ namespace MediaBrowser.Controller.Providers
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{HttpResponseInfo}.</returns>
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&lt;IItemIdentityProvider&lt;TLookupInfo, TIdentity&gt;&gt;.</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&lt;IItemIdentityConverter&lt;TIdentity&gt;&gt;.</returns>
IEnumerable<IItemIdentityConverter<TLookupInfo>> GetItemIdentityConverters<TLookupInfo>()
where TLookupInfo : ItemLookupInfo;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}
}
}
}

View File

@ -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);
}
}

View File

@ -1,3 +1,4 @@
using System;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Entities;
@ -5,10 +6,6 @@ namespace MediaBrowser.Controller.Providers
{
public class ItemInfo
{
public ItemInfo()
{
}
public ItemInfo(IHasMetadata item)
{
Path = item.Path;
@ -21,8 +18,11 @@ namespace MediaBrowser.Controller.Providers
VideoType = video.VideoType;
IsPlaceHolder = video.IsPlaceHolder;
}
ItemType = item.GetType();
}
public Type ItemType { get; set; }
public string Path { get; set; }
public string ContainingFolderPath { get; set; }
public VideoType VideoType { get; set; }

View File

@ -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;
}
}
}

View File

@ -315,9 +315,8 @@ namespace MediaBrowser.Controller.Session
/// <summary>
/// Revokes the user tokens.
/// </summary>
/// <param name="userId">The user identifier.</param>
/// <returns>Task.</returns>
Task RevokeUserTokens(string userId);
Task RevokeUserTokens(string userId, string currentAccessToken);
/// <summary>
/// Revokes the token.

View File

@ -1015,17 +1015,17 @@ namespace MediaBrowser.Dlna.Didl
int? width = null;
int? height = null;
//try
//{
// var size = _imageProcessor.GetImageSize(imageInfo);
try
{
var size = _imageProcessor.GetImageSize(imageInfo);
// width = Convert.ToInt32(size.Width);
// height = Convert.ToInt32(size.Height);
//}
//catch
//{
width = Convert.ToInt32(size.Width);
height = Convert.ToInt32(size.Height);
}
catch
{
//}
}
var inputFormat = (Path.GetExtension(imageInfo.Path) ?? string.Empty)
.TrimStart('.')

View File

@ -101,6 +101,7 @@ namespace MediaBrowser.Dlna.PlayTo
}
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);
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)
.ConfigureAwait(false);

View File

@ -21,8 +21,8 @@ namespace MediaBrowser.Dlna.Profiles
new HttpHeaderInfo
{
Name = "User-Agent",
Value = @"SEC_",
Match = HeaderMatchType.Substring
Value = @".*(SEC_HHP_\[TV\] [A-Z]{2}\d{2}J[A-Z]?\d{3,4})*.",
Match = HeaderMatchType.Regex
}
}
};

View File

@ -4,7 +4,7 @@
<Identification>
<ModelUrl>samsung.com</ModelUrl>
<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>
</Identification>
<Manufacturer>Emby</Manufacturer>

View File

@ -593,37 +593,29 @@ namespace MediaBrowser.LocalMetadata.Savers
builder.Append("</Studios>");
}
var hasTags = item as IHasTags;
if (hasTags != null)
{
if (hasTags.Tags.Count > 0)
if (item.Tags.Count > 0)
{
builder.Append("<Tags>");
foreach (var tag in hasTags.Tags)
foreach (var tag in item.Tags)
{
builder.Append("<Tag>" + SecurityElement.Escape(tag) + "</Tag>");
}
builder.Append("</Tags>");
}
}
var hasKeywords = item as IHasKeywords;
if (hasKeywords != null)
{
if (hasKeywords.Keywords.Count > 0)
if (item.Keywords.Count > 0)
{
builder.Append("<PlotKeywords>");
foreach (var tag in hasKeywords.Keywords)
foreach (var tag in item.Keywords)
{
builder.Append("<PlotKeyword>" + SecurityElement.Escape(tag) + "</PlotKeyword>");
}
builder.Append("</PlotKeywords>");
}
}
var people = libraryManager.GetPeople(item);

View File

@ -73,11 +73,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
var commandLineArgs = GetCommandLineArguments(encodingJob);
if (GetEncodingOptions().EnableDebugLogging)
{
commandLineArgs = "-loglevel debug " + commandLineArgs;
}
var process = new Process
{
StartInfo = new ProcessStartInfo

View File

@ -99,7 +99,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
if (videoRequest != null)
{
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)
{
@ -396,7 +396,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
return request.AudioChannels;
}
private int? GetVideoBitrateParamValue(EncodingJobOptions request, MediaStream videoStream)
private int? GetVideoBitrateParamValue(EncodingJobOptions request, MediaStream videoStream, string outputVideoCodec)
{
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;
}

View File

@ -408,7 +408,9 @@ namespace MediaBrowser.MediaEncoding.Probing
Level = streamInfo.level,
Index = streamInfo.index,
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) ||

View File

@ -58,6 +58,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
string outputFormat,
long startTimeTicks,
long? endTimeTicks,
bool preserveOriginalTimestamps,
CancellationToken cancellationToken)
{
var ms = new MemoryStream();
@ -68,7 +69,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
var trackInfo = reader.Parse(stream, cancellationToken);
FilterEvents(trackInfo, startTimeTicks, endTimeTicks, false);
FilterEvents(trackInfo, startTimeTicks, endTimeTicks, preserveOriginalTimestamps);
var writer = GetWriter(outputFormat);
@ -116,6 +117,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
string outputFormat,
long startTimeTicks,
long? endTimeTicks,
bool preserveOriginalTimestamps,
CancellationToken cancellationToken)
{
var subtitle = await GetSubtitleStream(itemId, mediaSourceId, subtitleStreamIndex, cancellationToken)
@ -130,7 +132,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
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);
}
}

View File

@ -230,12 +230,6 @@
<Compile Include="..\MediaBrowser.Model\Configuration\SubtitlePlaybackMode.cs">
<Link>Configuration\SubtitlePlaybackMode.cs</Link>
</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">
<Link>Configuration\UnratedItem.cs</Link>
</Compile>

View File

@ -204,12 +204,6 @@
<Compile Include="..\MediaBrowser.Model\Configuration\SubtitlePlaybackMode.cs">
<Link>Configuration\SubtitlePlaybackMode.cs</Link>
</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">
<Link>Configuration\UnratedItem.cs</Link>
</Compile>

View File

@ -57,6 +57,10 @@ namespace MediaBrowser.Model.ApiClient
{
existing.RemoteAddress = server.RemoteAddress;
}
if (!string.IsNullOrEmpty(server.ConnectServerId))
{
existing.ConnectServerId = server.ConnectServerId;
}
if (!string.IsNullOrEmpty(server.LocalAddress))
{
existing.LocalAddress = server.LocalAddress;

View File

@ -12,6 +12,7 @@ namespace MediaBrowser.Model.ApiClient
public String Name { get; set; }
public String Id { get; set; }
public String ConnectServerId { get; set; }
public String LocalAddress { get; set; }
public String RemoteAddress { get; set; }
public String ManualAddress { get; set; }

View File

@ -6,7 +6,6 @@ namespace MediaBrowser.Model.Configuration
public int EncodingThreadCount { get; set; }
public string TranscodingTempPath { get; set; }
public double DownMixAudioBoost { get; set; }
public bool EnableDebugLogging { get; set; }
public bool EnableThrottling { get; set; }
public int ThrottleDelaySeconds { get; set; }
public string HardwareAccelerationType { get; set; }

View File

@ -3,11 +3,6 @@ namespace MediaBrowser.Model.Configuration
{
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>
/// Gets or sets the user API key.
/// </summary>

View File

@ -86,12 +86,6 @@ namespace MediaBrowser.Model.Configuration
/// <value><c>true</c> if [save local meta]; otherwise, <c>false</c>.</value>
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>
/// Gets or sets the preferred metadata language.
/// </summary>
@ -190,14 +184,10 @@ namespace MediaBrowser.Model.Configuration
public bool EnableVideoArchiveFiles { get; set; }
public int RemoteClientBitrateLimit { get; set; }
public bool DenyIFrameEmbedding { get; set; }
public AutoOnOff EnableLibraryMonitor { get; set; }
public int SharingExpirationDays { get; set; }
public bool EnableDateLastRefresh { get; set; }
public string[] Migrations { get; set; }
public int MigrationVersion { get; set; }
@ -207,16 +197,24 @@ namespace MediaBrowser.Model.Configuration
public bool EnableAnonymousUsageReporting { 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>
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
/// </summary>
public ServerConfiguration()
{
LocalNetworkAddresses = new string[] { };
Migrations = new string[] { };
EnableLocalizedGuids = true;
EnableCustomPathSubFolders = true;
EnableLocalizedGuids = true;
DisplaySpecialsWithinSeasons = true;
ImageSavingConvention = ImageSavingConvention.Compatible;
PublicPort = 8096;
@ -229,10 +227,8 @@ namespace MediaBrowser.Model.Configuration
EnableAnonymousUsageReporting = true;
EnableAutomaticRestart = true;
DenyIFrameEmbedding = true;
EnableUPnP = true;
SharingExpirationDays = 30;
MinResumePct = 5;
MaxResumePct = 90;

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -34,14 +34,11 @@ namespace MediaBrowser.Model.Configuration
public SubtitlePlaybackMode SubtitleMode { get; set; }
public bool DisplayCollectionsView { get; set; }
public bool DisplayFoldersView { get; set; }
public bool EnableLocalPassword { get; set; }
public string[] OrderedViews { get; set; }
public bool IncludeTrailersInSuggestions { get; set; }
public string[] LatestItemsExcludes { get; set; }
public string[] PlainFolderViews { get; set; }
@ -51,6 +48,7 @@ namespace MediaBrowser.Model.Configuration
public bool RememberAudioSelections { get; set; }
public bool RememberSubtitleSelections { get; set; }
public bool EnableNextEpisodeAutoPlay { get; set; }
public bool DisplayFoldersView { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="UserConfiguration" /> class.
@ -69,8 +67,6 @@ namespace MediaBrowser.Model.Configuration
PlainFolderViews = new string[] { };
IncludeTrailersInSuggestions = true;
GroupedFolders = new string[] { };
}
}

View File

@ -56,5 +56,25 @@ namespace MediaBrowser.Model.Dlna
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);
}
}
}

View File

@ -335,7 +335,8 @@ namespace MediaBrowser.Model.Dlna
Name = stream.Language ?? "Unknown",
Format = subtitleProfile.Format,
Index = stream.Index,
DeliveryMethod = subtitleProfile.Method
DeliveryMethod = subtitleProfile.Method,
DisplayTitle = stream.DisplayTitle
};
if (info.DeliveryMethod == SubtitleDeliveryMethod.External)

View File

@ -7,6 +7,7 @@ namespace MediaBrowser.Model.Dlna
public string Name { get; set; }
public bool IsForced { get; set; }
public string Format { get; set; }
public string DisplayTitle { get; set; }
public int Index { get; set; }
public SubtitleDeliveryMethod DeliveryMethod { get; set; }
public bool IsExternalUrl { get; set; }

View File

@ -9,50 +9,50 @@ namespace MediaBrowser.Model.Entities
/// <summary>
/// The primary
/// </summary>
Primary,
Primary = 0,
/// <summary>
/// The art
/// </summary>
Art,
Art = 1,
/// <summary>
/// The backdrop
/// </summary>
Backdrop,
Backdrop = 2,
/// <summary>
/// The banner
/// </summary>
Banner,
Banner = 3,
/// <summary>
/// The logo
/// </summary>
Logo,
Logo = 4,
/// <summary>
/// The thumb
/// </summary>
Thumb,
Thumb = 5,
/// <summary>
/// The disc
/// </summary>
Disc,
Disc = 6,
/// <summary>
/// The box
/// </summary>
Box,
Box = 7,
/// <summary>
/// The screenshot
/// </summary>
Screenshot,
Screenshot = 8,
/// <summary>
/// The menu
/// </summary>
Menu,
Menu = 9,
/// <summary>
/// The chapter image
/// </summary>
Chapter,
Chapter = 10,
/// <summary>
/// The box rear
/// </summary>
BoxRear
BoxRear = 11
}
}

View File

@ -36,6 +36,9 @@ namespace MediaBrowser.Model.Entities
/// <value>The comment.</value>
public string Comment { get; set; }
public string TimeBase { get; set; }
public string CodecTimeBase { get; set; }
public string Title { get; set; }
public string DisplayTitle
@ -89,7 +92,7 @@ namespace MediaBrowser.Model.Entities
if (!string.IsNullOrEmpty(Language))
{
attributes.Add(Language);
attributes.Add(StringHelper.FirstToUpper(Language));
}
if (!string.IsNullOrEmpty(Codec))
{

View File

@ -1,4 +1,6 @@
using System.Collections.Generic;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Extensions;
namespace MediaBrowser.Model.LiveTv
{
@ -73,11 +75,33 @@ namespace MediaBrowser.Model.LiveTv
public string[] EnabledTuners { 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()
{
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[] { };
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;
}
}
}

View File

@ -97,8 +97,6 @@
<Compile Include="Configuration\FanartOptions.cs" />
<Compile Include="Configuration\MetadataConfiguration.cs" />
<Compile Include="Configuration\PeopleMetadataOptions.cs" />
<Compile Include="Configuration\TheMovieDbOptions.cs" />
<Compile Include="Configuration\TvdbOptions.cs" />
<Compile Include="Configuration\XbmcMetadataOptions.cs" />
<Compile Include="Configuration\SubtitlePlaybackMode.cs" />
<Compile Include="Connect\ConnectAuthenticationExchangeResult.cs" />

View File

@ -85,5 +85,6 @@ namespace MediaBrowser.Model.Querying
public const string GameSystem = "GameSystem";
public const string IsFavoriteOrLiked = "IsFavoriteOrLiked";
public const string DateLastContentAdded = "DateLastContentAdded";
public const string SeriesDatePlayed = "SeriesDatePlayed";
}
}

View File

@ -12,10 +12,6 @@ namespace MediaBrowser.Providers.Books
{
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)
{
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
@ -25,5 +21,9 @@ namespace MediaBrowser.Providers.Books
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)
{
}
}
}

View File

@ -15,10 +15,6 @@ namespace MediaBrowser.Providers.BoxSets
{
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)
{
var updateType = await base.BeforeSave(item, isFullRefresh, currentUpdateType).ConfigureAwait(false);
@ -54,5 +50,9 @@ namespace MediaBrowser.Providers.BoxSets
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)
{
}
}
}

View File

@ -12,13 +12,13 @@ namespace MediaBrowser.Providers.Channels
{
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)
{
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)
{
}
}
}

View File

@ -259,7 +259,7 @@ namespace MediaBrowser.Providers.Chapters
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);
}

View File

@ -16,14 +16,13 @@ namespace MediaBrowser.Providers.Folders
{
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)
{
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)
{
}
}
}

View File

@ -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));
}
}
}

View File

@ -12,10 +12,6 @@ namespace MediaBrowser.Providers.Folders
{
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
{
get
@ -29,5 +25,9 @@ namespace MediaBrowser.Providers.Folders
{
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)
{
}
}
}

View File

@ -12,13 +12,13 @@ namespace MediaBrowser.Providers.Folders
{
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)
{
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