This commit is contained in:
Luke Pulverenti 2016-03-25 13:52:36 -04:00
commit d9108f69f3
424 changed files with 14381 additions and 3462 deletions

View File

@ -33,7 +33,7 @@
<ItemGroup>
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\CommonIO.1.0.0.8\lib\net45\CommonIO.dll</HintPath>
<HintPath>..\packages\CommonIO.1.0.0.9\lib\net45\CommonIO.dll</HintPath>
</Reference>
<Reference Include="ImageMagickSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>

View File

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

View File

@ -63,6 +63,15 @@ namespace MediaBrowser.Api
_mediaSourceManager = mediaSourceManager;
Instance = this;
_sessionManager.PlaybackProgress += _sessionManager_PlaybackProgress;
}
void _sessionManager_PlaybackProgress(object sender, PlaybackProgressEventArgs e)
{
if (!string.IsNullOrWhiteSpace(e.PlaySessionId))
{
PingTranscodingJob(e.PlaySessionId, e.IsPaused);
}
}
/// <summary>
@ -300,26 +309,31 @@ namespace MediaBrowser.Api
PingTimer(job, false);
}
}
internal void PingTranscodingJob(string playSessionId)
internal void PingTranscodingJob(string playSessionId, bool? isUserPaused)
{
if (string.IsNullOrEmpty(playSessionId))
{
throw new ArgumentNullException("playSessionId");
}
//Logger.Debug("PingTranscodingJob PlaySessionId={0}", playSessionId);
//Logger.Debug("PingTranscodingJob PlaySessionId={0} isUsedPaused: {1}", playSessionId, isUserPaused);
var jobs = new List<TranscodingJob>();
List<TranscodingJob> jobs;
lock (_activeTranscodingJobs)
{
// This is really only needed for HLS.
// Progressive streams can stop on their own reliably
jobs = jobs.Where(j => string.Equals(playSessionId, j.PlaySessionId, StringComparison.OrdinalIgnoreCase)).ToList();
jobs = _activeTranscodingJobs.Where(j => string.Equals(playSessionId, j.PlaySessionId, StringComparison.OrdinalIgnoreCase)).ToList();
}
foreach (var job in jobs)
{
if (isUserPaused.HasValue)
{
//Logger.Debug("Setting job.IsUserPaused to {0}. jobId: {1}", isUserPaused, job.Id);
job.IsUserPaused = isUserPaused.Value;
}
PingTimer(job, true);
}
}
@ -655,6 +669,7 @@ namespace MediaBrowser.Api
public object ProcessLock = new object();
public bool HasExited { get; set; }
public bool IsUserPaused { get; set; }
public string Id { get; set; }

View File

@ -196,9 +196,13 @@ namespace MediaBrowser.Api
return name;
}
return libraryManager.RootFolder
.GetRecursiveChildren(i => i is IHasArtist)
.Cast<IHasArtist>()
var items = libraryManager.GetItemList(new InternalItemsQuery
{
IncludeItemTypes = new[] { typeof(Audio).Name, typeof(MusicVideo).Name, typeof(MusicAlbum).Name }
});
return items
.OfType<IHasArtist>()
.SelectMany(i => i.AllArtists)
.DistinctNames()
.FirstOrDefault(i =>
@ -239,8 +243,12 @@ namespace MediaBrowser.Api
return name;
}
return libraryManager.RootFolder
.GetRecursiveChildren(i => i is Game)
var items = libraryManager.GetItemList(new InternalItemsQuery
{
IncludeItemTypes = new[] { typeof(Game).Name }
});
return items
.SelectMany(i => i.Genres)
.DistinctNames()
.FirstOrDefault(i =>

View File

@ -108,7 +108,7 @@ namespace MediaBrowser.Api
IncludeItemTypes = new[] { typeof(GameSystem).Name }
};
var parentIds = new string[] { } ;
var gameSystems = _libraryManager.GetItems(query, parentIds)
var gameSystems = _libraryManager.GetItemList(query, parentIds)
.Cast<GameSystem>()
.ToList();
@ -129,7 +129,7 @@ namespace MediaBrowser.Api
IncludeItemTypes = new[] { typeof(Game).Name }
};
var parentIds = new string[] { };
var games = _libraryManager.GetItems(query, parentIds)
var games = _libraryManager.GetItemList(query, parentIds)
.Cast<Game>()
.ToList();
@ -192,7 +192,7 @@ namespace MediaBrowser.Api
_userDataRepository,
_dtoService,
Logger,
request, item => item is Game,
request, new[] { typeof(Game) },
SimilarItemsHelper.GetSimiliarityScore);
return ToOptimizedSerializedResultUsingCache(result);

View File

@ -699,6 +699,7 @@ namespace MediaBrowser.Api.Images
private ImageFormat[] GetClientSupportedFormats()
{
//Logger.Debug("Request types: {0}", string.Join(",", Request.AcceptTypes ?? new string[] { }));
var supportsWebP = (Request.AcceptTypes ?? new string[] { }).Contains("image/webp", StringComparer.OrdinalIgnoreCase);
var userAgent = Request.UserAgent ?? string.Empty;

View File

@ -289,7 +289,6 @@ namespace MediaBrowser.Api.Library
private readonly IActivityManager _activityManager;
private readonly ILocalizationManager _localization;
private readonly ILiveTvManager _liveTv;
private readonly IChannelManager _channelManager;
private readonly ITVSeriesManager _tvManager;
private readonly ILibraryMonitor _libraryMonitor;
private readonly IFileSystem _fileSystem;
@ -298,7 +297,7 @@ namespace MediaBrowser.Api.Library
/// Initializes a new instance of the <see cref="LibraryService" /> class.
/// </summary>
public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILiveTvManager liveTv, IChannelManager channelManager, ITVSeriesManager tvManager, ILibraryMonitor libraryMonitor, IFileSystem fileSystem)
IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILiveTvManager liveTv, ITVSeriesManager tvManager, ILibraryMonitor libraryMonitor, IFileSystem fileSystem)
{
_itemRepo = itemRepo;
_libraryManager = libraryManager;
@ -309,7 +308,6 @@ namespace MediaBrowser.Api.Library
_activityManager = activityManager;
_localization = localization;
_liveTv = liveTv;
_channelManager = channelManager;
_tvManager = tvManager;
_libraryMonitor = libraryMonitor;
_fileSystem = fileSystem;
@ -379,11 +377,10 @@ namespace MediaBrowser.Api.Library
}
var program = item as IHasProgramAttributes;
var channelItem = item as ChannelVideoItem;
if (item is Movie || (program != null && program.IsMovie) || (channelItem != null && channelItem.ContentType == ChannelMediaContentType.Movie) || (channelItem != null && channelItem.ContentType == ChannelMediaContentType.MovieExtra))
if (item is Movie || (program != null && program.IsMovie) || item is Trailer)
{
return new MoviesService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _channelManager)
return new MoviesService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService)
{
AuthorizationContext = AuthorizationContext,
Logger = Logger,
@ -400,7 +397,7 @@ namespace MediaBrowser.Api.Library
});
}
if (item is Series || (program != null && program.IsSeries) || (channelItem != null && channelItem.ContentType == ChannelMediaContentType.Episode))
if (item is Series || (program != null && program.IsSeries))
{
return new TvShowsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _tvManager)
{
@ -447,13 +444,11 @@ namespace MediaBrowser.Api.Library
public void Post(PostUpdatedSeries request)
{
var series = _libraryManager.GetItems(new InternalItemsQuery
var series = _libraryManager.GetItemList(new InternalItemsQuery
{
IncludeItemTypes = new[] { typeof(Series).Name }
}).Items;
series = series.Where(i => string.Equals(request.TvdbId, i.GetProviderId(MetadataProviders.Tvdb), StringComparison.OrdinalIgnoreCase)).ToArray();
}).Where(i => string.Equals(request.TvdbId, i.GetProviderId(MetadataProviders.Tvdb), StringComparison.OrdinalIgnoreCase)).ToArray();
if (series.Length > 0)
{
@ -470,11 +465,11 @@ namespace MediaBrowser.Api.Library
public void Post(PostUpdatedMovies request)
{
var movies = _libraryManager.GetItems(new InternalItemsQuery
var movies = _libraryManager.GetItemList(new InternalItemsQuery
{
IncludeItemTypes = new[] { typeof(Movie).Name }
}).Items;
}).ToArray();
if (!string.IsNullOrWhiteSpace(request.ImdbId))
{
@ -664,87 +659,38 @@ namespace MediaBrowser.Api.Library
/// <returns>System.Object.</returns>
public object Get(GetItemCounts request)
{
var filteredItems = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, i => i.LocationType != LocationType.Virtual && FilterItem(i, request, request.UserId));
var user = string.IsNullOrWhiteSpace(request.UserId) ? null : _userManager.GetUserById(request.UserId);
var counts = new ItemCounts
{
AlbumCount = filteredItems.Count(i => i is MusicAlbum),
EpisodeCount = filteredItems.Count(i => i is Episode),
GameCount = filteredItems.Count(i => i is Game),
GameSystemCount = filteredItems.Count(i => i is GameSystem),
MovieCount = filteredItems.Count(i => i is Movie),
SeriesCount = filteredItems.Count(i => i is Series),
SongCount = filteredItems.Count(i => i is Audio),
MusicVideoCount = filteredItems.Count(i => i is MusicVideo),
BoxSetCount = filteredItems.Count(i => i is BoxSet),
BookCount = filteredItems.Count(i => i is Book),
UniqueTypes = filteredItems.Select(i => i.GetClientTypeName()).Distinct().ToList()
AlbumCount = GetCount(typeof(MusicAlbum), user, request),
EpisodeCount = GetCount(typeof(Episode), user, request),
GameCount = GetCount(typeof(Game), user, request),
GameSystemCount = GetCount(typeof(GameSystem), user, request),
MovieCount = GetCount(typeof(Movie), user, request),
SeriesCount = GetCount(typeof(Series), user, request),
SongCount = GetCount(typeof(Audio), user, request),
MusicVideoCount = GetCount(typeof(MusicVideo), user, request),
BoxSetCount = GetCount(typeof(BoxSet), user, request),
BookCount = GetCount(typeof(Book), user, request)
};
return ToOptimizedSerializedResultUsingCache(counts);
}
private IList<BaseItem> GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func<BaseItem, bool> filter)
private int GetCount(Type type, User user, GetItemCounts request)
{
if (!string.IsNullOrEmpty(parentId))
var query = new InternalItemsQuery(user)
{
var folder = (Folder)libraryManager.GetItemById(new Guid(parentId));
IncludeItemTypes = new[] { type.Name },
Limit = 0,
Recursive = true,
ExcludeLocationTypes = new[] { LocationType.Virtual },
SourceTypes = new[] { SourceType.Library },
IsFavorite = request.IsFavorite
};
if (!string.IsNullOrWhiteSpace(userId))
{
var user = userManager.GetUserById(userId);
if (user == null)
{
throw new ArgumentException("User not found");
}
return folder
.GetRecursiveChildren(user, filter)
.ToList();
}
return folder
.GetRecursiveChildren(filter);
}
if (!string.IsNullOrWhiteSpace(userId))
{
var user = userManager.GetUserById(userId);
if (user == null)
{
throw new ArgumentException("User not found");
}
return userManager
.GetUserById(userId)
.RootFolder
.GetRecursiveChildren(user, filter)
.ToList();
}
return libraryManager
.RootFolder
.GetRecursiveChildren(filter);
}
private bool FilterItem(BaseItem item, GetItemCounts request, string userId)
{
if (!string.IsNullOrWhiteSpace(userId))
{
if (request.IsFavorite.HasValue)
{
var val = request.IsFavorite.Value;
if (_userDataManager.GetUserData(userId, item.GetUserDataKey()).IsFavorite != val)
{
return false;
}
}
}
return true;
return _libraryManager.GetItemsResult(query).TotalRecordCount;
}
/// <summary>
@ -985,20 +931,15 @@ namespace MediaBrowser.Api.Library
? new string[] { }
: request.IncludeItemTypes.Split(',');
Func<BaseItem, bool> filter = i =>
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
var query = new InternalItemsQuery(user)
{
if (includeTypes.Length > 0)
{
if (!includeTypes.Contains(i.GetType().Name, StringComparer.OrdinalIgnoreCase))
{
return false;
}
}
return true;
IncludeItemTypes = includeTypes,
Recursive = true
};
IEnumerable<BaseItem> items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, filter);
var items = _libraryManager.GetItemList(query);
var lookup = items
.ToLookup(i => i.ProductionYear ?? -1)

View File

@ -201,10 +201,10 @@ namespace MediaBrowser.Api.Library
var rootFolderPath = _appPaths.DefaultUserViewsPath;
var virtualFolderPath = Path.Combine(rootFolderPath, name);
if (_fileSystem.DirectoryExists(virtualFolderPath))
while (_fileSystem.DirectoryExists(virtualFolderPath))
{
throw new ArgumentException("There is already a media library with the name " + name + ".");
name += "1";
virtualFolderPath = Path.Combine(rootFolderPath, name);
}
if (request.Paths != null)
@ -236,7 +236,7 @@ namespace MediaBrowser.Api.Library
{
foreach (var path in request.Paths)
{
LibraryHelpers.AddMediaPath(_fileSystem, request.Name, path, _appPaths);
LibraryHelpers.AddMediaPath(_fileSystem, name, path, _appPaths);
}
}
}

View File

@ -478,19 +478,30 @@ namespace MediaBrowser.Api.LiveTv
public string Feature { get; set; }
}
[Route("/LiveTv/TunerHosts/Satip/IniMappings", "GET", Summary = "Gets available mappings")]
[Authenticated(AllowBeforeStartupWizard = true)]
public class GetSatIniMappings : IReturn<List<NameValuePair>>
{
}
public class LiveTvService : BaseApiService
{
private readonly ILiveTvManager _liveTvManager;
private readonly IUserManager _userManager;
private readonly IConfigurationManager _config;
private readonly IHttpClient _httpClient;
private readonly ILibraryManager _libraryManager;
private readonly IDtoService _dtoService;
public LiveTvService(ILiveTvManager liveTvManager, IUserManager userManager, IConfigurationManager config, IHttpClient httpClient)
public LiveTvService(ILiveTvManager liveTvManager, IUserManager userManager, IConfigurationManager config, IHttpClient httpClient, ILibraryManager libraryManager, IDtoService dtoService)
{
_liveTvManager = liveTvManager;
_userManager = userManager;
_config = config;
_httpClient = httpClient;
_libraryManager = libraryManager;
_dtoService = dtoService;
}
public async Task<object> Get(GetLiveTvRegistrationInfo request)
@ -500,6 +511,11 @@ namespace MediaBrowser.Api.LiveTv
return ToOptimizedResult(result);
}
public object Get(GetSatIniMappings request)
{
return ToOptimizedResult(_liveTvManager.GetSatIniMappings());
}
public async Task<object> Get(GetSchedulesDirectCountries request)
{
// https://json.schedulesdirect.org/20141201/available/countries
@ -581,7 +597,7 @@ namespace MediaBrowser.Api.LiveTv
public async Task<object> Get(GetChannels request)
{
var result = await _liveTvManager.GetChannels(new LiveTvChannelQuery
var channelResult = await _liveTvManager.GetInternalChannels(new LiveTvChannelQuery
{
ChannelType = request.Type,
UserId = request.UserId,
@ -593,16 +609,30 @@ namespace MediaBrowser.Api.LiveTv
EnableFavoriteSorting = request.EnableFavoriteSorting,
AddCurrentProgram = request.AddCurrentProgram
}, GetDtoOptions(request), CancellationToken.None).ConfigureAwait(false);
}, CancellationToken.None).ConfigureAwait(false);
var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(request.UserId);
var returnArray = _dtoService.GetBaseItemDtos(channelResult.Items, GetDtoOptions(Request), user).ToArray();
var result = new QueryResult<BaseItemDto>
{
Items = returnArray,
TotalRecordCount = channelResult.TotalRecordCount
};
return ToOptimizedSerializedResultUsingCache(result);
}
public async Task<object> Get(GetChannel request)
public object Get(GetChannel request)
{
var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(request.UserId);
var user = string.IsNullOrWhiteSpace(request.UserId) ? null : _userManager.GetUserById(request.UserId);
var result = await _liveTvManager.GetChannel(request.Id, CancellationToken.None, user).ConfigureAwait(false);
var item = _libraryManager.GetItemById(request.Id);
var dtoOptions = GetDtoOptions(request);
var result = _dtoService.GetBaseItemDto(item, dtoOptions, user);
return ToOptimizedSerializedResultUsingCache(result);
}

