From 9fdaa039c4b1e95842a219499f80ac963bbdb91e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 13 Oct 2017 15:18:05 -0400 Subject: rework device repository --- .../Devices/SqliteDeviceRepository.cs | 441 +++++++++++++++++++++ 1 file changed, 441 insertions(+) create mode 100644 Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs (limited to 'Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs') diff --git a/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs b/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs new file mode 100644 index 000000000..e8b7466a5 --- /dev/null +++ b/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs @@ -0,0 +1,441 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using Emby.Server.Implementations.Data; +using MediaBrowser.Controller; +using MediaBrowser.Model.Logging; +using SQLitePCL.pretty; +using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.IO; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Devices; +using MediaBrowser.Model.Devices; +using MediaBrowser.Model.Serialization; +using MediaBrowser.Model.Session; +using MediaBrowser.Controller.Configuration; + +namespace Emby.Server.Implementations.Devices +{ + public class SqliteDeviceRepository : BaseSqliteRepository, IDeviceRepository + { + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + protected IFileSystem FileSystem { get; private set; } + private readonly object _syncLock = new object(); + private readonly IJsonSerializer _json; + private IServerApplicationPaths _appPaths; + + public SqliteDeviceRepository(ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IJsonSerializer json) + : base(logger) + { + var appPaths = config.ApplicationPaths; + + DbFilePath = Path.Combine(appPaths.DataPath, "devices.db"); + FileSystem = fileSystem; + _json = json; + _appPaths = appPaths; + } + + public void Initialize() + { + try + { + InitializeInternal(); + } + catch (Exception ex) + { + Logger.ErrorException("Error loading database file. Will reset and retry.", ex); + + FileSystem.DeleteFile(DbFilePath); + + InitializeInternal(); + } + } + + private void InitializeInternal() + { + using (var connection = CreateConnection()) + { + RunDefaultInitialization(connection); + + string[] queries = { + "create table if not exists Devices (Id TEXT PRIMARY KEY, Name TEXT, ReportedName TEXT, CustomName TEXT, CameraUploadPath TEXT, LastUserName TEXT, AppName TEXT, AppVersion TEXT, LastUserId TEXT, DateLastModified DATETIME, Capabilities TEXT)", + "create index if not exists idx_id on Devices(Id)" + }; + + connection.RunQueries(queries); + + MigrateDevices(); + } + } + + private void MigrateDevices() + { + var files = FileSystem + .GetFilePaths(GetDevicesPath(), true) + .Where(i => string.Equals(Path.GetFileName(i), "device.json", StringComparison.OrdinalIgnoreCase)) + .ToList(); + + foreach (var file in files) + { + try + { + var device = _json.DeserializeFromFile(file); + + SaveDevice(device); + } + catch (Exception ex) + { + Logger.ErrorException("Error reading {0}", ex, file); + } + finally + { + try + { + FileSystem.DeleteFile(file); + } + catch (IOException) + { + try + { + FileSystem.MoveFile(file, Path.ChangeExtension(file, ".old")); + } + catch (IOException) + { + } + } + } + } + } + + private const string BaseSelectText = "select Id, Name, ReportedName, CustomName, CameraUploadPath, LastUserName, AppName, AppVersion, LastUserId, DateLastModified, Capabilities from Devices"; + + public void SaveCapabilities(string deviceId, ClientCapabilities capabilities) + { + using (WriteLock.Write()) + { + using (var connection = CreateConnection()) + { + connection.RunInTransaction(db => + { + using (var statement = db.PrepareStatement("update devices set Capabilities=@Capabilities where Id=@Id")) + { + statement.TryBind("@Id", deviceId); + + if (capabilities == null) + { + statement.TryBindNull("@Capabilities"); + } + else + { + statement.TryBind("@Capabilities", _json.SerializeToString(capabilities)); + } + + statement.MoveNext(); + } + }, TransactionMode); + } + } + } + + public void SaveDevice(DeviceInfo entry) + { + if (entry == null) + { + throw new ArgumentNullException("entry"); + } + + using (WriteLock.Write()) + { + using (var connection = CreateConnection()) + { + connection.RunInTransaction(db => + { + using (var statement = db.PrepareStatement("replace into Devices (Id, Name, ReportedName, CustomName, CameraUploadPath, LastUserName, AppName, AppVersion, LastUserId, DateLastModified, Capabilities) values (@Id, @Name, @ReportedName, @CustomName, @CameraUploadPath, @LastUserName, @AppName, @AppVersion, @LastUserId, @DateLastModified, @Capabilities)")) + { + statement.TryBind("@Id", entry.Id); + statement.TryBind("@Name", entry.Name); + statement.TryBind("@ReportedName", entry.ReportedName); + statement.TryBind("@CustomName", entry.CustomName); + statement.TryBind("@CameraUploadPath", entry.CameraUploadPath); + statement.TryBind("@LastUserName", entry.LastUserName); + statement.TryBind("@AppName", entry.AppName); + statement.TryBind("@AppVersion", entry.AppVersion); + statement.TryBind("@DateLastModified", entry.DateLastModified); + + if (entry.Capabilities == null) + { + statement.TryBindNull("@Capabilities"); + } + else + { + statement.TryBind("@Capabilities", _json.SerializeToString(entry.Capabilities)); + } + + statement.MoveNext(); + } + }, TransactionMode); + } + } + } + + public DeviceInfo GetDevice(string id) + { + using (WriteLock.Read()) + { + using (var connection = CreateConnection(true)) + { + var statementTexts = new List(); + statementTexts.Add(BaseSelectText + " where Id=@Id"); + + return connection.RunInTransaction(db => + { + var statements = PrepareAllSafe(db, statementTexts).ToList(); + + using (var statement = statements[0]) + { + statement.TryBind("@Id", id); + + foreach (var row in statement.ExecuteQuery()) + { + return GetEntry(row); + } + } + + return null; + + }, ReadTransactionMode); + } + } + } + + public List GetDevices() + { + using (WriteLock.Read()) + { + using (var connection = CreateConnection(true)) + { + var statementTexts = new List(); + statementTexts.Add(BaseSelectText + " order by DateLastModified desc"); + + return connection.RunInTransaction(db => + { + var list = new List(); + + var statements = PrepareAllSafe(db, statementTexts).ToList(); + + using (var statement = statements[0]) + { + foreach (var row in statement.ExecuteQuery()) + { + list.Add(GetEntry(row)); + } + } + + return list; + + }, ReadTransactionMode); + } + } + } + + public ClientCapabilities GetCapabilities(string id) + { + using (WriteLock.Read()) + { + using (var connection = CreateConnection(true)) + { + var statementTexts = new List(); + statementTexts.Add("Select Capabilities from Devices where Id=@Id"); + + return connection.RunInTransaction(db => + { + var statements = PrepareAllSafe(db, statementTexts).ToList(); + + using (var statement = statements[0]) + { + statement.TryBind("@Id", id); + + foreach (var row in statement.ExecuteQuery()) + { + if (row[0].SQLiteType != SQLiteType.Null) + { + return _json.DeserializeFromString(row.GetString(0)); + } + } + } + + return null; + + }, ReadTransactionMode); + } + } + } + + private DeviceInfo GetEntry(IReadOnlyList reader) + { + var index = 0; + + var info = new DeviceInfo + { + Id = reader.GetString(index) + }; + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.Name = reader.GetString(index); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.ReportedName = reader.GetString(index); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.CustomName = reader.GetString(index); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.CameraUploadPath = reader.GetString(index); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.LastUserName = reader.GetString(index); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.AppName = reader.GetString(index); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.AppVersion = reader.GetString(index); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.LastUserId = reader.GetString(index); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.DateLastModified = reader[index].ReadDateTime(); + } + + index++; + if (reader[index].SQLiteType != SQLiteType.Null) + { + info.Capabilities = _json.DeserializeFromString(reader.GetString(index)); + } + + return info; + } + + private string GetDevicesPath() + { + return Path.Combine(_appPaths.DataPath, "devices"); + } + + private string GetDevicePath(string id) + { + return Path.Combine(GetDevicesPath(), id.GetMD5().ToString("N")); + } + + public ContentUploadHistory GetCameraUploadHistory(string deviceId) + { + var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json"); + + lock (_syncLock) + { + try + { + return _json.DeserializeFromFile(path); + } + catch (IOException) + { + return new ContentUploadHistory + { + DeviceId = deviceId + }; + } + } + } + + public void AddCameraUpload(string deviceId, LocalFileInfo file) + { + var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json"); + FileSystem.CreateDirectory(FileSystem.GetDirectoryName(path)); + + lock (_syncLock) + { + ContentUploadHistory history; + + try + { + history = _json.DeserializeFromFile(path); + } + catch (IOException) + { + history = new ContentUploadHistory + { + DeviceId = deviceId + }; + } + + history.DeviceId = deviceId; + + var list = history.FilesUploaded.ToList(); + list.Add(file); + history.FilesUploaded = list.ToArray(list.Count); + + _json.SerializeToFile(history, path); + } + } + + public void DeleteDevice(string id) + { + using (WriteLock.Write()) + { + using (var connection = CreateConnection()) + { + connection.RunInTransaction(db => + { + using (var statement = db.PrepareStatement("delete from devices where Id=@Id")) + { + statement.TryBind("@Id", id); + + statement.MoveNext(); + } + }, TransactionMode); + } + } + + var path = GetDevicePath(id); + + lock (_syncLock) + { + try + { + FileSystem.DeleteDirectory(path, true); + } + catch (IOException) + { + } + } + } + } +} -- cgit v1.2.3 From 0bc3cdfab7d15a42dadb0101d037cbf12631362b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 13 Oct 2017 15:21:43 -0400 Subject: update suggestions --- Emby.Server.Implementations/Data/SqliteItemRepository.cs | 2 +- Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index bc4ab8315..a6c7150da 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -3038,8 +3038,8 @@ namespace Emby.Server.Implementations.Data { if (orderBy.Count == 0) { - orderBy.Add(new Tuple(ItemSortBy.Random, SortOrder.Ascending)); orderBy.Add(new Tuple("SimilarityScore", SortOrder.Descending)); + orderBy.Add(new Tuple(ItemSortBy.Random, SortOrder.Ascending)); //orderBy.Add(new Tuple(ItemSortBy.Random, SortOrder.Ascending)); } } diff --git a/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs b/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs index e8b7466a5..ca0552d98 100644 --- a/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs +++ b/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs @@ -83,6 +83,8 @@ namespace Emby.Server.Implementations.Devices { var device = _json.DeserializeFromFile(file); + device.Name = string.IsNullOrWhiteSpace(device.CustomName) ? device.ReportedName : device.CustomName; + SaveDevice(device); } catch (Exception ex) -- cgit v1.2.3 From 164e7dc896aa71a921f673e2058a2272fc917c4e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 14 Oct 2017 02:52:56 -0400 Subject: improve live tv direct play --- Emby.Server.Implementations/ApplicationHost.cs | 9 ++- .../Devices/SqliteDeviceRepository.cs | 16 ++++-- .../HttpClientManager/HttpClientInfo.cs | 2 + .../TunerHosts/HdHomerun/HdHomerunHttpStream.cs | 13 ++--- .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 7 +-- .../LiveTv/TunerHosts/LiveStream.cs | 34 ++++++++--- MediaBrowser.Api/LiveTv/LiveTvService.cs | 4 +- MediaBrowser.Api/LiveTv/ProgressiveFileCopier.cs | 13 ++--- MediaBrowser.Providers/Manager/MetadataService.cs | 66 +++++++++++++++------- .../TV/MissingEpisodeProvider.cs | 4 -- 10 files changed, 110 insertions(+), 58 deletions(-) (limited to 'Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 96c87b6a5..91493cf53 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -792,6 +792,11 @@ namespace Emby.Server.Implementations protected abstract IConnectManager CreateConnectManager(); protected abstract ISyncManager CreateSyncManager(); + + protected virtual IHttpClient CreateHttpClient() + { + return new HttpClientManager.HttpClientManager(ApplicationPaths, LogManager.GetLogger("HttpClient"), FileSystemManager, MemoryStreamFactory, GetDefaultUserAgent); + } /// /// Registers resources that classes will depend on @@ -814,7 +819,7 @@ namespace Emby.Server.Implementations RegisterSingleInstance(FileSystemManager); - HttpClient = new HttpClientManager.HttpClientManager(ApplicationPaths, LogManager.GetLogger("HttpClient"), FileSystemManager, MemoryStreamFactory, GetDefaultUserAgent); + HttpClient = CreateHttpClient(); RegisterSingleInstance(HttpClient); RegisterSingleInstance(NetworkManager); @@ -1118,7 +1123,7 @@ namespace Emby.Server.Implementations IsoManager.AddParts(list); } - private string GetDefaultUserAgent() + protected string GetDefaultUserAgent() { var name = FormatAttribute(Name); diff --git a/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs b/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs index ca0552d98..a15eb3558 100644 --- a/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs +++ b/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs @@ -72,10 +72,18 @@ namespace Emby.Server.Implementations.Devices private void MigrateDevices() { - var files = FileSystem - .GetFilePaths(GetDevicesPath(), true) - .Where(i => string.Equals(Path.GetFileName(i), "device.json", StringComparison.OrdinalIgnoreCase)) - .ToList(); + List files; + try + { + files = FileSystem + .GetFilePaths(GetDevicesPath(), true) + .Where(i => string.Equals(Path.GetFileName(i), "device.json", StringComparison.OrdinalIgnoreCase)) + .ToList(); + } + catch (IOException) + { + return; + } foreach (var file in files) { diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientInfo.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientInfo.cs index 6d17bf94d..21cec9d2b 100644 --- a/Emby.Server.Implementations/HttpClientManager/HttpClientInfo.cs +++ b/Emby.Server.Implementations/HttpClientManager/HttpClientInfo.cs @@ -1,4 +1,5 @@ using System; +using System.Net.Http; namespace Emby.Server.Implementations.HttpClientManager { @@ -12,5 +13,6 @@ namespace Emby.Server.Implementations.HttpClientManager /// /// The last timeout. public DateTime LastTimeout { get; set; } + public HttpClient HttpClient { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs index 5e3923972..ad9c0d894 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs @@ -22,7 +22,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private readonly IHttpClient _httpClient; private readonly IServerApplicationHost _appHost; - private readonly CancellationTokenSource _liveStreamCancellationTokenSource = new CancellationTokenSource(); private readonly TaskCompletionSource _liveStreamTaskCompletionSource = new TaskCompletionSource(); public HdHomerunHttpStream(MediaSourceInfo mediaSource, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, IEnvironmentInfo environment) @@ -35,7 +34,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun protected override Task OpenInternal(CancellationToken openCancellationToken) { - _liveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); + LiveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); var mediaSource = OriginalMediaSource; @@ -45,7 +44,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var taskCompletionSource = new TaskCompletionSource(); - StartStreaming(url, taskCompletionSource, _liveStreamCancellationTokenSource.Token); + StartStreaming(url, taskCompletionSource, LiveStreamCancellationTokenSource.Token); //OpenedMediaSource.Protocol = MediaProtocol.File; //OpenedMediaSource.Path = tempFile; @@ -65,12 +64,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun //await Task.Delay(5000).ConfigureAwait(false); } - public override Task Close() + public override async Task Close() { Logger.Info("Closing HDHR live stream"); - _liveStreamCancellationTokenSource.Cancel(); + LiveStreamCancellationTokenSource.Cancel(); - return _liveStreamTaskCompletionSource.Task; + await _liveStreamTaskCompletionSource.Task.ConfigureAwait(false); + await DeleteTempFile(TempFilePath).ConfigureAwait(false); } private Task StartStreaming(string url, TaskCompletionSource openTaskCompletionSource, CancellationToken cancellationToken) @@ -112,7 +112,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } _liveStreamTaskCompletionSource.TrySetResult(true); - await DeleteTempFile(TempFilePath).ConfigureAwait(false); }); } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index ff8fd1bc4..4187fcd8f 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -26,7 +26,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private readonly IServerApplicationHost _appHost; private readonly ISocketFactory _socketFactory; - private readonly CancellationTokenSource _liveStreamCancellationTokenSource = new CancellationTokenSource(); private readonly TaskCompletionSource _liveStreamTaskCompletionSource = new TaskCompletionSource(); private readonly IHdHomerunChannelCommands _channelCommands; private readonly int _numTuners; @@ -45,7 +44,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun protected override Task OpenInternal(CancellationToken openCancellationToken) { - _liveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); + LiveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); var mediaSource = OriginalMediaSource; @@ -56,7 +55,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var taskCompletionSource = new TaskCompletionSource(); - StartStreaming(uri.Host, localPort, taskCompletionSource, _liveStreamCancellationTokenSource.Token); + StartStreaming(uri.Host, localPort, taskCompletionSource, LiveStreamCancellationTokenSource.Token); //OpenedMediaSource.Protocol = MediaProtocol.File; //OpenedMediaSource.Path = tempFile; @@ -76,7 +75,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun public override Task Close() { Logger.Info("Closing HDHR UDP live stream"); - _liveStreamCancellationTokenSource.Cancel(); + LiveStreamCancellationTokenSource.Cancel(); return _liveStreamTaskCompletionSource.Task; } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 5be91c6c1..685f794fd 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -32,6 +32,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts protected readonly string TempFilePath; protected readonly ILogger Logger; + protected readonly CancellationTokenSource LiveStreamCancellationTokenSource = new CancellationTokenSource(); public LiveStream(MediaSourceInfo mediaSource, IEnvironmentInfo environment, IFileSystem fileSystem, ILogger logger, IServerApplicationPaths appPaths) { @@ -80,6 +81,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts FileSystem.DeleteFile(path); return; } + catch (DirectoryNotFoundException) + { + return; + } + catch (FileNotFoundException) + { + return; + } catch { @@ -96,6 +105,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts public async Task CopyToAsync(Stream stream, CancellationToken cancellationToken) { + cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, LiveStreamCancellationTokenSource.Token).Token; + var allowAsync = false;//Environment.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows; // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039 @@ -110,16 +121,27 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts private static async Task CopyTo(Stream source, Stream destination, int bufferSize, Action onStarted, CancellationToken cancellationToken) { byte[] buffer = new byte[bufferSize]; - while (true) + + var eofCount = 0; + var emptyReadLimit = 1000; + + while (eofCount < emptyReadLimit) { cancellationToken.ThrowIfCancellationRequested(); - var read = source.Read(buffer, 0, buffer.Length); + var bytesRead = source.Read(buffer, 0, buffer.Length); - if (read > 0) + if (bytesRead == 0) + { + eofCount++; + await Task.Delay(10, cancellationToken).ConfigureAwait(false); + } + else { + eofCount = 0; + //await destination.WriteAsync(buffer, 0, read).ConfigureAwait(false); - destination.Write(buffer, 0, read); + destination.Write(buffer, 0, bytesRead); if (onStarted != null) { @@ -127,10 +149,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts onStarted = null; } } - else - { - await Task.Delay(10).ConfigureAwait(false); - } } } diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 1ae7323dc..703c96e0c 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -734,7 +734,7 @@ namespace MediaBrowser.Api.LiveTv outputHeaders["Content-Type"] = Model.Net.MimeTypes.GetMimeType(path); - return new ProgressiveFileCopier(_fileSystem, path, outputHeaders, Logger, _environment, CancellationToken.None) + return new ProgressiveFileCopier(_fileSystem, path, outputHeaders, Logger, _environment) { AllowEndOfFile = false }; @@ -753,7 +753,7 @@ namespace MediaBrowser.Api.LiveTv outputHeaders["Content-Type"] = Model.Net.MimeTypes.GetMimeType("file." + request.Container); - return new ProgressiveFileCopier(directStreamProvider, outputHeaders, Logger, _environment, CancellationToken.None) + return new ProgressiveFileCopier(directStreamProvider, outputHeaders, Logger, _environment) { AllowEndOfFile = false }; diff --git a/MediaBrowser.Api/LiveTv/ProgressiveFileCopier.cs b/MediaBrowser.Api/LiveTv/ProgressiveFileCopier.cs index 9ce109fc4..74293ccd9 100644 --- a/MediaBrowser.Api/LiveTv/ProgressiveFileCopier.cs +++ b/MediaBrowser.Api/LiveTv/ProgressiveFileCopier.cs @@ -16,7 +16,6 @@ namespace MediaBrowser.Api.LiveTv private readonly IFileSystem _fileSystem; private readonly ILogger _logger; private readonly string _path; - private readonly CancellationToken _cancellationToken; private readonly Dictionary _outputHeaders; const int StreamCopyToBufferSize = 81920; @@ -28,22 +27,20 @@ namespace MediaBrowser.Api.LiveTv private readonly IDirectStreamProvider _directStreamProvider; private readonly IEnvironmentInfo _environment; - public ProgressiveFileCopier(IFileSystem fileSystem, string path, Dictionary outputHeaders, ILogger logger, IEnvironmentInfo environment, CancellationToken cancellationToken) + public ProgressiveFileCopier(IFileSystem fileSystem, string path, Dictionary outputHeaders, ILogger logger, IEnvironmentInfo environment) { _fileSystem = fileSystem; _path = path; _outputHeaders = outputHeaders; _logger = logger; - _cancellationToken = cancellationToken; _environment = environment; } - public ProgressiveFileCopier(IDirectStreamProvider directStreamProvider, Dictionary outputHeaders, ILogger logger, IEnvironmentInfo environment, CancellationToken cancellationToken) + public ProgressiveFileCopier(IDirectStreamProvider directStreamProvider, Dictionary outputHeaders, ILogger logger, IEnvironmentInfo environment) { _directStreamProvider = directStreamProvider; _outputHeaders = outputHeaders; _logger = logger; - _cancellationToken = cancellationToken; _environment = environment; } @@ -69,8 +66,6 @@ namespace MediaBrowser.Api.LiveTv public async Task WriteToAsync(Stream outputStream, CancellationToken cancellationToken) { - cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _cancellationToken).Token; - if (_directStreamProvider != null) { await _directStreamProvider.CopyToAsync(outputStream, cancellationToken).ConfigureAwait(false); @@ -89,7 +84,9 @@ namespace MediaBrowser.Api.LiveTv inputStream.Position = StartPosition; } - while (eofCount < 20 || !AllowEndOfFile) + var emptyReadLimit = AllowEndOfFile ? 20 : 100; + + while (eofCount < emptyReadLimit) { int bytesRead; if (allowAsyncFileRead) diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index c37e05d95..3759670d4 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using MediaBrowser.Model.IO; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Providers; +using MediaBrowser.Providers.MediaInfo; namespace MediaBrowser.Providers.Manager { @@ -37,6 +38,28 @@ namespace MediaBrowser.Providers.Manager LibraryManager = libraryManager; } + private bool RequiresRefresh(IHasMetadata item, IDirectoryService directoryService) + { + if (item.RequiresRefresh()) + { + return true; + } + + if (item.SupportsLocalMetadata) + { + var video = item as Video; + + if (video != null && !video.IsPlaceHolder) + { + return !video.SubtitleFiles + .SequenceEqual(SubtitleResolver.GetSubtitleFiles(video, directoryService, FileSystem, false) + .OrderBy(i => i), StringComparer.OrdinalIgnoreCase); + } + } + + return false; + } + public async Task RefreshMetadata(IHasMetadata item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) { var itemOfType = (TItemType)item; @@ -47,19 +70,35 @@ namespace MediaBrowser.Providers.Manager var libraryOptions = LibraryManager.GetLibraryOptions((BaseItem)item); - if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None) + DateTime? newDateModified = null; + if (item.LocationType == LocationType.FileSystem) { - // TODO: If this returns true, should we instead just change metadata refresh mode to Full? - requiresRefresh = item.RequiresRefresh(); + var file = refreshOptions.DirectoryService.GetFile(item.Path); + if (file != null) + { + newDateModified = file.LastWriteTimeUtc; + if (item.EnableRefreshOnDateModifiedChange) + { + if (newDateModified != item.DateModified) + { + Logger.Debug("Date modified for {0}. Old date {1} new date {2} Id {3}", item.Path, item.DateModified, newDateModified, item.Id); + requiresRefresh = true; + } + } + } } - if (!requiresRefresh && - libraryOptions.AutomaticRefreshIntervalDays > 0 && - (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= libraryOptions.AutomaticRefreshIntervalDays) + if (!requiresRefresh && libraryOptions.AutomaticRefreshIntervalDays > 0 && (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= libraryOptions.AutomaticRefreshIntervalDays) { requiresRefresh = true; } + if (!requiresRefresh && refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None) + { + // TODO: If this returns true, should we instead just change metadata refresh mode to Full? + requiresRefresh = RequiresRefresh(item, refreshOptions.DirectoryService); + } + var itemImageProvider = new ItemImageProvider(Logger, ProviderManager, ServerConfigurationManager, FileSystem); var localImagesFailed = false; @@ -145,20 +184,9 @@ namespace MediaBrowser.Providers.Manager var beforeSaveResult = BeforeSave(itemOfType, isFirstRefresh || refreshOptions.ReplaceAllMetadata || refreshOptions.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || requiresRefresh, updateType); updateType = updateType | beforeSaveResult; - if (item.LocationType == LocationType.FileSystem) + if (newDateModified.HasValue) { - var file = refreshOptions.DirectoryService.GetFile(item.Path); - if (file != null) - { - var fileLastWriteTime = file.LastWriteTimeUtc; - if (item.EnableRefreshOnDateModifiedChange && fileLastWriteTime != item.DateModified) - { - Logger.Debug("Date modified for {0}. Old date {1} new date {2} Id {3}", item.Path, item.DateModified, fileLastWriteTime, item.Id); - requiresRefresh = true; - } - - item.DateModified = fileLastWriteTime; - } + item.DateModified = newDateModified.Value; } // Save if changes were made, or it's never been saved before diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index 44e3cff6a..b68e6e4a9 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -350,8 +350,6 @@ namespace MediaBrowser.Providers.TV foreach (var episodeToRemove in episodesToRemove.Select(e => e.Episode)) { - _logger.Info("Removing missing/unaired episode {0} {1}x{2}", episodeToRemove.Series.Name, episodeToRemove.ParentIndexNumber, episodeToRemove.IndexNumber); - await episodeToRemove.Delete(new DeleteOptions { DeleteFileLocation = true @@ -418,8 +416,6 @@ namespace MediaBrowser.Providers.TV foreach (var seasonToRemove in seasonsToRemove) { - _logger.Info("Removing virtual season {0} {1}", seasonToRemove.Series.Name, seasonToRemove.IndexNumber); - await seasonToRemove.Delete(new DeleteOptions { DeleteFileLocation = true -- cgit v1.2.3 From 7e5036a5875cb7f03ad728f970d66471ca30236b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 22 Oct 2017 02:22:43 -0400 Subject: update image aspect ratio detection --- Emby.Dlna/Didl/DidlBuilder.cs | 17 ++++++- Emby.Drawing/ImageProcessor.cs | 36 +++++++++++---- Emby.Photos/PhotoProvider.cs | 10 ++-- .../Activity/ActivityRepository.cs | 2 +- .../Data/SqliteDisplayPreferencesRepository.cs | 2 +- .../Data/SqliteItemRepository.cs | 53 ++++++++++++++++++++-- .../Data/SqliteUserDataRepository.cs | 2 +- .../Data/SqliteUserRepository.cs | 3 +- .../Devices/SqliteDeviceRepository.cs | 2 +- Emby.Server.Implementations/Dto/DtoService.cs | 14 +++--- .../Library/LibraryManager.cs | 7 +++ .../Notifications/NotificationManager.cs | 1 - .../Security/AuthenticationRepository.cs | 2 +- .../Social/SharingRepository.cs | 2 +- MediaBrowser.Api/Images/ImageService.cs | 10 +++- MediaBrowser.Api/Session/SessionsService.cs | 17 ++++--- MediaBrowser.Controller/Channels/Channel.cs | 8 ---- MediaBrowser.Controller/Drawing/IImageProcessor.cs | 11 +---- MediaBrowser.Controller/Dto/IDtoService.cs | 4 +- MediaBrowser.Controller/Entities/BaseItem.cs | 7 +++ MediaBrowser.Controller/Entities/ItemImageInfo.cs | 3 ++ MediaBrowser.Controller/Entities/PhotoAlbum.cs | 5 -- MediaBrowser.Controller/Entities/Video.cs | 8 ---- MediaBrowser.Controller/Library/ILibraryManager.cs | 2 + .../Persistence/IItemRepository.cs | 2 + 25 files changed, 155 insertions(+), 75 deletions(-) (limited to 'Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs') diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index be76e5816..5b18a2b7c 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -1137,8 +1137,21 @@ namespace Emby.Dlna.Didl } - int? width = null; - int? height = null; + int? width = imageInfo.Width; + int? height = imageInfo.Height; + + if (width == 0 || height == 0) + { + //_imageProcessor.GetImageSize(item, imageInfo); + width = null; + height = null; + } + + else if (width == -1 || height == -1) + { + width = null; + height = null; + } //try //{ diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 831454972..6bdb06c83 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -442,19 +442,39 @@ namespace Emby.Drawing return GetCachePath(ResizedImageCachePath, filename, "." + format.ToString().ToLower()); } - public ImageSize GetImageSize(ItemImageInfo info, bool allowSlowMethods) + public ImageSize GetImageSize(BaseItem item, ItemImageInfo info) { - return GetImageSize(info.Path, allowSlowMethods); + return GetImageSize(item, info, false, true); } - public ImageSize GetImageSize(ItemImageInfo info) + public ImageSize GetImageSize(BaseItem item, ItemImageInfo info, bool allowSlowMethods, bool updateItem) { - return GetImageSize(info.Path, false); - } + var width = info.Width; + var height = info.Height; - public ImageSize GetImageSize(string path) - { - return GetImageSize(path, false); + if (height > 0 && width > 0) + { + return new ImageSize + { + Width = width, + Height = height + }; + } + + var path = item.Path; + _logger.Info("Getting image size for item {0} {1}", item.GetType().Name, path); + + var size = GetImageSize(path, allowSlowMethods); + + info.Height = Convert.ToInt32(size.Height); + info.Width = Convert.ToInt32(size.Width); + + if (updateItem) + { + _libraryManager().UpdateImages(item); + } + + return size; } /// diff --git a/Emby.Photos/PhotoProvider.cs b/Emby.Photos/PhotoProvider.cs index 3a29b86a5..11a7db47d 100644 --- a/Emby.Photos/PhotoProvider.cs +++ b/Emby.Photos/PhotoProvider.cs @@ -163,10 +163,14 @@ namespace Emby.Photos if (!item.Width.HasValue || !item.Height.HasValue) { - var size = _imageProcessor.GetImageSize(item.Path); + var img = item.GetImageInfo(ImageType.Primary, 0); + var size = _imageProcessor.GetImageSize(item, img, false, false); - item.Width = Convert.ToInt32(size.Width); - item.Height = Convert.ToInt32(size.Height); + if (size.Width > 0 && size.Height > 0) + { + item.Width = Convert.ToInt32(size.Width); + item.Height = Convert.ToInt32(size.Height); + } } const ItemUpdateType result = ItemUpdateType.ImageUpdate | ItemUpdateType.MetadataImport; diff --git a/Emby.Server.Implementations/Activity/ActivityRepository.cs b/Emby.Server.Implementations/Activity/ActivityRepository.cs index 1ae8e5e66..6293cc69f 100644 --- a/Emby.Server.Implementations/Activity/ActivityRepository.cs +++ b/Emby.Server.Implementations/Activity/ActivityRepository.cs @@ -49,7 +49,7 @@ namespace Emby.Server.Implementations.Activity RunDefaultInitialization(connection); string[] queries = { - "create table if not exists ActivityLogEntries (Id GUID PRIMARY KEY, Name TEXT, Overview TEXT, ShortOverview TEXT, Type TEXT, ItemId TEXT, UserId TEXT, DateCreated DATETIME, LogSeverity TEXT)", + "create table if not exists ActivityLogEntries (Id GUID PRIMARY KEY NOT NULL, Name TEXT NOT NULL, Overview TEXT, ShortOverview TEXT, Type TEXT NOT NULL, ItemId TEXT, UserId TEXT, DateCreated DATETIME NOT NULL, LogSeverity TEXT NOT NULL)", "create index if not exists idx_ActivityLogEntries on ActivityLogEntries(Id)" }; diff --git a/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs b/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs index 1901ce848..e6afcd410 100644 --- a/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs @@ -75,7 +75,7 @@ namespace Emby.Server.Implementations.Data string[] queries = { - "create table if not exists userdisplaypreferences (id GUID, userId GUID, client text, data BLOB)", + "create table if not exists userdisplaypreferences (id GUID NOT NULL, userId GUID NOT NULL, client text NOT NULL, data BLOB NOT NULL)", "create unique index if not exists userdisplaypreferencesindex on userdisplaypreferences (id, userId, client)" }; diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index a6c7150da..01416a307 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -146,11 +146,11 @@ namespace Emby.Server.Implementations.Data "create table if not exists TypedBaseItems (guid GUID primary key NOT NULL, type TEXT NOT NULL, data BLOB NULL, ParentId GUID NULL, Path TEXT NULL)", - "create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, AncestorIdText TEXT, PRIMARY KEY (ItemId, AncestorId))", + "create table if not exists AncestorIds (ItemId GUID NOT NULL, AncestorId GUID NOT NULL, AncestorIdText TEXT NOT NULL, PRIMARY KEY (ItemId, AncestorId))", "create index if not exists idx_AncestorIds1 on AncestorIds(AncestorId)", "create index if not exists idx_AncestorIds5 on AncestorIds(AncestorIdText,ItemId)", - "create table if not exists ItemValues (ItemId GUID, Type INT, Value TEXT, CleanValue TEXT)", + "create table if not exists ItemValues (ItemId GUID NOT NULL, Type INT NOT NULL, Value TEXT NOT NULL, CleanValue TEXT NOT NULL)", "create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)", @@ -158,7 +158,7 @@ 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, StartPositionTicks BIGINT, 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, @@ -616,6 +616,33 @@ namespace Emby.Server.Implementations.Data SaveItems(new List { item }, cancellationToken); } + public void SaveImages(BaseItem item) + { + if (item == null) + { + throw new ArgumentNullException("item"); + } + + CheckDisposed(); + + using (WriteLock.Write()) + { + using (var connection = CreateConnection()) + { + connection.RunInTransaction(db => + { + using (var saveImagesStatement = PrepareStatement(db, "Update TypedBaseItems set Images=@Images where guid=@Id")) + { + saveImagesStatement.TryBind("@Id", item.Id.ToGuidBlob()); + saveImagesStatement.TryBind("@Images", SerializeImages(item)); + + saveImagesStatement.MoveNext(); + } + }, TransactionMode); + } + } + } + /// /// Saves the items. /// @@ -1170,7 +1197,11 @@ namespace Emby.Server.Implementations.Data delimeter + image.DateModified.Ticks.ToString(CultureInfo.InvariantCulture) + delimeter + - image.Type; + image.Type + + delimeter + + image.Width.ToString(CultureInfo.InvariantCulture) + + delimeter + + image.Height.ToString(CultureInfo.InvariantCulture); } public ItemImageInfo ItemImageInfoFromValueString(string value) @@ -1198,6 +1229,20 @@ namespace Emby.Server.Implementations.Data image.Type = type; } + if (parts.Length >= 5) + { + int width; + int height; + if (int.TryParse(parts[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out width)) + { + if (int.TryParse(parts[4], NumberStyles.Integer, CultureInfo.InvariantCulture, out height)) + { + image.Width = width; + image.Height = height; + } + } + } + return image; } diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index ef1d7ba44..ad5c60ede 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -52,7 +52,7 @@ namespace Emby.Server.Implementations.Data { string[] queries = { - "create table if not exists userdata (key nvarchar, userId GUID, rating float null, played bit, playCount int, isFavorite bit, playbackPositionTicks bigint, lastPlayedDate datetime null)", + "create table if not exists userdata (key nvarchar not null, userId GUID not null, rating float null, played bit not null, playCount int not null, isFavorite bit not null, playbackPositionTicks bigint not null, lastPlayedDate datetime null)", "create table if not exists DataSettings (IsUserDataImported bit)", diff --git a/Emby.Server.Implementations/Data/SqliteUserRepository.cs b/Emby.Server.Implementations/Data/SqliteUserRepository.cs index b65996e40..e89de11c6 100644 --- a/Emby.Server.Implementations/Data/SqliteUserRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserRepository.cs @@ -53,9 +53,8 @@ namespace Emby.Server.Implementations.Data string[] queries = { - "create table if not exists users (guid GUID primary key, data BLOB)", + "create table if not exists users (guid GUID primary key NOT NULL, data BLOB NOT NULL)", "create index if not exists idx_users on users(guid)", - "create table if not exists schema_version (table_name primary key, version)", "pragma shrink_memory" }; diff --git a/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs b/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs index a15eb3558..b11a5d65b 100644 --- a/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs +++ b/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs @@ -60,7 +60,7 @@ namespace Emby.Server.Implementations.Devices RunDefaultInitialization(connection); string[] queries = { - "create table if not exists Devices (Id TEXT PRIMARY KEY, Name TEXT, ReportedName TEXT, CustomName TEXT, CameraUploadPath TEXT, LastUserName TEXT, AppName TEXT, AppVersion TEXT, LastUserId TEXT, DateLastModified DATETIME, Capabilities TEXT)", + "create table if not exists Devices (Id TEXT PRIMARY KEY, Name TEXT NOT NULL, ReportedName TEXT NOT NULL, CustomName TEXT, CameraUploadPath TEXT, LastUserName TEXT NOT NULL, AppName TEXT NOT NULL, AppVersion TEXT NOT NULL, LastUserId TEXT NOT NULL, DateLastModified DATETIME NOT NULL, Capabilities TEXT NOT NULL)", "create index if not exists idx_id on Devices(Id)" }; diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index ef66c201c..a0176e406 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -1608,12 +1608,12 @@ namespace Emby.Server.Implementations.Dto /// The dto. /// The item. /// Task. - public void AttachPrimaryImageAspectRatio(IItemDto dto, IHasMetadata item) + public void AttachPrimaryImageAspectRatio(IItemDto dto, BaseItem item) { dto.PrimaryImageAspectRatio = GetPrimaryImageAspectRatio(item); } - public double? GetPrimaryImageAspectRatio(IHasMetadata item) + public double? GetPrimaryImageAspectRatio(BaseItem item) { var imageInfo = item.GetImageInfo(ImageType.Primary, 0); @@ -1646,12 +1646,14 @@ namespace Emby.Server.Implementations.Dto return null; } - return null; - _logger.Info("Getting image size for item type {0}", item.GetType().Name); - try { - size = _imageProcessor.GetImageSize(imageInfo); + size = _imageProcessor.GetImageSize(item, imageInfo); + + if (size.Width <= 0 || size.Height <= 0) + { + return null; + } } catch { diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index a7b85ad42..cac1cb3b4 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1826,6 +1826,13 @@ namespace Emby.Server.Implementations.Library } } + public void UpdateImages(BaseItem item) + { + ItemRepository.SaveImages(item); + + RegisterItem(item); + } + /// /// Updates the item. /// diff --git a/Emby.Server.Implementations/Notifications/NotificationManager.cs b/Emby.Server.Implementations/Notifications/NotificationManager.cs index 5b4c43dd5..e11f2790e 100644 --- a/Emby.Server.Implementations/Notifications/NotificationManager.cs +++ b/Emby.Server.Implementations/Notifications/NotificationManager.cs @@ -76,7 +76,6 @@ namespace Emby.Server.Implementations.Notifications var tasks = users.Select(i => SendNotification(request, service, title, description, i, cancellationToken)); return Task.WhenAll(tasks); - } private IEnumerable GetUserIds(NotificationRequest request, NotificationOption options) diff --git a/Emby.Server.Implementations/Security/AuthenticationRepository.cs b/Emby.Server.Implementations/Security/AuthenticationRepository.cs index f5b847ccf..b1877d776 100644 --- a/Emby.Server.Implementations/Security/AuthenticationRepository.cs +++ b/Emby.Server.Implementations/Security/AuthenticationRepository.cs @@ -34,7 +34,7 @@ namespace Emby.Server.Implementations.Security string[] queries = { - "create table if not exists AccessTokens (Id GUID PRIMARY KEY, AccessToken TEXT NOT NULL, DeviceId TEXT, AppName TEXT, AppVersion TEXT, DeviceName TEXT, UserId TEXT, IsActive BIT, DateCreated DATETIME NOT NULL, DateRevoked DATETIME)", + "create table if not exists AccessTokens (Id GUID PRIMARY KEY NOT NULL, AccessToken TEXT NOT NULL, DeviceId TEXT NOT NULL, AppName TEXT NOT NULL, AppVersion TEXT NOT NULL, DeviceName TEXT NOT NULL, UserId TEXT, IsActive BIT NOT NULL, DateCreated DATETIME NOT NULL, DateRevoked DATETIME)", "create index if not exists idx_AccessTokens on AccessTokens(Id)" }; diff --git a/Emby.Server.Implementations/Social/SharingRepository.cs b/Emby.Server.Implementations/Social/SharingRepository.cs index f0b8cbd30..3c9e1024f 100644 --- a/Emby.Server.Implementations/Social/SharingRepository.cs +++ b/Emby.Server.Implementations/Social/SharingRepository.cs @@ -50,7 +50,7 @@ namespace Emby.Server.Implementations.Social string[] queries = { - "create table if not exists Shares (Id GUID, ItemId TEXT, UserId TEXT, ExpirationDate DateTime, PRIMARY KEY (Id))", + "create table if not exists Shares (Id GUID NOT NULL, ItemId TEXT NOT NULL, UserId TEXT NOT NULL, ExpirationDate DateTime NOT NULL, PRIMARY KEY (Id))", "create index if not exists idx_Shares on Shares(Id)", "pragma shrink_memory" diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 72e4fe224..2b8ac1a66 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -315,7 +315,7 @@ namespace MediaBrowser.Api.Images return list; } - private ImageInfo GetImageInfo(IHasMetadata item, ItemImageInfo info, int? imageIndex) + private ImageInfo GetImageInfo(BaseItem item, ItemImageInfo info, int? imageIndex) { try { @@ -330,11 +330,17 @@ namespace MediaBrowser.Api.Images var fileInfo = _fileSystem.GetFileInfo(info.Path); length = fileInfo.Length; - var size = _imageProcessor.GetImageSize(info, true); + var size = _imageProcessor.GetImageSize(item, info, true, true); width = Convert.ToInt32(size.Width); height = Convert.ToInt32(size.Height); + if (width <= 0 || height <= 0) + { + width = null; + height = null; + } + } } catch diff --git a/MediaBrowser.Api/Session/SessionsService.cs b/MediaBrowser.Api/Session/SessionsService.cs index 8f54b591e..e961f9d51 100644 --- a/MediaBrowser.Api/Session/SessionsService.cs +++ b/MediaBrowser.Api/Session/SessionsService.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.Services; +using MediaBrowser.Controller; namespace MediaBrowser.Api.Session { @@ -293,15 +294,9 @@ namespace MediaBrowser.Api.Session private readonly IAuthenticationRepository _authRepo; private readonly IDeviceManager _deviceManager; private readonly ISessionContext _sessionContext; + private IServerApplicationHost _appHost; - /// - /// Initializes a new instance of the class. - /// - /// The session manager. - /// The user manager. - /// The authentication context. - /// The authentication repo. - public SessionsService(ISessionManager sessionManager, IUserManager userManager, IAuthorizationContext authContext, IAuthenticationRepository authRepo, IDeviceManager deviceManager, ISessionContext sessionContext) + public SessionsService(ISessionManager sessionManager, IServerApplicationHost appHost, IUserManager userManager, IAuthorizationContext authContext, IAuthenticationRepository authRepo, IDeviceManager deviceManager, ISessionContext sessionContext) { _sessionManager = sessionManager; _userManager = userManager; @@ -309,6 +304,7 @@ namespace MediaBrowser.Api.Session _authRepo = authRepo; _deviceManager = deviceManager; _sessionContext = sessionContext; + _appHost = appHost; } public void Delete(RevokeKey request) @@ -324,7 +320,10 @@ namespace MediaBrowser.Api.Session AppName = request.App, IsActive = true, AccessToken = Guid.NewGuid().ToString("N"), - DateCreated = DateTime.UtcNow + DateCreated = DateTime.UtcNow, + DeviceId = _appHost.SystemId, + DeviceName = _appHost.FriendlyName, + AppVersion = _appHost.ApplicationVersion.ToString() }, CancellationToken.None); } diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs index f74c01994..54faa1443 100644 --- a/MediaBrowser.Controller/Channels/Channel.cs +++ b/MediaBrowser.Controller/Channels/Channel.cs @@ -32,14 +32,6 @@ namespace MediaBrowser.Controller.Channels return base.IsVisible(user); } - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 16; - value /= 9; - - return value; - } - [IgnoreDataMember] public override bool SupportsInheritedParentImages { diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index 542fa5e08..40ab71be8 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -31,16 +31,9 @@ namespace MediaBrowser.Controller.Drawing /// /// The information. /// ImageSize. - ImageSize GetImageSize(ItemImageInfo info); + ImageSize GetImageSize(BaseItem item, ItemImageInfo info); - ImageSize GetImageSize(ItemImageInfo info, bool allowSlowMethods); - - /// - /// Gets the size of the image. - /// - /// The path. - /// ImageSize. - ImageSize GetImageSize(string path); + ImageSize GetImageSize(BaseItem item, ItemImageInfo info, bool allowSlowMethods, bool updateItem); /// /// Adds the parts. diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs index c0217330d..5ba6e036e 100644 --- a/MediaBrowser.Controller/Dto/IDtoService.cs +++ b/MediaBrowser.Controller/Dto/IDtoService.cs @@ -23,14 +23,14 @@ namespace MediaBrowser.Controller.Dto /// /// The dto. /// The item. - void AttachPrimaryImageAspectRatio(IItemDto dto, IHasMetadata item); + void AttachPrimaryImageAspectRatio(IItemDto dto, BaseItem item); /// /// Gets the primary image aspect ratio. /// /// The item. /// System.Nullable<System.Double>. - double? GetPrimaryImageAspectRatio(IHasMetadata item); + double? GetPrimaryImageAspectRatio(BaseItem item); /// /// Gets the base item dto. diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 051a2cbca..6898c0178 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1952,6 +1952,8 @@ namespace MediaBrowser.Controller.Entities { existingImage.Path = image.Path; existingImage.DateModified = image.DateModified; + existingImage.Width = image.Width; + existingImage.Height = image.Height; } else @@ -2268,6 +2270,11 @@ namespace MediaBrowser.Controller.Entities info1.DateModified = FileSystem.GetLastWriteTimeUtc(info1.Path); info2.DateModified = FileSystem.GetLastWriteTimeUtc(info2.Path); + info1.Width = 0; + info1.Height = 0; + info2.Width = 0; + info2.Height = 0; + UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); } diff --git a/MediaBrowser.Controller/Entities/ItemImageInfo.cs b/MediaBrowser.Controller/Entities/ItemImageInfo.cs index 6b2d2392d..bd0011c4b 100644 --- a/MediaBrowser.Controller/Entities/ItemImageInfo.cs +++ b/MediaBrowser.Controller/Entities/ItemImageInfo.cs @@ -24,6 +24,9 @@ namespace MediaBrowser.Controller.Entities /// The date modified. public DateTime DateModified { get; set; } + public int Width { get; set; } + public int Height { get; set; } + [IgnoreDataMember] public bool IsLocalFile { diff --git a/MediaBrowser.Controller/Entities/PhotoAlbum.cs b/MediaBrowser.Controller/Entities/PhotoAlbum.cs index 52d743e36..af9d8c801 100644 --- a/MediaBrowser.Controller/Entities/PhotoAlbum.cs +++ b/MediaBrowser.Controller/Entities/PhotoAlbum.cs @@ -30,10 +30,5 @@ namespace MediaBrowser.Controller.Entities return false; } } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - return 1; - } } } diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 8203e5304..265e35341 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -78,14 +78,6 @@ namespace MediaBrowser.Controller.Entities } } - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 16; - value /= 9; - - return value; - } - public override string CreatePresentationUniqueKey() { if (!string.IsNullOrWhiteSpace(PrimaryVersionId)) diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 7fceeb780..37e0d5661 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -128,6 +128,8 @@ namespace MediaBrowser.Controller.Library /// void QueueLibraryScan(); + void UpdateImages(BaseItem item); + /// /// Gets the default view. /// diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 3d05d2fca..4cb3e2bb6 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -48,6 +48,8 @@ namespace MediaBrowser.Controller.Persistence /// The cancellation token. void SaveItems(List items, CancellationToken cancellationToken); + void SaveImages(BaseItem item); + /// /// Retrieves the item. /// -- cgit v1.2.3 From 6158381d12dc5198eef7f590185675682e301e72 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 22 Oct 2017 02:31:41 -0400 Subject: update devices --- Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs') diff --git a/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs b/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs index b11a5d65b..d7817b17a 100644 --- a/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs +++ b/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs @@ -60,7 +60,7 @@ namespace Emby.Server.Implementations.Devices RunDefaultInitialization(connection); string[] queries = { - "create table if not exists Devices (Id TEXT PRIMARY KEY, Name TEXT NOT NULL, ReportedName TEXT NOT NULL, CustomName TEXT, CameraUploadPath TEXT, LastUserName TEXT NOT NULL, AppName TEXT NOT NULL, AppVersion TEXT NOT NULL, LastUserId TEXT NOT NULL, DateLastModified DATETIME NOT NULL, Capabilities TEXT NOT NULL)", + "create table if not exists Devices (Id TEXT PRIMARY KEY, Name TEXT NOT NULL, ReportedName TEXT NOT NULL, CustomName TEXT, CameraUploadPath TEXT, LastUserName TEXT, AppName TEXT NOT NULL, AppVersion TEXT NOT NULL, LastUserId TEXT, DateLastModified DATETIME NOT NULL, Capabilities TEXT NOT NULL)", "create index if not exists idx_id on Devices(Id)" }; -- cgit v1.2.3