From 371a09c60bddb49298e2cf7f1968514ab4d243e4 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 7 Aug 2020 17:38:01 +0200 Subject: MemoryStream optimizations --- Jellyfin.Api/Controllers/ImageController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Jellyfin.Api/Controllers/ImageController.cs') diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 45447ae0c..8f5c6beb3 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -969,7 +969,7 @@ namespace Jellyfin.Api.Controllers var text = await reader.ReadToEndAsync().ConfigureAwait(false); var bytes = Convert.FromBase64String(text); - return new MemoryStream(bytes) { Position = 0 }; + return new MemoryStream(bytes, 0, bytes.Length, false, true); } private ImageInfo? GetImageInfo(BaseItem item, ItemImageInfo info, int? imageIndex) -- cgit v1.2.3 From 2b400c99ef946ef1e52e3f01cb18bc008a369c59 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 7 Aug 2020 19:26:28 +0200 Subject: Fix warnings --- Emby.Dlna/DlnaManager.cs | 12 +-- Emby.Dlna/PlayTo/Device.cs | 36 ++++--- Emby.Dlna/PlayTo/TransportCommands.cs | 17 ++-- .../Data/SqliteItemRepository.cs | 4 +- .../LiveTv/EmbyTV/EncodedRecorder.cs | 2 +- .../LiveTv/Listings/XmlTvListingsProvider.cs | 5 +- .../LiveTv/LiveTvManager.cs | 106 +++++++++++---------- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 16 ++-- Jellyfin.Api/Controllers/ImageController.cs | 2 +- MediaBrowser.Controller/Entities/Movies/Movie.cs | 4 +- MediaBrowser.Controller/Entities/TV/Series.cs | 2 +- MediaBrowser.Controller/Entities/Trailer.cs | 3 +- MediaBrowser.Controller/Library/Profiler.cs | 17 +++- MediaBrowser.Controller/LiveTv/LiveTvChannel.cs | 2 +- MediaBrowser.Controller/LiveTv/LiveTvProgram.cs | 2 +- .../MediaEncoding/EncodingHelper.cs | 8 +- .../Providers/IProviderManager.cs | 2 +- .../Encoder/EncodingUtils.cs | 9 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 14 +-- .../Subtitles/SubtitleEncoder.cs | 2 +- MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs | 2 +- MediaBrowser.Model/Dlna/DlnaMaps.cs | 8 +- .../Dlna/MediaFormatProfileResolver.cs | 21 ++-- MediaBrowser.Model/Dlna/StreamInfo.cs | 12 +-- MediaBrowser.Providers/Manager/ImageSaver.cs | 4 +- .../Manager/ItemImageProvider.cs | 57 +++++------ MediaBrowser.Providers/Manager/MetadataService.cs | 73 +++++++------- MediaBrowser.Providers/Manager/ProviderManager.cs | 37 +++++-- .../MediaInfo/FFProbeAudioInfo.cs | 15 +-- .../MediaInfo/FFProbeProvider.cs | 21 +--- MediaBrowser.Providers/Music/Extensions.cs | 4 +- .../Plugins/MusicBrainz/AlbumProvider.cs | 2 +- .../Plugins/MusicBrainz/ArtistProvider.cs | 4 +- .../Plugins/Omdb/OmdbImageProvider.cs | 3 +- .../Plugins/Omdb/OmdbItemProvider.cs | 2 +- .../Plugins/Omdb/OmdbProvider.cs | 25 +++-- .../Plugins/TheTvdb/TvdbClientManager.cs | 31 ++---- .../Plugins/TheTvdb/TvdbEpisodeImageProvider.cs | 7 +- .../Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs | 4 +- .../Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs | 2 +- .../Plugins/Tmdb/Movies/TmdbSearch.cs | 54 +++++++++-- .../Plugins/Tmdb/TV/TmdbEpisodeProvider.cs | 2 +- .../Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs | 4 +- .../Plugins/Tmdb/TV/TmdbSeasonProvider.cs | 4 +- .../Plugins/Tmdb/TV/TmdbSeriesProvider.cs | 2 +- .../Studios/StudiosImageProvider.cs | 3 +- 46 files changed, 366 insertions(+), 302 deletions(-) (limited to 'Jellyfin.Api/Controllers/ImageController.cs') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 269f7ee43..ce4be7b51 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -54,11 +54,15 @@ namespace Emby.Dlna _appHost = appHost; } + private string UserProfilesPath => Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "user"); + + private string SystemProfilesPath => Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "system"); + public async Task InitProfilesAsync() { try { - await ExtractSystemProfilesAsync(); + await ExtractSystemProfilesAsync().ConfigureAwait(false); LoadProfiles(); } catch (Exception ex) @@ -240,7 +244,7 @@ namespace Emby.Dlna } else { - var headerString = string.Join(", ", headers.Select(i => string.Format("{0}={1}", i.Key, i.Value)).ToArray()); + var headerString = string.Join(", ", headers.Select(i => string.Format(CultureInfo.InvariantCulture, "{0}={1}", i.Key, i.Value))); _logger.LogDebug("No matching device profile found. {0}", headerString); } @@ -280,10 +284,6 @@ namespace Emby.Dlna return false; } - private string UserProfilesPath => Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "user"); - - private string SystemProfilesPath => Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "system"); - private IEnumerable GetProfiles(string path, DeviceProfileType type) { try diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 72834c69d..86dd52a1b 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -19,6 +19,8 @@ namespace Emby.Dlna.PlayTo { public class Device : IDisposable { + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + private Timer _timer; public DeviceInfo Properties { get; set; } @@ -55,16 +57,13 @@ namespace Emby.Dlna.PlayTo private readonly ILogger _logger; - private readonly IServerConfigurationManager _config; - public Action OnDeviceUnavailable { get; set; } - public Device(DeviceInfo deviceProperties, IHttpClient httpClient, ILogger logger, IServerConfigurationManager config) + public Device(DeviceInfo deviceProperties, IHttpClient httpClient, ILogger logger) { Properties = deviceProperties; _httpClient = httpClient; _logger = logger; - _config = config; } public void Start() @@ -275,7 +274,7 @@ namespace Emby.Dlna.PlayTo throw new InvalidOperationException("Unable to find service"); } - await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, string.Format("{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME")) + await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, string.Format(CultureInfo.InvariantCulture, "{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME")) .ConfigureAwait(false); RestartTimer(true); @@ -285,7 +284,7 @@ namespace Emby.Dlna.PlayTo { var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false); - url = url.Replace("&", "&"); + url = url.Replace("&", "&", StringComparison.Ordinal); _logger.LogDebug("{0} - SetAvTransport Uri: {1} DlnaHeaders: {2}", Properties.Name, url, header); @@ -297,8 +296,8 @@ namespace Emby.Dlna.PlayTo var dictionary = new Dictionary { - {"CurrentURI", url}, - {"CurrentURIMetaData", CreateDidlMeta(metaData)} + { "CurrentURI", url }, + { "CurrentURIMetaData", CreateDidlMeta(metaData) } }; var service = GetAvTransportService(); @@ -732,10 +731,10 @@ namespace Emby.Dlna.PlayTo } var trackUriElem = result.Document.Descendants(uPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackURI")).FirstOrDefault(i => i != null); - var trackUri = trackUriElem == null ? null : trackUriElem.Value; + var trackUri = trackUriElem?.Value; var durationElem = result.Document.Descendants(uPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackDuration")).FirstOrDefault(i => i != null); - var duration = durationElem == null ? null : durationElem.Value; + var duration = durationElem?.Value; if (!string.IsNullOrWhiteSpace(duration) && !string.Equals(duration, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase)) @@ -748,7 +747,7 @@ namespace Emby.Dlna.PlayTo } var positionElem = result.Document.Descendants(uPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("RelTime")).FirstOrDefault(i => i != null); - var position = positionElem == null ? null : positionElem.Value; + var position = positionElem?.Value; if (!string.IsNullOrWhiteSpace(position) && !string.Equals(position, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase)) { @@ -819,7 +818,7 @@ namespace Emby.Dlna.PlayTo // some devices send back invalid xml try { - return XElement.Parse(xml.Replace("&", "&")); + return XElement.Parse(xml.Replace("&", "&", StringComparison.Ordinal)); } catch (XmlException) { @@ -848,7 +847,7 @@ namespace Emby.Dlna.PlayTo ParentId = container.GetAttributeValue(uPnpNamespaces.ParentId), Title = container.GetValue(uPnpNamespaces.title), IconUrl = container.GetValue(uPnpNamespaces.Artwork), - SecondText = "", + SecondText = string.Empty, Url = url, ProtocolInfo = GetProtocolInfo(container), MetaData = container.ToString() @@ -941,12 +940,12 @@ namespace Emby.Dlna.PlayTo return url; } - if (!url.Contains("/")) + if (!url.Contains('/', StringComparison.Ordinal)) { url = "/dmr/" + url; } - if (!url.StartsWith("/")) + if (!url.StartsWith("/", StringComparison.Ordinal)) { url = "/" + url; } @@ -981,7 +980,7 @@ namespace Emby.Dlna.PlayTo var deviceProperties = new DeviceInfo() { Name = string.Join(" ", friendlyNames), - BaseUrl = string.Format("http://{0}:{1}", url.Host, url.Port) + BaseUrl = string.Format(CultureInfo.InvariantCulture, "http://{0}:{1}", url.Host, url.Port) }; var model = document.Descendants(uPnpNamespaces.ud.GetName("modelName")).FirstOrDefault(); @@ -1068,10 +1067,9 @@ namespace Emby.Dlna.PlayTo } } - return new Device(deviceProperties, httpClient, logger, config); + return new Device(deviceProperties, httpClient, logger); } - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); private static DeviceIcon CreateIcon(XElement element) { if (element == null) @@ -1222,7 +1220,7 @@ namespace Emby.Dlna.PlayTo public override string ToString() { - return string.Format("{0} - {1}", Properties.Name, Properties.BaseUrl); + return string.Format(CultureInfo.InvariantCulture, "{0} - {1}", Properties.Name, Properties.BaseUrl); } } } diff --git a/Emby.Dlna/PlayTo/TransportCommands.cs b/Emby.Dlna/PlayTo/TransportCommands.cs index c0ce3ab6e..dc797a691 100644 --- a/Emby.Dlna/PlayTo/TransportCommands.cs +++ b/Emby.Dlna/PlayTo/TransportCommands.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Xml.Linq; using Emby.Dlna.Common; @@ -11,14 +12,16 @@ namespace Emby.Dlna.PlayTo { public class TransportCommands { + private const string CommandBase = "\r\n" + "" + "" + "" + "{2}" + "" + ""; private List _stateVariables = new List(); + private List _serviceActions = new List(); + public List StateVariables { get => _stateVariables; set => _stateVariables = value; } - private List _serviceActions = new List(); public List ServiceActions { get => _serviceActions; @@ -123,7 +126,7 @@ namespace Emby.Dlna.PlayTo } } - return string.Format(CommandBase, action.Name, xmlNamespace, stateString); + return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamespace, stateString); } public string BuildPost(ServiceAction action, string xmlNamesapce, object value, string commandParameter = "") @@ -147,7 +150,7 @@ namespace Emby.Dlna.PlayTo } } - return string.Format(CommandBase, action.Name, xmlNamesapce, stateString); + return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamesapce, stateString); } public string BuildPost(ServiceAction action, string xmlNamesapce, object value, Dictionary dictionary) @@ -170,7 +173,7 @@ namespace Emby.Dlna.PlayTo } } - return string.Format(CommandBase, action.Name, xmlNamesapce, stateString); + return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamesapce, stateString); } private string BuildArgumentXml(Argument argument, string value, string commandParameter = "") @@ -183,12 +186,10 @@ namespace Emby.Dlna.PlayTo state.AllowedValues.FirstOrDefault() ?? value; - return string.Format("<{0} xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"{1}\">{2}", argument.Name, state.DataType ?? "string", sendValue); + return string.Format(CultureInfo.InvariantCulture, "<{0} xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"{1}\">{2}", argument.Name, state.DataType ?? "string", sendValue); } - return string.Format("<{0}>{1}", argument.Name, value); + return string.Format(CultureInfo.InvariantCulture, "<{0}>{1}", argument.Name, value); } - - private const string CommandBase = "\r\n" + "" + "" + "" + "{2}" + "" + ""; } } diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index d11e5e62e..331ffc134 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -4560,13 +4560,13 @@ namespace Emby.Server.Implementations.Data if (query.AncestorIds.Length > 1) { var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + i.ToString("N", CultureInfo.InvariantCulture) + "'")); - whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorIdText in ({0}))", inClause)); + whereClauses.Add(string.Format(CultureInfo.InvariantCulture, "Guid in (select itemId from AncestorIds where AncestorIdText in ({0}))", inClause)); } if (!string.IsNullOrWhiteSpace(query.AncestorWithPresentationUniqueKey)) { var inClause = "select guid from TypedBaseItems where PresentationUniqueKey=@AncestorWithPresentationUniqueKey"; - whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorId in ({0}))", inClause)); + whereClauses.Add(string.Format(CultureInfo.InvariantCulture, "Guid in (select itemId from AncestorIds where AncestorId in ({0}))", inClause)); if (statement != null) { statement.TryBind("@AncestorWithPresentationUniqueKey", query.AncestorWithPresentationUniqueKey); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index d8ec107ec..612dc5238 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -230,7 +230,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (filters.Count > 0) { - output += string.Format(" -vf \"{0}\"", string.Join(",", filters.ToArray())); + output += string.Format(CultureInfo.InvariantCulture, " -vf \"{0}\"", string.Join(",", filters.ToArray())); } return output; diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 0a93c4674..f33d07174 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -237,7 +237,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings && !programInfo.IsRepeat && (programInfo.EpisodeNumber ?? 0) == 0) { - programInfo.ShowId = programInfo.ShowId + programInfo.StartDate.Ticks.ToString(CultureInfo.InvariantCulture); + programInfo.ShowId += programInfo.StartDate.Ticks.ToString(CultureInfo.InvariantCulture); } } else @@ -246,7 +246,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings } // Construct an id from the channel and start date - programInfo.Id = string.Format("{0}_{1:O}", program.ChannelId, program.StartDate); + programInfo.Id = string.Format(CultureInfo.InvariantCulture, "{0}_{1:O}", program.ChannelId, program.StartDate); if (programInfo.IsMovie) { @@ -296,7 +296,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings Name = c.DisplayName, ImageUrl = c.Icon != null && !string.IsNullOrEmpty(c.Icon.Source) ? c.Icon.Source : null, Number = string.IsNullOrWhiteSpace(c.Number) ? c.Id : c.Number - }).ToList(); } } diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 1b075d86a..90cbd85a5 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -41,6 +41,7 @@ namespace Emby.Server.Implementations.LiveTv /// public class LiveTvManager : ILiveTvManager, IDisposable { + private const int MaxGuideDays = 14; private const string ExternalServiceTag = "ExternalServiceId"; private const string EtagKey = "ProgramEtag"; @@ -560,7 +561,7 @@ namespace Emby.Server.Implementations.LiveTv item.Audio = info.Audio; item.ChannelId = channel.Id; - item.CommunityRating = item.CommunityRating ?? info.CommunityRating; + item.CommunityRating ??= info.CommunityRating; if ((item.CommunityRating ?? 0).Equals(0)) { item.CommunityRating = null; @@ -645,8 +646,8 @@ namespace Emby.Server.Implementations.LiveTv item.IsSeries = isSeries; item.Name = info.Name; - item.OfficialRating = item.OfficialRating ?? info.OfficialRating; - item.Overview = item.Overview ?? info.Overview; + item.OfficialRating ??= info.OfficialRating; + item.Overview ??= info.Overview; item.RunTimeTicks = (info.EndDate - info.StartDate).Ticks; item.ProviderIds = info.ProviderIds; @@ -683,19 +684,23 @@ namespace Emby.Server.Implementations.LiveTv { if (!string.IsNullOrWhiteSpace(info.ImagePath)) { - item.SetImage(new ItemImageInfo - { - Path = info.ImagePath, - Type = ImageType.Primary - }, 0); + item.SetImage( + new ItemImageInfo + { + Path = info.ImagePath, + Type = ImageType.Primary + }, + 0); } else if (!string.IsNullOrWhiteSpace(info.ImageUrl)) { - item.SetImage(new ItemImageInfo - { - Path = info.ImageUrl, - Type = ImageType.Primary - }, 0); + item.SetImage( + new ItemImageInfo + { + Path = info.ImageUrl, + Type = ImageType.Primary + }, + 0); } } @@ -703,11 +708,13 @@ namespace Emby.Server.Implementations.LiveTv { if (!string.IsNullOrWhiteSpace(info.ThumbImageUrl)) { - item.SetImage(new ItemImageInfo - { - Path = info.ThumbImageUrl, - Type = ImageType.Thumb - }, 0); + item.SetImage( + new ItemImageInfo + { + Path = info.ThumbImageUrl, + Type = ImageType.Thumb + }, + 0); } } @@ -715,11 +722,13 @@ namespace Emby.Server.Implementations.LiveTv { if (!string.IsNullOrWhiteSpace(info.LogoImageUrl)) { - item.SetImage(new ItemImageInfo - { - Path = info.LogoImageUrl, - Type = ImageType.Logo - }, 0); + item.SetImage( + new ItemImageInfo + { + Path = info.LogoImageUrl, + Type = ImageType.Logo + }, + 0); } } @@ -727,11 +736,13 @@ namespace Emby.Server.Implementations.LiveTv { if (!string.IsNullOrWhiteSpace(info.BackdropImageUrl)) { - item.SetImage(new ItemImageInfo - { - Path = info.BackdropImageUrl, - Type = ImageType.Backdrop - }, 0); + item.SetImage( + new ItemImageInfo + { + Path = info.BackdropImageUrl, + Type = ImageType.Backdrop + }, + 0); } } @@ -786,7 +797,6 @@ namespace Emby.Server.Implementations.LiveTv if (query.OrderBy.Count == 0) { - // Unless something else was specified, order by start date to take advantage of a specialized index query.OrderBy = new[] { @@ -824,7 +834,7 @@ namespace Emby.Server.Implementations.LiveTv if (!string.IsNullOrWhiteSpace(query.SeriesTimerId)) { - var seriesTimers = await GetSeriesTimersInternal(new SeriesTimerQuery { }, cancellationToken).ConfigureAwait(false); + var seriesTimers = await GetSeriesTimersInternal(new SeriesTimerQuery(), cancellationToken).ConfigureAwait(false); var seriesTimer = seriesTimers.Items.FirstOrDefault(i => string.Equals(_tvDtoService.GetInternalSeriesTimerId(i.Id).ToString("N", CultureInfo.InvariantCulture), query.SeriesTimerId, StringComparison.OrdinalIgnoreCase)); if (seriesTimer != null) { @@ -847,13 +857,11 @@ namespace Emby.Server.Implementations.LiveTv var returnArray = _dtoService.GetBaseItemDtos(queryResult.Items, options, user); - var result = new QueryResult + return new QueryResult { Items = returnArray, TotalRecordCount = queryResult.TotalRecordCount }; - - return result; } public QueryResult GetRecommendedProgramsInternal(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken) @@ -1173,7 +1181,6 @@ namespace Emby.Server.Implementations.LiveTv var existingPrograms = _libraryManager.GetItemList(new InternalItemsQuery { - IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name }, ChannelIds = new Guid[] { currentChannel.Id }, DtoOptions = new DtoOptions(true) @@ -1298,8 +1305,6 @@ namespace Emby.Server.Implementations.LiveTv } } - private const int MaxGuideDays = 14; - private double GetGuideDays() { var config = GetConfiguration(); @@ -1712,7 +1717,7 @@ namespace Emby.Server.Implementations.LiveTv if (timer == null) { - throw new ResourceNotFoundException(string.Format("Timer with Id {0} not found", id)); + throw new ResourceNotFoundException(string.Format(CultureInfo.InvariantCulture, "Timer with Id {0} not found", id)); } var service = GetService(timer.ServiceName); @@ -1731,7 +1736,7 @@ namespace Emby.Server.Implementations.LiveTv if (timer == null) { - throw new ResourceNotFoundException(string.Format("SeriesTimer with Id {0} not found", id)); + throw new ResourceNotFoundException(string.Format(CultureInfo.InvariantCulture, "SeriesTimer with Id {0} not found", id)); } var service = GetService(timer.ServiceName); @@ -1743,10 +1748,12 @@ namespace Emby.Server.Implementations.LiveTv public async Task GetTimer(string id, CancellationToken cancellationToken) { - var results = await GetTimers(new TimerQuery - { - Id = id - }, cancellationToken).ConfigureAwait(false); + var results = await GetTimers( + new TimerQuery + { + Id = id + }, + cancellationToken).ConfigureAwait(false); return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase)); } @@ -1794,10 +1801,7 @@ namespace Emby.Server.Implementations.LiveTv } var returnArray = timers - .Select(i => - { - return i.Item1; - }) + .Select(i => i.Item1) .ToArray(); return new QueryResult @@ -1968,7 +1972,7 @@ namespace Emby.Server.Implementations.LiveTv if (service == null) { - service = _services.First(); + service = _services[0]; } var info = await service.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false); @@ -1994,9 +1998,7 @@ namespace Emby.Server.Implementations.LiveTv { var info = await GetNewTimerDefaultsInternal(cancellationToken).ConfigureAwait(false); - var obj = _tvDtoService.GetSeriesTimerInfoDto(info.Item1, info.Item2, null); - - return obj; + return _tvDtoService.GetSeriesTimerInfoDto(info.Item1, info.Item2, null); } public async Task GetNewTimerDefaults(string programId, CancellationToken cancellationToken) @@ -2125,6 +2127,7 @@ namespace Emby.Server.Implementations.LiveTv public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } private bool _disposed = false; @@ -2447,8 +2450,7 @@ namespace Emby.Server.Implementations.LiveTv .SelectMany(i => i.Locations) .Distinct(StringComparer.OrdinalIgnoreCase) .Select(i => _libraryManager.FindByPath(i, true)) - .Where(i => i != null) - .Where(i => i.IsVisibleStandalone(user)) + .Where(i => i != null && i.IsVisibleStandalone(user)) .SelectMany(i => _libraryManager.GetCollectionFolders(i)) .GroupBy(x => x.Id) .Select(x => x.First()) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index c61189c0a..f1e120a64 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -182,12 +182,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); - using (var response = await _httpClient.SendAsync(new HttpRequestOptions() - { - Url = string.Format("{0}/tuners.html", GetApiUrl(info)), - CancellationToken = cancellationToken, - BufferContent = false - }, HttpMethod.Get).ConfigureAwait(false)) + using (var response = await _httpClient.SendAsync( + new HttpRequestOptions() + { + Url = string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), + CancellationToken = cancellationToken, + BufferContent = false + }, + HttpMethod.Get).ConfigureAwait(false)) using (var stream = response.Content) using (var sr = new StreamReader(stream, System.Text.Encoding.UTF8)) { @@ -730,7 +732,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun // Need a way to set the Receive timeout on the socket otherwise this might never timeout? try { - await udpClient.SendToAsync(discBytes, 0, discBytes.Length, new IPEndPoint(IPAddress.Parse("255.255.255.255"), 65001), cancellationToken); + await udpClient.SendToAsync(discBytes, 0, discBytes.Length, new IPEndPoint(IPAddress.Parse("255.255.255.255"), 65001), cancellationToken).ConfigureAwait(false); var receiveBuffer = new byte[8192]; while (!cancellationToken.IsCancellationRequested) diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 8f5c6beb3..75734f0af 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -113,7 +113,7 @@ namespace Jellyfin.Api.Controllers user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + MimeTypes.ToExtension(mimeType))); await _providerManager - .SaveImage(user, memoryStream, mimeType, user.ProfileImage.Path) + .SaveImage(memoryStream, mimeType, user.ProfileImage.Path) .ConfigureAwait(false); await _userManager.UpdateUserAsync(user).ConfigureAwait(false); diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 53badac4d..5ae396e68 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -1,5 +1,7 @@ + using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text.Json.Serialization; using System.Threading; @@ -179,7 +181,7 @@ namespace MediaBrowser.Controller.Entities.Movies list.Add(new ExternalUrl { Name = "Trakt", - Url = string.Format("https://trakt.tv/movies/{0}", imdbId) + Url = string.Format(CultureInfo.InvariantCulture, "https://trakt.tv/movies/{0}", imdbId) }); } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 45daa8a53..23d960092 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -496,7 +496,7 @@ namespace MediaBrowser.Controller.Entities.TV list.Add(new ExternalUrl { Name = "Trakt", - Url = string.Format("https://trakt.tv/shows/{0}", imdbId) + Url = string.Format(CultureInfo.InvariantCulture, "https://trakt.tv/shows/{0}", imdbId) }); } diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index 6b544afc6..83e9ce1e7 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Text.Json.Serialization; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Providers; @@ -86,7 +87,7 @@ namespace MediaBrowser.Controller.Entities list.Add(new ExternalUrl { Name = "Trakt", - Url = string.Format("https://trakt.tv/movies/{0}", imdbId) + Url = string.Format(CultureInfo.InvariantCulture, "https://trakt.tv/movies/{0}", imdbId) }); } diff --git a/MediaBrowser.Controller/Library/Profiler.cs b/MediaBrowser.Controller/Library/Profiler.cs index 399378a09..5efdc6a48 100644 --- a/MediaBrowser.Controller/Library/Profiler.cs +++ b/MediaBrowser.Controller/Library/Profiler.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Globalization; using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Library @@ -13,6 +14,7 @@ namespace MediaBrowser.Controller.Library /// The name. /// readonly string _name; + /// /// The stopwatch. /// @@ -44,6 +46,7 @@ namespace MediaBrowser.Controller.Library public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } /// @@ -58,13 +61,19 @@ namespace MediaBrowser.Controller.Library string message; if (_stopwatch.ElapsedMilliseconds > 300000) { - message = string.Format("{0} took {1} minutes.", - _name, ((float)_stopwatch.ElapsedMilliseconds / 60000).ToString("F")); + message = string.Format( + CultureInfo.InvariantCulture, + "{0} took {1} minutes.", + _name, + ((float)_stopwatch.ElapsedMilliseconds / 60000).ToString("F", CultureInfo.InvariantCulture)); } else { - message = string.Format("{0} took {1} seconds.", - _name, ((float)_stopwatch.ElapsedMilliseconds / 1000).ToString("#0.000")); + message = string.Format( + CultureInfo.InvariantCulture, + "{0} took {1} seconds.", + _name, + ((float)_stopwatch.ElapsedMilliseconds / 1000).ToString("#0.000", CultureInfo.InvariantCulture)); } _logger.LogInformation(message); diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index 10af98121..aa7c12dd1 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -63,7 +63,7 @@ namespace MediaBrowser.Controller.LiveTv if (double.TryParse(Number, NumberStyles.Any, CultureInfo.InvariantCulture, out number)) { - return string.Format("{0:00000.0}", number) + "-" + (Name ?? string.Empty); + return string.Format(CultureInfo.InvariantCulture, "{0:00000.0}", number) + "-" + (Name ?? string.Empty); } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 472b061e6..e1de01ff0 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -261,7 +261,7 @@ namespace MediaBrowser.Controller.LiveTv list.Add(new ExternalUrl { Name = "Trakt", - Url = string.Format("https://trakt.tv/movies/{0}", imdbId) + Url = string.Format(CultureInfo.InvariantCulture, "https://trakt.tv/movies/{0}", imdbId) }); } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 2dd21be3c..7b09f489e 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -675,7 +675,7 @@ namespace MediaBrowser.Controller.MediaEncoding // } // } - // fallbackFontParam = string.Format(":force_style='FontName=Droid Sans Fallback':fontsdir='{0}'", _mediaEncoder.EscapeSubtitleFilterPath(_fileSystem.GetDirectoryName(fallbackFontPath))); + // fallbackFontParam = string.Format(CultureInfo.InvariantCulture, ":force_style='FontName=Droid Sans Fallback':fontsdir='{0}'", _mediaEncoder.EscapeSubtitleFilterPath(_fileSystem.GetDirectoryName(fallbackFontPath))); if (state.SubtitleStream.IsExternal) { @@ -880,7 +880,7 @@ namespace MediaBrowser.Controller.MediaEncoding profileScore = Math.Min(profileScore, 2); // http://www.webmproject.org/docs/encoder-parameters/ - param += string.Format("-speed 16 -quality good -profile:v {0} -slices 8 -crf {1} -qmin {2} -qmax {3}", + param += string.Format(CultureInfo.InvariantCulture, "-speed 16 -quality good -profile:v {0} -slices 8 -crf {1} -qmin {2} -qmax {3}", profileScore.ToString(_usCulture), crf, qmin, @@ -904,7 +904,7 @@ namespace MediaBrowser.Controller.MediaEncoding var framerate = GetFramerateParam(state); if (framerate.HasValue) { - param += string.Format(" -r {0}", framerate.Value.ToString(_usCulture)); + param += string.Format(CultureInfo.InvariantCulture, " -r {0}", framerate.Value.ToString(_usCulture)); } var targetVideoCodec = state.ActualOutputVideoCodec; @@ -1484,7 +1484,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (time > 0) { - return string.Format("-ss {0}", _mediaEncoder.GetTimeParameter(time)); + return string.Format(CultureInfo.InvariantCulture, "-ss {0}", _mediaEncoder.GetTimeParameter(time)); } return string.Empty; diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 8ba01d773..c77349d01 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -72,7 +72,7 @@ namespace MediaBrowser.Controller.Providers /// Task. Task SaveImage(BaseItem item, string source, string mimeType, ImageType type, int? imageIndex, bool? saveLocallyWithMedia, CancellationToken cancellationToken); - Task SaveImage(User user, Stream source, string mimeType, string path); + Task SaveImage(Stream source, string mimeType, string path); /// /// Adds the metadata providers. diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs index 7c2d9f1fd..082ae2888 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System.Collections.Generic; +using System.Globalization; using System.Linq; using MediaBrowser.Model.MediaInfo; @@ -14,7 +15,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { var url = inputFiles[0]; - return string.Format("\"{0}\"", url); + return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", url); } return GetConcatInputArgument(inputFiles); @@ -33,7 +34,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { var files = string.Join("|", inputFiles.Select(NormalizePath)); - return string.Format("concat:\"{0}\"", files); + return string.Format(CultureInfo.InvariantCulture, "concat:\"{0}\"", files); } // Determine the input path for video files @@ -49,13 +50,13 @@ namespace MediaBrowser.MediaEncoding.Encoder { if (path.IndexOf("://") != -1) { - return string.Format("\"{0}\"", path); + return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", path); } // Quotes are valid path characters in linux and they need to be escaped here with a leading \ path = NormalizePath(path); - return string.Format("file:\"{0}\"", path); + return string.Format(CultureInfo.InvariantCulture, "file:\"{0}\"", path); } /// diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 778c0b18c..b9a6432ad 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -552,8 +552,8 @@ namespace MediaBrowser.MediaEncoding.Encoder // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. var thumbnail = enableThumbnail ? ",thumbnail=24" : string.Empty; - var args = useIFrame ? string.Format("-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}{4}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, thumbnail) : - string.Format("-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg); + var args = useIFrame ? string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}{4}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, thumbnail) : + string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg); var probeSizeArgument = EncodingHelper.GetProbeSizeArgument(1); var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1); @@ -570,7 +570,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (offset.HasValue) { - args = string.Format("-ss {0} ", GetTimeParameter(offset.Value)) + args; + args = string.Format(CultureInfo.InvariantCulture, "-ss {0} ", GetTimeParameter(offset.Value)) + args; } if (videoStream != null) @@ -641,7 +641,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (exitCode == -1 || !file.Exists || file.Length == 0) { - var msg = string.Format("ffmpeg image extraction failed for {0}", inputPath); + var msg = string.Format(CultureInfo.InvariantCulture, "ffmpeg image extraction failed for {0}", inputPath); _logger.LogError(msg); @@ -684,13 +684,13 @@ namespace MediaBrowser.MediaEncoding.Encoder { var maxWidthParam = maxWidth.Value.ToString(_usCulture); - vf += string.Format(",scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam); + vf += string.Format(CultureInfo.InvariantCulture, ",scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam); } Directory.CreateDirectory(targetDirectory); var outputPath = Path.Combine(targetDirectory, filenamePrefix + "%05d.jpg"); - var args = string.Format("-i {0} -threads 0 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf); + var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads 0 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf); var probeSizeArgument = EncodingHelper.GetProbeSizeArgument(1); var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1); @@ -790,7 +790,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (exitCode == -1) { - var msg = string.Format("ffmpeg image extraction failed for {0}", inputArgument); + var msg = string.Format(CultureInfo.InvariantCulture, "ffmpeg image extraction failed for {0}", inputArgument); _logger.LogError(msg); diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 374e35b96..fbe8bd69f 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -435,7 +435,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles CreateNoWindow = true, UseShellExecute = false, FileName = _mediaEncoder.EncoderPath, - Arguments = string.Format("{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), + Arguments = string.Format(CultureInfo.InvariantCulture, "{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false }, diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs index a579f8464..93e60753a 100644 --- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs +++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs @@ -157,7 +157,7 @@ namespace MediaBrowser.Model.Dlna // flagValue = flagValue | DlnaFlags.TimeBasedSeek; //} - string dlnaflags = string.Format(";DLNA.ORG_FLAGS={0}", + string dlnaflags = string.Format(CultureInfo.InvariantCulture, ";DLNA.ORG_FLAGS={0}", DlnaMaps.FlagsToString(flagValue)); ResponseProfile mediaProfile = _profile.GetVideoMediaProfile(container, diff --git a/MediaBrowser.Model/Dlna/DlnaMaps.cs b/MediaBrowser.Model/Dlna/DlnaMaps.cs index 052b4b78b..95cd0ac27 100644 --- a/MediaBrowser.Model/Dlna/DlnaMaps.cs +++ b/MediaBrowser.Model/Dlna/DlnaMaps.cs @@ -1,18 +1,20 @@ #pragma warning disable CS1591 +using System.Globalization; + namespace MediaBrowser.Model.Dlna { public static class DlnaMaps { private static readonly string DefaultStreaming = - FlagsToString(DlnaFlags.StreamingTransferMode | + FlagsToString(DlnaFlags.StreamingTransferMode | DlnaFlags.BackgroundTransferMode | DlnaFlags.ConnectionStall | DlnaFlags.ByteBasedSeek | DlnaFlags.DlnaV15); private static readonly string DefaultInteractive = - FlagsToString(DlnaFlags.InteractiveTransferMode | + FlagsToString(DlnaFlags.InteractiveTransferMode | DlnaFlags.BackgroundTransferMode | DlnaFlags.ConnectionStall | DlnaFlags.ByteBasedSeek | @@ -20,7 +22,7 @@ namespace MediaBrowser.Model.Dlna public static string FlagsToString(DlnaFlags flags) { - return string.Format("{0:X8}{1:D24}", (ulong)flags, 0); + return string.Format(CultureInfo.InvariantCulture, "{0:X8}{1:D24}", (ulong)flags, 0); } public static string GetOrgOpValue(bool hasKnownRuntime, bool isDirectStream, TranscodeSeekInfo profileTranscodeSeekInfo) diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs index bdc5f8bb7..3c955989a 100644 --- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs +++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using MediaBrowser.Model.MediaInfo; @@ -142,26 +143,26 @@ namespace MediaBrowser.Model.Dlna { if (timestampType == TransportStreamTimestamp.None) { - return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_HP_{0}D_MPEG1_L2_ISO", resolution)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "AVC_TS_HP_{0}D_MPEG1_L2_ISO", resolution)) }; } - return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_HP_{0}D_MPEG1_L2_T", resolution)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "AVC_TS_HP_{0}D_MPEG1_L2_T", resolution)) }; } if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase)) { - return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_MP_{0}D_AAC_MULT5{1}", resolution, suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "AVC_TS_MP_{0}D_AAC_MULT5{1}", resolution, suffix)) }; } if (string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase)) { - return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_MP_{0}D_MPEG1_L3{1}", resolution, suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "AVC_TS_MP_{0}D_MPEG1_L3{1}", resolution, suffix)) }; } if (string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase)) { - return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_MP_{0}D_AC3{1}", resolution, suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "AVC_TS_MP_{0}D_AC3{1}", resolution, suffix)) }; } } else if (string.Equals(videoCodec, "vc1", StringComparison.OrdinalIgnoreCase)) @@ -180,29 +181,29 @@ namespace MediaBrowser.Model.Dlna { suffix = string.Equals(suffix, "_ISO", StringComparison.OrdinalIgnoreCase) ? suffix : "_T"; - return new MediaFormatProfile[] { ValueOf(string.Format("VC1_TS_HD_DTS{0}", suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "VC1_TS_HD_DTS{0}", suffix)) }; } } else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase) || string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) { if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase)) { - return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_AAC{0}", suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "MPEG4_P2_TS_ASP_AAC{0}", suffix)) }; } if (string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase)) { - return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_MPEG1_L3{0}", suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "MPEG4_P2_TS_ASP_MPEG1_L3{0}", suffix)) }; } if (string.Equals(audioCodec, "mp2", StringComparison.OrdinalIgnoreCase)) { - return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_MPEG2_L2{0}", suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "MPEG4_P2_TS_ASP_MPEG2_L2{0}", suffix)) }; } if (string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase)) { - return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_AC3{0}", suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "MPEG4_P2_TS_ASP_AC3{0}", suffix)) }; } } diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 204340c46..94d53ab70 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -191,7 +191,7 @@ namespace MediaBrowser.Model.Dlna var encodedValue = pair.Value.Replace(" ", "%20"); - list.Add(string.Format("{0}={1}", pair.Name, encodedValue)); + list.Add(string.Format(CultureInfo.InvariantCulture, "{0}={1}", pair.Name, encodedValue)); } string queryString = string.Join("&", list.ToArray()); @@ -214,18 +214,18 @@ namespace MediaBrowser.Model.Dlna { if (string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) { - return string.Format("{0}/audio/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); + return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); } - return string.Format("{0}/audio/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); + return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); } if (string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) { - return string.Format("{0}/videos/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); + return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); } - return string.Format("{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); + return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); } private static List BuildParams(StreamInfo item, string accessToken) @@ -457,7 +457,7 @@ namespace MediaBrowser.Model.Dlna { if (MediaSource.Protocol == MediaProtocol.File || !string.Equals(stream.Codec, subtitleProfile.Format, StringComparison.OrdinalIgnoreCase) || !stream.IsExternal) { - info.Url = string.Format("{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}", + info.Url = string.Format(CultureInfo.InvariantCulture, "{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}", baseUrl, ItemId, MediaSourceId, diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 26b50784b..413d297cb 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -187,7 +187,7 @@ namespace MediaBrowser.Providers.Manager } } - public async Task SaveImage(User user, Stream source, string path) + public async Task SaveImage(Stream source, string path) { await SaveImageToLocation(source, path, path, CancellationToken.None).ConfigureAwait(false); } @@ -355,7 +355,7 @@ namespace MediaBrowser.Providers.Manager if (string.IsNullOrWhiteSpace(extension)) { - throw new ArgumentException(string.Format("Unable to determine image file extension from mime type {0}", mimeType)); + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Unable to determine image file extension from mime type {0}", mimeType)); } if (type == ImageType.Thumb && saveLocally) diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index a5eb095c4..9227b6d93 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -54,7 +54,12 @@ namespace MediaBrowser.Providers.Manager return hasChanges; } - public async Task RefreshImages(BaseItem item, LibraryOptions libraryOptions, List providers, ImageRefreshOptions refreshOptions, MetadataOptions savedOptions, CancellationToken cancellationToken) + public async Task RefreshImages( + BaseItem item, + LibraryOptions libraryOptions, + List providers, + ImageRefreshOptions refreshOptions, + CancellationToken cancellationToken) { if (refreshOptions.IsReplacingImage(ImageType.Backdrop)) { @@ -78,19 +83,15 @@ namespace MediaBrowser.Providers.Manager foreach (var provider in providers) { - var remoteProvider = provider as IRemoteImageProvider; - - if (remoteProvider != null) + if (provider is IRemoteImageProvider remoteProvider) { await RefreshFromProvider(item, libraryOptions, remoteProvider, refreshOptions, typeOptions, backdropLimit, screenshotLimit, downloadedImages, result, cancellationToken).ConfigureAwait(false); continue; } - var dynamicImageProvider = provider as IDynamicImageProvider; - - if (dynamicImageProvider != null) + if (provider is IDynamicImageProvider dynamicImageProvider) { - await RefreshFromProvider(item, dynamicImageProvider, refreshOptions, typeOptions, libraryOptions, downloadedImages, result, cancellationToken).ConfigureAwait(false); + await RefreshFromProvider(item, dynamicImageProvider, refreshOptions, typeOptions, downloadedImages, result, cancellationToken).ConfigureAwait(false); } } @@ -100,11 +101,11 @@ namespace MediaBrowser.Providers.Manager /// /// Refreshes from provider. /// - private async Task RefreshFromProvider(BaseItem item, + private async Task RefreshFromProvider( + BaseItem item, IDynamicImageProvider provider, ImageRefreshOptions refreshOptions, TypeOptions savedOptions, - LibraryOptions libraryOptions, ICollection downloadedImages, RefreshResult result, CancellationToken cancellationToken) @@ -115,7 +116,7 @@ namespace MediaBrowser.Providers.Manager foreach (var imageType in images) { - if (!IsEnabled(savedOptions, imageType, item)) + if (!IsEnabled(savedOptions, imageType)) { continue; } @@ -133,12 +134,13 @@ namespace MediaBrowser.Providers.Manager if (response.Protocol == MediaProtocol.Http) { _logger.LogDebug("Setting image url into item {0}", item.Id); - item.SetImage(new ItemImageInfo - { - Path = response.Path, - Type = imageType - - }, 0); + item.SetImage( + new ItemImageInfo + { + Path = response.Path, + Type = imageType + }, + 0); } else { @@ -157,7 +159,7 @@ namespace MediaBrowser.Providers.Manager } downloadedImages.Add(imageType); - result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate; + result.UpdateType |= ItemUpdateType.ImageUpdate; } } } @@ -279,7 +281,7 @@ namespace MediaBrowser.Providers.Manager foreach (var imageType in _singularImages) { - if (!IsEnabled(savedOptions, imageType, item)) + if (!IsEnabled(savedOptions, imageType)) { continue; } @@ -299,8 +301,7 @@ namespace MediaBrowser.Providers.Manager minWidth = savedOptions.GetMinWidth(ImageType.Backdrop); await DownloadBackdrops(item, libraryOptions, ImageType.Backdrop, backdropLimit, provider, result, list, minWidth, cancellationToken).ConfigureAwait(false); - var hasScreenshots = item as IHasScreenshots; - if (hasScreenshots != null) + if (item is IHasScreenshots hasScreenshots) { minWidth = savedOptions.GetMinWidth(ImageType.Screenshot); await DownloadBackdrops(item, libraryOptions, ImageType.Screenshot, screenshotLimit, provider, result, list, minWidth, cancellationToken).ConfigureAwait(false); @@ -317,7 +318,7 @@ namespace MediaBrowser.Providers.Manager } } - private bool IsEnabled(TypeOptions options, ImageType type, BaseItem item) + private bool IsEnabled(TypeOptions options, ImageType type) { return options.IsEnabled(type); } @@ -452,10 +453,10 @@ namespace MediaBrowser.Providers.Manager .Where(i => i.Type == type && !(i.Width.HasValue && i.Width.Value < minWidth)) .ToList(); - if (EnableImageStub(item, type, libraryOptions) && eligibleImages.Count > 0) + if (EnableImageStub(item, libraryOptions) && eligibleImages.Count > 0) { SaveImageStub(item, type, eligibleImages.Select(i => i.Url)); - result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate; + result.UpdateType |= ItemUpdateType.ImageUpdate; return true; } @@ -476,7 +477,7 @@ namespace MediaBrowser.Providers.Manager null, cancellationToken).ConfigureAwait(false); - result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate; + result.UpdateType |= ItemUpdateType.ImageUpdate; return true; } catch (HttpException ex) @@ -495,7 +496,7 @@ namespace MediaBrowser.Providers.Manager return false; } - private bool EnableImageStub(BaseItem item, ImageType type, LibraryOptions libraryOptions) + private bool EnableImageStub(BaseItem item, LibraryOptions libraryOptions) { if (item is LiveTvProgram) { @@ -563,10 +564,10 @@ namespace MediaBrowser.Providers.Manager var url = image.Url; - if (EnableImageStub(item, imageType, libraryOptions)) + if (EnableImageStub(item, libraryOptions)) { SaveImageStub(item, imageType, new[] { url }); - result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate; + result.UpdateType |= ItemUpdateType.ImageUpdate; continue; } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 3b0c7b56c..dcae300fc 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -52,7 +52,6 @@ namespace MediaBrowser.Providers.Manager public async Task RefreshMetadata(BaseItem item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) { var itemOfType = (TItemType)item; - var config = ProviderManager.GetMetadataOptions(item); var updateType = ItemUpdateType.None; var requiresRefresh = false; @@ -86,7 +85,7 @@ namespace MediaBrowser.Providers.Manager // Always validate images and check for new locally stored ones. if (itemImageProvider.ValidateImages(item, allImageProviders.OfType(), refreshOptions.DirectoryService)) { - updateType = updateType | ItemUpdateType.ImageUpdate; + updateType |= ItemUpdateType.ImageUpdate; } } catch (Exception ex) @@ -102,7 +101,7 @@ namespace MediaBrowser.Providers.Manager bool hasRefreshedMetadata = true; bool hasRefreshedImages = true; - var isFirstRefresh = item.DateLastRefreshed == default(DateTime); + var isFirstRefresh = item.DateLastRefreshed == default; // Next run metadata providers if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None) @@ -114,7 +113,7 @@ namespace MediaBrowser.Providers.Manager { if (item.BeforeMetadataRefresh(refreshOptions.ReplaceAllMetadata)) { - updateType = updateType | ItemUpdateType.MetadataImport; + updateType |= ItemUpdateType.MetadataImport; } } @@ -132,7 +131,7 @@ namespace MediaBrowser.Providers.Manager var result = await RefreshWithProviders(metadataResult, id, refreshOptions, providers, itemImageProvider, cancellationToken).ConfigureAwait(false); - updateType = updateType | result.UpdateType; + updateType |= result.UpdateType; if (result.Failures > 0) { hasRefreshedMetadata = false; @@ -147,9 +146,9 @@ namespace MediaBrowser.Providers.Manager if (providers.Count > 0) { - var result = await itemImageProvider.RefreshImages(itemOfType, libraryOptions, providers, refreshOptions, config, cancellationToken).ConfigureAwait(false); + var result = await itemImageProvider.RefreshImages(itemOfType, libraryOptions, providers, refreshOptions, cancellationToken).ConfigureAwait(false); - updateType = updateType | result.UpdateType; + updateType |= result.UpdateType; if (result.Failures > 0) { hasRefreshedImages = false; @@ -158,7 +157,7 @@ namespace MediaBrowser.Providers.Manager } var beforeSaveResult = BeforeSave(itemOfType, isFirstRefresh || refreshOptions.ReplaceAllMetadata || refreshOptions.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || requiresRefresh || refreshOptions.ForceSave, updateType); - updateType = updateType | beforeSaveResult; + updateType |= beforeSaveResult; // Save if changes were made, or it's never been saved before if (refreshOptions.ForceSave || updateType > ItemUpdateType.None || isFirstRefresh || refreshOptions.ReplaceAllMetadata || requiresRefresh) @@ -175,7 +174,7 @@ namespace MediaBrowser.Providers.Manager // If any of these properties are set then make sure the updateType is not None, just to force everything to save if (refreshOptions.ForceSave || refreshOptions.ReplaceAllMetadata) { - updateType = updateType | ItemUpdateType.MetadataDownload; + updateType |= ItemUpdateType.MetadataDownload; } if (hasRefreshedMetadata && hasRefreshedImages) @@ -184,11 +183,11 @@ namespace MediaBrowser.Providers.Manager } else { - item.DateLastRefreshed = default(DateTime); + item.DateLastRefreshed = default; } // Save to database - SaveItem(metadataResult, libraryOptions, updateType, cancellationToken); + await SaveItemAsync(metadataResult, libraryOptions, updateType, cancellationToken).ConfigureAwait(false); } await AfterMetadataRefresh(itemOfType, refreshOptions, cancellationToken).ConfigureAwait(false); @@ -203,26 +202,26 @@ namespace MediaBrowser.Providers.Manager lookupInfo.Year = result.ProductionYear; } - protected void SaveItem(MetadataResult result, LibraryOptions libraryOptions, ItemUpdateType reason, CancellationToken cancellationToken) + protected async Task SaveItemAsync(MetadataResult result, LibraryOptions libraryOptions, ItemUpdateType reason, CancellationToken cancellationToken) { if (result.Item.SupportsPeople && result.People != null) { var baseItem = result.Item; LibraryManager.UpdatePeople(baseItem, result.People); - SavePeopleMetadata(result.People, libraryOptions, cancellationToken); + await SavePeopleMetadataAsync(result.People, libraryOptions, cancellationToken).ConfigureAwait(false); } result.Item.UpdateToRepository(reason, cancellationToken); } - private void SavePeopleMetadata(List people, LibraryOptions libraryOptions, CancellationToken cancellationToken) + private async Task SavePeopleMetadataAsync(List people, LibraryOptions libraryOptions, CancellationToken cancellationToken) { foreach (var person in people) { cancellationToken.ThrowIfCancellationRequested(); - if (person.ProviderIds.Any() || !string.IsNullOrWhiteSpace(person.ImageUrl)) + if (person.ProviderIds.Count > 0 || !string.IsNullOrWhiteSpace(person.ImageUrl)) { var updateType = ItemUpdateType.MetadataDownload; @@ -239,10 +238,10 @@ namespace MediaBrowser.Providers.Manager if (!string.IsNullOrWhiteSpace(person.ImageUrl) && !personEntity.HasImage(ImageType.Primary)) { - AddPersonImage(personEntity, libraryOptions, person.ImageUrl, cancellationToken); + await AddPersonImageAsync(personEntity, libraryOptions, person.ImageUrl, cancellationToken).ConfigureAwait(false); saveEntity = true; - updateType = updateType | ItemUpdateType.ImageUpdate; + updateType |= ItemUpdateType.ImageUpdate; } if (saveEntity) @@ -253,26 +252,28 @@ namespace MediaBrowser.Providers.Manager } } - private void AddPersonImage(Person personEntity, LibraryOptions libraryOptions, string imageUrl, CancellationToken cancellationToken) + private async Task AddPersonImageAsync(Person personEntity, LibraryOptions libraryOptions, string imageUrl, CancellationToken cancellationToken) { - // if (libraryOptions.DownloadImagesInAdvance) - //{ - // try - // { - // await ProviderManager.SaveImage(personEntity, imageUrl, ImageType.Primary, null, cancellationToken).ConfigureAwait(false); - // return; - // } - // catch (Exception ex) - // { - // Logger.LogError(ex, "Error in AddPersonImage"); - // } - //} - - personEntity.SetImage(new ItemImageInfo - { - Path = imageUrl, - Type = ImageType.Primary - }, 0); + if (libraryOptions.DownloadImagesInAdvance) + { + try + { + await ProviderManager.SaveImage(personEntity, imageUrl, ImageType.Primary, null, cancellationToken).ConfigureAwait(false); + return; + } + catch (Exception ex) + { + Logger.LogError(ex, "Error in AddPersonImage"); + } + } + + personEntity.SetImage( + new ItemImageInfo + { + Path = imageUrl, + Type = ImageType.Primary + }, + 0); } protected virtual Task AfterMetadataRefresh(TItemType item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index e67d1b8c3..d9a84be5c 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -210,10 +210,10 @@ namespace MediaBrowser.Providers.Manager } /// - public Task SaveImage(User user, Stream source, string mimeType, string path) + public Task SaveImage(Stream source, string mimeType, string path) { return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger) - .SaveImage(user, source, path); + .SaveImage(source, path); } /// @@ -563,7 +563,7 @@ namespace MediaBrowser.Providers.Manager var pluginList = summary.Plugins.ToList(); AddMetadataPlugins(pluginList, dummy, libraryOptions, options); - AddImagePlugins(pluginList, dummy, imageProviders); + AddImagePlugins(pluginList, imageProviders); var subtitleProviders = _subtitleManager.GetSupportedProviders(dummy); @@ -594,14 +594,14 @@ namespace MediaBrowser.Providers.Manager var providers = GetMetadataProvidersInternal(item, libraryOptions, options, true, true).ToList(); // Locals - list.AddRange(providers.Where(i => (i is ILocalMetadataProvider)).Select(i => new MetadataPlugin + list.AddRange(providers.Where(i => i is ILocalMetadataProvider).Select(i => new MetadataPlugin { Name = i.Name, Type = MetadataPluginType.LocalMetadataProvider })); // Fetchers - list.AddRange(providers.Where(i => (i is IRemoteMetadataProvider)).Select(i => new MetadataPlugin + list.AddRange(providers.Where(i => i is IRemoteMetadataProvider).Select(i => new MetadataPlugin { Name = i.Name, Type = MetadataPluginType.MetadataFetcher @@ -615,11 +615,10 @@ namespace MediaBrowser.Providers.Manager })); } - private void AddImagePlugins(List list, T item, List imageProviders) - where T : BaseItem + private void AddImagePlugins(List list, List imageProviders) { // Locals - list.AddRange(imageProviders.Where(i => (i is ILocalImageProvider)).Select(i => new MetadataPlugin + list.AddRange(imageProviders.Where(i => i is ILocalImageProvider).Select(i => new MetadataPlugin { Name = i.Name, Type = MetadataPluginType.LocalImageProvider @@ -1166,12 +1165,32 @@ namespace MediaBrowser.Providers.Manager /// public void Dispose() { - _disposed = true; + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases unmanaged and optionally managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } if (!_disposeCancellationTokenSource.IsCancellationRequested) { _disposeCancellationTokenSource.Cancel(); } + + if (disposing) + { + _disposeCancellationTokenSource.Dispose(); + } + + _disposed = true; } } } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs index 69c6fd722..77f03580a 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs @@ -2,11 +2,9 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; @@ -17,7 +15,6 @@ using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; namespace MediaBrowser.Providers.MediaInfo { @@ -25,19 +22,17 @@ namespace MediaBrowser.Providers.MediaInfo { private readonly IMediaEncoder _mediaEncoder; private readonly IItemRepository _itemRepo; - private readonly IApplicationPaths _appPaths; - private readonly IJsonSerializer _json; private readonly ILibraryManager _libraryManager; private readonly IMediaSourceManager _mediaSourceManager; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - - public FFProbeAudioInfo(IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IApplicationPaths appPaths, IJsonSerializer json, ILibraryManager libraryManager) + public FFProbeAudioInfo( + IMediaSourceManager mediaSourceManager, + IMediaEncoder mediaEncoder, + IItemRepository itemRepo, + ILibraryManager libraryManager) { _mediaEncoder = mediaEncoder; _itemRepo = itemRepo; - _appPaths = appPaths; - _json = json; _libraryManager = libraryManager; _mediaSourceManager = mediaSourceManager; } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs index 4fabe709b..9926275ae 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs @@ -40,19 +40,15 @@ namespace MediaBrowser.Providers.MediaInfo IHasItemChangeMonitor { private readonly ILogger _logger; - private readonly IIsoManager _isoManager; private readonly IMediaEncoder _mediaEncoder; private readonly IItemRepository _itemRepo; private readonly IBlurayExaminer _blurayExaminer; private readonly ILocalizationManager _localization; - private readonly IApplicationPaths _appPaths; - private readonly IJsonSerializer _json; private readonly IEncodingManager _encodingManager; private readonly IServerConfigurationManager _config; private readonly ISubtitleManager _subtitleManager; private readonly IChapterManager _chapterManager; private readonly ILibraryManager _libraryManager; - private readonly IChannelManager _channelManager; private readonly IMediaSourceManager _mediaSourceManager; public string Name => "ffprobe"; @@ -126,14 +122,10 @@ namespace MediaBrowser.Providers.MediaInfo public FFProbeProvider( ILogger logger, IMediaSourceManager mediaSourceManager, - IChannelManager channelManager, - IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IBlurayExaminer blurayExaminer, ILocalizationManager localization, - IApplicationPaths appPaths, - IJsonSerializer json, IEncodingManager encodingManager, IServerConfigurationManager config, ISubtitleManager subtitleManager, @@ -141,19 +133,15 @@ namespace MediaBrowser.Providers.MediaInfo ILibraryManager libraryManager) { _logger = logger; - _isoManager = isoManager; _mediaEncoder = mediaEncoder; _itemRepo = itemRepo; _blurayExaminer = blurayExaminer; _localization = localization; - _appPaths = appPaths; - _json = json; _encodingManager = encodingManager; _config = config; _subtitleManager = subtitleManager; _chapterManager = chapterManager; _libraryManager = libraryManager; - _channelManager = channelManager; _mediaSourceManager = mediaSourceManager; _subtitleResolver = new SubtitleResolver(BaseItem.LocalizationManager); @@ -211,9 +199,9 @@ namespace MediaBrowser.Providers.MediaInfo private string NormalizeStrmLine(string line) { - return line.Replace("\t", string.Empty) - .Replace("\r", string.Empty) - .Replace("\n", string.Empty) + return line.Replace("\t", string.Empty, StringComparison.Ordinal) + .Replace("\r", string.Empty, StringComparison.Ordinal) + .Replace("\n", string.Empty, StringComparison.Ordinal) .Trim(); } @@ -242,10 +230,11 @@ namespace MediaBrowser.Providers.MediaInfo FetchShortcutInfo(item); } - var prober = new FFProbeAudioInfo(_mediaSourceManager, _mediaEncoder, _itemRepo, _appPaths, _json, _libraryManager); + var prober = new FFProbeAudioInfo(_mediaSourceManager, _mediaEncoder, _itemRepo, _libraryManager); return prober.Probe(item, options, cancellationToken); } + // Run last public int Order => 100; } diff --git a/MediaBrowser.Providers/Music/Extensions.cs b/MediaBrowser.Providers/Music/Extensions.cs index b57d35256..dddfd02e4 100644 --- a/MediaBrowser.Providers/Music/Extensions.cs +++ b/MediaBrowser.Providers/Music/Extensions.cs @@ -6,7 +6,7 @@ using MediaBrowser.Model.Entities; namespace MediaBrowser.Providers.Music { - public static class Extensions + public static class AlbumInfoExtensions { public static string GetAlbumArtist(this AlbumInfo info) { @@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Music return id; } - return info.AlbumArtists.FirstOrDefault(); + return info.AlbumArtists.Count > 0 ? info.AlbumArtists[0] : default; } public static string GetReleaseGroupId(this AlbumInfo info) diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs index 23acb7fd6..3550614dd 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs @@ -276,7 +276,7 @@ namespace MediaBrowser.Providers.Music private async Task GetReleaseResult(string albumName, string artistId, CancellationToken cancellationToken) { - var url = string.Format("/ws/2/release/?query=\"{0}\" AND arid:{1}", + var url = string.Format(CultureInfo.InvariantCulture, "/ws/2/release/?query=\"{0}\" AND arid:{1}", WebUtility.UrlEncode(albumName), artistId); diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs index b829ed378..781b71640 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Providers.Music // They seem to throw bad request failures on any term with a slash var nameToSearch = searchInfo.Name.Replace('/', ' '); - var url = string.Format("/ws/2/artist/?query=\"{0}\"&dismax=true", UrlEncode(nameToSearch)); + var url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=\"{0}\"&dismax=true", UrlEncode(nameToSearch)); using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false)) await using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) @@ -62,7 +62,7 @@ namespace MediaBrowser.Providers.Music if (HasDiacritics(searchInfo.Name)) { // Try again using the search with accent characters url - url = string.Format("/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch)); + url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch)); using var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs index 41e664aac..c18725e0a 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Net.Http; +using System.Globalization; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; @@ -70,7 +71,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb list.Add(new RemoteImageInfo { ProviderName = Name, - Url = string.Format("https://img.omdbapi.com/?i={0}&apikey=2c9d9507", imdbId) + Url = string.Format(CultureInfo.InvariantCulture, "https://img.omdbapi.com/?i={0}&apikey=2c9d9507", imdbId) }); } } diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs index d2823a08c..102ad82e1 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs @@ -127,7 +127,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb } } - var url = OmdbProvider.GetOmdbUrl(urlQuery, _appHost, cancellationToken); + var url = OmdbProvider.GetOmdbUrl(urlQuery); using var response = await OmdbProvider.GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 6ad5298de..c45149c3a 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -256,16 +256,16 @@ namespace MediaBrowser.Providers.Plugins.Omdb return false; } - public static string GetOmdbUrl(string query, IApplicationHost appHost, CancellationToken cancellationToken) + public static string GetOmdbUrl(string query) { - const string url = "https://www.omdbapi.com?apikey=2c9d9507"; + const string Url = "https://www.omdbapi.com?apikey=2c9d9507"; if (string.IsNullOrWhiteSpace(query)) { - return url; + return Url; } - return url + "&" + query; + return Url + "&" + query; } private async Task EnsureItemInfo(string imdbId, CancellationToken cancellationToken) @@ -290,7 +290,11 @@ namespace MediaBrowser.Providers.Plugins.Omdb } } - var url = GetOmdbUrl(string.Format("i={0}&plot=short&tomatoes=true&r=json", imdbParam), _appHost, cancellationToken); + var url = GetOmdbUrl( + string.Format( + CultureInfo.InvariantCulture, + "i={0}&plot=short&tomatoes=true&r=json", + imdbParam)); using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); @@ -323,7 +327,12 @@ namespace MediaBrowser.Providers.Plugins.Omdb } } - var url = GetOmdbUrl(string.Format("i={0}&season={1}&detail=full", imdbParam, seasonId), _appHost, cancellationToken); + var url = GetOmdbUrl( + string.Format( + CultureInfo.InvariantCulture, + "i={0}&season={1}&detail=full", + imdbParam, + seasonId)); using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); @@ -348,7 +357,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb var dataPath = Path.Combine(_configurationManager.ApplicationPaths.CachePath, "omdb"); - var filename = string.Format("{0}.json", imdbId); + var filename = string.Format(CultureInfo.InvariantCulture, "{0}.json", imdbId); return Path.Combine(dataPath, filename); } @@ -362,7 +371,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb var dataPath = Path.Combine(_configurationManager.ApplicationPaths.CachePath, "omdb"); - var filename = string.Format("{0}_season_{1}.json", imdbId, seasonId); + var filename = string.Format(CultureInfo.InvariantCulture, "{0}_season_{1}.json", imdbId, seasonId); return Path.Combine(dataPath, filename); } diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs index cd2f96f14..f22d484ab 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; @@ -19,7 +20,6 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb { private const string DefaultLanguage = "en"; - private readonly SemaphoreSlim _cacheWriteLock = new SemaphoreSlim(1, 1); private readonly IMemoryCache _cache; private readonly TvDbClient _tvDbClient; private DateTime _tokenCreatedAt; @@ -176,7 +176,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb string language, CancellationToken cancellationToken) { - searchInfo.SeriesProviderIds.TryGetValue(MetadataProvider.Tvdb.ToString(), + searchInfo.SeriesProviderIds.TryGetValue(nameof(MetadataProvider.Tvdb), out var seriesTvdbId); var episodeQuery = new EpisodeQuery(); @@ -203,10 +203,10 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb else if (searchInfo.PremiereDate.HasValue) { // tvdb expects yyyy-mm-dd format - episodeQuery.FirstAired = searchInfo.PremiereDate.Value.ToString("yyyy-MM-dd"); + episodeQuery.FirstAired = searchInfo.PremiereDate.Value.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); } - return GetEpisodeTvdbId(Convert.ToInt32(seriesTvdbId), episodeQuery, language, cancellationToken); + return GetEpisodeTvdbId(Convert.ToInt32(seriesTvdbId, CultureInfo.InvariantCulture), episodeQuery, language, cancellationToken); } public async Task GetEpisodeTvdbId( @@ -218,7 +218,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb var episodePage = await GetEpisodesPageAsync(Convert.ToInt32(seriesTvdbId), episodeQuery, language, cancellationToken) .ConfigureAwait(false); - return episodePage.Data.FirstOrDefault()?.Id.ToString(); + return episodePage.Data.FirstOrDefault()?.Id.ToString(CultureInfo.InvariantCulture); } public Task> GetEpisodesPageAsync( @@ -276,23 +276,10 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb return cachedValue; } - await _cacheWriteLock.WaitAsync().ConfigureAwait(false); - try - { - if (_cache.TryGetValue(key, out cachedValue)) - { - return cachedValue; - } - - _tvDbClient.AcceptedLanguage = TvdbUtils.NormalizeLanguage(language) ?? DefaultLanguage; - var result = await resultFactory.Invoke().ConfigureAwait(false); - _cache.Set(key, result, TimeSpan.FromHours(1)); - return result; - } - finally - { - _cacheWriteLock.Release(); - } + _tvDbClient.AcceptedLanguage = TvdbUtils.NormalizeLanguage(language) ?? DefaultLanguage; + var result = await resultFactory.Invoke().ConfigureAwait(false); + _cache.Set(key, result, TimeSpan.FromHours(1)); + return result; } private static string GenerateKey(params object[] objects) diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs index 4d38d38dc..4e7c0e5a6 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Net.Http; +using System.Globalization; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Entities; @@ -76,7 +77,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb var episodeResult = await _tvdbClientManager - .GetEpisodesAsync(Convert.ToInt32(episodeTvdbId), language, cancellationToken) + .GetEpisodesAsync(Convert.ToInt32(episodeTvdbId, CultureInfo.InvariantCulture), language, cancellationToken) .ConfigureAwait(false); var image = GetImageInfo(episodeResult.Data); @@ -103,8 +104,8 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb return new RemoteImageInfo { - Width = Convert.ToInt32(episode.ThumbWidth), - Height = Convert.ToInt32(episode.ThumbHeight), + Width = Convert.ToInt32(episode.ThumbWidth, CultureInfo.InvariantCulture), + Height = Convert.ToInt32(episode.ThumbHeight, CultureInfo.InvariantCulture), ProviderName = Name, Url = TvdbUtils.BannerUrl + episode.Filename, Type = ImageType.Primary diff --git a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs index 4f86a0293..4da2c042f 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs @@ -180,7 +180,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets if (!string.IsNullOrEmpty(language)) { - url += string.Format("&language={0}", TmdbMovieProvider.NormalizeLanguage(language)); + url += string.Format(CultureInfo.InvariantCulture, "&language={0}", TmdbMovieProvider.NormalizeLanguage(language)); // Get images in english and with no language url += "&include_image_language=" + TmdbMovieProvider.GetImageLanguagesParam(language); @@ -250,7 +250,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets { var path = GetDataPath(appPaths, tmdbId); - var filename = string.Format("all-{0}.json", preferredLanguage ?? string.Empty); + var filename = string.Format(CultureInfo.InvariantCulture, "all-{0}.json", preferredLanguage ?? string.Empty); return Path.Combine(path, filename); } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs index 27ca3759e..01a887eed 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs @@ -300,7 +300,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies { movie.RemoteTrailers = movieData.Trailers.Youtube.Select(i => new MediaUrl { - Url = string.Format("https://www.youtube.com/watch?v={0}", i.Source), + Url = string.Format(CultureInfo.InvariantCulture, "https://www.youtube.com/watch?v={0}", i.Source), Name = i.Name }).ToArray(); diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs index 48f2a68a6..b7c4a5643 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs @@ -37,7 +37,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies ).* # Match rest of string", RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase); - private const string _searchURL = TmdbUtils.BaseTmdbApiUrl + @"3/search/{3}?api_key={1}&query={0}&language={2}"; + private const string SearchUrl = TmdbUtils.BaseTmdbApiUrl + @"3/search/{3}?api_key={1}&query={0}&language={2}"; + private const string SearchUrlWithYear = TmdbUtils.BaseTmdbApiUrl + @"3/search/{3}?api_key={1}&query={0}&language={2}&first_air_date_year={4}"; private readonly ILogger _logger; private readonly IJsonSerializer _json; @@ -124,7 +125,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies name2 = name2.Trim(); // Search again if the new name is different - if (!string.Equals(name2, name) && !string.IsNullOrWhiteSpace(name2)) + if (!string.Equals(name2, name, StringComparison.Ordinal) && !string.IsNullOrWhiteSpace(name2)) { _logger.LogInformation("TmdbSearch: Finding id for item: {0} ({1})", name2, year); results = await GetSearchResults(name2, searchType, year, language, tmdbImageUrl, cancellationToken).ConfigureAwait(false); @@ -164,10 +165,30 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies { if (string.IsNullOrWhiteSpace(name)) { - throw new ArgumentException("name"); + throw new ArgumentException("String can't be null or empty.", nameof(name)); } - var url3 = string.Format(_searchURL, WebUtility.UrlEncode(name), TmdbUtils.ApiKey, language, type); + string url3; + if (year != null && string.Equals(type, "movie", StringComparison.OrdinalIgnoreCase)) + { + url3 = string.Format( + CultureInfo.InvariantCulture, + SearchUrl, + WebUtility.UrlEncode(name), + TmdbUtils.ApiKey, + language, + type) + "&primary_release_year=" + year; + } + else + { + url3 = string.Format( + CultureInfo.InvariantCulture, + SearchUrl, + WebUtility.UrlEncode(name), + TmdbUtils.ApiKey, + language, + type); + } var requestMessage = new HttpRequestMessage(HttpMethod.Get, url3); foreach (var header in TmdbUtils.AcceptHeaders) @@ -207,10 +228,31 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies { if (string.IsNullOrWhiteSpace(name)) { - throw new ArgumentException("name"); + throw new ArgumentException("String can't be null or empty.", nameof(name)); } - var url3 = string.Format(_searchURL, WebUtility.UrlEncode(name), TmdbUtils.ApiKey, language, "tv"); + string url3; + if (year == null) + { + url3 = string.Format( + CultureInfo.InvariantCulture, + SearchUrl, + WebUtility.UrlEncode(name), + TmdbUtils.ApiKey, + language, + "tv"); + } + else + { + url3 = string.Format( + CultureInfo.InvariantCulture, + SearchUrlWithYear, + WebUtility.UrlEncode(name), + TmdbUtils.ApiKey, + language, + "tv", + year); + } var requestMessage = new HttpRequestMessage(HttpMethod.Get, url3); foreach (var header in TmdbUtils.AcceptHeaders) diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs index b4aef4542..90e3cea93 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs @@ -131,7 +131,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV { if (video.Site.Equals("youtube", System.StringComparison.OrdinalIgnoreCase)) { - var videoUrl = string.Format("http://www.youtube.com/watch?v={0}", video.Key); + var videoUrl = string.Format(CultureInfo.InvariantCulture, "http://www.youtube.com/watch?v={0}", video.Key); item.AddTrailerUrl(videoUrl); } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs index 154664321..5705885b4 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs @@ -92,7 +92,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV var path = TmdbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId); - var filename = string.Format("season-{0}-episode-{1}-{2}.json", + var filename = string.Format(CultureInfo.InvariantCulture, "season-{0}-episode-{1}-{2}.json", seasonNumber.ToString(CultureInfo.InvariantCulture), episodeNumber.ToString(CultureInfo.InvariantCulture), preferredLanguage); @@ -116,7 +116,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV if (!string.IsNullOrEmpty(language)) { - url += string.Format("&language={0}", language); + url += string.Format(CultureInfo.InvariantCulture, "&language={0}", language); } var includeImageLanguageParam = TmdbMovieProvider.GetImageLanguagesParam(language); diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs index 2b9077f55..e59504cc6 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs @@ -180,7 +180,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV var path = TmdbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId); - var filename = string.Format("season-{0}-{1}.json", + var filename = string.Format(CultureInfo.InvariantCulture, "season-{0}-{1}.json", seasonNumber.ToString(CultureInfo.InvariantCulture), preferredLanguage); @@ -203,7 +203,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV if (!string.IsNullOrEmpty(language)) { - url += string.Format("&language={0}", TmdbMovieProvider.NormalizeLanguage(language)); + url += string.Format(CultureInfo.InvariantCulture, "&language={0}", TmdbMovieProvider.NormalizeLanguage(language)); } var includeImageLanguageParam = TmdbMovieProvider.GetImageLanguagesParam(language); diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs index ac577b125..0eded3233 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs @@ -496,7 +496,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV var path = GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId); - var filename = string.Format("series-{0}.json", preferredLanguage ?? string.Empty); + var filename = string.Format(CultureInfo.InvariantCulture, "series-{0}.json", preferredLanguage ?? string.Empty); return Path.Combine(path, filename); } diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs index dad155c81..321153c6b 100644 --- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Net.Http; @@ -100,7 +101,7 @@ namespace MediaBrowser.Providers.Studios private string GetUrl(string image, string filename) { - return string.Format("https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/studios/{0}/{1}.jpg", image, filename); + return string.Format(CultureInfo.InvariantCulture, "https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/studios/{0}/{1}.jpg", image, filename); } private Task EnsureThumbsList(string file, CancellationToken cancellationToken) -- cgit v1.2.3 From 119f64f5e7b09aeb4ff8f59237093906c1e08f5f Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 21 Aug 2020 22:01:19 +0200 Subject: Make some methods async --- .../Channels/ChannelManager.cs | 21 ++++++--- .../Collections/CollectionManager.cs | 51 +++++++++------------- .../Library/LibraryManager.cs | 39 +++++++---------- .../LiveTv/LiveTvManager.cs | 16 ++++--- .../Playlists/PlaylistManager.cs | 16 +++---- Jellyfin.Api/Controllers/CollectionController.cs | 15 ++++--- Jellyfin.Api/Controllers/ImageController.cs | 14 +++--- Jellyfin.Api/Controllers/ItemUpdateController.cs | 7 +-- Jellyfin.Api/Controllers/PlaylistsController.cs | 12 ++--- Jellyfin.Api/Controllers/RemoteImageController.cs | 2 +- Jellyfin.Api/Controllers/VideosController.cs | 14 +++--- .../Collections/ICollectionManager.cs | 12 ++--- MediaBrowser.Controller/Entities/BaseItem.cs | 20 ++++----- MediaBrowser.Controller/Entities/Folder.cs | 4 +- MediaBrowser.Controller/Entities/Video.cs | 7 +-- MediaBrowser.Controller/Library/ILibraryManager.cs | 41 +++++++++++++---- .../Playlists/IPlaylistManager.cs | 6 +-- .../Encoder/EncoderValidator.cs | 5 ++- MediaBrowser.Providers/Manager/MetadataService.cs | 4 +- MediaBrowser.Providers/TV/DummySeasonProvider.cs | 4 +- 20 files changed, 165 insertions(+), 145 deletions(-) (limited to 'Jellyfin.Api/Controllers/ImageController.cs') diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index d8ab1f1a1..26fc1bee4 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -746,12 +746,21 @@ namespace Emby.Server.Implementations.Channels // null if came from cache if (itemsResult != null) { - var internalItems = itemsResult.Items - .Select(i => GetChannelItemEntity(i, channelProvider, channel.Id, parentItem, cancellationToken)) - .ToArray(); + var items = itemsResult.Items; + var itemsLen = items.Count; + var internalItems = new Guid[itemsLen]; + for (int i = 0; i < itemsLen; i++) + { + internalItems[i] = (await GetChannelItemEntityAsync( + items[i], + channelProvider, + channel.Id, + parentItem, + cancellationToken).ConfigureAwait(false)).Id; + } var existingIds = _libraryManager.GetItemIds(query); - var deadIds = existingIds.Except(internalItems.Select(i => i.Id)) + var deadIds = existingIds.Except(internalItems) .ToArray(); foreach (var deadId in deadIds) @@ -963,7 +972,7 @@ namespace Emby.Server.Implementations.Channels return item; } - private BaseItem GetChannelItemEntity(ChannelItemInfo info, IChannel channelProvider, Guid internalChannelId, BaseItem parentFolder, CancellationToken cancellationToken) + private async Task GetChannelItemEntityAsync(ChannelItemInfo info, IChannel channelProvider, Guid internalChannelId, BaseItem parentFolder, CancellationToken cancellationToken) { var parentFolderId = parentFolder.Id; @@ -1165,7 +1174,7 @@ namespace Emby.Server.Implementations.Channels } else if (forceUpdate) { - item.UpdateToRepository(ItemUpdateType.None, cancellationToken); + await item.UpdateToRepositoryAsync(ItemUpdateType.None, cancellationToken).ConfigureAwait(false); } if ((isNew || forceUpdate) && info.Type == ChannelItemType.Media) diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index ac2edc1e2..3011a37e3 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -132,7 +132,7 @@ namespace Emby.Server.Implementations.Collections } /// - public BoxSet CreateCollection(CollectionCreationOptions options) + public async Task CreateCollectionAsync(CollectionCreationOptions options) { var name = options.Name; @@ -141,7 +141,7 @@ namespace Emby.Server.Implementations.Collections // This could cause it to get re-resolved as a plain folder var folderName = _fileSystem.GetValidFilename(name) + " [boxset]"; - var parentFolder = GetCollectionsFolder(true).GetAwaiter().GetResult(); + var parentFolder = await GetCollectionsFolder(true).ConfigureAwait(false); if (parentFolder == null) { @@ -169,12 +169,16 @@ namespace Emby.Server.Implementations.Collections if (options.ItemIdList.Length > 0) { - AddToCollection(collection.Id, options.ItemIdList, false, new MetadataRefreshOptions(new DirectoryService(_fileSystem)) - { - // The initial adding of items is going to create a local metadata file - // This will cause internet metadata to be skipped as a result - MetadataRefreshMode = MetadataRefreshMode.FullRefresh - }); + await AddToCollectionAsync( + collection.Id, + options.ItemIdList.Select(x => new Guid(x)), + false, + new MetadataRefreshOptions(new DirectoryService(_fileSystem)) + { + // The initial adding of items is going to create a local metadata file + // This will cause internet metadata to be skipped as a result + MetadataRefreshMode = MetadataRefreshMode.FullRefresh + }).ConfigureAwait(false); } else { @@ -197,18 +201,10 @@ namespace Emby.Server.Implementations.Collections } /// - public void AddToCollection(Guid collectionId, IEnumerable ids) - { - AddToCollection(collectionId, ids, true, new MetadataRefreshOptions(new DirectoryService(_fileSystem))); - } + public Task AddToCollectionAsync(Guid collectionId, IEnumerable ids) + => AddToCollectionAsync(collectionId, ids, true, new MetadataRefreshOptions(new DirectoryService(_fileSystem))); - /// - public void AddToCollection(Guid collectionId, IEnumerable ids) - { - AddToCollection(collectionId, ids.Select(i => i.ToString("N", CultureInfo.InvariantCulture)), true, new MetadataRefreshOptions(new DirectoryService(_fileSystem))); - } - - private void AddToCollection(Guid collectionId, IEnumerable ids, bool fireEvent, MetadataRefreshOptions refreshOptions) + private async Task AddToCollectionAsync(Guid collectionId, IEnumerable ids, bool fireEvent, MetadataRefreshOptions refreshOptions) { var collection = _libraryManager.GetItemById(collectionId) as BoxSet; if (collection == null) @@ -224,15 +220,14 @@ namespace Emby.Server.Implementations.Collections foreach (var id in ids) { - var guidId = new Guid(id); - var item = _libraryManager.GetItemById(guidId); + var item = _libraryManager.GetItemById(id); if (item == null) { throw new ArgumentException("No item exists with the supplied Id"); } - if (!currentLinkedChildrenIds.Contains(guidId)) + if (!currentLinkedChildrenIds.Contains(id)) { itemList.Add(item); @@ -249,7 +244,7 @@ namespace Emby.Server.Implementations.Collections collection.UpdateRatingToItems(linkedChildrenList); - collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await collection.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); refreshOptions.ForceSave = true; _providerManager.QueueRefresh(collection.Id, refreshOptions, RefreshPriority.High); @@ -266,13 +261,7 @@ namespace Emby.Server.Implementations.Collections } /// - public void RemoveFromCollection(Guid collectionId, IEnumerable itemIds) - { - RemoveFromCollection(collectionId, itemIds.Select(i => new Guid(i))); - } - - /// - public void RemoveFromCollection(Guid collectionId, IEnumerable itemIds) + public async Task RemoveFromCollectionAsync(Guid collectionId, IEnumerable itemIds) { var collection = _libraryManager.GetItemById(collectionId) as BoxSet; @@ -309,7 +298,7 @@ namespace Emby.Server.Implementations.Collections collection.LinkedChildren = collection.LinkedChildren.Except(list).ToArray(); } - collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await collection.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); _providerManager.QueueRefresh( collection.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 7ed8f0bbf..375f09f5b 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -771,7 +771,7 @@ namespace Emby.Server.Implementations.Library if (folder.ParentId != rootFolder.Id) { folder.ParentId = rootFolder.Id; - folder.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None); + folder.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, CancellationToken.None).GetAwaiter().GetResult(); } rootFolder.AddVirtualChild(folder); @@ -1868,7 +1868,8 @@ namespace Emby.Server.Implementations.Library return image.Path != null && !image.IsLocalFile; } - public void UpdateImages(BaseItem item, bool forceUpdate = false) + /// + public async Task UpdateImagesAsync(BaseItem item, bool forceUpdate = false) { if (item == null) { @@ -1891,7 +1892,7 @@ namespace Emby.Server.Implementations.Library try { var index = item.GetImageIndex(img); - image = ConvertImageToLocal(item, img, index).ConfigureAwait(false).GetAwaiter().GetResult(); + image = await ConvertImageToLocal(item, img, index).ConfigureAwait(false); } catch (ArgumentException) { @@ -1913,7 +1914,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError(ex, "Cannnot get image dimensions for {0}", image.Path); + _logger.LogError(ex, "Cannot get image dimensions for {0}", image.Path); image.Width = 0; image.Height = 0; continue; @@ -1943,10 +1944,8 @@ namespace Emby.Server.Implementations.Library RegisterItem(item); } - /// - /// Updates the item. - /// - public void UpdateItems(IReadOnlyList items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken) + /// + public async Task UpdateItemsAsync(IReadOnlyList items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken) { foreach (var item in items) { @@ -1957,7 +1956,7 @@ namespace Emby.Server.Implementations.Library item.DateLastSaved = DateTime.UtcNow; - UpdateImages(item, updateReason >= ItemUpdateType.ImageUpdate); + await UpdateImagesAsync(item, updateReason >= ItemUpdateType.ImageUpdate).ConfigureAwait(false); } _itemRepository.SaveItems(items, cancellationToken); @@ -1991,17 +1990,9 @@ namespace Emby.Server.Implementations.Library } } - /// - /// Updates the item. - /// - /// The item. - /// The parent item. - /// The update reason. - /// The cancellation token. - public void UpdateItem(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken) - { - UpdateItems(new[] { item }, parent, updateReason, cancellationToken); - } + /// + public Task UpdateItemAsync(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken) + => UpdateItemsAsync(new[] { item }, parent, updateReason, cancellationToken); /// /// Reports the item removed. @@ -2233,7 +2224,7 @@ namespace Emby.Server.Implementations.Library if (refresh) { - item.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None); + item.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, CancellationToken.None).GetAwaiter().GetResult(); ProviderManager.QueueRefresh(item.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.Normal); } @@ -2420,7 +2411,7 @@ namespace Emby.Server.Implementations.Library if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase)) { item.ViewType = viewType; - item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).GetAwaiter().GetResult(); } var refresh = isNew || DateTime.UtcNow - item.DateLastRefreshed >= _viewRefreshInterval; @@ -2902,7 +2893,7 @@ namespace Emby.Server.Implementations.Library await ProviderManager.SaveImage(item, url, image.Type, imageIndex, CancellationToken.None).ConfigureAwait(false); - item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); + await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); return item.GetImageInfo(image.Type, imageIndex); } @@ -2920,7 +2911,7 @@ namespace Emby.Server.Implementations.Library // Remove this image to prevent it from retrying over and over item.RemoveImage(image); - item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); + await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); throw new InvalidOperationException(); } diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 90cbd85a5..5ed6baeb9 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -422,7 +422,7 @@ namespace Emby.Server.Implementations.LiveTv } } - private LiveTvChannel GetChannel(ChannelInfo channelInfo, string serviceName, BaseItem parentFolder, CancellationToken cancellationToken) + private async Task GetChannelAsync(ChannelInfo channelInfo, string serviceName, BaseItem parentFolder, CancellationToken cancellationToken) { var parentFolderId = parentFolder.Id; var isNew = false; @@ -512,7 +512,7 @@ namespace Emby.Server.Implementations.LiveTv } else if (forceUpdate) { - _libraryManager.UpdateItem(item, parentFolder, ItemUpdateType.MetadataImport, cancellationToken); + await _libraryManager.UpdateItemAsync(item, parentFolder, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); } return item; @@ -1129,7 +1129,7 @@ namespace Emby.Server.Implementations.LiveTv try { - var item = GetChannel(channelInfo.Item2, channelInfo.Item1, parentFolder, cancellationToken); + var item = await GetChannelAsync(channelInfo.Item2, channelInfo.Item1, parentFolder, cancellationToken).ConfigureAwait(false); list.Add(item); } @@ -1146,7 +1146,7 @@ namespace Emby.Server.Implementations.LiveTv double percent = numComplete; percent /= allChannelsList.Count; - progress.Report(5 * percent + 10); + progress.Report((5 * percent) + 10); } progress.Report(15); @@ -1221,7 +1221,11 @@ namespace Emby.Server.Implementations.LiveTv if (updatedPrograms.Count > 0) { - _libraryManager.UpdateItems(updatedPrograms, currentChannel, ItemUpdateType.MetadataImport, cancellationToken); + await _libraryManager.UpdateItemsAsync( + updatedPrograms, + currentChannel, + ItemUpdateType.MetadataImport, + cancellationToken).ConfigureAwait(false); } currentChannel.IsMovie = isMovie; @@ -1234,7 +1238,7 @@ namespace Emby.Server.Implementations.LiveTv currentChannel.AddTag("Kids"); } - currentChannel.UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken); + await currentChannel.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); await currentChannel.RefreshMetadata( new MetadataRefreshOptions(new DirectoryService(_fileSystem)) { diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs index 38ceadedb..d35223b0a 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs @@ -184,17 +184,17 @@ namespace Emby.Server.Implementations.Playlists return Playlist.GetPlaylistItems(playlistMediaType, items, user, options); } - public void AddToPlaylist(string playlistId, ICollection itemIds, Guid userId) + public Task AddToPlaylistAsync(string playlistId, ICollection itemIds, Guid userId) { var user = userId.Equals(Guid.Empty) ? null : _userManager.GetUserById(userId); - AddToPlaylistInternal(playlistId, itemIds, user, new DtoOptions(false) + return AddToPlaylistInternal(playlistId, itemIds, user, new DtoOptions(false) { EnableImages = true }); } - private void AddToPlaylistInternal(string playlistId, ICollection newItemIds, User user, DtoOptions options) + private async Task AddToPlaylistInternal(string playlistId, ICollection newItemIds, User user, DtoOptions options) { // Retrieve the existing playlist var playlist = _libraryManager.GetItemById(playlistId) as Playlist @@ -238,7 +238,7 @@ namespace Emby.Server.Implementations.Playlists // Update the playlist in the repository playlist.LinkedChildren = newLinkedChildren; - playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await playlist.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); // Update the playlist on disk if (playlist.IsFile) @@ -256,7 +256,7 @@ namespace Emby.Server.Implementations.Playlists RefreshPriority.High); } - public void RemoveFromPlaylist(string playlistId, IEnumerable entryIds) + public async Task RemoveFromPlaylistAsync(string playlistId, IEnumerable entryIds) { if (!(_libraryManager.GetItemById(playlistId) is Playlist playlist)) { @@ -273,7 +273,7 @@ namespace Emby.Server.Implementations.Playlists .Select(i => i.Item1) .ToArray(); - playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await playlist.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); if (playlist.IsFile) { @@ -289,7 +289,7 @@ namespace Emby.Server.Implementations.Playlists RefreshPriority.High); } - public void MoveItem(string playlistId, string entryId, int newIndex) + public async Task MoveItemAsync(string playlistId, string entryId, int newIndex) { if (!(_libraryManager.GetItemById(playlistId) is Playlist playlist)) { @@ -322,7 +322,7 @@ namespace Emby.Server.Implementations.Playlists playlist.LinkedChildren = newList.ToArray(); - playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await playlist.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); if (playlist.IsFile) { diff --git a/Jellyfin.Api/Controllers/CollectionController.cs b/Jellyfin.Api/Controllers/CollectionController.cs index 53821a188..c5910d6e8 100644 --- a/Jellyfin.Api/Controllers/CollectionController.cs +++ b/Jellyfin.Api/Controllers/CollectionController.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel.DataAnnotations; +using System.Threading.Tasks; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; @@ -51,7 +52,7 @@ namespace Jellyfin.Api.Controllers /// A with information about the new collection. [HttpPost] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult CreateCollection( + public async Task> CreateCollection( [FromQuery] string? name, [FromQuery] string? ids, [FromQuery] Guid? parentId, @@ -59,14 +60,14 @@ namespace Jellyfin.Api.Controllers { var userId = _authContext.GetAuthorizationInfo(Request).UserId; - var item = _collectionManager.CreateCollection(new CollectionCreationOptions + var item = await _collectionManager.CreateCollectionAsync(new CollectionCreationOptions { IsLocked = isLocked, Name = name, ParentId = parentId, ItemIdList = RequestHelpers.Split(ids, ',', true), UserIds = new[] { userId } - }); + }).ConfigureAwait(false); var dtoOptions = new DtoOptions().AddClientFields(Request); @@ -87,9 +88,9 @@ namespace Jellyfin.Api.Controllers /// A indicating success. [HttpPost("{collectionId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult AddToCollection([FromRoute] Guid collectionId, [FromQuery, Required] string? itemIds) + public async Task AddToCollection([FromRoute] Guid collectionId, [FromQuery, Required] string? itemIds) { - _collectionManager.AddToCollection(collectionId, RequestHelpers.Split(itemIds, ',', true)); + await _collectionManager.AddToCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(true); return NoContent(); } @@ -102,9 +103,9 @@ namespace Jellyfin.Api.Controllers /// A indicating success. [HttpDelete("{collectionId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult RemoveFromCollection([FromRoute] Guid collectionId, [FromQuery, Required] string? itemIds) + public async Task RemoveFromCollection([FromRoute] Guid collectionId, [FromQuery, Required] string? itemIds) { - _collectionManager.RemoveFromCollection(collectionId, RequestHelpers.Split(itemIds, ',', true)); + await _collectionManager.RemoveFromCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(false); return NoContent(); } } diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 75734f0af..ca9c2fa46 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -174,7 +174,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult DeleteItemImage( + public async Task DeleteItemImage( [FromRoute] Guid itemId, [FromRoute] ImageType imageType, [FromRoute] int? imageIndex = null) @@ -185,7 +185,7 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - item.DeleteImage(imageType, imageIndex ?? 0); + await item.DeleteImageAsync(imageType, imageIndex ?? 0).ConfigureAwait(false); return NoContent(); } @@ -218,7 +218,7 @@ namespace Jellyfin.Api.Controllers // Handle image/png; charset=utf-8 var mimeType = Request.ContentType.Split(';').FirstOrDefault(); await _providerManager.SaveImage(item, Request.Body, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false); - item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); + await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); return NoContent(); } @@ -237,7 +237,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult UpdateItemImageIndex( + public async Task UpdateItemImageIndex( [FromRoute] Guid itemId, [FromRoute] ImageType imageType, [FromRoute] int imageIndex, @@ -249,7 +249,7 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - item.SwapImages(imageType, imageIndex, newIndex); + await item.SwapImagesAsync(imageType, imageIndex, newIndex).ConfigureAwait(false); return NoContent(); } @@ -264,7 +264,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult> GetItemImageInfos([FromRoute] Guid itemId) + public async Task>> GetItemImageInfos([FromRoute] Guid itemId) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -281,7 +281,7 @@ namespace Jellyfin.Api.Controllers return list; } - _libraryManager.UpdateImages(item); // this makes sure dimensions and hashes are correct + await _libraryManager.UpdateImagesAsync(item).ConfigureAwait(false); // this makes sure dimensions and hashes are correct foreach (var image in itemImages) { diff --git a/Jellyfin.Api/Controllers/ItemUpdateController.cs b/Jellyfin.Api/Controllers/ItemUpdateController.cs index 4b40c6ada..ec52f4996 100644 --- a/Jellyfin.Api/Controllers/ItemUpdateController.cs +++ b/Jellyfin.Api/Controllers/ItemUpdateController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading; +using System.Threading.Tasks; using Jellyfin.Api.Constants; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; @@ -67,7 +68,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Items/{itemId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult UpdateItem([FromRoute] Guid itemId, [FromBody, Required] BaseItemDto request) + public async Task UpdateItem([FromRoute] Guid itemId, [FromBody, Required] BaseItemDto request) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -101,7 +102,7 @@ namespace Jellyfin.Api.Controllers item.OnMetadataChanged(); - item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); if (isLockedChanged && item.IsFolder) { @@ -110,7 +111,7 @@ namespace Jellyfin.Api.Controllers foreach (var child in folder.GetRecursiveChildren()) { child.IsLocked = newLockData; - child.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await child.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); } } diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs index 12c87d7c3..d69228c33 100644 --- a/Jellyfin.Api/Controllers/PlaylistsController.cs +++ b/Jellyfin.Api/Controllers/PlaylistsController.cs @@ -83,12 +83,12 @@ namespace Jellyfin.Api.Controllers /// An on success. [HttpPost("{playlistId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult AddToPlaylist( + public async Task AddToPlaylist( [FromRoute] string? playlistId, [FromQuery] string? ids, [FromQuery] Guid? userId) { - _playlistManager.AddToPlaylist(playlistId, RequestHelpers.GetGuids(ids), userId ?? Guid.Empty); + await _playlistManager.AddToPlaylistAsync(playlistId, RequestHelpers.GetGuids(ids), userId ?? Guid.Empty).ConfigureAwait(false); return NoContent(); } @@ -102,12 +102,12 @@ namespace Jellyfin.Api.Controllers /// An on success. [HttpPost("{playlistId}/Items/{itemId}/Move/{newIndex}")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult MoveItem( + public async Task MoveItem( [FromRoute] string? playlistId, [FromRoute] string? itemId, [FromRoute] int newIndex) { - _playlistManager.MoveItem(playlistId, itemId, newIndex); + await _playlistManager.MoveItemAsync(playlistId, itemId, newIndex).ConfigureAwait(false); return NoContent(); } @@ -120,9 +120,9 @@ namespace Jellyfin.Api.Controllers /// An on success. [HttpDelete("{playlistId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult RemoveFromPlaylist([FromRoute] string? playlistId, [FromQuery] string? entryIds) + public async Task RemoveFromPlaylist([FromRoute] string? playlistId, [FromQuery] string? entryIds) { - _playlistManager.RemoveFromPlaylist(playlistId, RequestHelpers.Split(entryIds, ',', true)); + await _playlistManager.RemoveFromPlaylistAsync(playlistId, RequestHelpers.Split(entryIds, ',', true)).ConfigureAwait(false); return NoContent(); } diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index a203c50b9..30a4f73fc 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -221,7 +221,7 @@ namespace Jellyfin.Api.Controllers await _providerManager.SaveImage(item, imageUrl, type, null, CancellationToken.None) .ConfigureAwait(false); - item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); + await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); return NoContent(); } diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 14d3f2460..f42810c94 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -161,7 +161,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult DeleteAlternateSources([FromRoute] Guid itemId) + public async Task DeleteAlternateSources([FromRoute] Guid itemId) { var video = (Video)_libraryManager.GetItemById(itemId); @@ -180,12 +180,12 @@ namespace Jellyfin.Api.Controllers link.SetPrimaryVersionId(null); link.LinkedAlternateVersions = Array.Empty(); - link.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await link.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); } video.LinkedAlternateVersions = Array.Empty(); video.SetPrimaryVersionId(null); - video.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await video.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); return NoContent(); } @@ -201,7 +201,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status400BadRequest)] - public ActionResult MergeVersions([FromQuery, Required] string? itemIds) + public async Task MergeVersions([FromQuery, Required] string? itemIds) { var items = RequestHelpers.Split(itemIds, ',', true) .Select(i => _libraryManager.GetItemById(i)) @@ -239,7 +239,7 @@ namespace Jellyfin.Api.Controllers { item.SetPrimaryVersionId(primaryVersion.Id.ToString("N", CultureInfo.InvariantCulture)); - item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); list.Add(new LinkedChild { @@ -258,12 +258,12 @@ namespace Jellyfin.Api.Controllers if (item.LinkedAlternateVersions.Length > 0) { item.LinkedAlternateVersions = Array.Empty(); - item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); } } primaryVersion.LinkedAlternateVersions = list.ToArray(); - primaryVersion.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await primaryVersion.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); return NoContent(); } diff --git a/MediaBrowser.Controller/Collections/ICollectionManager.cs b/MediaBrowser.Controller/Collections/ICollectionManager.cs index 701423c0f..3861ae634 100644 --- a/MediaBrowser.Controller/Collections/ICollectionManager.cs +++ b/MediaBrowser.Controller/Collections/ICollectionManager.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using Jellyfin.Data.Entities; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -27,24 +28,23 @@ namespace MediaBrowser.Controller.Collections /// Creates the collection. /// /// The options. - BoxSet CreateCollection(CollectionCreationOptions options); + Task CreateCollectionAsync(CollectionCreationOptions options); /// /// Adds to collection. /// /// The collection identifier. /// The item ids. - void AddToCollection(Guid collectionId, IEnumerable itemIds); + /// representing the asynchronous operation. + Task AddToCollectionAsync(Guid collectionId, IEnumerable itemIds); /// /// Removes from collection. /// /// The collection identifier. /// The item ids. - void RemoveFromCollection(Guid collectionId, IEnumerable itemIds); - - void AddToCollection(Guid collectionId, IEnumerable itemIds); - void RemoveFromCollection(Guid collectionId, IEnumerable itemIds); + /// A representing the asynchronous operation. + Task RemoveFromCollectionAsync(Guid collectionId, IEnumerable itemIds); /// /// Collapses the items within box sets. diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index f34309c40..9e595ddc3 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1390,7 +1390,7 @@ namespace MediaBrowser.Controller.Entities new List(); var ownedItemsChanged = await RefreshedOwnedItems(options, files, cancellationToken).ConfigureAwait(false); - LibraryManager.UpdateImages(this); // ensure all image properties in DB are fresh + await LibraryManager.UpdateImagesAsync(this).ConfigureAwait(false); // ensure all image properties in DB are fresh if (ownedItemsChanged) { @@ -2279,7 +2279,7 @@ namespace MediaBrowser.Controller.Entities /// /// The type. /// The index. - public void DeleteImage(ImageType type, int index) + public async Task DeleteImageAsync(ImageType type, int index) { var info = GetImageInfo(type, index); @@ -2297,7 +2297,7 @@ namespace MediaBrowser.Controller.Entities FileSystem.DeleteFile(info.Path); } - UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); + await UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); } public void RemoveImage(ItemImageInfo image) @@ -2310,10 +2310,8 @@ namespace MediaBrowser.Controller.Entities ImageInfos = ImageInfos.Except(deletedImages).ToArray(); } - public virtual void UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) - { - LibraryManager.UpdateItem(this, GetParent(), updateReason, cancellationToken); - } + public virtual Task UpdateToRepositoryAsync(ItemUpdateType updateReason, CancellationToken cancellationToken) + => LibraryManager.UpdateItemAsync(this, GetParent(), updateReason, cancellationToken); /// /// Validates that images within the item are still on the filesystem. @@ -2558,7 +2556,7 @@ namespace MediaBrowser.Controller.Entities return type == ImageType.Backdrop || type == ImageType.Screenshot || type == ImageType.Chapter; } - public void SwapImages(ImageType type, int index1, int index2) + public Task SwapImagesAsync(ImageType type, int index1, int index2) { if (!AllowsMultipleImages(type)) { @@ -2571,13 +2569,13 @@ namespace MediaBrowser.Controller.Entities if (info1 == null || info2 == null) { // Nothing to do - return; + return Task.CompletedTask; } if (!info1.IsLocalFile || !info2.IsLocalFile) { // TODO: Not supported yet - return; + return Task.CompletedTask; } var path1 = info1.Path; @@ -2594,7 +2592,7 @@ namespace MediaBrowser.Controller.Entities info2.Width = 0; info2.Height = 0; - UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); + return UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None); } public virtual bool IsPlayed(User user) diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 6441340f9..11542c1ca 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -350,12 +350,12 @@ namespace MediaBrowser.Controller.Entities if (currentChild.UpdateFromResolvedItem(child) > ItemUpdateType.None) { - currentChild.UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken); + await currentChild.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); } else { // metadata is up-to-date; make sure DB has correct images dimensions and hash - LibraryManager.UpdateImages(currentChild); + await LibraryManager.UpdateImagesAsync(currentChild).ConfigureAwait(false); } continue; diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index b7d7e8e1a..eeff78e10 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -495,9 +495,10 @@ namespace MediaBrowser.Controller.Entities } } - public override void UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) + /// + public override async Task UpdateToRepositoryAsync(ItemUpdateType updateReason, CancellationToken cancellationToken) { - base.UpdateToRepository(updateReason, cancellationToken); + await base.UpdateToRepositoryAsync(updateReason, cancellationToken).ConfigureAwait(false); var localAlternates = GetLocalAlternateVersionIds() .Select(i => LibraryManager.GetItemById(i)) @@ -514,7 +515,7 @@ namespace MediaBrowser.Controller.Entities item.Genres = Genres; item.ProviderIds = ProviderIds; - item.UpdateToRepository(ItemUpdateType.MetadataDownload, cancellationToken); + await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataDownload, cancellationToken).ConfigureAwait(false); } } diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 9abcf2b62..d53b1fc8d 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -72,6 +72,7 @@ namespace MediaBrowser.Controller.Library /// The name. /// Task{Artist}. MusicArtist GetArtist(string name); + MusicArtist GetArtist(string name, DtoOptions options); /// /// Gets a Studio. @@ -124,7 +125,7 @@ namespace MediaBrowser.Controller.Library /// void QueueLibraryScan(); - void UpdateImages(BaseItem item, bool forceUpdate = false); + Task UpdateImagesAsync(BaseItem item, bool forceUpdate = false); /// /// Gets the default view. @@ -179,6 +180,7 @@ namespace MediaBrowser.Controller.Library /// The sort order. /// IEnumerable{BaseItem}. IEnumerable Sort(IEnumerable items, User user, IEnumerable sortBy, SortOrder sortOrder); + IEnumerable Sort(IEnumerable items, User user, IEnumerable> orderBy); /// @@ -200,9 +202,16 @@ namespace MediaBrowser.Controller.Library /// /// Updates the item. /// - void UpdateItems(IReadOnlyList items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken); + Task UpdateItemsAsync(IReadOnlyList items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken); - void UpdateItem(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken); + /// + /// Updates the item. + /// + /// The item. + /// The parent item. + /// The update reason. + /// The cancellation token. + Task UpdateItemAsync(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken); /// /// Retrieves the item. @@ -317,7 +326,8 @@ namespace MediaBrowser.Controller.Library /// The name. /// Type of the view. /// Name of the sort. - UserView GetNamedView(string name, + UserView GetNamedView( + string name, string viewType, string sortName); @@ -329,7 +339,8 @@ namespace MediaBrowser.Controller.Library /// Type of the view. /// Name of the sort. /// The unique identifier. - UserView GetNamedView(string name, + UserView GetNamedView( + string name, Guid parentId, string viewType, string sortName, @@ -341,7 +352,8 @@ namespace MediaBrowser.Controller.Library /// The parent. /// Type of the view. /// Name of the sort. - UserView GetShadowView(BaseItem parent, + UserView GetShadowView( + BaseItem parent, string viewType, string sortName); @@ -393,7 +405,9 @@ namespace MediaBrowser.Controller.Library /// The file system children. /// The directory service. /// IEnumerable<Trailer>. - IEnumerable