View File

@ -47,7 +47,7 @@
<ItemGroup>
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\CommonIO.1.0.0.8\lib\net45\CommonIO.dll</HintPath>
<HintPath>..\packages\CommonIO.1.0.0.9\lib\net45\CommonIO.dll</HintPath>
</Reference>
<Reference Include="MoreLinq">
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>

View File

@ -91,22 +91,21 @@ namespace MediaBrowser.Api.Movies
private readonly IItemRepository _itemRepo;
private readonly IDtoService _dtoService;
private readonly IChannelManager _channelManager;
/// <summary>
/// Initializes a new instance of the <see cref="MoviesService"/> class.
/// Initializes a new instance of the <see cref="MoviesService" /> class.
/// </summary>
/// <param name="userManager">The user manager.</param>
/// <param name="userDataRepository">The user data repository.</param>
/// <param name="libraryManager">The library manager.</param>
public MoviesService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService, IChannelManager channelManager)
/// <param name="itemRepo">The item repo.</param>
/// <param name="dtoService">The dto service.</param>
public MoviesService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService)
{
_userManager = userManager;
_userDataRepository = userDataRepository;
_libraryManager = libraryManager;
_itemRepo = itemRepo;
_dtoService = dtoService;
_channelManager = channelManager;
}
/// <summary>
@ -138,8 +137,16 @@ namespace MediaBrowser.Api.Movies
{
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.GetItems(query, parentIds);
var movies = _libraryManager.GetItemList(query, parentIds);
movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies);
var listEligibleForCategories = new List<BaseItem>();
@ -150,19 +157,6 @@ namespace MediaBrowser.Api.Movies
listEligibleForCategories.AddRange(list);
listEligibleForSuggestion.AddRange(list);
if (user.Configuration.IncludeTrailersInSuggestions)
{
var trailerResult = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery
{
ContentTypes = new[] { ChannelMediaContentType.MovieExtra },
ExtraTypes = new[] { ExtraType.Trailer },
UserId = user.Id.ToString("N")
}, CancellationToken.None).ConfigureAwait(false);
listEligibleForSuggestion.AddRange(trailerResult.Items);
}
listEligibleForCategories = listEligibleForCategories
.DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
.DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase)
@ -194,36 +188,25 @@ namespace MediaBrowser.Api.Movies
{
IncludeItemTypes = new[] { typeof(Movie).Name }
};
if (user == null || user.Configuration.IncludeTrailersInSuggestions)
{
var includeList = query.IncludeItemTypes.ToList();
includeList.Add(typeof(Trailer).Name);
query.IncludeItemTypes = includeList.ToArray();
}
var parentIds = new string[] { };
var list = _libraryManager.GetItems(query, parentIds)
var list = _libraryManager.GetItemList(query, parentIds)
.Where(i =>
{
// Strip out secondary versions
var v = i as Video;
return v != null && !v.PrimaryVersionId.HasValue;
})
.DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
.ToList();
if (user != null && user.Configuration.IncludeTrailersInSuggestions)
{
var trailerResult = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery
{
ContentTypes = new[] { ChannelMediaContentType.MovieExtra },
ExtraTypes = new[] { ExtraType.Trailer },
UserId = user.Id.ToString("N")
}, CancellationToken.None).ConfigureAwait(false);
var newTrailers = trailerResult.Items;
list.AddRange(newTrailers);
list = list
.DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
.DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase)
.ToList();
}
if (item is Video)
{
var imdbId = item.GetProviderId(MetadataProviders.Imdb);

View File

@ -12,6 +12,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Localization;
using MediaBrowser.Model.Serialization;
namespace MediaBrowser.Api.Movies
{
@ -41,87 +44,37 @@ namespace MediaBrowser.Api.Movies
private readonly ILibraryManager _libraryManager;
private readonly IDtoService _dtoService;
private readonly IChannelManager _channelManager;
private readonly ICollectionManager _collectionManager;
private readonly ILocalizationManager _localizationManager;
private readonly IJsonSerializer _json;
/// <summary>
/// Initializes a new instance of the <see cref="TrailersService"/> class.
/// </summary>
/// <param name="userManager">The user manager.</param>
/// <param name="userDataRepository">The user data repository.</param>
/// <param name="libraryManager">The library manager.</param>
public TrailersService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IDtoService dtoService, IChannelManager channelManager)
public TrailersService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IDtoService dtoService, ICollectionManager collectionManager, ILocalizationManager localizationManager, IJsonSerializer json)
{
_userManager = userManager;
_userDataRepository = userDataRepository;
_libraryManager = libraryManager;
_dtoService = dtoService;
_channelManager = channelManager;
_collectionManager = collectionManager;
_localizationManager = localizationManager;
_json = json;
}
public async Task<object> Get(Getrailers request)
public object Get(Getrailers request)
{
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
var result = await GetAllTrailers(user).ConfigureAwait(false);
var json = _json.SerializeToString(request);
var getItems = _json.DeserializeFromString<GetItems>(json);
IEnumerable<BaseItem> items = result.Items;
getItems.IncludeItemTypes = "Trailer";
// Apply filters
// Run them starting with the ones that are likely to reduce the list the most
foreach (var filter in request.GetFilters().OrderByDescending(f => (int)f))
return new ItemsService(_userManager, _libraryManager, _userDataRepository, _localizationManager, _dtoService, _collectionManager)
{
items = ItemsService.ApplyFilter(items, filter, user, _userDataRepository);
}
AuthorizationContext = AuthorizationContext,
Logger = Logger,
Request = Request,
ResultFactory = ResultFactory,
SessionContext = SessionContext
items = _libraryManager.Sort(items, user, request.GetOrderBy(), request.SortOrder ?? SortOrder.Ascending);
var itemsArray = items.ToList();
var pagedItems = ApplyPaging(request, itemsArray);
var dtoOptions = GetDtoOptions(request);
var returnItems = _dtoService.GetBaseItemDtos(pagedItems, dtoOptions, user).ToArray();
return new ItemsResult
{
TotalRecordCount = itemsArray.Count,
Items = returnItems
};
}
private IEnumerable<BaseItem> ApplyPaging(Getrailers request, IEnumerable<BaseItem> items)
{
// Start at
if (request.StartIndex.HasValue)
{
items = items.Skip(request.StartIndex.Value);
}
// Return limit
if (request.Limit.HasValue)
{
items = items.Take(request.Limit.Value);
}
return items;
}
private async Task<QueryResult<BaseItem>> GetAllTrailers(User user)
{
var trailerResult = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery
{
ContentTypes = new[] { ChannelMediaContentType.MovieExtra },
ExtraTypes = new[] { ExtraType.Trailer },
UserId = user.Id.ToString("N")
}, CancellationToken.None).ConfigureAwait(false);
return new QueryResult<BaseItem>
{
Items = trailerResult.Items,
TotalRecordCount = trailerResult.TotalRecordCount
};
}.Get(getItems);
}
}
}

View File

@ -52,10 +52,15 @@ namespace MediaBrowser.Api.Music
public object Get(GetSimilarArtists request)
{
var result = GetSimilarItemsResult(
request,
var dtoOptions = GetDtoOptions(request);
var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager,
_itemRepo,
_libraryManager,
_userDataRepository,
_dtoService,
Logger,
request, new[] { typeof(MusicArtist) },
SimilarItemsHelper.GetSimiliarityScore);
return ToOptimizedSerializedResultUsingCache(result);
@ -76,44 +81,11 @@ namespace MediaBrowser.Api.Music
_userDataRepository,
_dtoService,
Logger,
request, item => item is MusicAlbum,
request, new[] { typeof(MusicAlbum) },
GetAlbumSimilarityScore);
return ToOptimizedSerializedResultUsingCache(result);
}
private ItemsResult GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
{
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
var item = string.IsNullOrEmpty(request.Id) ?
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
var inputItems = _libraryManager.GetArtists(user.RootFolder.GetRecursiveChildren(user, i => i is IHasArtist).OfType<IHasArtist>());
var list = inputItems.ToList();
var items = SimilarItemsHelper.GetSimilaritems(item, _libraryManager, list, getSimilarityScore).ToList();
IEnumerable<BaseItem> returnItems = items;
if (request.Limit.HasValue)
{
returnItems = returnItems.Take(request.Limit.Value);
}
var dtoOptions = GetDtoOptions(request);
var result = new ItemsResult
{
Items = _dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ToArray(),
TotalRecordCount = items.Count
};
return result;
}
/// <summary>
/// Gets the album similarity score.

View File

@ -214,7 +214,7 @@ namespace MediaBrowser.Api.Playback
args += " -map -0:a";
}
if (state.SubtitleStream == null)
if (state.SubtitleStream == null || state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Hls)
{
args += " -map -0:s";
}
@ -477,7 +477,7 @@ namespace MediaBrowser.Api.Playback
var pts = string.Empty;
if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && !state.VideoRequest.CopyTimestamps)
if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode && !state.VideoRequest.CopyTimestamps)
{
var seconds = TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds;
@ -575,7 +575,7 @@ namespace MediaBrowser.Api.Playback
var output = string.Empty;
if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream)
if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode)
{
var subParam = GetTextSubtitleParam(state);
@ -865,7 +865,7 @@ namespace MediaBrowser.Api.Playback
{
var arg = string.Format("-i {0}", GetInputPathArgument(state));
if (state.SubtitleStream != null)
if (state.SubtitleStream != null && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode)
{
if (state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream)
{
@ -1482,6 +1482,17 @@ namespace MediaBrowser.Api.Playback
videoRequest.CopyTimestamps = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
}
}
else if (i == 25)
{
if (!string.IsNullOrWhiteSpace(val) && videoRequest != null)
{
SubtitleDeliveryMethod method;
if (Enum.TryParse(val, out method))
{
videoRequest.SubtitleMethod = method;
}
}
}
}
}

View File

@ -529,7 +529,12 @@ namespace MediaBrowser.Api.Playback.Hls
"subs" :
null;
AppendPlaylist(builder, playlistUrl, totalBitrate, subtitleGroup);
if (!string.IsNullOrWhiteSpace(subtitleGroup))
{
AddSubtitles(state, subtitleStreams, builder);
}
AppendPlaylist(builder, state, playlistUrl, totalBitrate, subtitleGroup);
if (EnableAdaptiveBitrateStreaming(state, isLiveStream))
{
@ -540,17 +545,12 @@ namespace MediaBrowser.Api.Playback.Hls
var newBitrate = totalBitrate - variation;
var variantUrl = ReplaceBitrate(playlistUrl, requestedVideoBitrate, (requestedVideoBitrate - variation));
AppendPlaylist(builder, variantUrl, newBitrate, subtitleGroup);
AppendPlaylist(builder, state, variantUrl, newBitrate, subtitleGroup);
variation *= 2;
newBitrate = totalBitrate - variation;
variantUrl = ReplaceBitrate(playlistUrl, requestedVideoBitrate, (requestedVideoBitrate - variation));
AppendPlaylist(builder, variantUrl, newBitrate, subtitleGroup);
}
if (!string.IsNullOrWhiteSpace(subtitleGroup))
{
AddSubtitles(state, subtitleStreams, builder);
AppendPlaylist(builder, state, variantUrl, newBitrate, subtitleGroup);
}
return builder.ToString();
@ -566,11 +566,11 @@ namespace MediaBrowser.Api.Playback.Hls
private void AddSubtitles(StreamState state, IEnumerable<MediaStream> subtitles, StringBuilder builder)
{
var selectedIndex = state.SubtitleStream == null ? (int?)null : state.SubtitleStream.Index;
var selectedIndex = state.SubtitleStream == null || state.VideoRequest.SubtitleMethod != SubtitleDeliveryMethod.Hls ? (int?)null : state.SubtitleStream.Index;
foreach (var stream in subtitles)
{
const string format = "#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"subs\",NAME=\"{0}\",DEFAULT={1},FORCED={2},URI=\"{3}\",LANGUAGE=\"{4}\"";
const string format = "#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"subs\",NAME=\"{0}\",DEFAULT={1},FORCED={2},AUTOSELECT=YES,URI=\"{3}\",LANGUAGE=\"{4}\"";
var name = stream.Language;
@ -579,10 +579,11 @@ namespace MediaBrowser.Api.Playback.Hls
if (string.IsNullOrWhiteSpace(name)) name = stream.Codec ?? "Unknown";
var url = string.Format("{0}/Subtitles/{1}/subtitles.m3u8?SegmentLength={2}",
var url = string.Format("{0}/Subtitles/{1}/subtitles.m3u8?SegmentLength={2}&api_key={3}",
state.Request.MediaSourceId,
stream.Index.ToString(UsCulture),
30.ToString(UsCulture));
30.ToString(UsCulture),
AuthorizationContext.GetAuthorizationInfo(Request).Token);
var line = string.Format(format,
name,
@ -635,9 +636,15 @@ namespace MediaBrowser.Api.Playback.Hls
//return state.VideoRequest.VideoBitRate.HasValue;
}
private void AppendPlaylist(StringBuilder builder, string url, int bitrate, string subtitleGroup)
private void AppendPlaylist(StringBuilder builder, StreamState state, string url, int bitrate, string subtitleGroup)
{
var header = "#EXT-X-STREAM-INF:BANDWIDTH=" + bitrate.ToString(UsCulture);
var header = "#EXT-X-STREAM-INF:BANDWIDTH=" + bitrate.ToString(UsCulture) + ",AVERAGE-BANDWIDTH=" + bitrate.ToString(UsCulture);
// tvos wants resolution, codecs, framerate
//if (state.TargetFramerate.HasValue)
//{
// header += string.Format(",FRAME-RATE=\"{0}\"", state.TargetFramerate.Value.ToString(CultureInfo.InvariantCulture));
//}
if (!string.IsNullOrWhiteSpace(subtitleGroup))
{
@ -694,6 +701,7 @@ namespace MediaBrowser.Api.Playback.Hls
var builder = new StringBuilder();
builder.AppendLine("#EXTM3U");
builder.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
builder.AppendLine("#EXT-X-VERSION:3");
builder.AppendLine("#EXT-X-TARGETDURATION:" + Math.Ceiling((segmentLengths.Length > 0 ? segmentLengths.Max() : state.SegmentLength)).ToString(UsCulture));
builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
@ -820,7 +828,7 @@ namespace MediaBrowser.Api.Playback.Hls
var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"",
state.SegmentLength.ToString(UsCulture));
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode;
args += " " + GetVideoQualityParam(state, GetH264Encoder(state)) + keyFrameArg;
@ -846,7 +854,7 @@ namespace MediaBrowser.Api.Playback.Hls
private bool EnableCopyTs(StreamState state)
{
return state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream;
return state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode;
}
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)

View File

@ -9,6 +9,7 @@ using MediaBrowser.Model.Serialization;
using ServiceStack;
using System;
using CommonIO;
using MediaBrowser.Model.Dlna;
namespace MediaBrowser.Api.Playback.Hls
{
@ -104,7 +105,7 @@ namespace MediaBrowser.Api.Playback.Hls
var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"",
state.SegmentLength.ToString(UsCulture));
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode;
args += " " + GetVideoQualityParam(state, GetH264Encoder(state)) + keyFrameArg;

View File

@ -73,9 +73,13 @@ namespace MediaBrowser.Api.Playback.Progressive
audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(UsCulture));
}
if (state.OutputAudioSampleRate.HasValue)
// opus will fail on 44100
if (!string.Equals(state.OutputAudioCodec, "opus", global::System.StringComparison.OrdinalIgnoreCase))
{
audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture));
if (state.OutputAudioSampleRate.HasValue)
{
audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture));
}
}
const string vn = " -vn";

View File

