diff --git a/MediaBrowser.Dlna/DlnaManager.cs b/MediaBrowser.Dlna/DlnaManager.cs index 2a688fa54d..63a36744f1 100644 --- a/MediaBrowser.Dlna/DlnaManager.cs +++ b/MediaBrowser.Dlna/DlnaManager.cs @@ -210,6 +210,10 @@ namespace MediaBrowser.Dlna throw new ArgumentNullException("headers"); } + //_logger.Debug("GetProfile. Headers: " + _jsonSerializer.SerializeToString(headers)); + // Convert to case insensitive + headers = new Dictionary(headers, StringComparer.OrdinalIgnoreCase); + var profile = GetProfiles().FirstOrDefault(i => i.Identification != null && IsMatch(headers, i.Identification)); if (profile != null) @@ -221,7 +225,7 @@ namespace MediaBrowser.Dlna string userAgent = null; headers.TryGetValue("User-Agent", out userAgent); - var msg = "No matching device profile found. The default will be used. "; + var msg = "No matching device profile via headers found. The default will be used. "; if (!string.IsNullOrEmpty(userAgent)) { msg += "User-agent: " + userAgent + ". "; @@ -249,7 +253,9 @@ namespace MediaBrowser.Dlna case HeaderMatchType.Equals: return string.Equals(value, header.Value, StringComparison.OrdinalIgnoreCase); case HeaderMatchType.Substring: - return value.IndexOf(header.Value, StringComparison.OrdinalIgnoreCase) != -1; + var isMatch = value.IndexOf(header.Value, StringComparison.OrdinalIgnoreCase) != -1; + //_logger.Debug("IsMatch-Substring value: {0} testValue: {1} isMatch: {2}", value, header.Value, isMatch); + return isMatch; case HeaderMatchType.Regex: // Reports of IgnoreCase not working on linux so try it a couple different ways. return Regex.IsMatch(value, header.Value, RegexOptions.IgnoreCase) || Regex.IsMatch(value.ToUpper(), header.Value.ToUpper(), RegexOptions.IgnoreCase); diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs index 6c3fe82b72..82fc5e4665 100644 --- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs +++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs @@ -177,7 +177,7 @@ namespace MediaBrowser.Dlna.Ssdp { if (i > 0) { - await Task.Delay(500).ConfigureAwait(false); + await Task.Delay(200).ConfigureAwait(false); } var dgram = new Datagram(endpoint, localAddress, _logger, msg, isBroadcast, enableDebugLogging); diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 8ce1665581..b4ff79567d 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -116,7 +116,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV var commandLineArgs = "-fflags +genpts -i \"{0}\" -sn {2} -map_metadata -1 -threads 0 {3} -y \"{1}\""; - //if (mediaSource.ReadAtNativeFramerate) + if (mediaSource.ReadAtNativeFramerate) { commandLineArgs = "-re " + commandLineArgs; } diff --git a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs b/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs index f883e6dbce..7302431e17 100644 --- a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs +++ b/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs @@ -13,20 +13,11 @@ using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Notifications { - public class SqliteNotificationsRepository : INotificationsRepository + public class SqliteNotificationsRepository : BaseSqliteRepository, INotificationsRepository { private IDbConnection _connection; - private readonly ILogger _logger; private readonly IServerApplicationPaths _appPaths; - private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1); - - public SqliteNotificationsRepository(ILogManager logManager, IServerApplicationPaths appPaths) - { - _appPaths = appPaths; - _logger = logManager.GetLogger(GetType().Name); - } - public event EventHandler NotificationAdded; public event EventHandler NotificationsMarkedRead; public event EventHandler NotificationUpdated; @@ -35,11 +26,17 @@ namespace MediaBrowser.Server.Implementations.Notifications private IDbCommand _markReadCommand; private IDbCommand _markAllReadCommand; + public SqliteNotificationsRepository(ILogManager logManager, IServerApplicationPaths appPaths) + : base(logManager) + { + _appPaths = appPaths; + } + public async Task Initialize() { var dbFile = Path.Combine(_appPaths.DataPath, "notifications.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false); + _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); string[] queries = { @@ -52,7 +49,7 @@ namespace MediaBrowser.Server.Implementations.Notifications "pragma shrink_memory" }; - _connection.RunQueries(queries, _logger); + _connection.RunQueries(queries, Logger); PrepareStatements(); } @@ -251,7 +248,7 @@ namespace MediaBrowser.Server.Implementations.Notifications } catch (Exception ex) { - _logger.ErrorException("Error in NotificationAdded event handler", ex); + Logger.ErrorException("Error in NotificationAdded event handler", ex); } } } @@ -275,7 +272,7 @@ namespace MediaBrowser.Server.Implementations.Notifications cancellationToken.ThrowIfCancellationRequested(); - await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); IDbTransaction transaction = null; @@ -311,7 +308,7 @@ namespace MediaBrowser.Server.Implementations.Notifications } catch (Exception e) { - _logger.ErrorException("Failed to save notification:", e); + Logger.ErrorException("Failed to save notification:", e); if (transaction != null) { @@ -327,7 +324,7 @@ namespace MediaBrowser.Server.Implementations.Notifications transaction.Dispose(); } - _writeLock.Release(); + WriteLock.Release(); } } @@ -359,7 +356,7 @@ namespace MediaBrowser.Server.Implementations.Notifications } catch (Exception ex) { - _logger.ErrorException("Error in NotificationsMarkedRead event handler", ex); + Logger.ErrorException("Error in NotificationsMarkedRead event handler", ex); } } } @@ -368,7 +365,7 @@ namespace MediaBrowser.Server.Implementations.Notifications { cancellationToken.ThrowIfCancellationRequested(); - await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); IDbTransaction transaction = null; @@ -396,7 +393,7 @@ namespace MediaBrowser.Server.Implementations.Notifications } catch (Exception e) { - _logger.ErrorException("Failed to save notification:", e); + Logger.ErrorException("Failed to save notification:", e); if (transaction != null) { @@ -412,7 +409,7 @@ namespace MediaBrowser.Server.Implementations.Notifications transaction.Dispose(); } - _writeLock.Release(); + WriteLock.Release(); } } @@ -420,7 +417,7 @@ namespace MediaBrowser.Server.Implementations.Notifications { cancellationToken.ThrowIfCancellationRequested(); - await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); IDbTransaction transaction = null; @@ -455,7 +452,7 @@ namespace MediaBrowser.Server.Implementations.Notifications } catch (Exception e) { - _logger.ErrorException("Failed to save notification:", e); + Logger.ErrorException("Failed to save notification:", e); if (transaction != null) { @@ -471,7 +468,21 @@ namespace MediaBrowser.Server.Implementations.Notifications transaction.Dispose(); } - _writeLock.Release(); + WriteLock.Release(); + } + } + + protected override void CloseConnection() + { + if (_connection != null) + { + if (_connection.IsOpen()) + { + _connection.Close(); + } + + _connection.Dispose(); + _connection = null; } } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index ed1aeac9f0..d7bf294e34 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; - private const int LatestSchemaVersion = 44; + private const int LatestSchemaVersion = 45; /// /// Initializes a new instance of the class. @@ -221,6 +221,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(Logger, "TypedBaseItems", "InheritedParentalRatingValue", "INT"); _connection.AddColumn(Logger, "TypedBaseItems", "UnratedType", "Text"); _connection.AddColumn(Logger, "TypedBaseItems", "TopParentId", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "IsItemByName", "BIT"); PrepareStatements(); @@ -445,7 +446,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "Tags", "IsFolder", "UnratedType", - "TopParentId" + "TopParentId", + "IsItemByName" }; _saveItemCommand = _connection.CreateCommand(); _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -730,6 +732,15 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = null; } + var isByName = false; + var byName = item as IItemByName; + if (byName != null) + { + var dualAccess = item as IHasDualAccess; + isByName = dualAccess == null || dualAccess.IsAccessedByName; + } + _saveItemCommand.GetParameter(index++).Value = isByName; + _saveItemCommand.Transaction = transaction; _saveItemCommand.ExecuteNonQuery(); @@ -1905,14 +1916,16 @@ namespace MediaBrowser.Server.Implementations.Persistence if (query.TopParentIds.Length == 1) { - whereClauses.Add("(TopParentId=@TopParentId)"); + whereClauses.Add("(TopParentId=@TopParentId or IsItemByName=@IsItemByName)"); cmd.Parameters.Add(cmd, "@TopParentId", DbType.String).Value = query.TopParentIds[0]; + cmd.Parameters.Add(cmd, "@IsItemByName", DbType.Boolean).Value = true; } if (query.TopParentIds.Length > 1) { var val = string.Join(",", query.TopParentIds.Select(i => "'" + i + "'").ToArray()); - whereClauses.Add("(TopParentId in (" + val + "))"); + whereClauses.Add("(IsItemByName=@IsItemByName or TopParentId in (" + val + "))"); + cmd.Parameters.Add(cmd, "@IsItemByName", DbType.Boolean).Value = true; } if (query.AncestorIds.Length == 1) diff --git a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs index b36db51b32..b932f0cac4 100644 --- a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs +++ b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs @@ -13,19 +13,17 @@ using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Security { - public class AuthenticationRepository : IAuthenticationRepository + public class AuthenticationRepository : BaseSqliteRepository, IAuthenticationRepository { private IDbConnection _connection; - private readonly ILogger _logger; - private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1); private readonly IServerApplicationPaths _appPaths; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private IDbCommand _saveInfoCommand; - public AuthenticationRepository(ILogger logger, IServerApplicationPaths appPaths) + public AuthenticationRepository(ILogManager logManager, IServerApplicationPaths appPaths) + : base(logManager) { - _logger = logger; _appPaths = appPaths; } @@ -33,7 +31,7 @@ namespace MediaBrowser.Server.Implementations.Security { var dbFile = Path.Combine(_appPaths.DataPath, "authentication.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false); + _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); string[] queries = { @@ -46,9 +44,9 @@ namespace MediaBrowser.Server.Implementations.Security "pragma shrink_memory" }; - _connection.RunQueries(queries, _logger); + _connection.RunQueries(queries, Logger); - _connection.AddColumn(_logger, "AccessTokens", "AppVersion", "TEXT"); + _connection.AddColumn(Logger, "AccessTokens", "AppVersion", "TEXT"); PrepareStatements(); } @@ -86,7 +84,7 @@ namespace MediaBrowser.Server.Implementations.Security cancellationToken.ThrowIfCancellationRequested(); - await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); IDbTransaction transaction = null; @@ -124,7 +122,7 @@ namespace MediaBrowser.Server.Implementations.Security } catch (Exception e) { - _logger.ErrorException("Failed to save record:", e); + Logger.ErrorException("Failed to save record:", e); if (transaction != null) { @@ -140,7 +138,7 @@ namespace MediaBrowser.Server.Implementations.Security transaction.Dispose(); } - _writeLock.Release(); + WriteLock.Release(); } } @@ -305,7 +303,7 @@ namespace MediaBrowser.Server.Implementations.Security { info.DeviceName = reader.GetString(5); } - + if (!reader.IsDBNull(6)) { info.UserId = reader.GetString(6); @@ -318,49 +316,21 @@ namespace MediaBrowser.Server.Implementations.Security { info.DateRevoked = reader.GetDateTime(9).ToUniversalTime(); } - - return info; - } - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); + return info; } - private readonly object _disposeLock = new object(); - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - protected virtual void Dispose(bool dispose) + protected override void CloseConnection() { - if (dispose) + if (_connection != null) { - try + if (_connection.IsOpen()) { - lock (_disposeLock) - { - if (_connection != null) - { - if (_connection.IsOpen()) - { - _connection.Close(); - } - - _connection.Dispose(); - _connection = null; - } - } - } - catch (Exception ex) - { - _logger.ErrorException("Error disposing database", ex); + _connection.Close(); } + + _connection.Dispose(); + _connection = null; } } } diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 735748e08b..e61a646467 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -683,7 +683,7 @@ namespace MediaBrowser.Server.Startup.Common private async Task GetAuthenticationRepository() { - var repo = new AuthenticationRepository(LogManager.GetLogger("AuthenticationRepository"), ServerConfigurationManager.ApplicationPaths); + var repo = new AuthenticationRepository(LogManager, ServerConfigurationManager.ApplicationPaths); await repo.Initialize().ConfigureAwait(false);