mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
Merge branch 'master' of https://github.com/MediaBrowser/Emby
This commit is contained in:
commit
d9108f69f3
@ -33,7 +33,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<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>
|
||||||
<Reference Include="ImageMagickSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="ImageMagickSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.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="ImageMagickSharp" version="1.0.0.18" targetFramework="net45" />
|
||||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -63,6 +63,15 @@ namespace MediaBrowser.Api
|
|||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
|
|
||||||
Instance = this;
|
Instance = this;
|
||||||
|
_sessionManager.PlaybackProgress += _sessionManager_PlaybackProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _sessionManager_PlaybackProgress(object sender, PlaybackProgressEventArgs e)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(e.PlaySessionId))
|
||||||
|
{
|
||||||
|
PingTranscodingJob(e.PlaySessionId, e.IsPaused);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -300,26 +309,31 @@ namespace MediaBrowser.Api
|
|||||||
PingTimer(job, false);
|
PingTimer(job, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal void PingTranscodingJob(string playSessionId)
|
internal void PingTranscodingJob(string playSessionId, bool? isUserPaused)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(playSessionId))
|
if (string.IsNullOrEmpty(playSessionId))
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException("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)
|
lock (_activeTranscodingJobs)
|
||||||
{
|
{
|
||||||
// This is really only needed for HLS.
|
// This is really only needed for HLS.
|
||||||
// Progressive streams can stop on their own reliably
|
// 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)
|
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);
|
PingTimer(job, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -655,6 +669,7 @@ namespace MediaBrowser.Api
|
|||||||
public object ProcessLock = new object();
|
public object ProcessLock = new object();
|
||||||
|
|
||||||
public bool HasExited { get; set; }
|
public bool HasExited { get; set; }
|
||||||
|
public bool IsUserPaused { get; set; }
|
||||||
|
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
@ -196,9 +196,13 @@ namespace MediaBrowser.Api
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return libraryManager.RootFolder
|
var items = libraryManager.GetItemList(new InternalItemsQuery
|
||||||
.GetRecursiveChildren(i => i is IHasArtist)
|
{
|
||||||
.Cast<IHasArtist>()
|
IncludeItemTypes = new[] { typeof(Audio).Name, typeof(MusicVideo).Name, typeof(MusicAlbum).Name }
|
||||||
|
});
|
||||||
|
|
||||||
|
return items
|
||||||
|
.OfType<IHasArtist>()
|
||||||
.SelectMany(i => i.AllArtists)
|
.SelectMany(i => i.AllArtists)
|
||||||
.DistinctNames()
|
.DistinctNames()
|
||||||
.FirstOrDefault(i =>
|
.FirstOrDefault(i =>
|
||||||
@ -239,8 +243,12 @@ namespace MediaBrowser.Api
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return libraryManager.RootFolder
|
var items = libraryManager.GetItemList(new InternalItemsQuery
|
||||||
.GetRecursiveChildren(i => i is Game)
|
{
|
||||||
|
IncludeItemTypes = new[] { typeof(Game).Name }
|
||||||
|
});
|
||||||
|
|
||||||
|
return items
|
||||||
.SelectMany(i => i.Genres)
|
.SelectMany(i => i.Genres)
|
||||||
.DistinctNames()
|
.DistinctNames()
|
||||||
.FirstOrDefault(i =>
|
.FirstOrDefault(i =>
|
||||||
|
@ -108,7 +108,7 @@ namespace MediaBrowser.Api
|
|||||||
IncludeItemTypes = new[] { typeof(GameSystem).Name }
|
IncludeItemTypes = new[] { typeof(GameSystem).Name }
|
||||||
};
|
};
|
||||||
var parentIds = new string[] { } ;
|
var parentIds = new string[] { } ;
|
||||||
var gameSystems = _libraryManager.GetItems(query, parentIds)
|
var gameSystems = _libraryManager.GetItemList(query, parentIds)
|
||||||
.Cast<GameSystem>()
|
.Cast<GameSystem>()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ namespace MediaBrowser.Api
|
|||||||
IncludeItemTypes = new[] { typeof(Game).Name }
|
IncludeItemTypes = new[] { typeof(Game).Name }
|
||||||
};
|
};
|
||||||
var parentIds = new string[] { };
|
var parentIds = new string[] { };
|
||||||
var games = _libraryManager.GetItems(query, parentIds)
|
var games = _libraryManager.GetItemList(query, parentIds)
|
||||||
.Cast<Game>()
|
.Cast<Game>()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ namespace MediaBrowser.Api
|
|||||||
_userDataRepository,
|
_userDataRepository,
|
||||||
_dtoService,
|
_dtoService,
|
||||||
Logger,
|
Logger,
|
||||||
request, item => item is Game,
|
request, new[] { typeof(Game) },
|
||||||
SimilarItemsHelper.GetSimiliarityScore);
|
SimilarItemsHelper.GetSimiliarityScore);
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
|
@ -699,6 +699,7 @@ namespace MediaBrowser.Api.Images
|
|||||||
|
|
||||||
private ImageFormat[] GetClientSupportedFormats()
|
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 supportsWebP = (Request.AcceptTypes ?? new string[] { }).Contains("image/webp", StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var userAgent = Request.UserAgent ?? string.Empty;
|
var userAgent = Request.UserAgent ?? string.Empty;
|
||||||
|
@ -289,7 +289,6 @@ namespace MediaBrowser.Api.Library
|
|||||||
private readonly IActivityManager _activityManager;
|
private readonly IActivityManager _activityManager;
|
||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
private readonly ILiveTvManager _liveTv;
|
private readonly ILiveTvManager _liveTv;
|
||||||
private readonly IChannelManager _channelManager;
|
|
||||||
private readonly ITVSeriesManager _tvManager;
|
private readonly ITVSeriesManager _tvManager;
|
||||||
private readonly ILibraryMonitor _libraryMonitor;
|
private readonly ILibraryMonitor _libraryMonitor;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
@ -298,7 +297,7 @@ namespace MediaBrowser.Api.Library
|
|||||||
/// Initializes a new instance of the <see cref="LibraryService" /> class.
|
/// Initializes a new instance of the <see cref="LibraryService" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
|
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;
|
_itemRepo = itemRepo;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
@ -309,7 +308,6 @@ namespace MediaBrowser.Api.Library
|
|||||||
_activityManager = activityManager;
|
_activityManager = activityManager;
|
||||||
_localization = localization;
|
_localization = localization;
|
||||||
_liveTv = liveTv;
|
_liveTv = liveTv;
|
||||||
_channelManager = channelManager;
|
|
||||||
_tvManager = tvManager;
|
_tvManager = tvManager;
|
||||||
_libraryMonitor = libraryMonitor;
|
_libraryMonitor = libraryMonitor;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
@ -379,11 +377,10 @@ namespace MediaBrowser.Api.Library
|
|||||||
}
|
}
|
||||||
|
|
||||||
var program = item as IHasProgramAttributes;
|
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,
|
AuthorizationContext = AuthorizationContext,
|
||||||
Logger = Logger,
|
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)
|
return new TvShowsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _tvManager)
|
||||||
{
|
{
|
||||||
@ -447,13 +444,11 @@ namespace MediaBrowser.Api.Library
|
|||||||
|
|
||||||
public void Post(PostUpdatedSeries request)
|
public void Post(PostUpdatedSeries request)
|
||||||
{
|
{
|
||||||
var series = _libraryManager.GetItems(new InternalItemsQuery
|
var series = _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Series).Name }
|
IncludeItemTypes = new[] { typeof(Series).Name }
|
||||||
|
|
||||||
}).Items;
|
}).Where(i => string.Equals(request.TvdbId, i.GetProviderId(MetadataProviders.Tvdb), StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||||
|
|
||||||
series = series.Where(i => string.Equals(request.TvdbId, i.GetProviderId(MetadataProviders.Tvdb), StringComparison.OrdinalIgnoreCase)).ToArray();
|
|
||||||
|
|
||||||
if (series.Length > 0)
|
if (series.Length > 0)
|
||||||
{
|
{
|
||||||
@ -470,11 +465,11 @@ namespace MediaBrowser.Api.Library
|
|||||||
|
|
||||||
public void Post(PostUpdatedMovies request)
|
public void Post(PostUpdatedMovies request)
|
||||||
{
|
{
|
||||||
var movies = _libraryManager.GetItems(new InternalItemsQuery
|
var movies = _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Movie).Name }
|
IncludeItemTypes = new[] { typeof(Movie).Name }
|
||||||
|
|
||||||
}).Items;
|
}).ToArray();
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(request.ImdbId))
|
if (!string.IsNullOrWhiteSpace(request.ImdbId))
|
||||||
{
|
{
|
||||||
@ -664,87 +659,38 @@ namespace MediaBrowser.Api.Library
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetItemCounts request)
|
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
|
var counts = new ItemCounts
|
||||||
{
|
{
|
||||||
AlbumCount = filteredItems.Count(i => i is MusicAlbum),
|
AlbumCount = GetCount(typeof(MusicAlbum), user, request),
|
||||||
EpisodeCount = filteredItems.Count(i => i is Episode),
|
EpisodeCount = GetCount(typeof(Episode), user, request),
|
||||||
GameCount = filteredItems.Count(i => i is Game),
|
GameCount = GetCount(typeof(Game), user, request),
|
||||||
GameSystemCount = filteredItems.Count(i => i is GameSystem),
|
GameSystemCount = GetCount(typeof(GameSystem), user, request),
|
||||||
MovieCount = filteredItems.Count(i => i is Movie),
|
MovieCount = GetCount(typeof(Movie), user, request),
|
||||||
SeriesCount = filteredItems.Count(i => i is Series),
|
SeriesCount = GetCount(typeof(Series), user, request),
|
||||||
SongCount = filteredItems.Count(i => i is Audio),
|
SongCount = GetCount(typeof(Audio), user, request),
|
||||||
MusicVideoCount = filteredItems.Count(i => i is MusicVideo),
|
MusicVideoCount = GetCount(typeof(MusicVideo), user, request),
|
||||||
BoxSetCount = filteredItems.Count(i => i is BoxSet),
|
BoxSetCount = GetCount(typeof(BoxSet), user, request),
|
||||||
BookCount = filteredItems.Count(i => i is Book),
|
BookCount = GetCount(typeof(Book), user, request)
|
||||||
|
|
||||||
UniqueTypes = filteredItems.Select(i => i.GetClientTypeName()).Distinct().ToList()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(counts);
|
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))
|
return _libraryManager.GetItemsResult(query).TotalRecordCount;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -985,20 +931,15 @@ namespace MediaBrowser.Api.Library
|
|||||||
? new string[] { }
|
? new string[] { }
|
||||||
: request.IncludeItemTypes.Split(',');
|
: 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)
|
IncludeItemTypes = includeTypes,
|
||||||
{
|
Recursive = true
|
||||||
if (!includeTypes.Contains(i.GetType().Name, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
IEnumerable<BaseItem> items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, null, filter);
|
var items = _libraryManager.GetItemList(query);
|
||||||
|
|
||||||
var lookup = items
|
var lookup = items
|
||||||
.ToLookup(i => i.ProductionYear ?? -1)
|
.ToLookup(i => i.ProductionYear ?? -1)
|
||||||
|
@ -201,10 +201,10 @@ namespace MediaBrowser.Api.Library
|
|||||||
var rootFolderPath = _appPaths.DefaultUserViewsPath;
|
var rootFolderPath = _appPaths.DefaultUserViewsPath;
|
||||||
|
|
||||||
var virtualFolderPath = Path.Combine(rootFolderPath, name);
|
var virtualFolderPath = Path.Combine(rootFolderPath, name);
|
||||||
|
while (_fileSystem.DirectoryExists(virtualFolderPath))
|
||||||
if (_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)
|
if (request.Paths != null)
|
||||||
@ -236,7 +236,7 @@ namespace MediaBrowser.Api.Library
|
|||||||
{
|
{
|
||||||
foreach (var path in request.Paths)
|
foreach (var path in request.Paths)
|
||||||
{
|
{
|
||||||
LibraryHelpers.AddMediaPath(_fileSystem, request.Name, path, _appPaths);
|
LibraryHelpers.AddMediaPath(_fileSystem, name, path, _appPaths);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -478,19 +478,30 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
public string Feature { get; set; }
|
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
|
public class LiveTvService : BaseApiService
|
||||||
{
|
{
|
||||||
private readonly ILiveTvManager _liveTvManager;
|
private readonly ILiveTvManager _liveTvManager;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly IConfigurationManager _config;
|
private readonly IConfigurationManager _config;
|
||||||
private readonly IHttpClient _httpClient;
|
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;
|
_liveTvManager = liveTvManager;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_config = config;
|
_config = config;
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
|
_libraryManager = libraryManager;
|
||||||
|
_dtoService = dtoService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetLiveTvRegistrationInfo request)
|
public async Task<object> Get(GetLiveTvRegistrationInfo request)
|
||||||
@ -500,6 +511,11 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object Get(GetSatIniMappings request)
|
||||||
|
{
|
||||||
|
return ToOptimizedResult(_liveTvManager.GetSatIniMappings());
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetSchedulesDirectCountries request)
|
public async Task<object> Get(GetSchedulesDirectCountries request)
|
||||||
{
|
{
|
||||||
// https://json.schedulesdirect.org/20141201/available/countries
|
// https://json.schedulesdirect.org/20141201/available/countries
|
||||||
@ -581,7 +597,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
|
|
||||||
public async Task<object> Get(GetChannels request)
|
public async Task<object> Get(GetChannels request)
|
||||||
{
|
{
|
||||||
var result = await _liveTvManager.GetChannels(new LiveTvChannelQuery
|
var channelResult = await _liveTvManager.GetInternalChannels(new LiveTvChannelQuery
|
||||||
{
|
{
|
||||||
ChannelType = request.Type,
|
ChannelType = request.Type,
|
||||||
UserId = request.UserId,
|
UserId = request.UserId,
|
||||||
@ -593,16 +609,30 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
EnableFavoriteSorting = request.EnableFavoriteSorting,
|
EnableFavoriteSorting = request.EnableFavoriteSorting,
|
||||||
AddCurrentProgram = request.AddCurrentProgram
|
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);
|
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);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<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>
|
||||||
<Reference Include="MoreLinq">
|
<Reference Include="MoreLinq">
|
||||||
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||||
|
@ -91,22 +91,21 @@ namespace MediaBrowser.Api.Movies
|
|||||||
private readonly IItemRepository _itemRepo;
|
private readonly IItemRepository _itemRepo;
|
||||||
private readonly IDtoService _dtoService;
|
private readonly IDtoService _dtoService;
|
||||||
|
|
||||||
private readonly IChannelManager _channelManager;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="MoviesService"/> class.
|
/// Initializes a new instance of the <see cref="MoviesService" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userManager">The user manager.</param>
|
/// <param name="userManager">The user manager.</param>
|
||||||
/// <param name="userDataRepository">The user data repository.</param>
|
/// <param name="userDataRepository">The user data repository.</param>
|
||||||
/// <param name="libraryManager">The library manager.</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;
|
_userManager = userManager;
|
||||||
_userDataRepository = userDataRepository;
|
_userDataRepository = userDataRepository;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_itemRepo = itemRepo;
|
_itemRepo = itemRepo;
|
||||||
_dtoService = dtoService;
|
_dtoService = dtoService;
|
||||||
_channelManager = channelManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -138,8 +137,16 @@ namespace MediaBrowser.Api.Movies
|
|||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Movie).Name }
|
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 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);
|
movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies);
|
||||||
|
|
||||||
var listEligibleForCategories = new List<BaseItem>();
|
var listEligibleForCategories = new List<BaseItem>();
|
||||||
@ -150,19 +157,6 @@ namespace MediaBrowser.Api.Movies
|
|||||||
listEligibleForCategories.AddRange(list);
|
listEligibleForCategories.AddRange(list);
|
||||||
listEligibleForSuggestion.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
|
listEligibleForCategories = listEligibleForCategories
|
||||||
.DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
|
.DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
|
||||||
.DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), 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 }
|
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 parentIds = new string[] { };
|
||||||
var list = _libraryManager.GetItems(query, parentIds)
|
var list = _libraryManager.GetItemList(query, parentIds)
|
||||||
.Where(i =>
|
.Where(i =>
|
||||||
{
|
{
|
||||||
// Strip out secondary versions
|
// Strip out secondary versions
|
||||||
var v = i as Video;
|
var v = i as Video;
|
||||||
return v != null && !v.PrimaryVersionId.HasValue;
|
return v != null && !v.PrimaryVersionId.HasValue;
|
||||||
})
|
})
|
||||||
|
.DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
|
||||||
.ToList();
|
.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)
|
if (item is Video)
|
||||||
{
|
{
|
||||||
var imdbId = item.GetProviderId(MetadataProviders.Imdb);
|
var imdbId = item.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
@ -12,6 +12,9 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Collections;
|
||||||
|
using MediaBrowser.Controller.Localization;
|
||||||
|
using MediaBrowser.Model.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Movies
|
namespace MediaBrowser.Api.Movies
|
||||||
{
|
{
|
||||||
@ -41,87 +44,37 @@ namespace MediaBrowser.Api.Movies
|
|||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
private readonly IDtoService _dtoService;
|
private readonly IDtoService _dtoService;
|
||||||
private readonly IChannelManager _channelManager;
|
private readonly ICollectionManager _collectionManager;
|
||||||
|
private readonly ILocalizationManager _localizationManager;
|
||||||
|
private readonly IJsonSerializer _json;
|
||||||
|
|
||||||
/// <summary>
|
public TrailersService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IDtoService dtoService, ICollectionManager collectionManager, ILocalizationManager localizationManager, IJsonSerializer json)
|
||||||
/// 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)
|
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_userDataRepository = userDataRepository;
|
_userDataRepository = userDataRepository;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_dtoService = dtoService;
|
_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 json = _json.SerializeToString(request);
|
||||||
var result = await GetAllTrailers(user).ConfigureAwait(false);
|
var getItems = _json.DeserializeFromString<GetItems>(json);
|
||||||
|
|
||||||
IEnumerable<BaseItem> items = result.Items;
|
getItems.IncludeItemTypes = "Trailer";
|
||||||
|
|
||||||
// Apply filters
|
return new ItemsService(_userManager, _libraryManager, _userDataRepository, _localizationManager, _dtoService, _collectionManager)
|
||||||
// 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))
|
|
||||||
{
|
{
|
||||||
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);
|
}.Get(getItems);
|
||||||
|
|
||||||
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
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,10 +52,15 @@ namespace MediaBrowser.Api.Music
|
|||||||
|
|
||||||
public object Get(GetSimilarArtists request)
|
public object Get(GetSimilarArtists request)
|
||||||
{
|
{
|
||||||
var result = GetSimilarItemsResult(
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
request,
|
|
||||||
|
|
||||||
|
var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager,
|
||||||
|
_itemRepo,
|
||||||
|
_libraryManager,
|
||||||
|
_userDataRepository,
|
||||||
|
_dtoService,
|
||||||
|
Logger,
|
||||||
|
request, new[] { typeof(MusicArtist) },
|
||||||
SimilarItemsHelper.GetSimiliarityScore);
|
SimilarItemsHelper.GetSimiliarityScore);
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
@ -76,44 +81,11 @@ namespace MediaBrowser.Api.Music
|
|||||||
_userDataRepository,
|
_userDataRepository,
|
||||||
_dtoService,
|
_dtoService,
|
||||||
Logger,
|
Logger,
|
||||||
request, item => item is MusicAlbum,
|
request, new[] { typeof(MusicAlbum) },
|
||||||
GetAlbumSimilarityScore);
|
GetAlbumSimilarityScore);
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
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>
|
/// <summary>
|
||||||
/// Gets the album similarity score.
|
/// Gets the album similarity score.
|
||||||
|
@ -214,7 +214,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
args += " -map -0:a";
|
args += " -map -0:a";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.SubtitleStream == null)
|
if (state.SubtitleStream == null || state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Hls)
|
||||||
{
|
{
|
||||||
args += " -map -0:s";
|
args += " -map -0:s";
|
||||||
}
|
}
|
||||||
@ -477,7 +477,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
|
|
||||||
var pts = string.Empty;
|
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;
|
var seconds = TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds;
|
||||||
|
|
||||||
@ -575,7 +575,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
|
|
||||||
var output = string.Empty;
|
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);
|
var subParam = GetTextSubtitleParam(state);
|
||||||
|
|
||||||
@ -865,7 +865,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
{
|
{
|
||||||
var arg = string.Format("-i {0}", GetInputPathArgument(state));
|
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)
|
if (state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream)
|
||||||
{
|
{
|
||||||
@ -1482,6 +1482,17 @@ namespace MediaBrowser.Api.Playback
|
|||||||
videoRequest.CopyTimestamps = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,7 +529,12 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
"subs" :
|
"subs" :
|
||||||
null;
|
null;
|
||||||
|
|
||||||
AppendPlaylist(builder, playlistUrl, totalBitrate, subtitleGroup);
|
if (!string.IsNullOrWhiteSpace(subtitleGroup))
|
||||||
|
{
|
||||||
|
AddSubtitles(state, subtitleStreams, builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendPlaylist(builder, state, playlistUrl, totalBitrate, subtitleGroup);
|
||||||
|
|
||||||
if (EnableAdaptiveBitrateStreaming(state, isLiveStream))
|
if (EnableAdaptiveBitrateStreaming(state, isLiveStream))
|
||||||
{
|
{
|
||||||
@ -540,17 +545,12 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
|
|
||||||
var newBitrate = totalBitrate - variation;
|
var newBitrate = totalBitrate - variation;
|
||||||
var variantUrl = ReplaceBitrate(playlistUrl, requestedVideoBitrate, (requestedVideoBitrate - variation));
|
var variantUrl = ReplaceBitrate(playlistUrl, requestedVideoBitrate, (requestedVideoBitrate - variation));
|
||||||
AppendPlaylist(builder, variantUrl, newBitrate, subtitleGroup);
|
AppendPlaylist(builder, state, variantUrl, newBitrate, subtitleGroup);
|
||||||
|
|
||||||
variation *= 2;
|
variation *= 2;
|
||||||
newBitrate = totalBitrate - variation;
|
newBitrate = totalBitrate - variation;
|
||||||
variantUrl = ReplaceBitrate(playlistUrl, requestedVideoBitrate, (requestedVideoBitrate - variation));
|
variantUrl = ReplaceBitrate(playlistUrl, requestedVideoBitrate, (requestedVideoBitrate - variation));
|
||||||
AppendPlaylist(builder, variantUrl, newBitrate, subtitleGroup);
|
AppendPlaylist(builder, state, variantUrl, newBitrate, subtitleGroup);
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(subtitleGroup))
|
|
||||||
{
|
|
||||||
AddSubtitles(state, subtitleStreams, builder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
@ -566,11 +566,11 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
|
|
||||||
private void AddSubtitles(StreamState state, IEnumerable<MediaStream> subtitles, StringBuilder builder)
|
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)
|
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;
|
var name = stream.Language;
|
||||||
|
|
||||||
@ -579,10 +579,11 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(name)) name = stream.Codec ?? "Unknown";
|
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,
|
state.Request.MediaSourceId,
|
||||||
stream.Index.ToString(UsCulture),
|
stream.Index.ToString(UsCulture),
|
||||||
30.ToString(UsCulture));
|
30.ToString(UsCulture),
|
||||||
|
AuthorizationContext.GetAuthorizationInfo(Request).Token);
|
||||||
|
|
||||||
var line = string.Format(format,
|
var line = string.Format(format,
|
||||||
name,
|
name,
|
||||||
@ -635,9 +636,15 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
//return state.VideoRequest.VideoBitRate.HasValue;
|
//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))
|
if (!string.IsNullOrWhiteSpace(subtitleGroup))
|
||||||
{
|
{
|
||||||
@ -694,6 +701,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
|
|
||||||
builder.AppendLine("#EXTM3U");
|
builder.AppendLine("#EXTM3U");
|
||||||
|
builder.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
|
||||||
builder.AppendLine("#EXT-X-VERSION:3");
|
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-TARGETDURATION:" + Math.Ceiling((segmentLengths.Length > 0 ? segmentLengths.Max() : state.SegmentLength)).ToString(UsCulture));
|
||||||
builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
|
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})\"",
|
var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"",
|
||||||
state.SegmentLength.ToString(UsCulture));
|
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;
|
args += " " + GetVideoQualityParam(state, GetH264Encoder(state)) + keyFrameArg;
|
||||||
|
|
||||||
@ -846,7 +854,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
|
|
||||||
private bool EnableCopyTs(StreamState state)
|
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)
|
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
|
||||||
|
@ -9,6 +9,7 @@ using MediaBrowser.Model.Serialization;
|
|||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System;
|
using System;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Playback.Hls
|
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})\"",
|
var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"",
|
||||||
state.SegmentLength.ToString(UsCulture));
|
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;
|
args += " " + GetVideoQualityParam(state, GetH264Encoder(state)) + keyFrameArg;
|
||||||
|
|
||||||
|
@ -73,9 +73,13 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(UsCulture));
|
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";
|
const string vn = " -vn";
|
||||||
|
@ -61,8 +61,9 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
new ProgressiveFileCopier(_fileSystem, _job)
|
var task = new ProgressiveFileCopier(_fileSystem, _job, Logger).StreamFile(Path, responseStream);
|
||||||
.StreamFile(Path, responseStream);
|
|
||||||
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
catch (IOException)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
@ -91,19 +92,21 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
{
|
{
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly TranscodingJob _job;
|
private readonly TranscodingJob _job;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
// 256k
|
// 256k
|
||||||
private const int BufferSize = 262144;
|
private const int BufferSize = 262144;
|
||||||
|
|
||||||
private long _bytesWritten = 0;
|
private long _bytesWritten = 0;
|
||||||
|
|
||||||
public ProgressiveFileCopier(IFileSystem fileSystem, TranscodingJob job)
|
public ProgressiveFileCopier(IFileSystem fileSystem, TranscodingJob job, ILogger logger)
|
||||||
{
|
{
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_job = job;
|
_job = job;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StreamFile(string path, Stream outputStream)
|
public async Task StreamFile(string path, Stream outputStream)
|
||||||
{
|
{
|
||||||
var eofCount = 0;
|
var eofCount = 0;
|
||||||
long position = 0;
|
long position = 0;
|
||||||
@ -126,8 +129,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
{
|
{
|
||||||
eofCount++;
|
eofCount++;
|
||||||
}
|
}
|
||||||
var task = Task.Delay(100);
|
await Task.Delay(100).ConfigureAwait(false);
|
||||||
Task.WaitAll(task);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -145,6 +147,30 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
int count;
|
int count;
|
||||||
while ((count = source.Read(array, 0, array.Length)) != 0)
|
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);
|
destination.Write(array, 0, count);
|
||||||
|
|
||||||
_bytesWritten += count;
|
_bytesWritten += count;
|
||||||
|
@ -13,6 +13,7 @@ using System;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Playback.Progressive
|
namespace MediaBrowser.Api.Playback.Progressive
|
||||||
{
|
{
|
||||||
@ -161,7 +162,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
|
|
||||||
args += keyFrameArg;
|
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;
|
var hasCopyTs = false;
|
||||||
// Add resolution params, if specified
|
// Add resolution params, if specified
|
||||||
|
@ -213,8 +213,6 @@ namespace MediaBrowser.Api.Reports
|
|||||||
SortBy = request.GetOrderBy(),
|
SortBy = request.GetOrderBy(),
|
||||||
SortOrder = request.SortOrder ?? SortOrder.Ascending,
|
SortOrder = request.SortOrder ?? SortOrder.Ascending,
|
||||||
|
|
||||||
Filter = i => ApplyAdditionalFilters(request, i, user, _libraryManager),
|
|
||||||
|
|
||||||
IsFavorite = request.IsFavorite,
|
IsFavorite = request.IsFavorite,
|
||||||
Limit = request.Limit,
|
Limit = request.Limit,
|
||||||
StartIndex = request.StartIndex,
|
StartIndex = request.StartIndex,
|
||||||
@ -258,7 +256,10 @@ namespace MediaBrowser.Api.Reports
|
|||||||
MinPlayers = request.MinPlayers,
|
MinPlayers = request.MinPlayers,
|
||||||
MaxPlayers = request.MaxPlayers,
|
MaxPlayers = request.MaxPlayers,
|
||||||
MinCommunityRating = request.MinCommunityRating,
|
MinCommunityRating = request.MinCommunityRating,
|
||||||
MinCriticRating = request.MinCriticRating
|
MinCriticRating = request.MinCriticRating,
|
||||||
|
ParentIndexNumber = request.ParentIndexNumber,
|
||||||
|
AiredDuringSeason = request.AiredDuringSeason,
|
||||||
|
AlbumArtistStartsWithOrGreater = request.AlbumArtistStartsWithOrGreater
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(request.Ids))
|
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)
|
if (request.HasQueryLimit == false)
|
||||||
{
|
{
|
||||||
query.StartIndex = null;
|
query.StartIndex = null;
|
||||||
@ -311,278 +378,6 @@ namespace MediaBrowser.Api.Reports
|
|||||||
return query;
|
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>
|
/// <summary> Gets query result. </summary>
|
||||||
/// <param name="request"> The request. </param>
|
/// <param name="request"> The request. </param>
|
||||||
/// <returns> The query result. </returns>
|
/// <returns> The query result. </returns>
|
||||||
|
@ -54,21 +54,7 @@ namespace MediaBrowser.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class SimilarItemsHelper
|
public static class SimilarItemsHelper
|
||||||
{
|
{
|
||||||
/// <summary>
|
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)
|
||||||
/// 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)
|
|
||||||
{
|
{
|
||||||
var user = !string.IsNullOrWhiteSpace(request.UserId) ? userManager.GetUserById(request.UserId) : null;
|
var user = !string.IsNullOrWhiteSpace(request.UserId) ? userManager.GetUserById(request.UserId) : null;
|
||||||
|
|
||||||
@ -76,11 +62,13 @@ namespace MediaBrowser.Api
|
|||||||
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
||||||
libraryManager.RootFolder) : libraryManager.GetItemById(request.Id);
|
libraryManager.RootFolder) : libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
Func<BaseItem, bool> filter = i => i.Id != item.Id && includeInSearch(i);
|
var query = new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
IncludeItemTypes = includeTypes.Select(i => i.Name).ToArray(),
|
||||||
|
Recursive = true
|
||||||
|
};
|
||||||
|
|
||||||
var inputItems = user == null
|
var inputItems = libraryManager.GetItemList(query);
|
||||||
? libraryManager.RootFolder.GetRecursiveChildren(filter)
|
|
||||||
: user.RootFolder.GetRecursiveChildren(user, filter);
|
|
||||||
|
|
||||||
var items = GetSimilaritems(item, libraryManager, inputItems, getSimilarityScore)
|
var items = GetSimilaritems(item, libraryManager, inputItems, getSimilarityScore)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
@ -68,6 +68,8 @@ namespace MediaBrowser.Api
|
|||||||
_config.Configuration.EnableLocalizedGuids = true;
|
_config.Configuration.EnableLocalizedGuids = true;
|
||||||
_config.Configuration.EnableCustomPathSubFolders = true;
|
_config.Configuration.EnableCustomPathSubFolders = true;
|
||||||
_config.Configuration.EnableDateLastRefresh = true;
|
_config.Configuration.EnableDateLastRefresh = true;
|
||||||
|
_config.Configuration.EnableStandaloneMusicKeys = true;
|
||||||
|
_config.Configuration.EnableCaseSensitiveItemIds = true;
|
||||||
_config.SaveConfiguration();
|
_config.SaveConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,6 +164,8 @@ namespace MediaBrowser.Api.Subtitles
|
|||||||
long positionTicks = 0;
|
long positionTicks = 0;
|
||||||
var segmentLengthTicks = TimeSpan.FromSeconds(request.SegmentLength).Ticks;
|
var segmentLengthTicks = TimeSpan.FromSeconds(request.SegmentLength).Ticks;
|
||||||
|
|
||||||
|
var accessToken = AuthorizationContext.GetAuthorizationInfo(Request).Token;
|
||||||
|
|
||||||
while (positionTicks < runtime)
|
while (positionTicks < runtime)
|
||||||
{
|
{
|
||||||
var remaining = runtime - positionTicks;
|
var remaining = runtime - positionTicks;
|
||||||
@ -173,9 +175,10 @@ namespace MediaBrowser.Api.Subtitles
|
|||||||
|
|
||||||
var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks);
|
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),
|
positionTicks.ToString(CultureInfo.InvariantCulture),
|
||||||
endPositionTicks.ToString(CultureInfo.InvariantCulture));
|
endPositionTicks.ToString(CultureInfo.InvariantCulture),
|
||||||
|
accessToken);
|
||||||
|
|
||||||
builder.AppendLine(url);
|
builder.AppendLine(url);
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ namespace MediaBrowser.Api
|
|||||||
_userDataManager,
|
_userDataManager,
|
||||||
_dtoService,
|
_dtoService,
|
||||||
Logger,
|
Logger,
|
||||||
request, item => item is Series,
|
request, new[] { typeof(Series) },
|
||||||
SimilarItemsHelper.GetSimiliarityScore);
|
SimilarItemsHelper.GetSimiliarityScore);
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedSerializedResultUsingCache(result);
|
||||||
@ -273,11 +273,11 @@ namespace MediaBrowser.Api
|
|||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
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 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 },
|
IncludeItemTypes = new[] { typeof(Episode).Name },
|
||||||
SortBy = new[] { "PremiereDate", "AirTime", "SortName" },
|
SortBy = new[] { "PremiereDate", "AirTime", "SortName" },
|
||||||
@ -286,15 +286,15 @@ namespace MediaBrowser.Api
|
|||||||
StartIndex = request.StartIndex,
|
StartIndex = request.StartIndex,
|
||||||
Limit = request.Limit
|
Limit = request.Limit
|
||||||
|
|
||||||
}, parentIds);
|
}, parentIds).ToList();
|
||||||
|
|
||||||
var options = GetDtoOptions(request);
|
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
|
var result = new ItemsResult
|
||||||
{
|
{
|
||||||
TotalRecordCount = itemsResult.TotalRecordCount,
|
TotalRecordCount = itemsResult.Count,
|
||||||
Items = returnItems
|
Items = returnItems
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,17 +85,16 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// <returns>Task{ItemsResult}.</returns>
|
/// <returns>Task{ItemsResult}.</returns>
|
||||||
private async Task<ItemsResult> GetItems(GetItems request)
|
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 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);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
return new ItemsResult
|
return new ItemsResult
|
||||||
{
|
{
|
||||||
TotalRecordCount = result.Item1.TotalRecordCount,
|
TotalRecordCount = result.TotalRecordCount,
|
||||||
Items = _dtoService.GetBaseItemDtos(result.Item1.Items, dtoOptions, user).ToArray()
|
Items = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user).ToArray()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,17 +103,16 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
/// <param name="parentItem">The parent item.</param>
|
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
/// <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) ?
|
var item = string.IsNullOrEmpty(request.ParentId) ?
|
||||||
user == null ? _libraryManager.RootFolder : user.RootFolder :
|
user == null ? _libraryManager.RootFolder : user.RootFolder :
|
||||||
parentItem;
|
_libraryManager.GetItemById(request.ParentId);
|
||||||
|
|
||||||
if (string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase))
|
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))
|
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();
|
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)
|
if (request.Recursive)
|
||||||
{
|
{
|
||||||
var result = await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
|
var result = await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
|
||||||
|
|
||||||
return new Tuple<QueryResult<BaseItem>, bool>(result, true);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
var result = await ((Folder)item).GetItems(GetItemsQuery(request, null)).ConfigureAwait(false);
|
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;
|
var userRoot = item as UserRootFolder;
|
||||||
@ -160,26 +158,24 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
{
|
{
|
||||||
var result = await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
|
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);
|
IEnumerable<BaseItem> items = ((Folder)item).GetChildren(user, true);
|
||||||
|
|
||||||
var itemsArray = items.ToArray();
|
var itemsArray = items.ToArray();
|
||||||
|
|
||||||
return new Tuple<QueryResult<BaseItem>, bool>(new QueryResult<BaseItem>
|
return new QueryResult<BaseItem>
|
||||||
{
|
{
|
||||||
Items = itemsArray,
|
Items = itemsArray,
|
||||||
TotalRecordCount = itemsArray.Length
|
TotalRecordCount = itemsArray.Length
|
||||||
|
};
|
||||||
}, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private InternalItemsQuery GetItemsQuery(GetItems request, User user)
|
private InternalItemsQuery GetItemsQuery(GetItems request, User user)
|
||||||
{
|
{
|
||||||
var query = new InternalItemsQuery
|
var query = new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
User = user,
|
|
||||||
IsPlayed = request.IsPlayed,
|
IsPlayed = request.IsPlayed,
|
||||||
MediaTypes = request.GetMediaTypes(),
|
MediaTypes = request.GetMediaTypes(),
|
||||||
IncludeItemTypes = request.GetIncludeItemTypes(),
|
IncludeItemTypes = request.GetIncludeItemTypes(),
|
||||||
@ -188,8 +184,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
SortBy = request.GetOrderBy(),
|
SortBy = request.GetOrderBy(),
|
||||||
SortOrder = request.SortOrder ?? SortOrder.Ascending,
|
SortOrder = request.SortOrder ?? SortOrder.Ascending,
|
||||||
|
|
||||||
Filter = i => ApplyAdditionalFilters(request, i, user, _libraryManager),
|
|
||||||
|
|
||||||
IsFavorite = request.IsFavorite,
|
IsFavorite = request.IsFavorite,
|
||||||
Limit = request.Limit,
|
Limit = request.Limit,
|
||||||
StartIndex = request.StartIndex,
|
StartIndex = request.StartIndex,
|
||||||
@ -234,7 +228,11 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
MinPlayers = request.MinPlayers,
|
MinPlayers = request.MinPlayers,
|
||||||
MaxPlayers = request.MaxPlayers,
|
MaxPlayers = request.MaxPlayers,
|
||||||
MinCommunityRating = request.MinCommunityRating,
|
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))
|
if (!string.IsNullOrWhiteSpace(request.Ids))
|
||||||
@ -278,331 +276,73 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
if (!string.IsNullOrEmpty(request.MinPremiereDate))
|
||||||
}
|
|
||||||
|
|
||||||
/// <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)
|
|
||||||
{
|
{
|
||||||
case ItemFilter.IsFavoriteOrLikes:
|
query.MinPremiereDate = DateTime.Parse(request.MinPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return items;
|
if (!string.IsNullOrEmpty(request.MaxPremiereDate))
|
||||||
}
|
|
||||||
|
|
||||||
private bool ApplyAdditionalFilters(GetItems request, BaseItem i, User user, ILibraryManager libraryManager)
|
|
||||||
{
|
|
||||||
// Artists
|
|
||||||
if (!string.IsNullOrEmpty(request.ArtistIds))
|
|
||||||
{
|
{
|
||||||
var artistIds = request.ArtistIds.Split(new[] { '|', ',' });
|
query.MaxPremiereDate = DateTime.Parse(request.MaxPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter by Series Status
|
// Filter by Series Status
|
||||||
if (!string.IsNullOrEmpty(request.SeriesStatus))
|
if (!string.IsNullOrEmpty(request.SeriesStatus))
|
||||||
{
|
{
|
||||||
var vals = request.SeriesStatus.Split(',');
|
query.SeriesStatuses = request.SeriesStatus.Split(',').Select(d => (SeriesStatus)Enum.Parse(typeof(SeriesStatus), d, true)).ToArray();
|
||||||
|
|
||||||
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
|
// Filter by Series AirDays
|
||||||
if (!string.IsNullOrEmpty(request.AirDays))
|
if (!string.IsNullOrEmpty(request.AirDays))
|
||||||
{
|
{
|
||||||
var days = request.AirDays.Split(',').Select(d => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), d, true));
|
query.AirDays = request.AirDays.Split(',').Select(d => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), d, true)).ToArray();
|
||||||
|
|
||||||
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)
|
// ExcludeLocationTypes
|
||||||
|
if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
|
||||||
{
|
{
|
||||||
var filterValue = request.ParentIndexNumber.Value;
|
query.ExcludeLocationTypes = request.ExcludeLocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
|
||||||
|
|
||||||
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)
|
if (!string.IsNullOrEmpty(request.LocationTypes))
|
||||||
{
|
{
|
||||||
var episode = i as Episode;
|
query.LocationTypes = request.LocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
|
||||||
|
|
||||||
if (episode == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Series.FilterEpisodesBySeason(new[] { episode }, request.AiredDuringSeason.Value, true).Any())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.MinPremiereDate))
|
// Min official rating
|
||||||
|
if (!string.IsNullOrEmpty(request.MinOfficialRating))
|
||||||
{
|
{
|
||||||
var date = DateTime.Parse(request.MinPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
|
query.MinParentalRating = _localization.GetRatingLevel(request.MinOfficialRating);
|
||||||
|
|
||||||
if (!(i.PremiereDate.HasValue && i.PremiereDate.Value >= date))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.MaxPremiereDate))
|
// Max official rating
|
||||||
|
if (!string.IsNullOrEmpty(request.MaxOfficialRating))
|
||||||
{
|
{
|
||||||
var date = DateTime.Parse(request.MaxPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
|
query.MaxParentalRating = _localization.GetRatingLevel(request.MinOfficialRating);
|
||||||
|
|
||||||
if (!(i.PremiereDate.HasValue && i.PremiereDate.Value <= date))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,11 +335,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
public void Post(ReportPlaybackProgress request)
|
public void Post(ReportPlaybackProgress request)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(request.PlaySessionId))
|
|
||||||
{
|
|
||||||
ApiEntryPoint.Instance.PingTranscodingJob(request.PlaySessionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
request.SessionId = GetSession().Result.Id;
|
request.SessionId = GetSession().Result.Id;
|
||||||
|
|
||||||
var task = _sessionManager.OnPlaybackProgress(request);
|
var task = _sessionManager.OnPlaybackProgress(request);
|
||||||
@ -349,7 +344,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
public void Post(PingPlaybackSession request)
|
public void Post(PingPlaybackSession request)
|
||||||
{
|
{
|
||||||
ApiEntryPoint.Instance.PingTranscodingJob(request.PlaySessionId);
|
ApiEntryPoint.Instance.PingTranscodingJob(request.PlaySessionId, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.8" targetFramework="net45" />
|
<package id="CommonIO" version="1.0.0.9" targetFramework="net45" />
|
||||||
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
||||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -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)
|
private WebRequest GetRequest(HttpRequestOptions options, string method, bool enableHttpCompression)
|
||||||
{
|
{
|
||||||
var request = CreateWebRequest(options.Url);
|
var request = CreateWebRequest(options.Url);
|
||||||
@ -133,6 +150,8 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||||||
|
|
||||||
if (httpWebRequest != null)
|
if (httpWebRequest != null)
|
||||||
{
|
{
|
||||||
|
AddIpv4Option(httpWebRequest, options);
|
||||||
|
|
||||||
AddRequestHeaders(httpWebRequest, options);
|
AddRequestHeaders(httpWebRequest, options);
|
||||||
|
|
||||||
httpWebRequest.AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None;
|
httpWebRequest.AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None;
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<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>
|
||||||
<Reference Include="MoreLinq">
|
<Reference Include="MoreLinq">
|
||||||
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||||
|
@ -170,6 +170,17 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
|
|||||||
QueueScheduledTask<T>(new TaskExecutionOptions());
|
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>()
|
public void Execute<T>()
|
||||||
where T : IScheduledTask
|
where T : IScheduledTask
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.8" targetFramework="net45" />
|
<package id="CommonIO" version="1.0.0.9" targetFramework="net45" />
|
||||||
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
||||||
<package id="NLog" version="4.2.3" targetFramework="net45" />
|
<package id="NLog" version="4.2.3" targetFramework="net45" />
|
||||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||||
|
@ -96,6 +96,7 @@ namespace MediaBrowser.Common.Net
|
|||||||
public TimeSpan CacheLength { get; set; }
|
public TimeSpan CacheLength { get; set; }
|
||||||
|
|
||||||
public int TimeoutMs { get; set; }
|
public int TimeoutMs { get; set; }
|
||||||
|
public bool PreferIpv4 { get; set; }
|
||||||
|
|
||||||
private string GetHeaderValue(string name)
|
private string GetHeaderValue(string name)
|
||||||
{
|
{
|
||||||
|
@ -50,6 +50,9 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
void QueueScheduledTask<T>()
|
void QueueScheduledTask<T>()
|
||||||
where T : IScheduledTask;
|
where T : IScheduledTask;
|
||||||
|
|
||||||
|
void QueueIfNotRunning<T>()
|
||||||
|
where T : IScheduledTask;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queues the scheduled task.
|
/// Queues the scheduled task.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -3,6 +3,7 @@ using MediaBrowser.Model.Channels;
|
|||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -30,6 +31,13 @@ namespace MediaBrowser.Controller.Channels
|
|||||||
return base.IsVisible(user);
|
return base.IsVisible(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override SourceType SourceType
|
||||||
|
{
|
||||||
|
get { return SourceType.Channel; }
|
||||||
|
set { }
|
||||||
|
}
|
||||||
|
|
||||||
public override async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
|
public override async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -75,5 +83,12 @@ namespace MediaBrowser.Controller.Channels
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static bool IsChannelVisible(BaseItem channelItem, User user)
|
||||||
|
{
|
||||||
|
var channel = ChannelManager.GetChannel(channelItem.ChannelId);
|
||||||
|
|
||||||
|
return channel.IsVisible(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ using System.Threading;
|
|||||||
|
|
||||||
namespace MediaBrowser.Controller.Channels
|
namespace MediaBrowser.Controller.Channels
|
||||||
{
|
{
|
||||||
public class ChannelAudioItem : Audio, IChannelMediaItem
|
public class ChannelAudioItem : Audio
|
||||||
{
|
{
|
||||||
public ChannelMediaContentType ContentType { get; set; }
|
public ChannelMediaContentType ContentType { get; set; }
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ using MediaBrowser.Model.Entities;
|
|||||||
|
|
||||||
namespace MediaBrowser.Controller.Channels
|
namespace MediaBrowser.Controller.Channels
|
||||||
{
|
{
|
||||||
public class ChannelFolderItem : Folder, IChannelItem
|
public class ChannelFolderItem : Folder
|
||||||
{
|
{
|
||||||
public ChannelFolderType ChannelFolderType { get; set; }
|
public ChannelFolderType ChannelFolderType { get; set; }
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ using System.Threading;
|
|||||||
|
|
||||||
namespace MediaBrowser.Controller.Channels
|
namespace MediaBrowser.Controller.Channels
|
||||||
{
|
{
|
||||||
public class ChannelVideoItem : Video, IChannelMediaItem, IHasLookupInfo<ChannelItemLookupInfo>
|
public class ChannelVideoItem : Video
|
||||||
{
|
{
|
||||||
public ChannelMediaContentType ContentType { get; set; }
|
public ChannelMediaContentType ContentType { get; set; }
|
||||||
|
|
||||||
@ -103,20 +103,6 @@ namespace MediaBrowser.Controller.Channels
|
|||||||
return list;
|
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)
|
protected override string GetInternalMetadataPath(string basePath)
|
||||||
{
|
{
|
||||||
return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
|
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);
|
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);
|
var channel = ChannelManager.GetChannel(item.ChannelId);
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ namespace MediaBrowser.Controller.Channels
|
|||||||
/// <param name="includeCachedVersions">if set to <c>true</c> [include cached versions].</param>
|
/// <param name="includeCachedVersions">if set to <c>true</c> [include cached versions].</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns>
|
/// <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>
|
/// <summary>
|
||||||
/// Gets the channel folder.
|
/// Gets the channel folder.
|
||||||
@ -141,6 +141,6 @@ namespace MediaBrowser.Controller.Channels
|
|||||||
/// <param name="progress">The progress.</param>
|
/// <param name="progress">The progress.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task DownloadChannelItem(IChannelMediaItem item, string destinationPath, IProgress<double> progress, CancellationToken cancellationToken);
|
Task DownloadChannelItem(BaseItem item, string destinationPath, IProgress<double> progress, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ namespace MediaBrowser.Controller.Dto
|
|||||||
public List<ImageType> ImageTypes { get; set; }
|
public List<ImageType> ImageTypes { get; set; }
|
||||||
public int ImageTypeLimit { get; set; }
|
public int ImageTypeLimit { get; set; }
|
||||||
public bool EnableImages { get; set; }
|
public bool EnableImages { get; set; }
|
||||||
|
public bool AddProgramRecordingInfo { get; set; }
|
||||||
public string DeviceId { get; set; }
|
public string DeviceId { get; set; }
|
||||||
|
|
||||||
public DtoOptions()
|
public DtoOptions()
|
||||||
|
@ -8,6 +8,8 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using System.Threading;
|
||||||
|
using MediaBrowser.Controller.Channels;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.Audio
|
namespace MediaBrowser.Controller.Entities.Audio
|
||||||
{
|
{
|
||||||
@ -24,6 +26,8 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
IThemeMedia,
|
IThemeMedia,
|
||||||
IArchivable
|
IArchivable
|
||||||
{
|
{
|
||||||
|
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
|
||||||
|
|
||||||
public long? Size { get; set; }
|
public long? Size { get; set; }
|
||||||
public string Container { get; set; }
|
public string Container { get; set; }
|
||||||
public int? TotalBitrate { get; set; }
|
public int? TotalBitrate { get; set; }
|
||||||
@ -153,6 +157,31 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected override string CreateUserDataKey()
|
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;
|
var parent = AlbumEntity;
|
||||||
|
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
@ -173,7 +202,11 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
|
|
||||||
public override UnratedItem GetBlockUnratedType()
|
public override UnratedItem GetBlockUnratedType()
|
||||||
{
|
{
|
||||||
return UnratedItem.Music;
|
if (SourceType == SourceType.Library)
|
||||||
|
{
|
||||||
|
return UnratedItem.Music;
|
||||||
|
}
|
||||||
|
return base.GetBlockUnratedType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SongInfo GetLookupInfo()
|
public SongInfo GetLookupInfo()
|
||||||
@ -189,6 +222,32 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
|
|
||||||
public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
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>
|
var result = new List<MediaSourceInfo>
|
||||||
{
|
{
|
||||||
GetVersionInfo(this, enablePathSubstitution)
|
GetVersionInfo(this, enablePathSubstitution)
|
||||||
|
12
MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs
Normal file
12
MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs
Normal 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
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -34,7 +34,17 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
{
|
{
|
||||||
get
|
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;
|
return "MusicAlbum-Musicbrainz-" + id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
|
||||||
|
{
|
||||||
|
var albumArtist = AlbumArtist;
|
||||||
|
if (!string.IsNullOrWhiteSpace(albumArtist))
|
||||||
|
{
|
||||||
|
return albumArtist + "-" + Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return base.CreateUserDataKey();
|
return base.CreateUserDataKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +144,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
|
|
||||||
id.AlbumArtists = AlbumArtists;
|
id.AlbumArtists = AlbumArtists;
|
||||||
|
|
||||||
var artist = GetParents().OfType<MusicArtist>().FirstOrDefault();
|
var artist = MusicArtist;
|
||||||
|
|
||||||
if (artist != null)
|
if (artist != null)
|
||||||
{
|
{
|
||||||
|
@ -20,9 +20,11 @@ using System.Globalization;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Controller.Sorting;
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
@ -57,7 +59,9 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public static string ThemeSongFilename = "theme";
|
public static string ThemeSongFilename = "theme";
|
||||||
public static string ThemeVideosFolderName = "backdrops";
|
public static string ThemeVideosFolderName = "backdrops";
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
public string PreferredMetadataCountryCode { get; set; }
|
public string PreferredMetadataCountryCode { get; set; }
|
||||||
|
[IgnoreDataMember]
|
||||||
public string PreferredMetadataLanguage { get; set; }
|
public string PreferredMetadataLanguage { get; set; }
|
||||||
|
|
||||||
public List<ItemImageInfo> ImageInfos { 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.
|
/// Gets a value indicating whether this instance is in mixed folder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value><c>true</c> if this instance is in mixed folder; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if this instance is in mixed folder; otherwise, <c>false</c>.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public bool IsInMixedFolder { get; set; }
|
public bool IsInMixedFolder { get; set; }
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
@ -166,6 +171,9 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsOffline { get; set; }
|
public bool IsOffline { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public virtual SourceType SourceType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the folder containing the item.
|
/// Returns the folder containing the item.
|
||||||
/// If the item is a folder, it returns the folder itself
|
/// If the item is a folder, it returns the folder itself
|
||||||
@ -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>
|
/// <summary>
|
||||||
/// If this content came from an external service, the id of the content on that service
|
/// If this content came from an external service, the id of the content on that service
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -252,6 +267,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
if (SourceType == SourceType.Channel)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var locationType = LocationType;
|
var locationType = LocationType;
|
||||||
|
|
||||||
return locationType != LocationType.Remote && locationType != LocationType.Virtual;
|
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>
|
/// <summary>
|
||||||
/// This is just a helper for convenience
|
/// This is just a helper for convenience
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -298,6 +352,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
public virtual bool CanDelete()
|
public virtual bool CanDelete()
|
||||||
{
|
{
|
||||||
|
if (SourceType == SourceType.Channel)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var locationType = LocationType;
|
var locationType = LocationType;
|
||||||
return locationType != LocationType.Remote &&
|
return locationType != LocationType.Remote &&
|
||||||
locationType != LocationType.Virtual;
|
locationType != LocationType.Virtual;
|
||||||
@ -342,6 +401,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public DateTime DateModified { get; set; }
|
public DateTime DateModified { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
public DateTime DateLastSaved { get; set; }
|
public DateTime DateLastSaved { get; set; }
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
@ -380,6 +440,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// Gets or sets the locked fields.
|
/// Gets or sets the locked fields.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The locked fields.</value>
|
/// <value>The locked fields.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public List<MetadataFields> LockedFields { get; set; }
|
public List<MetadataFields> LockedFields { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -433,11 +494,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(ForcedSortName))
|
|
||||||
{
|
|
||||||
return ForcedSortName;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _sortName ?? (_sortName = CreateSortName());
|
return _sortName ?? (_sortName = CreateSortName());
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
@ -455,6 +511,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
protected virtual string GetInternalMetadataPath(string basePath)
|
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");
|
var idString = Id.ToString("N");
|
||||||
|
|
||||||
basePath = System.IO.Path.Combine(basePath, "library");
|
basePath = System.IO.Path.Combine(basePath, "library");
|
||||||
@ -468,6 +529,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected virtual string CreateSortName()
|
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 (Name == null) return null; //some items may not have name filled in properly
|
||||||
|
|
||||||
if (!EnableAlphaNumericSorting)
|
if (!EnableAlphaNumericSorting)
|
||||||
@ -497,7 +563,32 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
sortable = sortable.Remove(sortable.Length - (searchLower.Length + 1));
|
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]
|
[IgnoreDataMember]
|
||||||
@ -595,6 +686,18 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public string OfficialRating { get; set; }
|
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>
|
/// <summary>
|
||||||
/// Gets or sets the official rating description.
|
/// Gets or sets the official rating description.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -620,6 +723,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// Gets or sets the studios.
|
/// Gets or sets the studios.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The studios.</value>
|
/// <value>The studios.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public List<string> Studios { get; set; }
|
public List<string> Studios { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -633,6 +737,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// Gets or sets the tags.
|
/// Gets or sets the tags.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The tags.</value>
|
/// <value>The tags.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public List<string> Tags { get; set; }
|
public List<string> Tags { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -1025,6 +1130,13 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
protected virtual string CreateUserDataKey()
|
protected virtual string CreateUserDataKey()
|
||||||
{
|
{
|
||||||
|
if (SourceType == SourceType.Channel)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(ExternalId))
|
||||||
|
{
|
||||||
|
return ExternalId;
|
||||||
|
}
|
||||||
|
}
|
||||||
return Id.ToString();
|
return Id.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1103,6 +1215,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
public virtual bool IsSaveLocalMetadataEnabled()
|
public virtual bool IsSaveLocalMetadataEnabled()
|
||||||
{
|
{
|
||||||
|
if (SourceType == SourceType.Channel)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return ConfigurationManager.Configuration.SaveLocalMeta;
|
return ConfigurationManager.Configuration.SaveLocalMeta;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1218,6 +1335,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
public virtual UnratedItem GetBlockUnratedType()
|
public virtual UnratedItem GetBlockUnratedType()
|
||||||
{
|
{
|
||||||
|
if (SourceType == SourceType.Channel)
|
||||||
|
{
|
||||||
|
return UnratedItem.ChannelContent;
|
||||||
|
}
|
||||||
|
|
||||||
return UnratedItem.Other;
|
return UnratedItem.Other;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1261,6 +1383,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
public virtual bool IsVisibleStandalone(User user)
|
public virtual bool IsVisibleStandalone(User user)
|
||||||
{
|
{
|
||||||
|
if (SourceType == SourceType.Channel)
|
||||||
|
{
|
||||||
|
return IsVisibleStandaloneInternal(user, false) && Channel.IsChannelVisible(this, user);
|
||||||
|
}
|
||||||
|
|
||||||
return IsVisibleStandaloneInternal(user, true);
|
return IsVisibleStandaloneInternal(user, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1312,6 +1439,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
public virtual string GetClientTypeName()
|
public virtual string GetClientTypeName()
|
||||||
{
|
{
|
||||||
|
if (IsFolder && SourceType == SourceType.Channel)
|
||||||
|
{
|
||||||
|
return "ChannelFolderItem";
|
||||||
|
}
|
||||||
|
|
||||||
return GetType().Name;
|
return GetType().Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1835,8 +1967,8 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
ProviderIds = ProviderIds,
|
ProviderIds = ProviderIds,
|
||||||
IndexNumber = IndexNumber,
|
IndexNumber = IndexNumber,
|
||||||
ParentIndexNumber = ParentIndexNumber,
|
ParentIndexNumber = ParentIndexNumber,
|
||||||
Year = ProductionYear,
|
Year = ProductionYear,
|
||||||
PremiereDate = PremiereDate
|
PremiereDate = PremiereDate
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1985,5 +2117,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
return LibraryManager.DeleteItem(this, options);
|
return LibraryManager.DeleteItem(this, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual Task OnFileDeleted()
|
||||||
|
{
|
||||||
|
// Remove from database
|
||||||
|
return Delete(new DeleteOptions
|
||||||
|
{
|
||||||
|
DeleteFileLocation = false
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@
|
|||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Users;
|
using MediaBrowser.Model.Users;
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
public class Book : BaseItem, IHasTags, IHasLookupInfo<BookInfo>, IHasSeries
|
public class Book : BaseItem, IHasTags, IHasLookupInfo<BookInfo>, IHasSeries
|
||||||
{
|
{
|
||||||
|
[IgnoreDataMember]
|
||||||
public override string MediaType
|
public override string MediaType
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -15,6 +15,9 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
|
using MediaBrowser.Controller.Playlists;
|
||||||
|
using MediaBrowser.Model.Channels;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
@ -145,60 +148,38 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
item.DateModified = DateTime.UtcNow;
|
item.DateModified = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddChildInternal(item);
|
AddChildInternal(item.Id);
|
||||||
|
|
||||||
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (!EnableNewFolderQuerying())
|
|
||||||
{
|
|
||||||
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
lock (_childrenSyncLock)
|
||||||
{
|
{
|
||||||
var newChildren = actualChildren.ToList();
|
var newChildren = ChildIds.ToList();
|
||||||
newChildren.AddRange(children);
|
newChildren.AddRange(children);
|
||||||
_children = newChildren;
|
_children = newChildren.ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected void AddChildInternal(BaseItem child)
|
protected void AddChildInternal(Guid 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()
|
|
||||||
{
|
{
|
||||||
lock (_childrenSyncLock)
|
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.
|
/// Removes the child.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
public void RemoveChild(BaseItem item)
|
||||||
/// <returns>Task.</returns>
|
|
||||||
/// <exception cref="System.InvalidOperationException">Unable to remove + item.Name</exception>
|
|
||||||
public Task RemoveChild(BaseItem item, CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
RemoveChildrenInternal(new[] { item });
|
RemoveChildrenInternal(new[] { item.Id }.ToList());
|
||||||
|
|
||||||
item.SetParent(null);
|
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
|
#region Indexing
|
||||||
@ -276,7 +228,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The children
|
/// The children
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IReadOnlyList<BaseItem> _children;
|
private IReadOnlyList<Guid> _children;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _children sync lock
|
/// The _children sync lock
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -285,21 +237,30 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// Gets or sets the actual children.
|
/// Gets or sets the actual children.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The actual children.</value>
|
/// <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
|
protected virtual IEnumerable<BaseItem> ActualChildren
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_children == null)
|
return ChildIds.Select(LibraryManager.GetItemById).Where(i => i != null);
|
||||||
{
|
|
||||||
lock (_childrenSyncLock)
|
|
||||||
{
|
|
||||||
if (_children == null)
|
|
||||||
{
|
|
||||||
_children = LoadChildren().ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _children;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,7 +314,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// Loads our children. Validation will occur externally.
|
/// Loads our children. Validation will occur externally.
|
||||||
/// We want this sychronous.
|
/// We want this sychronous.
|
||||||
/// </summary>
|
/// </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
|
//just load our children from the repo - the library will be validated and maintained in other processes
|
||||||
return GetCachedChildren();
|
return GetCachedChildren();
|
||||||
@ -503,7 +464,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
if (actualRemovals.Count > 0)
|
if (actualRemovals.Count > 0)
|
||||||
{
|
{
|
||||||
RemoveChildrenInternal(actualRemovals);
|
RemoveChildrenInternal(actualRemovals.Select(i => i.Id).ToList());
|
||||||
|
|
||||||
foreach (var item in actualRemovals)
|
foreach (var item in actualRemovals)
|
||||||
{
|
{
|
||||||
@ -518,12 +479,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false);
|
await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
AddChildrenInternal(newItems);
|
AddChildrenInternal(newItems.Select(i => i.Id).ToList());
|
||||||
|
|
||||||
if (!EnableNewFolderQuerying())
|
|
||||||
{
|
|
||||||
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -751,51 +707,459 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// Get our children from the repo - stubbed for now
|
/// Get our children from the repo - stubbed for now
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
/// <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)
|
var user = query.User;
|
||||||
{
|
|
||||||
Logger.Error("Item found with empty Id: " + (child.Path ?? child.Name));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var item = LibraryManager.GetMemoryItemById(child.Id);
|
if (RequiresPostFiltering(query))
|
||||||
|
|
||||||
if (item != null)
|
|
||||||
{
|
{
|
||||||
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);
|
return PostFilterAndSort(items, query);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
child.SetParent(this);
|
|
||||||
LibraryManager.RegisterItem(child);
|
|
||||||
item = child;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
var user = query.User;
|
||||||
|
|
||||||
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
|
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);
|
var result = PostFilterAndSort(items, query);
|
||||||
|
|
||||||
return Task.FromResult(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)
|
protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)
|
||||||
|
@ -83,6 +83,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public string[] OfficialRatings { get; set; }
|
public string[] OfficialRatings { get; set; }
|
||||||
|
|
||||||
public DateTime? MinPremiereDate { get; set; }
|
public DateTime? MinPremiereDate { get; set; }
|
||||||
|
public DateTime? MaxPremiereDate { get; set; }
|
||||||
public DateTime? MinStartDate { get; set; }
|
public DateTime? MinStartDate { get; set; }
|
||||||
public DateTime? MaxStartDate { get; set; }
|
public DateTime? MaxStartDate { get; set; }
|
||||||
public DateTime? MinEndDate { get; set; }
|
public DateTime? MinEndDate { get; set; }
|
||||||
@ -96,28 +97,45 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public int? MinPlayers { get; set; }
|
public int? MinPlayers { get; set; }
|
||||||
public int? MaxPlayers { get; set; }
|
public int? MaxPlayers { get; set; }
|
||||||
public int? MinIndexNumber { get; set; }
|
public int? MinIndexNumber { get; set; }
|
||||||
|
public int? AiredDuringSeason { get; set; }
|
||||||
public double? MinCriticRating { get; set; }
|
public double? MinCriticRating { get; set; }
|
||||||
public double? MinCommunityRating { get; set; }
|
public double? MinCommunityRating { get; set; }
|
||||||
|
|
||||||
public string[] ChannelIds { get; set; }
|
public string[] ChannelIds { get; set; }
|
||||||
|
|
||||||
internal List<Guid> ItemIdsFromPersonFilters { get; set; }
|
internal List<Guid> ItemIdsFromPersonFilters { get; set; }
|
||||||
|
public int? ParentIndexNumber { get; set; }
|
||||||
|
public int? MinParentalRating { get; set; }
|
||||||
public int? MaxParentalRating { get; set; }
|
public int? MaxParentalRating { get; set; }
|
||||||
|
|
||||||
public bool? IsCurrentSchema { get; set; }
|
public bool? IsCurrentSchema { get; set; }
|
||||||
public bool? HasDeadParentId { get; set; }
|
public bool? HasDeadParentId { get; set; }
|
||||||
public bool? IsOffline { get; set; }
|
public bool? IsOffline { get; set; }
|
||||||
public LocationType? LocationType { get; set; }
|
|
||||||
|
|
||||||
public Guid? ParentId { get; set; }
|
public Guid? ParentId { get; set; }
|
||||||
public string[] AncestorIds { get; set; }
|
public string[] AncestorIds { get; set; }
|
||||||
public string[] TopParentIds { get; set; }
|
public string[] TopParentIds { get; set; }
|
||||||
|
|
||||||
|
public LocationType[] LocationTypes { get; set; }
|
||||||
public LocationType[] ExcludeLocationTypes { get; set; }
|
public LocationType[] ExcludeLocationTypes { get; set; }
|
||||||
public string[] PresetViews { 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()
|
public InternalItemsQuery()
|
||||||
{
|
{
|
||||||
|
AlbumNames = new string[] { };
|
||||||
|
ArtistNames = new string[] { };
|
||||||
|
|
||||||
BlockUnratedItems = new UnratedItem[] { };
|
BlockUnratedItems = new UnratedItem[] { };
|
||||||
Tags = new string[] { };
|
Tags = new string[] { };
|
||||||
OfficialRatings = new string[] { };
|
OfficialRatings = new string[] { };
|
||||||
@ -139,8 +157,15 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
AncestorIds = new string[] { };
|
AncestorIds = new string[] { };
|
||||||
TopParentIds = new string[] { };
|
TopParentIds = new string[] { };
|
||||||
ExcludeTags = new string[] { };
|
ExcludeTags = new string[] { };
|
||||||
|
LocationTypes = new LocationType[] { };
|
||||||
ExcludeLocationTypes = new LocationType[] { };
|
ExcludeLocationTypes = new LocationType[] { };
|
||||||
PresetViews = new string[] { };
|
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)
|
public InternalItemsQuery(User user)
|
||||||
|
@ -6,6 +6,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
@ -67,24 +68,19 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
/// <value>The revenue.</value>
|
/// <value>The revenue.</value>
|
||||||
public double? Revenue { get; set; }
|
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>
|
/// <summary>
|
||||||
/// Gets or sets the name of the TMDB collection.
|
/// Gets or sets the name of the TMDB collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The name of the TMDB collection.</value>
|
/// <value>The name of the TMDB collection.</value>
|
||||||
public string TmdbCollectionName { get; set; }
|
public string TmdbCollectionName { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public string CollectionName
|
||||||
|
{
|
||||||
|
get { return TmdbCollectionName; }
|
||||||
|
set { TmdbCollectionName = value; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the trailer ids.
|
/// Gets the trailer ids.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
10
MediaBrowser.Controller/Entities/SourceType.cs
Normal file
10
MediaBrowser.Controller/Entities/SourceType.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Entities
|
||||||
|
{
|
||||||
|
public enum SourceType
|
||||||
|
{
|
||||||
|
Library = 0,
|
||||||
|
Channel = 1,
|
||||||
|
LiveTV = 2
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Trailer
|
/// Class Trailer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete]
|
|
||||||
public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasLookupInfo<TrailerInfo>
|
public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasLookupInfo<TrailerInfo>
|
||||||
{
|
{
|
||||||
public List<string> ProductionLocations { get; set; }
|
public List<string> ProductionLocations { get; set; }
|
||||||
@ -25,14 +24,23 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
Taglines = new List<string>();
|
Taglines = new List<string>();
|
||||||
Keywords = new List<string>();
|
Keywords = new List<string>();
|
||||||
ProductionLocations = new List<string>();
|
ProductionLocations = new List<string>();
|
||||||
|
TrailerTypes = new List<TrailerType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<TrailerType> TrailerTypes { get; set; }
|
||||||
|
|
||||||
public float? Metascore { get; set; }
|
public float? Metascore { get; set; }
|
||||||
|
|
||||||
public List<MediaUrl> RemoteTrailers { get; set; }
|
public List<MediaUrl> RemoteTrailers { get; set; }
|
||||||
|
|
||||||
public List<string> Keywords { get; set; }
|
public List<string> Keywords { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool IsLocalTrailer
|
||||||
|
{
|
||||||
|
get { return TrailerTypes.Contains(TrailerType.LocalTrailer); }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the taglines.
|
/// Gets or sets the taglines.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -51,32 +59,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <value>The revenue.</value>
|
/// <value>The revenue.</value>
|
||||||
public double? Revenue { get; set; }
|
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()
|
protected override string CreateUserDataKey()
|
||||||
{
|
{
|
||||||
var key = Movie.GetMovieUserDataKey(this);
|
var key = Movie.GetMovieUserDataKey(this);
|
||||||
@ -106,9 +88,50 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
var info = GetItemLookupInfo<TrailerInfo>();
|
var info = GetItemLookupInfo<TrailerInfo>();
|
||||||
|
|
||||||
info.IsLocalTrailer = IsLocalTrailer;
|
info.IsLocalTrailer = TrailerTypes.Contains(TrailerType.LocalTrailer);
|
||||||
|
|
||||||
|
if (!IsInMixedFolder)
|
||||||
|
{
|
||||||
|
info.Name = System.IO.Path.GetFileName(ContainingFolderPath);
|
||||||
|
}
|
||||||
|
|
||||||
return info;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,13 +19,9 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
public override async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
|
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)
|
if (query.Recursive)
|
||||||
{
|
{
|
||||||
var items = query.User.RootFolder.GetRecursiveChildren(query.User, filter);
|
return QueryRecursive(query);
|
||||||
return PostFilterAndSort(items, query);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await UserViewManager.GetUserViews(new UserViewQuery
|
var result = await UserViewManager.GetUserViews(new UserViewQuery
|
||||||
@ -35,6 +31,9 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
}, CancellationToken.None).ConfigureAwait(false);
|
}, 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);
|
return PostFilterAndSort(result.Where(filter), query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,15 +50,15 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
var user = query.User;
|
var user = query.User;
|
||||||
|
|
||||||
if (query.IncludeItemTypes != null &&
|
//if (query.IncludeItemTypes != null &&
|
||||||
query.IncludeItemTypes.Length == 1 &&
|
// query.IncludeItemTypes.Length == 1 &&
|
||||||
string.Equals(query.IncludeItemTypes[0], "Playlist", StringComparison.OrdinalIgnoreCase))
|
// string.Equals(query.IncludeItemTypes[0], "Playlist", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
//{
|
||||||
if (!string.Equals(viewType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
|
// if (!string.Equals(viewType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
// {
|
||||||
return await FindPlaylists(queryParent, user, query).ConfigureAwait(false);
|
// return await FindPlaylists(queryParent, user, query).ConfigureAwait(false);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
switch (viewType)
|
switch (viewType)
|
||||||
{
|
{
|
||||||
@ -766,7 +766,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool CollapseBoxSetItems(InternalItemsQuery query,
|
public static bool CollapseBoxSetItems(InternalItemsQuery query,
|
||||||
BaseItem queryParent,
|
BaseItem queryParent,
|
||||||
User user)
|
User user)
|
||||||
{
|
{
|
||||||
@ -1199,6 +1199,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (query.ExcludeLocationTypes.Length > 0 && query.ExcludeLocationTypes.Contains(item.LocationType))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (query.IsFolder.HasValue && query.IsFolder.Value != item.IsFolder)
|
if (query.IsFolder.HasValue && query.IsFolder.Value != item.IsFolder)
|
||||||
{
|
{
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,13 +6,16 @@ using MediaBrowser.Model.Entities;
|
|||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Mime;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
|
using MediaBrowser.Controller.Channels;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
@ -33,6 +36,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public List<string> AdditionalParts { get; set; }
|
public List<string> AdditionalParts { get; set; }
|
||||||
public List<string> LocalAlternateVersions { get; set; }
|
public List<string> LocalAlternateVersions { get; set; }
|
||||||
public List<LinkedChild> LinkedAlternateVersions { get; set; }
|
public List<LinkedChild> LinkedAlternateVersions { get; set; }
|
||||||
|
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsThemeMedia
|
public bool IsThemeMedia
|
||||||
@ -78,6 +82,23 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
locationType != LocationType.Virtual;
|
locationType != LocationType.Virtual;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override LocationType LocationType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (SourceType == SourceType.Channel)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(Path))
|
||||||
|
{
|
||||||
|
return LocationType.Remote;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.LocationType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool SupportsAddingToPlaylist
|
public override bool SupportsAddingToPlaylist
|
||||||
{
|
{
|
||||||
@ -130,6 +151,29 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
|
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>
|
/// <summary>
|
||||||
/// Gets the linked children.
|
/// Gets the linked children.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -441,6 +485,22 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
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 item = this;
|
||||||
|
|
||||||
var result = item.GetAlternateVersions()
|
var result = item.GetAlternateVersions()
|
||||||
|
@ -79,5 +79,12 @@ namespace MediaBrowser.Controller
|
|||||||
/// <param name="host">The host.</param>
|
/// <param name="host">The host.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
string GetLocalApiUrl(string host);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,13 +152,6 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <returns>BaseItem.</returns>
|
/// <returns>BaseItem.</returns>
|
||||||
BaseItem GetItemById(Guid id);
|
BaseItem GetItemById(Guid id);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the items.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="query">The query.</param>
|
|
||||||
/// <returns>QueryResult<BaseItem>.</returns>
|
|
||||||
QueryResult<BaseItem> GetItems(InternalItemsQuery query);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the memory item by identifier.
|
/// Gets the memory item by identifier.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -547,22 +540,28 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task<ItemImageInfo> ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex);
|
Task<ItemImageInfo> ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the items.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">The query.</param>
|
||||||
|
/// <returns>QueryResult<BaseItem>.</returns>
|
||||||
|
IEnumerable<BaseItem> GetItemList(InternalItemsQuery query);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the items.
|
/// Gets the items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
/// <param name="parentIds">The parent ids.</param>
|
/// <param name="parentIds">The parent ids.</param>
|
||||||
/// <returns>List<BaseItem>.</returns>
|
/// <returns>List<BaseItem>.</returns>
|
||||||
IEnumerable<BaseItem> GetItems(InternalItemsQuery query, IEnumerable<string> parentIds);
|
IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, IEnumerable<string> parentIds);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the items result.
|
/// Gets the items result.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
/// <param name="parentIds">The parent ids.</param>
|
|
||||||
/// <returns>QueryResult<BaseItem>.</returns>
|
/// <returns>QueryResult<BaseItem>.</returns>
|
||||||
QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query, IEnumerable<string> parentIds);
|
QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ignores the file.
|
/// Ignores the file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -15,11 +15,14 @@ namespace MediaBrowser.Controller.Library
|
|||||||
public BaseItem Item { get; set; }
|
public BaseItem Item { get; set; }
|
||||||
public BaseItemInfo MediaInfo { get; set; }
|
public BaseItemInfo MediaInfo { get; set; }
|
||||||
public string MediaSourceId { get; set; }
|
public string MediaSourceId { get; set; }
|
||||||
|
public bool IsPaused { get; set; }
|
||||||
|
|
||||||
public string DeviceId { get; set; }
|
public string DeviceId { get; set; }
|
||||||
public string DeviceName { get; set; }
|
public string DeviceName { get; set; }
|
||||||
public string ClientName { get; set; }
|
public string ClientName { get; set; }
|
||||||
|
|
||||||
|
public string PlaySessionId { get; set; }
|
||||||
|
|
||||||
public PlaybackProgressEventArgs()
|
public PlaybackProgressEventArgs()
|
||||||
{
|
{
|
||||||
Users = new List<User>();
|
Users = new List<User>();
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
using MediaBrowser.Controller.Entities;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
|
||||||
{
|
|
||||||
public interface ILiveTvItem : IHasId
|
|
||||||
{
|
|
||||||
string ServiceName { get; set; }
|
|
||||||
string ExternalId { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -50,7 +50,7 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="recording">The recording.</param>
|
/// <param name="recording">The recording.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task DeleteRecording(ILiveTvRecording recording);
|
Task DeleteRecording(BaseItem recording);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cancels the timer.
|
/// Cancels the timer.
|
||||||
@ -74,15 +74,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <param name="listingProviders">The listing providers.</param>
|
/// <param name="listingProviders">The listing providers.</param>
|
||||||
void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders);
|
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>
|
/// <summary>
|
||||||
/// Gets the recording.
|
/// Gets the recording.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -92,15 +83,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
/// <returns>Task{RecordingInfoDto}.</returns>
|
/// <returns>Task{RecordingInfoDto}.</returns>
|
||||||
Task<BaseItemDto> GetRecording(string id, DtoOptions options, CancellationToken cancellationToken, User user = null);
|
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>
|
/// <summary>
|
||||||
/// Gets the timer.
|
/// Gets the timer.
|
||||||
@ -156,7 +138,7 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <param name="id">The identifier.</param>
|
/// <param name="id">The identifier.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>LiveTvRecording.</returns>
|
/// <returns>LiveTvRecording.</returns>
|
||||||
Task<ILiveTvRecording> GetInternalRecording(string id, CancellationToken cancellationToken);
|
Task<BaseItem> GetInternalRecording(string id, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the recording stream.
|
/// Gets the recording stream.
|
||||||
@ -385,10 +367,22 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the channel information.
|
/// Adds the channel information.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dto">The dto.</param>
|
/// <param name="items">The items.</param>
|
||||||
/// <param name="channel">The channel.</param>
|
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
/// <param name="user">The user.</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<NameValuePair>.</returns>
|
||||||
|
List<NameValuePair> GetSatIniMappings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,10 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
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 ChannelId { get; }
|
||||||
string MediaType { get; }
|
string MediaType { get; }
|
||||||
|
|
||||||
|
@ -39,6 +39,13 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsPremiere { get; set; }
|
public bool IsPremiere { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override SourceType SourceType
|
||||||
|
{
|
||||||
|
get { return SourceType.LiveTV; }
|
||||||
|
set { }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user data key.
|
/// Gets the user data key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -50,8 +57,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
return name + "-" + Name + (EpisodeTitle ?? string.Empty);
|
return name + "-" + Name + (EpisodeTitle ?? string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ServiceName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this instance is owned item.
|
/// Gets a value indicating whether this instance is owned item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -151,5 +156,10 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
{
|
{
|
||||||
return LiveTvManager.DeleteRecording(this);
|
return LiveTvManager.DeleteRecording(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override Task OnFileDeleted()
|
||||||
|
{
|
||||||
|
return LiveTvManager.OnRecordingFileDeleted(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ using System.Runtime.Serialization;
|
|||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
public class LiveTvChannel : BaseItem, IHasMediaSources, ILiveTvItem
|
public class LiveTvChannel : BaseItem, IHasMediaSources
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user data key.
|
/// Gets the user data key.
|
||||||
@ -40,6 +40,13 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override SourceType SourceType
|
||||||
|
{
|
||||||
|
get { return SourceType.LiveTV; }
|
||||||
|
set { }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the number.
|
/// Gets or sets the number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -52,12 +59,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <value>The type of the channel.</value>
|
/// <value>The type of the channel.</value>
|
||||||
public ChannelType ChannelType { get; set; }
|
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]
|
[IgnoreDataMember]
|
||||||
public override LocationType LocationType
|
public override LocationType LocationType
|
||||||
{
|
{
|
||||||
|
@ -11,7 +11,7 @@ using MediaBrowser.Model.Entities;
|
|||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
public class LiveTvProgram : BaseItem, ILiveTvItem, IHasLookupInfo<LiveTvProgramLookupInfo>, IHasStartDate, IHasProgramAttributes
|
public class LiveTvProgram : BaseItem, IHasLookupInfo<LiveTvProgramLookupInfo>, IHasStartDate, IHasProgramAttributes
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user data key.
|
/// Gets the user data key.
|
||||||
@ -39,12 +39,12 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
return base.CreateUserDataKey();
|
return base.CreateUserDataKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the name.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The name.</value>
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public string ServiceName { get; set; }
|
public override SourceType SourceType
|
||||||
|
{
|
||||||
|
get { return SourceType.LiveTV; }
|
||||||
|
set { }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The start date of the program, in UTC.
|
/// The start date of the program, in UTC.
|
||||||
|
@ -39,6 +39,13 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsPremiere { get; set; }
|
public bool IsPremiere { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override SourceType SourceType
|
||||||
|
{
|
||||||
|
get { return SourceType.LiveTV; }
|
||||||
|
set { }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user data key.
|
/// Gets the user data key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -65,8 +72,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
return base.CreateUserDataKey();
|
return base.CreateUserDataKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ServiceName { get; set; }
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override string MediaType
|
public override string MediaType
|
||||||
{
|
{
|
||||||
@ -166,5 +171,10 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
{
|
{
|
||||||
return LiveTvManager.DeleteRecording(this);
|
return LiveTvManager.DeleteRecording(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override Task OnFileDeleted()
|
||||||
|
{
|
||||||
|
return LiveTvManager.OnRecordingFileDeleted(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using MediaBrowser.Controller.Entities;
|
using System.Runtime.Serialization;
|
||||||
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Users;
|
using MediaBrowser.Model.Users;
|
||||||
|
|
||||||
@ -24,5 +25,12 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override SourceType SourceType
|
||||||
|
{
|
||||||
|
get { return SourceType.LiveTV; }
|
||||||
|
set { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<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>
|
||||||
<Reference Include="Interfaces.IO">
|
<Reference Include="Interfaces.IO">
|
||||||
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
|
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
|
||||||
@ -75,6 +75,7 @@
|
|||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Activity\IActivityManager.cs" />
|
<Compile Include="Activity\IActivityManager.cs" />
|
||||||
<Compile Include="Activity\IActivityRepository.cs" />
|
<Compile Include="Activity\IActivityRepository.cs" />
|
||||||
|
<Compile Include="Channels\ChannelAudioItem.cs" />
|
||||||
<Compile Include="Channels\ChannelFolderItem.cs" />
|
<Compile Include="Channels\ChannelFolderItem.cs" />
|
||||||
<Compile Include="Channels\ChannelItemInfo.cs" />
|
<Compile Include="Channels\ChannelItemInfo.cs" />
|
||||||
<Compile Include="Channels\ChannelItemResult.cs" />
|
<Compile Include="Channels\ChannelItemResult.cs" />
|
||||||
@ -82,11 +83,10 @@
|
|||||||
<Compile Include="Channels\ChannelMediaInfo.cs" />
|
<Compile Include="Channels\ChannelMediaInfo.cs" />
|
||||||
<Compile Include="Channels\ChannelParentalRating.cs" />
|
<Compile Include="Channels\ChannelParentalRating.cs" />
|
||||||
<Compile Include="Channels\ChannelSearchInfo.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\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\Channel.cs" />
|
||||||
<Compile Include="Channels\IChannelMediaItem.cs" />
|
<Compile Include="Channels\IChannelMediaItem.cs" />
|
||||||
<Compile Include="Channels\IHasCacheKey.cs" />
|
<Compile Include="Channels\IHasCacheKey.cs" />
|
||||||
@ -128,6 +128,7 @@
|
|||||||
<Compile Include="Drawing\ImageStream.cs" />
|
<Compile Include="Drawing\ImageStream.cs" />
|
||||||
<Compile Include="Dto\DtoOptions.cs" />
|
<Compile Include="Dto\DtoOptions.cs" />
|
||||||
<Compile Include="Dto\IDtoService.cs" />
|
<Compile Include="Dto\IDtoService.cs" />
|
||||||
|
<Compile Include="Entities\Audio\AudioPodcast.cs" />
|
||||||
<Compile Include="Entities\Audio\IHasAlbumArtist.cs" />
|
<Compile Include="Entities\Audio\IHasAlbumArtist.cs" />
|
||||||
<Compile Include="Entities\Audio\IHasMusicGenres.cs" />
|
<Compile Include="Entities\Audio\IHasMusicGenres.cs" />
|
||||||
<Compile Include="Entities\Book.cs" />
|
<Compile Include="Entities\Book.cs" />
|
||||||
@ -180,6 +181,7 @@
|
|||||||
<Compile Include="Entities\Photo.cs" />
|
<Compile Include="Entities\Photo.cs" />
|
||||||
<Compile Include="Entities\PhotoAlbum.cs" />
|
<Compile Include="Entities\PhotoAlbum.cs" />
|
||||||
<Compile Include="Entities\Share.cs" />
|
<Compile Include="Entities\Share.cs" />
|
||||||
|
<Compile Include="Entities\SourceType.cs" />
|
||||||
<Compile Include="Entities\UserView.cs" />
|
<Compile Include="Entities\UserView.cs" />
|
||||||
<Compile Include="Entities\UserViewBuilder.cs" />
|
<Compile Include="Entities\UserViewBuilder.cs" />
|
||||||
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
|
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
|
||||||
@ -202,7 +204,6 @@
|
|||||||
<Compile Include="Library\UserDataSaveEventArgs.cs" />
|
<Compile Include="Library\UserDataSaveEventArgs.cs" />
|
||||||
<Compile Include="LiveTv\IHasRegistrationInfo.cs" />
|
<Compile Include="LiveTv\IHasRegistrationInfo.cs" />
|
||||||
<Compile Include="LiveTv\IListingsProvider.cs" />
|
<Compile Include="LiveTv\IListingsProvider.cs" />
|
||||||
<Compile Include="LiveTv\ILiveTvItem.cs" />
|
|
||||||
<Compile Include="LiveTv\ITunerHost.cs" />
|
<Compile Include="LiveTv\ITunerHost.cs" />
|
||||||
<Compile Include="LiveTv\RecordingGroup.cs" />
|
<Compile Include="LiveTv\RecordingGroup.cs" />
|
||||||
<Compile Include="LiveTv\RecordingStatusChangedEventArgs.cs" />
|
<Compile Include="LiveTv\RecordingStatusChangedEventArgs.cs" />
|
||||||
@ -271,7 +272,6 @@
|
|||||||
<Compile Include="Providers\ArtistInfo.cs" />
|
<Compile Include="Providers\ArtistInfo.cs" />
|
||||||
<Compile Include="Providers\BookInfo.cs" />
|
<Compile Include="Providers\BookInfo.cs" />
|
||||||
<Compile Include="Providers\BoxSetInfo.cs" />
|
<Compile Include="Providers\BoxSetInfo.cs" />
|
||||||
<Compile Include="Providers\ChannelItemLookupInfo.cs" />
|
|
||||||
<Compile Include="Providers\DirectoryService.cs" />
|
<Compile Include="Providers\DirectoryService.cs" />
|
||||||
<Compile Include="Providers\DynamicImageInfo.cs" />
|
<Compile Include="Providers\DynamicImageInfo.cs" />
|
||||||
<Compile Include="Providers\DynamicImageResponse.cs" />
|
<Compile Include="Providers\DynamicImageResponse.cs" />
|
||||||
@ -331,6 +331,7 @@
|
|||||||
<Compile Include="Security\IEncryptionManager.cs" />
|
<Compile Include="Security\IEncryptionManager.cs" />
|
||||||
<Compile Include="Session\AuthenticationRequest.cs" />
|
<Compile Include="Session\AuthenticationRequest.cs" />
|
||||||
<Compile Include="Social\ISharingManager.cs" />
|
<Compile Include="Social\ISharingManager.cs" />
|
||||||
|
<Compile Include="Sorting\SortHelper.cs" />
|
||||||
<Compile Include="Subtitles\ISubtitleManager.cs" />
|
<Compile Include="Subtitles\ISubtitleManager.cs" />
|
||||||
<Compile Include="Subtitles\ISubtitleProvider.cs" />
|
<Compile Include="Subtitles\ISubtitleProvider.cs" />
|
||||||
<Compile Include="Providers\ItemIdentifier.cs" />
|
<Compile Include="Providers\ItemIdentifier.cs" />
|
||||||
|
@ -90,8 +90,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
Cabac = info.Cabac;
|
Cabac = info.Cabac;
|
||||||
Context = info.Context;
|
Context = info.Context;
|
||||||
|
|
||||||
if (info.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode ||
|
if (info.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External)
|
||||||
info.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed)
|
|
||||||
{
|
{
|
||||||
SubtitleStreamIndex = info.SubtitleStreamIndex;
|
SubtitleStreamIndex = info.SubtitleStreamIndex;
|
||||||
}
|
}
|
||||||
|
@ -42,13 +42,6 @@ namespace MediaBrowser.Controller.Persistence
|
|||||||
/// <returns>Task{IEnumerable{ItemReview}}.</returns>
|
/// <returns>Task{IEnumerable{ItemReview}}.</returns>
|
||||||
IEnumerable<ItemReview> GetCriticReviews(Guid itemId);
|
IEnumerable<ItemReview> GetCriticReviews(Guid itemId);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the children items.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="parentId">The parent identifier.</param>
|
|
||||||
/// <returns>IEnumerable<BaseItem>.</returns>
|
|
||||||
IEnumerable<BaseItem> GetChildrenItems(Guid parentId);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves the critic reviews.
|
/// Saves the critic reviews.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -96,22 +89,6 @@ namespace MediaBrowser.Controller.Persistence
|
|||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task SaveChapters(Guid id, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken);
|
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>
|
/// <summary>
|
||||||
/// Gets the media streams.
|
/// Gets the media streams.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -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; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +1,5 @@
|
|||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Providers
|
namespace MediaBrowser.Controller.Providers
|
||||||
{
|
{
|
||||||
public class TrailerInfo : ItemLookupInfo
|
public class TrailerInfo : ItemLookupInfo
|
||||||
|
31
MediaBrowser.Controller/Sorting/SortHelper.cs
Normal file
31
MediaBrowser.Controller/Sorting/SortHelper.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.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="Interfaces.IO" version="1.0.0.5" targetFramework="net45" />
|
||||||
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
||||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||||
|
@ -488,12 +488,12 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||||||
var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
|
var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Person = person.Name,
|
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 },
|
SortBy = new[] { ItemSortBy.SortName },
|
||||||
Limit = limit,
|
Limit = limit,
|
||||||
StartIndex = startIndex
|
StartIndex = startIndex
|
||||||
|
|
||||||
}, new string[] { });
|
});
|
||||||
|
|
||||||
var serverItems = itemsResult.Items.Select(i => new ServerItem
|
var serverItems = itemsResult.Items.Select(i => new ServerItem
|
||||||
{
|
{
|
||||||
|
@ -188,15 +188,15 @@ namespace MediaBrowser.Dlna.Didl
|
|||||||
{
|
{
|
||||||
var subtitleAdded = AddSubtitleElement(container, subtitle);
|
var subtitleAdded = AddSubtitleElement(container, subtitle);
|
||||||
|
|
||||||
if (subtitleAdded && _profile.EnableSingleSubtitleLimit)
|
if (subtitleAdded && _profile.EnableSingleSubtitleLimit)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool AddSubtitleElement(XmlElement container, SubtitleStreamInfo info)
|
private bool AddSubtitleElement(XmlElement container, SubtitleStreamInfo info)
|
||||||
{
|
{
|
||||||
var subtitleProfile = _profile.SubtitleProfiles
|
var subtitleProfile = _profile.SubtitleProfiles
|
||||||
.FirstOrDefault(i => string.Equals(info.Format, i.Format, StringComparison.OrdinalIgnoreCase) && i.Method == SubtitleDeliveryMethod.External);
|
.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: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>
|
// <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:
|
//// TODO: attribute needs SEC:
|
||||||
//res.SetAttribute("type", info.Format.ToLower());
|
res.SetAttribute("type", "sec", info.Format.ToLower());
|
||||||
//container.AppendChild(res);
|
container.AppendChild(res);
|
||||||
}
|
}
|
||||||
else if (string.Equals(subtitleMode, "smi", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(subtitleMode, "smi", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
@ -243,7 +243,7 @@ namespace MediaBrowser.Dlna.Didl
|
|||||||
container.AppendChild(res);
|
container.AppendChild(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddVideoResource(XmlElement container, IHasMediaSources video, string deviceId, Filter filter, string contentFeatures, StreamInfo streamInfo)
|
private void AddVideoResource(XmlElement container, IHasMediaSources video, string deviceId, Filter filter, string contentFeatures, StreamInfo streamInfo)
|
||||||
|
@ -161,7 +161,7 @@ namespace MediaBrowser.Dlna.Main
|
|||||||
|
|
||||||
var descriptorURI = "/dlna/" + udn + "/description.xml";
|
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>
|
var services = new List<string>
|
||||||
{
|
{
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<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>
|
||||||
<Reference Include="MoreLinq">
|
<Reference Include="MoreLinq">
|
||||||
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||||
|
@ -171,7 +171,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||||||
|
|
||||||
private string GetServerAddress(IPAddress localIp)
|
private string GetServerAddress(IPAddress localIp)
|
||||||
{
|
{
|
||||||
return _appHost.GetLocalApiUrl(localIp.ToString());
|
return _appHost.GetLocalApiUrl(localIp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -31,10 +31,10 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
MaxIconWidth = 48;
|
MaxIconWidth = 48;
|
||||||
MaxIconHeight = 48;
|
MaxIconHeight = 48;
|
||||||
|
|
||||||
MaxStreamingBitrate = 12000000;
|
MaxStreamingBitrate = 15000000;
|
||||||
MaxStaticBitrate = 12000000;
|
MaxStaticBitrate = 15000000;
|
||||||
MusicStreamingTranscodingBitrate = 128000;
|
MusicStreamingTranscodingBitrate = 192000;
|
||||||
MusicSyncBitrate = 128000;
|
MusicSyncBitrate = 192000;
|
||||||
|
|
||||||
EnableAlbumArtInDidl = false;
|
EnableAlbumArtInDidl = false;
|
||||||
|
|
||||||
|
@ -99,6 +99,48 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
DidlMode = "",
|
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
|
new SubtitleProfile
|
||||||
{
|
{
|
||||||
Format = "sub",
|
Format = "sub",
|
||||||
|
@ -54,21 +54,21 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "ts",
|
Container = "ts",
|
||||||
VideoCodec = "h264",
|
VideoCodec = "h264,hevc",
|
||||||
AudioCodec = "aac,ac3,mp3",
|
AudioCodec = "aac,ac3,mp3",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
},
|
},
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mkv",
|
Container = "mkv",
|
||||||
VideoCodec = "h264",
|
VideoCodec = "h264,hevc",
|
||||||
AudioCodec = "aac,ac3,mp3",
|
AudioCodec = "aac,ac3,mp3",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
},
|
},
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp4",
|
Container = "mp4",
|
||||||
VideoCodec = "h264,mpeg4",
|
VideoCodec = "h264,mpeg4,hevc",
|
||||||
AudioCodec = "aac,ac3,mp3",
|
AudioCodec = "aac,ac3,mp3",
|
||||||
Type = DlnaProfileType.Video
|
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
@ -24,10 +24,10 @@
|
|||||||
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
||||||
<MaxIconWidth>48</MaxIconWidth>
|
<MaxIconWidth>48</MaxIconWidth>
|
||||||
<MaxIconHeight>48</MaxIconHeight>
|
<MaxIconHeight>48</MaxIconHeight>
|
||||||
<MaxStreamingBitrate>12000000</MaxStreamingBitrate>
|
<MaxStreamingBitrate>15000000</MaxStreamingBitrate>
|
||||||
<MaxStaticBitrate>12000000</MaxStaticBitrate>
|
<MaxStaticBitrate>15000000</MaxStaticBitrate>
|
||||||
<MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
|
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
||||||
<MusicSyncBitrate>128000</MusicSyncBitrate>
|
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
||||||
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
<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>
|
<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>
|
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||||
|
@ -52,6 +52,12 @@
|
|||||||
<SubtitleProfile format="srt" method="External" />
|
<SubtitleProfile format="srt" method="External" />
|
||||||
<SubtitleProfile format="sub" method="External" />
|
<SubtitleProfile format="sub" method="External" />
|
||||||
<SubtitleProfile format="srt" method="Embed" didlMode="" />
|
<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="" />
|
<SubtitleProfile format="sub" method="Embed" didlMode="" />
|
||||||
</SubtitleProfiles>
|
</SubtitleProfiles>
|
||||||
</Profile>
|
</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
@ -24,10 +24,10 @@
|
|||||||
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
||||||
<MaxIconWidth>48</MaxIconWidth>
|
<MaxIconWidth>48</MaxIconWidth>
|
||||||
<MaxIconHeight>48</MaxIconHeight>
|
<MaxIconHeight>48</MaxIconHeight>
|
||||||
<MaxStreamingBitrate>12000000</MaxStreamingBitrate>
|
<MaxStreamingBitrate>15000000</MaxStreamingBitrate>
|
||||||
<MaxStaticBitrate>12000000</MaxStaticBitrate>
|
<MaxStaticBitrate>15000000</MaxStaticBitrate>
|
||||||
<MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
|
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
||||||
<MusicSyncBitrate>128000</MusicSyncBitrate>
|
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
||||||
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
||||||
<SonyAggregationFlags>10</SonyAggregationFlags>
|
<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>
|
<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
Loading…
x
Reference in New Issue
Block a user