@ -61,8 +61,9 @@ namespace MediaBrowser.Api.Playback.Progressive
{
try
{
new ProgressiveFileCopier(_fileSystem, _job)
.StreamFile(Path, responseStream);
var task = new ProgressiveFileCopier(_fileSystem, _job, Logger).StreamFile(Path, responseStream);
Task.WaitAll(task);
}
catch (IOException)
{
@ -91,19 +92,21 @@ namespace MediaBrowser.Api.Playback.Progressive
{
private readonly IFileSystem _fileSystem;
private readonly TranscodingJob _job;
private readonly ILogger _logger;
// 256k
private const int BufferSize = 262144;
private long _bytesWritten = 0;
public ProgressiveFileCopier(IFileSystem fileSystem, TranscodingJob job)
public ProgressiveFileCopier(IFileSystem fileSystem, TranscodingJob job, ILogger logger)
{
_fileSystem = fileSystem;
_job = job;
_logger = logger;
}
public void StreamFile(string path, Stream outputStream)
public async Task StreamFile(string path, Stream outputStream)
{
var eofCount = 0;
long position = 0;
@ -126,8 +129,7 @@ namespace MediaBrowser.Api.Playback.Progressive
{
eofCount++;
}
var task = Task.Delay(100);
Task.WaitAll(task);
await Task.Delay(100).ConfigureAwait(false);
}
else
{
@ -145,6 +147,30 @@ namespace MediaBrowser.Api.Playback.Progressive
int count;
while ((count = source.Read(array, 0, array.Length)) != 0)
{
//if (_job != null)
//{
// var didPause = false;
// var totalPauseTime = 0;
// if (_job.IsUserPaused)
// {
// _logger.Debug("Pausing writing to network stream while user has paused playback.");
// while (_job.IsUserPaused && totalPauseTime < 30000)
// {
// didPause = true;
// var pauseTime = 500;
// totalPauseTime += pauseTime;
// await Task.Delay(pauseTime).ConfigureAwait(false);
// }
// }
// if (didPause)
// {
// _logger.Debug("Resuming writing to network stream due to user unpausing playback.");
// }
//}
destination.Write(array, 0, count);
_bytesWritten += count;

View File

@ -13,6 +13,7 @@ using System;
using System.Globalization;
using System.IO;
using CommonIO;
using MediaBrowser.Model.Dlna;
namespace MediaBrowser.Api.Playback.Progressive
{
@ -161,7 +162,7 @@ namespace MediaBrowser.Api.Playback.Progressive
args += keyFrameArg;
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode;
var hasCopyTs = false;
// Add resolution params, if specified

View File

@ -213,8 +213,6 @@ namespace MediaBrowser.Api.Reports
SortBy = request.GetOrderBy(),
SortOrder = request.SortOrder ?? SortOrder.Ascending,
Filter = i => ApplyAdditionalFilters(request, i, user, _libraryManager),
IsFavorite = request.IsFavorite,
Limit = request.Limit,
StartIndex = request.StartIndex,
@ -258,7 +256,10 @@ namespace MediaBrowser.Api.Reports
MinPlayers = request.MinPlayers,
MaxPlayers = request.MaxPlayers,
MinCommunityRating = request.MinCommunityRating,
MinCriticRating = request.MinCriticRating
MinCriticRating = request.MinCriticRating,
ParentIndexNumber = request.ParentIndexNumber,
AiredDuringSeason = request.AiredDuringSeason,
AlbumArtistStartsWithOrGreater = request.AlbumArtistStartsWithOrGreater
};
if (!string.IsNullOrWhiteSpace(request.Ids))
@ -302,6 +303,72 @@ namespace MediaBrowser.Api.Reports
}
}
if (!string.IsNullOrEmpty(request.MinPremiereDate))
{
query.MinPremiereDate = DateTime.Parse(request.MinPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
}
if (!string.IsNullOrEmpty(request.MaxPremiereDate))
{
query.MaxPremiereDate = DateTime.Parse(request.MaxPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
}
// Filter by Series Status
if (!string.IsNullOrEmpty(request.SeriesStatus))
{
query.SeriesStatuses = request.SeriesStatus.Split(',').Select(d => (SeriesStatus)Enum.Parse(typeof(SeriesStatus), d, true)).ToArray();
}
// Filter by Series AirDays
if (!string.IsNullOrEmpty(request.AirDays))
{
query.AirDays = request.AirDays.Split(',').Select(d => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), d, true)).ToArray();
}
// ExcludeLocationTypes
if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
{
query.ExcludeLocationTypes = request.ExcludeLocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
}
if (!string.IsNullOrEmpty(request.LocationTypes))
{
query.LocationTypes = request.LocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
}
// Min official rating
if (!string.IsNullOrEmpty(request.MinOfficialRating))
{
query.MinParentalRating = _localization.GetRatingLevel(request.MinOfficialRating);
}
// Max official rating
if (!string.IsNullOrEmpty(request.MaxOfficialRating))
{
query.MaxParentalRating = _localization.GetRatingLevel(request.MinOfficialRating);
}
// Artists
if (!string.IsNullOrEmpty(request.ArtistIds))
{
var artistIds = request.ArtistIds.Split(new[] { '|', ',' });
var artistItems = artistIds.Select(_libraryManager.GetItemById).Where(i => i != null).ToList();
query.ArtistNames = artistItems.Select(i => i.Name).ToArray();
}
// Artists
if (!string.IsNullOrEmpty(request.Artists))
{
query.ArtistNames = request.Artists.Split('|');
}
// Albums
if (!string.IsNullOrEmpty(request.Albums))
{
query.AlbumNames = request.Albums.Split('|');
}
if (request.HasQueryLimit == false)
{
query.StartIndex = null;
@ -311,278 +378,6 @@ namespace MediaBrowser.Api.Reports
return query;
}
private bool ApplyAdditionalFilters(BaseReportRequest request, BaseItem i, User user, ILibraryManager libraryManager)
{
// Artists
if (!string.IsNullOrEmpty(request.ArtistIds))
{
var artistIds = request.ArtistIds.Split(new[] { '|', ',' });
var audio = i as IHasArtist;
if (!(audio != null && artistIds.Any(id =>
{
var artistItem = libraryManager.GetItemById(id);
return artistItem != null && audio.HasAnyArtist(artistItem.Name);
})))
{
return false;
}
}
// Artists
if (!string.IsNullOrEmpty(request.Artists))
{
var artists = request.Artists.Split('|');
var audio = i as IHasArtist;
if (!(audio != null && artists.Any(audio.HasAnyArtist)))
{
return false;
}
}
// Albums
if (!string.IsNullOrEmpty(request.Albums))
{
var albums = request.Albums.Split('|');
var audio = i as Audio;
if (audio != null)
{
if (!albums.Any(a => string.Equals(a, audio.Album, StringComparison.OrdinalIgnoreCase)))
{
return false;
}
}
var album = i as MusicAlbum;
if (album != null)
{
if (!albums.Any(a => string.Equals(a, album.Name, StringComparison.OrdinalIgnoreCase)))
{
return false;
}
}
var musicVideo = i as MusicVideo;
if (musicVideo != null)
{
if (!albums.Any(a => string.Equals(a, musicVideo.Album, StringComparison.OrdinalIgnoreCase)))
{
return false;
}
}
return false;
}
// Min index number
if (request.MinIndexNumber.HasValue)
{
if (!(i.IndexNumber.HasValue && i.IndexNumber.Value >= request.MinIndexNumber.Value))
{
return false;
}
}
// Min official rating
if (!string.IsNullOrEmpty(request.MinOfficialRating))
{
var level = _localization.GetRatingLevel(request.MinOfficialRating);
if (level.HasValue)
{
var rating = i.CustomRating;
if (string.IsNullOrEmpty(rating))
{
rating = i.OfficialRating;
}
if (!string.IsNullOrEmpty(rating))
{
var itemLevel = _localization.GetRatingLevel(rating);
if (!(!itemLevel.HasValue || itemLevel.Value >= level.Value))
{
return false;
}
}
}
}
// Max official rating
if (!string.IsNullOrEmpty(request.MaxOfficialRating))
{
var level = _localization.GetRatingLevel(request.MaxOfficialRating);
if (level.HasValue)
{
var rating = i.CustomRating;
if (string.IsNullOrEmpty(rating))
{
rating = i.OfficialRating;
}
if (!string.IsNullOrEmpty(rating))
{
var itemLevel = _localization.GetRatingLevel(rating);
if (!(!itemLevel.HasValue || itemLevel.Value <= level.Value))
{
return false;
}
}
}
}
// LocationTypes
if (!string.IsNullOrEmpty(request.LocationTypes))
{
var vals = request.LocationTypes.Split(',');
if (!vals.Contains(i.LocationType.ToString(), StringComparer.OrdinalIgnoreCase))
{
return false;
}
}
// ExcludeLocationTypes
if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
{
var vals = request.ExcludeLocationTypes.Split(',');
if (vals.Contains(i.LocationType.ToString(), StringComparer.OrdinalIgnoreCase))
{
return false;
}
}
if (!string.IsNullOrEmpty(request.AlbumArtistStartsWithOrGreater))
{
var ok = new[] { i }.OfType<IHasAlbumArtist>()
.Any(p => string.Compare(request.AlbumArtistStartsWithOrGreater, p.AlbumArtists.FirstOrDefault(), StringComparison.CurrentCultureIgnoreCase) < 1);
if (!ok)
{
return false;
}
}
// Filter by Series Status
if (!string.IsNullOrEmpty(request.SeriesStatus))
{
var vals = request.SeriesStatus.Split(',');
var ok = new[] { i }.OfType<Series>().Any(p => p.Status.HasValue && vals.Contains(p.Status.Value.ToString(), StringComparer.OrdinalIgnoreCase));
if (!ok)
{
return false;
}
}
// Filter by Series AirDays
if (!string.IsNullOrEmpty(request.AirDays))
{
var days = request.AirDays.Split(',').Select(d => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), d, true));
var ok = new[] { i }.OfType<Series>().Any(p => p.AirDays != null && days.Any(d => p.AirDays.Contains(d)));
if (!ok)
{
return false;
}
}
if (request.ParentIndexNumber.HasValue)
{
var filterValue = request.ParentIndexNumber.Value;
var episode = i as Episode;
if (episode != null)
{
if (episode.ParentIndexNumber.HasValue && episode.ParentIndexNumber.Value != filterValue)
{
return false;
}
}
var song = i as Audio;
if (song != null)
{
if (song.ParentIndexNumber.HasValue && song.ParentIndexNumber.Value != filterValue)
{
return false;
}
}
}
if (request.AiredDuringSeason.HasValue)
{
var episode = i as Episode;
if (episode == null)
{
return false;
}
if (!Series.FilterEpisodesBySeason(new[] { episode }, request.AiredDuringSeason.Value, true).Any())
{
return false;
}
}
if (!string.IsNullOrEmpty(request.MinPremiereDate))
{
var date = DateTime.Parse(request.MinPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
if (!(i.PremiereDate.HasValue && i.PremiereDate.Value >= date))
{
return false;
}
}
if (!string.IsNullOrEmpty(request.MaxPremiereDate))
{
var date = DateTime.Parse(request.MaxPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
if (!(i.PremiereDate.HasValue && i.PremiereDate.Value <= date))
{
return false;
}
}
return true;
}
/// <summary> Applies the paging. </summary>
/// <param name="request"> The request. </param>
/// <param name="items"> The items. </param>
/// <returns> IEnumerable{BaseItem}. </returns>
private IEnumerable<BaseItem> ApplyPaging(BaseReportRequest request, IEnumerable<BaseItem> items)
{
// Start at
if (request.StartIndex.HasValue)
{
items = items.Skip(request.StartIndex.Value);
}
// Return limit
if (request.Limit.HasValue)
{
items = items.Take(request.Limit.Value);
}
return items;
}
/// <summary> Gets query result. </summary>
/// <param name="request"> The request. </param>
/// <returns> The query result. </returns>

View File

@ -54,21 +54,7 @@ namespace MediaBrowser.Api
/// </summary>
public static class SimilarItemsHelper
{
/// <summary>
/// Gets the similar items.
/// </summary>
/// <param name="dtoOptions">The dto options.</param>
/// <param name="userManager">The user manager.</param>
/// <param name="itemRepository">The item repository.</param>
/// <param name="libraryManager">The library manager.</param>
/// <param name="userDataRepository">The user data repository.</param>
/// <param name="dtoService">The dto service.</param>
/// <param name="logger">The logger.</param>
/// <param name="request">The request.</param>
/// <param name="includeInSearch">The include in search.</param>
/// <param name="getSimilarityScore">The get similarity score.</param>
/// <returns>ItemsResult.</returns>
internal static ItemsResult GetSimilarItemsResult(DtoOptions dtoOptions, IUserManager userManager, IItemRepository itemRepository, ILibraryManager libraryManager, IUserDataManager userDataRepository, IDtoService dtoService, ILogger logger, BaseGetSimilarItemsFromItem request, Func<BaseItem, bool> includeInSearch, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
internal static ItemsResult GetSimilarItemsResult(DtoOptions dtoOptions, IUserManager userManager, IItemRepository itemRepository, ILibraryManager libraryManager, IUserDataManager userDataRepository, IDtoService dtoService, ILogger logger, BaseGetSimilarItemsFromItem request, Type[] includeTypes, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
{
var user = !string.IsNullOrWhiteSpace(request.UserId) ? userManager.GetUserById(request.UserId) : null;
@ -76,11 +62,13 @@ namespace MediaBrowser.Api
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
libraryManager.RootFolder) : libraryManager.GetItemById(request.Id);
Func<BaseItem, bool> filter = i => i.Id != item.Id && includeInSearch(i);
var query = new InternalItemsQuery(user)
{
IncludeItemTypes = includeTypes.Select(i => i.Name).ToArray(),
Recursive = true
};
var inputItems = user == null
? libraryManager.RootFolder.GetRecursiveChildren(filter)
: user.RootFolder.GetRecursiveChildren(user, filter);
var inputItems = libraryManager.GetItemList(query);
var items = GetSimilaritems(item, libraryManager, inputItems, getSimilarityScore)
.ToList();

View File

@ -68,6 +68,8 @@ namespace MediaBrowser.Api
_config.Configuration.EnableLocalizedGuids = true;
_config.Configuration.EnableCustomPathSubFolders = true;
_config.Configuration.EnableDateLastRefresh = true;
_config.Configuration.EnableStandaloneMusicKeys = true;
_config.Configuration.EnableCaseSensitiveItemIds = true;
_config.SaveConfiguration();
}

View File

@ -164,6 +164,8 @@ namespace MediaBrowser.Api.Subtitles
long positionTicks = 0;
var segmentLengthTicks = TimeSpan.FromSeconds(request.SegmentLength).Ticks;
var accessToken = AuthorizationContext.GetAuthorizationInfo(Request).Token;
while (positionTicks < runtime)
{
var remaining = runtime - positionTicks;
@ -173,9 +175,10 @@ namespace MediaBrowser.Api.Subtitles
var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks);
var url = string.Format("stream.srt?StartPositionTicks={0}&EndPositionTicks={1}",
var url = string.Format("stream.vtt?StartPositionTicks={0}&EndPositionTicks={1}&api_key={2}",
positionTicks.ToString(CultureInfo.InvariantCulture),
endPositionTicks.ToString(CultureInfo.InvariantCulture));
endPositionTicks.ToString(CultureInfo.InvariantCulture),
accessToken);
builder.AppendLine(url);

View File

@ -263,7 +263,7 @@ namespace MediaBrowser.Api
_userDataManager,
_dtoService,
Logger,
request, item => item is Series,
request, new[] { typeof(Series) },
SimilarItemsHelper.GetSimiliarityScore);
return ToOptimizedSerializedResultUsingCache(result);
@ -273,11 +273,11 @@ namespace MediaBrowser.Api
{
var user = _userManager.GetUserById(request.UserId);
var minPremiereDate = DateTime.Now.Date.AddDays(-1).ToUniversalTime();
var minPremiereDate = DateTime.Now.Date.ToUniversalTime();
var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Episode).Name },
SortBy = new[] { "PremiereDate", "AirTime", "SortName" },
@ -286,15 +286,15 @@ namespace MediaBrowser.Api
StartIndex = request.StartIndex,
Limit = request.Limit
}, parentIds);
}, parentIds).ToList();
var options = GetDtoOptions(request);
var returnItems = _dtoService.GetBaseItemDtos(itemsResult.Items, options, user).ToArray();
var returnItems = _dtoService.GetBaseItemDtos(itemsResult, options, user).ToArray();
var result = new ItemsResult
{
TotalRecordCount = itemsResult.TotalRecordCount,
TotalRecordCount = itemsResult.Count,
Items = returnItems
};

