Merge pull request #2447 from Bond-009/minor
Add analyzers to MediaBrowser.Providers and minor improvements
This commit is contained in:
commit
10275a1f32
|
@ -1,6 +1,5 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1402
|
#pragma warning disable SA1402
|
||||||
#pragma warning disable SA1600
|
|
||||||
#pragma warning disable SA1649
|
#pragma warning disable SA1649
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
|
|
@ -844,10 +844,15 @@ namespace Emby.Server.Implementations
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IDeviceDiscovery>(new DeviceDiscovery(ServerConfigurationManager));
|
serviceCollection.AddSingleton<IDeviceDiscovery>(new DeviceDiscovery(ServerConfigurationManager));
|
||||||
|
|
||||||
ChapterManager = new ChapterManager(LibraryManager, LoggerFactory, ServerConfigurationManager, ItemRepository);
|
ChapterManager = new ChapterManager(ItemRepository);
|
||||||
serviceCollection.AddSingleton(ChapterManager);
|
serviceCollection.AddSingleton(ChapterManager);
|
||||||
|
|
||||||
EncodingManager = new MediaEncoder.EncodingManager(FileSystemManager, LoggerFactory, MediaEncoder, ChapterManager, LibraryManager);
|
EncodingManager = new MediaEncoder.EncodingManager(
|
||||||
|
LoggerFactory.CreateLogger<MediaEncoder.EncodingManager>(),
|
||||||
|
FileSystemManager,
|
||||||
|
MediaEncoder,
|
||||||
|
ChapterManager,
|
||||||
|
LibraryManager);
|
||||||
serviceCollection.AddSingleton(EncodingManager);
|
serviceCollection.AddSingleton(EncodingManager);
|
||||||
|
|
||||||
var activityLogRepo = GetActivityLogRepository();
|
var activityLogRepo = GetActivityLogRepository();
|
||||||
|
|
|
@ -2006,7 +2006,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves the chapters.
|
/// Saves the chapters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SaveChapters(Guid id, List<ChapterInfo> chapters)
|
public void SaveChapters(Guid id, IReadOnlyList<ChapterInfo> chapters)
|
||||||
{
|
{
|
||||||
CheckDisposed();
|
CheckDisposed();
|
||||||
|
|
||||||
|
@ -2035,22 +2035,24 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InsertChapters(byte[] idBlob, List<ChapterInfo> chapters, IDatabaseConnection db)
|
private void InsertChapters(byte[] idBlob, IReadOnlyList<ChapterInfo> chapters, IDatabaseConnection db)
|
||||||
{
|
{
|
||||||
var startIndex = 0;
|
var startIndex = 0;
|
||||||
var limit = 100;
|
var limit = 100;
|
||||||
var chapterIndex = 0;
|
var chapterIndex = 0;
|
||||||
|
|
||||||
|
const string StartInsertText = "insert into " + ChaptersTableName + " (ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath, ImageDateModified) values ";
|
||||||
|
var insertText = new StringBuilder(StartInsertText, 256);
|
||||||
|
|
||||||
while (startIndex < chapters.Count)
|
while (startIndex < chapters.Count)
|
||||||
{
|
{
|
||||||
var insertText = new StringBuilder("insert into " + ChaptersTableName + " (ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath, ImageDateModified) values ");
|
|
||||||
|
|
||||||
var endIndex = Math.Min(chapters.Count, startIndex + limit);
|
var endIndex = Math.Min(chapters.Count, startIndex + limit);
|
||||||
|
|
||||||
for (var i = startIndex; i < endIndex; i++)
|
for (var i = startIndex; i < endIndex; i++)
|
||||||
{
|
{
|
||||||
insertText.AppendFormat("(@ItemId, @ChapterIndex{0}, @StartPositionTicks{0}, @Name{0}, @ImagePath{0}, @ImageDateModified{0}),", i.ToString(CultureInfo.InvariantCulture));
|
insertText.AppendFormat("(@ItemId, @ChapterIndex{0}, @StartPositionTicks{0}, @Name{0}, @ImagePath{0}, @ImageDateModified{0}),", i.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
insertText.Length -= 1; // Remove last ,
|
insertText.Length -= 1; // Remove last ,
|
||||||
|
|
||||||
using (var statement = PrepareStatement(db, insertText.ToString()))
|
using (var statement = PrepareStatement(db, insertText.ToString()))
|
||||||
|
@ -2077,6 +2079,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
startIndex += limit;
|
startIndex += limit;
|
||||||
|
insertText.Length = StartInsertText.Length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Controller.Plugins;
|
using MediaBrowser.Controller.Plugins;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -26,14 +26,20 @@ namespace Emby.Server.Implementations.MediaEncoder
|
||||||
private readonly IChapterManager _chapterManager;
|
private readonly IChapterManager _chapterManager;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The first chapter ticks.
|
||||||
|
/// </summary>
|
||||||
|
private static readonly long _firstChapterTicks = TimeSpan.FromSeconds(15).Ticks;
|
||||||
|
|
||||||
public EncodingManager(
|
public EncodingManager(
|
||||||
|
ILogger<EncodingManager> logger,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILoggerFactory loggerFactory,
|
|
||||||
IMediaEncoder encoder,
|
IMediaEncoder encoder,
|
||||||
IChapterManager chapterManager, ILibraryManager libraryManager)
|
IChapterManager chapterManager,
|
||||||
|
ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
|
_logger = logger;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_logger = loggerFactory.CreateLogger(nameof(EncodingManager));
|
|
||||||
_encoder = encoder;
|
_encoder = encoder;
|
||||||
_chapterManager = chapterManager;
|
_chapterManager = chapterManager;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
@ -97,12 +103,7 @@ namespace Emby.Server.Implementations.MediaEncoder
|
||||||
return video.DefaultVideoStreamIndex.HasValue;
|
return video.DefaultVideoStreamIndex.HasValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public async Task<bool> RefreshChapterImages(Video video, IDirectoryService directoryService, IReadOnlyList<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken)
|
||||||
/// The first chapter ticks
|
|
||||||
/// </summary>
|
|
||||||
private static readonly long FirstChapterTicks = TimeSpan.FromSeconds(15).Ticks;
|
|
||||||
|
|
||||||
public async Task<bool> RefreshChapterImages(Video video, IDirectoryService directoryService, List<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
if (!IsEligibleForChapterImageExtraction(video))
|
if (!IsEligibleForChapterImageExtraction(video))
|
||||||
{
|
{
|
||||||
|
@ -135,7 +136,7 @@ namespace Emby.Server.Implementations.MediaEncoder
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Add some time for the first chapter to make sure we don't end up with a black image
|
// Add some time for the first chapter to make sure we don't end up with a black image
|
||||||
var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(FirstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks);
|
var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(_firstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks);
|
||||||
|
|
||||||
var protocol = MediaProtocol.File;
|
var protocol = MediaProtocol.File;
|
||||||
|
|
||||||
|
@ -152,9 +153,9 @@ namespace Emby.Server.Implementations.MediaEncoder
|
||||||
{
|
{
|
||||||
_fileSystem.DeleteFile(tempFile);
|
_fileSystem.DeleteFile(tempFile);
|
||||||
}
|
}
|
||||||
catch
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
|
_logger.LogError(ex, "Error deleting temporary chapter image encoding file {Path}", tempFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
chapter.ImagePath = path;
|
chapter.ImagePath = path;
|
||||||
|
@ -184,7 +185,7 @@ namespace Emby.Server.Implementations.MediaEncoder
|
||||||
|
|
||||||
if (saveChapters && changesMade)
|
if (saveChapters && changesMade)
|
||||||
{
|
{
|
||||||
_chapterManager.SaveChapters(video.Id.ToString(), chapters);
|
_chapterManager.SaveChapters(video.Id, chapters);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteDeadImages(currentImages, chapters);
|
DeleteDeadImages(currentImages, chapters);
|
||||||
|
@ -199,22 +200,21 @@ namespace Emby.Server.Implementations.MediaEncoder
|
||||||
return Path.Combine(GetChapterImagesPath(video), filename);
|
return Path.Combine(GetChapterImagesPath(video), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<string> GetSavedChapterImages(Video video, IDirectoryService directoryService)
|
private static IReadOnlyList<string> GetSavedChapterImages(Video video, IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
var path = GetChapterImagesPath(video);
|
var path = GetChapterImagesPath(video);
|
||||||
if (!Directory.Exists(path))
|
if (!Directory.Exists(path))
|
||||||
{
|
{
|
||||||
return new List<string>();
|
return Array.Empty<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return directoryService.GetFilePaths(path)
|
return directoryService.GetFilePaths(path);
|
||||||
.ToList();
|
|
||||||
}
|
}
|
||||||
catch (IOException)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
return new List<string>();
|
return Array.Empty<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ namespace Emby.Server.Implementations.MediaEncoder
|
||||||
|
|
||||||
foreach (var image in deadImages)
|
foreach (var image in deadImages)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("Deleting dead chapter image {path}", image);
|
_logger.LogDebug("Deleting dead chapter image {Path}", image);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -235,7 +235,7 @@ namespace Emby.Server.Implementations.MediaEncoder
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Error deleting {path}.", image);
|
_logger.LogError(ex, "Error deleting {Path}.", image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Chapters
|
namespace MediaBrowser.Controller.Chapters
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interface IChapterManager
|
/// Interface IChapterManager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IChapterManager
|
public interface IChapterManager
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves the chapters.
|
/// Saves the chapters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void SaveChapters(string itemId, List<ChapterInfo> chapters);
|
void SaveChapters(Guid itemId, IReadOnlyList<ChapterInfo> chapters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
@ -28,7 +30,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Folder : BaseItem
|
public class Folder : BaseItem
|
||||||
{
|
{
|
||||||
public static IUserManager UserManager { get; set; }
|
|
||||||
public static IUserViewManager UserViewManager { get; set; }
|
public static IUserViewManager UserViewManager { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -620,7 +621,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
EnableImages = false
|
EnableImages = false
|
||||||
}
|
}
|
||||||
|
|
||||||
}).TotalRecordCount;
|
}).TotalRecordCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1713,7 +1713,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
EnableImages = false
|
EnableImages = false
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
double unplayedCount = unplayedQueryResult.TotalRecordCount;
|
double unplayedCount = unplayedQueryResult.TotalRecordCount;
|
||||||
|
|
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Marker interface
|
/// Marker interface.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IItemByName
|
public interface IItemByName
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -12,6 +14,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Refreshes the chapter images.
|
/// Refreshes the chapter images.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task<bool> RefreshChapterImages(Video video, IDirectoryService directoryService, List<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken);
|
Task<bool> RefreshChapterImages(Video video, IDirectoryService directoryService, IReadOnlyList<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ namespace MediaBrowser.Controller.Persistence
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves the chapters.
|
/// Saves the chapters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void SaveChapters(Guid id, List<ChapterInfo> chapters);
|
void SaveChapters(Guid id, IReadOnlyList<ChapterInfo> chapters);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the media streams.
|
/// Gets the media streams.
|
||||||
|
|
|
@ -66,12 +66,10 @@ namespace MediaBrowser.Controller.Providers
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> GetFilePaths(string path)
|
public IReadOnlyList<string> GetFilePaths(string path)
|
||||||
{
|
=> GetFilePaths(path, false);
|
||||||
return GetFilePaths(path, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<string> GetFilePaths(string path, bool clearCache)
|
public IReadOnlyList<string> GetFilePaths(string path, bool clearCache)
|
||||||
{
|
{
|
||||||
if (clearCache || !_filePathCache.TryGetValue(path, out List<string> result))
|
if (clearCache || !_filePathCache.TryGetValue(path, out List<string> result))
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,8 +11,8 @@ namespace MediaBrowser.Controller.Providers
|
||||||
|
|
||||||
FileSystemMetadata GetFile(string path);
|
FileSystemMetadata GetFile(string path);
|
||||||
|
|
||||||
List<string> GetFilePaths(string path);
|
IReadOnlyList<string> GetFilePaths(string path);
|
||||||
|
|
||||||
List<string> GetFilePaths(string path, bool clearCache);
|
IReadOnlyList<string> GetFilePaths(string path, bool clearCache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -429,7 +429,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ProbeResultNormalizer(_logger, _fileSystem, _localization).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol);
|
return new ProbeResultNormalizer(_logger, _localization).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
@ -19,13 +18,11 @@ namespace MediaBrowser.MediaEncoding.Probing
|
||||||
{
|
{
|
||||||
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IFileSystem _fileSystem;
|
|
||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
|
|
||||||
public ProbeResultNormalizer(ILogger logger, IFileSystem fileSystem, ILocalizationManager localization)
|
public ProbeResultNormalizer(ILogger logger, ILocalizationManager localization)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_fileSystem = fileSystem;
|
|
||||||
_localization = localization;
|
_localization = localization;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +37,7 @@ namespace MediaBrowser.MediaEncoding.Probing
|
||||||
FFProbeHelpers.NormalizeFFProbeResult(data);
|
FFProbeHelpers.NormalizeFFProbeResult(data);
|
||||||
SetSize(data, info);
|
SetSize(data, info);
|
||||||
|
|
||||||
var internalStreams = data.Streams ?? new MediaStreamInfo[] { };
|
var internalStreams = data.Streams ?? Array.Empty<MediaStreamInfo>();
|
||||||
|
|
||||||
info.MediaStreams = internalStreams.Select(s => GetMediaStream(isAudio, s, data.Format))
|
info.MediaStreams = internalStreams.Select(s => GetMediaStream(isAudio, s, data.Format))
|
||||||
.Where(i => i != null)
|
.Where(i => i != null)
|
||||||
|
|
|
@ -1,36 +1,26 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using MediaBrowser.Controller.Chapters;
|
using MediaBrowser.Controller.Chapters;
|
||||||
using MediaBrowser.Controller.Configuration;
|
|
||||||
using MediaBrowser.Controller.Library;
|
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Providers.Chapters
|
namespace MediaBrowser.Providers.Chapters
|
||||||
{
|
{
|
||||||
public class ChapterManager : IChapterManager
|
public class ChapterManager : IChapterManager
|
||||||
{
|
{
|
||||||
private readonly ILibraryManager _libraryManager;
|
|
||||||
private readonly ILogger _logger;
|
|
||||||
private readonly IServerConfigurationManager _config;
|
|
||||||
private readonly IItemRepository _itemRepo;
|
private readonly IItemRepository _itemRepo;
|
||||||
|
|
||||||
public ChapterManager(
|
public ChapterManager(IItemRepository itemRepo)
|
||||||
ILibraryManager libraryManager,
|
|
||||||
ILoggerFactory loggerFactory,
|
|
||||||
IServerConfigurationManager config,
|
|
||||||
IItemRepository itemRepo)
|
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
|
||||||
_logger = loggerFactory.CreateLogger(nameof(ChapterManager));
|
|
||||||
_config = config;
|
|
||||||
_itemRepo = itemRepo;
|
_itemRepo = itemRepo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveChapters(string itemId, List<ChapterInfo> chapters)
|
/// <inheritdoc />
|
||||||
|
public void SaveChapters(Guid itemId, IReadOnlyList<ChapterInfo> chapters)
|
||||||
{
|
{
|
||||||
_itemRepo.SaveChapters(new Guid(itemId), chapters);
|
_itemRepo.SaveChapters(itemId, chapters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
@ -897,7 +901,10 @@ namespace MediaBrowser.Providers.Manager
|
||||||
return new ExternalUrl
|
return new ExternalUrl
|
||||||
{
|
{
|
||||||
Name = i.Name,
|
Name = i.Name,
|
||||||
Url = string.Format(i.UrlFormatString, value)
|
Url = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
i.UrlFormatString,
|
||||||
|
value)
|
||||||
};
|
};
|
||||||
|
|
||||||
}).Where(i => i != null).Concat(item.GetRelatedUrls());
|
}).Where(i => i != null).Concat(item.GetRelatedUrls());
|
||||||
|
@ -911,11 +918,10 @@ namespace MediaBrowser.Providers.Manager
|
||||||
Name = i.Name,
|
Name = i.Name,
|
||||||
Key = i.Key,
|
Key = i.Key,
|
||||||
UrlFormatString = i.UrlFormatString
|
UrlFormatString = i.UrlFormatString
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<Guid, double> _activeRefreshes = new Dictionary<Guid, double>();
|
private ConcurrentDictionary<Guid, double> _activeRefreshes = new ConcurrentDictionary<Guid, double>();
|
||||||
|
|
||||||
public Dictionary<Guid, Guid> GetRefreshQueue()
|
public Dictionary<Guid, Guid> GetRefreshQueue()
|
||||||
{
|
{
|
||||||
|
@ -927,66 +933,54 @@ namespace MediaBrowser.Providers.Manager
|
||||||
{
|
{
|
||||||
dict[item.Item1] = item.Item1;
|
dict[item.Item1] = item.Item1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnRefreshStart(BaseItem item)
|
public void OnRefreshStart(BaseItem item)
|
||||||
{
|
{
|
||||||
//_logger.LogInformation("OnRefreshStart {0}", item.Id.ToString("N", CultureInfo.InvariantCulture));
|
_logger.LogInformation("OnRefreshStart {0}", item.Id.ToString("N", CultureInfo.InvariantCulture));
|
||||||
var id = item.Id;
|
_activeRefreshes[item.Id] = 0;
|
||||||
|
|
||||||
lock (_activeRefreshes)
|
|
||||||
{
|
|
||||||
_activeRefreshes[id] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefreshStarted?.Invoke(this, new GenericEventArgs<BaseItem>(item));
|
RefreshStarted?.Invoke(this, new GenericEventArgs<BaseItem>(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnRefreshComplete(BaseItem item)
|
public void OnRefreshComplete(BaseItem item)
|
||||||
{
|
{
|
||||||
//_logger.LogInformation("OnRefreshComplete {0}", item.Id.ToString("N", CultureInfo.InvariantCulture));
|
_logger.LogInformation("OnRefreshComplete {0}", item.Id.ToString("N", CultureInfo.InvariantCulture));
|
||||||
lock (_activeRefreshes)
|
|
||||||
{
|
_activeRefreshes.Remove(item.Id, out _);
|
||||||
_activeRefreshes.Remove(item.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
RefreshCompleted?.Invoke(this, new GenericEventArgs<BaseItem>(item));
|
RefreshCompleted?.Invoke(this, new GenericEventArgs<BaseItem>(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
public double? GetRefreshProgress(Guid id)
|
public double? GetRefreshProgress(Guid id)
|
||||||
{
|
{
|
||||||
lock (_activeRefreshes)
|
if (_activeRefreshes.TryGetValue(id, out double value))
|
||||||
{
|
{
|
||||||
if (_activeRefreshes.TryGetValue(id, out double value))
|
return value;
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnRefreshProgress(BaseItem item, double progress)
|
public void OnRefreshProgress(BaseItem item, double progress)
|
||||||
{
|
{
|
||||||
//_logger.LogInformation("OnRefreshProgress {0} {1}", item.Id.ToString("N", CultureInfo.InvariantCulture), progress);
|
|
||||||
var id = item.Id;
|
var id = item.Id;
|
||||||
|
_logger.LogInformation("OnRefreshProgress {0} {1}", id.ToString("N", CultureInfo.InvariantCulture), progress);
|
||||||
|
|
||||||
lock (_activeRefreshes)
|
// TODO: Need to hunt down the conditions for this happening
|
||||||
{
|
_activeRefreshes.AddOrUpdate(
|
||||||
if (_activeRefreshes.ContainsKey(id))
|
id,
|
||||||
{
|
(_) => throw new Exception(
|
||||||
_activeRefreshes[id] = progress;
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
"Cannot update refresh progress of item '{0}' ({1}) because a refresh for this item is not running",
|
||||||
|
item.GetType().Name,
|
||||||
|
item.Id.ToString("N", CultureInfo.InvariantCulture))),
|
||||||
|
(_, __) => progress);
|
||||||
|
|
||||||
RefreshProgress?.Invoke(this, new GenericEventArgs<Tuple<BaseItem, double>>(new Tuple<BaseItem, double>(item, progress)));
|
RefreshProgress?.Invoke(this, new GenericEventArgs<Tuple<BaseItem, double>>(new Tuple<BaseItem, double>(item, progress)));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// TODO: Need to hunt down the conditions for this happening
|
|
||||||
//throw new Exception(string.Format("Refresh for item {0} {1} is not in progress", item.GetType().Name, item.Id.ToString("N", CultureInfo.InvariantCulture)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly SimplePriorityQueue<Tuple<Guid, MetadataRefreshOptions>> _refreshQueue =
|
private readonly SimplePriorityQueue<Tuple<Guid, MetadataRefreshOptions>> _refreshQueue =
|
||||||
|
@ -1040,10 +1034,9 @@ namespace MediaBrowser.Providers.Manager
|
||||||
// Try to throttle this a little bit.
|
// Try to throttle this a little bit.
|
||||||
await Task.Delay(100).ConfigureAwait(false);
|
await Task.Delay(100).ConfigureAwait(false);
|
||||||
|
|
||||||
var artist = item as MusicArtist;
|
var task = item is MusicArtist artist
|
||||||
var task = artist == null
|
? RefreshArtist(artist, refreshItem.Item2, cancellationToken)
|
||||||
? RefreshItem(item, refreshItem.Item2, cancellationToken)
|
: RefreshItem(item, refreshItem.Item2, cancellationToken);
|
||||||
: RefreshArtist(artist, refreshItem.Item2, cancellationToken);
|
|
||||||
|
|
||||||
await task.ConfigureAwait(false);
|
await task.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -1125,8 +1118,7 @@ namespace MediaBrowser.Providers.Manager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task RefreshFullItem(BaseItem item, MetadataRefreshOptions options,
|
public Task RefreshFullItem(BaseItem item, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
||||||
CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
return RefreshItem(item, options, cancellationToken);
|
return RefreshItem(item, options, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,18 @@
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- Code Analyzers-->
|
||||||
|
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
|
<CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="Plugins\AudioDb\Configuration\config.html" />
|
<None Remove="Plugins\AudioDb\Configuration\config.html" />
|
||||||
<EmbeddedResource Include="Plugins\AudioDb\Configuration\config.html" />
|
<EmbeddedResource Include="Plugins\AudioDb\Configuration\config.html" />
|
||||||
|
|
|
@ -194,7 +194,19 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
FetchShortcutInfo(item);
|
FetchShortcutInfo(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
var prober = new FFProbeVideoInfo(_logger, _mediaSourceManager, _isoManager, _mediaEncoder, _itemRepo, _blurayExaminer, _localization, _appPaths, _json, _encodingManager, _fileSystem, _config, _subtitleManager, _chapterManager, _libraryManager);
|
var prober = new FFProbeVideoInfo(
|
||||||
|
_logger,
|
||||||
|
_mediaSourceManager,
|
||||||
|
_mediaEncoder,
|
||||||
|
_itemRepo,
|
||||||
|
_blurayExaminer,
|
||||||
|
_localization,
|
||||||
|
_encodingManager,
|
||||||
|
_fileSystem,
|
||||||
|
_config,
|
||||||
|
_subtitleManager,
|
||||||
|
_chapterManager,
|
||||||
|
_libraryManager);
|
||||||
|
|
||||||
return prober.ProbeVideo(item, options, cancellationToken);
|
return prober.ProbeVideo(item, options, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
@ -25,7 +27,6 @@ using MediaBrowser.Model.Globalization;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
using MediaBrowser.Model.Providers;
|
using MediaBrowser.Model.Providers;
|
||||||
using MediaBrowser.Model.Serialization;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.Providers.MediaInfo
|
namespace MediaBrowser.Providers.MediaInfo
|
||||||
|
@ -33,13 +34,10 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
public class FFProbeVideoInfo
|
public class FFProbeVideoInfo
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IIsoManager _isoManager;
|
|
||||||
private readonly IMediaEncoder _mediaEncoder;
|
private readonly IMediaEncoder _mediaEncoder;
|
||||||
private readonly IItemRepository _itemRepo;
|
private readonly IItemRepository _itemRepo;
|
||||||
private readonly IBlurayExaminer _blurayExaminer;
|
private readonly IBlurayExaminer _blurayExaminer;
|
||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
private readonly IApplicationPaths _appPaths;
|
|
||||||
private readonly IJsonSerializer _json;
|
|
||||||
private readonly IEncodingManager _encodingManager;
|
private readonly IEncodingManager _encodingManager;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
|
@ -48,16 +46,27 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
|
|
||||||
public FFProbeVideoInfo(ILogger logger, IMediaSourceManager mediaSourceManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IBlurayExaminer blurayExaminer, ILocalizationManager localization, IApplicationPaths appPaths, IJsonSerializer json, IEncodingManager encodingManager, IFileSystem fileSystem, IServerConfigurationManager config, ISubtitleManager subtitleManager, IChapterManager chapterManager, ILibraryManager libraryManager)
|
private readonly long _dummyChapterDuration = TimeSpan.FromMinutes(5).Ticks;
|
||||||
|
|
||||||
|
public FFProbeVideoInfo(
|
||||||
|
ILogger logger,
|
||||||
|
IMediaSourceManager mediaSourceManager,
|
||||||
|
IMediaEncoder mediaEncoder,
|
||||||
|
IItemRepository itemRepo,
|
||||||
|
IBlurayExaminer blurayExaminer,
|
||||||
|
ILocalizationManager localization,
|
||||||
|
IEncodingManager encodingManager,
|
||||||
|
IFileSystem fileSystem,
|
||||||
|
IServerConfigurationManager config,
|
||||||
|
ISubtitleManager subtitleManager,
|
||||||
|
IChapterManager chapterManager,
|
||||||
|
ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_isoManager = isoManager;
|
|
||||||
_mediaEncoder = mediaEncoder;
|
_mediaEncoder = mediaEncoder;
|
||||||
_itemRepo = itemRepo;
|
_itemRepo = itemRepo;
|
||||||
_blurayExaminer = blurayExaminer;
|
_blurayExaminer = blurayExaminer;
|
||||||
_localization = localization;
|
_localization = localization;
|
||||||
_appPaths = appPaths;
|
|
||||||
_json = json;
|
|
||||||
_encodingManager = encodingManager;
|
_encodingManager = encodingManager;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
@ -159,7 +168,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
{
|
{
|
||||||
List<MediaStream> mediaStreams;
|
List<MediaStream> mediaStreams;
|
||||||
IReadOnlyList<MediaAttachment> mediaAttachments;
|
IReadOnlyList<MediaAttachment> mediaAttachments;
|
||||||
List<ChapterInfo> chapters;
|
ChapterInfo[] chapters;
|
||||||
|
|
||||||
if (mediaInfo != null)
|
if (mediaInfo != null)
|
||||||
{
|
{
|
||||||
|
@ -177,6 +186,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
{
|
{
|
||||||
video.RunTimeTicks = mediaInfo.RunTimeTicks;
|
video.RunTimeTicks = mediaInfo.RunTimeTicks;
|
||||||
}
|
}
|
||||||
|
|
||||||
video.Size = mediaInfo.Size;
|
video.Size = mediaInfo.Size;
|
||||||
|
|
||||||
if (video.VideoType == VideoType.VideoFile)
|
if (video.VideoType == VideoType.VideoFile)
|
||||||
|
@ -189,19 +199,20 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
{
|
{
|
||||||
video.Container = null;
|
video.Container = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
video.Container = mediaInfo.Container;
|
video.Container = mediaInfo.Container;
|
||||||
|
|
||||||
chapters = mediaInfo.Chapters == null ? new List<ChapterInfo>() : mediaInfo.Chapters.ToList();
|
chapters = mediaInfo.Chapters == null ? Array.Empty<ChapterInfo>() : mediaInfo.Chapters;
|
||||||
if (blurayInfo != null)
|
if (blurayInfo != null)
|
||||||
{
|
{
|
||||||
FetchBdInfo(video, chapters, mediaStreams, blurayInfo);
|
FetchBdInfo(video, ref chapters, mediaStreams, blurayInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mediaStreams = new List<MediaStream>();
|
mediaStreams = new List<MediaStream>();
|
||||||
mediaAttachments = Array.Empty<MediaAttachment>();
|
mediaAttachments = Array.Empty<MediaAttachment>();
|
||||||
chapters = new List<ChapterInfo>();
|
chapters = Array.Empty<ChapterInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
await AddExternalSubtitles(video, mediaStreams, options, cancellationToken).ConfigureAwait(false);
|
await AddExternalSubtitles(video, mediaStreams, options, cancellationToken).ConfigureAwait(false);
|
||||||
|
@ -231,9 +242,9 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh ||
|
if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh ||
|
||||||
options.MetadataRefreshMode == MetadataRefreshMode.Default)
|
options.MetadataRefreshMode == MetadataRefreshMode.Default)
|
||||||
{
|
{
|
||||||
if (chapters.Count == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video))
|
if (chapters.Length == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video))
|
||||||
{
|
{
|
||||||
AddDummyChapters(video, chapters);
|
chapters = CreateDummyChapters(video);
|
||||||
}
|
}
|
||||||
|
|
||||||
NormalizeChapterNames(chapters);
|
NormalizeChapterNames(chapters);
|
||||||
|
@ -246,28 +257,29 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
|
|
||||||
await _encodingManager.RefreshChapterImages(video, options.DirectoryService, chapters, extractDuringScan, false, cancellationToken).ConfigureAwait(false);
|
await _encodingManager.RefreshChapterImages(video, options.DirectoryService, chapters, extractDuringScan, false, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
_chapterManager.SaveChapters(video.Id.ToString(), chapters);
|
_chapterManager.SaveChapters(video.Id, chapters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NormalizeChapterNames(List<ChapterInfo> chapters)
|
private void NormalizeChapterNames(ChapterInfo[] chapters)
|
||||||
{
|
{
|
||||||
var index = 1;
|
for (int i = 0; i < chapters.Length; i++)
|
||||||
|
|
||||||
foreach (var chapter in chapters)
|
|
||||||
{
|
{
|
||||||
|
string name = chapters[i].Name;
|
||||||
// Check if the name is empty and/or if the name is a time
|
// Check if the name is empty and/or if the name is a time
|
||||||
// Some ripping programs do that.
|
// Some ripping programs do that.
|
||||||
if (string.IsNullOrWhiteSpace(chapter.Name) ||
|
if (string.IsNullOrWhiteSpace(name) ||
|
||||||
TimeSpan.TryParse(chapter.Name, out var time))
|
TimeSpan.TryParse(name, out _))
|
||||||
{
|
{
|
||||||
chapter.Name = string.Format(_localization.GetLocalizedString("ChapterNameValue"), index.ToString(CultureInfo.InvariantCulture));
|
chapters[i].Name = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localization.GetLocalizedString("ChapterNameValue"),
|
||||||
|
(i + 1).ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FetchBdInfo(BaseItem item, List<ChapterInfo> chapters, List<MediaStream> mediaStreams, BlurayDiscInfo blurayInfo)
|
private void FetchBdInfo(BaseItem item, ref ChapterInfo[] chapters, List<MediaStream> mediaStreams, BlurayDiscInfo blurayInfo)
|
||||||
{
|
{
|
||||||
var video = (Video)item;
|
var video = (Video)item;
|
||||||
|
|
||||||
|
@ -301,13 +313,15 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
|
|
||||||
if (blurayInfo.Chapters != null)
|
if (blurayInfo.Chapters != null)
|
||||||
{
|
{
|
||||||
chapters.Clear();
|
double[] brChapter = blurayInfo.Chapters;
|
||||||
|
chapters = new ChapterInfo[brChapter.Length];
|
||||||
chapters.AddRange(blurayInfo.Chapters.Select(c => new ChapterInfo
|
for (int i = 0; i < brChapter.Length; i++)
|
||||||
{
|
{
|
||||||
StartPositionTicks = TimeSpan.FromSeconds(c).Ticks
|
chapters[i] = new ChapterInfo
|
||||||
|
{
|
||||||
}));
|
StartPositionTicks = TimeSpan.FromSeconds(brChapter[i]).Ticks
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
videoStream = mediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video);
|
videoStream = mediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video);
|
||||||
|
@ -495,17 +509,17 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
var libraryOptions = _libraryManager.GetLibraryOptions(video);
|
var libraryOptions = _libraryManager.GetLibraryOptions(video);
|
||||||
|
|
||||||
string[] subtitleDownloadLanguages;
|
string[] subtitleDownloadLanguages;
|
||||||
bool SkipIfEmbeddedSubtitlesPresent;
|
bool skipIfEmbeddedSubtitlesPresent;
|
||||||
bool SkipIfAudioTrackMatches;
|
bool skipIfAudioTrackMatches;
|
||||||
bool RequirePerfectMatch;
|
bool requirePerfectMatch;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
|
|
||||||
if (libraryOptions.SubtitleDownloadLanguages == null)
|
if (libraryOptions.SubtitleDownloadLanguages == null)
|
||||||
{
|
{
|
||||||
subtitleDownloadLanguages = subtitleOptions.DownloadLanguages;
|
subtitleDownloadLanguages = subtitleOptions.DownloadLanguages;
|
||||||
SkipIfEmbeddedSubtitlesPresent = subtitleOptions.SkipIfEmbeddedSubtitlesPresent;
|
skipIfEmbeddedSubtitlesPresent = subtitleOptions.SkipIfEmbeddedSubtitlesPresent;
|
||||||
SkipIfAudioTrackMatches = subtitleOptions.SkipIfAudioTrackMatches;
|
skipIfAudioTrackMatches = subtitleOptions.SkipIfAudioTrackMatches;
|
||||||
RequirePerfectMatch = subtitleOptions.RequirePerfectMatch;
|
requirePerfectMatch = subtitleOptions.RequirePerfectMatch;
|
||||||
enabled = (subtitleOptions.DownloadEpisodeSubtitles &&
|
enabled = (subtitleOptions.DownloadEpisodeSubtitles &&
|
||||||
video is Episode) ||
|
video is Episode) ||
|
||||||
(subtitleOptions.DownloadMovieSubtitles &&
|
(subtitleOptions.DownloadMovieSubtitles &&
|
||||||
|
@ -514,9 +528,9 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
subtitleDownloadLanguages = libraryOptions.SubtitleDownloadLanguages;
|
subtitleDownloadLanguages = libraryOptions.SubtitleDownloadLanguages;
|
||||||
SkipIfEmbeddedSubtitlesPresent = libraryOptions.SkipSubtitlesIfEmbeddedSubtitlesPresent;
|
skipIfEmbeddedSubtitlesPresent = libraryOptions.SkipSubtitlesIfEmbeddedSubtitlesPresent;
|
||||||
SkipIfAudioTrackMatches = libraryOptions.SkipSubtitlesIfAudioTrackMatches;
|
skipIfAudioTrackMatches = libraryOptions.SkipSubtitlesIfAudioTrackMatches;
|
||||||
RequirePerfectMatch = libraryOptions.RequirePerfectSubtitleMatch;
|
requirePerfectMatch = libraryOptions.RequirePerfectSubtitleMatch;
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,9 +540,9 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
_subtitleManager)
|
_subtitleManager)
|
||||||
.DownloadSubtitles(video,
|
.DownloadSubtitles(video,
|
||||||
currentStreams.Concat(externalSubtitleStreams).ToList(),
|
currentStreams.Concat(externalSubtitleStreams).ToList(),
|
||||||
SkipIfEmbeddedSubtitlesPresent,
|
skipIfEmbeddedSubtitlesPresent,
|
||||||
SkipIfAudioTrackMatches,
|
skipIfAudioTrackMatches,
|
||||||
RequirePerfectMatch,
|
requirePerfectMatch,
|
||||||
subtitleDownloadLanguages,
|
subtitleDownloadLanguages,
|
||||||
libraryOptions.DisabledSubtitleFetchers,
|
libraryOptions.DisabledSubtitleFetchers,
|
||||||
libraryOptions.SubtitleFetcherOrder,
|
libraryOptions.SubtitleFetcherOrder,
|
||||||
|
@ -547,43 +561,45 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The dummy chapter duration
|
/// Creates dummy chapters.
|
||||||
/// </summary>
|
|
||||||
private readonly long _dummyChapterDuration = TimeSpan.FromMinutes(5).Ticks;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds the dummy chapters.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="video">The video.</param>
|
/// <param name="video">The video.</param>
|
||||||
/// <param name="chapters">The chapters.</param>
|
/// <return>An array of dummy chapters.</returns>
|
||||||
private void AddDummyChapters(Video video, List<ChapterInfo> chapters)
|
private ChapterInfo[] CreateDummyChapters(Video video)
|
||||||
{
|
{
|
||||||
var runtime = video.RunTimeTicks ?? 0;
|
var runtime = video.RunTimeTicks ?? 0;
|
||||||
|
|
||||||
if (runtime < 0)
|
if (runtime < 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentException(string.Format("{0} has invalid runtime of {1}", video.Name, runtime));
|
throw new ArgumentException(
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
"{0} has invalid runtime of {1}",
|
||||||
|
video.Name,
|
||||||
|
runtime));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtime < _dummyChapterDuration)
|
if (runtime < _dummyChapterDuration)
|
||||||
{
|
{
|
||||||
return;
|
return Array.Empty<ChapterInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
long currentChapterTicks = 0;
|
|
||||||
var index = 1;
|
|
||||||
|
|
||||||
// Limit to 100 chapters just in case there's some incorrect metadata here
|
// Limit to 100 chapters just in case there's some incorrect metadata here
|
||||||
while (currentChapterTicks < runtime && index < 100)
|
int chapterCount = (int)Math.Min(runtime / _dummyChapterDuration, 100);
|
||||||
|
var chapters = new ChapterInfo[chapterCount];
|
||||||
|
|
||||||
|
long currentChapterTicks = 0;
|
||||||
|
for (int i = 0; i < chapterCount; i++)
|
||||||
{
|
{
|
||||||
chapters.Add(new ChapterInfo
|
chapters[i] = new ChapterInfo
|
||||||
{
|
{
|
||||||
StartPositionTicks = currentChapterTicks
|
StartPositionTicks = currentChapterTicks
|
||||||
});
|
};
|
||||||
|
|
||||||
index++;
|
|
||||||
currentChapterTicks += _dummyChapterDuration;
|
currentChapterTicks += _dummyChapterDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return chapters;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string[] FetchFromDvdLib(Video item)
|
private string[] FetchFromDvdLib(Video item)
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -775,7 +776,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
_logger.LogDebug("GetMusicBrainzResponse: Time since previous request: {0} ms", _stopWatchMusicBrainz.ElapsedMilliseconds);
|
_logger.LogDebug("GetMusicBrainzResponse: Time since previous request: {0} ms", _stopWatchMusicBrainz.ElapsedMilliseconds);
|
||||||
_stopWatchMusicBrainz.Restart();
|
_stopWatchMusicBrainz.Restart();
|
||||||
|
|
||||||
response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false);
|
response = await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false);
|
||||||
|
|
||||||
// We retry a finite number of times, and only whilst MB is indicating 503 (throttling)
|
// We retry a finite number of times, and only whilst MB is indicating 503 (throttling)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
|
@ -36,7 +37,6 @@ namespace MediaBrowser.Providers.Tmdb.Movies
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly IServerConfigurationManager _configurationManager;
|
private readonly IServerConfigurationManager _configurationManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly ILocalizationManager _localization;
|
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IApplicationHost _appHost;
|
private readonly IApplicationHost _appHost;
|
||||||
|
|
||||||
|
@ -48,7 +48,6 @@ namespace MediaBrowser.Providers.Tmdb.Movies
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IServerConfigurationManager configurationManager,
|
IServerConfigurationManager configurationManager,
|
||||||
ILogger<TmdbMovieProvider> logger,
|
ILogger<TmdbMovieProvider> logger,
|
||||||
ILocalizationManager localization,
|
|
||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
IApplicationHost appHost)
|
IApplicationHost appHost)
|
||||||
{
|
{
|
||||||
|
@ -57,7 +56,6 @@ namespace MediaBrowser.Providers.Tmdb.Movies
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_configurationManager = configurationManager;
|
_configurationManager = configurationManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_localization = localization;
|
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
Current = this;
|
Current = this;
|
||||||
|
@ -409,15 +407,15 @@ namespace MediaBrowser.Providers.Tmdb.Movies
|
||||||
|
|
||||||
private static long _lastRequestTicks;
|
private static long _lastRequestTicks;
|
||||||
// The limit is 40 requests per 10 seconds
|
// The limit is 40 requests per 10 seconds
|
||||||
private static int requestIntervalMs = 300;
|
private const int RequestIntervalMs = 300;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the movie db response.
|
/// Gets the movie db response.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal async Task<HttpResponseInfo> GetMovieDbResponse(HttpRequestOptions options)
|
internal async Task<HttpResponseInfo> GetMovieDbResponse(HttpRequestOptions options)
|
||||||
{
|
{
|
||||||
var delayTicks = (requestIntervalMs * 10000) - (DateTime.UtcNow.Ticks - _lastRequestTicks);
|
var delayTicks = (RequestIntervalMs * 10000) - (DateTime.UtcNow.Ticks - _lastRequestTicks);
|
||||||
var delayMs = Math.Min(delayTicks / 10000, requestIntervalMs);
|
var delayMs = Math.Min(delayTicks / 10000, RequestIntervalMs);
|
||||||
|
|
||||||
if (delayMs > 0)
|
if (delayMs > 0)
|
||||||
{
|
{
|
||||||
|
@ -430,11 +428,13 @@ namespace MediaBrowser.Providers.Tmdb.Movies
|
||||||
options.BufferContent = true;
|
options.BufferContent = true;
|
||||||
options.UserAgent = _appHost.ApplicationUserAgent;
|
options.UserAgent = _appHost.ApplicationUserAgent;
|
||||||
|
|
||||||
return await _httpClient.SendAsync(options, "GET").ConfigureAwait(false);
|
return await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public int Order => 1;
|
public int Order => 1;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _httpClient.GetResponse(new HttpRequestOptions
|
return _httpClient.GetResponse(new HttpRequestOptions
|
||||||
|
|
Loading…
Reference in New Issue
Block a user