diff options
Diffstat (limited to 'MediaBrowser.Server.Implementations')
5 files changed, 91 insertions, 108 deletions
diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs index 415205cb1..cb3621fd1 100644 --- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -26,6 +26,7 @@ namespace MediaBrowser.Server.Implementations.Configuration { UpdateItemsByNamePath(); UpdateTranscodingTempPath(); + UpdateMetadataPath(); } /// <summary> @@ -77,6 +78,16 @@ namespace MediaBrowser.Server.Implementations.Configuration } /// <summary> + /// Updates the metadata path. + /// </summary> + private void UpdateMetadataPath() + { + ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = string.IsNullOrEmpty(Configuration.MetadataPath) ? + null : + Configuration.MetadataPath; + } + + /// <summary> /// Updates the transcoding temporary path. /// </summary> private void UpdateTranscodingTempPath() @@ -98,6 +109,7 @@ namespace MediaBrowser.Server.Implementations.Configuration ValidateItemByNamePath(newConfig); ValidateTranscodingTempPath(newConfig); ValidatePathSubstitutions(newConfig); + ValidateMetadataPath(newConfig); base.ReplaceConfiguration(newConfiguration); } @@ -166,5 +178,25 @@ namespace MediaBrowser.Server.Implementations.Configuration } } } + + /// <summary> + /// Validates the metadata path. + /// </summary> + /// <param name="newConfig">The new configuration.</param> + /// <exception cref="System.IO.DirectoryNotFoundException"></exception> + private void ValidateMetadataPath(ServerConfiguration newConfig) + { + var newPath = newConfig.MetadataPath; + + if (!string.IsNullOrWhiteSpace(newPath) + && !string.Equals(Configuration.MetadataPath ?? string.Empty, newPath)) + { + // Validate + if (!Directory.Exists(newPath)) + { + throw new DirectoryNotFoundException(string.Format("{0} does not exist.", newPath)); + } + } + } } } diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index 06028d37e..2ee843f09 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -260,6 +260,8 @@ namespace MediaBrowser.Server.Implementations.Library public event EventHandler<GenericEventArgs<User>> UserCreated; + private readonly SemaphoreSlim _userListLock = new SemaphoreSlim(1, 1); + /// <summary> /// Creates the user. /// </summary> @@ -279,19 +281,28 @@ namespace MediaBrowser.Server.Implementations.Library throw new ArgumentException(string.Format("A user with the name '{0}' already exists.", name)); } - var user = InstantiateNewUser(name); + await _userListLock.WaitAsync(CancellationToken.None).ConfigureAwait(false); - var list = Users.ToList(); - list.Add(user); - Users = list; + try + { + var user = InstantiateNewUser(name); - user.DateLastSaved = DateTime.UtcNow; + var list = Users.ToList(); + list.Add(user); + Users = list; - await UserRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false); + user.DateLastSaved = DateTime.UtcNow; - EventHelper.QueueEventIfNotNull(UserCreated, this, new GenericEventArgs<User> { Argument = user }, _logger); + await UserRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false); - return user; + EventHelper.QueueEventIfNotNull(UserCreated, this, new GenericEventArgs<User> { Argument = user }, _logger); + + return user; + } + finally + { + _userListLock.Release(); + } } /// <summary> @@ -325,23 +336,32 @@ namespace MediaBrowser.Server.Implementations.Library throw new ArgumentException(string.Format("The user '{0}' cannot be deleted because there must be at least one admin user in the system.", user.Name)); } - await UserRepository.DeleteUser(user, CancellationToken.None).ConfigureAwait(false); - - var path = user.ConfigurationFilePath; + await _userListLock.WaitAsync(CancellationToken.None).ConfigureAwait(false); try { - File.Delete(path); + await UserRepository.DeleteUser(user, CancellationToken.None).ConfigureAwait(false); + + var path = user.ConfigurationFilePath; + + try + { + File.Delete(path); + } + catch (IOException ex) + { + _logger.ErrorException("Error deleting file {0}", ex, path); + } + + // Force this to be lazy loaded again + Users = await LoadUsers().ConfigureAwait(false); + + OnUserDeleted(user); } - catch (IOException ex) + finally { - _logger.ErrorException("Error deleting file {0}", ex, path); + _userListLock.Release(); } - - // Force this to be lazy loaded again - Users = await LoadUsers().ConfigureAwait(false); - - OnUserDeleted(user); } /// <summary> diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 6a4c3930a..db8786d62 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1498,8 +1498,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv { var programs = _programs.ToList(); - var startDate = programs.Select(i => i.Value.StartDate).Min(); - var endDate = programs.Select(i => i.Value.StartDate).Max(); + var startDate = _programs.Count == 0 ? DateTime.MinValue : + programs.Select(i => i.Value.StartDate).Min(); + + var endDate = programs.Count == 0 ? DateTime.MinValue : + programs.Select(i => i.Value.StartDate).Max(); return new GuideInfo { diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs b/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs index fddba7662..c646d80bc 100644 --- a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs +++ b/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs @@ -175,6 +175,10 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder string probeSizeArgument, CancellationToken cancellationToken) { + var args = extractChapters + ? "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_chapters -show_format" + : "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_format"; + var process = new Process { StartInfo = new ProcessStartInfo @@ -186,8 +190,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder RedirectStandardOutput = true, RedirectStandardError = true, FileName = FFProbePath, - Arguments = string.Format( - "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_format", + Arguments = string.Format(args, probeSizeArgument, inputPath).Trim(), WindowStyle = ProcessWindowStyle.Hidden, @@ -204,7 +207,6 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder await _ffProbeResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); InternalMediaInfoResult result; - string standardError = null; try { @@ -221,24 +223,9 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder try { - Task<string> standardErrorReadTask = null; - - // MUST read both stdout and stderr asynchronously or a deadlock may occurr - if (extractChapters) - { - standardErrorReadTask = process.StandardError.ReadToEndAsync(); - } - else - { - process.BeginErrorReadLine(); - } + process.BeginErrorReadLine(); result = _jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream); - - if (extractChapters) - { - standardError = await standardErrorReadTask.ConfigureAwait(false); - } } catch { @@ -282,11 +269,6 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder } } - if (extractChapters && !string.IsNullOrEmpty(standardError)) - { - AddChapters(result, standardError); - } - return result; } @@ -296,66 +278,6 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); /// <summary> - /// Adds the chapters. - /// </summary> - /// <param name="result">The result.</param> - /// <param name="standardError">The standard error.</param> - private void AddChapters(InternalMediaInfoResult result, string standardError) - { - var lines = standardError.Split('\n').Select(l => l.TrimStart()); - - var chapters = new List<ChapterInfo>(); - - ChapterInfo lastChapter = null; - - foreach (var line in lines) - { - if (line.StartsWith("Chapter", StringComparison.OrdinalIgnoreCase)) - { - // Example: - // Chapter #0.2: start 400.534, end 4565.435 - const string srch = "start "; - var start = line.IndexOf(srch, StringComparison.OrdinalIgnoreCase); - - if (start == -1) - { - continue; - } - - var subString = line.Substring(start + srch.Length); - subString = subString.Substring(0, subString.IndexOf(',')); - - double seconds; - - if (double.TryParse(subString, NumberStyles.Any, UsCulture, out seconds)) - { - lastChapter = new ChapterInfo - { - StartPositionTicks = TimeSpan.FromSeconds(seconds).Ticks - }; - - chapters.Add(lastChapter); - } - } - - else if (line.StartsWith("title", StringComparison.OrdinalIgnoreCase)) - { - if (lastChapter != null && string.IsNullOrEmpty(lastChapter.Name)) - { - var index = line.IndexOf(':'); - - if (index != -1) - { - lastChapter.Name = line.Substring(index + 1).Trim().TrimEnd('\r'); - } - } - } - } - - result.Chapters = chapters; - } - - /// <summary> /// Processes the exited. /// </summary> /// <param name="sender">The sender.</param> diff --git a/MediaBrowser.Server.Implementations/ServerApplicationPaths.cs b/MediaBrowser.Server.Implementations/ServerApplicationPaths.cs index c36c49df0..df2a5f83c 100644 --- a/MediaBrowser.Server.Implementations/ServerApplicationPaths.cs +++ b/MediaBrowser.Server.Implementations/ServerApplicationPaths.cs @@ -1,6 +1,6 @@ -using System; -using MediaBrowser.Common.Implementations; +using MediaBrowser.Common.Implementations; using MediaBrowser.Controller; +using System; using System.IO; namespace MediaBrowser.Server.Implementations @@ -239,14 +239,20 @@ namespace MediaBrowser.Server.Implementations } } + private string _internalMetadataPath; public string InternalMetadataPath { get { - return Path.Combine(DataPath, "metadata"); + return _internalMetadataPath ?? (_internalMetadataPath = Path.Combine(DataPath, "metadata")); + } + set + { + _internalMetadataPath = value; } } + public string GetInternalMetadataPath(Guid id) { var idString = id.ToString("N"); |