View File

@ -85,17 +85,16 @@ namespace MediaBrowser.Api.UserLibrary
/// <returns>Task{ItemsResult}.</returns>
private async Task<ItemsResult> GetItems(GetItems request)
{
var parentItem = string.IsNullOrEmpty(request.ParentId) ? null : _libraryManager.GetItemById(request.ParentId);
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
var result = await GetItemsToSerialize(request, user, parentItem).ConfigureAwait(false);
var result = await GetItemsToSerialize(request, user).ConfigureAwait(false);
var dtoOptions = GetDtoOptions(request);
return new ItemsResult
{
TotalRecordCount = result.Item1.TotalRecordCount,
Items = _dtoService.GetBaseItemDtos(result.Item1.Items, dtoOptions, user).ToArray()
TotalRecordCount = result.TotalRecordCount,
Items = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user).ToArray()
};
}
@ -104,17 +103,16 @@ namespace MediaBrowser.Api.UserLibrary
/// </summary>
/// <param name="request">The request.</param>
/// <param name="user">The user.</param>
/// <param name="parentItem">The parent item.</param>
/// <returns>IEnumerable{BaseItem}.</returns>
private async Task<Tuple<QueryResult<BaseItem>, bool>> GetItemsToSerialize(GetItems request, User user, BaseItem parentItem)
private async Task<QueryResult<BaseItem>> GetItemsToSerialize(GetItems request, User user)
{
var item = string.IsNullOrEmpty(request.ParentId) ?
user == null ? _libraryManager.RootFolder : user.RootFolder :
parentItem;
_libraryManager.GetItemById(request.ParentId);
if (string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase))
{
item = user == null ? _libraryManager.RootFolder : user.RootFolder;
//item = user == null ? _libraryManager.RootFolder : user.RootFolder;
}
else if (string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase))
{
@ -137,21 +135,21 @@ namespace MediaBrowser.Api.UserLibrary
result.Items = result.Items.OrderBy(i => ids.IndexOf(i.Id.ToString("N"))).ToArray();
}
return new Tuple<QueryResult<BaseItem>, bool>(result, true);
return result;
}
if (request.Recursive)
{
var result = await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
return new Tuple<QueryResult<BaseItem>, bool>(result, true);
return result;
}
if (user == null)
{
var result = await ((Folder)item).GetItems(GetItemsQuery(request, null)).ConfigureAwait(false);
return new Tuple<QueryResult<BaseItem>, bool>(result, true);
return result;
}
var userRoot = item as UserRootFolder;
@ -160,26 +158,24 @@ namespace MediaBrowser.Api.UserLibrary
{
var result = await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
return new Tuple<QueryResult<BaseItem>, bool>(result, true);
return result;
}
IEnumerable<BaseItem> items = ((Folder)item).GetChildren(user, true);
var itemsArray = items.ToArray();
return new Tuple<QueryResult<BaseItem>, bool>(new QueryResult<BaseItem>
return new QueryResult<BaseItem>
{
Items = itemsArray,
TotalRecordCount = itemsArray.Length
}, false);
};
}
private InternalItemsQuery GetItemsQuery(GetItems request, User user)
{
var query = new InternalItemsQuery
var query = new InternalItemsQuery(user)
{
User = user,
IsPlayed = request.IsPlayed,
MediaTypes = request.GetMediaTypes(),
IncludeItemTypes = request.GetIncludeItemTypes(),
@ -188,8 +184,6 @@ namespace MediaBrowser.Api.UserLibrary
SortBy = request.GetOrderBy(),
SortOrder = request.SortOrder ?? SortOrder.Ascending,
Filter = i => ApplyAdditionalFilters(request, i, user, _libraryManager),
IsFavorite = request.IsFavorite,
Limit = request.Limit,
StartIndex = request.StartIndex,
@ -234,7 +228,11 @@ namespace MediaBrowser.Api.UserLibrary
MinPlayers = request.MinPlayers,
MaxPlayers = request.MaxPlayers,
MinCommunityRating = request.MinCommunityRating,
MinCriticRating = request.MinCriticRating
MinCriticRating = request.MinCriticRating,
ParentId = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId),
ParentIndexNumber = request.ParentIndexNumber,
AiredDuringSeason = request.AiredDuringSeason,
AlbumArtistStartsWithOrGreater = request.AlbumArtistStartsWithOrGreater
};
if (!string.IsNullOrWhiteSpace(request.Ids))
@ -278,331 +276,73 @@ namespace MediaBrowser.Api.UserLibrary
}
}
return query;
}
/// <summary>
/// Applies filtering
/// </summary>
/// <param name="items">The items.</param>
/// <param name="filter">The filter.</param>
/// <param name="user">The user.</param>
/// <param name="repository">The repository.</param>
/// <returns>IEnumerable{BaseItem}.</returns>
internal static IEnumerable<BaseItem> ApplyFilter(IEnumerable<BaseItem> items, ItemFilter filter, User user, IUserDataManager repository)
{
// Avoid implicitly captured closure
var currentUser = user;
switch (filter)
if (!string.IsNullOrEmpty(request.MinPremiereDate))
{
case ItemFilter.IsFavoriteOrLikes:
return items.Where(item =>
{
var userdata = repository.GetUserData(user.Id, item.GetUserDataKey());
if (userdata == null)
{
return false;
}
var likes = userdata.Likes ?? false;
var favorite = userdata.IsFavorite;
return likes || favorite;
});
case ItemFilter.Likes:
return items.Where(item =>
{
var userdata = repository.GetUserData(user.Id, item.GetUserDataKey());
return userdata != null && userdata.Likes.HasValue && userdata.Likes.Value;
});
case ItemFilter.Dislikes:
return items.Where(item =>
{
var userdata = repository.GetUserData(user.Id, item.GetUserDataKey());
return userdata != null && userdata.Likes.HasValue && !userdata.Likes.Value;
});
case ItemFilter.IsFavorite:
return items.Where(item =>
{
var userdata = repository.GetUserData(user.Id, item.GetUserDataKey());
return userdata != null && userdata.IsFavorite;
});
case ItemFilter.IsResumable:
return items.Where(item =>
{
var userdata = repository.GetUserData(user.Id, item.GetUserDataKey());
return userdata != null && userdata.PlaybackPositionTicks > 0;
});
case ItemFilter.IsPlayed:
return items.Where(item => item.IsPlayed(currentUser));
case ItemFilter.IsUnplayed:
return items.Where(item => item.IsUnplayed(currentUser));
case ItemFilter.IsFolder:
return items.Where(item => item.IsFolder);
case ItemFilter.IsNotFolder:
return items.Where(item => !item.IsFolder);
case ItemFilter.IsRecentlyAdded:
return items.Where(item => (DateTime.UtcNow - item.DateCreated).TotalDays <= 10);
query.MinPremiereDate = DateTime.Parse(request.MinPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
}
return items;
}
private bool ApplyAdditionalFilters(GetItems request, BaseItem i, User user, ILibraryManager libraryManager)
{
// Artists
if (!string.IsNullOrEmpty(request.ArtistIds))
if (!string.IsNullOrEmpty(request.MaxPremiereDate))
{
var artistIds = request.ArtistIds.Split(new[] { '|', ',' });
var audio = i as IHasArtist;
if (!(audio != null && artistIds.Any(id =>
{
var artistItem = libraryManager.GetItemById(id);
return artistItem != null && audio.HasAnyArtist(artistItem.Name);
})))
{
return false;
}
}
// Artists
if (!string.IsNullOrEmpty(request.Artists))
{
var artists = request.Artists.Split('|');
var audio = i as IHasArtist;
if (!(audio != null && artists.Any(audio.HasAnyArtist)))
{
return false;
}
}
// Albums
if (!string.IsNullOrEmpty(request.Albums))
{
var albums = request.Albums.Split('|');
var audio = i as Audio;
if (audio != null)
{
if (!albums.Any(a => string.Equals(a, audio.Album, StringComparison.OrdinalIgnoreCase)))
{
return false;
}
}
var album = i as MusicAlbum;
if (album != null)
{
if (!albums.Any(a => string.Equals(a, album.Name, StringComparison.OrdinalIgnoreCase)))
{
return false;
}
}
var musicVideo = i as MusicVideo;
if (musicVideo != null)
{
if (!albums.Any(a => string.Equals(a, musicVideo.Album, StringComparison.OrdinalIgnoreCase)))
{
return false;
}
}
return false;
}
// Min official rating
if (!string.IsNullOrEmpty(request.MinOfficialRating))
{
var level = _localization.GetRatingLevel(request.MinOfficialRating);
if (level.HasValue)
{
var rating = i.CustomRating;
if (string.IsNullOrEmpty(rating))
{
rating = i.OfficialRating;
}
if (!string.IsNullOrEmpty(rating))
{
var itemLevel = _localization.GetRatingLevel(rating);
if (!(!itemLevel.HasValue || itemLevel.Value >= level.Value))
{
return false;
}
}
}
}
// Max official rating
if (!string.IsNullOrEmpty(request.MaxOfficialRating))
{
var level = _localization.GetRatingLevel(request.MaxOfficialRating);
if (level.HasValue)
{
var rating = i.CustomRating;
if (string.IsNullOrEmpty(rating))
{
rating = i.OfficialRating;
}
if (!string.IsNullOrEmpty(rating))
{
var itemLevel = _localization.GetRatingLevel(rating);
if (!(!itemLevel.HasValue || itemLevel.Value <= level.Value))
{
return false;
}
}
}
}
// LocationTypes
if (!string.IsNullOrEmpty(request.LocationTypes))
{
var vals = request.LocationTypes.Split(',');
if (!vals.Contains(i.LocationType.ToString(), StringComparer.OrdinalIgnoreCase))
{
return false;
}
}
// ExcludeLocationTypes
if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
{
var vals = request.ExcludeLocationTypes.Split(',');
if (vals.Contains(i.LocationType.ToString(), StringComparer.OrdinalIgnoreCase))
{
return false;
}
}
if (!string.IsNullOrEmpty(request.AlbumArtistStartsWithOrGreater))
{
var ok = new[] { i }.OfType<IHasAlbumArtist>()
.Any(p => string.Compare(request.AlbumArtistStartsWithOrGreater, p.AlbumArtists.FirstOrDefault(), StringComparison.CurrentCultureIgnoreCase) < 1);
if (!ok)
{
return false;
}
query.MaxPremiereDate = DateTime.Parse(request.MaxPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
}
// Filter by Series Status
if (!string.IsNullOrEmpty(request.SeriesStatus))
{
var vals = request.SeriesStatus.Split(',');
var ok = new[] { i }.OfType<Series>().Any(p => p.Status.HasValue && vals.Contains(p.Status.Value.ToString(), StringComparer.OrdinalIgnoreCase));
if (!ok)
{
return false;
}
query.SeriesStatuses = request.SeriesStatus.Split(',').Select(d => (SeriesStatus)Enum.Parse(typeof(SeriesStatus), d, true)).ToArray();
}
// Filter by Series AirDays
if (!string.IsNullOrEmpty(request.AirDays))
{
var days = request.AirDays.Split(',').Select(d => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), d, true));
var ok = new[] { i }.OfType<Series>().Any(p => p.AirDays != null && days.Any(d => p.AirDays.Contains(d)));
if (!ok)
{
return false;
}
query.AirDays = request.AirDays.Split(',').Select(d => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), d, true)).ToArray();
}
if (request.ParentIndexNumber.HasValue)
// ExcludeLocationTypes
if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
{
var filterValue = request.ParentIndexNumber.Value;
var episode = i as Episode;
if (episode != null)
{
if (episode.ParentIndexNumber.HasValue && episode.ParentIndexNumber.Value != filterValue)
{
return false;
}
}
var song = i as Audio;
if (song != null)
{
if (song.ParentIndexNumber.HasValue && song.ParentIndexNumber.Value != filterValue)
{
return false;
}
}
query.ExcludeLocationTypes = request.ExcludeLocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
}
if (request.AiredDuringSeason.HasValue)
if (!string.IsNullOrEmpty(request.LocationTypes))
{
var episode = i as Episode;
if (episode == null)
{
return false;
}
if (!Series.FilterEpisodesBySeason(new[] { episode }, request.AiredDuringSeason.Value, true).Any())
{
return false;
}
query.LocationTypes = request.LocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
}
if (!string.IsNullOrEmpty(request.MinPremiereDate))
// Min official rating
if (!string.IsNullOrEmpty(request.MinOfficialRating))
{
var date = DateTime.Parse(request.MinPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
if (!(i.PremiereDate.HasValue && i.PremiereDate.Value >= date))
{
return false;
}
query.MinParentalRating = _localization.GetRatingLevel(request.MinOfficialRating);
}
if (!string.IsNullOrEmpty(request.MaxPremiereDate))
// Max official rating
if (!string.IsNullOrEmpty(request.MaxOfficialRating))
{
var date = DateTime.Parse(request.MaxPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
if (!(i.PremiereDate.HasValue && i.PremiereDate.Value <= date))
{
return false;
}
query.MaxParentalRating = _localization.GetRatingLevel(request.MinOfficialRating);
}
return true;
// Artists
if (!string.IsNullOrEmpty(request.ArtistIds))
{
var artistIds = request.ArtistIds.Split(new[] { '|', ',' });
var artistItems = artistIds.Select(_libraryManager.GetItemById).Where(i => i != null).ToList();
query.ArtistNames = artistItems.Select(i => i.Name).ToArray();
}
// Artists
if (!string.IsNullOrEmpty(request.Artists))
{
query.ArtistNames = request.Artists.Split('|');
}
// Albums
if (!string.IsNullOrEmpty(request.Albums))
{
query.AlbumNames = request.Albums.Split('|');
}
return query;
}
}

View File

@ -335,11 +335,6 @@ namespace MediaBrowser.Api.UserLibrary
public void Post(ReportPlaybackProgress request)
{
if (!string.IsNullOrWhiteSpace(request.PlaySessionId))
{
ApiEntryPoint.Instance.PingTranscodingJob(request.PlaySessionId);
}
request.SessionId = GetSession().Result.Id;
var task = _sessionManager.OnPlaybackProgress(request);
@ -349,7 +344,7 @@ namespace MediaBrowser.Api.UserLibrary
public void Post(PingPlaybackSession request)
{
ApiEntryPoint.Instance.PingTranscodingJob(request.PlaySessionId);
ApiEntryPoint.Instance.PingTranscodingJob(request.PlaySessionId, null);
}
/// <summary>

View File

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

View File

@ -126,6 +126,23 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
}
}
private void AddIpv4Option(HttpWebRequest request, HttpRequestOptions options)
{
if (!options.PreferIpv4)
{
return;
}
request.ServicePoint.BindIPEndPointDelegate = (servicePount, remoteEndPoint, retryCount) =>
{
if (remoteEndPoint.AddressFamily == AddressFamily.InterNetwork)
{
return new IPEndPoint(IPAddress.Any, 0);
}
throw new InvalidOperationException("no IPv4 address");
};
}
private WebRequest GetRequest(HttpRequestOptions options, string method, bool enableHttpCompression)
{
var request = CreateWebRequest(options.Url);
@ -133,6 +150,8 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
if (httpWebRequest != null)
{
AddIpv4Option(httpWebRequest, options);
AddRequestHeaders(httpWebRequest, options);
httpWebRequest.AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None;

View File

@ -49,7 +49,7 @@
<ItemGroup>
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\CommonIO.1.0.0.8\lib\net45\CommonIO.dll</HintPath>
<HintPath>..\packages\CommonIO.1.0.0.9\lib\net45\CommonIO.dll</HintPath>
</Reference>
<Reference Include="MoreLinq">
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>

View File

@ -170,6 +170,17 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
QueueScheduledTask<T>(new TaskExecutionOptions());
}
public void QueueIfNotRunning<T>()
where T : IScheduledTask
{
var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T));
if (task.State != TaskState.Running)
{
QueueScheduledTask<T>(new TaskExecutionOptions());
}
}
public void Execute<T>()
where T : IScheduledTask
{

View File

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

View File

@ -96,6 +96,7 @@ namespace MediaBrowser.Common.Net
public TimeSpan CacheLength { get; set; }
public int TimeoutMs { get; set; }
public bool PreferIpv4 { get; set; }
private string GetHeaderValue(string name)
{

View File

@ -50,6 +50,9 @@ namespace MediaBrowser.Common.ScheduledTasks
void QueueScheduledTask<T>()
where T : IScheduledTask;
void QueueIfNotRunning<T>()
where T : IScheduledTask;
/// <summary>
/// Queues the scheduled task.
/// </summary>

View File

@ -3,6 +3,7 @@ using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Querying;
using System;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
@ -30,6 +31,13 @@ namespace MediaBrowser.Controller.Channels
return base.IsVisible(user);
}
[IgnoreDataMember]
public override SourceType SourceType
{
get { return SourceType.Channel; }
set { }
}
public override async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
{
try
@ -75,5 +83,12 @@ namespace MediaBrowser.Controller.Channels
{
return false;
}
internal static bool IsChannelVisible(BaseItem channelItem, User user)
{
var channel = ChannelManager.GetChannel(channelItem.ChannelId);
return channel.IsVisible(user);
}
}
}

