mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-03-23 02:27:17 +00:00
@@ -45,6 +45,11 @@ namespace MediaBrowser.Server.Implementations.IO
|
||||
|
||||
private void AddAffectedPath(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
throw new ArgumentNullException("path");
|
||||
}
|
||||
|
||||
if (!_affectedPaths.Contains(path, StringComparer.Ordinal))
|
||||
{
|
||||
_affectedPaths.Add(path);
|
||||
@@ -53,6 +58,11 @@ namespace MediaBrowser.Server.Implementations.IO
|
||||
|
||||
public void AddPath(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
throw new ArgumentNullException("path");
|
||||
}
|
||||
|
||||
lock (_timerLock)
|
||||
{
|
||||
AddAffectedPath(path);
|
||||
|
||||
@@ -2838,9 +2838,13 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
|
||||
private bool ValidateNetworkPath(string path)
|
||||
{
|
||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT || !path.StartsWith("\\\\", StringComparison.OrdinalIgnoreCase))
|
||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
||||
{
|
||||
return Directory.Exists(path);
|
||||
// We can't validate protocol-based paths, so just allow them
|
||||
if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) == -1)
|
||||
{
|
||||
return Directory.Exists(path);
|
||||
}
|
||||
}
|
||||
|
||||
// Without native support for unc, we cannot validate this when running under mono
|
||||
|
||||
@@ -360,7 +360,6 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
|
||||
public async Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, bool enableAutoClose, CancellationToken cancellationToken)
|
||||
{
|
||||
enableAutoClose = false;
|
||||
await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
try
|
||||
|
||||
@@ -207,14 +207,18 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||
// Find movies with their own folders
|
||||
if (args.IsDirectory)
|
||||
{
|
||||
var files = args.FileSystemChildren
|
||||
.Where(i => !LibraryManager.IgnoreFile(i, args.Parent))
|
||||
.ToList();
|
||||
|
||||
if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return null;
|
||||
return FindMovie<MusicVideo>(args.Path, args.Parent, files, args.DirectoryService, collectionType, false);
|
||||
}
|
||||
|
||||
if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return null;
|
||||
return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType, false);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(collectionType))
|
||||
@@ -222,6 +226,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||
// Owned items will be caught by the plain video resolver
|
||||
if (args.Parent == null)
|
||||
{
|
||||
//return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -231,21 +236,13 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||
}
|
||||
|
||||
{
|
||||
var files = args.FileSystemChildren
|
||||
.Where(i => !LibraryManager.IgnoreFile(i, args.Parent))
|
||||
.ToList();
|
||||
|
||||
return FindMovie<Movie>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
|
||||
return FindMovie<Movie>(args.Path, args.Parent, files, args.DirectoryService, collectionType, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var files = args.FileSystemChildren
|
||||
.Where(i => !LibraryManager.IgnoreFile(i, args.Parent))
|
||||
.ToList();
|
||||
|
||||
return FindMovie<Movie>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
|
||||
return FindMovie<Movie>(args.Path, args.Parent, files, args.DirectoryService, collectionType, true);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -360,13 +357,8 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||
/// Finds a movie based on a child file system entries
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <param name="parent">The parent.</param>
|
||||
/// <param name="fileSystemEntries">The file system entries.</param>
|
||||
/// <param name="directoryService">The directory service.</param>
|
||||
/// <param name="collectionType">Type of the collection.</param>
|
||||
/// <returns>Movie.</returns>
|
||||
private T FindMovie<T>(string path, Folder parent, List<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, string collectionType)
|
||||
private T FindMovie<T>(string path, Folder parent, List<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, string collectionType, bool allowFilesAsFolders)
|
||||
where T : Video, new()
|
||||
{
|
||||
var multiDiscFolders = new List<FileSystemMetadata>();
|
||||
@@ -413,23 +405,27 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||
}
|
||||
}
|
||||
|
||||
var supportsMultiVersion = !string.Equals(collectionType, CollectionType.HomeVideos) &&
|
||||
!string.Equals(collectionType, CollectionType.Photos) &&
|
||||
!string.Equals(collectionType, CollectionType.MusicVideos);
|
||||
|
||||
var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, supportsMultiVersion);
|
||||
|
||||
if (result.Items.Count == 1)
|
||||
if (allowFilesAsFolders)
|
||||
{
|
||||
var movie = (T)result.Items[0];
|
||||
movie.IsInMixedFolder = false;
|
||||
movie.Name = Path.GetFileName(movie.ContainingFolderPath);
|
||||
return movie;
|
||||
}
|
||||
// TODO: Allow GetMultiDiscMovie in here
|
||||
var supportsMultiVersion = !string.Equals(collectionType, CollectionType.HomeVideos) &&
|
||||
!string.Equals(collectionType, CollectionType.Photos) &&
|
||||
!string.Equals(collectionType, CollectionType.MusicVideos);
|
||||
|
||||
if (result.Items.Count == 0 && multiDiscFolders.Count > 0)
|
||||
{
|
||||
return GetMultiDiscMovie<T>(multiDiscFolders, directoryService);
|
||||
var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, supportsMultiVersion);
|
||||
|
||||
if (result.Items.Count == 1)
|
||||
{
|
||||
var movie = (T)result.Items[0];
|
||||
movie.IsInMixedFolder = false;
|
||||
movie.Name = Path.GetFileName(movie.ContainingFolderPath);
|
||||
return movie;
|
||||
}
|
||||
|
||||
if (result.Items.Count == 0 && multiDiscFolders.Count > 0)
|
||||
{
|
||||
return GetMultiDiscMovie<T>(multiDiscFolders, directoryService);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -1021,7 +1021,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
||||
{
|
||||
var stream = new MediaSourceInfo
|
||||
{
|
||||
Path = _appHost.GetLocalApiUrl("localhost") + "/LiveTv/LiveRecordings/" + recordingId + "/stream",
|
||||
Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveRecordings/" + recordingId + "/stream",
|
||||
Id = recordingId,
|
||||
SupportsDirectPlay = false,
|
||||
SupportsDirectStream = true,
|
||||
@@ -1854,23 +1854,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
||||
ParentIndexNumber = program.SeasonNumber.Value,
|
||||
IndexNumber = program.EpisodeNumber.Value,
|
||||
AncestorIds = seriesIds,
|
||||
ExcludeLocationTypes = new[] { LocationType.Virtual }
|
||||
});
|
||||
|
||||
if (result.TotalRecordCount > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(program.EpisodeTitle))
|
||||
{
|
||||
var result = _libraryManager.GetItemsResult(new InternalItemsQuery
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(Episode).Name },
|
||||
Name = program.EpisodeTitle,
|
||||
AncestorIds = seriesIds,
|
||||
ExcludeLocationTypes = new[] { LocationType.Virtual }
|
||||
IsVirtualItem = false
|
||||
});
|
||||
|
||||
if (result.TotalRecordCount > 0)
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
||||
{
|
||||
var format = _liveTvOptions.RecordingEncodingFormat;
|
||||
|
||||
if (string.Equals(format, "mkv", StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(format, "mkv", StringComparison.OrdinalIgnoreCase) || _liveTvOptions.EnableOriginalVideoWithEncodedRecordings)
|
||||
{
|
||||
return "mkv";
|
||||
}
|
||||
@@ -204,6 +204,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
||||
|
||||
private bool EncodeVideo(MediaSourceInfo mediaSource)
|
||||
{
|
||||
if (_liveTvOptions.EnableOriginalAudioWithEncodedRecordings)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var mediaStreams = mediaSource.MediaStreams ?? new List<MediaStream>();
|
||||
return !mediaStreams.Any(i => i.Type == MediaStreamType.Video && string.Equals(i.Codec, "h264", StringComparison.OrdinalIgnoreCase) && !i.IsInterlaced);
|
||||
}
|
||||
|
||||
@@ -72,7 +72,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
{
|
||||
dto.ProgramInfo = _dtoService.GetBaseItemDto(program, new DtoOptions());
|
||||
|
||||
dto.ProgramInfo.TimerId = dto.Id;
|
||||
if (info.Status != RecordingStatus.Cancelled && info.Status != RecordingStatus.Error)
|
||||
{
|
||||
dto.ProgramInfo.TimerId = dto.Id;
|
||||
dto.ProgramInfo.Status = info.Status.ToString();
|
||||
}
|
||||
|
||||
dto.ProgramInfo.SeriesTimerId = dto.SeriesTimerId;
|
||||
}
|
||||
|
||||
@@ -877,6 +877,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
SortOrder = query.SortOrder ?? SortOrder.Ascending,
|
||||
EnableTotalRecordCount = query.EnableTotalRecordCount,
|
||||
TopParentIds = new[] { topFolder.Id.ToString("N") },
|
||||
Name = query.Name,
|
||||
DtoOptions = options
|
||||
};
|
||||
|
||||
@@ -1946,7 +1947,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
}
|
||||
else
|
||||
{
|
||||
timers = timers.Where(i => !(i.Item1.Status == RecordingStatus.New));
|
||||
timers = timers.Where(i => i.Item1.Status != RecordingStatus.New);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2304,7 +2305,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
|
||||
var info = await service.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false);
|
||||
|
||||
info.RecordAnyChannel = true;
|
||||
info.RecordAnyTime = true;
|
||||
info.Days = new List<DayOfWeek>
|
||||
{
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
|
||||
try
|
||||
{
|
||||
if (stream.MediaStreams.Any(i => i.Index != -1))
|
||||
if (!stream.SupportsProbing || stream.MediaStreams.Any(i => i.Index != -1))
|
||||
{
|
||||
await AddMediaInfo(stream, isAudio, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||
//OpenedMediaSource.Path = tempFile;
|
||||
//OpenedMediaSource.ReadAtNativeFramerate = true;
|
||||
|
||||
OpenedMediaSource.Path = _appHost.GetLocalApiUrl("localhost") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
|
||||
OpenedMediaSource.Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
|
||||
OpenedMediaSource.Protocol = MediaProtocol.Http;
|
||||
OpenedMediaSource.SupportsDirectPlay = false;
|
||||
OpenedMediaSource.SupportsDirectStream = true;
|
||||
|
||||
@@ -13,6 +13,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CommonIO;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.MediaEncoding;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
@@ -24,12 +25,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
|
||||
{
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
|
||||
public M3UTunerHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient)
|
||||
public M3UTunerHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost)
|
||||
: base(config, logger, jsonSerializer, mediaEncoder)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_httpClient = httpClient;
|
||||
_appHost = appHost;
|
||||
}
|
||||
|
||||
public override string Type
|
||||
@@ -46,7 +49,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
|
||||
|
||||
protected override async Task<IEnumerable<ChannelInfo>> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken)
|
||||
{
|
||||
return await new M3uParser(Logger, _fileSystem, _httpClient).Parse(info.Url, ChannelIdPrefix, info.Id, cancellationToken).ConfigureAwait(false);
|
||||
return await new M3uParser(Logger, _fileSystem, _httpClient, _appHost).Parse(info.Url, ChannelIdPrefix, info.Id, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public Task<List<LiveTvTunerInfo>> GetTunerInfos(CancellationToken cancellationToken)
|
||||
@@ -75,7 +78,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
|
||||
|
||||
public async Task Validate(TunerHostInfo info)
|
||||
{
|
||||
using (var stream = await new M3uParser(Logger, _fileSystem, _httpClient).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false))
|
||||
using (var stream = await new M3uParser(Logger, _fileSystem, _httpClient, _appHost).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Threading.Tasks;
|
||||
using CommonIO;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Model.Logging;
|
||||
|
||||
@@ -18,12 +19,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
|
||||
private readonly ILogger _logger;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
|
||||
public M3uParser(ILogger logger, IFileSystem fileSystem, IHttpClient httpClient)
|
||||
public M3uParser(ILogger logger, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost)
|
||||
{
|
||||
_logger = logger;
|
||||
_fileSystem = fileSystem;
|
||||
_httpClient = httpClient;
|
||||
_appHost = appHost;
|
||||
}
|
||||
|
||||
public async Task<List<M3UChannel>> Parse(string url, string channelIdPrefix, string tunerHostId, CancellationToken cancellationToken)
|
||||
@@ -41,7 +44,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
|
||||
{
|
||||
if (url.StartsWith("http", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return _httpClient.Get(url, cancellationToken);
|
||||
return _httpClient.Get(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
CancellationToken = cancellationToken,
|
||||
// Some data providers will require a user agent
|
||||
UserAgent = _appHost.FriendlyName + "/" + _appHost.ApplicationVersion
|
||||
});
|
||||
}
|
||||
return Task.FromResult(_fileSystem.OpenRead(url));
|
||||
}
|
||||
@@ -111,15 +120,31 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
|
||||
channel.Number = "0";
|
||||
}
|
||||
|
||||
channel.ImageUrl = FindProperty("tvg-logo", extInf, null);
|
||||
channel.Number = FindProperty("channel-id", extInf, channel.Number);
|
||||
channel.Number = FindProperty("tvg-id", extInf, channel.Number);
|
||||
channel.Name = FindProperty("tvg-id", extInf, channel.Name);
|
||||
channel.Name = FindProperty("tvg-name", extInf, channel.Name);
|
||||
channel.ImageUrl = FindProperty("tvg-logo", extInf);
|
||||
|
||||
var name = FindProperty("tvg-name", extInf);
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
name = FindProperty("tvg-id", extInf);
|
||||
}
|
||||
|
||||
channel.Name = name;
|
||||
|
||||
var numberString = FindProperty("tvg-id", extInf);
|
||||
if (string.IsNullOrWhiteSpace(numberString))
|
||||
{
|
||||
numberString = FindProperty("channel-id", extInf);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(numberString))
|
||||
{
|
||||
channel.Number = numberString;
|
||||
}
|
||||
|
||||
return channel;
|
||||
|
||||
}
|
||||
private string FindProperty(string property, string properties, string defaultResult = "")
|
||||
private string FindProperty(string property, string properties)
|
||||
{
|
||||
var reg = new Regex(@"([a-z0-9\-_]+)=\""([^""]+)\""", RegexOptions.IgnoreCase);
|
||||
var matches = reg.Matches(properties);
|
||||
@@ -130,7 +155,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
|
||||
return match.Groups[2].Value;
|
||||
}
|
||||
}
|
||||
return defaultResult;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using CommonIO;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Controller.MediaEncoding;
|
||||
@@ -25,12 +26,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
|
||||
{
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
|
||||
public SatIpHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient)
|
||||
public SatIpHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost)
|
||||
: base(config, logger, jsonSerializer, mediaEncoder)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_httpClient = httpClient;
|
||||
_appHost = appHost;
|
||||
}
|
||||
|
||||
private const string ChannelIdPrefix = "sat_";
|
||||
@@ -39,7 +42,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(tuner.M3UUrl))
|
||||
{
|
||||
return await new M3uParser(Logger, _fileSystem, _httpClient).Parse(tuner.M3UUrl, ChannelIdPrefix, tuner.Id, cancellationToken).ConfigureAwait(false);
|
||||
return await new M3uParser(Logger, _fileSystem, _httpClient, _appHost).Parse(tuner.M3UUrl, ChannelIdPrefix, tuner.Id, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var channels = await new ChannelScan(Logger).Scan(tuner, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -144,7 +144,7 @@ namespace MediaBrowser.Server.Implementations.Photos
|
||||
return ItemUpdateType.None;
|
||||
}
|
||||
|
||||
await ProviderManager.SaveImage(item, outputPath, "image/png", imageType, null, Guid.NewGuid().ToString("N"), cancellationToken).ConfigureAwait(false);
|
||||
await ProviderManager.SaveImage(item, outputPath, "image/png", imageType, null, false, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return ItemUpdateType.ImageUpdate;
|
||||
}
|
||||
|
||||
@@ -22,9 +22,7 @@ namespace MediaBrowser.Server.Implementations.Sorting
|
||||
|
||||
private float GetValue(BaseItem x)
|
||||
{
|
||||
var hasCriticRating = x as IHasCriticRating;
|
||||
|
||||
return hasCriticRating == null ? 0 : hasCriticRating.CriticRating ?? 0;
|
||||
return x.CriticRating ?? 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user