diff options
56 files changed, 962 insertions, 1282 deletions
diff --git a/Emby.Dlna/ContentDirectory/ContentDirectory.cs b/Emby.Dlna/ContentDirectory/ContentDirectory.cs index cd21599d0..b0fec90e6 100644 --- a/Emby.Dlna/ContentDirectory/ContentDirectory.cs +++ b/Emby.Dlna/ContentDirectory/ContentDirectory.cs @@ -76,7 +76,6 @@ namespace Emby.Dlna.ContentDirectory _dlna.GetDefaultProfile(); var serverAddress = request.RequestedUrl.Substring(0, request.RequestedUrl.IndexOf("/dlna", StringComparison.OrdinalIgnoreCase)); - string accessToken = null; var user = GetUser(profile); @@ -85,7 +84,7 @@ namespace Emby.Dlna.ContentDirectory _libraryManager, profile, serverAddress, - accessToken, + null, _imageProcessor, _userDataManager, user, diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index 2f6a0ecee..2d8bb87f9 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -483,27 +483,26 @@ namespace Emby.Dlna.ContentDirectory return GetGenreItems(item, Guid.Empty, user, sort, startIndex, limit); } - if (!stubType.HasValue || stubType.Value != StubType.Folder) + if ((!stubType.HasValue || stubType.Value != StubType.Folder) + && item is IHasCollectionType collectionFolder) { - var collectionFolder = item as IHasCollectionType; - if (collectionFolder != null && string.Equals(CollectionType.Music, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(CollectionType.Music, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) { return GetMusicFolders(item, user, stubType, sort, startIndex, limit); } - if (collectionFolder != null && string.Equals(CollectionType.Movies, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(CollectionType.Movies, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) { return GetMovieFolders(item, user, stubType, sort, startIndex, limit); } - if (collectionFolder != null && string.Equals(CollectionType.TvShows, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(CollectionType.TvShows, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) { return GetTvFolders(item, user, stubType, sort, startIndex, limit); } - - if (collectionFolder != null && string.Equals(CollectionType.Folders, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(CollectionType.Folders, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) { return GetFolders(item, user, stubType, sort, startIndex, limit); } - if (collectionFolder != null && string.Equals(CollectionType.LiveTv, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(CollectionType.LiveTv, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) { return GetLiveTvChannels(item, user, stubType, sort, startIndex, limit); } diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 81c4d3d16..440f96b3f 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -1088,8 +1088,8 @@ namespace Emby.Dlna.Didl //{ // var size = _imageProcessor.GetImageSize(imageInfo); - // width = Convert.ToInt32(size.Width); - // height = Convert.ToInt32(size.Height); + // width = size.Width; + // height = size.Height; //} //catch //{ @@ -1162,8 +1162,7 @@ namespace Emby.Dlna.Didl info.ImageTag, format, maxWidth.ToString(CultureInfo.InvariantCulture), - maxHeight.ToString(CultureInfo.InvariantCulture) - ); + maxHeight.ToString(CultureInfo.InvariantCulture)); var width = info.Width; var height = info.Height; @@ -1172,15 +1171,11 @@ namespace Emby.Dlna.Didl if (width.HasValue && height.HasValue) { - var newSize = DrawingUtils.Resize(new ImageSize - { - Height = height.Value, - Width = width.Value - - }, 0, 0, maxWidth, maxHeight); + var newSize = DrawingUtils.Resize( + new ImageDimensions(width.Value, height.Value), 0, 0, maxWidth, maxHeight); - width = Convert.ToInt32(newSize.Width); - height = Convert.ToInt32(newSize.Height); + width = newSize.Width; + height = newSize.Height; var normalizedFormat = format .Replace("jpeg", "jpg", StringComparison.OrdinalIgnoreCase); diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index 8e82e6f69..790625705 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -162,9 +162,7 @@ namespace Emby.Dlna.PlayTo uuid = location.GetMD5().ToString("N"); } - string deviceName = null; - - var sessionInfo = _sessionManager.LogSessionActivity("DLNA", _appHost.ApplicationVersion, uuid, deviceName, uri.OriginalString, null); + var sessionInfo = _sessionManager.LogSessionActivity("DLNA", _appHost.ApplicationVersion, uuid, null, uri.OriginalString, null); var controller = sessionInfo.SessionControllers.OfType<PlayToController>().FirstOrDefault(); @@ -172,7 +170,7 @@ namespace Emby.Dlna.PlayTo { var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger, _timerFactory, cancellationToken).ConfigureAwait(false); - deviceName = device.Properties.Name; + string deviceName = device.Properties.Name; _sessionManager.UpdateDeviceName(sessionInfo.Id, deviceName); @@ -186,8 +184,6 @@ namespace Emby.Dlna.PlayTo serverAddress = _appHost.GetLocalApiUrl(info.LocalIpAddress); } - string accessToken = null; - controller = new PlayToController(sessionInfo, _sessionManager, _libraryManager, @@ -196,7 +192,7 @@ namespace Emby.Dlna.PlayTo _userManager, _imageProcessor, serverAddress, - accessToken, + null, _deviceDiscovery, _userDataManager, _localization, diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index c750b60e2..8ac2b9b27 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -18,7 +18,6 @@ using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; using Microsoft.Extensions.Logging; -using SkiaSharp; namespace Emby.Drawing { @@ -66,7 +65,7 @@ namespace Emby.Drawing _appPaths = appPaths; ImageEnhancers = Array.Empty<IImageEnhancer>(); - + ImageHelper.ImageProcessor = this; } @@ -168,10 +167,10 @@ namespace Emby.Drawing string originalImagePath = originalImage.Path; DateTime dateModified = originalImage.DateModified; - ImageSize? originalImageSize = null; + ImageDimensions? originalImageSize = null; if (originalImage.Width > 0 && originalImage.Height > 0) { - originalImageSize = new ImageSize(originalImage.Width, originalImage.Height); + originalImageSize = new ImageDimensions(originalImage.Width, originalImage.Height); } if (!_imageEncoder.SupportsImageEncoding) @@ -231,7 +230,7 @@ namespace Emby.Drawing return (originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); } - ImageSize newSize = ImageHelper.GetNewImageSize(options, null); + ImageDimensions newSize = ImageHelper.GetNewImageSize(options, null); int quality = options.Quality; ImageFormat outputFormat = GetOutputFormat(options.SupportedOutputFormats, requiresTransparency); @@ -334,7 +333,7 @@ namespace Emby.Drawing /// <summary> /// Gets the cache file path based on a set of parameters /// </summary> - private string GetCacheFilePath(string originalPath, ImageSize outputSize, int quality, DateTime dateModified, ImageFormat format, bool addPlayedIndicator, double percentPlayed, int? unwatchedCount, int? blur, string backgroundColor, string foregroundLayer) + private string GetCacheFilePath(string originalPath, ImageDimensions outputSize, int quality, DateTime dateModified, ImageFormat format, bool addPlayedIndicator, double percentPlayed, int? unwatchedCount, int? blur, string backgroundColor, string foregroundLayer) { var filename = originalPath + "width=" + outputSize.Width @@ -378,26 +377,25 @@ namespace Emby.Drawing return GetCachePath(ResizedImageCachePath, filename, "." + format.ToString().ToLower()); } - public ImageSize GetImageSize(BaseItem item, ItemImageInfo info) + public ImageDimensions GetImageSize(BaseItem item, ItemImageInfo info) => GetImageSize(item, info, true); - public ImageSize GetImageSize(BaseItem item, ItemImageInfo info, bool updateItem) + public ImageDimensions GetImageSize(BaseItem item, ItemImageInfo info, bool updateItem) { int width = info.Width; int height = info.Height; if (height > 0 && width > 0) { - return new ImageSize(width, height); + return new ImageDimensions(width, height); } string path = info.Path; _logger.LogInformation("Getting image size for item {ItemType} {Path}", item.GetType().Name, path); - var size = GetImageSize(path); - - info.Height = Convert.ToInt32(size.Height); - info.Width = Convert.ToInt32(size.Width); + ImageDimensions size = GetImageSize(path); + info.Width = size.Width; + info.Height = size.Height; if (updateItem) { @@ -410,20 +408,8 @@ namespace Emby.Drawing /// <summary> /// Gets the size of the image. /// </summary> - public ImageSize GetImageSize(string path) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException(nameof(path)); - } - - using (var s = new SKFileStream(path)) - using (var codec = SKCodec.Create(s)) - { - var info = codec.Info; - return new ImageSize(info.Width, info.Height); - } - } + public ImageDimensions GetImageSize(string path) + => _imageEncoder.GetImageSize(path); /// <summary> /// Gets the image cache tag. diff --git a/Emby.Drawing/NullImageEncoder.cs b/Emby.Drawing/NullImageEncoder.cs index e6f205a1f..14f0424ac 100644 --- a/Emby.Drawing/NullImageEncoder.cs +++ b/Emby.Drawing/NullImageEncoder.cs @@ -37,7 +37,7 @@ namespace Emby.Drawing public bool SupportsImageEncoding => false; - public ImageSize GetImageSize(string path) + public ImageDimensions GetImageSize(string path) { throw new NotImplementedException(); } diff --git a/Emby.Drawing/PercentPlayedDrawer.cs b/Emby.Drawing/PercentPlayedDrawer.cs index 52b4329e1..3ce46bc12 100644 --- a/Emby.Drawing/PercentPlayedDrawer.cs +++ b/Emby.Drawing/PercentPlayedDrawer.cs @@ -8,7 +8,7 @@ namespace Emby.Drawing { private const int IndicatorHeight = 8; - public static void Process(SKCanvas canvas, ImageSize imageSize, double percent) + public static void Process(SKCanvas canvas, ImageDimensions imageSize, double percent) { using (var paint = new SKPaint()) { @@ -24,7 +24,7 @@ namespace Emby.Drawing foregroundWidth /= 100; paint.Color = SKColor.Parse("#FF52B54B"); - canvas.DrawRect(SKRect.Create(0, (float)endY - IndicatorHeight, Convert.ToInt32(Math.Round(foregroundWidth)), (float)endY), paint); + canvas.DrawRect(SKRect.Create(0, (float)endY - IndicatorHeight, Convert.ToInt32(foregroundWidth), (float)endY), paint); } } } diff --git a/Emby.Drawing/PlayedIndicatorDrawer.cs b/Emby.Drawing/PlayedIndicatorDrawer.cs index a82398fa5..38b5edc92 100644 --- a/Emby.Drawing/PlayedIndicatorDrawer.cs +++ b/Emby.Drawing/PlayedIndicatorDrawer.cs @@ -7,7 +7,7 @@ namespace Emby.Drawing { private const int OffsetFromTopRightCorner = 38; - public static void DrawPlayedIndicator(SKCanvas canvas, ImageSize imageSize) + public static void DrawPlayedIndicator(SKCanvas canvas, ImageDimensions imageSize) { var x = imageSize.Width - OffsetFromTopRightCorner; diff --git a/Emby.Drawing/SkiaEncoder.cs b/Emby.Drawing/SkiaEncoder.cs index 9883b3cca..aae10f6cc 100644 --- a/Emby.Drawing/SkiaEncoder.cs +++ b/Emby.Drawing/SkiaEncoder.cs @@ -168,18 +168,14 @@ namespace Emby.Drawing } } - public ImageSize GetImageSize(string path) + public ImageDimensions GetImageSize(string path) { using (var s = new SKFileStream(path)) using (var codec = SKCodec.Create(s)) { var info = codec.Info; - return new ImageSize - { - Width = info.Width, - Height = info.Height - }; + return new ImageDimensions(info.Width, info.Height); } } @@ -513,7 +509,7 @@ namespace Emby.Drawing //_logger.LogInformation("Color type {0}", bitmap.Info.ColorType); - var originalImageSize = new ImageSize(bitmap.Width, bitmap.Height); + var originalImageSize = new ImageDimensions(bitmap.Width, bitmap.Height); if (!options.CropWhiteSpace && options.HasDefaultOptions(inputPath, originalImageSize) && !autoOrient) { @@ -523,8 +519,8 @@ namespace Emby.Drawing var newImageSize = ImageHelper.GetNewImageSize(options, originalImageSize); - var width = Convert.ToInt32(Math.Round(newImageSize.Width)); - var height = Convert.ToInt32(Math.Round(newImageSize.Height)); + var width = newImageSize.Width; + var height = newImageSize.Height; using (var resizedBitmap = new SKBitmap(width, height))//, bitmap.ColorType, bitmap.AlphaType)) { @@ -626,7 +622,7 @@ namespace Emby.Drawing { try { - var currentImageSize = new ImageSize(imageWidth, imageHeight); + var currentImageSize = new ImageDimensions(imageWidth, imageHeight); if (options.AddPlayedIndicator) { diff --git a/Emby.Drawing/UnplayedCountIndicator.cs b/Emby.Drawing/UnplayedCountIndicator.cs index 16c084a21..4d0cc9d40 100644 --- a/Emby.Drawing/UnplayedCountIndicator.cs +++ b/Emby.Drawing/UnplayedCountIndicator.cs @@ -8,7 +8,7 @@ namespace Emby.Drawing { private const int OffsetFromTopRightCorner = 38; - public static void DrawUnplayedCountIndicator(SKCanvas canvas, ImageSize imageSize, int count) + public static void DrawUnplayedCountIndicator(SKCanvas canvas, ImageDimensions imageSize, int count) { var x = imageSize.Width - OffsetFromTopRightCorner; var text = count.ToString(CultureInfo.InvariantCulture); diff --git a/Emby.Naming/AudioBook/AudioBookResolver.cs b/Emby.Naming/AudioBook/AudioBookResolver.cs index 67451a639..67ab62e80 100644 --- a/Emby.Naming/AudioBook/AudioBookResolver.cs +++ b/Emby.Naming/AudioBook/AudioBookResolver.cs @@ -36,7 +36,7 @@ namespace Emby.Naming.AudioBook return null; } - var extension = Path.GetExtension(path) ?? string.Empty; + var extension = Path.GetExtension(path); // Check supported extensions if (!_options.AudioFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) { diff --git a/Emby.Photos/PhotoProvider.cs b/Emby.Photos/PhotoProvider.cs index 4e483ad5b..aaebe1a21 100644 --- a/Emby.Photos/PhotoProvider.cs +++ b/Emby.Photos/PhotoProvider.cs @@ -185,8 +185,8 @@ namespace Emby.Photos if (size.Width > 0 && size.Height > 0) { - item.Width = Convert.ToInt32(size.Width); - item.Height = Convert.ToInt32(size.Height); + item.Width = size.Width; + item.Height = size.Height; } } catch (ArgumentException) diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index aef72c697..a8e8f815a 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; @@ -93,18 +92,18 @@ namespace Emby.Server.Implementations.Activity _appHost.ApplicationUpdated += _appHost_ApplicationUpdated; } - async void _deviceManager_CameraImageUploaded(object sender, GenericEventArgs<CameraImageUploadInfo> e) + void _deviceManager_CameraImageUploaded(object sender, GenericEventArgs<CameraImageUploadInfo> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("CameraImageUploadedFrom"), e.Argument.Device.Name), Type = NotificationType.CameraImageUploaded.ToString() }); } - async void _userManager_UserLockedOut(object sender, GenericEventArgs<User> e) + void _userManager_UserLockedOut(object sender, GenericEventArgs<User> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserLockedOutWithName"), e.Argument.Name), Type = NotificationType.UserLockedOut.ToString(), @@ -112,9 +111,9 @@ namespace Emby.Server.Implementations.Activity }); } - async void _subManager_SubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e) + void _subManager_SubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("SubtitleDownloadFailureFromForItem"), e.Provider, Notifications.Notifications.GetItemName(e.Item)), Type = "SubtitleDownloadFailure", @@ -123,7 +122,7 @@ namespace Emby.Server.Implementations.Activity }); } - async void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e) + void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e) { var item = e.MediaInfo; @@ -146,7 +145,7 @@ namespace Emby.Server.Implementations.Activity var user = e.Users.First(); - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserStoppedPlayingItemWithValues"), user.Name, GetItemName(item), e.DeviceName), Type = GetPlaybackStoppedNotificationType(item.MediaType), @@ -154,7 +153,7 @@ namespace Emby.Server.Implementations.Activity }); } - async void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e) + void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e) { var item = e.MediaInfo; @@ -177,7 +176,7 @@ namespace Emby.Server.Implementations.Activity var user = e.Users.First(); - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserStartedPlayingItemWithValues"), user.Name, GetItemName(item), e.DeviceName), Type = GetPlaybackNotificationType(item.MediaType), @@ -238,7 +237,7 @@ namespace Emby.Server.Implementations.Activity return null; } - async void _sessionManager_SessionEnded(object sender, SessionEventArgs e) + void _sessionManager_SessionEnded(object sender, SessionEventArgs e) { string name; var session = e.SessionInfo; @@ -255,7 +254,7 @@ namespace Emby.Server.Implementations.Activity name = string.Format(_localization.GetLocalizedString("UserOfflineFromDevice"), session.UserName, session.DeviceName); } - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = name, Type = "SessionEnded", @@ -264,11 +263,11 @@ namespace Emby.Server.Implementations.Activity }); } - async void _sessionManager_AuthenticationSucceeded(object sender, GenericEventArgs<AuthenticationResult> e) + void _sessionManager_AuthenticationSucceeded(object sender, GenericEventArgs<AuthenticationResult> e) { var user = e.Argument.User; - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("AuthenticationSucceededWithUserName"), user.Name), Type = "AuthenticationSucceeded", @@ -277,9 +276,9 @@ namespace Emby.Server.Implementations.Activity }); } - async void _sessionManager_AuthenticationFailed(object sender, GenericEventArgs<AuthenticationRequest> e) + void _sessionManager_AuthenticationFailed(object sender, GenericEventArgs<AuthenticationRequest> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("FailedLoginAttemptWithUserName"), e.Argument.Username), Type = "AuthenticationFailed", @@ -288,9 +287,9 @@ namespace Emby.Server.Implementations.Activity }); } - async void _appHost_ApplicationUpdated(object sender, GenericEventArgs<PackageVersionInfo> e) + void _appHost_ApplicationUpdated(object sender, GenericEventArgs<PackageVersionInfo> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("MessageApplicationUpdatedTo"), e.Argument.versionStr), Type = NotificationType.ApplicationUpdateInstalled.ToString(), @@ -298,27 +297,27 @@ namespace Emby.Server.Implementations.Activity }); } - async void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) + void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("MessageNamedServerConfigurationUpdatedWithValue"), e.Key), Type = "NamedConfigurationUpdated" }); } - async void _config_ConfigurationUpdated(object sender, EventArgs e) + void _config_ConfigurationUpdated(object sender, EventArgs e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = _localization.GetLocalizedString("MessageServerConfigurationUpdated"), Type = "ServerConfigurationUpdated" }); } - async void _userManager_UserPolicyUpdated(object sender, GenericEventArgs<User> e) + void _userManager_UserPolicyUpdated(object sender, GenericEventArgs<User> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserPolicyUpdatedWithName"), e.Argument.Name), Type = "UserPolicyUpdated", @@ -326,18 +325,18 @@ namespace Emby.Server.Implementations.Activity }); } - async void _userManager_UserDeleted(object sender, GenericEventArgs<User> e) + void _userManager_UserDeleted(object sender, GenericEventArgs<User> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserDeletedWithName"), e.Argument.Name), Type = "UserDeleted" }); } - async void _userManager_UserPasswordChanged(object sender, GenericEventArgs<User> e) + void _userManager_UserPasswordChanged(object sender, GenericEventArgs<User> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserPasswordChangedWithName"), e.Argument.Name), Type = "UserPasswordChanged", @@ -345,9 +344,9 @@ namespace Emby.Server.Implementations.Activity }); } - async void _userManager_UserCreated(object sender, GenericEventArgs<User> e) + void _userManager_UserCreated(object sender, GenericEventArgs<User> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserCreatedWithName"), e.Argument.Name), Type = "UserCreated", @@ -355,9 +354,9 @@ namespace Emby.Server.Implementations.Activity }); } - async void _subManager_SubtitlesDownloaded(object sender, SubtitleDownloadEventArgs e) + void _subManager_SubtitlesDownloaded(object sender, SubtitleDownloadEventArgs e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("SubtitlesDownloadedForItem"), Notifications.Notifications.GetItemName(e.Item)), Type = "SubtitlesDownloaded", @@ -366,7 +365,7 @@ namespace Emby.Server.Implementations.Activity }); } - async void _sessionManager_SessionStarted(object sender, SessionEventArgs e) + void _sessionManager_SessionStarted(object sender, SessionEventArgs e) { string name; var session = e.SessionInfo; @@ -383,7 +382,7 @@ namespace Emby.Server.Implementations.Activity name = string.Format(_localization.GetLocalizedString("UserOnlineFromDevice"), session.UserName, session.DeviceName); } - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = name, Type = "SessionStarted", @@ -392,9 +391,9 @@ namespace Emby.Server.Implementations.Activity }); } - async void _installationManager_PluginUpdated(object sender, GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> e) + void _installationManager_PluginUpdated(object sender, GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("PluginUpdatedWithName"), e.Argument.Item1.Name), Type = NotificationType.PluginUpdateInstalled.ToString(), @@ -403,18 +402,18 @@ namespace Emby.Server.Implementations.Activity }); } - async void _installationManager_PluginUninstalled(object sender, GenericEventArgs<IPlugin> e) + void _installationManager_PluginUninstalled(object sender, GenericEventArgs<IPlugin> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("PluginUninstalledWithName"), e.Argument.Name), Type = NotificationType.PluginUninstalled.ToString() }); } - async void _installationManager_PluginInstalled(object sender, GenericEventArgs<PackageVersionInfo> e) + void _installationManager_PluginInstalled(object sender, GenericEventArgs<PackageVersionInfo> e) { - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("PluginInstalledWithName"), e.Argument.name), Type = NotificationType.PluginInstalled.ToString(), @@ -422,11 +421,11 @@ namespace Emby.Server.Implementations.Activity }); } - async void _installationManager_PackageInstallationFailed(object sender, InstallationFailedEventArgs e) + void _installationManager_PackageInstallationFailed(object sender, InstallationFailedEventArgs e) { var installationInfo = e.InstallationInfo; - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("NameInstallFailed"), installationInfo.Name), Type = NotificationType.InstallationFailed.ToString(), @@ -435,7 +434,7 @@ namespace Emby.Server.Implementations.Activity }); } - async void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e) + void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e) { var result = e.Result; var task = e.Task; @@ -462,7 +461,7 @@ namespace Emby.Server.Implementations.Activity vals.Add(e.Result.LongErrorMessage); } - await CreateLogEntry(new ActivityLogEntry + CreateLogEntry(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name), Type = NotificationType.TaskFailed.ToString(), @@ -473,11 +472,11 @@ namespace Emby.Server.Implementations.Activity } } - private async Task CreateLogEntry(ActivityLogEntry entry) + private void CreateLogEntry(ActivityLogEntry entry) { try { - await _activityManager.CreateAsync(entry); + _activityManager.Create(entry); } catch { diff --git a/Emby.Server.Implementations/Activity/ActivityManager.cs b/Emby.Server.Implementations/Activity/ActivityManager.cs index 8fcacb002..6febcc2f7 100644 --- a/Emby.Server.Implementations/Activity/ActivityManager.cs +++ b/Emby.Server.Implementations/Activity/ActivityManager.cs @@ -1,10 +1,9 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Activity; using MediaBrowser.Model.Events; +using MediaBrowser.Model.Querying; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Activity @@ -27,38 +26,20 @@ namespace Emby.Server.Implementations.Activity _userManager = userManager; } - public async Task CreateAsync(ActivityLogEntry entry) + public void Create(ActivityLogEntry entry) { entry.Date = DateTime.UtcNow; - await _repo.CreateAsync(entry); + _repo.Create(entry); EntryCreated?.Invoke(this, new GenericEventArgs<ActivityLogEntry>(entry)); } - public IEnumerable<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, bool? hasUserId, int? startIndex, int? limit) + public QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, bool? hasUserId, int? startIndex, int? limit) { - var result = _repo.GetActivityLogEntries(); + var result = _repo.GetActivityLogEntries(minDate, hasUserId, startIndex, limit); - if (minDate.HasValue) - { - result = result.Where(x => x.Date >= minDate.Value); - } - if (hasUserId.HasValue) - { - result = result.Where(x => x.UserId != null && x.UserId != Guid.Empty); - } - if (startIndex.HasValue) - { - result = result.Where(x => x.Id >= startIndex.Value); - } - if (limit.HasValue) - { - result = result.Take(limit.Value); - } - - // Add images for each user - foreach (var item in result) + foreach (var item in result.Items.Where(i => !i.UserId.Equals(Guid.Empty))) { var user = _userManager.GetUserById(item.UserId); @@ -69,7 +50,12 @@ namespace Emby.Server.Implementations.Activity } } - return result.AsEnumerable(); + return result; + } + + public QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, int? startIndex, int? limit) + { + return GetActivityLogEntries(minDate, null, startIndex, limit); } } } diff --git a/Emby.Server.Implementations/Activity/ActivityRepository.cs b/Emby.Server.Implementations/Activity/ActivityRepository.cs index af0b20d92..aeed8b6f1 100644 --- a/Emby.Server.Implementations/Activity/ActivityRepository.cs +++ b/Emby.Server.Implementations/Activity/ActivityRepository.cs @@ -1,37 +1,310 @@ +using System; +using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; -using System.Threading.Tasks; +using Emby.Server.Implementations.Data; +using MediaBrowser.Controller; using MediaBrowser.Model.Activity; -using Microsoft.EntityFrameworkCore; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Querying; +using Microsoft.Extensions.Logging; +using SQLitePCL.pretty; namespace Emby.Server.Implementations.Activity { - public class ActivityRepository : DbContext, IActivityRepository + public class ActivityRepository : BaseSqliteRepository, IActivityRepository { - protected string _dataDirPath; + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + protected IFileSystem FileSystem { get; private set; } - public DbSet<ActivityLogEntry> ActivityLogs { get; set; } + public ActivityRepository(ILoggerFactory loggerFactory, IServerApplicationPaths appPaths, IFileSystem fileSystem) + : base(loggerFactory.CreateLogger(nameof(ActivityRepository))) + { + DbFilePath = Path.Combine(appPaths.DataPath, "activitylog.db"); + FileSystem = fileSystem; + } - public ActivityRepository(string dataDirPath) + public void Initialize() { - _dataDirPath = dataDirPath; + try + { + InitializeInternal(); + } + catch (Exception ex) + { + Logger.LogError(ex, "Error loading database file. Will reset and retry."); + + FileSystem.DeleteFile(DbFilePath); + + InitializeInternal(); + } } - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + private void InitializeInternal() { - // Ensure the dir exists - Directory.CreateDirectory(_dataDirPath); + using (var connection = CreateConnection()) + { + RunDefaultInitialization(connection); + + connection.RunQueries(new[] + { + "create table if not exists ActivityLog (Id INTEGER PRIMARY KEY, Name TEXT NOT NULL, Overview TEXT, ShortOverview TEXT, Type TEXT NOT NULL, ItemId TEXT, UserId TEXT, DateCreated DATETIME NOT NULL, LogSeverity TEXT NOT NULL)", + "drop index if exists idx_ActivityLogEntries" + }); + + TryMigrate(connection); + } + } - optionsBuilder.UseSqlite($"Filename={Path.Combine(_dataDirPath, "activitylog.sqlite.db")}"); + private void TryMigrate(ManagedConnection connection) + { + try + { + if (TableExists(connection, "ActivityLogEntries")) + { + connection.RunQueries(new[] + { + "INSERT INTO ActivityLog (Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity) SELECT Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity FROM ActivityLogEntries", + "drop table if exists ActivityLogEntries" + }); + } + } + catch (Exception ex) + { + Logger.LogError(ex, "Error migrating activity log database"); + } } - public async Task CreateAsync(ActivityLogEntry entry) + private const string BaseActivitySelectText = "select Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity from ActivityLog"; + + public void Create(ActivityLogEntry entry) { - await ActivityLogs.AddAsync(entry); - await SaveChangesAsync(); + if (entry == null) + { + throw new ArgumentNullException(nameof(entry)); + } + + using (WriteLock.Write()) + using (var connection = CreateConnection()) + { + connection.RunInTransaction(db => + { + using (var statement = db.PrepareStatement("insert into ActivityLog (Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity) values (@Name, @Overview, @ShortOverview, @Type, @ItemId, @UserId, @DateCreated, @LogSeverity)")) + { + statement.TryBind("@Name", entry.Name); + + statement.TryBind("@Overview", entry.Overview); + statement.TryBind("@ShortOverview", entry.ShortOverview); + statement.TryBind("@Type", entry.Type); + statement.TryBind("@ItemId", entry.ItemId); + + if (entry.UserId.Equals(Guid.Empty)) + { + statement.TryBindNull("@UserId"); + } + else + { + statement.TryBind("@UserId", entry.UserId.ToString("N")); + } + + statement.TryBind("@DateCreated", entry.Date.ToDateTimeParamValue()); + statement.TryBind("@LogSeverity", entry.Severity.ToString()); + + statement.MoveNext(); + } + }, TransactionMode); + } + } + + public void Update(ActivityLogEntry entry) + { + if (entry == null) + { + throw new ArgumentNullException(nameof(entry)); + } + + using (WriteLock.Write()) + using (var connection = CreateConnection()) + { + connection.RunInTransaction(db => + { + using (var statement = db.PrepareStatement("Update ActivityLog set Name=@Name,Overview=@Overview,ShortOverview=@ShortOverview,Type=@Type,ItemId=@ItemId,UserId=@UserId,DateCreated=@DateCreated,LogSeverity=@LogSeverity where Id=@Id")) + { + statement.TryBind("@Id", entry.Id); + + statement.TryBind("@Name", entry.Name); + statement.TryBind("@Overview", entry.Overview); + statement.TryBind("@ShortOverview", entry.ShortOverview); + statement.TryBind("@Type", entry.Type); + statement.TryBind("@ItemId", entry.ItemId); + + if (entry.UserId.Equals(Guid.Empty)) + { + statement.TryBindNull("@UserId"); + } + else + { + statement.TryBind("@UserId", entry.UserId.ToString("N")); + } + + statement.TryBind("@DateCreated", entry.Date.ToDateTimeParamValue()); + statement.TryBind("@LogSeverity", entry.Severity.ToString()); + + statement.MoveNext(); + } + }, TransactionMode); + } + } + + public QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, bool? hasUserId, int? startIndex, int? limit) + { + using (WriteLock.Read()) + using (var connection = CreateConnection(true)) + { + var commandText = BaseActivitySelectText; + var whereClauses = new List<string>(); + + if (minDate.HasValue) + { + whereClauses.Add("DateCreated>=@DateCreated"); + } + if (hasUserId.HasValue) + { + if (hasUserId.Value) + { + whereClauses.Add("UserId not null"); + } + else + { + whereClauses.Add("UserId is null"); + } + } + + var whereTextWithoutPaging = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); + + if (startIndex.HasValue && startIndex.Value > 0) + { + var pagingWhereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); + + whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM ActivityLog {0} ORDER BY DateCreated DESC LIMIT {1})", + pagingWhereText, + startIndex.Value.ToString(_usCulture))); + } + + var whereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); + + commandText += whereText; + + commandText += " ORDER BY DateCreated DESC"; + + if (limit.HasValue) + { + commandText += " LIMIT " + limit.Value.ToString(_usCulture); + } + + var statementTexts = new List<string>(); + statementTexts.Add(commandText); + statementTexts.Add("select count (Id) from ActivityLog" + whereTextWithoutPaging); + + return connection.RunInTransaction(db => + { + var list = new List<ActivityLogEntry>(); + var result = new QueryResult<ActivityLogEntry>(); + + var statements = PrepareAllSafe(db, statementTexts).ToList(); + + using (var statement = statements[0]) + { + if (minDate.HasValue) + { + statement.TryBind("@DateCreated", minDate.Value.ToDateTimeParamValue()); + } + + foreach (var row in statement.ExecuteQuery()) + { + list.Add(GetEntry(row)); + } + } + + using (var statement = statements[1]) + { + if (minDate.HasValue) + { + statement.TryBind("@DateCreated", minDate.Value.ToDateTimeParamValue()); + } + + result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); + } + + result.Items = list.ToArray(); + return result; + + }, ReadTransactionMode); + } } - public IQueryable<ActivityLogEntry> GetActivityLogEntries() - => ActivityLogs; + private static ActivityLogEntry GetEntry(IReadOnlyList<IResultSetValue> reader) + { + var index = 0; + + var info = new ActivityLogEntry + { + Id = reader[index].ToInt64() + }; + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.Name = reader[index].ToString(); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.Overview = reader[index].ToString(); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.ShortOverview = reader[index].ToString(); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.Type = reader[index].ToString(); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.ItemId = reader[index].ToString(); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.UserId = new Guid(reader[index].ToString()); + } + + index++; + info.Date = reader[index].ReadDateTime(); + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.Severity = (LogLevel)Enum.Parse(typeof(LogLevel), reader[index].ToString(), true); + } + + return info; + } } } diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index f5a4f1581..f0a914922 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -244,8 +244,6 @@ namespace Emby.Server.Implementations /// </summary> protected readonly SimpleInjector.Container Container = new SimpleInjector.Container(); - protected ISystemEvents SystemEvents { get; set; } - /// <summary> /// Gets the server configuration manager. /// </summary> @@ -317,7 +315,7 @@ namespace Emby.Server.Implementations private IUserDataManager UserDataManager { get; set; } private IUserRepository UserRepository { get; set; } internal IDisplayPreferencesRepository DisplayPreferencesRepository { get; set; } - internal IItemRepository ItemRepository { get; set; } + internal SqliteItemRepository ItemRepository { get; set; } private INotificationManager NotificationManager { get; set; } private ISubtitleManager SubtitleManager { get; set; } @@ -371,7 +369,6 @@ namespace Emby.Server.Implementations IFileSystem fileSystem, IEnvironmentInfo environmentInfo, IImageEncoder imageEncoder, - ISystemEvents systemEvents, INetworkManager networkManager) { @@ -383,7 +380,6 @@ namespace Emby.Server.Implementations NetworkManager = networkManager; networkManager.LocalSubnetsFn = GetConfiguredLocalSubnets; EnvironmentInfo = environmentInfo; - SystemEvents = systemEvents; ApplicationPaths = applicationPaths; LoggerFactory = loggerFactory; @@ -466,9 +462,8 @@ namespace Emby.Server.Implementations private static Tuple<Assembly, string> GetAssembly(Type type) { var assembly = type.GetTypeInfo().Assembly; - string path = null; - return new Tuple<Assembly, string>(assembly, path); + return new Tuple<Assembly, string>(assembly, null); } public virtual IStreamHelper CreateStreamHelper() @@ -709,7 +704,7 @@ namespace Emby.Server.Implementations } } - public async Task InitAsync() + public void Init() { HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber; HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber; @@ -739,7 +734,7 @@ namespace Emby.Server.Implementations SetHttpLimit(); - await RegisterResourcesAsync(); + RegisterResources(); FindParts(); } @@ -754,7 +749,7 @@ namespace Emby.Server.Implementations /// <summary> /// Registers resources that classes will depend on /// </summary> - protected async Task RegisterResourcesAsync() + protected void RegisterResources() { RegisterSingleInstance(ConfigurationManager); RegisterSingleInstance<IApplicationHost>(this); @@ -762,7 +757,6 @@ namespace Emby.Server.Implementations RegisterSingleInstance<IApplicationPaths>(ApplicationPaths); RegisterSingleInstance(JsonSerializer); - RegisterSingleInstance(SystemEvents); RegisterSingleInstance(LoggerFactory, false); RegisterSingleInstance(Logger); @@ -779,7 +773,7 @@ namespace Emby.Server.Implementations IsoManager = new IsoManager(); RegisterSingleInstance(IsoManager); - TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, LoggerFactory, FileSystemManager, SystemEvents); + TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, LoggerFactory, FileSystemManager); RegisterSingleInstance(TaskManager); RegisterSingleInstance(XmlSerializer); @@ -836,9 +830,8 @@ namespace Emby.Server.Implementations DisplayPreferencesRepository = displayPreferencesRepo; RegisterSingleInstance(DisplayPreferencesRepository); - var itemRepo = new SqliteItemRepository(ServerConfigurationManager, this, JsonSerializer, LoggerFactory, assemblyInfo, FileSystemManager, EnvironmentInfo, TimerFactory); - ItemRepository = itemRepo; - RegisterSingleInstance(ItemRepository); + ItemRepository = new SqliteItemRepository(ServerConfigurationManager, this, JsonSerializer, LoggerFactory, assemblyInfo); + RegisterSingleInstance<IItemRepository>(ItemRepository); AuthenticationRepository = GetAuthenticationRepository(); RegisterSingleInstance(AuthenticationRepository); @@ -853,7 +846,7 @@ namespace Emby.Server.Implementations var musicManager = new MusicManager(LibraryManager); RegisterSingleInstance<IMusicManager>(new MusicManager(LibraryManager)); - LibraryMonitor = new LibraryMonitor(LoggerFactory, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager, TimerFactory, SystemEvents, EnvironmentInfo); + LibraryMonitor = new LibraryMonitor(LoggerFactory, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager, TimerFactory, EnvironmentInfo); RegisterSingleInstance(LibraryMonitor); RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LoggerFactory, LibraryManager, UserManager)); @@ -931,7 +924,7 @@ namespace Emby.Server.Implementations EncodingManager = new MediaEncoder.EncodingManager(FileSystemManager, LoggerFactory, MediaEncoder, ChapterManager, LibraryManager); RegisterSingleInstance(EncodingManager); - var activityLogRepo = await GetActivityLogRepositoryAsync(); + var activityLogRepo = GetActivityLogRepository(); RegisterSingleInstance(activityLogRepo); RegisterSingleInstance<IActivityManager>(new ActivityManager(LoggerFactory, activityLogRepo, UserManager)); @@ -956,7 +949,7 @@ namespace Emby.Server.Implementations ((UserManager)UserManager).Initialize(); ((UserDataManager)UserDataManager).Repository = userDataRepo; - itemRepo.Initialize(userDataRepo, UserManager); + ItemRepository.Initialize(userDataRepo, UserManager); ((LibraryManager)LibraryManager).ItemRepository = ItemRepository; } @@ -1146,11 +1139,11 @@ namespace Emby.Server.Implementations return repo; } - private async Task<IActivityRepository> GetActivityLogRepositoryAsync() + private IActivityRepository GetActivityLogRepository() { - var repo = new ActivityRepository(ServerConfigurationManager.ApplicationPaths.DataPath); + var repo = new ActivityRepository(LoggerFactory, ServerConfigurationManager.ApplicationPaths, FileSystemManager); - await repo.Database.EnsureCreatedAsync(); + repo.Initialize(); return repo; } diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 21294f96f..ca7b48cc6 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -22,13 +22,10 @@ using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Playlists; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Reflection; using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.System; -using MediaBrowser.Model.Threading; using Microsoft.Extensions.Logging; using SQLitePCL.pretty; @@ -57,9 +54,6 @@ namespace Emby.Server.Implementations.Data /// The _app paths /// </summary> private readonly IServerConfigurationManager _config; - - private readonly IFileSystem _fileSystem; - private readonly IEnvironmentInfo _environmentInfo; private IServerApplicationHost _appHost; public IImageProcessor ImageProcessor { get; set; } @@ -72,16 +66,14 @@ namespace Emby.Server.Implementations.Data IServerApplicationHost appHost, IJsonSerializer jsonSerializer, ILoggerFactory loggerFactory, - IAssemblyInfo assemblyInfo, - IFileSystem fileSystem, - IEnvironmentInfo environmentInfo, - ITimerFactory timerFactory) + IAssemblyInfo assemblyInfo) : base(loggerFactory.CreateLogger(nameof(SqliteItemRepository))) { if (config == null) { throw new ArgumentNullException(nameof(config)); } + if (jsonSerializer == null) { throw new ArgumentNullException(nameof(jsonSerializer)); @@ -90,8 +82,6 @@ namespace Emby.Server.Implementations.Data _appHost = appHost; _config = config; _jsonSerializer = jsonSerializer; - _fileSystem = fileSystem; - _environmentInfo = environmentInfo; _typeMapper = new TypeMapper(assemblyInfo); DbFilePath = Path.Combine(_config.ApplicationPaths.DataPath, "library.db"); @@ -112,7 +102,7 @@ namespace Emby.Server.Implementations.Data { RunDefaultInitialization(connection); - var createMediaStreamsTableCommand + const string createMediaStreamsTableCommand = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, IsAvc BIT NULL, Title TEXT NULL, TimeBase TEXT NULL, CodecTimeBase TEXT NULL, ColorPrimaries TEXT NULL, ColorSpace TEXT NULL, ColorTransfer TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; string[] queries = { @@ -132,12 +122,11 @@ namespace Emby.Server.Implementations.Data "create index if not exists idxPeopleItemId1 on People(ItemId,ListOrder)", "create index if not exists idxPeopleName on People(Name)", - "create table if not exists "+ChaptersTableName+" (ItemId GUID, ChapterIndex INT NOT NULL, StartPositionTicks BIGINT NOT NULL, Name TEXT, ImagePath TEXT, PRIMARY KEY (ItemId, ChapterIndex))", + "create table if not exists " + ChaptersTableName + " (ItemId GUID, ChapterIndex INT NOT NULL, StartPositionTicks BIGINT NOT NULL, Name TEXT, ImagePath TEXT, PRIMARY KEY (ItemId, ChapterIndex))", createMediaStreamsTableCommand, "pragma shrink_memory" - }; connection.RunQueries(queries); @@ -247,7 +236,6 @@ namespace Emby.Server.Implementations.Data }, TransactionMode); string[] postQueries = - { // obsolete "drop index if exists idx_TypedBaseItems", @@ -325,14 +313,12 @@ namespace Emby.Server.Implementations.Data }; connection.RunQueries(postQueries); - - //await Vacuum(_connection).ConfigureAwait(false); } userDataRepo.Initialize(WriteLock, _connection, userManager); } - private readonly string[] _retriveItemColumns = + private static readonly string[] _retriveItemColumns = { "type", "data", @@ -402,7 +388,7 @@ namespace Emby.Server.Implementations.Data "OwnerId" }; - private readonly string[] _mediaStreamSaveColumns = + private static readonly string[] _mediaStreamSaveColumns = { "ItemId", "StreamIndex", @@ -443,7 +429,7 @@ namespace Emby.Server.Implementations.Data private static string GetSaveItemCommandText() { - var saveColumns = new List<string> + var saveColumns = new [] { "guid", "type", @@ -520,11 +506,11 @@ namespace Emby.Server.Implementations.Data "OwnerId" }; - var saveItemCommandCommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; + var saveItemCommandCommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns) + ") values ("; - for (var i = 0; i < saveColumns.Count; i++) + for (var i = 0; i < saveColumns.Length; i++) { - if (i > 0) + if (i != 0) { saveItemCommandCommandText += ","; } @@ -628,44 +614,39 @@ namespace Emby.Server.Implementations.Data private void SaveItemsInTranscation(IDatabaseConnection db, List<Tuple<BaseItem, List<Guid>, BaseItem, string, List<string>>> tuples) { - var requiresReset = false; - var statements = PrepareAllSafe(db, new string[] { GetSaveItemCommandText(), "delete from AncestorIds where ItemId=@ItemId" - - }).ToList(); + }); using (var saveItemStatement = statements[0]) + using (var deleteAncestorsStatement = statements[1]) { - using (var deleteAncestorsStatement = statements[1]) + var requiresReset = false; + foreach (var tuple in tuples) { - foreach (var tuple in tuples) + if (requiresReset) { - if (requiresReset) - { - saveItemStatement.Reset(); - } + saveItemStatement.Reset(); + } - var item = tuple.Item1; - var topParent = tuple.Item3; - var userDataKey = tuple.Item4; + var item = tuple.Item1; + var topParent = tuple.Item3; + var userDataKey = tuple.Item4; - SaveItem(item, topParent, userDataKey, saveItemStatement); - //logger.LogDebug(_saveItemCommand.CommandText); + SaveItem(item, topParent, userDataKey, saveItemStatement); - var inheritedTags = tuple.Item5; + var inheritedTags = tuple.Item5; - if (item.SupportsAncestors) - { - UpdateAncestors(item.Id, tuple.Item2, db, deleteAncestorsStatement); - } + if (item.SupportsAncestors) + { + UpdateAncestors(item.Id, tuple.Item2, db, deleteAncestorsStatement); + } - UpdateItemValues(item.Id, GetItemValuesToSave(item, inheritedTags), db); + UpdateItemValues(item.Id, GetItemValuesToSave(item, inheritedTags), db); - requiresReset = true; - } + requiresReset = true; } } } @@ -701,8 +682,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@Path", GetPathToSave(item.Path)); - var hasStartDate = item as IHasStartDate; - if (hasStartDate != null) + if (item is IHasStartDate hasStartDate) { saveItemStatement.TryBind("@StartDate", hasStartDate.StartDate); } @@ -722,8 +702,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@ChannelId", item.ChannelId.Equals(Guid.Empty) ? null : item.ChannelId.ToString("N")); - var hasProgramAttributes = item as IHasProgramAttributes; - if (hasProgramAttributes != null) + if (item is IHasProgramAttributes hasProgramAttributes) { saveItemStatement.TryBind("@IsMovie", hasProgramAttributes.IsMovie); saveItemStatement.TryBind("@IsSeries", hasProgramAttributes.IsSeries); @@ -822,7 +801,7 @@ namespace Emby.Server.Implementations.Data if (item.LockedFields.Length > 0) { - saveItemStatement.TryBind("@LockedFields", string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray())); + saveItemStatement.TryBind("@LockedFields", string.Join("|", item.LockedFields)); } else { @@ -831,7 +810,7 @@ namespace Emby.Server.Implementations.Data if (item.Studios.Length > 0) { - saveItemStatement.TryBind("@Studios", string.Join("|", item.Studios.ToArray())); + saveItemStatement.TryBind("@Studios", string.Join("|", item.Studios)); } else { @@ -847,10 +826,9 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBindNull("@Audio"); } - var livetvChannel = item as LiveTvChannel; - if (livetvChannel != null) + if (item is LiveTvChannel liveTvChannel) { - saveItemStatement.TryBind("@ExternalServiceId", livetvChannel.ServiceName); + saveItemStatement.TryBind("@ExternalServiceId", liveTvChannel.ServiceName); } else { @@ -870,21 +848,18 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@UnratedType", item.GetBlockUnratedType().ToString()); - if (topParent != null) + if (topParent == null) { - //logger.LogDebug("Item {0} has top parent {1}", item.Id, topParent.Id); - saveItemStatement.TryBind("@TopParentId", topParent.Id.ToString("N")); + saveItemStatement.TryBindNull("@TopParentId"); } else { - //logger.LogDebug("Item {0} has null top parent", item.Id); - saveItemStatement.TryBindNull("@TopParentId"); + saveItemStatement.TryBind("@TopParentId", topParent.Id.ToString("N")); } - var trailer = item as Trailer; - if (trailer != null && trailer.TrailerTypes.Length > 0) + if (item is Trailer trailer && trailer.TrailerTypes.Length > 0) { - saveItemStatement.TryBind("@TrailerTypes", string.Join("|", trailer.TrailerTypes.Select(i => i.ToString()).ToArray())); + saveItemStatement.TryBind("@TrailerTypes", string.Join("|", trailer.TrailerTypes)); } else { @@ -905,8 +880,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@PresentationUniqueKey", item.PresentationUniqueKey); saveItemStatement.TryBind("@OriginalTitle", item.OriginalTitle); - var video = item as Video; - if (video != null) + if (item is Video video) { saveItemStatement.TryBind("@PrimaryVersionId", video.PrimaryVersionId); } @@ -915,8 +889,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBindNull("@PrimaryVersionId"); } - var folder = item as Folder; - if (folder != null && folder.DateLastMediaAdded.HasValue) + if (item is Folder folder && folder.DateLastMediaAdded.HasValue) { saveItemStatement.TryBind("@DateLastMediaAdded", folder.DateLastMediaAdded.Value); } @@ -928,8 +901,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@Album", item.Album); saveItemStatement.TryBind("@IsVirtualItem", item.IsVirtualItem); - var hasSeriesName = item as IHasSeries; - if (hasSeriesName != null) + if (item is IHasSeries hasSeriesName) { saveItemStatement.TryBind("@SeriesName", hasSeriesName.SeriesName); } @@ -937,7 +909,6 @@ namespace Emby.Server.Implementations.Data { saveItemStatement.TryBindNull("@SeriesName"); } - if (string.IsNullOrWhiteSpace(userDataKey)) { saveItemStatement.TryBindNull("@UserDataKey"); @@ -947,12 +918,11 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@UserDataKey", userDataKey); } - var episode = item as Episode; - if (episode != null) + if (item is Episode episode) { saveItemStatement.TryBind("@SeasonName", episode.SeasonName); - var nullableSeasonId = episode.SeasonId.Equals(Guid.Empty) ? (Guid?)null : episode.SeasonId; + var nullableSeasonId = episode.SeasonId == Guid.Empty ? (Guid?)null : episode.SeasonId; saveItemStatement.TryBind("@SeasonId", nullableSeasonId); } @@ -962,8 +932,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBindNull("@SeasonId"); } - var hasSeries = item as IHasSeries; - if (hasSeries != null) + if (item is IHasSeries hasSeries) { var nullableSeriesId = hasSeries.SeriesId.Equals(Guid.Empty) ? (Guid?)null : hasSeries.SeriesId; @@ -1011,30 +980,22 @@ namespace Emby.Server.Implementations.Data } string artists = null; - var hasArtists = item as IHasArtist; - if (hasArtists != null) + if (item is IHasArtist hasArtists && hasArtists.Artists.Length > 0) { - if (hasArtists.Artists.Length > 0) - { - artists = string.Join("|", hasArtists.Artists); - } + artists = string.Join("|", hasArtists.Artists); } saveItemStatement.TryBind("@Artists", artists); string albumArtists = null; - var hasAlbumArtists = item as IHasAlbumArtist; - if (hasAlbumArtists != null) + if (item is IHasAlbumArtist hasAlbumArtists + && hasAlbumArtists.AlbumArtists.Length > 0) { - if (hasAlbumArtists.AlbumArtists.Length > 0) - { - albumArtists = string.Join("|", hasAlbumArtists.AlbumArtists); - } + albumArtists = string.Join("|", hasAlbumArtists.AlbumArtists); } saveItemStatement.TryBind("@AlbumArtists", albumArtists); saveItemStatement.TryBind("@ExternalId", item.ExternalId); - var program = item as LiveTvProgram; - if (program != null) + if (item is LiveTvProgram program) { saveItemStatement.TryBind("@ShowId", program.ShowId); } @@ -1043,14 +1004,14 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBindNull("@ShowId"); } - var ownerId = item.OwnerId; - if (!ownerId.Equals(Guid.Empty)) + Guid ownerId = item.OwnerId; + if (ownerId == Guid.Empty) { - saveItemStatement.TryBind("@OwnerId", ownerId); + saveItemStatement.TryBindNull("@OwnerId"); } else { - saveItemStatement.TryBindNull("@OwnerId"); + saveItemStatement.TryBind("@OwnerId", ownerId); } saveItemStatement.MoveNext(); @@ -1058,17 +1019,24 @@ namespace Emby.Server.Implementations.Data private static string SerializeProviderIds(BaseItem item) { - // Ideally we shouldn't need this IsNullOrWhiteSpace check but we're seeing some cases of bad data slip through - var ids = item.ProviderIds - .Where(i => !string.IsNullOrWhiteSpace(i.Value)) - .ToList(); + StringBuilder str = new StringBuilder(); + foreach (var i in item.ProviderIds) + { + // Ideally we shouldn't need this IsNullOrWhiteSpace check, + // but we're seeing some cases of bad data slip through + if (string.IsNullOrWhiteSpace(i.Value)) + { + continue; + } + str.Append($"{i.Key}={i.Value}|"); + } - if (ids.Count == 0) + if (str.Length == 0) { return null; } - - return string.Join("|", ids.Select(i => i.Key + "=" + i.Value).ToArray()); + str.Length -= 1; // Remove last | + return str.ToString(); } private static void DeserializeProviderIds(string value, BaseItem item) @@ -1104,10 +1072,17 @@ namespace Emby.Server.Implementations.Data { return null; } - - var imageStrings = images.Where(i => !string.IsNullOrWhiteSpace(i.Path)).Select(ToValueString).ToArray(); - - return string.Join("|", imageStrings); + StringBuilder str = new StringBuilder(); + foreach (var i in images) + { + if (string.IsNullOrWhiteSpace(i.Path)) + { + continue; + } + str.Append(ToValueString(i) + "|"); + } + str.Length -= 1; // Remove last | + return str.ToString(); } private void DeserializeImages(string value, BaseItem item) @@ -1184,13 +1159,11 @@ namespace Emby.Server.Implementations.Data if (parts.Length >= 5) { - if (int.TryParse(parts[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out var width)) + if (int.TryParse(parts[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out var width) + && int.TryParse(parts[4], NumberStyles.Integer, CultureInfo.InvariantCulture, out var height)) { - if (int.TryParse(parts[4], NumberStyles.Integer, CultureInfo.InvariantCulture, out var height)) - { - image.Width = width; - image.Height = height; - } + image.Width = width; + image.Height = height; } } @@ -1212,7 +1185,7 @@ namespace Emby.Server.Implementations.Data } CheckDisposed(); - //logger.LogInformation("Retrieving item {0}", id.ToString("N")); + using (WriteLock.Read()) { using (var connection = CreateConnection(true)) @@ -1240,7 +1213,7 @@ namespace Emby.Server.Implementations.Data { return false; } - if (type == typeof(UserRootFolder)) + else if (type == typeof(UserRootFolder)) { return false; } @@ -1250,63 +1223,59 @@ namespace Emby.Server.Implementations.Data { return false; } - if (type == typeof(MusicArtist)) + else if (type == typeof(MusicArtist)) { return false; } - - if (type == typeof(Person)) + else if (type == typeof(Person)) { return false; } - if (type == typeof(MusicGenre)) + else if (type == typeof(MusicGenre)) { return false; } - if (type == typeof(GameGenre)) + else if (type == typeof(GameGenre)) { return false; } - if (type == typeof(Genre)) + else if (type == typeof(Genre)) { return false; } - if (type == typeof(Studio)) + else if (type == typeof(Studio)) { return false; } - if (type == typeof(PlaylistsFolder)) + else if (type == typeof(PlaylistsFolder)) { return false; } - - if (type == typeof(PhotoAlbum)) + else if (type == typeof(PhotoAlbum)) { return false; } - - if (type == typeof(Year)) + else if (type == typeof(Year)) { return false; } - if (type == typeof(Book)) + else if (type == typeof(Book)) { return false; } - if (type == typeof(LiveTvProgram)) + else if (type == typeof(LiveTvProgram)) { return false; } - if (type == typeof(AudioBook)) + else if (type == typeof(AudioBook)) { return false; } - - if (type == typeof(Audio)) + else if (type == typeof(Audio)) { return false; } - if (type == typeof(MusicAlbum)) + else if (type == typeof(MusicAlbum)) { return false; } @@ -1327,8 +1296,6 @@ namespace Emby.Server.Implementations.Data if (type == null) { - //logger.LogDebug("Unknown type {0}", typeString); - return null; } @@ -1373,8 +1340,7 @@ namespace Emby.Server.Implementations.Data { if (!reader.IsDBNull(index)) { - var hasStartDate = item as IHasStartDate; - if (hasStartDate != null) + if (item is IHasStartDate hasStartDate) { hasStartDate.StartDate = reader[index].ReadDateTime(); } @@ -1396,8 +1362,7 @@ namespace Emby.Server.Implementations.Data if (enableProgramAttributes) { - var hasProgramAttributes = item as IHasProgramAttributes; - if (hasProgramAttributes != null) + if (item is IHasProgramAttributes hasProgramAttributes) { if (!reader.IsDBNull(index)) { @@ -1604,12 +1569,11 @@ namespace Emby.Server.Implementations.Data // But get this excluded from contexts where it is not needed if (hasServiceName) { - var livetvChannel = item as LiveTvChannel; - if (livetvChannel != null) + if (item is LiveTvChannel liveTvChannel) { if (!reader.IsDBNull(index)) { - livetvChannel.ServiceName = reader.GetString(index); + liveTvChannel.ServiceName = reader.GetString(index); } } index++; @@ -1634,15 +1598,17 @@ namespace Emby.Server.Implementations.Data { if (!reader.IsDBNull(index)) { - item.LockedFields = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).Select( - i => + IEnumerable<MetadataFields> GetLockedFields(string s) + { + foreach (var i in s.Split(new [] { '|' }, StringSplitOptions.RemoveEmptyEntries)) { if (Enum.TryParse(i, true, out MetadataFields parsedValue)) { - return parsedValue; + yield return parsedValue; } - return (MetadataFields?)null; - }).Where(i => i.HasValue).Select(i => i.Value).ToArray(); + } + } + item.LockedFields = GetLockedFields(reader.GetString(index)).ToArray(); } index++; } @@ -1667,21 +1633,21 @@ namespace Emby.Server.Implementations.Data if (hasTrailerTypes) { - var trailer = item as Trailer; - if (trailer != null) + if (item is Trailer trailer) { if (!reader.IsDBNull(index)) { - trailer.TrailerTypes = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).Select( - i => + IEnumerable<TrailerType> GetTrailerTypes(string s) + { + foreach (var i in s.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)) { if (Enum.TryParse(i, true, out TrailerType parsedValue)) { - return parsedValue; + yield return parsedValue; } - return (TrailerType?)null; - - }).Where(i => i.HasValue).Select(i => i.Value).ToArray(); + } + } + trailer.TrailerTypes = GetTrailerTypes(reader.GetString(index)).ToArray(); } } index++; @@ -1696,8 +1662,7 @@ namespace Emby.Server.Implementations.Data index++; } - var video = item as Video; - if (video != null) + if (item is Video video) { if (!reader.IsDBNull(index)) { @@ -1708,8 +1673,7 @@ namespace Emby.Server.Implementations.Data if (HasField(query, ItemFields.DateLastMediaAdded)) { - var folder = item as Folder; - if (folder != null && !reader.IsDBNull(index)) + if (item is Folder folder && !reader.IsDBNull(index)) { folder.DateLastMediaAdded = reader[index].TryReadDateTime(); } @@ -1734,8 +1698,7 @@ namespace Emby.Server.Implementations.Data } index++; - var hasSeriesName = item as IHasSeries; - if (hasSeriesName != null) + if (item is IHasSeries hasSeriesName) { if (!reader.IsDBNull(index)) { @@ -1746,8 +1709,7 @@ namespace Emby.Server.Implementations.Data if (hasEpisodeAttributes) { - var episode = item as Episode; - if (episode != null) + if (item is Episode episode) { if (!reader.IsDBNull(index)) { @@ -1834,7 +1796,7 @@ namespace Emby.Server.Implementations.Data { if (!reader.IsDBNull(index)) { - item.ProductionLocations = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray(); + item.ProductionLocations = reader.GetString(index).Split(new [] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToArray(); } index++; } @@ -1865,15 +1827,13 @@ namespace Emby.Server.Implementations.Data if (hasArtistFields) { - var hasArtists = item as IHasArtist; - if (hasArtists != null && !reader.IsDBNull(index)) + if (item is IHasArtist hasArtists && !reader.IsDBNull(index)) { hasArtists.Artists = reader.GetString(index).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); } index++; - var hasAlbumArtists = item as IHasAlbumArtist; - if (hasAlbumArtists != null && !reader.IsDBNull(index)) + if (item is IHasAlbumArtist hasAlbumArtists && !reader.IsDBNull(index)) { hasAlbumArtists.AlbumArtists = reader.GetString(index).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); } @@ -1900,19 +1860,11 @@ namespace Emby.Server.Implementations.Data if (enableProgramAttributes) { - var program = item as LiveTvProgram; - if (program != null) - { - if (!reader.IsDBNull(index)) - { - program.ShowId = reader.GetString(index); - } - index++; - } - else + if (item is LiveTvProgram program && !reader.IsDBNull(index)) { - index++; + program.ShowId = reader.GetString(index); } + index++; } if (!reader.IsDBNull(index)) @@ -2080,18 +2032,12 @@ namespace Emby.Server.Implementations.Data var insertText = new StringBuilder("insert into " + ChaptersTableName + " (ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath, ImageDateModified) values "); var endIndex = Math.Min(chapters.Count, startIndex + limit); - var isSubsequentRow = false; for (var i = startIndex; i < endIndex; i++) { - if (isSubsequentRow) - { - insertText.Append(","); - } - - insertText.AppendFormat("(@ItemId, @ChapterIndex{0}, @StartPositionTicks{0}, @Name{0}, @ImagePath{0}, @ImageDateModified{0})", i.ToString(CultureInfo.InvariantCulture)); - isSubsequentRow = true; + insertText.AppendFormat("(@ItemId, @ChapterIndex{0}, @StartPositionTicks{0}, @Name{0}, @ImagePath{0}, @ImageDateModified{0}),", i.ToString(CultureInfo.InvariantCulture)); } + insertText.Length -= 1; // Remove last , using (var statement = PrepareStatementSafe(db, insertText.ToString())) { @@ -2127,59 +2073,19 @@ namespace Emby.Server.Implementations.Data return false; } - var sortingFields = query.OrderBy.Select(i => i.Item1).ToList(); - - if (sortingFields.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - if (sortingFields.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - if (sortingFields.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - if (sortingFields.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - if (sortingFields.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - if (sortingFields.Contains(ItemSortBy.SeriesDatePlayed, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - - if (query.IsFavoriteOrLiked.HasValue) - { - return true; - } - - if (query.IsFavorite.HasValue) - { - return true; - } - - if (query.IsResumable.HasValue) - { - return true; - } + var sortingFields = query.OrderBy.Select(i => i.Item1); - if (query.IsPlayed.HasValue) - { - return true; - } - - if (query.IsLiked.HasValue) - { - return true; - } - - return false; + return sortingFields.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase) + || sortingFields.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase) + || sortingFields.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase) + || sortingFields.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase) + || sortingFields.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase) + || sortingFields.Contains(ItemSortBy.SeriesDatePlayed, StringComparer.OrdinalIgnoreCase) + || query.IsFavoriteOrLiked.HasValue + || query.IsFavorite.HasValue + || query.IsResumable.HasValue + || query.IsPlayed.HasValue + || query.IsLiked.HasValue; } private readonly List<ItemFields> allFields = Enum.GetNames(typeof(ItemFields)) @@ -2188,32 +2094,23 @@ namespace Emby.Server.Implementations.Data private string[] GetColumnNamesFromField(ItemFields field) { - if (field == ItemFields.Settings) - { - return new[] { "IsLocked", "PreferredMetadataCountryCode", "PreferredMetadataLanguage", "LockedFields" }; - } - if (field == ItemFields.ServiceName) - { - return new[] { "ExternalServiceId" }; - } - if (field == ItemFields.SortName) - { - return new[] { "ForcedSortName" }; - } - if (field == ItemFields.Taglines) - { - return new[] { "Tagline" }; - } - if (field == ItemFields.Tags) + switch (field) { - return new[] { "Tags" }; - } - if (field == ItemFields.IsHD) - { - return Array.Empty<string>(); + case ItemFields.Settings: + return new[] { "IsLocked", "PreferredMetadataCountryCode", "PreferredMetadataLanguage", "LockedFields" }; + case ItemFields.ServiceName: + return new[] { "ExternalServiceId" }; + case ItemFields.SortName: + return new[] { "ForcedSortName" }; + case ItemFields.Taglines: + return new[] { "Tagline" }; + case ItemFields.Tags: + return new[] { "Tags" }; + case ItemFields.IsHD: + return Array.Empty<string>(); + default: + return new[] { field.ToString() }; } - - return new[] { field.ToString() }; } private bool HasField(InternalItemsQuery query, ItemFields name) @@ -2347,12 +2244,7 @@ namespace Emby.Server.Implementations.Data return true; } - var types = new string[] - { - "Episode" - }; - - return types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase)); + return query.IncludeItemTypes.Contains("Episode", StringComparer.OrdinalIgnoreCase); } private bool HasTrailerTypes(InternalItemsQuery query) @@ -2362,12 +2254,7 @@ namespace Emby.Server.Implementations.Data return true; } - var types = new string[] - { - "Trailer" - }; - - return types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase)); + return query.IncludeItemTypes.Contains("Trailer", StringComparer.OrdinalIgnoreCase); } private bool HasArtistFields(InternalItemsQuery query) @@ -2403,12 +2290,7 @@ namespace Emby.Server.Implementations.Data private bool HasSeriesFields(InternalItemsQuery query) { - var excludeParentTypes = new string[] - { - "PhotoAlbum" - }; - - if (excludeParentTypes.Contains(query.ParentType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (string.Equals(query.ParentType, "PhotoAlbum", StringComparison.OrdinalIgnoreCase)) { return false; } @@ -2520,7 +2402,6 @@ namespace Emby.Server.Implementations.Data if (item.ProductionYear.HasValue) { - //builder.Append("+ ((ProductionYear=@ItemProductionYear) * 10)"); builder.Append("+(Select Case When Abs(COALESCE(ProductionYear, 0) - @ItemProductionYear) < 10 Then 10 Else 0 End )"); builder.Append("+(Select Case When Abs(COALESCE(ProductionYear, 0) - @ItemProductionYear) < 5 Then 5 Else 0 End )"); } @@ -2528,12 +2409,6 @@ namespace Emby.Server.Implementations.Data //// genres, tags builder.Append("+ ((Select count(CleanValue) from ItemValues where ItemId=Guid and CleanValue in (select CleanValue from itemvalues where ItemId=@SimilarItemId)) * 10)"); - //builder.Append("+ ((Select count(CleanValue) from ItemValues where ItemId=Guid and Type=3 and CleanValue in (select CleanValue from itemvalues where ItemId=@SimilarItemId and type=3)) * 3)"); - - //builder.Append("+ ((Select count(Name) from People where ItemId=Guid and Name in (select Name from People where ItemId=@SimilarItemId)) * 3)"); - - ////builder.Append("(select group_concat((Select Name from People where ItemId=Guid and Name in (Select Name from People where ItemId=@SimilarItemId)), '|'))"); - builder.Append(") as SimilarityScore"); list.Add(builder.ToString()); @@ -2642,7 +2517,7 @@ namespace Emby.Server.Implementations.Data if (groups.Count > 0) { - return " Group by " + string.Join(",", groups.ToArray()); + return " Group by " + string.Join(",", groups); } return string.Empty; @@ -2662,8 +2537,6 @@ namespace Emby.Server.Implementations.Data CheckDisposed(); - //logger.LogInformation("GetItemList: " + _environmentInfo.StackTrace); - var now = DateTime.UtcNow; // Hack for right now since we currently don't support filtering out these duplicates within a query @@ -2672,18 +2545,16 @@ namespace Emby.Server.Implementations.Data query.Limit = query.Limit.Value + 4; } - var commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count(distinct PresentationUniqueKey)" })) + GetFromText(); - commandText += GetJoinUserDataText(query); + var commandText = "select " + + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count(distinct PresentationUniqueKey)" })) + + GetFromText() + + GetJoinUserDataText(query); var whereClauses = GetWhereClauses(query, null); - - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - commandText += whereText; - - //commandText += GetGroupBy(query); + if (whereClauses.Count != 0) + { + commandText += " where " + string.Join(" AND ", whereClauses); + } using (WriteLock.Read()) { @@ -2720,8 +2591,6 @@ namespace Emby.Server.Implementations.Data CheckDisposed(); - //logger.LogInformation("GetItemList: " + _environmentInfo.StackTrace); - var now = DateTime.UtcNow; // Hack for right now since we currently don't support filtering out these duplicates within a query @@ -2730,20 +2599,20 @@ namespace Emby.Server.Implementations.Data query.Limit = query.Limit.Value + 4; } - var commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns)) + GetFromText(); - commandText += GetJoinUserDataText(query); + var commandText = "select " + + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns)) + + GetFromText() + + GetJoinUserDataText(query); var whereClauses = GetWhereClauses(query, null); - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - commandText += whereText; - - commandText += GetGroupBy(query); + if (whereClauses.Count != 0) + { + commandText += " where " + string.Join(" AND ", whereClauses); + } - commandText += GetOrderByText(query); + commandText += GetGroupBy(query) + + GetOrderByText(query); if (query.Limit.HasValue || query.StartIndex.HasValue) { @@ -2878,25 +2747,18 @@ namespace Emby.Server.Implementations.Data { var elapsed = (DateTime.UtcNow - startDate).TotalMilliseconds; - var slowThreshold = 1000; + int slowThreshold = 1000; #if DEBUG - slowThreshold = 10; + slowThreshold = 250; #endif if (elapsed >= slowThreshold) { - Logger.LogDebug("{2} query time (slow): {0}ms. Query: {1}", - Convert.ToInt32(elapsed), - commandText, - methodName); - } - else - { - //logger.LogDebug("{2} query time: {0}ms. Query: {1}", - // Convert.ToInt32(elapsed), - // commandText, - // methodName); + Logger.LogWarning("{0} query time (slow): {1}ms. Query: {2}", + methodName, + elapsed, + commandText); } } @@ -2918,7 +2780,6 @@ namespace Emby.Server.Implementations.Data TotalRecordCount = returnList.Count }; } - //logger.LogInformation("GetItems: " + _environmentInfo.StackTrace); var now = DateTime.UtcNow; @@ -2930,8 +2791,10 @@ namespace Emby.Server.Implementations.Data query.Limit = query.Limit.Value + 4; } - var commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns)) + GetFromText(); - commandText += GetJoinUserDataText(query); + var commandText = "select " + + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns)) + + GetFromText() + + GetJoinUserDataText(query); var whereClauses = GetWhereClauses(query, null); @@ -2939,13 +2802,9 @@ namespace Emby.Server.Implementations.Data string.Empty : " where " + string.Join(" AND ", whereClauses.ToArray()); - var whereTextWithoutPaging = whereText; - - commandText += whereText; - - commandText += GetGroupBy(query); - - commandText += GetOrderByText(query); + commandText += whereText + + GetGroupBy(query) + + GetOrderByText(query); if (query.Limit.HasValue || query.StartIndex.HasValue) { @@ -2986,8 +2845,8 @@ namespace Emby.Server.Implementations.Data commandText += " select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (guid)" })) + GetFromText(); } - commandText += GetJoinUserDataText(query); - commandText += whereTextWithoutPaging; + commandText += GetJoinUserDataText(query) + + whereText; statementTexts.Add(commandText); } @@ -3068,14 +2927,10 @@ namespace Emby.Server.Implementations.Data var orderBy = query.OrderBy.ToList(); var enableOrderInversion = false; - if (query.SimilarTo != null) + if (query.SimilarTo != null && orderBy.Count == 0) { - if (orderBy.Count == 0) - { - orderBy.Add(new ValueTuple<string, SortOrder>("SimilarityScore", SortOrder.Descending)); - orderBy.Add(new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending)); - //orderBy.Add(new Tuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending)); - } + orderBy.Add(new ValueTuple<string, SortOrder>("SimilarityScore", SortOrder.Descending)); + orderBy.Add(new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending)); } if (!string.IsNullOrEmpty(query.SearchTerm)) @@ -3104,7 +2959,7 @@ namespace Emby.Server.Implementations.Data var sortOrder = columnAscending ? "ASC" : "DESC"; return columnMap.Item1 + " " + sortOrder; - }).ToArray()); + })); } private ValueTuple<string, bool> MapOrderByField(string name, InternalItemsQuery query) @@ -3112,76 +2967,75 @@ namespace Emby.Server.Implementations.Data if (string.Equals(name, ItemSortBy.AirTime, StringComparison.OrdinalIgnoreCase)) { // TODO - return new ValueTuple<string, bool>("SortName", false); + return ("SortName", false); } - if (string.Equals(name, ItemSortBy.Runtime, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.Runtime, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("RuntimeTicks", false); + return ("RuntimeTicks", false); } - if (string.Equals(name, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("RANDOM()", false); + return ("RANDOM()", false); } - if (string.Equals(name, ItemSortBy.DatePlayed, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.DatePlayed, StringComparison.OrdinalIgnoreCase)) { if (query.GroupBySeriesPresentationUniqueKey) { - return new ValueTuple<string, bool>("MAX(LastPlayedDate)", false); + return ("MAX(LastPlayedDate)", false); } - return new ValueTuple<string, bool>("LastPlayedDate", false); + return ("LastPlayedDate", false); } - if (string.Equals(name, ItemSortBy.PlayCount, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.PlayCount, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("PlayCount", false); + return ("PlayCount", false); } - if (string.Equals(name, ItemSortBy.IsFavoriteOrLiked, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.IsFavoriteOrLiked, StringComparison.OrdinalIgnoreCase)) { - // (Select Case When Abs(COALESCE(ProductionYear, 0) - @ItemProductionYear) < 10 Then 2 Else 0 End ) - return new ValueTuple<string, bool>("(Select Case When IsFavorite is null Then 0 Else IsFavorite End )", true); + return ("(Select Case When IsFavorite is null Then 0 Else IsFavorite End )", true); } - if (string.Equals(name, ItemSortBy.IsFolder, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.IsFolder, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("IsFolder", true); + return ("IsFolder", true); } - if (string.Equals(name, ItemSortBy.IsPlayed, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.IsPlayed, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("played", true); + return ("played", true); } - if (string.Equals(name, ItemSortBy.IsUnplayed, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.IsUnplayed, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("played", false); + return ("played", false); } - if (string.Equals(name, ItemSortBy.DateLastContentAdded, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.DateLastContentAdded, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("DateLastMediaAdded", false); + return ("DateLastMediaAdded", false); } - if (string.Equals(name, ItemSortBy.Artist, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.Artist, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("(select CleanValue from itemvalues where ItemId=Guid and Type=0 LIMIT 1)", false); + return ("(select CleanValue from itemvalues where ItemId=Guid and Type=0 LIMIT 1)", false); } - if (string.Equals(name, ItemSortBy.AlbumArtist, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.AlbumArtist, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("(select CleanValue from itemvalues where ItemId=Guid and Type=1 LIMIT 1)", false); + return ("(select CleanValue from itemvalues where ItemId=Guid and Type=1 LIMIT 1)", false); } - if (string.Equals(name, ItemSortBy.OfficialRating, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.OfficialRating, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("InheritedParentalRatingValue", false); + return ("InheritedParentalRatingValue", false); } - if (string.Equals(name, ItemSortBy.Studio, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.Studio, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("(select CleanValue from itemvalues where ItemId=Guid and Type=3 LIMIT 1)", false); + return ("(select CleanValue from itemvalues where ItemId=Guid and Type=3 LIMIT 1)", false); } - if (string.Equals(name, ItemSortBy.SeriesDatePlayed, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.SeriesDatePlayed, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)", false); + return ("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)", false); } - if (string.Equals(name, ItemSortBy.SeriesSortName, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(name, ItemSortBy.SeriesSortName, StringComparison.OrdinalIgnoreCase)) { - return new ValueTuple<string, bool>("SeriesName", false); + return ("SeriesName", false); } - return new ValueTuple<string, bool>(name, false); + return (name, false); } public List<Guid> GetItemIdsList(InternalItemsQuery query) @@ -3192,24 +3046,22 @@ namespace Emby.Server.Implementations.Data } CheckDisposed(); - //logger.LogInformation("GetItemIdsList: " + _environmentInfo.StackTrace); var now = DateTime.UtcNow; - var commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" })) + GetFromText(); - commandText += GetJoinUserDataText(query); + var commandText = "select " + + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" })) + + GetFromText() + + GetJoinUserDataText(query); var whereClauses = GetWhereClauses(query, null); + if (whereClauses.Count != 0) + { + commandText += " where " + string.Join(" AND ", whereClauses); + } - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - commandText += whereText; - - commandText += GetGroupBy(query); - - commandText += GetOrderByText(query); + commandText += GetGroupBy(query) + + GetOrderByText(query); if (query.Limit.HasValue || query.StartIndex.HasValue) { @@ -3272,16 +3124,13 @@ namespace Emby.Server.Implementations.Data var commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid", "path" })) + GetFromText(); var whereClauses = GetWhereClauses(query, null); + if (whereClauses.Count != 0) + { + commandText += " where " + string.Join(" AND ", whereClauses); + } - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - commandText += whereText; - - commandText += GetGroupBy(query); - - commandText += GetOrderByText(query); + commandText += GetGroupBy(query) + + GetOrderByText(query); if (query.Limit.HasValue || query.StartIndex.HasValue) { @@ -3298,10 +3147,9 @@ namespace Emby.Server.Implementations.Data } } - var list = new List<Tuple<Guid, string>>(); - using (WriteLock.Read()) { + var list = new List<Tuple<Guid, string>>(); using (var connection = CreateConnection(true)) { using (var statement = PrepareStatementSafe(connection, commandText)) @@ -3352,12 +3200,13 @@ namespace Emby.Server.Implementations.Data TotalRecordCount = returnList.Count }; } - //logger.LogInformation("GetItemIds: " + _environmentInfo.StackTrace); var now = DateTime.UtcNow; - var commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" })) + GetFromText(); - commandText += GetJoinUserDataText(query); + var commandText = "select " + + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" })) + + GetFromText() + + GetJoinUserDataText(query); var whereClauses = GetWhereClauses(query, null); @@ -3365,13 +3214,9 @@ namespace Emby.Server.Implementations.Data string.Empty : " where " + string.Join(" AND ", whereClauses.ToArray()); - var whereTextWithoutPaging = whereText; - - commandText += whereText; - - commandText += GetGroupBy(query); - - commandText += GetOrderByText(query); + commandText += whereText + + GetGroupBy(query) + + GetOrderByText(query); if (query.Limit.HasValue || query.StartIndex.HasValue) { @@ -3413,8 +3258,8 @@ namespace Emby.Server.Implementations.Data commandText += " select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (guid)" })) + GetFromText(); } - commandText += GetJoinUserDataText(query); - commandText += whereTextWithoutPaging; + commandText += GetJoinUserDataText(query) + + whereText; statementTexts.Add(commandText); } @@ -3482,12 +3327,16 @@ namespace Emby.Server.Implementations.Data private bool IsAlphaNumeric(string str) { if (string.IsNullOrWhiteSpace(str)) + { return false; + } for (int i = 0; i < str.Length; i++) { if (!(char.IsLetter(str[i])) && (!(char.IsNumber(str[i])))) + { return false; + } } return true; @@ -3503,11 +3352,6 @@ namespace Emby.Server.Implementations.Data return IsAlphaNumeric(value); } - private bool IsValidId(string value) - { - return IsAlphaNumeric(value); - } - private bool IsValidPersonType(string value) { return IsAlphaNumeric(value); @@ -3520,13 +3364,6 @@ namespace Emby.Server.Implementations.Data query.IsVirtualItem = false; } - var whereClauses = new List<string>(); - - if (EnableJoinUserData(query)) - { - //whereClauses.Add("(UserId is null or UserId=@UserId)"); - } - var minWidth = query.MinWidth; var maxWidth = query.MaxWidth; @@ -3556,6 +3393,8 @@ namespace Emby.Server.Implementations.Data } } + var whereClauses = new List<string>(); + if (minWidth.HasValue) { whereClauses.Add("Width>=@MinWidth"); @@ -3601,47 +3440,8 @@ namespace Emby.Server.Implementations.Data var tags = query.Tags.ToList(); var excludeTags = query.ExcludeTags.ToList(); - //if (!(query.IsMovie ?? true) || !(query.IsSeries ?? true)) - //{ - // if (query.IsMovie.HasValue) - // { - // var alternateTypes = new List<string>(); - // if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Movie).Name)) - // { - // alternateTypes.Add(typeof(Movie).FullName); - // } - // if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Trailer).Name)) - // { - // alternateTypes.Add(typeof(Trailer).FullName); - // } - - // if (alternateTypes.Count == 0) - // { - // whereClauses.Add("IsMovie=@IsMovie"); - // if (statement != null) - // { - // statement.TryBind("@IsMovie", query.IsMovie); - // } - // } - // else - // { - // whereClauses.Add("(IsMovie is null OR IsMovie=@IsMovie)"); - // if (statement != null) - // { - // statement.TryBind("@IsMovie", query.IsMovie); - // } - // } - // } - //} - //else - //{ - - //} - if (query.IsMovie ?? false) { - var programAttribtues = new List<string>(); - var alternateTypes = new List<string>(); if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Movie).Name)) { @@ -3652,6 +3452,7 @@ namespace Emby.Server.Implementations.Data alternateTypes.Add(typeof(Trailer).FullName); } + var programAttribtues = new List<string>(); if (alternateTypes.Count == 0) { programAttribtues.Add("IsMovie=@IsMovie"); @@ -3666,7 +3467,7 @@ namespace Emby.Server.Implementations.Data statement.TryBind("@IsMovie", true); } - whereClauses.Add("(" + string.Join(" OR ", programAttribtues.ToArray()) + ")"); + whereClauses.Add("(" + string.Join(" OR ", programAttribtues) + ")"); } else if (query.IsMovie.HasValue) { @@ -3752,8 +3553,8 @@ namespace Emby.Server.Implementations.Data } else if (includeTypes.Length > 1) { - var inClause = string.Join(",", includeTypes.Select(i => "'" + i + "'").ToArray()); - whereClauses.Add(string.Format("type in ({0})", inClause)); + var inClause = string.Join(",", includeTypes.Select(i => "'" + i + "'")); + whereClauses.Add($"type in ({inClause})"); } // Only specify excluded types if no included types are specified @@ -3770,8 +3571,8 @@ namespace Emby.Server.Implementations.Data } else if (excludeTypes.Length > 1) { - var inClause = string.Join(",", excludeTypes.Select(i => "'" + i + "'").ToArray()); - whereClauses.Add(string.Format("type not in ({0})", inClause)); + var inClause = string.Join(",", excludeTypes.Select(i => "'" + i + "'")); + whereClauses.Add($"type not in ({inClause})"); } } @@ -3785,8 +3586,8 @@ namespace Emby.Server.Implementations.Data } else if (query.ChannelIds.Length > 1) { - var inClause = string.Join(",", query.ChannelIds.Select(i => "'" + i.ToString("N") + "'").ToArray()); - whereClauses.Add(string.Format("ChannelId in ({0})", inClause)); + var inClause = string.Join(",", query.ChannelIds.Select(i => "'" + i.ToString("N") + "'")); + whereClauses.Add($"ChannelId in ({inClause})"); } if (!query.ParentId.Equals(Guid.Empty)) @@ -3800,7 +3601,6 @@ namespace Emby.Server.Implementations.Data if (!string.IsNullOrWhiteSpace(query.Path)) { - //whereClauses.Add("(Path=@Path COLLATE NOCASE)"); whereClauses.Add("Path=@Path"); if (statement != null) { @@ -3862,18 +3662,6 @@ namespace Emby.Server.Implementations.Data } } - //if (query.MinPlayers.HasValue) - //{ - // whereClauses.Add("Players>=@MinPlayers"); - // cmd.Parameters.Add(cmd, "@MinPlayers", DbType.Int32).Value = query.MinPlayers.Value; - //} - - //if (query.MaxPlayers.HasValue) - //{ - // whereClauses.Add("Players<=@MaxPlayers"); - // cmd.Parameters.Add(cmd, "@MaxPlayers", DbType.Int32).Value = query.MaxPlayers.Value; - //} - if (query.IndexNumber.HasValue) { whereClauses.Add("IndexNumber=@IndexNumber"); @@ -3982,7 +3770,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4030,7 +3818,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4241,7 +4029,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4260,7 +4048,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4279,7 +4067,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4298,7 +4086,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4317,7 +4105,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4336,7 +4124,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4353,7 +4141,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4370,7 +4158,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4387,7 +4175,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4407,7 +4195,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4424,7 +4212,7 @@ namespace Emby.Server.Implementations.Data } index++; } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4631,7 +4419,7 @@ namespace Emby.Server.Implementations.Data } else if (queryMediaTypes.Length > 1) { - var val = string.Join(",", queryMediaTypes.Select(i => "'" + i + "'").ToArray()); + var val = string.Join(",", queryMediaTypes.Select(i => "'" + i + "'")); whereClauses.Add("MediaType in (" + val + ")"); } @@ -4650,7 +4438,7 @@ namespace Emby.Server.Implementations.Data index++; } - whereClauses.Add("(" + string.Join(" OR ", includeIds.ToArray()) + ")"); + whereClauses.Add("(" + string.Join(" OR ", includeIds) + ")"); } if (query.ExcludeItemIds.Length > 0) { @@ -4667,7 +4455,7 @@ namespace Emby.Server.Implementations.Data index++; } - whereClauses.Add(string.Join(" AND ", excludeIds.ToArray())); + whereClauses.Add(string.Join(" AND ", excludeIds)); } if (query.ExcludeProviderIds.Count > 0) @@ -4683,7 +4471,6 @@ namespace Emby.Server.Implementations.Data } var paramName = "@ExcludeProviderId" + index; - //excludeIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = '" + pair.Key + "'), '') <> " + paramName + ")"); excludeIds.Add("(ProviderIds is null or ProviderIds not like " + paramName + ")"); if (statement != null) { @@ -4696,7 +4483,7 @@ namespace Emby.Server.Implementations.Data if (excludeIds.Count > 0) { - whereClauses.Add(string.Join(" AND ", excludeIds.ToArray())); + whereClauses.Add(string.Join(" AND ", excludeIds)); } } @@ -4738,7 +4525,7 @@ namespace Emby.Server.Implementations.Data if (hasProviderIds.Count > 0) { - whereClauses.Add("(" + string.Join(" OR ", hasProviderIds.ToArray()) + ")"); + whereClauses.Add("(" + string.Join(" OR ", hasProviderIds) + ")"); } } @@ -4774,7 +4561,7 @@ namespace Emby.Server.Implementations.Data } else if (enableItemsByName && includedItemByNameTypes.Count > 1) { - var itemByNameTypeVal = string.Join(",", includedItemByNameTypes.Select(i => "'" + i + "'").ToArray()); + var itemByNameTypeVal = string.Join(",", includedItemByNameTypes.Select(i => "'" + i + "'")); whereClauses.Add("(TopParentId=@TopParentId or Type in (" + itemByNameTypeVal + "))"); } else @@ -4788,7 +4575,7 @@ namespace Emby.Server.Implementations.Data } else if (queryTopParentIds.Length > 1) { - var val = string.Join(",", queryTopParentIds.Select(i => "'" + i.ToString("N") + "'").ToArray()); + var val = string.Join(",", queryTopParentIds.Select(i => "'" + i.ToString("N") + "'")); if (enableItemsByName && includedItemByNameTypes.Count == 1) { @@ -4800,12 +4587,12 @@ namespace Emby.Server.Implementations.Data } else if (enableItemsByName && includedItemByNameTypes.Count > 1) { - var itemByNameTypeVal = string.Join(",", includedItemByNameTypes.Select(i => "'" + i + "'").ToArray()); + var itemByNameTypeVal = string.Join(",", includedItemByNameTypes.Select(i => "'" + i + "'")); whereClauses.Add("(Type in (" + itemByNameTypeVal + ") or TopParentId in (" + val + "))"); } else { - whereClauses.Add("(TopParentId in (" + val + "))"); + whereClauses.Add("TopParentId in (" + val + ")"); } } @@ -4820,7 +4607,7 @@ namespace Emby.Server.Implementations.Data } if (query.AncestorIds.Length > 1) { - var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + i.ToString("N") + "'").ToArray()); + var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + i.ToString("N") + "'")); whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorIdText in ({0}))", inClause)); } if (!string.IsNullOrWhiteSpace(query.AncestorWithPresentationUniqueKey)) @@ -4853,13 +4640,13 @@ namespace Emby.Server.Implementations.Data } if (query.BlockUnratedItems.Length > 1) { - var inClause = string.Join(",", query.BlockUnratedItems.Select(i => "'" + i.ToString() + "'").ToArray()); + var inClause = string.Join(",", query.BlockUnratedItems.Select(i => "'" + i.ToString() + "'")); whereClauses.Add(string.Format("(InheritedParentalRatingValue > 0 or UnratedType not in ({0}))", inClause)); } if (query.ExcludeInheritedTags.Length > 0) { - var tagValues = query.ExcludeInheritedTags.Select(i => "'" + GetCleanValue(i) + "'").ToArray(); + var tagValues = query.ExcludeInheritedTags.Select(i => "'" + GetCleanValue(i) + "'"); var tagValuesList = string.Join(",", tagValues); whereClauses.Add("((select CleanValue from itemvalues where ItemId=Guid and Type=6 and cleanvalue in (" + tagValuesList + ")) is null)"); @@ -4874,7 +4661,7 @@ namespace Emby.Server.Implementations.Data statuses.Add("data like '%" + seriesStatus + "%'"); } - whereClauses.Add("(" + string.Join(" OR ", statuses.ToArray()) + ")"); + whereClauses.Add("(" + string.Join(" OR ", statuses) + ")"); } if (query.BoxSetLibraryFolders.Length > 0) @@ -4886,7 +4673,7 @@ namespace Emby.Server.Implementations.Data folderIdQueries.Add("data like '%" + folderId.ToString("N") + "%'"); } - whereClauses.Add("(" + string.Join(" OR ", folderIdQueries.ToArray()) + ")"); + whereClauses.Add("(" + string.Join(" OR ", folderIdQueries) + ")"); } if (query.VideoTypes.Length > 0) @@ -4898,7 +4685,7 @@ namespace Emby.Server.Implementations.Data videoTypes.Add("data like '%\"VideoType\":\"" + videoType.ToString() + "\"%'"); } - whereClauses.Add("(" + string.Join(" OR ", videoTypes.ToArray()) + ")"); + whereClauses.Add("(" + string.Join(" OR ", videoTypes) + ")"); } if (query.Is3D.HasValue) @@ -5055,13 +4842,15 @@ namespace Emby.Server.Implementations.Data return true; } - var types = new[] { + var types = new[] + { typeof(Episode).Name, - typeof(Video).Name , - typeof(Movie).Name , - typeof(MusicVideo).Name , - typeof(Series).Name , - typeof(Season).Name }; + typeof(Video).Name, + typeof(Movie).Name, + typeof(MusicVideo).Name, + typeof(Series).Name, + typeof(Season).Name + }; if (types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase))) { @@ -5169,7 +4958,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type public void DeleteItem(Guid id, CancellationToken cancellationToken) { - if (id.Equals(Guid.Empty)) + if (id == Guid.Empty) { throw new ArgumentNullException(nameof(id)); } @@ -5229,9 +5018,9 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var whereClauses = GetPeopleWhereClauses(query, null); - if (whereClauses.Count > 0) + if (whereClauses.Count != 0) { - commandText += " where " + string.Join(" AND ", whereClauses.ToArray()); + commandText += " where " + string.Join(" AND ", whereClauses); } commandText += " order by ListOrder"; @@ -5269,9 +5058,9 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var whereClauses = GetPeopleWhereClauses(query, null); - if (whereClauses.Count > 0) + if (whereClauses.Count != 0) { - commandText += " where " + string.Join(" AND ", whereClauses.ToArray()); + commandText += " where " + string.Join(" AND ", whereClauses); } commandText += " order by ListOrder"; @@ -5330,7 +5119,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } else if (queryPersonTypes.Count > 1) { - var val = string.Join(",", queryPersonTypes.Select(i => "'" + i + "'").ToArray()); + var val = string.Join(",", queryPersonTypes.Select(i => "'" + i + "'")); whereClauses.Add("PersonType in (" + val + ")"); } @@ -5346,7 +5135,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } else if (queryExcludePersonTypes.Count > 1) { - var val = string.Join(",", queryExcludePersonTypes.Select(i => "'" + i + "'").ToArray()); + var val = string.Join(",", queryExcludePersonTypes.Select(i => "'" + i + "'")); whereClauses.Add("PersonType not in (" + val + ")"); } @@ -5498,18 +5287,18 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var typeClause = itemValueTypes.Length == 1 ? ("Type=" + itemValueTypes[0].ToString(CultureInfo.InvariantCulture)) : - ("Type in (" + string.Join(",", itemValueTypes.Select(i => i.ToString(CultureInfo.InvariantCulture)).ToArray()) + ")"); + ("Type in (" + string.Join(",", itemValueTypes.Select(i => i.ToString(CultureInfo.InvariantCulture))) + ")"); var commandText = "Select Value From ItemValues where " + typeClause; if (withItemTypes.Count > 0) { - var typeString = string.Join(",", withItemTypes.Select(i => "'" + i + "'").ToArray()); + var typeString = string.Join(",", withItemTypes.Select(i => "'" + i + "'")); commandText += " AND ItemId In (select guid from typedbaseitems where type in (" + typeString + "))"; } if (excludeItemTypes.Count > 0) { - var typeString = string.Join(",", excludeItemTypes.Select(i => "'" + i + "'").ToArray()); + var typeString = string.Join(",", excludeItemTypes.Select(i => "'" + i + "'")); commandText += " AND ItemId not In (select guid from typedbaseitems where type in (" + typeString + "))"; } @@ -5552,7 +5341,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } CheckDisposed(); - //logger.LogInformation("GetItemValues: " + _environmentInfo.StackTrace); var now = DateTime.UtcNow; @@ -5562,7 +5350,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type InternalItemsQuery typeSubQuery = null; - var itemCountColumns = new List<Tuple<string, string>>(); + Dictionary<string, string> itemCountColumns = null; var typesToCount = query.IncludeItemTypes; @@ -5588,17 +5376,21 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var typeWhereText = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + " where " + string.Join(" AND ", whereClauses); itemCountColumnQuery += typeWhereText; - //itemCountColumnQuery += ")"; - - itemCountColumns.Add(new Tuple<string, string>("itemTypes", "(" + itemCountColumnQuery + ") as itemTypes")); + itemCountColumns = new Dictionary<string, string>() + { + { "itemTypes", "(" + itemCountColumnQuery + ") as itemTypes"} + }; } - var columns = _retriveItemColumns.ToList(); - columns.AddRange(itemCountColumns.Select(i => i.Item2).ToArray()); + List<string> columns = _retriveItemColumns.ToList(); + if (itemCountColumns != null) + { + columns.AddRange(itemCountColumns.Values); + } // do this first before calling GetFinalColumnsToSelect, otherwise ExcludeItemIds will be set by SimilarTo var innerQuery = new InternalItemsQuery(query.User) @@ -5621,26 +5413,18 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type columns = GetFinalColumnsToSelect(query, columns.ToArray()).ToList(); - var commandText = "select " + string.Join(",", columns.ToArray()) + GetFromText(); - commandText += GetJoinUserDataText(query); + var commandText = "select " + + string.Join(",", columns) + + GetFromText() + + GetJoinUserDataText(query); var innerWhereClauses = GetWhereClauses(innerQuery, null); var innerWhereText = innerWhereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", innerWhereClauses.ToArray()); + " where " + string.Join(" AND ", innerWhereClauses); - var whereText = " where Type=@SelectType"; - - if (typesToCount.Length == 0) - { - whereText += " And CleanName In (Select CleanValue from ItemValues where " + typeClause + " AND ItemId in (select guid from TypedBaseItems" + innerWhereText + "))"; - } - else - { - //whereText += " And itemTypes not null"; - whereText += " And CleanName In (Select CleanValue from ItemValues where " + typeClause + " AND ItemId in (select guid from TypedBaseItems" + innerWhereText + "))"; - } + var whereText = " where Type=@SelectType And CleanName In (Select CleanValue from ItemValues where " + typeClause + " AND ItemId in (select guid from TypedBaseItems" + innerWhereText + "))"; var outerQuery = new InternalItemsQuery(query.User) { @@ -5664,13 +5448,12 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var outerWhereClauses = GetWhereClauses(outerQuery, null); - whereText += outerWhereClauses.Count == 0 ? - string.Empty : - " AND " + string.Join(" AND ", outerWhereClauses.ToArray()); - //cmd.CommandText += GetGroupBy(query); + if (outerWhereClauses.Count != 0) + { + whereText += " AND " + string.Join(" AND ", outerWhereClauses); + } - commandText += whereText; - commandText += " group by PresentationUniqueKey"; + commandText += whereText + " group by PresentationUniqueKey"; if (query.SimilarTo != null || !string.IsNullOrEmpty(query.SearchTerm)) { @@ -5705,10 +5488,12 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } if (query.EnableTotalRecordCount) { - var countText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + GetFromText(); + var countText = "select " + + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + + GetFromText() + + GetJoinUserDataText(query) + + whereText; - countText += GetJoinUserDataText(query); - countText += whereText; statementTexts.Add(countText); } @@ -5721,7 +5506,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var list = new List<Tuple<BaseItem, ItemCounts>>(); var result = new QueryResult<Tuple<BaseItem, ItemCounts>>(); - //logger.LogInformation("GetItemValues {0}", string.Join(";", statementTexts.ToArray())); var statements = PrepareAllSafe(db, statementTexts); if (!isReturningZeroItems) @@ -5768,10 +5552,11 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type if (query.EnableTotalRecordCount) { - commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + GetFromText(); - - commandText += GetJoinUserDataText(query); - commandText += whereText; + commandText = "select " + + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + + GetFromText() + + GetJoinUserDataText(query) + + whereText; using (var statement = statements[statements.Count - 1]) { @@ -5826,11 +5611,11 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } var allTypes = typeString.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries) - .ToLookup(i => i).ToList(); + .ToLookup(i => i); foreach (var type in allTypes) { - var value = type.ToList().Count; + var value = type.Count(); var typeName = type.Key; if (string.Equals(typeName, typeof(Series).FullName, StringComparison.OrdinalIgnoreCase)) @@ -5875,14 +5660,12 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type { var list = new List<Tuple<int, string>>(); - var hasArtist = item as IHasArtist; - if (hasArtist != null) + if (item is IHasArtist hasArtist) { list.AddRange(hasArtist.Artists.Select(i => new Tuple<int, string>(0, i))); } - var hasAlbumArtist = item as IHasAlbumArtist; - if (hasAlbumArtist != null) + if (item is IHasAlbumArtist hasAlbumArtist) { list.AddRange(hasAlbumArtist.AlbumArtists.Select(i => new Tuple<int, string>(1, i))); } @@ -6092,9 +5875,10 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type throw new ArgumentNullException(nameof(query)); } - var cmdText = "select " + string.Join(",", _mediaStreamSaveColumns) + " from mediastreams where"; - - cmdText += " ItemId=@ItemId"; + var cmdText = "select " + + string.Join(",", _mediaStreamSaveColumns) + + " from mediastreams where" + + " ItemId=@ItemId"; if (query.Type.HasValue) { @@ -6143,7 +5927,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type { CheckDisposed(); - if (id.Equals(Guid.Empty)) + if (id == Guid.Empty) { throw new ArgumentNullException(nameof(id)); } @@ -6183,21 +5967,24 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var insertText = new StringBuilder(string.Format("insert into mediastreams ({0}) values ", string.Join(",", _mediaStreamSaveColumns))); var endIndex = Math.Min(streams.Count, startIndex + limit); - var isSubsequentRow = false; for (var i = startIndex; i < endIndex; i++) { - if (isSubsequentRow) + if (i != startIndex) { insertText.Append(","); } var index = i.ToString(CultureInfo.InvariantCulture); + insertText.Append("(@ItemId, "); - var mediaStreamSaveColumns = string.Join(",", _mediaStreamSaveColumns.Skip(1).Select(m => "@" + m + index).ToArray()); + foreach (var column in _mediaStreamSaveColumns.Skip(1)) + { + insertText.Append("@" + column + index + ","); + } + insertText.Length -= 1; // Remove the last comma - insertText.AppendFormat("(@ItemId, {0})", mediaStreamSaveColumns); - isSubsequentRow = true; + insertText.Append(")"); } using (var statement = PrepareStatementSafe(db, insertText.ToString())) diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 13febc214..d0a7de11d 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -1428,7 +1428,7 @@ namespace Emby.Server.Implementations.Dto var supportedEnhancers = _imageProcessor.GetSupportedEnhancers(item, ImageType.Primary); - ImageSize size; + ImageDimensions size; var defaultAspectRatio = item.GetDefaultPrimaryImageAspectRatio(); @@ -1439,9 +1439,9 @@ namespace Emby.Server.Implementations.Dto return defaultAspectRatio; } - double dummyWidth = 200; - double dummyHeight = dummyWidth / defaultAspectRatio; - size = new ImageSize(dummyWidth, dummyHeight); + int dummyWidth = 200; + int dummyHeight = Convert.ToInt32(dummyWidth / defaultAspectRatio); + size = new ImageDimensions(dummyWidth, dummyHeight); } else { @@ -1481,7 +1481,7 @@ namespace Emby.Server.Implementations.Dto var width = size.Width; var height = size.Height; - if (width.Equals(0) || height.Equals(0)) + if (width <= 0 || height <= 0) { return null; } diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index f2a5b2e38..3aa617b02 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -22,7 +22,6 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.0" /> <PackageReference Include="ServiceStack.Text.Core" Version="5.4.0" /> <PackageReference Include="sharpcompress" Version="0.22.0" /> <PackageReference Include="SimpleInjector" Version="4.4.2" /> diff --git a/Emby.Server.Implementations/EntryPoints/SystemEvents.cs b/Emby.Server.Implementations/EntryPoints/SystemEvents.cs deleted file mode 100644 index 72c8acd9f..000000000 --- a/Emby.Server.Implementations/EntryPoints/SystemEvents.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.System; - -namespace Emby.Server.Implementations.EntryPoints -{ - public class SystemEvents : IServerEntryPoint - { - private readonly ISystemEvents _systemEvents; - private readonly IServerApplicationHost _appHost; - - public SystemEvents(ISystemEvents systemEvents, IServerApplicationHost appHost) - { - _systemEvents = systemEvents; - _appHost = appHost; - } - - public void Run() - { - _systemEvents.SystemShutdown += _systemEvents_SystemShutdown; - } - - private void _systemEvents_SystemShutdown(object sender, EventArgs e) - { - _appHost.Shutdown(); - } - - public void Dispose() - { - _systemEvents.SystemShutdown -= _systemEvents_SystemShutdown; - } - } -} diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index 6a3204011..204f9d949 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -140,7 +140,14 @@ namespace Emby.Server.Implementations.IO /// <summary> /// Initializes a new instance of the <see cref="LibraryMonitor" /> class. /// </summary> - public LibraryMonitor(ILoggerFactory loggerFactory, ITaskManager taskManager, ILibraryManager libraryManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ITimerFactory timerFactory, ISystemEvents systemEvents, IEnvironmentInfo environmentInfo) + public LibraryMonitor( + ILoggerFactory loggerFactory, + ITaskManager taskManager, + ILibraryManager libraryManager, + IServerConfigurationManager configurationManager, + IFileSystem fileSystem, + ITimerFactory timerFactory, + IEnvironmentInfo environmentInfo) { if (taskManager == null) { @@ -154,26 +161,9 @@ namespace Emby.Server.Implementations.IO _fileSystem = fileSystem; _timerFactory = timerFactory; _environmentInfo = environmentInfo; - - systemEvents.Resume += _systemEvents_Resume; - } - - private void _systemEvents_Resume(object sender, EventArgs e) - { - Restart(); - } - - private void Restart() - { - Stop(); - - if (!_disposed) - { - Start(); - } } - private bool IsLibraryMonitorEnabaled(BaseItem item) + private bool IsLibraryMonitorEnabled(BaseItem item) { if (item is BasePluginFolder) { @@ -200,7 +190,7 @@ namespace Emby.Server.Implementations.IO var paths = LibraryManager .RootFolder .Children - .Where(IsLibraryMonitorEnabaled) + .Where(IsLibraryMonitorEnabled) .OfType<Folder>() .SelectMany(f => f.PhysicalLocations) .Distinct(StringComparer.OrdinalIgnoreCase) @@ -223,7 +213,7 @@ namespace Emby.Server.Implementations.IO private void StartWatching(BaseItem item) { - if (IsLibraryMonitorEnabaled(item)) + if (IsLibraryMonitorEnabled(item)) { StartWatchingPath(item.Path); } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 9e11494c9..4805e54dd 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -60,7 +60,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private readonly IProviderManager _providerManager; private readonly IMediaEncoder _mediaEncoder; private readonly IProcessFactory _processFactory; - private readonly ISystemEvents _systemEvents; private readonly IAssemblyInfo _assemblyInfo; private IMediaSourceManager _mediaSourceManager; @@ -90,8 +89,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV IProviderManager providerManager, IMediaEncoder mediaEncoder, ITimerFactory timerFactory, - IProcessFactory processFactory, - ISystemEvents systemEvents) + IProcessFactory processFactory) { Current = this; @@ -105,7 +103,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _providerManager = providerManager; _mediaEncoder = mediaEncoder; _processFactory = processFactory; - _systemEvents = systemEvents; _liveTvManager = (LiveTvManager)liveTvManager; _jsonSerializer = jsonSerializer; _assemblyInfo = assemblyInfo; @@ -131,15 +128,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { _timerProvider.RestartTimers(); - _systemEvents.Resume += _systemEvents_Resume; await CreateRecordingFolders().ConfigureAwait(false); } - private void _systemEvents_Resume(object sender, EventArgs e) - { - _timerProvider.RestartTimers(); - } - private async void OnRecordingFoldersChanged() { await CreateRecordingFolders().ConfigureAwait(false); diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index af05cd7d7..c408a47f6 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -502,58 +502,55 @@ namespace Emby.Server.Implementations.Localization return culture + ".json"; } - public LocalizatonOption[] GetLocalizationOptions() - { - return new LocalizatonOption[] + public LocalizationOption[] GetLocalizationOptions() + => new LocalizationOption[] { - new LocalizatonOption{ Name="Arabic", Value="ar"}, - new LocalizatonOption{ Name="Belarusian (Belarus)", Value="be-BY"}, - new LocalizatonOption{ Name="Bulgarian (Bulgaria)", Value="bg-BG"}, - new LocalizatonOption{ Name="Catalan", Value="ca"}, - new LocalizatonOption{ Name="Chinese Simplified", Value="zh-CN"}, - new LocalizatonOption{ Name="Chinese Traditional", Value="zh-TW"}, - new LocalizatonOption{ Name="Chinese Traditional (Hong Kong)", Value="zh-HK"}, - new LocalizatonOption{ Name="Croatian", Value="hr"}, - new LocalizatonOption{ Name="Czech", Value="cs"}, - new LocalizatonOption{ Name="Danish", Value="da"}, - new LocalizatonOption{ Name="Dutch", Value="nl"}, - new LocalizatonOption{ Name="English (United Kingdom)", Value="en-GB"}, - new LocalizatonOption{ Name="English (United States)", Value="en-US"}, - new LocalizatonOption{ Name="Finnish", Value="fi"}, - new LocalizatonOption{ Name="French", Value="fr"}, - new LocalizatonOption{ Name="French (Canada)", Value="fr-CA"}, - new LocalizatonOption{ Name="German", Value="de"}, - new LocalizatonOption{ Name="Greek", Value="el"}, - new LocalizatonOption{ Name="Hebrew", Value="he"}, - new LocalizatonOption{ Name="Hindi (India)", Value="hi-IN"}, - new LocalizatonOption{ Name="Hungarian", Value="hu"}, - new LocalizatonOption{ Name="Indonesian", Value="id"}, - new LocalizatonOption{ Name="Italian", Value="it"}, - new LocalizatonOption{ Name="Japanese", Value="ja"}, - new LocalizatonOption{ Name="Kazakh", Value="kk"}, - new LocalizatonOption{ Name="Korean", Value="ko"}, - new LocalizatonOption{ Name="Lithuanian", Value="lt-LT"}, - new LocalizatonOption{ Name="Malay", Value="ms"}, - new LocalizatonOption{ Name="Norwegian Bokmål", Value="nb"}, - new LocalizatonOption{ Name="Persian", Value="fa"}, - new LocalizatonOption{ Name="Polish", Value="pl"}, - new LocalizatonOption{ Name="Portuguese (Brazil)", Value="pt-BR"}, - new LocalizatonOption{ Name="Portuguese (Portugal)", Value="pt-PT"}, - new LocalizatonOption{ Name="Romanian", Value="ro"}, - new LocalizatonOption{ Name="Russian", Value="ru"}, - new LocalizatonOption{ Name="Slovak", Value="sk"}, - new LocalizatonOption{ Name="Slovenian (Slovenia)", Value="sl-SI"}, - new LocalizatonOption{ Name="Spanish", Value="es"}, - new LocalizatonOption{ Name="Spanish (Latin America)", Value="es-419"}, - new LocalizatonOption{ Name="Spanish (Mexico)", Value="es-MX"}, - new LocalizatonOption{ Name="Swedish", Value="sv"}, - new LocalizatonOption{ Name="Swiss German", Value="gsw"}, - new LocalizatonOption{ Name="Turkish", Value="tr"}, - new LocalizatonOption{ Name="Ukrainian", Value="uk"}, - new LocalizatonOption{ Name="Vietnamese", Value="vi"} - + new LocalizationOption("Arabic", "ar"), + new LocalizationOption("Belarusian (Belarus)", "be-BY"), + new LocalizationOption("Bulgarian (Bulgaria)", "bg-BG"), + new LocalizationOption("Catalan", "ca"), + new LocalizationOption("Chinese Simplified", "zh-CN"), + new LocalizationOption("Chinese Traditional", "zh-TW"), + new LocalizationOption("Chinese Traditional (Hong Kong)", "zh-HK"), + new LocalizationOption("Croatian", "hr"), + new LocalizationOption("Czech", "cs"), + new LocalizationOption("Danish", "da"), + new LocalizationOption("Dutch", "nl"), + new LocalizationOption("English (United Kingdom)", "en-GB"), + new LocalizationOption("English (United States)", "en-US"), + new LocalizationOption("Finnish", "fi"), + new LocalizationOption("French", "fr"), + new LocalizationOption("French (Canada)", "fr-CA"), + new LocalizationOption("German", "de"), + new LocalizationOption("Greek", "el"), + new LocalizationOption("Hebrew", "he"), + new LocalizationOption("Hindi (India)", "hi-IN"), + new LocalizationOption("Hungarian", "hu"), + new LocalizationOption("Indonesian", "id"), + new LocalizationOption("Italian", "it"), + new LocalizationOption("Japanese", "ja"), + new LocalizationOption("Kazakh", "kk"), + new LocalizationOption("Korean", "ko"), + new LocalizationOption("Lithuanian", "lt-LT"), + new LocalizationOption("Malay", "ms"), + new LocalizationOption("Norwegian Bokmål", "nb"), + new LocalizationOption("Persian", "fa"), + new LocalizationOption("Polish", "pl"), + new LocalizationOption("Portuguese (Brazil)", "pt-BR"), + new LocalizationOption("Portuguese (Portugal)", "pt-PT"), + new LocalizationOption("Romanian", "ro"), + new LocalizationOption("Russian", "ru"), + new LocalizationOption("Slovak", "sk"), + new LocalizationOption("Slovenian (Slovenia)", "sl-SI"), + new LocalizationOption("Spanish", "es"), + new LocalizationOption("Spanish (Latin America)", "es-419"), + new LocalizationOption("Spanish (Mexico)", "es-MX"), + new LocalizationOption("Swedish", "sv"), + new LocalizationOption("Swiss German", "gsw"), + new LocalizationOption("Turkish", "tr"), + new LocalizationOption("Ukrainian", "uk"), + new LocalizationOption("Vietnamese", "vi") }; - } } public interface ITextLocalizer diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 44f6e2d7b..93a9a0d81 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -53,7 +53,6 @@ namespace Emby.Server.Implementations.ScheduledTasks /// <value>The task manager.</value> private ITaskManager TaskManager { get; set; } private readonly IFileSystem _fileSystem; - private readonly ISystemEvents _systemEvents; /// <summary> /// Initializes a new instance of the <see cref="ScheduledTaskWorker" /> class. @@ -74,7 +73,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// or /// logger /// </exception> - public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger, IFileSystem fileSystem, ISystemEvents systemEvents) + public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger, IFileSystem fileSystem) { if (scheduledTask == null) { @@ -103,7 +102,6 @@ namespace Emby.Server.Implementations.ScheduledTasks JsonSerializer = jsonSerializer; Logger = logger; _fileSystem = fileSystem; - _systemEvents = systemEvents; InitTriggerEvents(); } @@ -762,20 +760,6 @@ namespace Emby.Server.Implementations.ScheduledTasks }; } - if (info.Type.Equals(typeof(SystemEventTrigger).Name, StringComparison.OrdinalIgnoreCase)) - { - if (!info.SystemEvent.HasValue) - { - throw new ArgumentException("Info did not contain a SystemEvent.", nameof(info)); - } - - return new SystemEventTrigger(_systemEvents) - { - SystemEvent = info.SystemEvent.Value, - TaskOptions = options - }; - } - if (info.Type.Equals(typeof(StartupTrigger).Name, StringComparison.OrdinalIgnoreCase)) { return new StartupTrigger(); diff --git a/Emby.Server.Implementations/ScheduledTasks/SystemEventTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/SystemEventTrigger.cs deleted file mode 100644 index 7a88fc2b0..000000000 --- a/Emby.Server.Implementations/ScheduledTasks/SystemEventTrigger.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Threading.Tasks; -using MediaBrowser.Model.System; -using MediaBrowser.Model.Tasks; -using Microsoft.Extensions.Logging; - -namespace Emby.Server.Implementations.ScheduledTasks -{ - /// <summary> - /// Class SystemEventTrigger - /// </summary> - public class SystemEventTrigger : ITaskTrigger - { - /// <summary> - /// Gets or sets the system event. - /// </summary> - /// <value>The system event.</value> - public SystemEvent SystemEvent { get; set; } - - /// <summary> - /// Gets or sets the options of this task. - /// </summary> - public TaskOptions TaskOptions { get; set; } - - private readonly ISystemEvents _systemEvents; - - public SystemEventTrigger(ISystemEvents systemEvents) - { - _systemEvents = systemEvents; - } - - /// <summary> - /// Stars waiting for the trigger action - /// </summary> - /// <param name="lastResult">The last result.</param> - /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param> - public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup) - { - switch (SystemEvent) - { - case SystemEvent.WakeFromSleep: - _systemEvents.Resume += _systemEvents_Resume; - break; - } - } - - private async void _systemEvents_Resume(object sender, EventArgs e) - { - if (SystemEvent == SystemEvent.WakeFromSleep) - { - // This value is a bit arbitrary, but add a delay to help ensure network connections have been restored before running the task - await Task.Delay(10000).ConfigureAwait(false); - - OnTriggered(); - } - } - - /// <summary> - /// Stops waiting for the trigger action - /// </summary> - public void Stop() - { - _systemEvents.Resume -= _systemEvents_Resume; - } - - /// <summary> - /// Occurs when [triggered]. - /// </summary> - public event EventHandler<EventArgs> Triggered; - - /// <summary> - /// Called when [triggered]. - /// </summary> - private void OnTriggered() - { - if (Triggered != null) - { - Triggered(this, EventArgs.Empty); - } - } - } -} diff --git a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs index 02a082d3f..d74c8fe8c 100644 --- a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs +++ b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs @@ -46,8 +46,6 @@ namespace Emby.Server.Implementations.ScheduledTasks /// <value>The application paths.</value> private IApplicationPaths ApplicationPaths { get; set; } - private readonly ISystemEvents _systemEvents; - /// <summary> /// Gets the logger. /// </summary> @@ -66,54 +64,16 @@ namespace Emby.Server.Implementations.ScheduledTasks IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, ILoggerFactory loggerFactory, - IFileSystem fileSystem, - ISystemEvents systemEvents) + IFileSystem fileSystem) { ApplicationPaths = applicationPaths; JsonSerializer = jsonSerializer; Logger = loggerFactory.CreateLogger(nameof(TaskManager)); _fileSystem = fileSystem; - _systemEvents = systemEvents; ScheduledTasks = new IScheduledTaskWorker[] { }; } - private void BindToSystemEvent() - { - _systemEvents.Resume += _systemEvents_Resume; - } - - private void _systemEvents_Resume(object sender, EventArgs e) - { - foreach (var task in ScheduledTasks) - { - task.ReloadTriggerEvents(); - } - } - - public void RunTaskOnNextStartup(string key) - { - var path = Path.Combine(ApplicationPaths.CachePath, "startuptasks.txt"); - - List<string> lines; - - try - { - lines = _fileSystem.ReadAllLines(path).ToList(); - } - catch - { - lines = new List<string>(); - } - - if (!lines.Contains(key, StringComparer.OrdinalIgnoreCase)) - { - lines.Add(key); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path)); - _fileSystem.WriteAllLines(path, lines); - } - } - private void RunStartupTasks() { var path = Path.Combine(ApplicationPaths.CachePath, "startuptasks.txt"); @@ -290,12 +250,10 @@ namespace Emby.Server.Implementations.ScheduledTasks var myTasks = ScheduledTasks.ToList(); var list = tasks.ToList(); - myTasks.AddRange(list.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger, _fileSystem, _systemEvents))); + myTasks.AddRange(list.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger, _fileSystem))); ScheduledTasks = myTasks.ToArray(); - BindToSystemEvent(); - RunStartupTasks(); } diff --git a/Emby.Server.Implementations/SystemEvents.cs b/Emby.Server.Implementations/SystemEvents.cs deleted file mode 100644 index e4c54c3c5..000000000 --- a/Emby.Server.Implementations/SystemEvents.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using MediaBrowser.Model.System; - -namespace Emby.Server.Implementations -{ - public class SystemEvents : ISystemEvents - { - public event EventHandler Resume; - public event EventHandler Suspend; - public event EventHandler SessionLogoff; - public event EventHandler SystemShutdown; - } -} diff --git a/Emby.XmlTv/Emby.XmlTv/Classes/XmlTvReader.cs b/Emby.XmlTv/Emby.XmlTv/Classes/XmlTvReader.cs index 52e58ed8d..52ec7a135 100644 --- a/Emby.XmlTv/Emby.XmlTv/Classes/XmlTvReader.cs +++ b/Emby.XmlTv/Emby.XmlTv/Classes/XmlTvReader.cs @@ -1005,7 +1005,7 @@ namespace Emby.XmlTv.Classes } } - public static Regex _regDateWithOffset = new Regex(@"^(?<dateDigits>[0-9]{4,14})(\s(?<dateOffset>[+-]*[0-9]{1,4}))?$"); + public const string _regDateWithOffset = @"^(?<dateDigits>[0-9]{4,14})(\s(?<dateOffset>[+-]*[0-9]{1,4}))?$"; public DateTimeOffset? ParseDate(string dateValue) { @@ -1018,50 +1018,47 @@ namespace Emby.XmlTv.Classes '200007281733 BST', '200209', '19880523083000 +0300'. (BST == +0100.) */ - DateTimeOffset? result = null; - - if (!string.IsNullOrEmpty(dateValue)) + if (string.IsNullOrEmpty(dateValue)) { - var completeDate = "20000101000000"; - var dateComponent = string.Empty; - var dateOffset = "+00:00"; + return null; + } - var match = _regDateWithOffset.Match(dateValue); - if (match.Success) + var completeDate = "20000101000000"; + var dateComponent = string.Empty; + var dateOffset = "+00:00"; + var match = Regex.Match(dateValue, _regDateWithOffset); + if (match.Success) + { + dateComponent = match.Groups["dateDigits"].Value; + if (!string.IsNullOrEmpty(match.Groups["dateOffset"].Value)) { - dateComponent = match.Groups["dateDigits"].Value; - if (!string.IsNullOrEmpty(match.Groups["dateOffset"].Value)) + dateOffset = match.Groups["dateOffset"].Value; // Add in the colon to ease parsing later + if (dateOffset.Length == 5) { - dateOffset = match.Groups["dateOffset"].Value; // Add in the colon to ease parsing later - if (dateOffset.Length == 5) - { - dateOffset = dateOffset.Insert(3, ":"); // Add in the colon to ease parsing later - } - else - { - dateOffset = "+00:00"; - } + dateOffset = dateOffset.Insert(3, ":"); // Add in the colon to ease parsing later + } + else + { + dateOffset = "+00:00"; } } + } - // Pad out the date component part to 14 characaters so 2016061509 becomes 20160615090000 - if (dateComponent.Length < 14) - { - dateComponent = dateComponent + completeDate.Substring(dateComponent.Length, completeDate.Length - dateComponent.Length); - } + // Pad out the date component part to 14 characaters so 2016061509 becomes 20160615090000 + if (dateComponent.Length < 14) + { + dateComponent = dateComponent + completeDate.Substring(dateComponent.Length, completeDate.Length - dateComponent.Length); + } - var standardDate = string.Format("{0} {1}", dateComponent, dateOffset); - if (DateTimeOffset.TryParseExact(standardDate, "yyyyMMddHHmmss zzz", CultureInfo.CurrentCulture, DateTimeStyles.None, out var parsedDateTime)) - { - return parsedDateTime.ToUniversalTime(); - } - else - { - //Logger.LogWarning("Unable to parse the date {0} from standardised form {1}", dateValue, standardDate); - } + var standardDate = string.Format("{0} {1}", dateComponent, dateOffset); + if (DateTimeOffset.TryParseExact(standardDate, "yyyyMMddHHmmss zzz", CultureInfo.CurrentCulture, DateTimeStyles.None, out DateTimeOffset parsedDateTime)) + { + return parsedDateTime.ToUniversalTime(); } - return result; + // Logger.LogWarning("Unable to parse the date {0} from standardised form {1}", dateValue, standardDate); + + return null; } public string StandardiseDate(string value) @@ -1070,7 +1067,7 @@ namespace Emby.XmlTv.Classes var dateComponent = string.Empty; var dateOffset = "+0000"; - var match = _regDateWithOffset.Match(value); + var match = Regex.Match(value, _regDateWithOffset); if (match.Success) { dateComponent = match.Groups["dateDigits"].Value; diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 6832fe743..b580f45ca 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -11,8 +11,8 @@ namespace Jellyfin.Server { public class CoreAppHost : ApplicationHost { - public CoreAppHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager) - : base(applicationPaths, loggerFactory, options, fileSystem, environmentInfo, imageEncoder, systemEvents, networkManager) + public CoreAppHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, MediaBrowser.Common.Net.INetworkManager networkManager) + : base(applicationPaths, loggerFactory, options, fileSystem, environmentInfo, imageEncoder, networkManager) { } diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index fef7de512..f64f50cd7 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -96,10 +96,9 @@ namespace Jellyfin.Server fileSystem, environmentInfo, new NullImageEncoder(), - new SystemEvents(), new NetworkManager(_loggerFactory, environmentInfo))) { - await appHost.InitAsync(); + appHost.Init(); appHost.ImageProcessor.ImageEncoder = GetImageEncoder(fileSystem, appPaths, appHost.LocalizationManager); @@ -108,6 +107,7 @@ namespace Jellyfin.Server await appHost.RunStartupTasks(); // TODO: read input for a stop command + try { // Block main thread until shutdown @@ -166,6 +166,7 @@ namespace Jellyfin.Server { Directory.CreateDirectory(programDataPath); } + string configDir = Environment.GetEnvironmentVariable("JELLYFIN_CONFIG_DIR"); if (string.IsNullOrEmpty(configDir)) { diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 26ac8d40e..149e54f01 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -328,10 +328,9 @@ namespace MediaBrowser.Api.Images var fileInfo = _fileSystem.GetFileInfo(info.Path); length = fileInfo.Length; - var size = _imageProcessor.GetImageSize(item, info, true); - - width = Convert.ToInt32(size.Width); - height = Convert.ToInt32(size.Height); + ImageDimensions size = _imageProcessor.GetImageSize(item, info, true); + width = size.Width; + height = size.Height; if (width <= 0 || height <= 0) { diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index d3009295f..12d807a7e 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -839,7 +839,7 @@ namespace MediaBrowser.Api.Library { try { - _activityManager.CreateAsync(new ActivityLogEntry + _activityManager.Create(new ActivityLogEntry { Name = string.Format(_localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Name, item.Name), Type = "UserDownloadingContent", diff --git a/MediaBrowser.Api/LocalizationService.cs b/MediaBrowser.Api/LocalizationService.cs index 0694de782..3b2e18852 100644 --- a/MediaBrowser.Api/LocalizationService.cs +++ b/MediaBrowser.Api/LocalizationService.cs @@ -33,7 +33,7 @@ namespace MediaBrowser.Api /// Class ParentalRatings /// </summary> [Route("/Localization/Options", "GET", Summary = "Gets localization options")] - public class GetLocalizationOptions : IReturn<LocalizatonOption[]> + public class GetLocalizationOptions : IReturn<LocalizationOption[]> { } diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index 9dc625e35..385127c54 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -131,7 +131,7 @@ namespace MediaBrowser.Common /// <summary> /// Inits this instance. /// </summary> - Task InitAsync(); + void Init(); /// <summary> /// Creates the instance. diff --git a/MediaBrowser.Controller/Drawing/IImageEncoder.cs b/MediaBrowser.Controller/Drawing/IImageEncoder.cs index 6e2d5781a..5b8c9da6f 100644 --- a/MediaBrowser.Controller/Drawing/IImageEncoder.cs +++ b/MediaBrowser.Controller/Drawing/IImageEncoder.cs @@ -44,6 +44,6 @@ namespace MediaBrowser.Controller.Drawing /// <value><c>true</c> if [supports image encoding]; otherwise, <c>false</c>.</value> bool SupportsImageEncoding { get; } - ImageSize GetImageSize(string path); + ImageDimensions GetImageSize(string path); } } diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index 7e6e0127f..783182730 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -26,16 +26,16 @@ namespace MediaBrowser.Controller.Drawing /// <value>The image enhancers.</value> IImageEnhancer[] ImageEnhancers { get; } - ImageSize GetImageSize(string path); + ImageDimensions GetImageSize(string path); /// <summary> /// Gets the size of the image. /// </summary> /// <param name="info">The information.</param> /// <returns>ImageSize.</returns> - ImageSize GetImageSize(BaseItem item, ItemImageInfo info); + ImageDimensions GetImageSize(BaseItem item, ItemImageInfo info); - ImageSize GetImageSize(BaseItem item, ItemImageInfo info, bool updateItem); + ImageDimensions GetImageSize(BaseItem item, ItemImageInfo info, bool updateItem); /// <summary> /// Adds the parts. diff --git a/MediaBrowser.Controller/Drawing/ImageHelper.cs b/MediaBrowser.Controller/Drawing/ImageHelper.cs index 2680c60bd..f88a63223 100644 --- a/MediaBrowser.Controller/Drawing/ImageHelper.cs +++ b/MediaBrowser.Controller/Drawing/ImageHelper.cs @@ -1,3 +1,4 @@ +using System; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Entities; @@ -6,7 +7,7 @@ namespace MediaBrowser.Controller.Drawing { public static class ImageHelper { - public static ImageSize GetNewImageSize(ImageProcessingOptions options, ImageSize? originalImageSize) + public static ImageDimensions GetNewImageSize(ImageProcessingOptions options, ImageDimensions? originalImageSize) { if (originalImageSize.HasValue) { @@ -20,26 +21,26 @@ namespace MediaBrowser.Controller.Drawing public static IImageProcessor ImageProcessor { get; set; } - private static ImageSize GetSizeEstimate(ImageProcessingOptions options) + private static ImageDimensions GetSizeEstimate(ImageProcessingOptions options) { if (options.Width.HasValue && options.Height.HasValue) { - return new ImageSize(options.Width.Value, options.Height.Value); + return new ImageDimensions(options.Width.Value, options.Height.Value); } - var aspect = GetEstimatedAspectRatio(options.Image.Type, options.Item); + double aspect = GetEstimatedAspectRatio(options.Image.Type, options.Item); - var width = options.Width ?? options.MaxWidth; + int? width = options.Width ?? options.MaxWidth; if (width.HasValue) { - var heightValue = width.Value / aspect; - return new ImageSize(width.Value, heightValue); + int heightValue = Convert.ToInt32((double)width.Value / aspect); + return new ImageDimensions(width.Value, heightValue); } var height = options.Height ?? options.MaxHeight ?? 200; - var widthValue = aspect * height; - return new ImageSize(widthValue, height); + int widthValue = Convert.ToInt32(aspect * height); + return new ImageDimensions(widthValue, height); } private static double GetEstimatedAspectRatio(ImageType type, BaseItem item) diff --git a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs index 00d93930f..db432f500 100644 --- a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs +++ b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.Controller.Drawing !MaxHeight.HasValue; } - public bool HasDefaultOptions(string originalImagePath, ImageSize? size) + public bool HasDefaultOptions(string originalImagePath, ImageDimensions? size) { if (!size.HasValue) { diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 5534576f1..0d1a0ce86 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2235,11 +2235,7 @@ namespace MediaBrowser.Controller.Entities /// </exception> /// <exception cref="ArgumentNullException">item</exception> public string GetImagePath(ImageType imageType, int imageIndex) - { - var info = GetImageInfo(imageType, imageIndex); - - return info == null ? null : info.Path; - } + => GetImageInfo(imageType, imageIndex)?.Path; /// <summary> /// Gets the image information. diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 6f98fcd8d..0b0134669 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -508,7 +508,7 @@ namespace MediaBrowser.Controller.Entities if (query.IsLiked.HasValue) { - userData = userData ?? userDataManager.GetUserData(user, item); + userData = userDataManager.GetUserData(user, item); if (!userData.Likes.HasValue || userData.Likes != query.IsLiked.Value) { diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index e086f9d33..d8d0a1aa3 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -424,11 +424,9 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.VideoStream != null && state.VideoStream.Width.HasValue) { // This is hacky but not sure how to get the exact subtitle resolution - double height = state.VideoStream.Width.Value; - height /= 16; - height *= 9; + int height = Convert.ToInt32((double)state.VideoStream.Width.Value / 16.0 * 9.0); - arg += string.Format(" -canvas_size {0}:{1}", state.VideoStream.Width.Value.ToString(CultureInfo.InvariantCulture), Convert.ToInt32(height).ToString(CultureInfo.InvariantCulture)); + arg += string.Format(" -canvas_size {0}:{1}", state.VideoStream.Width.Value.ToString(CultureInfo.InvariantCulture), height.ToString(CultureInfo.InvariantCulture)); } var subtitlePath = state.SubtitleStream.Path; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index 6651a6d70..1fe8856cc 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -319,7 +319,7 @@ namespace MediaBrowser.Controller.MediaEncoding { if (VideoStream != null && VideoStream.Width.HasValue && VideoStream.Height.HasValue) { - var size = new ImageSize + var size = new ImageDimensions { Width = VideoStream.Width.Value, Height = VideoStream.Height.Value @@ -331,7 +331,7 @@ namespace MediaBrowser.Controller.MediaEncoding BaseRequest.MaxWidth ?? 0, BaseRequest.MaxHeight ?? 0); - return Convert.ToInt32(newSize.Width); + return newSize.Width; } if (!IsVideoRequest) @@ -349,7 +349,7 @@ namespace MediaBrowser.Controller.MediaEncoding { if (VideoStream != null && VideoStream.Width.HasValue && VideoStream.Height.HasValue) { - var size = new ImageSize + var size = new ImageDimensions { Width = VideoStream.Width.Value, Height = VideoStream.Height.Value @@ -361,7 +361,7 @@ namespace MediaBrowser.Controller.MediaEncoding BaseRequest.MaxWidth ?? 0, BaseRequest.MaxHeight ?? 0); - return Convert.ToInt32(newSize.Height); + return newSize.Height; } if (!IsVideoRequest) diff --git a/MediaBrowser.Controller/Providers/IImageEnhancer.cs b/MediaBrowser.Controller/Providers/IImageEnhancer.cs index 2de657854..c27c00ca2 100644 --- a/MediaBrowser.Controller/Providers/IImageEnhancer.cs +++ b/MediaBrowser.Controller/Providers/IImageEnhancer.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Controller.Providers /// <param name="imageIndex">Index of the image.</param> /// <param name="originalImageSize">Size of the original image.</param> /// <returns>ImageSize.</returns> - ImageSize GetEnhancedImageSize(BaseItem item, ImageType imageType, int imageIndex, ImageSize originalImageSize); + ImageDimensions GetEnhancedImageSize(BaseItem item, ImageType imageType, int imageIndex, ImageDimensions originalImageSize); EnhancedImageInfo GetEnhancedImageInfo(BaseItem item, string inputFile, ImageType imageType, int imageIndex); diff --git a/MediaBrowser.Model/Activity/IActivityManager.cs b/MediaBrowser.Model/Activity/IActivityManager.cs index bbd7b6f2d..897d93d79 100644 --- a/MediaBrowser.Model/Activity/IActivityManager.cs +++ b/MediaBrowser.Model/Activity/IActivityManager.cs @@ -1,7 +1,6 @@ using System; -using System.Collections.Generic; -using System.Threading.Tasks; using MediaBrowser.Model.Events; +using MediaBrowser.Model.Querying; namespace MediaBrowser.Model.Activity { @@ -9,8 +8,10 @@ namespace MediaBrowser.Model.Activity { event EventHandler<GenericEventArgs<ActivityLogEntry>> EntryCreated; - Task CreateAsync(ActivityLogEntry entry); + void Create(ActivityLogEntry entry); - IEnumerable<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, bool? hasUserId, int? x, int? y); + QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, int? startIndex, int? limit); + + QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, bool? hasUserId, int? x, int? y); } } diff --git a/MediaBrowser.Model/Activity/IActivityRepository.cs b/MediaBrowser.Model/Activity/IActivityRepository.cs index 3ed6175ce..f0e3b902c 100644 --- a/MediaBrowser.Model/Activity/IActivityRepository.cs +++ b/MediaBrowser.Model/Activity/IActivityRepository.cs @@ -1,12 +1,12 @@ -using System.Linq; -using System.Threading.Tasks; +using System; +using MediaBrowser.Model.Querying; namespace MediaBrowser.Model.Activity { public interface IActivityRepository { - Task CreateAsync(ActivityLogEntry entry); + void Create(ActivityLogEntry entry); - IQueryable<ActivityLogEntry> GetActivityLogEntries(); + QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, bool? z, int? startIndex, int? limit); } } diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 522c10980..6d03a03b0 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -953,22 +953,11 @@ namespace MediaBrowser.Model.Dlna if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue) { - var size = new ImageSize - { - Width = videoStream.Width.Value, - Height = videoStream.Height.Value - }; - - double? maxWidth = MaxWidth.HasValue ? (double)MaxWidth.Value : (double?)null; - double? maxHeight = MaxHeight.HasValue ? (double)MaxHeight.Value : (double?)null; + ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value); - var newSize = DrawingUtils.Resize(size, - 0, - 0, - maxWidth ?? 0, - maxHeight ?? 0); + size = DrawingUtils.Resize(size, 0, 0, MaxWidth ?? 0, MaxHeight ?? 0); - return Convert.ToInt32(newSize.Width); + return size.Width; } return MaxWidth; @@ -983,22 +972,11 @@ namespace MediaBrowser.Model.Dlna if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue) { - var size = new ImageSize - { - Width = videoStream.Width.Value, - Height = videoStream.Height.Value - }; - - double? maxWidth = MaxWidth.HasValue ? (double)MaxWidth.Value : (double?)null; - double? maxHeight = MaxHeight.HasValue ? (double)MaxHeight.Value : (double?)null; + ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value); - var newSize = DrawingUtils.Resize(size, - 0, - 0, - maxWidth ?? 0, - maxHeight ?? 0); + size = DrawingUtils.Resize(size, 0, 0, MaxWidth ?? 0, MaxHeight ?? 0); - return Convert.ToInt32(newSize.Height); + return size.Height; } return MaxHeight; diff --git a/MediaBrowser.Model/Drawing/DrawingUtils.cs b/MediaBrowser.Model/Drawing/DrawingUtils.cs index fbd074218..9fe85512f 100644 --- a/MediaBrowser.Model/Drawing/DrawingUtils.cs +++ b/MediaBrowser.Model/Drawing/DrawingUtils.cs @@ -1,3 +1,5 @@ +using System; + namespace MediaBrowser.Model.Drawing { /// <summary> @@ -14,27 +16,25 @@ namespace MediaBrowser.Model.Drawing /// <param name="maxWidth">A max fixed width, if desired</param> /// <param name="maxHeight">A max fixed height, if desired</param> /// <returns>A new size object</returns> - public static ImageSize Resize(ImageSize size, - double width, - double height, - double maxWidth, - double maxHeight) + public static ImageDimensions Resize(ImageDimensions size, + int width, + int height, + int maxWidth, + int maxHeight) { - double newWidth = size.Width; - double newHeight = size.Height; + int newWidth = size.Width; + int newHeight = size.Height; if (width > 0 && height > 0) { newWidth = width; newHeight = height; } - else if (height > 0) { newWidth = GetNewWidth(newHeight, newWidth, height); newHeight = height; } - else if (width > 0) { newHeight = GetNewHeight(newHeight, newWidth, width); @@ -53,7 +53,7 @@ namespace MediaBrowser.Model.Drawing newWidth = maxWidth; } - return new ImageSize { Width = newWidth, Height = newHeight }; + return new ImageDimensions(newWidth, newHeight); } /// <summary> @@ -62,15 +62,9 @@ namespace MediaBrowser.Model.Drawing /// <param name="currentHeight">Height of the current.</param> /// <param name="currentWidth">Width of the current.</param> /// <param name="newHeight">The new height.</param> - /// <returns>System.Double.</returns> - private static double GetNewWidth(double currentHeight, double currentWidth, double newHeight) - { - double scaleFactor = newHeight; - scaleFactor /= currentHeight; - scaleFactor *= currentWidth; - - return scaleFactor; - } + /// <returns>the new width</returns> + private static int GetNewWidth(int currentHeight, int currentWidth, int newHeight) + => Convert.ToInt32((double)newHeight / currentHeight * currentWidth); /// <summary> /// Gets the new height. @@ -79,13 +73,7 @@ namespace MediaBrowser.Model.Drawing /// <param name="currentWidth">Width of the current.</param> /// <param name="newWidth">The new width.</param> /// <returns>System.Double.</returns> - private static double GetNewHeight(double currentHeight, double currentWidth, double newWidth) - { - double scaleFactor = newWidth; - scaleFactor /= currentWidth; - scaleFactor *= currentHeight; - - return scaleFactor; - } + private static int GetNewHeight(int currentHeight, int currentWidth, int newWidth) + => Convert.ToInt32((double)newWidth / currentWidth * currentHeight); } } diff --git a/MediaBrowser.Model/Drawing/ImageSize.cs b/MediaBrowser.Model/Drawing/ImageSize.cs index 87764bbf4..75591d83d 100644 --- a/MediaBrowser.Model/Drawing/ImageSize.cs +++ b/MediaBrowser.Model/Drawing/ImageSize.cs @@ -1,36 +1,23 @@ -using System.Globalization; - namespace MediaBrowser.Model.Drawing { /// <summary> /// Struct ImageSize /// </summary> - public struct ImageSize + public struct ImageDimensions { - private double _height; - private double _width; - /// <summary> /// Gets or sets the height. /// </summary> /// <value>The height.</value> - public double Height - { - get => _height; - set => _height = value; - } + public int Height { get; set; } /// <summary> /// Gets or sets the width. /// </summary> /// <value>The width.</value> - public double Width - { - get => _width; - set => _width = value; - } + public int Width { get; set; } - public bool Equals(ImageSize size) + public bool Equals(ImageDimensions size) { return Width.Equals(size.Width) && Height.Equals(size.Height); } @@ -40,46 +27,10 @@ namespace MediaBrowser.Model.Drawing return string.Format("{0}-{1}", Width, Height); } - public ImageSize(string value) + public ImageDimensions(int width, int height) { - _width = 0; - - _height = 0; - - ParseValue(value); - } - - public ImageSize(int width, int height) - { - _width = width; - _height = height; - } - - public ImageSize(double width, double height) - { - _width = width; - _height = height; - } - - private void ParseValue(string value) - { - if (!string.IsNullOrEmpty(value)) - { - string[] parts = value.Split('-'); - - if (parts.Length == 2) - { - if (double.TryParse(parts[0], NumberStyles.Any, CultureInfo.InvariantCulture, out var val)) - { - _width = val; - } - - if (double.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out val)) - { - _height = val; - } - } - } + Width = width; + Height = height; } } } diff --git a/MediaBrowser.Model/Globalization/ILocalizationManager.cs b/MediaBrowser.Model/Globalization/ILocalizationManager.cs index a2531e504..05efb6681 100644 --- a/MediaBrowser.Model/Globalization/ILocalizationManager.cs +++ b/MediaBrowser.Model/Globalization/ILocalizationManager.cs @@ -49,7 +49,7 @@ namespace MediaBrowser.Model.Globalization /// Gets the localization options. /// </summary> /// <returns>IEnumerable{LocalizatonOption}.</returns> - LocalizatonOption[] GetLocalizationOptions(); + LocalizationOption[] GetLocalizationOptions(); string RemoveDiacritics(string text); diff --git a/MediaBrowser.Model/Globalization/LocalizationOption.cs b/MediaBrowser.Model/Globalization/LocalizationOption.cs new file mode 100644 index 000000000..c4c9a8919 --- /dev/null +++ b/MediaBrowser.Model/Globalization/LocalizationOption.cs @@ -0,0 +1,14 @@ +namespace MediaBrowser.Model.Globalization +{ + public class LocalizationOption + { + public LocalizationOption(string name, string value) + { + Name = name; + Value = value; + } + + public string Name { get; set; } + public string Value { get; set; } + } +} diff --git a/MediaBrowser.Model/Globalization/LocalizatonOption.cs b/MediaBrowser.Model/Globalization/LocalizatonOption.cs deleted file mode 100644 index 7fbc8135d..000000000 --- a/MediaBrowser.Model/Globalization/LocalizatonOption.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace MediaBrowser.Model.Globalization -{ - public class LocalizatonOption - { - public string Name { get; set; } - public string Value { get; set; } - } -} diff --git a/MediaBrowser.Model/System/ISystemEvents.cs b/MediaBrowser.Model/System/ISystemEvents.cs deleted file mode 100644 index 8c47d6fbf..000000000 --- a/MediaBrowser.Model/System/ISystemEvents.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace MediaBrowser.Model.System -{ - public interface ISystemEvents - { - event EventHandler Resume; - event EventHandler Suspend; - event EventHandler SessionLogoff; - event EventHandler SystemShutdown; - } -} diff --git a/MediaBrowser.Model/Tasks/ITaskManager.cs b/MediaBrowser.Model/Tasks/ITaskManager.cs index a7c2f6d86..57b8d1af8 100644 --- a/MediaBrowser.Model/Tasks/ITaskManager.cs +++ b/MediaBrowser.Model/Tasks/ITaskManager.cs @@ -72,7 +72,5 @@ namespace MediaBrowser.Model.Tasks event EventHandler<GenericEventArgs<IScheduledTaskWorker>> TaskExecuting; event EventHandler<TaskCompletionEventArgs> TaskCompleted; - - void RunTaskOnNextStartup(string key); } } diff --git a/MediaBrowser.Model/Tasks/SystemEvent.cs b/MediaBrowser.Model/Tasks/SystemEvent.cs deleted file mode 100644 index 5a3d8a8eb..000000000 --- a/MediaBrowser.Model/Tasks/SystemEvent.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace MediaBrowser.Model.Tasks -{ - /// <summary> - /// Enum SystemEvent - /// </summary> - public enum SystemEvent - { - /// <summary> - /// The wake from sleep - /// </summary> - WakeFromSleep = 0 - } -} diff --git a/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs b/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs index 80101ec48..714f11872 100644 --- a/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs +++ b/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs @@ -26,12 +26,6 @@ namespace MediaBrowser.Model.Tasks public long? IntervalTicks { get; set; } /// <summary> - /// Gets or sets the system event. - /// </summary> - /// <value>The system event.</value> - public SystemEvent? SystemEvent { get; set; } - - /// <summary> /// Gets or sets the day of week. /// </summary> /// <value>The day of week.</value> diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index ecae0c39d..e4bb52217 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -510,13 +510,11 @@ namespace MediaBrowser.Providers.Music return new ValueTuple<string, string>(); } - private static ValueTuple<string, string> ParseArtistNameCredit(XmlReader reader) + private static (string, string) ParseArtistNameCredit(XmlReader reader) { reader.MoveToContent(); reader.Read(); - string name = null; - // http://stackoverflow.com/questions/2299632/why-does-xmlreader-skip-every-other-element-if-there-is-no-whitespace-separator // Loop through each element @@ -547,7 +545,7 @@ namespace MediaBrowser.Providers.Music } } - return new ValueTuple<string, string>(name, null); + return (null, null); } private static ValueTuple<string, string> ParseArtistArtistCredit(XmlReader reader, string artistId) |