View File

@ -12,7 +12,7 @@ using System.Threading;
namespace MediaBrowser.Controller.Channels
{
public class ChannelAudioItem : Audio, IChannelMediaItem
public class ChannelAudioItem : Audio
{
public ChannelMediaContentType ContentType { get; set; }

View File

@ -11,7 +11,7 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Channels
{
public class ChannelFolderItem : Folder, IChannelItem
public class ChannelFolderItem : Folder
{
public ChannelFolderType ChannelFolderType { get; set; }

View File

@ -13,7 +13,7 @@ using System.Threading;
namespace MediaBrowser.Controller.Channels
{
public class ChannelVideoItem : Video, IChannelMediaItem, IHasLookupInfo<ChannelItemLookupInfo>
public class ChannelVideoItem : Video
{
public ChannelMediaContentType ContentType { get; set; }
@ -103,20 +103,6 @@ namespace MediaBrowser.Controller.Channels
return list;
}
public ChannelItemLookupInfo GetLookupInfo()
{
var info = GetItemLookupInfo<ChannelItemLookupInfo>();
info.ContentType = ContentType;
if (ExtraType.HasValue)
{
info.ExtraType = ExtraType.Value;
}
return info;
}
protected override string GetInternalMetadataPath(string basePath)
{
return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
@ -132,7 +118,7 @@ namespace MediaBrowser.Controller.Channels
return IsVisibleStandaloneInternal(user, false) && IsChannelVisible(this, user);
}
internal static bool IsChannelVisible(IChannelItem item, User user)
internal static bool IsChannelVisible(BaseItem item, User user)
{
var channel = ChannelManager.GetChannel(item.ChannelId);

View File

@ -116,7 +116,7 @@ namespace MediaBrowser.Controller.Channels
/// <param name="includeCachedVersions">if set to <c>true</c> [include cached versions].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns>
Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(IChannelMediaItem item, bool includeCachedVersions, CancellationToken cancellationToken);
Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(BaseItem item, bool includeCachedVersions, CancellationToken cancellationToken);
/// <summary>
/// Gets the channel folder.
@ -141,6 +141,6 @@ namespace MediaBrowser.Controller.Channels
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task DownloadChannelItem(IChannelMediaItem item, string destinationPath, IProgress<double> progress, CancellationToken cancellationToken);
Task DownloadChannelItem(BaseItem item, string destinationPath, IProgress<double> progress, CancellationToken cancellationToken);
}
}

View File

@ -17,6 +17,7 @@ namespace MediaBrowser.Controller.Dto
public List<ImageType> ImageTypes { get; set; }
public int ImageTypeLimit { get; set; }
public bool EnableImages { get; set; }
public bool AddProgramRecordingInfo { get; set; }
public string DeviceId { get; set; }
public DtoOptions()

View File

@ -8,6 +8,8 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using MediaBrowser.Controller.Channels;
namespace MediaBrowser.Controller.Entities.Audio
{
@ -24,6 +26,8 @@ namespace MediaBrowser.Controller.Entities.Audio
IThemeMedia,
IArchivable
{
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
public long? Size { get; set; }
public string Container { get; set; }
public int? TotalBitrate { get; set; }
@ -153,6 +157,31 @@ namespace MediaBrowser.Controller.Entities.Audio
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
{
if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
{
var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty;
if (ParentIndexNumber.HasValue)
{
songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey;
}
songKey+= Name;
if (!string.IsNullOrWhiteSpace(Album))
{
songKey = Album + "-" + songKey;
}
var albumArtist = AlbumArtists.FirstOrDefault();
if (!string.IsNullOrWhiteSpace(albumArtist))
{
songKey = albumArtist + "-" + songKey;
}
return songKey;
}
var parent = AlbumEntity;
if (parent != null)
@ -173,7 +202,11 @@ namespace MediaBrowser.Controller.Entities.Audio
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Music;
if (SourceType == SourceType.Library)
{
return UnratedItem.Music;
}
return base.GetBlockUnratedType();
}
public SongInfo GetLookupInfo()
@ -189,6 +222,32 @@ namespace MediaBrowser.Controller.Entities.Audio
public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
{
if (SourceType == SourceType.Channel)
{
var sources = ChannelManager.GetStaticMediaSources(this, false, CancellationToken.None)
.Result.ToList();
if (sources.Count > 0)
{
return sources;
}
var list = new List<MediaSourceInfo>
{
GetVersionInfo(this, enablePathSubstitution)
};
foreach (var mediaSource in list)
{
if (string.IsNullOrWhiteSpace(mediaSource.Path))
{
mediaSource.Type = MediaSourceType.Placeholder;
}
}
return list;
}
var result = new List<MediaSourceInfo>
{
GetVersionInfo(this, enablePathSubstitution)

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Entities.Audio
{
public class AudioPodcast : Audio
{
}
}

View File

@ -34,7 +34,17 @@ namespace MediaBrowser.Controller.Entities.Audio
{
get
{
return GetParents().OfType<MusicArtist>().FirstOrDefault();
var artist = GetParents().OfType<MusicArtist>().FirstOrDefault();
if (artist == null)
{
var name = AlbumArtist;
if (!string.IsNullOrWhiteSpace(name))
{
artist = LibraryManager.GetArtist(name);
}
}
return artist;
}
}
@ -106,6 +116,15 @@ namespace MediaBrowser.Controller.Entities.Audio
return "MusicAlbum-Musicbrainz-" + id;
}
if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
{
var albumArtist = AlbumArtist;
if (!string.IsNullOrWhiteSpace(albumArtist))
{
return albumArtist + "-" + Name;
}
}
return base.CreateUserDataKey();
}
@ -125,7 +144,7 @@ namespace MediaBrowser.Controller.Entities.Audio
id.AlbumArtists = AlbumArtists;
var artist = GetParents().OfType<MusicArtist>().FirstOrDefault();
var artist = MusicArtist;
if (artist != null)
{

View File

@ -20,9 +20,11 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.LiveTv;
namespace MediaBrowser.Controller.Entities
@ -57,7 +59,9 @@ namespace MediaBrowser.Controller.Entities
public static string ThemeSongFilename = "theme";
public static string ThemeVideosFolderName = "backdrops";
[IgnoreDataMember]
public string PreferredMetadataCountryCode { get; set; }
[IgnoreDataMember]
public string PreferredMetadataLanguage { get; set; }
public List<ItemImageInfo> ImageInfos { get; set; }
@ -88,6 +92,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets a value indicating whether this instance is in mixed folder.
/// </summary>
/// <value><c>true</c> if this instance is in mixed folder; otherwise, <c>false</c>.</value>
[IgnoreDataMember]
public bool IsInMixedFolder { get; set; }
[IgnoreDataMember]
@ -166,6 +171,9 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public bool IsOffline { get; set; }
[IgnoreDataMember]
public virtual SourceType SourceType { get; set; }
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself
@ -184,6 +192,13 @@ namespace MediaBrowser.Controller.Entities
}
}
/// <summary>
/// Gets or sets the name of the service.
/// </summary>
/// <value>The name of the service.</value>
[IgnoreDataMember]
public string ServiceName { get; set; }
/// <summary>
/// If this content came from an external service, the id of the content on that service
/// </summary>
@ -252,6 +267,11 @@ namespace MediaBrowser.Controller.Entities
{
get
{
if (SourceType == SourceType.Channel)
{
return false;
}
var locationType = LocationType;
return locationType != LocationType.Remote && locationType != LocationType.Virtual;
@ -281,6 +301,40 @@ namespace MediaBrowser.Controller.Entities
}
}
private List<Tuple<StringBuilder,bool>> GetSortChunks(string s1)
{
var list = new List<Tuple<StringBuilder, bool>>();
int thisMarker = 0, thisNumericChunk = 0;
while ((thisMarker < s1.Length))
{
if (thisMarker >= s1.Length)
{
break;
}
char thisCh = s1[thisMarker];
StringBuilder thisChunk = new StringBuilder();
while ((thisMarker < s1.Length) && (thisChunk.Length == 0 || SortHelper.InChunk(thisCh, thisChunk[0])))
{
thisChunk.Append(thisCh);
thisMarker++;
if (thisMarker < s1.Length)
{
thisCh = s1[thisMarker];
}
}
var isNumeric = thisChunk.Length > 0 && char.IsDigit(thisChunk[0]);
list.Add(new Tuple<StringBuilder, bool>(thisChunk, isNumeric));
}
return list;
}
/// <summary>
/// This is just a helper for convenience
/// </summary>
@ -298,6 +352,11 @@ namespace MediaBrowser.Controller.Entities
public virtual bool CanDelete()
{
if (SourceType == SourceType.Channel)
{
return false;
}
var locationType = LocationType;
return locationType != LocationType.Remote &&
locationType != LocationType.Virtual;
@ -342,6 +401,7 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public DateTime DateModified { get; set; }
[IgnoreDataMember]
public DateTime DateLastSaved { get; set; }
[IgnoreDataMember]
@ -380,6 +440,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the locked fields.
/// </summary>
/// <value>The locked fields.</value>
[IgnoreDataMember]
public List<MetadataFields> LockedFields { get; set; }
/// <summary>
@ -433,11 +494,6 @@ namespace MediaBrowser.Controller.Entities
{
get
{
if (!string.IsNullOrWhiteSpace(ForcedSortName))
{
return ForcedSortName;
}
return _sortName ?? (_sortName = CreateSortName());
}
set
@ -455,6 +511,11 @@ namespace MediaBrowser.Controller.Entities
protected virtual string GetInternalMetadataPath(string basePath)
{
if (SourceType == SourceType.Channel)
{
return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
}
var idString = Id.ToString("N");
basePath = System.IO.Path.Combine(basePath, "library");
@ -468,6 +529,11 @@ namespace MediaBrowser.Controller.Entities
/// <returns>System.String.</returns>
protected virtual string CreateSortName()
{
if (!string.IsNullOrWhiteSpace(ForcedSortName))
{
return ModifySortChunks(ForcedSortName).ToLower();
}
if (Name == null) return null; //some items may not have name filled in properly
if (!EnableAlphaNumericSorting)
@ -497,7 +563,32 @@ namespace MediaBrowser.Controller.Entities
sortable = sortable.Remove(sortable.Length - (searchLower.Length + 1));
}
}
return sortable;
return ModifySortChunks(sortable);
}
private string ModifySortChunks(string name)
{
var chunks = GetSortChunks(name);
var builder = new StringBuilder();
foreach (var chunk in chunks)
{
var chunkBuilder = chunk.Item1;
// This chunk is numeric
if (chunk.Item2)
{
while (chunkBuilder.Length < 10)
{
chunkBuilder.Insert(0, '0');
}
}
builder.Append(chunkBuilder);
}
//Logger.Debug("ModifySortChunks Start: {0} End: {1}", name, builder.ToString());
return builder.ToString();
}
[IgnoreDataMember]
@ -595,6 +686,18 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public string OfficialRating { get; set; }
/// <summary>
/// Gets or sets the critic rating.
/// </summary>
/// <value>The critic rating.</value>
public float? CriticRating { get; set; }
/// <summary>
/// Gets or sets the critic rating summary.
/// </summary>
/// <value>The critic rating summary.</value>
public string CriticRatingSummary { get; set; }
/// <summary>
/// Gets or sets the official rating description.
/// </summary>
@ -620,6 +723,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the studios.
/// </summary>
/// <value>The studios.</value>
[IgnoreDataMember]
public List<string> Studios { get; set; }
/// <summary>
@ -633,6 +737,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the tags.
/// </summary>
/// <value>The tags.</value>
[IgnoreDataMember]
public List<string> Tags { get; set; }
/// <summary>
@ -1025,6 +1130,13 @@ namespace MediaBrowser.Controller.Entities
protected virtual string CreateUserDataKey()
{
if (SourceType == SourceType.Channel)
{
if (!string.IsNullOrWhiteSpace(ExternalId))
{
return ExternalId;
}
}
return Id.ToString();
}
@ -1103,6 +1215,11 @@ namespace MediaBrowser.Controller.Entities
public virtual bool IsSaveLocalMetadataEnabled()
{
if (SourceType == SourceType.Channel)
{
return false;
}
return ConfigurationManager.Configuration.SaveLocalMeta;
}
@ -1218,6 +1335,11 @@ namespace MediaBrowser.Controller.Entities
public virtual UnratedItem GetBlockUnratedType()
{
if (SourceType == SourceType.Channel)
{
return UnratedItem.ChannelContent;
}
return UnratedItem.Other;
}
@ -1261,6 +1383,11 @@ namespace MediaBrowser.Controller.Entities
public virtual bool IsVisibleStandalone(User user)
{
if (SourceType == SourceType.Channel)
{
return IsVisibleStandaloneInternal(user, false) && Channel.IsChannelVisible(this, user);
}
return IsVisibleStandaloneInternal(user, true);
}
@ -1312,6 +1439,11 @@ namespace MediaBrowser.Controller.Entities
public virtual string GetClientTypeName()
{
if (IsFolder && SourceType == SourceType.Channel)
{
return "ChannelFolderItem";
}
return GetType().Name;
}
@ -1835,8 +1967,8 @@ namespace MediaBrowser.Controller.Entities
ProviderIds = ProviderIds,
IndexNumber = IndexNumber,
ParentIndexNumber = ParentIndexNumber,
Year = ProductionYear,
PremiereDate = PremiereDate
Year = ProductionYear,
PremiereDate = PremiereDate
};
}
@ -1985,5 +2117,14 @@ namespace MediaBrowser.Controller.Entities
{
return LibraryManager.DeleteItem(this, options);
}
public virtual Task OnFileDeleted()
{
// Remove from database
return Delete(new DeleteOptions
{
DeleteFileLocation = false
});
}
}
}

View File

@ -2,6 +2,7 @@
using MediaBrowser.Model.Configuration;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Users;
@ -9,6 +10,7 @@ namespace MediaBrowser.Controller.Entities
{
public class Book : BaseItem, IHasTags, IHasLookupInfo<BookInfo>, IHasSeries
{
[IgnoreDataMember]
public override string MediaType
{
get

View File

@ -15,6 +15,9 @@ using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.Channels;
namespace MediaBrowser.Controller.Entities
{
@ -145,60 +148,38 @@ namespace MediaBrowser.Controller.Entities
item.DateModified = DateTime.UtcNow;
}
AddChildInternal(item);
AddChildInternal(item.Id);
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
if (!EnableNewFolderQuerying())
{
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
}
}
private static bool EnableNewFolderQuerying()
protected void AddChildrenInternal(List<Guid> children)
{
return ConfigurationManager.Configuration.MigrationVersion >= 1;
}
protected void AddChildrenInternal(IEnumerable<BaseItem> children)
{
var actualChildren = ActualChildren;
lock (_childrenSyncLock)
{
var newChildren = actualChildren.ToList();
var newChildren = ChildIds.ToList();
newChildren.AddRange(children);
_children = newChildren;
_children = newChildren.ToList();
}
}
protected void AddChildInternal(BaseItem child)
{
var actualChildren = ActualChildren;
lock (_childrenSyncLock)
{
var newChildren = actualChildren.ToList();
newChildren.Add(child);
_children = newChildren;
}
}
protected void RemoveChildrenInternal(IEnumerable<BaseItem> children)
{
var ids = children.Select(i => i.Id).ToList();
var actualChildren = ActualChildren;
lock (_childrenSyncLock)
{
_children = actualChildren.Where(i => !ids.Contains(i.Id)).ToList();
}
}
protected void ClearChildrenInternal()
protected void AddChildInternal(Guid child)
{
lock (_childrenSyncLock)
{
_children = new List<BaseItem>();
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();
}
}
@ -206,40 +187,11 @@ namespace MediaBrowser.Controller.Entities
/// Removes the child.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
/// <exception cref="System.InvalidOperationException">Unable to remove + item.Name</exception>
public Task RemoveChild(BaseItem item, CancellationToken cancellationToken)
public void RemoveChild(BaseItem item)
{
RemoveChildrenInternal(new[] { item });
RemoveChildrenInternal(new[] { item.Id }.ToList());
item.SetParent(null);
if (!EnableNewFolderQuerying())
{
return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken);
}
return Task.FromResult(true);
}
/// <summary>
/// Clears the children.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public Task ClearChildren(CancellationToken cancellationToken)
{
var items = ActualChildren.ToList();
ClearChildrenInternal();
foreach (var item in items)
{
LibraryManager.ReportItemRemoved(item);
}
return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken);
}
#region Indexing
@ -276,7 +228,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// The children
/// </summary>
private IReadOnlyList<BaseItem> _children;
private IReadOnlyList<Guid> _children;
/// <summary>
/// The _children sync lock
/// </summary>
@ -285,21 +237,30 @@ namespace MediaBrowser.Controller.Entities
/// 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>
/// <value>The actual children.</value>
protected virtual IEnumerable<BaseItem> ActualChildren
{
get
{
if (_children == null)
{
lock (_childrenSyncLock)
{
if (_children == null)
{
_children = LoadChildren().ToList();
}
}
}
return _children;
return ChildIds.Select(LibraryManager.GetItemById).Where(i => i != null);
}
}
@ -353,7 +314,7 @@ namespace MediaBrowser.Controller.Entities
/// Loads our children. Validation will occur externally.
/// We want this sychronous.
/// </summary>
protected virtual IEnumerable<BaseItem> LoadChildren()
protected virtual IEnumerable<Guid> LoadChildren()
{
//just load our children from the repo - the library will be validated and maintained in other processes
return GetCachedChildren();
@ -503,7 +464,7 @@ namespace MediaBrowser.Controller.Entities
if (actualRemovals.Count > 0)
{
RemoveChildrenInternal(actualRemovals);
RemoveChildrenInternal(actualRemovals.Select(i => i.Id).ToList());
foreach (var item in actualRemovals)
{
@ -518,12 +479,7 @@ namespace MediaBrowser.Controller.Entities
await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false);
AddChildrenInternal(newItems);
if (!EnableNewFolderQuerying())
{
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
}
AddChildrenInternal(newItems.Select(i => i.Id).ToList());
}
}
@ -751,51 +707,459 @@ namespace MediaBrowser.Controller.Entities
/// Get our children from the repo - stubbed for now
/// </summary>
/// <returns>IEnumerable{BaseItem}.</returns>
protected IEnumerable<BaseItem> GetCachedChildren()
protected IEnumerable<Guid> GetCachedChildren()
{
if (EnableNewFolderQuerying())
return ItemRepository.GetItemIdsList(new InternalItemsQuery
{
return ItemRepository.GetItemList(new InternalItemsQuery
{
ParentId = Id
ParentId = Id
}).Select(RetrieveChild).Where(i => i != null);
}
return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null);
});
}
private BaseItem RetrieveChild(BaseItem child)
public QueryResult<BaseItem> QueryRecursive(InternalItemsQuery query)
{
if (child == null || child.Id == Guid.Empty)
{
Logger.Error("Item found with empty Id: " + (child.Path ?? child.Name));
return null;
}
var user = query.User;
var item = LibraryManager.GetMemoryItemById(child.Id);
if (item != null)
if (RequiresPostFiltering(query))
{
if (item is IByReferenceItem)
IEnumerable<BaseItem> items;
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
if (query.User == null)
{
return LibraryManager.GetOrAddByReferenceItem(item);
items = GetRecursiveChildren(filter);
}
else
{
items = GetRecursiveChildren(user, filter);
}
item.SetParent(this);
}
else
{
child.SetParent(this);
LibraryManager.RegisterItem(child);
item = child;
return PostFilterAndSort(items, query);
}
return item;
if (!(this is UserRootFolder) && !(this is AggregateFolder))
{
query.ParentId = query.ParentId ?? Id;
}
return LibraryManager.GetItemsResult(query);
}
public virtual Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
private bool RequiresPostFiltering(InternalItemsQuery query)
{
if (LinkedChildren.Count > 0)
{
if (!(this is ICollectionFolder))
{
Logger.Debug("Query requires post-filtering due to LinkedChildren");
return true;
}
}
if (query.SortBy != null && query.SortBy.Length > 0)
{
if (query.SortBy.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.DatePlayed");
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 (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
return true;
}
if (query.SortBy.Contains(ItemSortBy.Album, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.Album");
return true;
}
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.Budget, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.Budget");
return true;
}
if (query.SortBy.Contains(ItemSortBy.DateLastContentAdded, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.DateLastContentAdded");
return true;
}
if (query.SortBy.Contains(ItemSortBy.GameSystem, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.GameSystem");
return true;
}
if (query.SortBy.Contains(ItemSortBy.Metascore, StringComparer.OrdinalIgnoreCase))
{
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.PlayCount, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.PlayCount");
return true;
}
if (query.SortBy.Contains(ItemSortBy.Players, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.Players");
return true;
}
if (query.SortBy.Contains(ItemSortBy.Revenue, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.Revenue");
return true;
}
if (query.SortBy.Contains(ItemSortBy.SeriesSortName, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.SeriesSortName");
return true;
}
if (query.SortBy.Contains(ItemSortBy.StartDate, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.StartDate");
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");
return true;
}
}
if (query.ItemIds.Length > 0)
{
Logger.Debug("Query requires post-filtering due to ItemIds");
return true;
}
if (query.PersonIds.Length > 0)
{
Logger.Debug("Query requires post-filtering due to PersonIds");
return true;
}
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");
return true;
}
// Filter by Video3DFormat
if (query.Is3D.HasValue)
{
Logger.Debug("Query requires post-filtering due to Is3D");
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");
return true;
}
if (query.IsPlaceHolder.HasValue)
{
Logger.Debug("Query requires post-filtering due to IsPlaceHolder");
return true;
}
if (query.HasSpecialFeature.HasValue)
{
Logger.Debug("Query requires post-filtering due to HasSpecialFeature");
return true;
}
if (query.HasSubtitles.HasValue)
{
Logger.Debug("Query requires post-filtering due to HasSubtitles");
return true;
}
if (query.HasTrailer.HasValue)
{
Logger.Debug("Query requires post-filtering due to HasTrailer");
return true;
}
if (query.HasThemeSong.HasValue)
{
Logger.Debug("Query requires post-filtering due to HasThemeSong");
return true;
}
if (query.HasThemeVideo.HasValue)
{
Logger.Debug("Query requires post-filtering due to HasThemeVideo");
return true;
}
// Filter by VideoType
if (query.VideoTypes.Length > 0)
{
Logger.Debug("Query requires post-filtering due to VideoTypes");
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)
{
Logger.Debug("Query requires post-filtering due to StudioIds");
return true;
}
// Apply genre filter
if (query.GenreIds.Length > 0)
{
Logger.Debug("Query requires post-filtering due to GenreIds");
return true;
}
// Apply person filter
if (query.ItemIdsFromPersonFilters != null)
{
Logger.Debug("Query requires post-filtering due to ItemIdsFromPersonFilters");
return true;
}
if (query.MinPlayers.HasValue)
{
Logger.Debug("Query requires post-filtering due to MinPlayers");
return true;
}
if (query.MaxPlayers.HasValue)
{
Logger.Debug("Query requires post-filtering due to MaxPlayers");
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");
return true;
}
if (query.IsUnaired.HasValue)
{
Logger.Debug("Query requires post-filtering due to IsUnaired");
return true;
}
if (query.IsVirtualUnaired.HasValue)
{
Logger.Debug("Query requires post-filtering due to IsVirtualUnaired");
return true;
}
if (UserViewBuilder.CollapseBoxSetItems(query, this, query.User))
{
Logger.Debug("Query requires post-filtering due to CollapseBoxSetItems");
return true;
}
if (!string.IsNullOrWhiteSpace(query.AdjacentTo))
{
Logger.Debug("Query requires post-filtering due to AdjacentTo");
return true;
}
if (!string.IsNullOrWhiteSpace(query.NameContains))
{
Logger.Debug("Query requires post-filtering due to NameContains");
return true;
}
if (!string.IsNullOrWhiteSpace(query.NameLessThan))
{
Logger.Debug("Query requires post-filtering due to NameLessThan");
return true;
}
if (!string.IsNullOrWhiteSpace(query.NameStartsWith))
{
Logger.Debug("Query requires post-filtering due to NameStartsWith");
return true;
}
if (!string.IsNullOrWhiteSpace(query.NameStartsWithOrGreater))
{
Logger.Debug("Query requires post-filtering due to NameStartsWithOrGreater");
return true;
}
if (query.AirDays.Length > 0)
{
Logger.Debug("Query requires post-filtering due to AirDays");
return true;
}
if (query.SeriesStatuses.Length > 0)
{
Logger.Debug("Query requires post-filtering due to SeriesStatuses");
return true;
}
if (query.AiredDuringSeason.HasValue)
{
Logger.Debug("Query requires post-filtering due to AiredDuringSeason");
return true;
}
if (!string.IsNullOrWhiteSpace(query.AlbumArtistStartsWithOrGreater))
{
Logger.Debug("Query requires post-filtering due to AlbumArtistStartsWithOrGreater");
return true;
}
if (query.AlbumNames.Length > 0)
{
Logger.Debug("Query requires post-filtering due to AlbumNames");
return true;
}
if (query.ArtistNames.Length > 0)
{
Logger.Debug("Query requires post-filtering due to ArtistNames");
return true;
}
return false;
}
public virtual async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
{
if (SourceType == SourceType.Channel)
{
try
{
// Don't blow up here because it could cause parent screens with other content to fail
return await ChannelManager.GetChannelItemsInternal(new ChannelItemQuery
{
ChannelId = ChannelId,
FolderId = Id.ToString("N"),
Limit = query.Limit,
StartIndex = query.StartIndex,
UserId = query.User.Id.ToString("N"),
SortBy = query.SortBy,
SortOrder = query.SortOrder
}, new Progress<double>(), CancellationToken.None);
}
catch
{
// Already logged at lower levels
return new QueryResult<BaseItem>
{
};
}
}
if (query.Recursive)
{
return QueryRecursive(query);
}
var user = query.User;
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
@ -817,7 +1181,7 @@ namespace MediaBrowser.Controller.Entities
var result = PostFilterAndSort(items, query);
return Task.FromResult(result);
return result;
}
protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)

View File

@ -83,6 +83,7 @@ namespace MediaBrowser.Controller.Entities
public string[] OfficialRatings { get; set; }
public DateTime? MinPremiereDate { get; set; }
public DateTime? MaxPremiereDate { get; set; }
public DateTime? MinStartDate { get; set; }
public DateTime? MaxStartDate { get; set; }
public DateTime? MinEndDate { get; set; }
@ -96,28 +97,45 @@ namespace MediaBrowser.Controller.Entities
public int? MinPlayers { get; set; }
public int? MaxPlayers { get; set; }
public int? MinIndexNumber { get; set; }
public int? AiredDuringSeason { get; set; }
public double? MinCriticRating { get; set; }
public double? MinCommunityRating { get; set; }
public string[] ChannelIds { get; set; }
internal List<Guid> ItemIdsFromPersonFilters { get; set; }
public int? ParentIndexNumber { get; set; }
public int? MinParentalRating { get; set; }
public int? MaxParentalRating { get; set; }
public bool? IsCurrentSchema { get; set; }
public bool? HasDeadParentId { get; set; }
public bool? IsOffline { get; set; }
public LocationType? LocationType { get; set; }
public Guid? ParentId { get; set; }
public string[] AncestorIds { get; set; }
public string[] TopParentIds { get; set; }
public LocationType[] LocationTypes { get; set; }
public LocationType[] ExcludeLocationTypes { get; set; }
public string[] PresetViews { get; set; }
public SourceType[] SourceTypes { get; set; }
public SourceType[] ExcludeSourceTypes { get; set; }
public TrailerType[] TrailerTypes { get; set; }
public TrailerType[] ExcludeTrailerTypes { get; set; }
public DayOfWeek[] AirDays { get; set; }
public SeriesStatus[] SeriesStatuses { get; set; }
public string AlbumArtistStartsWithOrGreater { get; set; }
public string[] AlbumNames { get; set; }
public string[] ArtistNames { get; set; }
public InternalItemsQuery()
{
AlbumNames = new string[] { };
ArtistNames = new string[] { };
BlockUnratedItems = new UnratedItem[] { };
Tags = new string[] { };
OfficialRatings = new string[] { };
@ -139,8 +157,15 @@ namespace MediaBrowser.Controller.Entities
AncestorIds = new string[] { };
TopParentIds = new string[] { };
ExcludeTags = new string[] { };
LocationTypes = new LocationType[] { };
ExcludeLocationTypes = new LocationType[] { };
PresetViews = new string[] { };
SourceTypes = new SourceType[] { };
ExcludeSourceTypes = new SourceType[] { };
TrailerTypes = new TrailerType[] { };
ExcludeTrailerTypes = new TrailerType[] { };
AirDays = new DayOfWeek[] { };
SeriesStatuses = new SeriesStatus[] { };
}
public InternalItemsQuery(User user)

View File

@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
@ -67,24 +68,19 @@ namespace MediaBrowser.Controller.Entities.Movies
/// <value>The revenue.</value>
public double? Revenue { get; set; }
/// <summary>
/// Gets or sets the critic rating.
/// </summary>
/// <value>The critic rating.</value>
public float? CriticRating { get; set; }
/// <summary>
/// Gets or sets the critic rating summary.
/// </summary>
/// <value>The critic rating summary.</value>
public string CriticRatingSummary { get; set; }
/// <summary>
/// Gets or sets the name of the TMDB collection.
/// </summary>
/// <value>The name of the TMDB collection.</value>
public string TmdbCollectionName { get; set; }
[IgnoreDataMember]
public string CollectionName
{
get { return TmdbCollectionName; }
set { TmdbCollectionName = value; }
}
/// <summary>
/// Gets the trailer ids.
/// </summary>

View File

@ -0,0 +1,10 @@

namespace MediaBrowser.Controller.Entities
{
public enum SourceType
{
Library = 0,
Channel = 1,
LiveTV = 2
}
}

View File

@ -14,7 +14,6 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Class Trailer
/// </summary>
[Obsolete]
public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasLookupInfo<TrailerInfo>
{
public List<string> ProductionLocations { get; set; }
@ -25,14 +24,23 @@ namespace MediaBrowser.Controller.Entities
Taglines = new List<string>();
Keywords = new List<string>();
ProductionLocations = new List<string>();
TrailerTypes = new List<TrailerType>();
}
public List<TrailerType> TrailerTypes { get; set; }
public float? Metascore { get; set; }
public List<MediaUrl> RemoteTrailers { get; set; }
public List<string> Keywords { get; set; }
[IgnoreDataMember]
public bool IsLocalTrailer
{
get { return TrailerTypes.Contains(TrailerType.LocalTrailer); }
}
/// <summary>
/// Gets or sets the taglines.
/// </summary>
@ -51,32 +59,6 @@ namespace MediaBrowser.Controller.Entities
/// <value>The revenue.</value>
public double? Revenue { get; set; }
/// <summary>
/// Gets or sets the critic rating.
/// </summary>
/// <value>The critic rating.</value>
public float? CriticRating { get; set; }
/// <summary>
/// Gets or sets the critic rating summary.
/// </summary>
/// <value>The critic rating summary.</value>
public string CriticRatingSummary { get; set; }
/// <summary>
/// Gets a value indicating whether this instance is local trailer.
/// </summary>
/// <value><c>true</c> if this instance is local trailer; otherwise, <c>false</c>.</value>
[IgnoreDataMember]
public bool IsLocalTrailer
{
get
{
// Local trailers are not part of children
return GetParent() == null;
}
}
protected override string CreateUserDataKey()
{
var key = Movie.GetMovieUserDataKey(this);
@ -106,9 +88,50 @@ namespace MediaBrowser.Controller.Entities
{
var info = GetItemLookupInfo<TrailerInfo>();
info.IsLocalTrailer = IsLocalTrailer;
info.IsLocalTrailer = TrailerTypes.Contains(TrailerType.LocalTrailer);
if (!IsInMixedFolder)
{
info.Name = System.IO.Path.GetFileName(ContainingFolderPath);
}
return info;
}
public override bool BeforeMetadataRefresh()
{
var hasChanges = base.BeforeMetadataRefresh();
if (!ProductionYear.HasValue)
{
var info = LibraryManager.ParseName(Name);
var yearInName = info.Year;
if (yearInName.HasValue)
{
ProductionYear = yearInName;
hasChanges = true;
}
else
{
// Try to get the year from the folder name
if (!IsInMixedFolder)
{
info = LibraryManager.ParseName(System.IO.Path.GetFileName(ContainingFolderPath));
yearInName = info.Year;
if (yearInName.HasValue)
{
ProductionYear = yearInName;
hasChanges = true;
}
}
}
}
return hasChanges;
}
}
}

View File

@ -19,13 +19,9 @@ namespace MediaBrowser.Controller.Entities
{
public override async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
{
var user = query.User;
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
if (query.Recursive)
{
var items = query.User.RootFolder.GetRecursiveChildren(query.User, filter);
return PostFilterAndSort(items, query);
return QueryRecursive(query);
}
var result = await UserViewManager.GetUserViews(new UserViewQuery
@ -35,6 +31,9 @@ namespace MediaBrowser.Controller.Entities
}, CancellationToken.None).ConfigureAwait(false);
var user = query.User;
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
return PostFilterAndSort(result.Where(filter), query);
}

View File

@ -50,15 +50,15 @@ namespace MediaBrowser.Controller.Entities
{
var user = query.User;
if (query.IncludeItemTypes != null &&
query.IncludeItemTypes.Length == 1 &&
string.Equals(query.IncludeItemTypes[0], "Playlist", StringComparison.OrdinalIgnoreCase))
{
if (!string.Equals(viewType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
{
return await FindPlaylists(queryParent, user, query).ConfigureAwait(false);
}
}
//if (query.IncludeItemTypes != null &&
// query.IncludeItemTypes.Length == 1 &&
// string.Equals(query.IncludeItemTypes[0], "Playlist", StringComparison.OrdinalIgnoreCase))
//{
// if (!string.Equals(viewType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
// {
// return await FindPlaylists(queryParent, user, query).ConfigureAwait(false);
// }
//}
switch (viewType)
{
@ -766,7 +766,7 @@ namespace MediaBrowser.Controller.Entities
return items;
}
private static bool CollapseBoxSetItems(InternalItemsQuery query,
public static bool CollapseBoxSetItems(InternalItemsQuery query,
BaseItem queryParent,
User user)
{
@ -1199,6 +1199,11 @@ namespace MediaBrowser.Controller.Entities
return false;
}
if (query.ExcludeLocationTypes.Length > 0 && query.ExcludeLocationTypes.Contains(item.LocationType))
{
return false;
}
if (query.IsFolder.HasValue && query.IsFolder.Value != item.IsFolder)
{
return false;
@ -1689,6 +1694,127 @@ namespace MediaBrowser.Controller.Entities
}
}
if (query.MinPremiereDate.HasValue)
{
var val = query.MinPremiereDate.Value;
if (!(item.PremiereDate.HasValue && item.PremiereDate.Value >= val))
{
return false;
}
}
if (query.MaxPremiereDate.HasValue)
{
var val = query.MaxPremiereDate.Value;
if (!(item.PremiereDate.HasValue && item.PremiereDate.Value <= val))
{
return false;
}
}
if (query.ParentIndexNumber.HasValue)
{
var filterValue = query.ParentIndexNumber.Value;
if (item.ParentIndexNumber.HasValue && item.ParentIndexNumber.Value != filterValue)
{
return false;
}
}
if (query.AirDays.Length > 0)
{
var ok = new[] { item }.OfType<Series>().Any(p => p.AirDays != null && query.AirDays.Any(d => p.AirDays.Contains(d)));
if (!ok)
{
return false;
}
}
if (query.SeriesStatuses.Length > 0)
{
var ok = new[] { item }.OfType<Series>().Any(p => p.Status.HasValue && query.SeriesStatuses.Contains(p.Status.Value));
if (!ok)
{
return false;
}
}
if (query.AiredDuringSeason.HasValue)
{
var episode = item as Episode;
if (episode == null)
{
return false;
}
if (!Series.FilterEpisodesBySeason(new[] { episode }, query.AiredDuringSeason.Value, true).Any())
{
return false;
}
}
if (!string.IsNullOrEmpty(query.AlbumArtistStartsWithOrGreater))
{
var ok = new[] { item }.OfType<IHasAlbumArtist>()
.Any(p => string.Compare(query.AlbumArtistStartsWithOrGreater, p.AlbumArtists.FirstOrDefault(), StringComparison.CurrentCultureIgnoreCase) < 1);
if (!ok)
{
return false;
}
}
// Artists
if (query.ArtistNames.Length > 0)
{
var audio = item as IHasArtist;
if (!(audio != null && query.ArtistNames.Any(audio.HasAnyArtist)))
{
return false;
}
}
// Albums
if (query.AlbumNames.Length > 0)
{
var audio = item as Audio.Audio;
if (audio != null)
{
if (!query.AlbumNames.Any(a => string.Equals(a, audio.Album, StringComparison.OrdinalIgnoreCase)))
{
return false;
}
}
var album = item as MusicAlbum;
if (album != null)
{
if (!query.AlbumNames.Any(a => string.Equals(a, album.Name, StringComparison.OrdinalIgnoreCase)))
{
return false;
}
}
var musicVideo = item as MusicVideo;
if (musicVideo != null)
{
if (!query.AlbumNames.Any(a => string.Equals(a, musicVideo.Album, StringComparison.OrdinalIgnoreCase)))
{
return false;
}
}
return false;
}
return true;
}

View File

@ -6,13 +6,16 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.MediaInfo;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Mime;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
namespace MediaBrowser.Controller.Entities
{
@ -33,6 +36,7 @@ namespace MediaBrowser.Controller.Entities
public List<string> AdditionalParts { get; set; }
public List<string> LocalAlternateVersions { get; set; }
public List<LinkedChild> LinkedAlternateVersions { get; set; }
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
[IgnoreDataMember]
public bool IsThemeMedia
@ -78,6 +82,23 @@ namespace MediaBrowser.Controller.Entities
locationType != LocationType.Virtual;
}
[IgnoreDataMember]
public override LocationType LocationType
{
get
{
if (SourceType == SourceType.Channel)
{
if (string.IsNullOrEmpty(Path))
{
return LocationType.Remote;
}
}
return base.LocationType;
}
}
[IgnoreDataMember]
public override bool SupportsAddingToPlaylist
{
@ -130,6 +151,29 @@ namespace MediaBrowser.Controller.Entities
return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
}
protected override string CreateUserDataKey()
{
if (ExtraType.HasValue)
{
var key = this.GetProviderId(MetadataProviders.Imdb) ?? this.GetProviderId(MetadataProviders.Tmdb);
if (!string.IsNullOrWhiteSpace(key))
{
key = key + "-" + ExtraType.ToString().ToLower();
// Make sure different trailers have their own data.
if (RunTimeTicks.HasValue)
{
key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
}
return key;
}
}
return base.CreateUserDataKey();
}
/// <summary>
/// Gets the linked children.
/// </summary>
@ -441,6 +485,22 @@ namespace MediaBrowser.Controller.Entities
public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
{
if (SourceType == SourceType.Channel)
{
var sources = ChannelManager.GetStaticMediaSources(this, false, CancellationToken.None)
.Result.ToList();
if (sources.Count > 0)
{
return sources;
}
return new List<MediaSourceInfo>
{
GetVersionInfo(enablePathSubstitution, this, MediaSourceType.Placeholder)
};
}
var item = this;
var result = item.GetAlternateVersions()

View File

@ -79,5 +79,12 @@ namespace MediaBrowser.Controller
/// <param name="host">The host.</param>
/// <returns>System.String.</returns>
string GetLocalApiUrl(string host);
/// <summary>
/// Gets the local API URL.
/// </summary>
/// <param name="ipAddress">The ip address.</param>
/// <returns>System.String.</returns>
string GetLocalApiUrl(IPAddress ipAddress);
}
}

View File

@ -152,13 +152,6 @@ namespace MediaBrowser.Controller.Library
/// <returns>BaseItem.</returns>
BaseItem GetItemById(Guid id);
/// <summary>
/// Gets the items.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>QueryResult&lt;BaseItem&gt;.</returns>
QueryResult<BaseItem> GetItems(InternalItemsQuery query);
/// <summary>
/// Gets the memory item by identifier.
/// </summary>
@ -547,22 +540,28 @@ namespace MediaBrowser.Controller.Library
/// <returns>Task.</returns>
Task<ItemImageInfo> ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex);
/// <summary>
/// Gets the items.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>QueryResult&lt;BaseItem&gt;.</returns>
IEnumerable<BaseItem> GetItemList(InternalItemsQuery query);
/// <summary>
/// Gets the items.
/// </summary>
/// <param name="query">The query.</param>
/// <param name="parentIds">The parent ids.</param>
/// <returns>List&lt;BaseItem&gt;.</returns>
IEnumerable<BaseItem> GetItems(InternalItemsQuery query, IEnumerable<string> parentIds);
IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, IEnumerable<string> parentIds);
/// <summary>
/// Gets the items result.
/// </summary>
/// <param name="query">The query.</param>
/// <param name="parentIds">The parent ids.</param>
/// <returns>QueryResult&lt;BaseItem&gt;.</returns>
QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query, IEnumerable<string> parentIds);
QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query);
/// <summary>
/// Ignores the file.
/// </summary>

View File

@ -15,11 +15,14 @@ namespace MediaBrowser.Controller.Library
public BaseItem Item { get; set; }
public BaseItemInfo MediaInfo { get; set; }
public string MediaSourceId { get; set; }
public bool IsPaused { get; set; }
public string DeviceId { get; set; }
public string DeviceName { get; set; }
public string ClientName { get; set; }
public string PlaySessionId { get; set; }
public PlaybackProgressEventArgs()
{
Users = new List<User>();

View File

@ -1,10 +0,0 @@
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.LiveTv
{
public interface ILiveTvItem : IHasId
{
string ServiceName { get; set; }
string ExternalId { get; set; }
}
}

View File

@ -50,7 +50,7 @@ namespace MediaBrowser.Controller.LiveTv
/// </summary>
/// <param name="recording">The recording.</param>
/// <returns>Task.</returns>
Task DeleteRecording(ILiveTvRecording recording);
Task DeleteRecording(BaseItem recording);
/// <summary>
/// Cancels the timer.
@ -74,15 +74,6 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="listingProviders">The listing providers.</param>
void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders);
/// <summary>
/// Gets the channels.
/// </summary>
/// <param name="query">The query.</param>
/// <param name="options">The options.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>IEnumerable{Channel}.</returns>
Task<QueryResult<ChannelInfoDto>> GetChannels(LiveTvChannelQuery query, DtoOptions options, CancellationToken cancellationToken);
/// <summary>
/// Gets the recording.
/// </summary>
@ -92,15 +83,6 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="user">The user.</param>
/// <returns>Task{RecordingInfoDto}.</returns>
Task<BaseItemDto> GetRecording(string id, DtoOptions options, CancellationToken cancellationToken, User user = null);
/// <summary>
/// Gets the channel.
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="user">The user.</param>
/// <returns>Task{RecordingInfoDto}.</returns>
Task<ChannelInfoDto> GetChannel(string id, CancellationToken cancellationToken, User user = null);
/// <summary>
/// Gets the timer.
@ -156,7 +138,7 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="id">The identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>LiveTvRecording.</returns>
Task<ILiveTvRecording> GetInternalRecording(string id, CancellationToken cancellationToken);
Task<BaseItem> GetInternalRecording(string id, CancellationToken cancellationToken);
/// <summary>
/// Gets the recording stream.
@ -385,10 +367,22 @@ namespace MediaBrowser.Controller.LiveTv
/// <summary>
/// Adds the channel information.
/// </summary>
/// <param name="dto">The dto.</param>
/// <param name="channel">The channel.</param>
/// <param name="items">The items.</param>
/// <param name="options">The options.</param>
/// <param name="user">The user.</param>
void AddChannelInfo(BaseItemDto dto, LiveTvChannel channel, DtoOptions options, User user);
void AddChannelInfo(List<Tuple<BaseItemDto, LiveTvChannel>> items, DtoOptions options, User user);
/// <summary>
/// Called when [recording file deleted].
/// </summary>
/// <param name="recording">The recording.</param>
/// <returns>Task.</returns>
Task OnRecordingFileDeleted(BaseItem recording);
/// <summary>
/// Gets the sat ini mappings.
/// </summary>
/// <returns>List&lt;NameValuePair&gt;.</returns>
List<NameValuePair> GetSatIniMappings();
}
}

View File

@ -9,8 +9,10 @@ using System.Threading.Tasks;
namespace MediaBrowser.Controller.LiveTv
{
public interface ILiveTvRecording : IHasImages, IHasMediaSources, IHasUserData, ILiveTvItem, IHasStartDate, IHasProgramAttributes
public interface ILiveTvRecording : IHasImages, IHasMediaSources, IHasUserData, IHasStartDate, IHasProgramAttributes
{
string ServiceName { get; set; }
string ExternalId { get; set; }
string ChannelId { get; }
string MediaType { get; }

View File

@ -39,6 +39,13 @@ namespace MediaBrowser.Controller.LiveTv
[IgnoreDataMember]
public bool IsPremiere { get; set; }
[IgnoreDataMember]
public override SourceType SourceType
{
get { return SourceType.LiveTV; }
set { }
}
/// <summary>
/// Gets the user data key.
/// </summary>
@ -50,8 +57,6 @@ namespace MediaBrowser.Controller.LiveTv
return name + "-" + Name + (EpisodeTitle ?? string.Empty);
}
public string ServiceName { get; set; }
/// <summary>
/// Gets a value indicating whether this instance is owned item.
/// </summary>
@ -151,5 +156,10 @@ namespace MediaBrowser.Controller.LiveTv
{
return LiveTvManager.DeleteRecording(this);
}
public override Task OnFileDeleted()
{
return LiveTvManager.OnRecordingFileDeleted(this);
}
}
}

View File

@ -11,7 +11,7 @@ using System.Runtime.Serialization;
namespace MediaBrowser.Controller.LiveTv
{
public class LiveTvChannel : BaseItem, IHasMediaSources, ILiveTvItem
public class LiveTvChannel : BaseItem, IHasMediaSources
{
/// <summary>
/// Gets the user data key.
@ -40,6 +40,13 @@ namespace MediaBrowser.Controller.LiveTv
}
}
[IgnoreDataMember]
public override SourceType SourceType
{
get { return SourceType.LiveTV; }
set { }
}
/// <summary>
/// Gets or sets the number.
/// </summary>
@ -52,12 +59,6 @@ namespace MediaBrowser.Controller.LiveTv
/// <value>The type of the channel.</value>
public ChannelType ChannelType { get; set; }
/// <summary>
/// Gets or sets the name of the service.
/// </summary>
/// <value>The name of the service.</value>
public string ServiceName { get; set; }
[IgnoreDataMember]
public override LocationType LocationType
{

View File

@ -11,7 +11,7 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.LiveTv
{
public class LiveTvProgram : BaseItem, ILiveTvItem, IHasLookupInfo<LiveTvProgramLookupInfo>, IHasStartDate, IHasProgramAttributes
public class LiveTvProgram : BaseItem, IHasLookupInfo<LiveTvProgramLookupInfo>, IHasStartDate, IHasProgramAttributes
{
/// <summary>
/// Gets the user data key.
@ -39,12 +39,12 @@ namespace MediaBrowser.Controller.LiveTv
return base.CreateUserDataKey();
}
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
[IgnoreDataMember]
public string ServiceName { get; set; }
public override SourceType SourceType
{
get { return SourceType.LiveTV; }
set { }
}
/// <summary>
/// The start date of the program, in UTC.

View File

@ -39,6 +39,13 @@ namespace MediaBrowser.Controller.LiveTv
[IgnoreDataMember]
public bool IsPremiere { get; set; }
[IgnoreDataMember]
public override SourceType SourceType
{
get { return SourceType.LiveTV; }
set { }
}
/// <summary>
/// Gets the user data key.
/// </summary>
@ -65,8 +72,6 @@ namespace MediaBrowser.Controller.LiveTv
return base.CreateUserDataKey();
}
public string ServiceName { get; set; }
[IgnoreDataMember]
public override string MediaType
{
@ -166,5 +171,10 @@ namespace MediaBrowser.Controller.LiveTv
{
return LiveTvManager.DeleteRecording(this);
}
public override Task OnFileDeleted()
{
return LiveTvManager.OnRecordingFileDeleted(this);
}
}
}

View File

@ -1,4 +1,5 @@
using MediaBrowser.Controller.Entities;
using System.Runtime.Serialization;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Users;
@ -24,5 +25,12 @@ namespace MediaBrowser.Controller.LiveTv
return false;
}
}
[IgnoreDataMember]
public override SourceType SourceType
{
get { return SourceType.LiveTV; }
set { }
}
}
}

View File

@ -46,7 +46,7 @@
<ItemGroup>
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\CommonIO.1.0.0.8\lib\net45\CommonIO.dll</HintPath>
<HintPath>..\packages\CommonIO.1.0.0.9\lib\net45\CommonIO.dll</HintPath>
</Reference>
<Reference Include="Interfaces.IO">
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
@ -75,6 +75,7 @@
</Compile>
<Compile Include="Activity\IActivityManager.cs" />
<Compile Include="Activity\IActivityRepository.cs" />
<Compile Include="Channels\ChannelAudioItem.cs" />
<Compile Include="Channels\ChannelFolderItem.cs" />
<Compile Include="Channels\ChannelItemInfo.cs" />
<Compile Include="Channels\ChannelItemResult.cs" />
@ -82,11 +83,10 @@
<Compile Include="Channels\ChannelMediaInfo.cs" />
<Compile Include="Channels\ChannelParentalRating.cs" />
<Compile Include="Channels\ChannelSearchInfo.cs" />
<Compile Include="Channels\IChannel.cs" />
<Compile Include="Channels\IChannelManager.cs" />
<Compile Include="Channels\IChannelItem.cs" />
<Compile Include="Channels\ChannelAudioItem.cs" />
<Compile Include="Channels\ChannelVideoItem.cs" />
<Compile Include="Channels\IChannel.cs" />
<Compile Include="Channels\IChannelItem.cs" />
<Compile Include="Channels\IChannelManager.cs" />
<Compile Include="Channels\Channel.cs" />
<Compile Include="Channels\IChannelMediaItem.cs" />
<Compile Include="Channels\IHasCacheKey.cs" />
@ -128,6 +128,7 @@
<Compile Include="Drawing\ImageStream.cs" />
<Compile Include="Dto\DtoOptions.cs" />
<Compile Include="Dto\IDtoService.cs" />
<Compile Include="Entities\Audio\AudioPodcast.cs" />
<Compile Include="Entities\Audio\IHasAlbumArtist.cs" />
<Compile Include="Entities\Audio\IHasMusicGenres.cs" />
<Compile Include="Entities\Book.cs" />
@ -180,6 +181,7 @@
<Compile Include="Entities\Photo.cs" />
<Compile Include="Entities\PhotoAlbum.cs" />
<Compile Include="Entities\Share.cs" />
<Compile Include="Entities\SourceType.cs" />
<Compile Include="Entities\UserView.cs" />
<Compile Include="Entities\UserViewBuilder.cs" />
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
@ -202,7 +204,6 @@
<Compile Include="Library\UserDataSaveEventArgs.cs" />
<Compile Include="LiveTv\IHasRegistrationInfo.cs" />
<Compile Include="LiveTv\IListingsProvider.cs" />
<Compile Include="LiveTv\ILiveTvItem.cs" />
<Compile Include="LiveTv\ITunerHost.cs" />
<Compile Include="LiveTv\RecordingGroup.cs" />
<Compile Include="LiveTv\RecordingStatusChangedEventArgs.cs" />
@ -271,7 +272,6 @@
<Compile Include="Providers\ArtistInfo.cs" />
<Compile Include="Providers\BookInfo.cs" />
<Compile Include="Providers\BoxSetInfo.cs" />
<Compile Include="Providers\ChannelItemLookupInfo.cs" />
<Compile Include="Providers\DirectoryService.cs" />
<Compile Include="Providers\DynamicImageInfo.cs" />
<Compile Include="Providers\DynamicImageResponse.cs" />
@ -331,6 +331,7 @@
<Compile Include="Security\IEncryptionManager.cs" />
<Compile Include="Session\AuthenticationRequest.cs" />
<Compile Include="Social\ISharingManager.cs" />
<Compile Include="Sorting\SortHelper.cs" />
<Compile Include="Subtitles\ISubtitleManager.cs" />
<Compile Include="Subtitles\ISubtitleProvider.cs" />
<Compile Include="Providers\ItemIdentifier.cs" />

View File

@ -90,8 +90,7 @@ namespace MediaBrowser.Controller.MediaEncoding
Cabac = info.Cabac;
Context = info.Context;
if (info.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode ||
info.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed)
if (info.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External)
{
SubtitleStreamIndex = info.SubtitleStreamIndex;
}

View File

@ -42,13 +42,6 @@ namespace MediaBrowser.Controller.Persistence
/// <returns>Task{IEnumerable{ItemReview}}.</returns>
IEnumerable<ItemReview> GetCriticReviews(Guid itemId);
/// <summary>
/// Gets the children items.
/// </summary>
/// <param name="parentId">The parent identifier.</param>
/// <returns>IEnumerable&lt;BaseItem&gt;.</returns>
IEnumerable<BaseItem> GetChildrenItems(Guid parentId);
/// <summary>
/// Saves the critic reviews.
/// </summary>
@ -96,22 +89,6 @@ namespace MediaBrowser.Controller.Persistence
/// <returns>Task.</returns>
Task SaveChapters(Guid id, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken);
/// <summary>
/// Gets the children.
/// </summary>
/// <param name="parentId">The parent id.</param>
/// <returns>IEnumerable{ChildDefinition}.</returns>
IEnumerable<Guid> GetChildren(Guid parentId);
/// <summary>
/// Saves the children.
/// </summary>
/// <param name="parentId">The parent id.</param>
/// <param name="children">The children.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SaveChildren(Guid parentId, IEnumerable<Guid> children, CancellationToken cancellationToken);
/// <summary>
/// Gets the media streams.
/// </summary>

View File

@ -1,11 +0,0 @@
using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Providers
{
public class ChannelItemLookupInfo : ItemLookupInfo
{
public ChannelMediaContentType ContentType { get; set; }
public ExtraType ExtraType { get; set; }
}
}

View File

@ -1,3 +1,5 @@
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Providers
{
public class TrailerInfo : ItemLookupInfo

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Sorting
{
public static class SortHelper
{
private enum ChunkType { Alphanumeric, Numeric };
public static bool InChunk(char ch, char otherCh)
{
var type = ChunkType.Alphanumeric;
if (char.IsDigit(otherCh))
{
type = ChunkType.Numeric;
}
if ((type == ChunkType.Alphanumeric && char.IsDigit(ch))
|| (type == ChunkType.Numeric && !char.IsDigit(ch)))
{
return false;
}
return true;
}
}
}

View File

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

View File

@ -488,12 +488,12 @@ namespace MediaBrowser.Dlna.ContentDirectory
var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
{
Person = person.Name,
IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name, typeof(ChannelVideoItem).Name },
IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name, typeof(Trailer).Name },
SortBy = new[] { ItemSortBy.SortName },
Limit = limit,
StartIndex = startIndex
}, new string[] { });
});
var serverItems = itemsResult.Items.Select(i => new ServerItem
{

View File

@ -188,15 +188,15 @@ namespace MediaBrowser.Dlna.Didl
{
var subtitleAdded = AddSubtitleElement(container, subtitle);
if (subtitleAdded && _profile.EnableSingleSubtitleLimit)
{
break;
}
if (subtitleAdded && _profile.EnableSingleSubtitleLimit)
{
break;
}
}
}
}
private bool AddSubtitleElement(XmlElement container, SubtitleStreamInfo info)
private bool AddSubtitleElement(XmlElement container, SubtitleStreamInfo info)
{
var subtitleProfile = _profile.SubtitleProfiles
.FirstOrDefault(i => string.Equals(info.Format, i.Format, StringComparison.OrdinalIgnoreCase) && i.Method == SubtitleDeliveryMethod.External);
@ -213,13 +213,13 @@ namespace MediaBrowser.Dlna.Didl
// <sec:CaptionInfoEx sec:type="srt">http://192.168.1.3:9999/video.srt</sec:CaptionInfoEx>
// <sec:CaptionInfo sec:type="srt">http://192.168.1.3:9999/video.srt</sec:CaptionInfo>
//var res = container.OwnerDocument.CreateElement("SEC", "CaptionInfoEx");
var res = container.OwnerDocument.CreateElement("CaptionInfoEx", "sec");
//res.InnerText = info.Url;
res.InnerText = info.Url;
//// TODO: attribute needs SEC:
//res.SetAttribute("type", info.Format.ToLower());
//container.AppendChild(res);
res.SetAttribute("type", "sec", info.Format.ToLower());
container.AppendChild(res);
}
else if (string.Equals(subtitleMode, "smi", StringComparison.OrdinalIgnoreCase))
{
@ -243,7 +243,7 @@ namespace MediaBrowser.Dlna.Didl
container.AppendChild(res);
}
return true;
return true;
}
private void AddVideoResource(XmlElement container, IHasMediaSources video, string deviceId, Filter filter, string contentFeatures, StreamInfo streamInfo)

View File

@ -161,7 +161,7 @@ namespace MediaBrowser.Dlna.Main
var descriptorURI = "/dlna/" + udn + "/description.xml";
var uri = new Uri(_appHost.GetLocalApiUrl(addressString) + descriptorURI);
var uri = new Uri(_appHost.GetLocalApiUrl(address) + descriptorURI);
var services = new List<string>
{

View File

@ -42,7 +42,7 @@
<ItemGroup>
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\CommonIO.1.0.0.8\lib\net45\CommonIO.dll</HintPath>
<HintPath>..\packages\CommonIO.1.0.0.9\lib\net45\CommonIO.dll</HintPath>
</Reference>
<Reference Include="MoreLinq">
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>

View File

@ -171,7 +171,7 @@ namespace MediaBrowser.Dlna.PlayTo
private string GetServerAddress(IPAddress localIp)
{
return _appHost.GetLocalApiUrl(localIp.ToString());
return _appHost.GetLocalApiUrl(localIp);
}
public void Dispose()

View File

@ -31,10 +31,10 @@ namespace MediaBrowser.Dlna.Profiles
MaxIconWidth = 48;
MaxIconHeight = 48;
MaxStreamingBitrate = 12000000;
MaxStaticBitrate = 12000000;
MusicStreamingTranscodingBitrate = 128000;
MusicSyncBitrate = 128000;
MaxStreamingBitrate = 15000000;
MaxStaticBitrate = 15000000;
MusicStreamingTranscodingBitrate = 192000;
MusicSyncBitrate = 192000;
EnableAlbumArtInDidl = false;

View File

@ -99,6 +99,48 @@ namespace MediaBrowser.Dlna.Profiles
DidlMode = "",
},
new SubtitleProfile
{
Format = "ass",
Method = SubtitleDeliveryMethod.Embed,
DidlMode = "",
},
new SubtitleProfile
{
Format = "ssa",
Method = SubtitleDeliveryMethod.Embed,
DidlMode = "",
},
new SubtitleProfile
{
Format = "smi",
Method = SubtitleDeliveryMethod.Embed,
DidlMode = "",
},
new SubtitleProfile
{
Format = "dvdsub",
Method = SubtitleDeliveryMethod.Embed,
DidlMode = "",
},
new SubtitleProfile
{
Format = "pgs",
Method = SubtitleDeliveryMethod.Embed,
DidlMode = "",
},
new SubtitleProfile
{
Format = "pgssub",
Method = SubtitleDeliveryMethod.Embed,
DidlMode = "",
},
new SubtitleProfile
{
Format = "sub",

View File

@ -54,21 +54,21 @@ namespace MediaBrowser.Dlna.Profiles
new DirectPlayProfile
{
Container = "ts",
VideoCodec = "h264",
VideoCodec = "h264,hevc",
AudioCodec = "aac,ac3,mp3",
Type = DlnaProfileType.Video
},
new DirectPlayProfile
{
Container = "mkv",
VideoCodec = "h264",
VideoCodec = "h264,hevc",
AudioCodec = "aac,ac3,mp3",
Type = DlnaProfileType.Video
},
new DirectPlayProfile
{
Container = "mp4",
VideoCodec = "h264,mpeg4",
VideoCodec = "h264,mpeg4,hevc",
AudioCodec = "aac,ac3,mp3",
Type = DlnaProfileType.Video
},

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -24,10 +24,10 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
<MaxStreamingBitrate>12000000</MaxStreamingBitrate>
<MaxStaticBitrate>12000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
<MusicSyncBitrate>128000</MusicSyncBitrate>
<MaxStreamingBitrate>15000000</MaxStreamingBitrate>
<MaxStaticBitrate>15000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MusicSyncBitrate>192000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<ProtocolInfo>http-get:*:video/mp2t:*,http-get:*:video/MP1S:*,http-get:*:video/mpeg2:*,http-get:*:video/mp4:*,http-get:*:video/x-matroska:*,http-get:*:audio/mpeg:*,http-get:*:audio/mpeg3:*,http-get:*:audio/mp3:*,http-get:*:audio/mp4:*,http-get:*:audio/mp4a-latm:*,http-get:*:image/jpeg:*</ProtocolInfo>
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>

View File

@ -52,6 +52,12 @@
<SubtitleProfile format="srt" method="External" />
<SubtitleProfile format="sub" method="External" />
<SubtitleProfile format="srt" method="Embed" didlMode="" />
<SubtitleProfile format="ass" method="Embed" didlMode="" />
<SubtitleProfile format="ssa" method="Embed" didlMode="" />
<SubtitleProfile format="smi" method="Embed" didlMode="" />
<SubtitleProfile format="dvdsub" method="Embed" didlMode="" />
<SubtitleProfile format="pgs" method="Embed" didlMode="" />
<SubtitleProfile format="pgssub" method="Embed" didlMode="" />
<SubtitleProfile format="sub" method="Embed" didlMode="" />
</SubtitleProfiles>
</Profile>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -24,10 +24,10 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
<MaxStreamingBitrate>12000000</MaxStreamingBitrate>
<MaxStaticBitrate>12000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
<MusicSyncBitrate>128000</MusicSyncBitrate>
<MaxStreamingBitrate>15000000</MaxStreamingBitrate>
<MaxStaticBitrate>15000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MusicSyncBitrate>192000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<SonyAggregationFlags>10</SonyAggregationFlags>
<ProtocolInfo>http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000</ProtocolInfo>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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