diff --git a/MediaBrowser.Api/Library/LibraryHelpers.cs b/MediaBrowser.Api/Library/LibraryHelpers.cs
index 008cfb27f7..3d0dd4e088 100644
--- a/MediaBrowser.Api/Library/LibraryHelpers.cs
+++ b/MediaBrowser.Api/Library/LibraryHelpers.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.IO;
using System;
@@ -12,20 +13,27 @@ namespace MediaBrowser.Api.Library
///
public static class LibraryHelpers
{
+ ///
+ /// The shortcut file extension
+ ///
private const string ShortcutFileExtension = ".mblink";
+ ///
+ /// The shortcut file search
+ ///
private const string ShortcutFileSearch = "*" + ShortcutFileExtension;
///
/// Adds the virtual folder.
///
+ /// The file system.
/// The name.
/// Type of the collection.
/// The user.
/// The app paths.
/// There is already a media collection with the name + name + .
- public static void AddVirtualFolder(string name, string collectionType, User user, IServerApplicationPaths appPaths)
+ public static void AddVirtualFolder(IFileSystem fileSystem, string name, string collectionType, User user, IServerApplicationPaths appPaths)
{
- name = FileSystem.GetValidFilename(name);
+ name = fileSystem.GetValidFilename(name);
var rootFolderPath = user != null ? user.RootFolderPath : appPaths.DefaultUserViewsPath;
var virtualFolderPath = Path.Combine(rootFolderPath, name);
@@ -106,12 +114,13 @@ namespace MediaBrowser.Api.Library
///
/// Deletes a shortcut from within a virtual folder, within either the default view or a user view
///
+ /// The file system.
/// Name of the virtual folder.
/// The media path.
/// The user.
/// The app paths.
/// The media folder does not exist
- public static void RemoveMediaPath(string virtualFolderName, string mediaPath, User user, IServerApplicationPaths appPaths)
+ public static void RemoveMediaPath(IFileSystem fileSystem, string virtualFolderName, string mediaPath, User user, IServerApplicationPaths appPaths)
{
var rootFolderPath = user != null ? user.RootFolderPath : appPaths.DefaultUserViewsPath;
var path = Path.Combine(rootFolderPath, virtualFolderName);
@@ -121,7 +130,7 @@ namespace MediaBrowser.Api.Library
throw new DirectoryNotFoundException(string.Format("The media collection {0} does not exist", virtualFolderName));
}
- var shortcut = Directory.EnumerateFiles(path, ShortcutFileSearch, SearchOption.AllDirectories).FirstOrDefault(f => FileSystem.ResolveShortcut(f).Equals(mediaPath, StringComparison.OrdinalIgnoreCase));
+ var shortcut = Directory.EnumerateFiles(path, ShortcutFileSearch, SearchOption.AllDirectories).FirstOrDefault(f => fileSystem.ResolveShortcut(f).Equals(mediaPath, StringComparison.OrdinalIgnoreCase));
if (!string.IsNullOrEmpty(shortcut))
{
@@ -132,13 +141,14 @@ namespace MediaBrowser.Api.Library
///
/// Adds an additional mediaPath to an existing virtual folder, within either the default view or a user view
///
+ /// The file system.
/// Name of the virtual folder.
/// The path.
/// The user.
/// The app paths.
/// The path is not valid.
/// The path does not exist.
- public static void AddMediaPath(string virtualFolderName, string path, User user, IServerApplicationPaths appPaths)
+ public static void AddMediaPath(IFileSystem fileSystem, string virtualFolderName, string path, User user, IServerApplicationPaths appPaths)
{
if (!Path.IsPathRooted(path))
{
@@ -160,7 +170,7 @@ namespace MediaBrowser.Api.Library
var rootFolderPath = user != null ? user.RootFolderPath : appPaths.DefaultUserViewsPath;
var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName);
- ValidateNewMediaPath(rootFolderPath, path, appPaths);
+ ValidateNewMediaPath(fileSystem, rootFolderPath, path, appPaths);
var shortcutFilename = Path.GetFileNameWithoutExtension(path);
@@ -172,20 +182,22 @@ namespace MediaBrowser.Api.Library
lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension);
}
- FileSystem.CreateShortcut(lnk, path);
+ fileSystem.CreateShortcut(lnk, path);
}
///
/// Validates that a new media path can be added
///
+ /// The file system.
/// The current view root folder path.
/// The media path.
/// The app paths.
- ///
- private static void ValidateNewMediaPath(string currentViewRootFolderPath, string mediaPath, IServerApplicationPaths appPaths)
+ ///
+ ///
+ private static void ValidateNewMediaPath(IFileSystem fileSystem, string currentViewRootFolderPath, string mediaPath, IServerApplicationPaths appPaths)
{
var duplicate = Directory.EnumerateFiles(appPaths.RootFolderPath, ShortcutFileSearch, SearchOption.AllDirectories)
- .Select(FileSystem.ResolveShortcut)
+ .Select(fileSystem.ResolveShortcut)
.FirstOrDefault(p => !IsNewPathValid(mediaPath, p, false));
if (!string.IsNullOrEmpty(duplicate))
@@ -196,7 +208,7 @@ namespace MediaBrowser.Api.Library
// Don't allow duplicate sub-paths within the same user library, or it will result in duplicate items
// See comments in IsNewPathValid
duplicate = Directory.EnumerateFiles(currentViewRootFolderPath, ShortcutFileSearch, SearchOption.AllDirectories)
- .Select(FileSystem.ResolveShortcut)
+ .Select(fileSystem.ResolveShortcut)
.FirstOrDefault(p => !IsNewPathValid(mediaPath, p, true));
if (!string.IsNullOrEmpty(duplicate))
@@ -206,7 +218,7 @@ namespace MediaBrowser.Api.Library
// Make sure the current root folder doesn't already have a shortcut to the same path
duplicate = Directory.EnumerateFiles(currentViewRootFolderPath, ShortcutFileSearch, SearchOption.AllDirectories)
- .Select(FileSystem.ResolveShortcut)
+ .Select(fileSystem.ResolveShortcut)
.FirstOrDefault(p => mediaPath.Equals(p, StringComparison.OrdinalIgnoreCase));
if (!string.IsNullOrEmpty(duplicate))
diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs
index e6fa1d1c0b..0126586ab7 100644
--- a/MediaBrowser.Api/Library/LibraryStructureService.cs
+++ b/MediaBrowser.Api/Library/LibraryStructureService.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
@@ -186,6 +187,8 @@ namespace MediaBrowser.Api.Library
private readonly IDirectoryWatchers _directoryWatchers;
+ private readonly IFileSystem _fileSystem;
+
///
/// Initializes a new instance of the class.
///
@@ -193,7 +196,7 @@ namespace MediaBrowser.Api.Library
/// The user manager.
/// The library manager.
/// appPaths
- public LibraryStructureService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IDirectoryWatchers directoryWatchers)
+ public LibraryStructureService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IDirectoryWatchers directoryWatchers, IFileSystem fileSystem)
{
if (appPaths == null)
{
@@ -204,6 +207,7 @@ namespace MediaBrowser.Api.Library
_appPaths = appPaths;
_libraryManager = libraryManager;
_directoryWatchers = directoryWatchers;
+ _fileSystem = fileSystem;
}
///
@@ -241,13 +245,13 @@ namespace MediaBrowser.Api.Library
{
if (string.IsNullOrEmpty(request.UserId))
{
- LibraryHelpers.AddVirtualFolder(request.Name, request.CollectionType, null, _appPaths);
+ LibraryHelpers.AddVirtualFolder(_fileSystem, request.Name, request.CollectionType, null, _appPaths);
}
else
{
var user = _userManager.GetUserById(new Guid(request.UserId));
- LibraryHelpers.AddVirtualFolder(request.Name, request.CollectionType, user, _appPaths);
+ LibraryHelpers.AddVirtualFolder(_fileSystem, request.Name, request.CollectionType, user, _appPaths);
}
// Need to add a delay here or directory watchers may still pick up the changes
@@ -352,13 +356,13 @@ namespace MediaBrowser.Api.Library
{
if (string.IsNullOrEmpty(request.UserId))
{
- LibraryHelpers.AddMediaPath(request.Name, request.Path, null, _appPaths);
+ LibraryHelpers.AddMediaPath(_fileSystem, request.Name, request.Path, null, _appPaths);
}
else
{
var user = _userManager.GetUserById(new Guid(request.UserId));
- LibraryHelpers.AddMediaPath(request.Name, request.Path, user, _appPaths);
+ LibraryHelpers.AddMediaPath(_fileSystem, request.Name, request.Path, user, _appPaths);
}
// Need to add a delay here or directory watchers may still pick up the changes
@@ -389,13 +393,13 @@ namespace MediaBrowser.Api.Library
{
if (string.IsNullOrEmpty(request.UserId))
{
- LibraryHelpers.RemoveMediaPath(request.Name, request.Path, null, _appPaths);
+ LibraryHelpers.RemoveMediaPath(_fileSystem, request.Name, request.Path, null, _appPaths);
}
else
{
var user = _userManager.GetUserById(new Guid(request.UserId));
- LibraryHelpers.RemoveMediaPath(request.Name, request.Path, user, _appPaths);
+ LibraryHelpers.RemoveMediaPath(_fileSystem, request.Name, request.Path, user, _appPaths);
}
// Need to add a delay here or directory watchers may still pick up the changes
diff --git a/MediaBrowser.Api/LibraryService.cs b/MediaBrowser.Api/LibraryService.cs
index 82089536cb..5b133fbd3e 100644
--- a/MediaBrowser.Api/LibraryService.cs
+++ b/MediaBrowser.Api/LibraryService.cs
@@ -5,8 +5,10 @@ using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using System;
@@ -32,6 +34,21 @@ namespace MediaBrowser.Api
public string Id { get; set; }
}
+ [Route("/Items/{Id}/RemoteImages/{Type}", "GET")]
+ [Api(Description = "Gets available remote images for an item")]
+ public class GetRemoteImages : IReturn>
+ {
+ ///
+ /// Gets or sets the id.
+ ///
+ /// The id.
+ [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string Id { get; set; }
+
+ [ApiMember(Name = "Type", Description = "The image type", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public ImageType Type { get; set; }
+ }
+
///
/// Class GetCriticReviews
///
@@ -208,6 +225,7 @@ namespace MediaBrowser.Api
private readonly ILibraryManager _libraryManager;
private readonly IUserManager _userManager;
private readonly IUserDataManager _userDataManager;
+ private readonly IProviderManager _providerManager;
private readonly IDtoService _dtoService;
@@ -215,13 +233,14 @@ namespace MediaBrowser.Api
/// Initializes a new instance of the class.
///
public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
- IDtoService dtoService, IUserDataManager userDataManager)
+ IDtoService dtoService, IUserDataManager userDataManager, IProviderManager providerManager)
{
_itemRepo = itemRepo;
_libraryManager = libraryManager;
_userManager = userManager;
_dtoService = dtoService;
_userDataManager = userDataManager;
+ _providerManager = providerManager;
}
public object Get(GetFile request)
@@ -240,6 +259,15 @@ namespace MediaBrowser.Api
return ToStaticFileResult(item.Path);
}
+ public object Get(GetRemoteImages request)
+ {
+ var item = _dtoService.GetItemByDtoId(request.Id);
+
+ var result = _providerManager.GetAvailableRemoteImages(item, request.Type, CancellationToken.None).Result;
+
+ return ToOptimizedResult(result);
+ }
+
///
/// Gets the specified request.
///
@@ -335,7 +363,9 @@ namespace MediaBrowser.Api
/// System.Object.
public object Get(GetItemCounts request)
{
- var items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager).ToList();
+ var items = GetAllLibraryItems(request.UserId, _userManager, _libraryManager)
+ .Where(i => i.LocationType != LocationType.Virtual)
+ .ToList();
var filteredItems = request.UserId.HasValue ? FilterItems(items, request, request.UserId.Value).ToList() : items;
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 6462301600..4332999015 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -59,6 +59,8 @@ namespace MediaBrowser.Api.Playback
protected IMediaEncoder MediaEncoder { get; private set; }
protected IDtoService DtoService { get; private set; }
+ protected IFileSystem FileSystem { get; private set; }
+
///
/// Initializes a new instance of the class.
///
@@ -67,8 +69,9 @@ namespace MediaBrowser.Api.Playback
/// The library manager.
/// The iso manager.
/// The media encoder.
- protected BaseStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService)
+ protected BaseStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem)
{
+ FileSystem = fileSystem;
DtoService = dtoService;
ApplicationPaths = appPaths;
UserManager = userManager;
@@ -269,7 +272,7 @@ namespace MediaBrowser.Api.Playback
// If fixed dimensions were supplied
if (request.Width.HasValue && request.Height.HasValue)
{
- return string.Format(" -vf \"scale={0}:{1}{2}\"", request.Width.Value, request.Height.Value, assSubtitleParam);
+ return string.Format(" -vf \"scale=trunc({0}/2)*2:trunc({1}/2)*2{2}\"", request.Width.Value, request.Height.Value, assSubtitleParam);
}
var isH264Output = outputVideoCodec.Equals("libx264", StringComparison.OrdinalIgnoreCase);
@@ -653,7 +656,7 @@ namespace MediaBrowser.Api.Playback
var logFilePath = Path.Combine(ApplicationPaths.LogDirectoryPath, "ffmpeg-" + Guid.NewGuid() + ".txt");
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
- state.LogFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous);
+ state.LogFileStream = FileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true);
process.Exited += (sender, args) => OnFfMpegProcessExited(process, state);
diff --git a/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs b/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs
index 6e36ba0ad8..6636db05d2 100644
--- a/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.MediaInfo;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library;
@@ -32,8 +33,8 @@ namespace MediaBrowser.Api.Playback.Hls
/// The library manager.
/// The iso manager.
/// The media encoder.
- public AudioHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService)
- : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService)
+ public AudioHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem)
+ : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem)
{
}
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 787727cd3a..3e96cf2f82 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -38,8 +38,8 @@ namespace MediaBrowser.Api.Playback.Hls
/// The library manager.
/// The iso manager.
/// The media encoder.
- protected BaseHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService)
- : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService)
+ protected BaseHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem)
+ : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem)
{
}
@@ -209,7 +209,7 @@ namespace MediaBrowser.Api.Playback.Hls
string fileText;
// Need to use FileShare.ReadWrite because we're reading the file at the same time it's being written
- using (var fileStream = new FileStream(playlist, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
+ using (var fileStream = FileSystem.GetFileStream(playlist, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true))
{
using (var reader = new StreamReader(fileStream))
{
diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
index ecc53ce349..453039ba8a 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.MediaInfo;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library;
@@ -39,8 +40,8 @@ namespace MediaBrowser.Api.Playback.Hls
/// The iso manager.
/// The media encoder.
/// The dto service.
- public VideoHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService)
- : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService)
+ public VideoHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem)
+ : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem)
{
}
diff --git a/MediaBrowser.Api/Playback/Progressive/AudioService.cs b/MediaBrowser.Api/Playback/Progressive/AudioService.cs
index 4165055755..36a998c16d 100644
--- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.MediaInfo;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
@@ -40,8 +41,8 @@ namespace MediaBrowser.Api.Playback.Progressive
///
public class AudioService : BaseProgressiveStreamingService
{
- public AudioService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IDtoService dtoService, IImageProcessor imageProcessor)
- : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, itemRepo, dtoService, imageProcessor)
+ public AudioService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IDtoService dtoService, IImageProcessor imageProcessor, IFileSystem fileSystem)
+ : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, itemRepo, dtoService, imageProcessor, fileSystem)
{
}
diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
index 0bc147a46c..a31b6af0e2 100644
--- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Api.Images;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
@@ -27,8 +28,8 @@ namespace MediaBrowser.Api.Playback.Progressive
protected readonly IItemRepository ItemRepository;
protected readonly IImageProcessor ImageProcessor;
- protected BaseProgressiveStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepository, IDtoService dtoService, IImageProcessor imageProcessor) :
- base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService)
+ protected BaseProgressiveStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepository, IDtoService dtoService, IImageProcessor imageProcessor, IFileSystem fileSystem) :
+ base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem)
{
ItemRepository = itemRepository;
ImageProcessor = imageProcessor;
@@ -346,7 +347,7 @@ namespace MediaBrowser.Api.Playback.Progressive
ApiEntryPoint.Instance.OnTranscodeBeginRequest(outputPath, TranscodingJobType.Progressive);
}
- var result = new ProgressiveStreamWriter(outputPath, Logger);
+ var result = new ProgressiveStreamWriter(outputPath, Logger, FileSystem);
result.Options["Accept-Ranges"] = "none";
result.Options["Content-Type"] = contentType;
diff --git a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs
index c967a0d015..816cab105d 100644
--- a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs
+++ b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs
@@ -13,6 +13,7 @@ namespace MediaBrowser.Api.Playback.Progressive
{
private string Path { get; set; }
private ILogger Logger { get; set; }
+ private readonly IFileSystem _fileSystem;
///
/// The _options
@@ -32,10 +33,11 @@ namespace MediaBrowser.Api.Playback.Progressive
///
/// The path.
/// The logger.
- public ProgressiveStreamWriter(string path, ILogger logger)
+ public ProgressiveStreamWriter(string path, ILogger logger, IFileSystem fileSystem)
{
Path = path;
Logger = logger;
+ _fileSystem = fileSystem;
}
///
@@ -83,7 +85,7 @@ namespace MediaBrowser.Api.Playback.Progressive
var eofCount = 0;
long position = 0;
- using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
+ using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true))
{
while (eofCount < 15)
{
diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
index c1dd7fa017..fe5d22f584 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.MediaInfo;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
@@ -54,8 +55,8 @@ namespace MediaBrowser.Api.Playback.Progressive
///
public class VideoService : BaseProgressiveStreamingService
{
- public VideoService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IDtoService dtoService, IImageProcessor imageProcessor)
- : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, itemRepo, dtoService, imageProcessor)
+ public VideoService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IDtoService dtoService, IImageProcessor imageProcessor, IFileSystem fileSystem)
+ : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, itemRepo, dtoService, imageProcessor, fileSystem)
{
}
diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/SessionsService.cs
index 5888d9fba3..a3f7e3037c 100644
--- a/MediaBrowser.Api/SessionsService.cs
+++ b/MediaBrowser.Api/SessionsService.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Session;
using ServiceStack.ServiceHost;
@@ -182,16 +183,18 @@ namespace MediaBrowser.Api
private readonly ISessionManager _sessionManager;
private readonly IDtoService _dtoService;
+ private readonly IUserManager _userManager;
///
/// Initializes a new instance of the class.
///
/// The session manager.
/// The dto service.
- public SessionsService(ISessionManager sessionManager, IDtoService dtoService)
+ public SessionsService(ISessionManager sessionManager, IDtoService dtoService, IUserManager userManager)
{
_sessionManager = sessionManager;
_dtoService = dtoService;
+ _userManager = userManager;
}
///
@@ -208,6 +211,16 @@ namespace MediaBrowser.Api
result = result.Where(i => i.SupportsRemoteControl == request.SupportsRemoteControl.Value);
}
+ if (request.ControllableByUserId.HasValue)
+ {
+ var user = _userManager.GetUserById(request.ControllableByUserId.Value);
+
+ if (!user.Configuration.EnableRemoteControlOfOtherUsers)
+ {
+ result = result.Where(i => i.User == null || i.User.Id == request.ControllableByUserId.Value);
+ }
+ }
+
return ToOptimizedResult(result.Select(_dtoService.GetSessionInfoDto).ToList());
}
diff --git a/MediaBrowser.Api/SystemService.cs b/MediaBrowser.Api/SystemService.cs
index 9bbd6a5883..ae6c607954 100644
--- a/MediaBrowser.Api/SystemService.cs
+++ b/MediaBrowser.Api/SystemService.cs
@@ -1,6 +1,8 @@
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.System;
@@ -75,6 +77,9 @@ namespace MediaBrowser.Api
///
private readonly IServerConfigurationManager _configurationManager;
+ private readonly IFileSystem _fileSystem;
+
+
///
/// Initializes a new instance of the class.
///
@@ -82,7 +87,7 @@ namespace MediaBrowser.Api
/// The app host.
/// The configuration manager.
/// jsonSerializer
- public SystemService(IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IServerConfigurationManager configurationManager)
+ public SystemService(IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
: base()
{
if (jsonSerializer == null)
@@ -96,6 +101,7 @@ namespace MediaBrowser.Api
_appHost = appHost;
_configurationManager = configurationManager;
+ _fileSystem = fileSystem;
_jsonSerializer = jsonSerializer;
}
@@ -118,7 +124,7 @@ namespace MediaBrowser.Api
/// System.Object.
public object Get(GetConfiguration request)
{
- var dateModified = File.GetLastWriteTimeUtc(_configurationManager.ApplicationPaths.SystemConfigurationFilePath);
+ var dateModified = _fileSystem.GetLastWriteTimeUtc(_configurationManager.ApplicationPaths.SystemConfigurationFilePath);
var cacheKey = (_configurationManager.ApplicationPaths.SystemConfigurationFilePath + dateModified.Ticks).GetMD5();
diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs
index fad17814ec..0ac181dea2 100644
--- a/MediaBrowser.Api/TvShowsService.cs
+++ b/MediaBrowser.Api/TvShowsService.cs
@@ -1,10 +1,9 @@
-using System.Collections;
-using System.Globalization;
-using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using System;
@@ -48,18 +47,9 @@ namespace MediaBrowser.Api
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, OverviewHtml, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
- [ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string ExcludeLocationTypes { get; set; }
+ [ApiMember(Name = "SeriesId", Description = "Optional. Filter by series id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public string SeriesId { get; set; }
- [ApiMember(Name = "MinPremiereDate", Description = "Optional. The minimum premiere date. Format = yyyyMMddHHmmss", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string MinPremiereDate { get; set; }
-
- [ApiMember(Name = "MaxPremiereDate", Description = "Optional. The maximum premiere date. Format = yyyyMMddHHmmss", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string MaxPremiereDate { get; set; }
-
- [ApiMember(Name = "HasPremiereDate", Description = "Optional filter by items with premiere dates.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public bool? HasPremiereDate { get; set; }
-
///
/// Gets the item fields.
///
@@ -170,10 +160,15 @@ namespace MediaBrowser.Api
{
var user = _userManager.GetUserById(request.UserId);
- var itemsList = user.RootFolder
- .GetRecursiveChildren(user, i => i is Series)
+ var items = user.RootFolder
+ .GetRecursiveChildren(user)
+ .OfType();
+
+ items = FilterSeries(request, items);
+
+ var itemsList = items
.AsParallel()
- .Select(i => GetNextUp((Series)i, user, request))
+ .Select(i => GetNextUp(i, user, request))
.ToList();
itemsList = itemsList
@@ -264,35 +259,19 @@ namespace MediaBrowser.Api
private IEnumerable FilterItems(GetNextUpEpisodes request, IEnumerable items)
{
- // ExcludeLocationTypes
- if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
- {
- var vals = request.ExcludeLocationTypes.Split(',');
-
- items = items
- .Where(f => !vals.Contains(f.LocationType.ToString(), StringComparer.OrdinalIgnoreCase))
- .ToList();
- }
-
- if (!string.IsNullOrEmpty(request.MinPremiereDate))
- {
- var date = DateTime.ParseExact(request.MinPremiereDate, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
+ // Make this configurable when needed
+ items = items.Where(i => i.LocationType != LocationType.Virtual);
- items = items.Where(i => !i.PremiereDate.HasValue || i.PremiereDate.Value >= date);
- }
-
- if (!string.IsNullOrEmpty(request.MaxPremiereDate))
- {
- var date = DateTime.ParseExact(request.MaxPremiereDate, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
-
- items = items.Where(i => !i.PremiereDate.HasValue || i.PremiereDate.Value <= date);
- }
+ return items;
+ }
- if (request.HasPremiereDate.HasValue)
+ private IEnumerable FilterSeries(GetNextUpEpisodes request, IEnumerable items)
+ {
+ if (!string.IsNullOrWhiteSpace(request.SeriesId))
{
- var val = request.HasPremiereDate.Value;
+ var id = new Guid(request.SeriesId);
- items = items.Where(i => i.PremiereDate.HasValue == val);
+ items = items.Where(i => i.Id == id);
}
return items;
diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs
index cb01dae733..9c3ea7bf04 100644
--- a/MediaBrowser.Api/UserLibrary/ItemsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs
@@ -1,5 +1,4 @@
-using System.Globalization;
-using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
@@ -181,22 +180,22 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "IsHD", Description = "Optional filter by items that are HD or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? IsHD { get; set; }
- [ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string ExcludeLocationTypes { get; set; }
-
[ApiMember(Name = "LocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string LocationTypes { get; set; }
- [ApiMember(Name = "MinPremiereDate", Description = "Optional. The minimum premiere date. Format = yyyyMMddHHmmss", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string MinPremiereDate { get; set; }
+ [ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ public string ExcludeLocationTypes { get; set; }
- [ApiMember(Name = "MaxPremiereDate", Description = "Optional. The maximum premiere date. Format = yyyyMMddHHmmss", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string MaxPremiereDate { get; set; }
+ public bool IncludeIndexContainers { get; set; }
- [ApiMember(Name = "HasPremiereDate", Description = "Optional filter by items with premiere dates.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public bool? HasPremiereDate { get; set; }
+ [ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
+ public bool? IsMissing { get; set; }
- public bool IncludeIndexContainers { get; set; }
+ [ApiMember(Name = "IsUnaired", Description = "Optional filter by items that are unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
+ public bool? IsUnaired { get; set; }
+
+ [ApiMember(Name = "IsVirtualUnaired", Description = "Optional filter by items that are virtual unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
+ public bool? IsVirtualUnaired { get; set; }
}
///
@@ -270,6 +269,8 @@ namespace MediaBrowser.Api.UserLibrary
items = ApplyFilter(items, filter, user, _userDataRepository);
}
+ items = FilterVirtualEpisodes(request, items, user);
+
items = items.AsEnumerable();
items = ApplySearchTerm(request, items);
@@ -440,6 +441,121 @@ namespace MediaBrowser.Api.UserLibrary
return items;
}
+ private IEnumerable FilterVirtualEpisodes(GetItems request, IEnumerable items, User user)
+ {
+ items = FilterVirtualSeasons(request, items, user);
+
+ if (request.IsMissing.HasValue)
+ {
+ var val = request.IsMissing.Value;
+ items = items.Where(i =>
+ {
+ var e = i as Episode;
+ if (e != null)
+ {
+ return e.IsMissingEpisode == val;
+ }
+ return true;
+ });
+ }
+
+ if (request.IsUnaired.HasValue)
+ {
+ var val = request.IsUnaired.Value;
+ items = items.Where(i =>
+ {
+ var e = i as Episode;
+ if (e != null)
+ {
+ return e.IsUnaired == val;
+ }
+ return true;
+ });
+ }
+
+ if (request.IsVirtualUnaired.HasValue)
+ {
+ var val = request.IsVirtualUnaired.Value;
+ items = items.Where(i =>
+ {
+ var e = i as Episode;
+ if (e != null)
+ {
+ return e.IsVirtualUnaired == val;
+ }
+ return true;
+ });
+ }
+
+ return items;
+ }
+
+ private IEnumerable FilterVirtualSeasons(GetItems request, IEnumerable items, User user)
+ {
+ if (request.IsMissing.HasValue && request.IsUnaired.HasValue)
+ {
+ var isMissing = request.IsMissing.Value;
+ var isUnaired = request.IsUnaired.Value;
+
+ if (!isMissing && !isUnaired)
+ {
+ return items.Where(i =>
+ {
+ var e = i as Season;
+ if (e != null)
+ {
+ return !e.IsMissingOrVirtualUnaired;
+ }
+ return true;
+ });
+ }
+ }
+
+ if (request.IsMissing.HasValue)
+ {
+ var val = request.IsMissing.Value;
+ items = items.Where(i =>
+ {
+ var e = i as Season;
+ if (e != null)
+ {
+ return e.IsMissingSeason == val;
+ }
+ return true;
+ });
+ }
+
+ if (request.IsUnaired.HasValue)
+ {
+ var val = request.IsUnaired.Value;
+ items = items.Where(i =>
+ {
+ var e = i as Season;
+ if (e != null)
+ {
+ return e.IsUnaired == val;
+ }
+ return true;
+ });
+ }
+
+ if (request.IsVirtualUnaired.HasValue)
+ {
+ var val = request.IsVirtualUnaired.Value;
+ items = items.Where(i =>
+ {
+ var e = i as Season;
+ if (e != null)
+ {
+ return e.IsVirtualUnaired == val;
+ }
+ return true;
+ });
+ }
+
+ return items;
+ }
+
///
/// Applies the additional filters.
///
@@ -593,13 +709,6 @@ namespace MediaBrowser.Api.UserLibrary
items = items.Where(f => vals.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase));
}
- // ExcludeLocationTypes
- if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
- {
- var vals = request.ExcludeLocationTypes.Split(',');
- items = items.Where(f => !vals.Contains(f.LocationType.ToString(), StringComparer.OrdinalIgnoreCase));
- }
-
// LocationTypes
if (!string.IsNullOrEmpty(request.LocationTypes))
{
@@ -607,6 +716,13 @@ namespace MediaBrowser.Api.UserLibrary
items = items.Where(f => vals.Contains(f.LocationType.ToString(), StringComparer.OrdinalIgnoreCase));
}
+ // ExcludeLocationTypes
+ if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
+ {
+ var vals = request.ExcludeLocationTypes.Split(',');
+ items = items.Where(f => !vals.Contains(f.LocationType.ToString(), StringComparer.OrdinalIgnoreCase));
+ }
+
if (!string.IsNullOrEmpty(request.NameStartsWithOrGreater))
{
items = items.Where(i => string.Compare(request.NameStartsWithOrGreater, i.SortName, StringComparison.CurrentCultureIgnoreCase) < 1);
@@ -826,7 +942,8 @@ namespace MediaBrowser.Api.UserLibrary
if (request.IsHD.HasValue)
{
- items = items.OfType
private readonly ILogManager _logManager;
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
///
/// The logger.
/// The log manager.
- public LogFileWebSocketListener(ILogger logger, ILogManager logManager)
+ public LogFileWebSocketListener(ILogger logger, ILogManager logManager, IFileSystem fileSystem)
: base(logger)
{
_logManager = logManager;
+ _fileSystem = fileSystem;
_logManager.LoggerLoaded += kernel_LoggerLoaded;
}
@@ -53,7 +56,7 @@ namespace MediaBrowser.Api.WebSocket
state.StartLine = 0;
}
- var lines = await GetLogLines(state.LastLogFilePath, state.StartLine).ConfigureAwait(false);
+ var lines = await GetLogLines(state.LastLogFilePath, state.StartLine, _fileSystem).ConfigureAwait(false);
state.StartLine += lines.Count;
@@ -96,11 +99,11 @@ namespace MediaBrowser.Api.WebSocket
/// The log file path.
/// The start line.
/// Task{IEnumerable{System.String}}.
- internal static async Task> GetLogLines(string logFilePath, int startLine)
+ internal static async Task> GetLogLines(string logFilePath, int startLine, IFileSystem fileSystem)
{
var lines = new List();
- using (var fs = new FileStream(logFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, StreamDefaults.DefaultFileStreamBufferSize, true))
+ using (var fs = fileSystem.GetFileStream(logFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true))
{
using (var reader = new StreamReader(fs))
{
diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
index daa664a388..ee22b7baa2 100644
--- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
+++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
@@ -1,5 +1,4 @@
-using System.Net;
-using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Implementations.Archiving;
using MediaBrowser.Common.Implementations.IO;
@@ -7,6 +6,7 @@ using MediaBrowser.Common.Implementations.ScheduledTasks;
using MediaBrowser.Common.Implementations.Security;
using MediaBrowser.Common.Implementations.Serialization;
using MediaBrowser.Common.Implementations.Updates;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.ScheduledTasks;
@@ -21,6 +21,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Threading;
@@ -150,15 +151,17 @@ namespace MediaBrowser.Common.Implementations
/// Gets or sets the installation manager.
///
/// The installation manager.
- protected IInstallationManager InstallationManager { get; set; }
+ protected IInstallationManager InstallationManager { get; private set; }
+ protected IFileSystem FileSystemManager { get; private set; }
+
///
/// Gets or sets the zip client.
///
/// The zip client.
- protected IZipClient ZipClient { get; set; }
+ protected IZipClient ZipClient { get; private set; }
- protected IIsoManager IsoManager { get; set; }
+ protected IIsoManager IsoManager { get; private set; }
///
/// Initializes a new instance of the class.
@@ -347,7 +350,10 @@ namespace MediaBrowser.Common.Implementations
RegisterSingleInstance(TaskManager);
- HttpClient = new HttpClientManager.HttpClientManager(ApplicationPaths, Logger, CreateHttpClient);
+ FileSystemManager = CreateFileSystemManager();
+ RegisterSingleInstance(FileSystemManager);
+
+ HttpClient = new HttpClientManager.HttpClientManager(ApplicationPaths, Logger, CreateHttpClient, FileSystemManager);
RegisterSingleInstance(HttpClient);
NetworkManager = CreateNetworkManager();
@@ -367,6 +373,11 @@ namespace MediaBrowser.Common.Implementations
});
}
+ protected virtual IFileSystem CreateFileSystemManager()
+ {
+ return new CommonFileSystem(Logger, true);
+ }
+
protected abstract HttpClient CreateHttpClient(bool enableHttpCompression);
///
diff --git a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
index b75234107f..0d6ba5c1da 100644
--- a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
+++ b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
@@ -34,6 +34,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
public delegate HttpClient GetHttpClientHandler(bool enableHttpCompression);
private readonly GetHttpClientHandler _getHttpClientHandler;
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
@@ -46,7 +47,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
/// or
/// logger
///
- public HttpClientManager(IApplicationPaths appPaths, ILogger logger, GetHttpClientHandler getHttpClientHandler)
+ public HttpClientManager(IApplicationPaths appPaths, ILogger logger, GetHttpClientHandler getHttpClientHandler, IFileSystem fileSystem)
{
if (appPaths == null)
{
@@ -59,6 +60,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
_logger = logger;
_getHttpClientHandler = getHttpClientHandler;
+ _fileSystem = fileSystem;
_appPaths = appPaths;
}
@@ -417,7 +419,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
// We're not able to track progress
using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
{
- using (var fs = new FileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
+ using (var fs = _fileSystem.GetFileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
await stream.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false);
}
@@ -427,7 +429,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
{
using (var stream = ProgressStream.CreateReadProgressStream(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), options.Progress.Report, contentLength.Value))
{
- using (var fs = new FileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
+ using (var fs = _fileSystem.GetFileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
await stream.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Controller/IO/FileSystem.cs b/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs
similarity index 70%
rename from MediaBrowser.Controller/IO/FileSystem.cs
rename to MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs
index 1c49545be1..ed9baf3b2f 100644
--- a/MediaBrowser.Controller/IO/FileSystem.cs
+++ b/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs
@@ -1,122 +1,42 @@
-using System.Collections.Generic;
-using System.Linq;
+using MediaBrowser.Common.IO;
using MediaBrowser.Model.Logging;
using System;
-using System.Collections.Specialized;
using System.IO;
using System.Text;
-namespace MediaBrowser.Controller.IO
+namespace MediaBrowser.Common.Implementations.IO
{
///
- /// Class FileSystem
+ /// Class CommonFileSystem
///
- public static class FileSystem
+ public class CommonFileSystem : IFileSystem
{
- ///
- /// Gets the file system info.
- ///
- /// The path.
- /// FileSystemInfo.
- public static FileSystemInfo GetFileSystemInfo(string path)
- {
- // Take a guess to try and avoid two file system hits, but we'll double-check by calling Exists
- if (Path.HasExtension(path))
- {
- var fileInfo = new FileInfo(path);
-
- if (fileInfo.Exists)
- {
- return fileInfo;
- }
-
- return new DirectoryInfo(path);
- }
- else
- {
- var fileInfo = new DirectoryInfo(path);
-
- if (fileInfo.Exists)
- {
- return fileInfo;
- }
+ protected ILogger Logger;
- return new FileInfo(path);
- }
- }
+ private readonly bool _supportsAsyncFileStreams;
- ///
- /// Gets the creation time UTC.
- ///
- /// The info.
- /// The logger.
- /// DateTime.
- public static DateTime GetLastWriteTimeUtc(FileSystemInfo info, ILogger logger)
+ public CommonFileSystem(ILogger logger, bool supportsAsyncFileStreams)
{
- // This could throw an error on some file systems that have dates out of range
-
- try
- {
- return info.LastWriteTimeUtc;
- }
- catch (Exception ex)
- {
- logger.ErrorException("Error determining LastAccessTimeUtc for {0}", ex, info.FullName);
- return DateTime.MinValue;
- }
- }
-
- ///
- /// Gets the creation time UTC.
- ///
- /// The info.
- /// The logger.
- /// DateTime.
- public static DateTime GetCreationTimeUtc(FileSystemInfo info, ILogger logger)
- {
- // This could throw an error on some file systems that have dates out of range
-
- try
- {
- return info.CreationTimeUtc;
- }
- catch (Exception ex)
- {
- logger.ErrorException("Error determining CreationTimeUtc for {0}", ex, info.FullName);
- return DateTime.MinValue;
- }
+ Logger = logger;
+ _supportsAsyncFileStreams = supportsAsyncFileStreams;
}
///
- /// The space char
- ///
- private const char SpaceChar = ' ';
- ///
- /// The invalid file name chars
- ///
- private static readonly char[] InvalidFileNameChars = Path.GetInvalidFileNameChars();
-
- ///
- /// Takes a filename and removes invalid characters
+ /// Determines whether the specified filename is shortcut.
///
/// The filename.
- /// System.String.
+ /// true if the specified filename is shortcut; otherwise, false.
/// filename
- public static string GetValidFilename(string filename)
+ public virtual bool IsShortcut(string filename)
{
if (string.IsNullOrEmpty(filename))
{
throw new ArgumentNullException("filename");
}
- var builder = new StringBuilder(filename);
-
- foreach (var c in InvalidFileNameChars)
- {
- builder = builder.Replace(c, SpaceChar);
- }
+ var extension = Path.GetExtension(filename);
- return builder.ToString();
+ return string.Equals(extension, ".mblink", StringComparison.OrdinalIgnoreCase);
}
///
@@ -125,7 +45,7 @@ namespace MediaBrowser.Controller.IO
/// The filename.
/// System.String.
/// filename
- public static string ResolveShortcut(string filename)
+ public virtual string ResolveShortcut(string filename)
{
if (string.IsNullOrEmpty(filename))
{
@@ -137,25 +57,20 @@ namespace MediaBrowser.Controller.IO
return File.ReadAllText(filename);
}
- //return new WindowsShortcut(filename).ResolvedPath;
-
- var link = new ShellLink();
- ((IPersistFile)link).Load(filename, NativeMethods.STGM_READ);
- // TODO: if I can get hold of the hwnd call resolve first. This handles moved and renamed files.
- // ((IShellLinkW)link).Resolve(hwnd, 0)
- var sb = new StringBuilder(NativeMethods.MAX_PATH);
- WIN32_FIND_DATA data;
- ((IShellLinkW)link).GetPath(sb, sb.Capacity, out data, 0);
- return sb.ToString();
+ return null;
}
///
- /// Creates a shortcut file pointing to a specified path
+ /// Creates the shortcut.
///
/// The shortcut path.
/// The target.
- /// shortcutPath
- public static void CreateShortcut(string shortcutPath, string target)
+ ///
+ /// shortcutPath
+ /// or
+ /// target
+ ///
+ public void CreateShortcut(string shortcutPath, string target)
{
if (string.IsNullOrEmpty(shortcutPath))
{
@@ -168,96 +83,138 @@ namespace MediaBrowser.Controller.IO
}
File.WriteAllText(shortcutPath, target);
+ }
- //var link = new ShellLink();
+ ///
+ /// Gets the file system info.
+ ///
+ /// The path.
+ /// FileSystemInfo.
+ public FileSystemInfo GetFileSystemInfo(string path)
+ {
+ // Take a guess to try and avoid two file system hits, but we'll double-check by calling Exists
+ if (Path.HasExtension(path))
+ {
+ var fileInfo = new FileInfo(path);
+
+ if (fileInfo.Exists)
+ {
+ return fileInfo;
+ }
- //((IShellLinkW)link).SetPath(target);
+ return new DirectoryInfo(path);
+ }
+ else
+ {
+ var fileInfo = new DirectoryInfo(path);
+
+ if (fileInfo.Exists)
+ {
+ return fileInfo;
+ }
- //((IPersistFile)link).Save(shortcutPath, true);
+ return new FileInfo(path);
+ }
}
- private static readonly Dictionary ShortcutExtensionsDictionary = new[] { ".mblink", ".lnk" }
- .ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
+ ///
+ /// The space char
+ ///
+ private const char SpaceChar = ' ';
+ ///
+ /// The invalid file name chars
+ ///
+ private static readonly char[] InvalidFileNameChars = Path.GetInvalidFileNameChars();
///
- /// Determines whether the specified filename is shortcut.
+ /// Takes a filename and removes invalid characters
///
/// The filename.
- /// true if the specified filename is shortcut; otherwise, false.
+ /// System.String.
/// filename
- public static bool IsShortcut(string filename)
+ public string GetValidFilename(string filename)
{
if (string.IsNullOrEmpty(filename))
{
throw new ArgumentNullException("filename");
}
- var extension = Path.GetExtension(filename);
+ var builder = new StringBuilder(filename);
- return !string.IsNullOrEmpty(extension) && ShortcutExtensionsDictionary.ContainsKey(extension);
+ foreach (var c in InvalidFileNameChars)
+ {
+ builder = builder.Replace(c, SpaceChar);
+ }
+
+ return builder.ToString();
}
///
- /// Copies all.
+ /// Gets the creation time UTC.
///
- /// The source.
- /// The target.
- /// source
- /// The source and target directories are the same
- public static void CopyAll(string source, string target)
+ /// The info.
+ /// DateTime.
+ public DateTime GetCreationTimeUtc(FileSystemInfo info)
{
- if (string.IsNullOrEmpty(source))
- {
- throw new ArgumentNullException("source");
- }
- if (string.IsNullOrEmpty(target))
+ // This could throw an error on some file systems that have dates out of range
+ try
{
- throw new ArgumentNullException("target");
+ return info.CreationTimeUtc;
}
-
- if (source.Equals(target, StringComparison.OrdinalIgnoreCase))
+ catch (Exception ex)
{
- throw new ArgumentException("The source and target directories are the same");
+ Logger.ErrorException("Error determining CreationTimeUtc for {0}", ex, info.FullName);
+ return DateTime.MinValue;
}
+ }
- // Check if the target directory exists, if not, create it.
- Directory.CreateDirectory(target);
-
- foreach (var file in Directory.EnumerateFiles(source))
+ ///
+ /// Gets the creation time UTC.
+ ///
+ /// The info.
+ /// The logger.
+ /// DateTime.
+ public DateTime GetLastWriteTimeUtc(FileSystemInfo info)
+ {
+ // This could throw an error on some file systems that have dates out of range
+ try
{
- File.Copy(file, Path.Combine(target, Path.GetFileName(file)), true);
+ return info.LastWriteTimeUtc;
}
-
- // Copy each subdirectory using recursion.
- foreach (var dir in Directory.EnumerateDirectories(source))
+ catch (Exception ex)
{
- CopyAll(dir, Path.Combine(target, Path.GetFileName(dir)));
+ Logger.ErrorException("Error determining LastAccessTimeUtc for {0}", ex, info.FullName);
+ return DateTime.MinValue;
}
}
///
- /// Parses the ini file.
+ /// Gets the last write time UTC.
///
/// The path.
- /// NameValueCollection.
- public static NameValueCollection ParseIniFile(string path)
+ /// DateTime.
+ public DateTime GetLastWriteTimeUtc(string path)
{
- var values = new NameValueCollection();
+ return GetLastWriteTimeUtc(GetFileSystemInfo(path));
+ }
- foreach (var line in File.ReadAllLines(path))
+ ///
+ /// Gets the file stream.
+ ///
+ /// The path.
+ /// The mode.
+ /// The access.
+ /// The share.
+ /// if set to true [is asynchronous].
+ /// FileStream.
+ public FileStream GetFileStream(string path, FileMode mode, FileAccess access, FileShare share, bool isAsync = false)
+ {
+ if (_supportsAsyncFileStreams && isAsync)
{
- var data = line.Split('=');
-
- if (data.Length < 2) continue;
-
- var key = data[0];
-
- var value = data.Length == 2 ? data[1] : string.Join(string.Empty, data, 1, data.Length - 1);
-
- values[key] = value;
+ return new FileStream(path, mode, access, share, 4096, true);
}
- return values;
+ return new FileStream(path, mode, access, share);
}
}
@@ -381,4 +338,5 @@ namespace MediaBrowser.Controller.IO
}
}
+
}
diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
index 3ec330d9ce..9e48f3b3e9 100644
--- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
+++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
@@ -44,6 +44,10 @@
..\packages\sharpcompress.0.10.1.3\lib\net40\SharpCompress.dll
+
+ False
+ ..\packages\SimpleInjector.2.3.6\lib\net40-client\SimpleInjector.dll
+
@@ -54,9 +58,6 @@
..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll
-
- ..\packages\SimpleInjector.2.3.5\lib\net40-client\SimpleInjector.dll
-
@@ -68,6 +69,7 @@
+
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
index 812269ea8a..e04cadfc5a 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
@@ -1,12 +1,13 @@
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Model.Logging;
namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
{
@@ -23,14 +24,17 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
private readonly ILogger _logger;
+ private readonly IFileSystem _fileSystem;
+
///
/// Initializes a new instance of the class.
///
/// The app paths.
- public DeleteCacheFileTask(IApplicationPaths appPaths, ILogger logger)
+ public DeleteCacheFileTask(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem)
{
ApplicationPaths = appPaths;
_logger = logger;
+ _fileSystem = fileSystem;
}
///
@@ -94,7 +98,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
private void DeleteCacheFilesFromDirectory(CancellationToken cancellationToken, string directory, DateTime minDateModified, IProgress progress)
{
var filesToDelete = new DirectoryInfo(directory).EnumerateFiles("*", SearchOption.AllDirectories)
- .Where(f => f.LastWriteTimeUtc < minDateModified)
+ .Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified)
.ToList();
var index = 0;
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs
index bfd626adbc..7c7833ae64 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.ScheduledTasks;
using System;
using System.Collections.Generic;
@@ -20,13 +21,16 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
/// The configuration manager.
private IConfigurationManager ConfigurationManager { get; set; }
+ private readonly IFileSystem _fileSystem;
+
///
/// Initializes a new instance of the class.
///
/// The configuration manager.
- public DeleteLogFileTask(IConfigurationManager configurationManager)
+ public DeleteLogFileTask(IConfigurationManager configurationManager, IFileSystem fileSystem)
{
ConfigurationManager = configurationManager;
+ _fileSystem = fileSystem;
}
///
@@ -58,7 +62,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
var minDateModified = DateTime.UtcNow.AddDays(-(ConfigurationManager.CommonConfiguration.LogFileRetentionDays));
var filesToDelete = new DirectoryInfo(ConfigurationManager.CommonApplicationPaths.LogDirectoryPath).EnumerateFileSystemInfos("*", SearchOption.AllDirectories)
- .Where(f => f.LastWriteTimeUtc < minDateModified)
+ .Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified)
.ToList();
var index = 0;
diff --git a/MediaBrowser.Common.Implementations/packages.config b/MediaBrowser.Common.Implementations/packages.config
index 8716325bf4..f2fe488309 100644
--- a/MediaBrowser.Common.Implementations/packages.config
+++ b/MediaBrowser.Common.Implementations/packages.config
@@ -3,5 +3,5 @@
-
+
\ No newline at end of file
diff --git a/MediaBrowser.Common/IO/IFileSystem.cs b/MediaBrowser.Common/IO/IFileSystem.cs
new file mode 100644
index 0000000000..d307b74e5d
--- /dev/null
+++ b/MediaBrowser.Common/IO/IFileSystem.cs
@@ -0,0 +1,78 @@
+using System;
+using System.IO;
+
+namespace MediaBrowser.Common.IO
+{
+ ///
+ /// Interface IFileSystem
+ ///
+ public interface IFileSystem
+ {
+ ///
+ /// Determines whether the specified filename is shortcut.
+ ///
+ /// The filename.
+ /// true if the specified filename is shortcut; otherwise, false.
+ bool IsShortcut(string filename);
+
+ ///
+ /// Resolves the shortcut.
+ ///
+ /// The filename.
+ /// System.String.
+ string ResolveShortcut(string filename);
+
+ ///
+ /// Creates the shortcut.
+ ///
+ /// The shortcut path.
+ /// The target.
+ void CreateShortcut(string shortcutPath, string target);
+
+ ///
+ /// Gets the file system info.
+ ///
+ /// The path.
+ /// FileSystemInfo.
+ FileSystemInfo GetFileSystemInfo(string path);
+
+ ///
+ /// Gets the valid filename.
+ ///
+ /// The filename.
+ /// System.String.
+ string GetValidFilename(string filename);
+
+ ///
+ /// Gets the creation time UTC.
+ ///
+ /// The info.
+ /// DateTime.
+ DateTime GetCreationTimeUtc(FileSystemInfo info);
+
+ ///
+ /// Gets the last write time UTC.
+ ///
+ /// The information.
+ /// DateTime.
+ DateTime GetLastWriteTimeUtc(FileSystemInfo info);
+
+ ///
+ /// Gets the last write time UTC.
+ ///
+ /// The path.
+ /// DateTime.
+ DateTime GetLastWriteTimeUtc(string path);
+
+ ///
+ /// Gets the file stream.
+ ///
+ /// The path.
+ /// The mode.
+ /// The access.
+ /// The share.
+ /// if set to true [is asynchronous].
+ /// FileStream.
+ FileStream GetFileStream(string path, FileMode mode, FileAccess access, FileShare share, bool isAsync = false);
+ }
+}
diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj
index 8acd1a83cb..f4d759a4d1 100644
--- a/MediaBrowser.Common/MediaBrowser.Common.csproj
+++ b/MediaBrowser.Common/MediaBrowser.Common.csproj
@@ -60,6 +60,7 @@
+
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 77cc541675..839fe34ffe 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.IO;
@@ -212,6 +213,7 @@ namespace MediaBrowser.Controller.Entities
public static IProviderManager ProviderManager { get; set; }
public static ILocalizationManager LocalizationManager { get; set; }
public static IItemRepository ItemRepository { get; set; }
+ public static IFileSystem FileSystem { get; set; }
///
/// Returns a that represents this instance.
@@ -395,7 +397,7 @@ namespace MediaBrowser.Controller.Entities
// When resolving the root, we need it's grandchildren (children of user views)
var flattenFolderDepth = isPhysicalRoot ? 2 : 0;
- args.FileSystemDictionary = FileData.GetFilteredFileSystemEntries(args.Path, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf);
+ args.FileSystemDictionary = FileData.GetFilteredFileSystemEntries(args.Path, FileSystem, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf);
// Need to remove subpaths that may have been resolved from shortcuts
// Example: if \\server\movies exists, then strip out \\server\movies\action
@@ -413,7 +415,7 @@ namespace MediaBrowser.Controller.Entities
}
//update our dates
- EntityResolutionHelper.EnsureDates(this, args, false);
+ EntityResolutionHelper.EnsureDates(FileSystem, this, args, false);
IsOffline = false;
@@ -1337,6 +1339,13 @@ namespace MediaBrowser.Controller.Entities
var data = userManager.GetUserData(user.Id, key);
+ if (datePlayed.HasValue)
+ {
+ // Incremenet
+ data.PlayCount++;
+ }
+
+ // Ensure it's at least one
data.PlayCount = Math.Max(data.PlayCount, 1);
data.LastPlayedDate = datePlayed ?? data.LastPlayedDate;
@@ -1530,7 +1539,8 @@ namespace MediaBrowser.Controller.Entities
}
// Refresh metadata
- return RefreshMetadata(CancellationToken.None, forceSave: true);
+ // Need to disable slow providers or the image might get re-downloaded
+ return RefreshMetadata(CancellationToken.None, forceSave: true, allowSlowProviders: false);
}
///
@@ -1728,7 +1738,7 @@ namespace MediaBrowser.Controller.Entities
if (locationType == LocationType.Remote ||
locationType == LocationType.Virtual)
{
- return File.GetLastWriteTimeUtc(imagePath);
+ return FileSystem.GetLastWriteTimeUtc(imagePath);
}
var metaFileEntry = ResolveArgs.GetMetaFileByPath(imagePath);
@@ -1745,7 +1755,7 @@ namespace MediaBrowser.Controller.Entities
}
// See if we can avoid a file system lookup by looking for the file in ResolveArgs
- return metaFileEntry == null ? File.GetLastWriteTimeUtc(imagePath) : metaFileEntry.LastWriteTimeUtc;
+ return metaFileEntry == null ? FileSystem.GetLastWriteTimeUtc(imagePath) : FileSystem.GetLastWriteTimeUtc(metaFileEntry);
}
}
}
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index c54b812420..a4ba146165 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -693,7 +693,7 @@ namespace MediaBrowser.Controller.Entities
//existing item - check if it has changed
if (currentChild.HasChanged(child))
{
- EntityResolutionHelper.EnsureDates(currentChild, child.ResolveArgs, false);
+ EntityResolutionHelper.EnsureDates(FileSystem, currentChild, child.ResolveArgs, false);
validChildren.Add(new Tuple(currentChild, true));
}
diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs
index 14c6554556..96b120b8fe 100644
--- a/MediaBrowser.Controller/Entities/TV/Episode.cs
+++ b/MediaBrowser.Controller/Entities/TV/Episode.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
@@ -191,5 +192,23 @@ namespace MediaBrowser.Controller.Entities.TV
return false;
}
+
+ public bool IsMissingEpisode
+ {
+ get
+ {
+ return LocationType == Model.Entities.LocationType.Virtual && PremiereDate.HasValue && PremiereDate.Value < DateTime.UtcNow;
+ }
+ }
+
+ public bool IsUnaired
+ {
+ get { return PremiereDate.HasValue && PremiereDate.Value.ToLocalTime().Date >= DateTime.Now.Date; }
+ }
+
+ public bool IsVirtualUnaired
+ {
+ get { return LocationType == Model.Entities.LocationType.Virtual && IsUnaired; }
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs
index 9f15de920a..5a53e8c0fe 100644
--- a/MediaBrowser.Controller/Entities/TV/Season.cs
+++ b/MediaBrowser.Controller/Entities/TV/Season.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Library;
+using System.Linq;
+using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Localization;
using System;
using System.Collections.Generic;
@@ -147,5 +148,25 @@ namespace MediaBrowser.Controller.Entities.TV
{
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
}
+
+ public bool IsMissingSeason
+ {
+ get { return LocationType == Model.Entities.LocationType.Virtual && Children.OfType().All(i => i.IsMissingEpisode); }
+ }
+
+ public bool IsUnaired
+ {
+ get { return Children.OfType().All(i => i.IsUnaired); }
+ }
+
+ public bool IsVirtualUnaired
+ {
+ get { return LocationType == Model.Entities.LocationType.Virtual && IsUnaired; }
+ }
+
+ public bool IsMissingOrVirtualUnaired
+ {
+ get { return LocationType == Model.Entities.LocationType.Virtual && Children.OfType().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); }
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs
index 9d85399067..06f50e552b 100644
--- a/MediaBrowser.Controller/Entities/User.cs
+++ b/MediaBrowser.Controller/Entities/User.cs
@@ -165,7 +165,7 @@ namespace MediaBrowser.Controller.Entities
// Ensure it's been lazy loaded
var config = Configuration;
- return File.GetLastWriteTimeUtc(ConfigurationFilePath);
+ return FileSystem.GetLastWriteTimeUtc(ConfigurationFilePath);
}
}
diff --git a/MediaBrowser.Controller/IO/FileData.cs b/MediaBrowser.Controller/IO/FileData.cs
index b1fc28e7b7..270afd89a1 100644
--- a/MediaBrowser.Controller/IO/FileData.cs
+++ b/MediaBrowser.Controller/IO/FileData.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Library;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
@@ -15,6 +16,7 @@ namespace MediaBrowser.Controller.IO
/// Gets the filtered file system entries.
///
/// The path.
+ /// The file system.
/// The logger.
/// The args.
/// The search pattern.
@@ -22,7 +24,7 @@ namespace MediaBrowser.Controller.IO
/// if set to true [resolve shortcuts].
/// Dictionary{System.StringFileSystemInfo}.
/// path
- public static Dictionary GetFilteredFileSystemEntries(string path, ILogger logger, ItemResolveArgs args, string searchPattern = "*", int flattenFolderDepth = 0, bool resolveShortcuts = true)
+ public static Dictionary GetFilteredFileSystemEntries(string path, IFileSystem fileSystem, ILogger logger, ItemResolveArgs args, string searchPattern = "*", int flattenFolderDepth = 0, bool resolveShortcuts = true)
{
if (string.IsNullOrEmpty(path))
{
@@ -56,9 +58,9 @@ namespace MediaBrowser.Controller.IO
var fullName = entry.FullName;
- if (resolveShortcuts && FileSystem.IsShortcut(fullName))
+ if (resolveShortcuts && fileSystem.IsShortcut(fullName))
{
- var newPath = FileSystem.ResolveShortcut(fullName);
+ var newPath = fileSystem.ResolveShortcut(fullName);
if (string.IsNullOrWhiteSpace(newPath))
{
@@ -77,7 +79,7 @@ namespace MediaBrowser.Controller.IO
}
else if (flattenFolderDepth > 0 && isDirectory)
{
- foreach (var child in GetFilteredFileSystemEntries(fullName, logger, args, flattenFolderDepth: flattenFolderDepth - 1, resolveShortcuts: resolveShortcuts))
+ foreach (var child in GetFilteredFileSystemEntries(fullName, fileSystem, logger, args, flattenFolderDepth: flattenFolderDepth - 1, resolveShortcuts: resolveShortcuts))
{
dict[child.Key] = child.Value;
}
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 8154cb0a28..978d56bd4e 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -108,6 +108,7 @@
+
@@ -139,9 +140,7 @@
-
-
diff --git a/MediaBrowser.Controller/MediaInfo/FFMpegManager.cs b/MediaBrowser.Controller/MediaInfo/FFMpegManager.cs
index 87036df84e..fd1b12c2f2 100644
--- a/MediaBrowser.Controller/MediaInfo/FFMpegManager.cs
+++ b/MediaBrowser.Controller/MediaInfo/FFMpegManager.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -35,6 +36,8 @@ namespace MediaBrowser.Controller.MediaInfo
private readonly ILogger _logger;
private readonly IItemRepository _itemRepo;
+ private readonly IFileSystem _fileSystem;
+
///
/// Initializes a new instance of the class.
///
@@ -43,12 +46,13 @@ namespace MediaBrowser.Controller.MediaInfo
/// The logger.
/// The item repo.
/// zipClient
- public FFMpegManager(IServerApplicationPaths appPaths, IMediaEncoder encoder, ILogger logger, IItemRepository itemRepo)
+ public FFMpegManager(IServerApplicationPaths appPaths, IMediaEncoder encoder, ILogger logger, IItemRepository itemRepo, IFileSystem fileSystem)
{
_appPaths = appPaths;
_encoder = encoder;
_logger = logger;
_itemRepo = itemRepo;
+ _fileSystem = fileSystem;
VideoImageCache = new FileSystemRepository(VideoImagesDataPath);
SubtitleCache = new FileSystemRepository(SubtitleCachePath);
@@ -203,7 +207,7 @@ namespace MediaBrowser.Controller.MediaInfo
if (stream.IsExternal)
{
- ticksParam += File.GetLastWriteTimeUtc(stream.Path).Ticks;
+ ticksParam += _fileSystem.GetLastWriteTimeUtc(stream.Path).Ticks;
}
return SubtitleCache.GetResourcePath(input.Id + "_" + subtitleStreamIndex + "_" + input.DateModified.Ticks + ticksParam, outputExtension);
diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
index e1b38bc714..e9bb7f66d9 100644
--- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
+++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
@@ -552,32 +552,6 @@ namespace MediaBrowser.Controller.Providers
}
break;
- case "GamesDbId":
- var gamesdbId = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(gamesdbId))
- {
- item.SetProviderId(MetadataProviders.Gamesdb, gamesdbId);
- }
- break;
-
- case "Players":
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- int num;
-
- if (int.TryParse(val, NumberStyles.Integer, _usCulture, out num))
- {
- var game = item as Game;
- if (game != null)
- {
- game.PlayersSupported = num;
- }
- }
- }
- break;
- }
case "VoteCount":
{
var val = reader.ReadElementContentAsString();
@@ -592,19 +566,6 @@ namespace MediaBrowser.Controller.Providers
}
break;
}
- case "GameSystem":
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- var game = item as Game;
- if (game != null)
- {
- game.GameSystem = val;
- }
- }
- break;
- }
case "MusicbrainzId":
{
var mbz = reader.ReadElementContentAsString();
diff --git a/MediaBrowser.Controller/Providers/IImageProvider.cs b/MediaBrowser.Controller/Providers/IImageProvider.cs
new file mode 100644
index 0000000000..0764794388
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/IImageProvider.cs
@@ -0,0 +1,38 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Providers
+{
+ ///
+ /// Interface IImageProvider
+ ///
+ public interface IImageProvider
+ {
+ ///
+ /// Gets the name.
+ ///
+ /// The name.
+ string Name { get; }
+
+ ///
+ /// Supportses the specified item.
+ ///
+ /// The item.
+ /// Type of the image.
+ /// true if XXXX, false otherwise
+ bool Supports(BaseItem item, ImageType imageType);
+
+ ///
+ /// Gets the available images.
+ ///
+ /// The item.
+ /// Type of the image.
+ /// The cancellation token.
+ /// Task{IEnumerable{RemoteImageInfo}}.
+ Task> GetAvailableImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken);
+ }
+}
diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs
index 6a4d132b76..2eb2be6db1 100644
--- a/MediaBrowser.Controller/Providers/IProviderManager.cs
+++ b/MediaBrowser.Controller/Providers/IProviderManager.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
using System.Collections.Generic;
using System.IO;
using System.Threading;
@@ -52,6 +53,16 @@ namespace MediaBrowser.Controller.Providers
/// Adds the metadata providers.
///
/// The providers.
- void AddParts(IEnumerable providers);
+ /// The image providers.
+ void AddParts(IEnumerable providers, IEnumerable imageProviders);
+
+ ///
+ /// Gets the available remote images.
+ ///
+ /// The item.
+ /// The type.
+ /// The cancellation token.
+ /// Task{IEnumerable{RemoteImageInfo}}.
+ Task> GetAvailableRemoteImages(BaseItem item, ImageType type, CancellationToken cancellationToken);
}
}
\ No newline at end of file
diff --git a/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs b/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs
index 1b3aba1026..1e4fabc7c2 100644
--- a/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs
+++ b/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using System;
@@ -44,7 +45,8 @@ namespace MediaBrowser.Controller.Resolvers
".f4v",
".3gp",
".webm",
- ".mts"
+ ".mts",
+ ".rec"
};
private static readonly Dictionary VideoFileExtensionsDictionary = VideoFileExtensions.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
@@ -125,10 +127,11 @@ namespace MediaBrowser.Controller.Resolvers
///
/// Ensures DateCreated and DateModified have values
///
+ /// The file system.
/// The item.
/// The args.
/// if set to true [include creation time].
- public static void EnsureDates(BaseItem item, ItemResolveArgs args, bool includeCreationTime)
+ public static void EnsureDates(IFileSystem fileSystem, BaseItem item, ItemResolveArgs args, bool includeCreationTime)
{
if (!Path.IsPathRooted(item.Path))
{
@@ -144,22 +147,22 @@ namespace MediaBrowser.Controller.Resolvers
{
if (includeCreationTime)
{
- item.DateCreated = childData.CreationTimeUtc;
+ item.DateCreated = fileSystem.GetCreationTimeUtc(childData);
}
- item.DateModified = childData.LastWriteTimeUtc;
+ item.DateModified = fileSystem.GetLastWriteTimeUtc(childData);
}
else
{
- var fileData = FileSystem.GetFileSystemInfo(item.Path);
+ var fileData = fileSystem.GetFileSystemInfo(item.Path);
if (fileData.Exists)
{
if (includeCreationTime)
{
- item.DateCreated = fileData.CreationTimeUtc;
+ item.DateCreated = fileSystem.GetCreationTimeUtc(fileData);
}
- item.DateModified = fileData.LastWriteTimeUtc;
+ item.DateModified = fileSystem.GetLastWriteTimeUtc(fileData);
}
}
}
@@ -167,9 +170,9 @@ namespace MediaBrowser.Controller.Resolvers
{
if (includeCreationTime)
{
- item.DateCreated = args.FileInfo.CreationTimeUtc;
+ item.DateCreated = fileSystem.GetCreationTimeUtc(args.FileInfo);
}
- item.DateModified = args.FileInfo.LastWriteTimeUtc;
+ item.DateModified = fileSystem.GetLastWriteTimeUtc(args.FileInfo);
}
}
}
diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
index 9027a814e2..8a6197857d 100644
--- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
+++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
@@ -290,6 +290,9 @@
Plugins\PluginInfo.cs
+
+ Providers\RemoteImageInfo.cs
+
Querying\ArtistsQuery.cs
diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
index e13c348e04..dfff0356bc 100644
--- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
+++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
@@ -277,6 +277,9 @@
Plugins\PluginInfo.cs
+
+ Providers\RemoteImageInfo.cs
+
Querying\ArtistsQuery.cs
diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs
index d88474d61d..b736474e0d 100644
--- a/MediaBrowser.Model/Configuration/UserConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs
@@ -56,16 +56,18 @@ namespace MediaBrowser.Model.Configuration
public bool IsDisabled { get; set; }
- public bool DisplayVirtualEpisodes { get; set; }
-
+ public bool DisplayMissingEpisodes { get; set; }
+ public bool DisplayUnairedEpisodes { get; set; }
+ public bool EnableRemoteControlOfOtherUsers { get; set; }
+
///
/// Initializes a new instance of the class.
///
public UserConfiguration()
{
IsAdministrator = true;
+ EnableRemoteControlOfOtherUsers = true;
BlockNotRated = false;
- DisplayVirtualEpisodes = true;
}
}
}
diff --git a/MediaBrowser.Model/Entities/MetadataProviders.cs b/MediaBrowser.Model/Entities/MetadataProviders.cs
index b508be13b2..5ef449317f 100644
--- a/MediaBrowser.Model/Entities/MetadataProviders.cs
+++ b/MediaBrowser.Model/Entities/MetadataProviders.cs
@@ -36,6 +36,8 @@ namespace MediaBrowser.Model.Entities
///
TmdbCollection,
MusicBrainzReleaseGroup,
- Zap2It
+ Zap2It,
+ NesBox,
+ NesBoxRom
}
}
diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj
index b49368cf73..fc3b270f6b 100644
--- a/MediaBrowser.Model/MediaBrowser.Model.csproj
+++ b/MediaBrowser.Model/MediaBrowser.Model.csproj
@@ -59,6 +59,7 @@
+
diff --git a/MediaBrowser.Model/Providers/RemoteImageInfo.cs b/MediaBrowser.Model/Providers/RemoteImageInfo.cs
new file mode 100644
index 0000000000..1a281f07d2
--- /dev/null
+++ b/MediaBrowser.Model/Providers/RemoteImageInfo.cs
@@ -0,0 +1,59 @@
+
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Model.Providers
+{
+ ///
+ /// Class RemoteImageInfo
+ ///
+ public class RemoteImageInfo
+ {
+ ///
+ /// Gets or sets the name of the provider.
+ ///
+ /// The name of the provider.
+ public string ProviderName { get; set; }
+
+ ///
+ /// Gets or sets the URL.
+ ///
+ /// The URL.
+ public string Url { get; set; }
+
+ ///
+ /// Gets or sets the height.
+ ///
+ /// The height.
+ public int? Height { get; set; }
+
+ ///
+ /// Gets or sets the width.
+ ///
+ /// The width.
+ public int? Width { get; set; }
+
+ ///
+ /// Gets or sets the community rating.
+ ///
+ /// The community rating.
+ public double? CommunityRating { get; set; }
+
+ ///
+ /// Gets or sets the vote count.
+ ///
+ /// The vote count.
+ public int? VoteCount { get; set; }
+
+ ///
+ /// Gets or sets the language.
+ ///
+ /// The language.
+ public string Language { get; set; }
+
+ ///
+ /// Gets or sets the type.
+ ///
+ /// The type.
+ public ImageType Type { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Querying/ItemQuery.cs b/MediaBrowser.Model/Querying/ItemQuery.cs
index d351474eb7..f4a1d20d2d 100644
--- a/MediaBrowser.Model/Querying/ItemQuery.cs
+++ b/MediaBrowser.Model/Querying/ItemQuery.cs
@@ -241,16 +241,27 @@ namespace MediaBrowser.Model.Querying
///
/// The location types.
public LocationType[] LocationTypes { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether this instance is missing episode.
+ ///
+ /// null if [is missing episode] contains no value, true if [is missing episode]; otherwise, false.
+ public bool? IsMissing { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether this instance is unaired episode.
+ ///
+ /// null if [is unaired episode] contains no value, true if [is unaired episode]; otherwise, false.
+ public bool? IsUnaired { get; set; }
+
+ public bool? IsVirtualUnaired { get; set; }
+
///
/// Gets or sets the exclude location types.
///
/// The exclude location types.
public LocationType[] ExcludeLocationTypes { get; set; }
-
- public bool? HasPremiereDate { get; set; }
- public DateTime? MinPremiereDate { get; set; }
- public DateTime? MaxPremiereDate { get; set; }
-
+
///
/// Initializes a new instance of the class.
///
diff --git a/MediaBrowser.Model/Querying/NextUpQuery.cs b/MediaBrowser.Model/Querying/NextUpQuery.cs
index 1b7b45ca30..4f5d47a04e 100644
--- a/MediaBrowser.Model/Querying/NextUpQuery.cs
+++ b/MediaBrowser.Model/Querying/NextUpQuery.cs
@@ -1,6 +1,4 @@
-using MediaBrowser.Model.Entities;
-using System;
-
+
namespace MediaBrowser.Model.Querying
{
public class NextUpQuery
@@ -11,6 +9,12 @@ namespace MediaBrowser.Model.Querying
/// The user id.
public string UserId { get; set; }
+ ///
+ /// Gets or sets the series id.
+ ///
+ /// The series id.
+ public string SeriesId { get; set; }
+
///
/// Skips over a given number of items within the results. Use for paging.
///
@@ -28,20 +32,5 @@ namespace MediaBrowser.Model.Querying
///
/// The fields.
public ItemFields[] Fields { get; set; }
-
- ///
- /// Gets or sets the exclude location types.
- ///
- /// The exclude location types.
- public LocationType[] ExcludeLocationTypes { get; set; }
-
- public bool? HasPremiereDate { get; set; }
- public DateTime? MinPremiereDate { get; set; }
- public DateTime? MaxPremiereDate { get; set; }
-
- public NextUpQuery()
- {
- ExcludeLocationTypes = new LocationType[] { };
- }
}
}
diff --git a/MediaBrowser.Mono.userprefs b/MediaBrowser.Mono.userprefs
index 4378247fd4..f1260b1dad 100644
--- a/MediaBrowser.Mono.userprefs
+++ b/MediaBrowser.Mono.userprefs
@@ -1,25 +1,24 @@
-
+
-
+
+
+
-
-
-
-
-
-
+
+
+
-
+
diff --git a/MediaBrowser.Providers/FolderProviderFromXml.cs b/MediaBrowser.Providers/FolderProviderFromXml.cs
index 2a22d04482..449de7450d 100644
--- a/MediaBrowser.Providers/FolderProviderFromXml.cs
+++ b/MediaBrowser.Providers/FolderProviderFromXml.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Providers;
@@ -17,10 +18,12 @@ namespace MediaBrowser.Providers
public class FolderProviderFromXml : BaseMetadataProvider
{
public static FolderProviderFromXml Current;
+ private readonly IFileSystem _fileSystem;
- public FolderProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager)
+ public FolderProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
+ _fileSystem = fileSystem;
Current = this;
}
@@ -53,7 +56,7 @@ namespace MediaBrowser.Providers
return false;
}
- return FileSystem.GetLastWriteTimeUtc(xml, Logger) > providerInfo.LastRefreshed;
+ return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed;
}
///
diff --git a/MediaBrowser.Providers/Games/GameProviderFromXml.cs b/MediaBrowser.Providers/Games/GameProviderFromXml.cs
index 6292cec465..724e3f5fa0 100644
--- a/MediaBrowser.Providers/Games/GameProviderFromXml.cs
+++ b/MediaBrowser.Providers/Games/GameProviderFromXml.cs
@@ -1,27 +1,30 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Providers.Savers;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Providers.Savers;
namespace MediaBrowser.Providers.Games
{
public class GameProviderFromXml : BaseMetadataProvider
{
+ private readonly IFileSystem _fileSystem;
+
///
///
///
///
///
- public GameProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager)
+ public GameProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
-
+ _fileSystem = fileSystem;
}
///
@@ -45,7 +48,7 @@ namespace MediaBrowser.Providers.Games
return false;
}
- return FileSystem.GetLastWriteTimeUtc(xml, Logger) > providerInfo.LastRefreshed;
+ return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed;
}
///
@@ -78,7 +81,7 @@ namespace MediaBrowser.Providers.Games
try
{
- new BaseItemXmlParser(Logger).Fetch(game, metaFile, cancellationToken);
+ new GameXmlParser(Logger).Fetch(game, metaFile, cancellationToken);
}
finally
{
diff --git a/MediaBrowser.Providers/Games/GameSystemProviderFromXml.cs b/MediaBrowser.Providers/Games/GameSystemProviderFromXml.cs
index 526170db54..0c9d55a094 100644
--- a/MediaBrowser.Providers/Games/GameSystemProviderFromXml.cs
+++ b/MediaBrowser.Providers/Games/GameSystemProviderFromXml.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Providers;
@@ -14,10 +15,12 @@ namespace MediaBrowser.Providers.Games
public class GameSystemProviderFromXml : BaseMetadataProvider
{
internal static GameSystemProviderFromXml Current { get; private set; }
+ private readonly IFileSystem _fileSystem;
- public GameSystemProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager)
+ public GameSystemProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
+ _fileSystem = fileSystem;
Current = this;
}
@@ -50,7 +53,7 @@ namespace MediaBrowser.Providers.Games
return false;
}
- return FileSystem.GetLastWriteTimeUtc(xml, Logger) > providerInfo.LastRefreshed;
+ return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed;
}
///
diff --git a/MediaBrowser.Providers/Games/GameXmlParser.cs b/MediaBrowser.Providers/Games/GameXmlParser.cs
new file mode 100644
index 0000000000..53cc123884
--- /dev/null
+++ b/MediaBrowser.Providers/Games/GameXmlParser.cs
@@ -0,0 +1,110 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using System.Globalization;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace MediaBrowser.Providers.Games
+{
+ ///
+ /// Class EpisodeXmlParser
+ ///
+ public class GameXmlParser : BaseItemXmlParser
+ {
+ private Task _chaptersTask = null;
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+
+ public GameXmlParser(ILogger logger)
+ : base(logger)
+ {
+ }
+
+ public async Task FetchAsync(Game item, string metadataFile, CancellationToken cancellationToken)
+ {
+ _chaptersTask = null;
+
+ Fetch(item, metadataFile, cancellationToken);
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (_chaptersTask != null)
+ {
+ await _chaptersTask.ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Fetches the data from XML node.
+ ///
+ /// The reader.
+ /// The item.
+ protected override void FetchDataFromXmlNode(XmlReader reader, Game item)
+ {
+ switch (reader.Name)
+ {
+ case "GameSystem":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.GameSystem = val;
+ }
+ break;
+ }
+
+ case "GamesDbId":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.SetProviderId(MetadataProviders.Gamesdb, val);
+ }
+ break;
+ }
+
+ case "NesBox":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.SetProviderId(MetadataProviders.NesBox, val);
+ }
+ break;
+ }
+
+ case "NesBoxRom":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.SetProviderId(MetadataProviders.NesBoxRom, val);
+ }
+ break;
+ }
+
+ case "Players":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int num;
+
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out num))
+ {
+ item.PlayersSupported = num;
+ }
+ }
+ break;
+ }
+
+
+ default:
+ base.FetchDataFromXmlNode(reader, item);
+ break;
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/ImagesByNameProvider.cs b/MediaBrowser.Providers/ImagesByNameProvider.cs
index e4bfee6e33..6be4ee108b 100644
--- a/MediaBrowser.Providers/ImagesByNameProvider.cs
+++ b/MediaBrowser.Providers/ImagesByNameProvider.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.IO;
@@ -18,9 +19,12 @@ namespace MediaBrowser.Providers
///
public class ImagesByNameProvider : ImageFromMediaLocationProvider
{
- public ImagesByNameProvider(ILogManager logManager, IServerConfigurationManager configurationManager)
+ private readonly IFileSystem _fileSystem;
+
+ public ImagesByNameProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
+ _fileSystem = fileSystem;
}
public override ItemUpdateType ItemUpdateType
@@ -110,8 +114,8 @@ namespace MediaBrowser.Providers
return files.Select(f =>
{
- var lastWriteTime = FileSystem.GetLastWriteTimeUtc(f, Logger);
- var creationTime = FileSystem.GetCreationTimeUtc(f, Logger);
+ var lastWriteTime = _fileSystem.GetLastWriteTimeUtc(f);
+ var creationTime = _fileSystem.GetCreationTimeUtc(f);
return creationTime > lastWriteTime ? creationTime : lastWriteTime;
@@ -150,7 +154,7 @@ namespace MediaBrowser.Providers
/// System.String.
protected string GetLocation(BaseItem item)
{
- var name = FileSystem.GetValidFilename(item.Name);
+ var name = _fileSystem.GetValidFilename(item.Name);
return Path.Combine(ConfigurationManager.ApplicationPaths.GeneralPath, name);
}
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index e687e14d9d..7a8975937d 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -49,6 +49,7 @@
+
@@ -59,6 +60,7 @@
+
diff --git a/MediaBrowser.Providers/Movies/BoxSetProviderFromXml.cs b/MediaBrowser.Providers/Movies/BoxSetProviderFromXml.cs
index e697738fe5..0b2502ba9f 100644
--- a/MediaBrowser.Providers/Movies/BoxSetProviderFromXml.cs
+++ b/MediaBrowser.Providers/Movies/BoxSetProviderFromXml.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.IO;
@@ -18,10 +19,12 @@ namespace MediaBrowser.Providers.Movies
public class BoxSetProviderFromXml : BaseMetadataProvider
{
public static BoxSetProviderFromXml Current;
+ private readonly IFileSystem _fileSystem;
- public BoxSetProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager)
+ public BoxSetProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
+ _fileSystem = fileSystem;
Current = this;
}
@@ -54,7 +57,7 @@ namespace MediaBrowser.Providers.Movies
return false;
}
- return FileSystem.GetLastWriteTimeUtc(xml, Logger) > providerInfo.LastRefreshed;
+ return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed;
}
///
diff --git a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs
index f34988481e..3458622d34 100644
--- a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs
+++ b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
@@ -40,6 +41,7 @@ namespace MediaBrowser.Providers.Movies
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
internal static FanArtMovieProvider Current { get; private set; }
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
@@ -49,7 +51,7 @@ namespace MediaBrowser.Providers.Movies
/// The configuration manager.
/// The provider manager.
/// httpClient
- public FanArtMovieProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
+ public FanArtMovieProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
if (httpClient == null)
@@ -58,6 +60,7 @@ namespace MediaBrowser.Providers.Movies
}
HttpClient = httpClient;
_providerManager = providerManager;
+ _fileSystem = fileSystem;
Current = this;
}
@@ -174,7 +177,7 @@ namespace MediaBrowser.Providers.Movies
{
var files = new DirectoryInfo(path)
.EnumerateFiles("*.xml", SearchOption.TopDirectoryOnly)
- .Select(i => i.LastWriteTimeUtc)
+ .Select(i => _fileSystem.GetLastWriteTimeUtc(i))
.ToList();
if (files.Count > 0)
@@ -275,7 +278,7 @@ namespace MediaBrowser.Providers.Movies
}).ConfigureAwait(false))
{
- using (var xmlFileStream = new FileStream(xmlPath, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
+ using (var xmlFileStream = _fileSystem.GetFileStream(xmlPath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
await response.CopyToAsync(xmlFileStream).ConfigureAwait(false);
}
@@ -300,14 +303,14 @@ namespace MediaBrowser.Providers.Movies
string path;
- if (ConfigurationManager.Configuration.DownloadMovieImages.Disc && !item.HasImage(ImageType.Disc))
+ if (ConfigurationManager.Configuration.DownloadMovieImages.Primary && !item.HasImage(ImageType.Primary))
{
var node = doc.SelectSingleNode("//fanart/movie/movieposters/movieposter[@lang = \"" + language + "\"]/@url") ??
doc.SelectSingleNode("//fanart/movie/movieposters/movieposter/@url");
path = node != null ? node.Value : null;
if (!string.IsNullOrEmpty(path))
{
- await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Disc, null, cancellationToken)
+ await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Primary, null, cancellationToken)
.ConfigureAwait(false);
}
}
diff --git a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs
index 51b77599e2..706dffa7e0 100644
--- a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs
+++ b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
@@ -32,15 +33,17 @@ namespace MediaBrowser.Providers.Movies
///
private readonly IServerConfigurationManager _config;
private readonly IJsonSerializer _jsonSerializer;
+ private readonly IFileSystem _fileSystem;
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
- public FanArtMovieUpdatesPrescanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient)
+ public FanArtMovieUpdatesPrescanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem)
{
_jsonSerializer = jsonSerializer;
_config = config;
_logger = logger;
_httpClient = httpClient;
+ _fileSystem = fileSystem;
}
///
@@ -66,7 +69,7 @@ namespace MediaBrowser.Providers.Movies
var timestampFileInfo = new FileInfo(timestampFile);
// Don't check for tvdb updates anymore frequently than 24 hours
- if (timestampFileInfo.Exists && (DateTime.UtcNow - timestampFileInfo.LastWriteTimeUtc).TotalDays < 1)
+ if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 1)
{
return;
}
diff --git a/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs b/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs
new file mode 100644
index 0000000000..f84845af7d
--- /dev/null
+++ b/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs
@@ -0,0 +1,168 @@
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Model.Serialization;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Providers.Movies
+{
+ class ManualMovieDbImageProvider : IImageProvider
+ {
+ private readonly IJsonSerializer _jsonSerializer;
+ private readonly IServerConfigurationManager _config;
+
+ public ManualMovieDbImageProvider(IJsonSerializer jsonSerializer, IServerConfigurationManager config)
+ {
+ _jsonSerializer = jsonSerializer;
+ _config = config;
+ }
+
+ public string Name
+ {
+ get { return "TheMovieDB"; }
+ }
+
+ public bool Supports(BaseItem item, ImageType imageType)
+ {
+ if (MovieDbImagesProvider.SupportsItem(item))
+ {
+ return imageType == ImageType.Primary || imageType == ImageType.Backdrop;
+ }
+
+ return false;
+ }
+
+ public async Task> GetAvailableImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken)
+ {
+ var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false);
+
+ return images.Where(i => i.Type == imageType);
+ }
+
+ public async Task> GetAllImages(BaseItem item, CancellationToken cancellationToken)
+ {
+ var list = new List();
+
+ var results = FetchImages(item, _jsonSerializer);
+
+ if (results == null)
+ {
+ return list;
+ }
+
+ var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+
+ var tmdbImageUrl = tmdbSettings.images.base_url + "original";
+
+ list.AddRange(GetPosters(results, item).Select(i => new RemoteImageInfo
+ {
+ Url = tmdbImageUrl + i.file_path,
+ CommunityRating = i.vote_average,
+ VoteCount = i.vote_count,
+ Width = i.width,
+ Height = i.height,
+ Language = i.iso_639_1,
+ ProviderName = Name,
+ Type = ImageType.Primary
+ }));
+
+ list.AddRange(GetBackdrops(results, item).Select(i => new RemoteImageInfo
+ {
+ Url = tmdbImageUrl + i.file_path,
+ CommunityRating = i.vote_average,
+ VoteCount = i.vote_count,
+ Width = i.width,
+ Height = i.height,
+ ProviderName = Name,
+ Type = ImageType.Backdrop
+ }));
+
+ return list;
+ }
+
+ ///
+ /// Gets the posters.
+ ///
+ /// The images.
+ /// The item.
+ /// IEnumerable{MovieDbProvider.Poster}.
+ private IEnumerable GetPosters(MovieDbProvider.Images images, BaseItem item)
+ {
+ var language = _config.Configuration.PreferredMetadataLanguage;
+
+ var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase);
+
+ var eligiblePosters = images.posters == null ?
+ new List() :
+ images.posters.Where(i => i.width >= _config.Configuration.MinMoviePosterWidth)
+ .ToList();
+
+ return eligiblePosters.OrderByDescending(i =>
+ {
+ if (string.Equals(language, i.iso_639_1, StringComparison.OrdinalIgnoreCase))
+ {
+ return 3;
+ }
+ if (!isLanguageEn)
+ {
+ if (string.Equals("en", i.iso_639_1, StringComparison.OrdinalIgnoreCase))
+ {
+ return 2;
+ }
+ }
+ if (string.IsNullOrEmpty(i.iso_639_1))
+ {
+ return isLanguageEn ? 3 : 2;
+ }
+ return 0;
+ })
+ .ThenByDescending(i => i.vote_average)
+ .ToList();
+ }
+
+ ///
+ /// Gets the backdrops.
+ ///
+ /// The images.
+ /// The item.
+ /// IEnumerable{MovieDbProvider.Backdrop}.
+ private IEnumerable GetBackdrops(MovieDbProvider.Images images, BaseItem item)
+ {
+ var eligibleBackdrops = images.backdrops == null ? new List() :
+ images.backdrops.Where(i => i.width >= _config.Configuration.MinMovieBackdropWidth)
+ .ToList();
+
+ return eligibleBackdrops.OrderByDescending(i => i.vote_average);
+ }
+
+ ///
+ /// Fetches the images.
+ ///
+ /// The item.
+ /// The json serializer.
+ /// Task{MovieImages}.
+ private MovieDbProvider.Images FetchImages(BaseItem item, IJsonSerializer jsonSerializer)
+ {
+ var path = MovieDbProvider.Current.GetDataFilePath(item, "default");
+
+ if (!string.IsNullOrEmpty(path))
+ {
+ var fileInfo = new FileInfo(path);
+
+ if (fileInfo.Exists)
+ {
+ return jsonSerializer.DeserializeFromFile(path).images;
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs b/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs
index 52e6c214f9..e34cbc54f0 100644
--- a/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
@@ -6,6 +7,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
@@ -21,11 +23,6 @@ namespace MediaBrowser.Providers.Movies
///
public class MovieDbImagesProvider : BaseMetadataProvider
{
- ///
- /// The get images
- ///
- private const string GetImages = @"http://api.themoviedb.org/3/{2}/{0}/images?api_key={1}";
-
///
/// The _provider manager
///
@@ -35,6 +32,7 @@ namespace MediaBrowser.Providers.Movies
/// The _json serializer
///
private readonly IJsonSerializer _jsonSerializer;
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
@@ -43,11 +41,12 @@ namespace MediaBrowser.Providers.Movies
/// The configuration manager.
/// The provider manager.
/// The json serializer.
- public MovieDbImagesProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IJsonSerializer jsonSerializer)
+ public MovieDbImagesProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
_providerManager = providerManager;
_jsonSerializer = jsonSerializer;
+ _fileSystem = fileSystem;
}
///
@@ -65,6 +64,11 @@ namespace MediaBrowser.Providers.Movies
/// The item.
/// true if XXXX, false otherwise
public override bool Supports(BaseItem item)
+ {
+ return SupportsItem(item);
+ }
+
+ public static bool SupportsItem(BaseItem item)
{
var trailer = item as Trailer;
@@ -149,7 +153,7 @@ namespace MediaBrowser.Providers.Movies
{
return false;
}
-
+
var path = MovieDbProvider.Current.GetDataFilePath(item, "default");
if (!string.IsNullOrEmpty(path))
@@ -158,7 +162,7 @@ namespace MediaBrowser.Providers.Movies
if (fileInfo.Exists)
{
- return fileInfo.LastWriteTimeUtc > providerInfo.LastRefreshed;
+ return _fileSystem.GetLastWriteTimeUtc(fileInfo) > providerInfo.LastRefreshed;
}
}
@@ -176,44 +180,18 @@ namespace MediaBrowser.Providers.Movies
{
var id = item.GetProviderId(MetadataProviders.Tmdb);
- var status = ProviderRefreshStatus.Success;
-
if (!string.IsNullOrEmpty(id))
{
- var images = FetchImages(item);
+ var images = await new ManualMovieDbImageProvider(_jsonSerializer, ConfigurationManager).GetAllImages(item,
+ cancellationToken).ConfigureAwait(false);
- if (images != null)
- {
- status = await ProcessImages(item, images, cancellationToken).ConfigureAwait(false);
- }
+ await ProcessImages(item, images.ToList(), cancellationToken).ConfigureAwait(false);
}
- SetLastRefreshed(item, DateTime.UtcNow, status);
+ SetLastRefreshed(item, DateTime.UtcNow);
return true;
}
- ///
- /// Fetches the images.
- ///
- /// The item.
- /// Task{MovieImages}.
- private MovieDbProvider.Images FetchImages(BaseItem item)
- {
- var path = MovieDbProvider.Current.GetDataFilePath(item, "default");
-
- if (!string.IsNullOrEmpty(path))
- {
- var fileInfo = new FileInfo(path);
-
- if (fileInfo.Exists)
- {
- return _jsonSerializer.DeserializeFromFile(path).images;
- }
- }
-
- return null;
- }
-
///
/// Processes the images.
///
@@ -221,68 +199,36 @@ namespace MediaBrowser.Providers.Movies
/// The images.
/// The cancellation token
/// Task.
- private async Task ProcessImages(BaseItem item, MovieDbProvider.Images images, CancellationToken cancellationToken)
+ private async Task ProcessImages(BaseItem item, List images, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
- var status = ProviderRefreshStatus.Success;
-
- var eligiblePosters = images.posters == null ?
- new List() :
- images.posters.Where(i => i.width >= ConfigurationManager.Configuration.MinMoviePosterWidth)
+ var eligiblePosters = images
+ .Where(i => i.Type == ImageType.Primary)
.ToList();
- eligiblePosters = eligiblePosters.OrderByDescending(i => i.vote_average).ToList();
-
// poster
if (eligiblePosters.Count > 0 && !item.HasImage(ImageType.Primary))
{
- var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+ var poster = eligiblePosters[0];
- var tmdbImageUrl = tmdbSettings.images.base_url + "original";
- // get highest rated poster for our language
+ var url = poster.Url;
- var poster = eligiblePosters.FirstOrDefault(p => string.Equals(p.iso_639_1, ConfigurationManager.Configuration.PreferredMetadataLanguage, StringComparison.OrdinalIgnoreCase));
-
- if (poster == null)
+ var img = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
- // couldn't find our specific language, find english
- poster = eligiblePosters.FirstOrDefault(p => string.Equals(p.iso_639_1, "en", StringComparison.OrdinalIgnoreCase));
- }
+ Url = url,
+ CancellationToken = cancellationToken
- if (poster == null)
- {
- //still couldn't find it - try highest rated null one
- poster = eligiblePosters.FirstOrDefault(p => p.iso_639_1 == null);
- }
+ }).ConfigureAwait(false);
- if (poster == null)
- {
- //finally - just get the highest rated one
- poster = eligiblePosters.FirstOrDefault();
- }
-
- if (poster != null)
- {
- var url = tmdbImageUrl + poster.file_path;
-
- var img = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
- {
- Url = url,
- CancellationToken = cancellationToken
-
- }).ConfigureAwait(false);
-
- await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(poster.file_path), ImageType.Primary, null, url, cancellationToken)
- .ConfigureAwait(false);
-
- }
+ await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(url), ImageType.Primary, null, url, cancellationToken)
+ .ConfigureAwait(false);
}
cancellationToken.ThrowIfCancellationRequested();
- var eligibleBackdrops = images.backdrops == null ? new List() :
- images.backdrops.Where(i => i.width >= ConfigurationManager.Configuration.MinMovieBackdropWidth)
+ var eligibleBackdrops = images
+ .Where(i => i.Type == ImageType.Backdrop)
.ToList();
var backdropLimit = ConfigurationManager.Configuration.MaxBackdrops;
@@ -290,13 +236,9 @@ namespace MediaBrowser.Providers.Movies
// backdrops - only download if earlier providers didn't find any (fanart)
if (eligibleBackdrops.Count > 0 && ConfigurationManager.Configuration.DownloadMovieImages.Backdrops && item.BackdropImagePaths.Count < backdropLimit)
{
- var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
-
- var tmdbImageUrl = tmdbSettings.images.base_url + "original";
-
for (var i = 0; i < eligibleBackdrops.Count; i++)
{
- var url = tmdbImageUrl + eligibleBackdrops[i].file_path;
+ var url = eligibleBackdrops[i].Url;
if (!item.ContainsImageWithSourceUrl(url))
{
@@ -307,7 +249,7 @@ namespace MediaBrowser.Providers.Movies
}).ConfigureAwait(false);
- await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(eligibleBackdrops[i].file_path), ImageType.Backdrop, item.BackdropImagePaths.Count, url, cancellationToken)
+ await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(url), ImageType.Backdrop, item.BackdropImagePaths.Count, url, cancellationToken)
.ConfigureAwait(false);
}
@@ -317,8 +259,6 @@ namespace MediaBrowser.Providers.Movies
}
}
}
-
- return status;
}
}
}
diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
index 9ed0860b2e..d7b7faeea7 100644
--- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@@ -47,6 +48,7 @@ namespace MediaBrowser.Providers.Movies
///
/// The HTTP client.
protected IHttpClient HttpClient { get; private set; }
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
@@ -56,12 +58,13 @@ namespace MediaBrowser.Providers.Movies
/// The json serializer.
/// The HTTP client.
/// The provider manager.
- public MovieDbProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient, IProviderManager providerManager)
+ public MovieDbProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient, IProviderManager providerManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
JsonSerializer = jsonSerializer;
HttpClient = httpClient;
ProviderManager = providerManager;
+ _fileSystem = fileSystem;
Current = this;
}
@@ -189,6 +192,7 @@ namespace MediaBrowser.Providers.Movies
static readonly Regex[] NameMatches = new[] {
new Regex(@"(?.*)\((?\d{4})\)"), // matches "My Movie (2001)" and gives us the name and the year
+ new Regex(@"(?.*)(\.(?\d{4})(\.|$)).*$"),
new Regex(@"(?.*)") // last resort matches the whole string as the name
};
@@ -215,7 +219,7 @@ namespace MediaBrowser.Providers.Movies
if (fileInfo.Exists)
{
- return fileInfo.LastWriteTimeUtc > providerInfo.LastRefreshed;
+ return _fileSystem.GetLastWriteTimeUtc(fileInfo) > providerInfo.LastRefreshed;
}
return true;
@@ -320,7 +324,7 @@ namespace MediaBrowser.Providers.Movies
/// The name.
/// Name of the just.
/// The year.
- protected void ParseName(string name, out string justName, out int? year)
+ public static void ParseName(string name, out string justName, out int? year)
{
justName = null;
year = null;
diff --git a/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs b/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs
index ed92151c75..dfab655f10 100644
--- a/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs
+++ b/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs
@@ -1,7 +1,7 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
@@ -21,11 +21,13 @@ namespace MediaBrowser.Providers.Movies
{
internal static MovieProviderFromXml Current { get; private set; }
private readonly IItemRepository _itemRepo;
+ private readonly IFileSystem _fileSystem;
- public MovieProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IItemRepository itemRepo)
+ public MovieProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IItemRepository itemRepo, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
_itemRepo = itemRepo;
+ _fileSystem = fileSystem;
Current = this;
}
@@ -71,7 +73,7 @@ namespace MediaBrowser.Providers.Movies
return false;
}
- return FileSystem.GetLastWriteTimeUtc(xml, Logger) > providerInfo.LastRefreshed;
+ return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed;
}
///
diff --git a/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs b/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs
index b5d2646829..4c1838cfc5 100644
--- a/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs
+++ b/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
using MediaBrowser.Common.Progress;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
@@ -35,6 +36,7 @@ namespace MediaBrowser.Providers.Movies
///
private readonly IServerConfigurationManager _config;
private readonly IJsonSerializer _json;
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
@@ -43,12 +45,13 @@ namespace MediaBrowser.Providers.Movies
/// The HTTP client.
/// The config.
/// The json.
- public MovieUpdatesPreScanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IJsonSerializer json)
+ public MovieUpdatesPreScanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IJsonSerializer json, IFileSystem fileSystem)
{
_logger = logger;
_httpClient = httpClient;
_config = config;
_json = json;
+ _fileSystem = fileSystem;
}
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
@@ -100,7 +103,7 @@ namespace MediaBrowser.Providers.Movies
var refreshDays = _config.Configuration.EnableTmdbUpdates ? 1 : 7;
// Don't check for tvdb updates anymore frequently than 24 hours
- if (timestampFileInfo.Exists && (DateTime.UtcNow - timestampFileInfo.LastWriteTimeUtc).TotalDays < refreshDays)
+ if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < refreshDays)
{
return;
}
diff --git a/MediaBrowser.Providers/Movies/PersonProviderFromXml.cs b/MediaBrowser.Providers/Movies/PersonProviderFromXml.cs
index ab90675fd7..8de061b99b 100644
--- a/MediaBrowser.Providers/Movies/PersonProviderFromXml.cs
+++ b/MediaBrowser.Providers/Movies/PersonProviderFromXml.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Providers;
@@ -13,10 +14,12 @@ namespace MediaBrowser.Providers.Movies
class PersonProviderFromXml : BaseMetadataProvider
{
internal static PersonProviderFromXml Current { get; private set; }
+ private readonly IFileSystem _fileSystem;
- public PersonProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager)
+ public PersonProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
+ _fileSystem = fileSystem;
Current = this;
}
@@ -49,7 +52,7 @@ namespace MediaBrowser.Providers.Movies
return false;
}
- return FileSystem.GetLastWriteTimeUtc(xml, Logger) > providerInfo.LastRefreshed;
+ return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed;
}
///
diff --git a/MediaBrowser.Providers/Movies/PersonUpdatesPreScanTask.cs b/MediaBrowser.Providers/Movies/PersonUpdatesPreScanTask.cs
index d6cc39c86d..8a5e6bd9dc 100644
--- a/MediaBrowser.Providers/Movies/PersonUpdatesPreScanTask.cs
+++ b/MediaBrowser.Providers/Movies/PersonUpdatesPreScanTask.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
@@ -34,6 +35,7 @@ namespace MediaBrowser.Providers.Movies
///
private readonly IServerConfigurationManager _config;
private readonly IJsonSerializer _json;
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
@@ -41,12 +43,13 @@ namespace MediaBrowser.Providers.Movies
/// The logger.
/// The HTTP client.
/// The config.
- public PersonUpdatesPreScanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IJsonSerializer json)
+ public PersonUpdatesPreScanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IJsonSerializer json, IFileSystem fileSystem)
{
_logger = logger;
_httpClient = httpClient;
_config = config;
_json = json;
+ _fileSystem = fileSystem;
}
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
@@ -74,7 +77,7 @@ namespace MediaBrowser.Providers.Movies
var timestampFileInfo = new FileInfo(timestampFile);
// Don't check for tvdb updates anymore frequently than 24 hours
- if (timestampFileInfo.Exists && (DateTime.UtcNow - timestampFileInfo.LastWriteTimeUtc).TotalDays < 1)
+ if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 1)
{
return;
}
diff --git a/MediaBrowser.Providers/Movies/TmdbPersonProvider.cs b/MediaBrowser.Providers/Movies/TmdbPersonProvider.cs
index 4a5db1d81a..7c38eb97b8 100644
--- a/MediaBrowser.Providers/Movies/TmdbPersonProvider.cs
+++ b/MediaBrowser.Providers/Movies/TmdbPersonProvider.cs
@@ -30,8 +30,9 @@ namespace MediaBrowser.Providers.Movies
internal static TmdbPersonProvider Current { get; private set; }
const string DataFileName = "info.json";
+ private readonly IFileSystem _fileSystem;
- public TmdbPersonProvider(IJsonSerializer jsonSerializer, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
+ public TmdbPersonProvider(IJsonSerializer jsonSerializer, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
if (jsonSerializer == null)
@@ -40,6 +41,7 @@ namespace MediaBrowser.Providers.Movies
}
JsonSerializer = jsonSerializer;
ProviderManager = providerManager;
+ _fileSystem = fileSystem;
Current = this;
}
@@ -105,7 +107,7 @@ namespace MediaBrowser.Providers.Movies
if (fileInfo.Exists)
{
- return fileInfo.LastWriteTimeUtc > providerInfo.LastRefreshed;
+ return _fileSystem.GetLastWriteTimeUtc(fileInfo) > providerInfo.LastRefreshed;
}
return true;
@@ -270,7 +272,7 @@ namespace MediaBrowser.Providers.Movies
{
Directory.CreateDirectory(personDataPath);
- using (var fs = new FileStream(Path.Combine(personDataPath, DataFileName), FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, true))
+ using (var fs = _fileSystem.GetFileStream(Path.Combine(personDataPath, DataFileName), FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
await json.CopyToAsync(fs).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Providers/Music/ArtistProviderFromXml.cs b/MediaBrowser.Providers/Music/ArtistProviderFromXml.cs
index 9353d4565c..99cf925e57 100644
--- a/MediaBrowser.Providers/Music/ArtistProviderFromXml.cs
+++ b/MediaBrowser.Providers/Music/ArtistProviderFromXml.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.IO;
@@ -15,10 +16,12 @@ namespace MediaBrowser.Providers.Music
class ArtistProviderFromXml : BaseMetadataProvider
{
public static ArtistProviderFromXml Current;
+ private readonly IFileSystem _fileSystem;
- public ArtistProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager)
+ public ArtistProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
+ _fileSystem = fileSystem;
Current = this;
}
@@ -51,7 +54,7 @@ namespace MediaBrowser.Providers.Music
return false;
}
- return FileSystem.GetLastWriteTimeUtc(xml, Logger) > providerInfo.LastRefreshed;
+ return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed;
}
///
diff --git a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
index e454b048c9..d6c7f1dfd7 100644
--- a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
+++ b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@@ -37,6 +38,7 @@ namespace MediaBrowser.Providers.Music
protected IHttpClient HttpClient { get; private set; }
internal static FanArtAlbumProvider Current { get; private set; }
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
@@ -45,10 +47,11 @@ namespace MediaBrowser.Providers.Music
/// The log manager.
/// The configuration manager.
/// The provider manager.
- public FanArtAlbumProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
+ public FanArtAlbumProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
_providerManager = providerManager;
+ _fileSystem = fileSystem;
HttpClient = httpClient;
Current = this;
@@ -140,7 +143,7 @@ namespace MediaBrowser.Providers.Music
if (file.Exists)
{
- return file.LastWriteTimeUtc;
+ return _fileSystem.GetLastWriteTimeUtc(file);
}
}
diff --git a/MediaBrowser.Providers/Music/FanArtArtistByNameProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistByNameProvider.cs
index f0dd460e6c..5d18f16ffa 100644
--- a/MediaBrowser.Providers/Music/FanArtArtistByNameProvider.cs
+++ b/MediaBrowser.Providers/Music/FanArtArtistByNameProvider.cs
@@ -1,7 +1,9 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
@@ -15,12 +17,8 @@ namespace MediaBrowser.Providers.Music
///
/// Initializes a new instance of the class.
///
- /// The HTTP client.
- /// The log manager.
- /// The configuration manager.
- /// The provider manager.
- public FanArtArtistByNameProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
- : base(httpClient, logManager, configurationManager, providerManager)
+ public FanArtArtistByNameProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
+ : base(httpClient, logManager, configurationManager, providerManager, fileSystem)
{
}
diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
index 79d53d5785..b1d97d8b59 100644
--- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
+++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
@@ -1,24 +1,23 @@
-using System.Net;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Net;
using System;
-using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
+using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
-using MediaBrowser.Model.Net;
namespace MediaBrowser.Providers.Music
{
@@ -39,6 +38,7 @@ namespace MediaBrowser.Providers.Music
private readonly IProviderManager _providerManager;
internal static FanArtArtistProvider Current;
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
@@ -48,7 +48,7 @@ namespace MediaBrowser.Providers.Music
/// The configuration manager.
/// The provider manager.
/// httpClient
- public FanArtArtistProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
+ public FanArtArtistProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
if (httpClient == null)
@@ -57,6 +57,7 @@ namespace MediaBrowser.Providers.Music
}
HttpClient = httpClient;
_providerManager = providerManager;
+ _fileSystem = fileSystem;
Current = this;
}
@@ -167,7 +168,7 @@ namespace MediaBrowser.Providers.Music
{
var files = new DirectoryInfo(path)
.EnumerateFiles("*.xml", SearchOption.TopDirectoryOnly)
- .Select(i => i.LastWriteTimeUtc)
+ .Select(i => _fileSystem.GetLastWriteTimeUtc(i))
.ToList();
if (files.Count > 0)
@@ -284,7 +285,7 @@ namespace MediaBrowser.Providers.Music
}).ConfigureAwait(false))
{
- using (var xmlFileStream = new FileStream(xmlPath, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
+ using (var xmlFileStream = _fileSystem.GetFileStream(xmlPath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
await response.CopyToAsync(xmlFileStream).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs b/MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs
index 379866945a..6d9a16e874 100644
--- a/MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs
+++ b/MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
@@ -31,15 +32,17 @@ namespace MediaBrowser.Providers.Music
///
private readonly IServerConfigurationManager _config;
private readonly IJsonSerializer _jsonSerializer;
+ private readonly IFileSystem _fileSystem;
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
- public FanArtUpdatesPrescanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient)
+ public FanArtUpdatesPrescanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem)
{
_jsonSerializer = jsonSerializer;
_config = config;
_logger = logger;
_httpClient = httpClient;
+ _fileSystem = fileSystem;
}
///
@@ -65,7 +68,7 @@ namespace MediaBrowser.Providers.Music
var timestampFileInfo = new FileInfo(timestampFile);
// Don't check for tvdb updates anymore frequently than 24 hours
- if (timestampFileInfo.Exists && (DateTime.UtcNow - timestampFileInfo.LastWriteTimeUtc).TotalDays < 1)
+ if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 1)
{
return;
}
diff --git a/MediaBrowser.Providers/RefreshIntrosTask.cs b/MediaBrowser.Providers/RefreshIntrosTask.cs
index 3ff2b40a6b..3ecddf6130 100644
--- a/MediaBrowser.Providers/RefreshIntrosTask.cs
+++ b/MediaBrowser.Providers/RefreshIntrosTask.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.IO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
using System;
@@ -22,15 +23,18 @@ namespace MediaBrowser.Providers
///
private readonly ILogger _logger;
+ private readonly IFileSystem _fileSystem;
+
///
/// Initializes a new instance of the class.
///
/// The library manager.
/// The logger.
- public RefreshIntrosTask(ILibraryManager libraryManager, ILogger logger)
+ public RefreshIntrosTask(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem)
{
_libraryManager = libraryManager;
_logger = logger;
+ _fileSystem = fileSystem;
}
///
@@ -77,7 +81,7 @@ namespace MediaBrowser.Providers
/// Task.
private async Task RefreshIntro(string path, CancellationToken cancellationToken)
{
- var item = _libraryManager.ResolvePath(FileSystem.GetFileSystemInfo(path));
+ var item = _libraryManager.ResolvePath(_fileSystem.GetFileSystemInfo(path));
if (item == null)
{
diff --git a/MediaBrowser.Providers/Savers/GameXmlSaver.cs b/MediaBrowser.Providers/Savers/GameXmlSaver.cs
index 5564b71cef..f35e4d1319 100644
--- a/MediaBrowser.Providers/Savers/GameXmlSaver.cs
+++ b/MediaBrowser.Providers/Savers/GameXmlSaver.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Providers.Movies;
using System;
using System.Collections.Generic;
@@ -70,6 +71,20 @@ namespace MediaBrowser.Providers.Savers
builder.Append("" + SecurityElement.Escape(game.GameSystem) + "");
}
+ var val = game.GetProviderId(MetadataProviders.NesBox);
+
+ if (!string.IsNullOrEmpty(val))
+ {
+ builder.Append("" + SecurityElement.Escape(val) + "");
+ }
+
+ val = game.GetProviderId(MetadataProviders.NesBoxRom);
+
+ if (!string.IsNullOrEmpty(val))
+ {
+ builder.Append("" + SecurityElement.Escape(val) + "");
+ }
+
XmlSaverHelpers.AddCommonNodes(item, builder);
builder.Append("");
@@ -79,7 +94,9 @@ namespace MediaBrowser.Providers.Savers
XmlSaverHelpers.Save(builder, xmlFilePath, new List
{
"Players",
- "GameSystem"
+ "GameSystem",
+ "NesBox",
+ "NesBoxRom"
});
// Set last refreshed so that the provider doesn't trigger after the file save
diff --git a/MediaBrowser.Providers/TV/EpisodeProviderFromXml.cs b/MediaBrowser.Providers/TV/EpisodeProviderFromXml.cs
index 9862f10fee..b6fdaaa831 100644
--- a/MediaBrowser.Providers/TV/EpisodeProviderFromXml.cs
+++ b/MediaBrowser.Providers/TV/EpisodeProviderFromXml.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.IO;
@@ -20,11 +21,13 @@ namespace MediaBrowser.Providers.TV
{
internal static EpisodeProviderFromXml Current { get; private set; }
private readonly IItemRepository _itemRepo;
+ private readonly IFileSystem _fileSystem;
- public EpisodeProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IItemRepository itemRepo)
+ public EpisodeProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IItemRepository itemRepo, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
_itemRepo = itemRepo;
+ _fileSystem = fileSystem;
Current = this;
}
@@ -76,7 +79,7 @@ namespace MediaBrowser.Providers.TV
return false;
}
- return FileSystem.GetLastWriteTimeUtc(file, Logger) > providerInfo.LastRefreshed;
+ return _fileSystem.GetLastWriteTimeUtc(file) > providerInfo.LastRefreshed;
}
///
diff --git a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs b/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs
index dd87db5b5c..fe316e85b7 100644
--- a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs
+++ b/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
@@ -22,6 +23,7 @@ namespace MediaBrowser.Providers.TV
/// The _provider manager
///
private readonly IProviderManager _providerManager;
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
@@ -29,10 +31,11 @@ namespace MediaBrowser.Providers.TV
/// The log manager.
/// The configuration manager.
/// The provider manager.
- public FanArtSeasonProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
+ public FanArtSeasonProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
_providerManager = providerManager;
+ _fileSystem = fileSystem;
}
public override ItemUpdateType ItemUpdateType
@@ -76,7 +79,7 @@ namespace MediaBrowser.Providers.TV
if (imagesFileInfo.Exists)
{
- return imagesFileInfo.LastWriteTimeUtc;
+ return _fileSystem.GetLastWriteTimeUtc(imagesFileInfo);
}
}
diff --git a/MediaBrowser.Providers/TV/FanArtTVProvider.cs b/MediaBrowser.Providers/TV/FanArtTVProvider.cs
index ed7ca941c2..af89bc205e 100644
--- a/MediaBrowser.Providers/TV/FanArtTVProvider.cs
+++ b/MediaBrowser.Providers/TV/FanArtTVProvider.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
@@ -31,8 +32,9 @@ namespace MediaBrowser.Providers.TV
protected IHttpClient HttpClient { get; private set; }
private readonly IProviderManager _providerManager;
+ private readonly IFileSystem _fileSystem;
- public FanArtTvProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
+ public FanArtTvProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
if (httpClient == null)
@@ -41,6 +43,7 @@ namespace MediaBrowser.Providers.TV
}
HttpClient = httpClient;
_providerManager = providerManager;
+ _fileSystem = fileSystem;
Current = this;
}
@@ -115,7 +118,7 @@ namespace MediaBrowser.Providers.TV
{
var files = new DirectoryInfo(path)
.EnumerateFiles("*.xml", SearchOption.TopDirectoryOnly)
- .Select(i => i.LastWriteTimeUtc)
+ .Select(i => _fileSystem.GetLastWriteTimeUtc(i))
.ToList();
if (files.Count > 0)
@@ -353,7 +356,7 @@ namespace MediaBrowser.Providers.TV
}).ConfigureAwait(false))
{
- using (var xmlFileStream = new FileStream(xmlPath, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
+ using (var xmlFileStream = _fileSystem.GetFileStream(xmlPath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
await response.CopyToAsync(xmlFileStream).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs b/MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs
index 2a8e019741..5c1c7a69d9 100644
--- a/MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs
+++ b/MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
@@ -32,15 +33,17 @@ namespace MediaBrowser.Providers.TV
///
private readonly IServerConfigurationManager _config;
private readonly IJsonSerializer _jsonSerializer;
+ private readonly IFileSystem _fileSystem;
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
- public FanArtTvUpdatesPrescanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient)
+ public FanArtTvUpdatesPrescanTask(IJsonSerializer jsonSerializer, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient, IFileSystem fileSystem)
{
_jsonSerializer = jsonSerializer;
_config = config;
_logger = logger;
_httpClient = httpClient;
+ _fileSystem = fileSystem;
}
///
@@ -66,7 +69,7 @@ namespace MediaBrowser.Providers.TV
var timestampFileInfo = new FileInfo(timestampFile);
// Don't check for tvdb updates anymore frequently than 24 hours
- if (timestampFileInfo.Exists && (DateTime.UtcNow - timestampFileInfo.LastWriteTimeUtc).TotalDays < 1)
+ if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 1)
{
return;
}
diff --git a/MediaBrowser.Providers/TV/RemoteEpisodeProvider.cs b/MediaBrowser.Providers/TV/RemoteEpisodeProvider.cs
index e8b4b0f3de..cc6bca0b3f 100644
--- a/MediaBrowser.Providers/TV/RemoteEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/RemoteEpisodeProvider.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
@@ -36,6 +37,7 @@ namespace MediaBrowser.Providers.TV
///
/// The HTTP client.
protected IHttpClient HttpClient { get; private set; }
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
@@ -44,11 +46,12 @@ namespace MediaBrowser.Providers.TV
/// The log manager.
/// The configuration manager.
/// The provider manager.
- public RemoteEpisodeProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
+ public RemoteEpisodeProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
HttpClient = httpClient;
_providerManager = providerManager;
+ _fileSystem = fileSystem;
}
///
@@ -149,7 +152,7 @@ namespace MediaBrowser.Providers.TV
if (files.Count > 0)
{
- return files.Select(i => i.LastWriteTimeUtc).Max() > providerInfo.LastRefreshed;
+ return files.Select(i => _fileSystem.GetLastWriteTimeUtc(i)).Max() > providerInfo.LastRefreshed;
}
}
@@ -240,17 +243,16 @@ namespace MediaBrowser.Providers.TV
{
cancellationToken.ThrowIfCancellationRequested();
+ var status = ProviderRefreshStatus.Success;
+
var episode = (Episode)item;
var seriesId = episode.Series != null ? episode.Series.GetProviderId(MetadataProviders.Tvdb) : null;
if (!string.IsNullOrEmpty(seriesId))
{
- var seriesDataPath = RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths,
- seriesId);
+ var seriesDataPath = RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId);
- var status = ProviderRefreshStatus.Success;
-
try
{
status = await FetchEpisodeData(episode, seriesDataPath, cancellationToken).ConfigureAwait(false);
@@ -259,20 +261,10 @@ namespace MediaBrowser.Providers.TV
{
// Don't fail the provider because this will just keep on going and going.
}
-
- BaseProviderInfo data;
- if (!item.ProviderData.TryGetValue(Id, out data))
- {
- data = new BaseProviderInfo();
- item.ProviderData[Id] = data;
- }
-
- SetLastRefreshed(item, DateTime.UtcNow, status);
- return true;
}
- Logger.Info("Episode provider not fetching because series does not have a tvdb id: " + item.Path);
- return false;
+ SetLastRefreshed(item, DateTime.UtcNow, status);
+ return true;
}
diff --git a/MediaBrowser.Providers/TV/RemoteSeasonProvider.cs b/MediaBrowser.Providers/TV/RemoteSeasonProvider.cs
index c0ff760549..1f702a2d21 100644
--- a/MediaBrowser.Providers/TV/RemoteSeasonProvider.cs
+++ b/MediaBrowser.Providers/TV/RemoteSeasonProvider.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
@@ -23,6 +24,7 @@ namespace MediaBrowser.Providers.TV
/// The _provider manager
///
private readonly IProviderManager _providerManager;
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
@@ -31,10 +33,11 @@ namespace MediaBrowser.Providers.TV
/// The configuration manager.
/// The provider manager.
/// httpClient
- public RemoteSeasonProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
+ public RemoteSeasonProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
_providerManager = providerManager;
+ _fileSystem = fileSystem;
}
///
@@ -115,7 +118,7 @@ namespace MediaBrowser.Providers.TV
if (imagesFileInfo.Exists)
{
- return imagesFileInfo.LastWriteTimeUtc > providerInfo.LastRefreshed;
+ return _fileSystem.GetLastWriteTimeUtc(imagesFileInfo) > providerInfo.LastRefreshed;
}
}
return false;
@@ -275,6 +278,7 @@ namespace MediaBrowser.Providers.TV
string url = null;
int? bannerSeason = null;
string resolution = null;
+ string language = null;
while (reader.Read())
{
@@ -282,6 +286,12 @@ namespace MediaBrowser.Providers.TV
{
switch (reader.Name)
{
+ case "Language":
+ {
+ language = reader.ReadElementContentAsString() ?? string.Empty;
+ break;
+ }
+
case "BannerType":
{
bannerType = reader.ReadElementContentAsString() ?? string.Empty;
@@ -325,11 +335,30 @@ namespace MediaBrowser.Providers.TV
{
if (string.Equals(bannerType2, "season", StringComparison.OrdinalIgnoreCase))
{
- data.Poster = url;
+ // Just grab the first
+ if (string.IsNullOrWhiteSpace(data.Poster))
+ {
+ data.Poster = url;
+ }
}
else if (string.Equals(bannerType2, "seasonwide", StringComparison.OrdinalIgnoreCase))
{
- data.Banner = url;
+ if (string.IsNullOrWhiteSpace(language) || string.Equals(language, "en", StringComparison.OrdinalIgnoreCase))
+ {
+ // Just grab the first
+ if (string.IsNullOrWhiteSpace(data.Banner))
+ {
+ data.Banner = url;
+ }
+ }
+ else if (string.Equals(language, ConfigurationManager.Configuration.PreferredMetadataLanguage, StringComparison.OrdinalIgnoreCase))
+ {
+ // Just grab the first
+ if (string.IsNullOrWhiteSpace(data.LanguageBanner))
+ {
+ data.LanguageBanner = url;
+ }
+ }
}
}
else if (string.Equals(bannerType, "fanart", StringComparison.OrdinalIgnoreCase))
diff --git a/MediaBrowser.Providers/TV/RemoteSeriesProvider.cs b/MediaBrowser.Providers/TV/RemoteSeriesProvider.cs
index 322fcd2280..3e2736cbca 100644
--- a/MediaBrowser.Providers/TV/RemoteSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/RemoteSeriesProvider.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
@@ -49,6 +50,8 @@ namespace MediaBrowser.Providers.TV
/// The HTTP client.
protected IHttpClient HttpClient { get; private set; }
+ private readonly IFileSystem _fileSystem;
+
///
/// Initializes a new instance of the class.
///
@@ -57,7 +60,7 @@ namespace MediaBrowser.Providers.TV
/// The configuration manager.
/// The zip client.
/// httpClient
- public RemoteSeriesProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IZipClient zipClient)
+ public RemoteSeriesProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IZipClient zipClient, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
if (httpClient == null)
@@ -66,6 +69,7 @@ namespace MediaBrowser.Providers.TV
}
HttpClient = httpClient;
_zipClient = zipClient;
+ _fileSystem = fileSystem;
Current = this;
}
@@ -176,7 +180,7 @@ namespace MediaBrowser.Providers.TV
{
var files = new DirectoryInfo(path)
.EnumerateFiles("*.xml", SearchOption.TopDirectoryOnly)
- .Select(i => i.LastWriteTimeUtc)
+ .Select(i => _fileSystem.GetLastWriteTimeUtc(i))
.ToList();
if (files.Count > 0)
@@ -344,7 +348,7 @@ namespace MediaBrowser.Providers.TV
{
string validXml;
- using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, true))
+ using (var fileStream = _fileSystem.GetFileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, true))
{
using (var reader = new StreamReader(fileStream))
{
@@ -354,7 +358,7 @@ namespace MediaBrowser.Providers.TV
}
}
- using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, true))
+ using (var fileStream = _fileSystem.GetFileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
using (var writer = new StreamWriter(fileStream))
{
@@ -1109,21 +1113,37 @@ namespace MediaBrowser.Providers.TV
var nodes = doc.SelectNodes("//Series");
var comparableName = GetComparableName(name);
if (nodes != null)
+ {
foreach (XmlNode node in nodes)
{
- var n = node.SelectSingleNode("./SeriesName");
- if (n != null && string.Equals(GetComparableName(n.InnerText), comparableName, StringComparison.OrdinalIgnoreCase))
+ var titles = new List();
+
+ var nameNode = node.SelectSingleNode("./SeriesName");
+ if (nameNode != null)
{
- n = node.SelectSingleNode("./seriesid");
- if (n != null)
- return n.InnerText;
+ titles.Add(GetComparableName(nameNode.InnerText));
}
- else
+
+ var aliasNode = node.SelectSingleNode("./AliasNames");
+ if (aliasNode != null)
{
- if (n != null)
- Logger.Info("TVDb Provider - " + n.InnerText + " did not match " + comparableName);
+ var alias = aliasNode.InnerText.Split('|').Select(GetComparableName);
+ titles.AddRange(alias);
+ }
+
+ if (titles.Any(t => string.Equals(t, comparableName, StringComparison.OrdinalIgnoreCase)))
+ {
+ var id = node.SelectSingleNode("./seriesid");
+ if (id != null)
+ return id.InnerText;
+ }
+
+ foreach (var title in titles)
+ {
+ Logger.Info("TVDb Provider - " + title + " did not match " + comparableName);
}
}
+ }
}
// Try stripping off the year if it was supplied
diff --git a/MediaBrowser.Providers/TV/SeasonProviderFromXml.cs b/MediaBrowser.Providers/TV/SeasonProviderFromXml.cs
index 0c8fcf066c..5f1eb5cb3f 100644
--- a/MediaBrowser.Providers/TV/SeasonProviderFromXml.cs
+++ b/MediaBrowser.Providers/TV/SeasonProviderFromXml.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.IO;
@@ -18,10 +19,12 @@ namespace MediaBrowser.Providers.TV
public class SeasonProviderFromXml : BaseMetadataProvider
{
public static SeasonProviderFromXml Current;
+ private readonly IFileSystem _fileSystem;
- public SeasonProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager)
+ public SeasonProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
+ _fileSystem = fileSystem;
Current = this;
}
@@ -54,7 +57,7 @@ namespace MediaBrowser.Providers.TV
return false;
}
- return FileSystem.GetLastWriteTimeUtc(xml, Logger) > providerInfo.LastRefreshed;
+ return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed;
}
///
diff --git a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs
index 2e9910aebd..22ff917618 100644
--- a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs
+++ b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs
@@ -39,6 +39,13 @@ namespace MediaBrowser.Providers.TV
private async Task RunInternal(IProgress progress, CancellationToken cancellationToken)
{
+ if (!_config.Configuration.EnableInternetProviders ||
+ _config.Configuration.InternetProviderExcludeTypes.Contains(typeof(Series).Name, StringComparer.OrdinalIgnoreCase))
+ {
+ progress.Report(100);
+ return;
+ }
+
var seriesList = _libraryManager.RootFolder
.RecursiveChildren
.OfType()
@@ -136,21 +143,27 @@ namespace MediaBrowser.Providers.TV
.Where(i => i.Item1 != -1 && i.Item2 != -1)
.ToList();
- var anySeasonsRemoved = await RemoveObsoleteOrMissingSeasons(series, episodeLookup, cancellationToken).ConfigureAwait(false);
+ var anySeasonsRemoved = await RemoveObsoleteOrMissingSeasons(series, episodeLookup, cancellationToken)
+ .ConfigureAwait(false);
- var anyEpisodesRemoved = await RemoveObsoleteOrMissingEpisodes(series, episodeLookup, cancellationToken).ConfigureAwait(false);
+ var anyEpisodesRemoved = await RemoveObsoleteOrMissingEpisodes(series, episodeLookup, cancellationToken)
+ .ConfigureAwait(false);
var hasNewEpisodes = false;
if (_config.Configuration.EnableInternetProviders)
{
- hasNewEpisodes = await AddMissingEpisodes(series, seriesDataPath, episodeLookup, cancellationToken).ConfigureAwait(false);
+ hasNewEpisodes = await AddMissingEpisodes(series, seriesDataPath, episodeLookup, cancellationToken)
+ .ConfigureAwait(false);
}
if (hasNewEpisodes || anySeasonsRemoved || anyEpisodesRemoved)
{
- await series.RefreshMetadata(cancellationToken, true).ConfigureAwait(false);
- await series.ValidateChildren(new Progress(), cancellationToken, true).ConfigureAwait(false);
+ await series.RefreshMetadata(cancellationToken, true)
+ .ConfigureAwait(false);
+
+ await series.ValidateChildren(new Progress(), cancellationToken, true)
+ .ConfigureAwait(false);
}
}
@@ -211,7 +224,7 @@ namespace MediaBrowser.Providers.TV
else if (airDate.Value > now)
{
// tvdb has a lot of nearly blank episodes
- _logger.Info("Creating virtual future episode {0} {1}x{2}", series.Name, tuple.Item1, tuple.Item2);
+ _logger.Info("Creating virtual unaired episode {0} {1}x{2}", series.Name, tuple.Item1, tuple.Item2);
await AddEpisode(series, tuple.Item1, tuple.Item2, cancellationToken).ConfigureAwait(false);
diff --git a/MediaBrowser.Providers/TV/SeriesProviderFromXml.cs b/MediaBrowser.Providers/TV/SeriesProviderFromXml.cs
index 67d6e423c9..c4b82d51eb 100644
--- a/MediaBrowser.Providers/TV/SeriesProviderFromXml.cs
+++ b/MediaBrowser.Providers/TV/SeriesProviderFromXml.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.IO;
@@ -18,10 +19,12 @@ namespace MediaBrowser.Providers.TV
public class SeriesProviderFromXml : BaseMetadataProvider
{
internal static SeriesProviderFromXml Current { get; private set; }
-
- public SeriesProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager)
+ private readonly IFileSystem _fileSystem;
+
+ public SeriesProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
+ _fileSystem = fileSystem;
Current = this;
}
@@ -54,7 +57,7 @@ namespace MediaBrowser.Providers.TV
return false;
}
- return FileSystem.GetLastWriteTimeUtc(xml, Logger) > providerInfo.LastRefreshed;
+ return _fileSystem.GetLastWriteTimeUtc(xml) > providerInfo.LastRefreshed;
}
///
diff --git a/MediaBrowser.Providers/TV/TvdbPrescanTask.cs b/MediaBrowser.Providers/TV/TvdbPrescanTask.cs
index 94f857d9c9..d77698725a 100644
--- a/MediaBrowser.Providers/TV/TvdbPrescanTask.cs
+++ b/MediaBrowser.Providers/TV/TvdbPrescanTask.cs
@@ -1,11 +1,13 @@
-using System.Globalization;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
@@ -42,6 +44,7 @@ namespace MediaBrowser.Providers.TV
/// The _config
///
private readonly IServerConfigurationManager _config;
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
@@ -49,11 +52,12 @@ namespace MediaBrowser.Providers.TV
/// The logger.
/// The HTTP client.
/// The config.
- public TvdbPrescanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config)
+ public TvdbPrescanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IFileSystem fileSystem)
{
_logger = logger;
_httpClient = httpClient;
_config = config;
+ _fileSystem = fileSystem;
}
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
@@ -66,7 +70,8 @@ namespace MediaBrowser.Providers.TV
/// Task.
public async Task Run(IProgress progress, CancellationToken cancellationToken)
{
- if (!_config.Configuration.EnableInternetProviders)
+ if (!_config.Configuration.EnableInternetProviders ||
+ _config.Configuration.InternetProviderExcludeTypes.Contains(typeof(Series).Name, StringComparer.OrdinalIgnoreCase))
{
progress.Report(100);
return;
@@ -81,7 +86,7 @@ namespace MediaBrowser.Providers.TV
var timestampFileInfo = new FileInfo(timestampFile);
// Don't check for tvdb updates anymore frequently than 24 hours
- if (timestampFileInfo.Exists && (DateTime.UtcNow - timestampFileInfo.LastWriteTimeUtc).TotalDays < 1)
+ if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 1)
{
return;
}
diff --git a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs
index fa42257607..2e19a853db 100644
--- a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs
@@ -1,8 +1,9 @@
-using System.Linq;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
@@ -11,6 +12,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
+using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -30,6 +32,7 @@ namespace MediaBrowser.Providers.TV
/// The _provider manager
///
private readonly IProviderManager _providerManager;
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
@@ -39,7 +42,7 @@ namespace MediaBrowser.Providers.TV
/// The configuration manager.
/// The provider manager.
/// httpClient
- public TvdbSeriesImageProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
+ public TvdbSeriesImageProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
: base(logManager, configurationManager)
{
if (httpClient == null)
@@ -48,6 +51,7 @@ namespace MediaBrowser.Providers.TV
}
HttpClient = httpClient;
_providerManager = providerManager;
+ _fileSystem = fileSystem;
}
///
@@ -127,7 +131,7 @@ namespace MediaBrowser.Providers.TV
if (imagesFileInfo.Exists)
{
- return imagesFileInfo.LastWriteTimeUtc;
+ return _fileSystem.GetLastWriteTimeUtc(imagesFileInfo);
}
}
@@ -373,11 +377,19 @@ namespace MediaBrowser.Providers.TV
{
if (string.Equals(type, "poster", StringComparison.OrdinalIgnoreCase))
{
- data.Poster = url;
+ // Just grab the first
+ if (string.IsNullOrWhiteSpace(data.Poster))
+ {
+ data.Poster = url;
+ }
}
else if (string.Equals(type, "series", StringComparison.OrdinalIgnoreCase))
{
- data.Banner = url;
+ // Just grab the first
+ if (string.IsNullOrWhiteSpace(data.Banner))
+ {
+ data.Banner = url;
+ }
}
else if (string.Equals(type, "fanart", StringComparison.OrdinalIgnoreCase))
{
diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageHeader.cs b/MediaBrowser.Server.Implementations/Drawing/ImageHeader.cs
index 4da836cc68..f9cf90787d 100644
--- a/MediaBrowser.Server.Implementations/Drawing/ImageHeader.cs
+++ b/MediaBrowser.Server.Implementations/Drawing/ImageHeader.cs
@@ -1,4 +1,6 @@
-using MediaBrowser.Model.Logging;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.Drawing;
@@ -40,9 +42,10 @@ namespace MediaBrowser.Server.Implementations.Drawing
///
/// The path of the image to get the dimensions of.
/// The logger.
+ /// The file system.
/// The dimensions of the specified image.
/// The image was of an unrecognised format.
- public static Size GetDimensions(string path, ILogger logger)
+ public static Size GetDimensions(string path, ILogger logger, IFileSystem fileSystem)
{
try
{
@@ -60,7 +63,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
}
// Buffer to memory stream to avoid image locking file
- using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
+ using (var fs = fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (var memoryStream = new MemoryStream())
{
diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
index 95a6448023..ace633be71 100644
--- a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
+++ b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Common.IO;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
@@ -51,16 +52,18 @@ namespace MediaBrowser.Server.Implementations.Drawing
/// The _app paths
///
private readonly IServerApplicationPaths _appPaths;
+ private readonly IFileSystem _fileSystem;
private readonly string _imageSizeCachePath;
private readonly string _croppedWhitespaceImageCachePath;
private readonly string _enhancedImageCachePath;
private readonly string _resizedImageCachePath;
- public ImageProcessor(ILogger logger, IServerApplicationPaths appPaths)
+ public ImageProcessor(ILogger logger, IServerApplicationPaths appPaths, IFileSystem fileSystem)
{
_logger = logger;
_appPaths = appPaths;
+ _fileSystem = fileSystem;
_imageSizeCachePath = Path.Combine(_appPaths.ImageCachePath, "image-sizes");
_croppedWhitespaceImageCachePath = Path.Combine(_appPaths.ImageCachePath, "cropped-images");
@@ -113,7 +116,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
try
{
- using (var fileStream = new FileStream(cacheFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
+ using (var fileStream = _fileSystem.GetFileStream(cacheFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
{
await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
return;
@@ -131,7 +134,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
// Check again in case of lock contention
try
{
- using (var fileStream = new FileStream(cacheFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
+ using (var fileStream = _fileSystem.GetFileStream(cacheFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
{
await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
semaphore.Release();
@@ -150,7 +153,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
try
{
- using (var fileStream = new FileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, true))
+ using (var fileStream = _fileSystem.GetFileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
{
// Copy to memory stream to avoid Image locking file
using (var memoryStream = new MemoryStream())
@@ -228,7 +231,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
Directory.CreateDirectory(parentPath);
// Save to the cache location
- using (var cacheFileStream = new FileStream(cacheFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
+ using (var cacheFileStream = _fileSystem.GetFileStream(cacheFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
// Save to the filestream
await cacheFileStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
@@ -359,7 +362,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
try
{
- using (var fileStream = new FileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, true))
+ using (var fileStream = _fileSystem.GetFileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
{
// Copy to memory stream to avoid Image locking file
using (var memoryStream = new MemoryStream())
@@ -376,7 +379,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
Directory.CreateDirectory(parentPath);
- using (var outputStream = new FileStream(croppedImagePath, FileMode.Create, FileAccess.Write, FileShare.Read))
+ using (var outputStream = _fileSystem.GetFileStream(croppedImagePath, FileMode.Create, FileAccess.Write, FileShare.Read, false))
{
croppedImage.Save(outputFormat, outputStream, 100);
}
@@ -525,7 +528,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
// Cache file doesn't exist no biggie
}
- var size = ImageHeader.GetDimensions(path, _logger);
+ var size = ImageHeader.GetDimensions(path, _logger, _fileSystem);
var parentPath = Path.GetDirectoryName(fullCachePath);
@@ -685,7 +688,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
try
{
- using (var fileStream = new FileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, true))
+ using (var fileStream = _fileSystem.GetFileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
{
// Copy to memory stream to avoid Image locking file
using (var memoryStream = new MemoryStream())
@@ -702,7 +705,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
Directory.CreateDirectory(parentDirectory);
//And then save it in the cache
- using (var outputStream = new FileStream(enhancedImagePath, FileMode.Create, FileAccess.Write, FileShare.Read))
+ using (var outputStream = _fileSystem.GetFileStream(enhancedImagePath, FileMode.Create, FileAccess.Write, FileShare.Read, false))
{
newImage.Save(ImageFormat.Png, outputStream, 100);
}
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index 65a161821c..19e19f8ea4 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -373,6 +373,11 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.GameSystem = item.GameSystem;
}
+ private void SetGameSystemProperties(BaseItemDto dto, GameSystem item)
+ {
+ dto.GameSystem = item.GameSystemName;
+ }
+
///
/// Gets the backdrop image tags.
///
@@ -1064,6 +1069,13 @@ namespace MediaBrowser.Server.Implementations.Dto
SetGameProperties(dto, game);
}
+ var gameSystem = item as GameSystem;
+
+ if (gameSystem != null)
+ {
+ SetGameSystemProperties(dto, gameSystem);
+ }
+
var musicVideo = item as MusicVideo;
if (musicVideo != null)
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs
index cb60975046..723e4fdd31 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs
@@ -1,5 +1,7 @@
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Notifications;
using MediaBrowser.Controller.Plugins;
@@ -26,11 +28,12 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
private readonly IJsonSerializer _json;
private readonly INotificationsRepository _notificationsRepo;
private readonly IUserManager _userManager;
+ private readonly IFileSystem _fileSystem;
private readonly TimeSpan _frequency = TimeSpan.FromHours(6);
private readonly TimeSpan _maxAge = TimeSpan.FromDays(31);
- public RemoteNotifications(IApplicationPaths appPaths, ILogger logger, IHttpClient httpClient, IJsonSerializer json, INotificationsRepository notificationsRepo, IUserManager userManager)
+ public RemoteNotifications(IApplicationPaths appPaths, ILogger logger, IHttpClient httpClient, IJsonSerializer json, INotificationsRepository notificationsRepo, IUserManager userManager, IFileSystem fileSystem)
{
_appPaths = appPaths;
_logger = logger;
@@ -38,6 +41,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
_json = json;
_notificationsRepo = notificationsRepo;
_userManager = userManager;
+ _fileSystem = fileSystem;
}
///
@@ -56,7 +60,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
{
var dataPath = Path.Combine(_appPaths.DataPath, "remotenotifications.json");
- var lastRunTime = File.Exists(dataPath) ? File.GetLastWriteTimeUtc(dataPath) : DateTime.MinValue;
+ var lastRunTime = File.Exists(dataPath) ? _fileSystem.GetLastWriteTimeUtc(dataPath) : DateTime.MinValue;
try
{
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs
index 356c6fc4d4..e6942fae6a 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Model.Logging;
using ServiceStack.Common;
using ServiceStack.Common.Web;
@@ -25,13 +26,15 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// The _logger
///
private readonly ILogger _logger;
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
///
/// The log manager.
- public HttpResultFactory(ILogManager logManager)
+ public HttpResultFactory(ILogManager logManager, IFileSystem fileSystem)
{
+ _fileSystem = fileSystem;
_logger = logManager.GetLogger("HttpResultFactory");
}
@@ -288,7 +291,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
throw new ArgumentException("FileShare must be either Read or ReadWrite");
}
- var dateModified = File.GetLastWriteTimeUtc(path);
+ var dateModified = _fileSystem.GetLastWriteTimeUtc(path);
var cacheKey = path + dateModified.Ticks;
@@ -303,7 +306,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// Stream.
private Stream GetFileStream(string path, FileShare fileShare)
{
- return new FileStream(path, FileMode.Open, FileAccess.Read, fileShare, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous);
+ return _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, fileShare, true);
}
///
diff --git a/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs b/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs
index a4d99ae17e..330469877a 100644
--- a/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs
+++ b/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.IO;
@@ -87,10 +88,12 @@ namespace MediaBrowser.Server.Implementations.IO
private ILibraryManager LibraryManager { get; set; }
private IServerConfigurationManager ConfigurationManager { get; set; }
+ private readonly IFileSystem _fileSystem;
+
///
/// Initializes a new instance of the class.
///
- public DirectoryWatchers(ILogManager logManager, ITaskManager taskManager, ILibraryManager libraryManager, IServerConfigurationManager configurationManager)
+ public DirectoryWatchers(ILogManager logManager, ITaskManager taskManager, ILibraryManager libraryManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
{
if (taskManager == null)
{
@@ -101,6 +104,7 @@ namespace MediaBrowser.Server.Implementations.IO
TaskManager = taskManager;
Logger = logManager.GetLogger("DirectoryWatchers");
ConfigurationManager = configurationManager;
+ _fileSystem = fileSystem;
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
}
@@ -318,6 +322,18 @@ namespace MediaBrowser.Server.Implementations.IO
/// The source of the event.
/// The instance containing the event data.
void watcher_Changed(object sender, FileSystemEventArgs e)
+ {
+ try
+ {
+ OnWatcherChanged(e);
+ }
+ catch (IOException ex)
+ {
+ Logger.ErrorException("IOException in watcher changed", ex);
+ }
+ }
+
+ private void OnWatcherChanged(FileSystemEventArgs e)
{
var name = e.Name;
@@ -418,7 +434,7 @@ namespace MediaBrowser.Server.Implementations.IO
{
try
{
- var data = FileSystem.GetFileSystemInfo(path);
+ var data = _fileSystem.GetFileSystemInfo(path);
if (!data.Exists
|| data.Attributes.HasFlag(FileAttributes.Directory)
@@ -434,7 +450,7 @@ namespace MediaBrowser.Server.Implementations.IO
try
{
- using (new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
+ using (_fileSystem.GetFileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
//file is not locked
return false;
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index cbe15aa626..1aa9e5b9c1 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.Progress;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Configuration;
@@ -169,6 +170,8 @@ namespace MediaBrowser.Server.Implementations.Library
private readonly ConcurrentDictionary _userRootFolders =
new ConcurrentDictionary();
+ private readonly IFileSystem _fileSystem;
+
///
/// Initializes a new instance of the class.
///
@@ -177,7 +180,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// The user manager.
/// The configuration manager.
/// The user data repository.
- public LibraryManager(ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager, IUserDataManager userDataRepository, Func directoryWatchersFactory)
+ public LibraryManager(ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager, IUserDataManager userDataRepository, Func directoryWatchersFactory, IFileSystem fileSystem)
{
_logger = logger;
_taskManager = taskManager;
@@ -185,6 +188,7 @@ namespace MediaBrowser.Server.Implementations.Library
ConfigurationManager = configurationManager;
_userDataRepository = userDataRepository;
_directoryWatchersFactory = directoryWatchersFactory;
+ _fileSystem = fileSystem;
ByReferenceItems = new ConcurrentDictionary();
ConfigurationManager.ConfigurationUpdated += ConfigurationUpdated;
@@ -417,7 +421,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (item != null)
{
- ResolverHelper.SetInitialItemValues(item, args);
+ ResolverHelper.SetInitialItemValues(item, args, _fileSystem);
// Now handle the issue with posibly having the same item referenced from multiple physical
// places within the library. Be sure we always end up with just one instance.
@@ -482,7 +486,7 @@ namespace MediaBrowser.Server.Implementations.Library
// When resolving the root, we need it's grandchildren (children of user views)
var flattenFolderDepth = isPhysicalRoot ? 2 : 0;
- args.FileSystemDictionary = FileData.GetFilteredFileSystemEntries(args.Path, _logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf);
+ args.FileSystemDictionary = FileData.GetFilteredFileSystemEntries(args.Path, _fileSystem, _logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf);
// Need to remove subpaths that may have been resolved from shortcuts
// Example: if \\server\movies exists, then strip out \\server\movies\action
@@ -701,7 +705,7 @@ namespace MediaBrowser.Server.Implementations.Library
throw new ArgumentNullException();
}
- var validFilename = FileSystem.GetValidFilename(name).Trim();
+ var validFilename = _fileSystem.GetValidFilename(name).Trim();
string subFolderPrefix = null;
@@ -768,8 +772,8 @@ namespace MediaBrowser.Server.Implementations.Library
{
Name = name,
Id = id,
- DateCreated = fileInfo.CreationTimeUtc,
- DateModified = fileInfo.LastWriteTimeUtc,
+ DateCreated = _fileSystem.GetCreationTimeUtc(fileInfo),
+ DateModified = _fileSystem.GetLastWriteTimeUtc(fileInfo),
Path = path
};
isNew = true;
@@ -1066,7 +1070,7 @@ namespace MediaBrowser.Server.Implementations.Library
Name = Path.GetFileName(dir),
Locations = Directory.EnumerateFiles(dir, "*.mblink", SearchOption.TopDirectoryOnly)
- .Select(FileSystem.ResolveShortcut)
+ .Select(_fileSystem.ResolveShortcut)
.OrderBy(i => i)
.ToList(),
@@ -1150,7 +1154,7 @@ namespace MediaBrowser.Server.Implementations.Library
try
{
// Try to resolve the path into a video
- video = ResolvePath(FileSystem.GetFileSystemInfo(info.Path)) as Video;
+ video = ResolvePath(_fileSystem.GetFileSystemInfo(info.Path)) as Video;
if (video == null)
{
diff --git a/MediaBrowser.Server.Implementations/Library/ResolverHelper.cs b/MediaBrowser.Server.Implementations/Library/ResolverHelper.cs
index a6b13f8dd6..96057f8b7e 100644
--- a/MediaBrowser.Server.Implementations/Library/ResolverHelper.cs
+++ b/MediaBrowser.Server.Implementations/Library/ResolverHelper.cs
@@ -1,5 +1,7 @@
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Resolvers;
using System;
@@ -18,7 +20,8 @@ namespace MediaBrowser.Server.Implementations.Library
///
/// The item.
/// The args.
- public static void SetInitialItemValues(BaseItem item, ItemResolveArgs args)
+ /// The file system.
+ public static void SetInitialItemValues(BaseItem item, ItemResolveArgs args, IFileSystem fileSystem)
{
item.ResetResolveArgs(args);
@@ -48,7 +51,7 @@ namespace MediaBrowser.Server.Implementations.Library
item.DontFetchMeta = item.Path.IndexOf("[dontfetchmeta]", StringComparison.OrdinalIgnoreCase) != -1;
// Make sure DateCreated and DateModified have values
- EntityResolutionHelper.EnsureDates(item, args, true);
+ EntityResolutionHelper.EnsureDates(fileSystem, item, args, true);
}
///
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
index 9a2f6c6373..adf914766b 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
@@ -52,7 +52,8 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
// If there's a collection type and it's not tv, it can't be a series
if (!string.IsNullOrEmpty(collectionType) &&
- !string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
+ !string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) &&
+ !string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
{
return null;
}
diff --git a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
index c9777e54a6..0d428742ce 100644
--- a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
+++ b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
@@ -1,4 +1,6 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Localization;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
@@ -30,13 +32,16 @@ namespace MediaBrowser.Server.Implementations.Localization
private readonly ConcurrentDictionary> _allParentalRatings =
new ConcurrentDictionary>(StringComparer.OrdinalIgnoreCase);
+ private readonly IFileSystem _fileSystem;
+
///
/// Initializes a new instance of the class.
///
/// The configuration manager.
- public LocalizationManager(IServerConfigurationManager configurationManager)
+ public LocalizationManager(IServerConfigurationManager configurationManager, IFileSystem fileSystem)
{
_configurationManager = configurationManager;
+ _fileSystem = fileSystem;
ExtractAll();
}
@@ -65,7 +70,7 @@ namespace MediaBrowser.Server.Implementations.Localization
{
using (var stream = type.Assembly.GetManifestResourceStream(resource))
{
- using (var fs = new FileStream(Path.Combine(localizationPath, filename), FileMode.Create, FileAccess.Write, FileShare.Read))
+ using (var fs = _fileSystem.GetFileStream(Path.Combine(localizationPath, filename), FileMode.Create, FileAccess.Write, FileShare.Read))
{
stream.CopyTo(fs);
}
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index 05c5f5a826..017dc2b541 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -46,6 +46,14 @@
+
+ False
+ ..\packages\System.Data.SQLite.x86.1.0.89.0\lib\net45\System.Data.SQLite.dll
+
+
+ False
+ ..\packages\System.Data.SQLite.x86.1.0.89.0\lib\net45\System.Data.SQLite.Linq.dll
+
..\packages\Rx-Core.2.1.30214.0\lib\Net45\System.Reactive.Core.dll
@@ -88,12 +96,6 @@
..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll
-
- ..\packages\System.Data.SQLite.x86.1.0.88.0\lib\net45\System.Data.SQLite.dll
-
-
- ..\packages\System.Data.SQLite.x86.1.0.88.0\lib\net45\System.Data.SQLite.Linq.dll
-
..\packages\ServiceStack.OrmLite.Sqlite.Mono.3.9.64\lib\net35\Mono.Data.Sqlite.dll
diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs b/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs
index 785bbca7c1..a66f9c56ba 100644
--- a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs
+++ b/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.MediaInfo;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
@@ -53,6 +54,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// The FF probe resource pool
///
private readonly SemaphoreSlim _ffProbeResourcePool = new SemaphoreSlim(1, 1);
+ private readonly IFileSystem _fileSystem;
public string FFMpegPath { get; private set; }
@@ -61,12 +63,13 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
public string Version { get; private set; }
public MediaEncoder(ILogger logger, IApplicationPaths appPaths,
- IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, string version)
+ IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, string version, IFileSystem fileSystem)
{
_logger = logger;
_appPaths = appPaths;
_jsonSerializer = jsonSerializer;
Version = version;
+ _fileSystem = fileSystem;
FFProbePath = ffProbePath;
FFMpegPath = ffMpegPath;
}
@@ -458,8 +461,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-convert-" + Guid.NewGuid() + ".txt");
- var logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read,
- StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous);
+ var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true);
try
{
@@ -685,7 +687,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-extract-" + Guid.NewGuid() + ".txt");
- var logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous);
+ var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true);
try
{
diff --git a/MediaBrowser.Server.Implementations/Providers/ImageSaver.cs b/MediaBrowser.Server.Implementations/Providers/ImageSaver.cs
index a967c535e8..cbca2ba763 100644
--- a/MediaBrowser.Server.Implementations/Providers/ImageSaver.cs
+++ b/MediaBrowser.Server.Implementations/Providers/ImageSaver.cs
@@ -35,16 +35,18 @@ namespace MediaBrowser.Server.Implementations.Providers
/// The _directory watchers
///
private readonly IDirectoryWatchers _directoryWatchers;
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
///
/// The config.
/// The directory watchers.
- public ImageSaver(IServerConfigurationManager config, IDirectoryWatchers directoryWatchers)
+ public ImageSaver(IServerConfigurationManager config, IDirectoryWatchers directoryWatchers, IFileSystem fileSystem)
{
_config = config;
_directoryWatchers = directoryWatchers;
+ _fileSystem = fileSystem;
_remoteImageCache = new FileSystemRepository(config.ApplicationPaths.DownloadedImagesDataPath);
}
@@ -67,30 +69,20 @@ namespace MediaBrowser.Server.Implementations.Providers
throw new ArgumentNullException("mimeType");
}
- var saveLocally = _config.Configuration.SaveLocalMeta;
+ var saveLocally = _config.Configuration.SaveLocalMeta || item is IItemByName || item is User;
- if (item is IItemByName)
- {
- saveLocally = true;
- }
- else if (item is User)
- {
- saveLocally = true;
- }
- else if (item is Audio || item.Parent == null || string.IsNullOrEmpty(item.MetaLocation))
+ if (item is Audio || item.Parent == null)
{
saveLocally = false;
}
- if (type != ImageType.Primary)
+ if (type != ImageType.Primary && item is Episode)
{
- if (item is Episode)
- {
- saveLocally = false;
- }
+ saveLocally = false;
}
- if (item.LocationType == LocationType.Remote || item.LocationType == LocationType.Virtual)
+ var locationType = item.LocationType;
+ if (locationType == LocationType.Remote || locationType == LocationType.Virtual)
{
saveLocally = false;
}
@@ -186,7 +178,7 @@ namespace MediaBrowser.Server.Implementations.Providers
}
}
- using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
+ using (var fs = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
await source.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false);
}
@@ -373,7 +365,7 @@ namespace MediaBrowser.Server.Implementations.Providers
path = GetSavePathForItemInMixedFolder(item, type, filename, extension);
}
- if (string.IsNullOrEmpty(path) && !string.IsNullOrEmpty(item.MetaLocation))
+ if (string.IsNullOrEmpty(path))
{
path = Path.Combine(item.MetaLocation, filename + extension);
}
diff --git a/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs b/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs
index 19230cecdb..af89122db1 100644
--- a/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs
+++ b/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs
@@ -13,6 +13,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Providers;
namespace MediaBrowser.Server.Implementations.Providers
{
@@ -48,6 +49,9 @@ namespace MediaBrowser.Server.Implementations.Providers
/// The metadata providers enumerable.
private BaseMetadataProvider[] MetadataProviders { get; set; }
+ private IImageProvider[] ImageProviders { get; set; }
+ private readonly IFileSystem _fileSystem;
+
///
/// Initializes a new instance of the class.
///
@@ -55,22 +59,25 @@ namespace MediaBrowser.Server.Implementations.Providers
/// The configuration manager.
/// The directory watchers.
/// The log manager.
- /// The library manager.
- public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, IDirectoryWatchers directoryWatchers, ILogManager logManager, ILibraryManager libraryManager)
+ public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, IDirectoryWatchers directoryWatchers, ILogManager logManager, IFileSystem fileSystem)
{
_logger = logManager.GetLogger("ProviderManager");
_httpClient = httpClient;
ConfigurationManager = configurationManager;
_directoryWatchers = directoryWatchers;
+ _fileSystem = fileSystem;
}
///
/// Adds the metadata providers.
///
/// The providers.
- public void AddParts(IEnumerable providers)
+ /// The image providers.
+ public void AddParts(IEnumerable providers, IEnumerable imageProviders)
{
MetadataProviders = providers.OrderBy(e => e.Priority).ToArray();
+
+ ImageProviders = imageProviders.ToArray();
}
///
@@ -288,7 +295,7 @@ namespace MediaBrowser.Server.Implementations.Providers
{
using (dataToSave)
{
- using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
+ using (var fs = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
await dataToSave.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false);
}
@@ -342,7 +349,60 @@ namespace MediaBrowser.Server.Implementations.Providers
/// Task.
public Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, string sourceUrl, CancellationToken cancellationToken)
{
- return new ImageSaver(ConfigurationManager, _directoryWatchers).SaveImage(item, source, mimeType, type, imageIndex, sourceUrl, cancellationToken);
+ return new ImageSaver(ConfigurationManager, _directoryWatchers, _fileSystem).SaveImage(item, source, mimeType, type, imageIndex, sourceUrl, cancellationToken);
+ }
+
+ ///
+ /// Gets the available remote images.
+ ///
+ /// The item.
+ /// The type.
+ /// The cancellation token.
+ /// Task{IEnumerable{RemoteImageInfo}}.
+ public async Task> GetAvailableRemoteImages(BaseItem item, ImageType type, CancellationToken cancellationToken)
+ {
+ var providers = GetSupportedImageProviders(item, type);
+
+ var tasks = providers.Select(i => Task.Run(async () =>
+ {
+ try
+ {
+ var result = await i.GetAvailableImages(item, type, cancellationToken).ConfigureAwait(false);
+ return result.ToList();
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("{0} failed in GetAvailableImages for type {1}", ex, i.GetType().Name, item.GetType().Name);
+ return new List();
+ }
+ }));
+
+ var results = await Task.WhenAll(tasks).ConfigureAwait(false);
+
+ return results.SelectMany(i => i);
+ }
+
+ ///
+ /// Gets the supported image providers.
+ ///
+ /// The item.
+ /// The type.
+ /// IEnumerable{IImageProvider}.
+ private IEnumerable GetSupportedImageProviders(BaseItem item, ImageType type)
+ {
+ return ImageProviders.Where(i =>
+ {
+ try
+ {
+ return i.Supports(item, type);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("{0} failed in Supports for type {1}", ex, i.GetType().Name, item.GetType().Name);
+ return false;
+ }
+
+ });
}
}
}
diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config
index 771a5c8b2a..eeeedfe362 100644
--- a/MediaBrowser.Server.Implementations/packages.config
+++ b/MediaBrowser.Server.Implementations/packages.config
@@ -14,5 +14,5 @@
-
+
\ No newline at end of file
diff --git a/MediaBrowser.Server.Mono/IO/FileSystemFactory.cs b/MediaBrowser.Server.Mono/IO/FileSystemFactory.cs
new file mode 100644
index 0000000000..4a424a2824
--- /dev/null
+++ b/MediaBrowser.Server.Mono/IO/FileSystemFactory.cs
@@ -0,0 +1,21 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Common.Implementations.IO;
+
+namespace MediaBrowser.ServerApplication.IO
+{
+ ///
+ /// Class FileSystemFactory
+ ///
+ public static class FileSystemFactory
+ {
+ ///
+ /// Creates the file system manager.
+ ///
+ /// IFileSystem.
+ public static IFileSystem CreateFileSystemManager(ILogManager logManager)
+ {
+ return new CommonFileSystem(logManager.GetLogger("FileSystem"), false);
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
index 2c99f3370a..900169c707 100644
--- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
+++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
@@ -88,6 +88,7 @@
FFMpeg\FFMpegDownloader.cs
+
@@ -129,6 +130,7 @@
+
diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs
index 6d3cbcf26b..057a2456f5 100644
--- a/MediaBrowser.Server.Mono/Program.cs
+++ b/MediaBrowser.Server.Mono/Program.cs
@@ -17,6 +17,7 @@ using System.Security.Cryptography.X509Certificates;
using Gtk;
using Gdk;
using System.Threading.Tasks;
+using System.Reflection;
namespace MediaBrowser.Server.Mono
{
@@ -203,6 +204,8 @@ namespace MediaBrowser.Server.Mono
logger.Info("Server: {0}", Environment.MachineName);
logger.Info("Operating system: {0}", Environment.OSVersion.ToString());
+
+ MonoBug11817WorkAround.Apply ();
}
///
@@ -280,4 +283,34 @@ namespace MediaBrowser.Server.Mono
return true;
}
}
+
+ public class MonoBug11817WorkAround
+ {
+ public static void Apply()
+ {
+ var property = typeof(TimeZoneInfo).GetProperty("TimeZoneDirectory", BindingFlags.Static | BindingFlags.NonPublic);
+
+ if (property == null) return;
+
+ var zoneInfo = FindZoneInfoFolder();
+ property.SetValue(null, zoneInfo, new object[0]);
+ }
+
+ public static string FindZoneInfoFolder()
+ {
+ var current = new DirectoryInfo(Directory.GetCurrentDirectory());
+
+ while(current != null)
+ {
+ var zoneinfoTestPath = Path.Combine(current.FullName, "zoneinfo");
+
+ if (Directory.Exists(zoneinfoTestPath))
+ return zoneinfoTestPath;
+
+ current = current.Parent;
+ }
+
+ return null;
+ }
+ }
}
diff --git a/MediaBrowser.ServerApplication/App.config b/MediaBrowser.ServerApplication/App.config
index a5cbacb614..4f60de1457 100644
--- a/MediaBrowser.ServerApplication/App.config
+++ b/MediaBrowser.ServerApplication/App.config
@@ -41,6 +41,10 @@
+
+
+
+
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index 8ae5e34c28..0ec1d68135 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -5,6 +5,7 @@ using MediaBrowser.Common.Constants;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Implementations;
using MediaBrowser.Common.Implementations.ScheduledTasks;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
@@ -47,6 +48,7 @@ using MediaBrowser.Server.Implementations.ServerManager;
using MediaBrowser.Server.Implementations.Session;
using MediaBrowser.Server.Implementations.WebSocket;
using MediaBrowser.ServerApplication.FFMpeg;
+using MediaBrowser.ServerApplication.IO;
using MediaBrowser.ServerApplication.Native;
using MediaBrowser.ServerApplication.Networking;
using MediaBrowser.WebDashboard.Api;
@@ -234,7 +236,7 @@ namespace MediaBrowser.ServerApplication
await base.RegisterResources().ConfigureAwait(false);
- RegisterSingleInstance(new HttpResultFactory(LogManager));
+ RegisterSingleInstance(new HttpResultFactory(LogManager, FileSystemManager));
RegisterSingleInstance(this);
RegisterSingleInstance(ApplicationPaths);
@@ -263,13 +265,13 @@ namespace MediaBrowser.ServerApplication
UserManager = new UserManager(Logger, ServerConfigurationManager, UserRepository);
RegisterSingleInstance(UserManager);
- LibraryManager = new LibraryManager(Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => DirectoryWatchers);
+ LibraryManager = new LibraryManager(Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => DirectoryWatchers, FileSystemManager);
RegisterSingleInstance(LibraryManager);
- DirectoryWatchers = new DirectoryWatchers(LogManager, TaskManager, LibraryManager, ServerConfigurationManager);
+ DirectoryWatchers = new DirectoryWatchers(LogManager, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager);
RegisterSingleInstance(DirectoryWatchers);
- ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, DirectoryWatchers, LogManager, LibraryManager);
+ ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, DirectoryWatchers, LogManager, FileSystemManager);
RegisterSingleInstance(ProviderManager);
RegisterSingleInstance(() => new LuceneSearchEngine(ApplicationPaths, LogManager, LibraryManager));
@@ -283,10 +285,10 @@ namespace MediaBrowser.ServerApplication
ServerManager = new ServerManager(this, JsonSerializer, Logger, ServerConfigurationManager);
RegisterSingleInstance(ServerManager);
- LocalizationManager = new LocalizationManager(ServerConfigurationManager);
+ LocalizationManager = new LocalizationManager(ServerConfigurationManager, FileSystemManager);
RegisterSingleInstance(LocalizationManager);
- ImageProcessor = new ImageProcessor(Logger, ServerConfigurationManager.ApplicationPaths);
+ ImageProcessor = new ImageProcessor(Logger, ServerConfigurationManager.ApplicationPaths, FileSystemManager);
RegisterSingleInstance(ImageProcessor);
DtoService = new DtoService(Logger, LibraryManager, UserManager, UserDataManager, ItemRepository, ImageProcessor);
@@ -311,15 +313,20 @@ namespace MediaBrowser.ServerApplication
return new NetworkManager();
}
+ protected override IFileSystem CreateFileSystemManager()
+ {
+ return FileSystemFactory.CreateFileSystemManager(LogManager);
+ }
+
///
/// Registers the media encoder.
///
/// Task.
private async Task RegisterMediaEncoder()
{
- var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient).GetFFMpegInfo().ConfigureAwait(false);
+ var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager).GetFFMpegInfo().ConfigureAwait(false);
- MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), ApplicationPaths, JsonSerializer, info.Path, info.ProbePath, info.Version);
+ MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), ApplicationPaths, JsonSerializer, info.Path, info.ProbePath, info.Version, FileSystemManager);
RegisterSingleInstance(MediaEncoder);
}
@@ -329,7 +336,7 @@ namespace MediaBrowser.ServerApplication
private void SetKernelProperties()
{
Parallel.Invoke(
- () => ServerKernel.FFMpegManager = new FFMpegManager(ApplicationPaths, MediaEncoder, Logger, ItemRepository),
+ () => ServerKernel.FFMpegManager = new FFMpegManager(ApplicationPaths, MediaEncoder, Logger, ItemRepository, FileSystemManager),
() => LocalizedStrings.StringFiles = GetExports(),
SetStaticProperties
);
@@ -412,6 +419,7 @@ namespace MediaBrowser.ServerApplication
User.UserManager = UserManager;
LocalizedStrings.ApplicationPaths = ApplicationPaths;
Folder.UserManager = UserManager;
+ BaseItem.FileSystem = FileSystemManager;
}
///
@@ -442,7 +450,7 @@ namespace MediaBrowser.ServerApplication
GetExports(),
GetExports());
- ProviderManager.AddParts(GetExports());
+ ProviderManager.AddParts(GetExports(), GetExports());
ImageProcessor.AddParts(GetExports());
diff --git a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs
index 69025c9eb0..e8af0a13e7 100644
--- a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs
+++ b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
@@ -20,18 +21,20 @@ namespace MediaBrowser.ServerApplication.FFMpeg
private readonly IApplicationPaths _appPaths;
private readonly ILogger _logger;
private readonly IZipClient _zipClient;
+ private readonly IFileSystem _fileSystem;
private readonly string[] _fontUrls = new[]
{
"https://www.dropbox.com/s/pj847twf7riq0j7/ARIALUNI.7z?dl=1"
};
- public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient)
+ public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient, IFileSystem fileSystem)
{
_logger = logger;
_appPaths = appPaths;
_httpClient = httpClient;
_zipClient = zipClient;
+ _fileSystem = fileSystem;
}
public async Task GetFFMpegInfo()
@@ -272,9 +275,8 @@ namespace MediaBrowser.ServerApplication.FFMpeg
var bytes = Encoding.UTF8.GetBytes(contents);
- using (var fileStream = new FileStream(fontConfigFile, FileMode.Create, FileAccess.Write,
- FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize,
- FileOptions.Asynchronous))
+ using (var fileStream = _fileSystem.GetFileStream(fontConfigFile, FileMode.Create, FileAccess.Write,
+ FileShare.Read, true))
{
await fileStream.WriteAsync(bytes, 0, bytes.Length);
}
diff --git a/MediaBrowser.ServerApplication/IO/FileSystemFactory.cs b/MediaBrowser.ServerApplication/IO/FileSystemFactory.cs
new file mode 100644
index 0000000000..698c4b616f
--- /dev/null
+++ b/MediaBrowser.ServerApplication/IO/FileSystemFactory.cs
@@ -0,0 +1,21 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.Logging;
+
+namespace MediaBrowser.ServerApplication.IO
+{
+ ///
+ /// Class FileSystemFactory
+ ///
+ public static class FileSystemFactory
+ {
+ ///
+ /// Creates the file system manager.
+ ///
+ /// IFileSystem.
+ public static IFileSystem CreateFileSystemManager(ILogManager logManager)
+ {
+ return new NativeFileSystem(logManager.GetLogger("FileSystem"));
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/IO/NativeMethods.cs b/MediaBrowser.ServerApplication/IO/NativeFileSystem.cs
similarity index 90%
rename from MediaBrowser.Controller/IO/NativeMethods.cs
rename to MediaBrowser.ServerApplication/IO/NativeFileSystem.cs
index 97c7dfe875..5320c52507 100644
--- a/MediaBrowser.Controller/IO/NativeMethods.cs
+++ b/MediaBrowser.ServerApplication/IO/NativeFileSystem.cs
@@ -1,11 +1,56 @@
-using System;
+using MediaBrowser.Common.Implementations.IO;
+using MediaBrowser.Model.Logging;
+using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
-namespace MediaBrowser.Controller.IO
+namespace MediaBrowser.ServerApplication.IO
{
+ public class NativeFileSystem : CommonFileSystem
+ {
+ public NativeFileSystem(ILogger logger)
+ : base(logger, true)
+ {
+ }
+
+ public override bool IsShortcut(string filename)
+ {
+ return base.IsShortcut(filename) ||
+ string.Equals(Path.GetExtension(filename), ".lnk", StringComparison.OrdinalIgnoreCase);
+ }
+
+ public override string ResolveShortcut(string filename)
+ {
+ var path = base.ResolveShortcut(filename);
+
+ if (!string.IsNullOrEmpty(path))
+ {
+ return path;
+ }
+
+ if (string.Equals(Path.GetExtension(filename), ".lnk", StringComparison.OrdinalIgnoreCase))
+ {
+ return ResolveLnk(filename);
+ }
+
+ return null;
+ }
+
+ private string ResolveLnk(string filename)
+ {
+ var link = new ShellLink();
+ ((IPersistFile)link).Load(filename, NativeMethods.STGM_READ);
+ // TODO: if I can get hold of the hwnd call resolve first. This handles moved and renamed files.
+ // ((IShellLinkW)link).Resolve(hwnd, 0)
+ var sb = new StringBuilder(NativeMethods.MAX_PATH);
+ WIN32_FIND_DATA data;
+ ((IShellLinkW)link).GetPath(sb, sb.Capacity, out data, 0);
+ return sb.ToString();
+ }
+ }
+
///
/// Class NativeMethods
///
@@ -46,7 +91,6 @@ namespace MediaBrowser.Controller.IO
public uint dwHighDateTime;
}
-
///
/// Struct WIN32_FIND_DATA
///
@@ -184,7 +228,6 @@ namespace MediaBrowser.Controller.IO
SLR_INVOKE_MSI = 0x80
}
-
///
/// The IShellLink interface allows Shell links to be created, modified, and resolved
///
@@ -311,7 +354,6 @@ namespace MediaBrowser.Controller.IO
void GetClassID(out Guid pClassID);
}
-
///
/// Interface IPersistFile
///
@@ -374,4 +416,5 @@ namespace MediaBrowser.Controller.IO
public class ShellLink
{
}
+
}
diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs
index 3d45f143bc..d3eed5c484 100644
--- a/MediaBrowser.ServerApplication/MainStartup.cs
+++ b/MediaBrowser.ServerApplication/MainStartup.cs
@@ -214,8 +214,6 @@ namespace MediaBrowser.ServerApplication
SystemEvents.SessionEnding += SystemEvents_SessionEnding;
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
- MigrateShortcuts(appPaths.RootFolderPath);
-
_appHost = new ApplicationHost(appPaths, logManager);
_app = new App(_appHost, _appHost.LogManager.GetLogger("App"), runService);
@@ -537,34 +535,5 @@ namespace MediaBrowser.ServerApplication
///
SEM_NOOPENFILEERRORBOX = 0x8000
}
-
- private static void MigrateShortcuts(string directory)
- {
- Directory.CreateDirectory(directory);
-
- foreach (var file in Directory.EnumerateFiles(directory, "*.lnk", SearchOption.AllDirectories).ToList())
- {
- MigrateShortcut(file);
- }
- }
-
- private static void MigrateShortcut(string file)
- {
- var newFile = Path.ChangeExtension(file, ".mblink");
-
- try
- {
- var resolvedPath = FileSystem.ResolveShortcut(file);
-
- if (!string.IsNullOrEmpty(resolvedPath))
- {
- FileSystem.CreateShortcut(newFile, resolvedPath);
- }
- }
- finally
- {
- File.Delete(file);
- }
- }
}
}
diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
index c39ee40a8c..f24283e70d 100644
--- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
+++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
@@ -157,9 +157,9 @@
False
..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll
-
+
False
- ..\packages\SimpleInjector.2.3.5\lib\net40-client\SimpleInjector.dll
+ ..\packages\SimpleInjector.2.3.6\lib\net40-client\SimpleInjector.dll
@@ -188,9 +188,11 @@
+
+
diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config
index 4af6fa65e0..0893a1b38a 100644
--- a/MediaBrowser.ServerApplication/packages.config
+++ b/MediaBrowser.ServerApplication/packages.config
@@ -8,5 +8,5 @@
-
+
\ No newline at end of file
diff --git a/MediaBrowser.Tests/MediaBrowser.Tests.csproj b/MediaBrowser.Tests/MediaBrowser.Tests.csproj
index a7a7ac2433..95e55fda0c 100644
--- a/MediaBrowser.Tests/MediaBrowser.Tests.csproj
+++ b/MediaBrowser.Tests/MediaBrowser.Tests.csproj
@@ -50,6 +50,7 @@
+
@@ -63,6 +64,10 @@
{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}
MediaBrowser.Model
+
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}
+ MediaBrowser.Providers
+
diff --git a/MediaBrowser.Tests/Providers/MovieDbProviderTests.cs b/MediaBrowser.Tests/Providers/MovieDbProviderTests.cs
new file mode 100644
index 0000000000..f7a87c9d47
--- /dev/null
+++ b/MediaBrowser.Tests/Providers/MovieDbProviderTests.cs
@@ -0,0 +1,36 @@
+using MediaBrowser.Providers.Movies;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace MediaBrowser.Tests.Providers {
+ [TestClass]
+ public class MovieDbProviderTests {
+ [TestMethod]
+ public void TestNameMatches() {
+ var name = string.Empty;
+ int? year = null;
+ MovieDbProvider.ParseName("My Movie (2013)", out name, out year);
+ Assert.AreEqual("My Movie", name);
+ Assert.AreEqual(2013, year);
+ name = string.Empty;
+ year = null;
+ MovieDbProvider.ParseName("My Movie 2 (2013)", out name, out year);
+ Assert.AreEqual("My Movie 2", name);
+ Assert.AreEqual(2013, year);
+ name = string.Empty;
+ year = null;
+ MovieDbProvider.ParseName("My Movie 2001 (2013)", out name, out year);
+ Assert.AreEqual("My Movie 2001", name);
+ Assert.AreEqual(2013, year);
+ name = string.Empty;
+ year = null;
+ MovieDbProvider.ParseName("My Movie - 2 (2013)", out name, out year);
+ Assert.AreEqual("My Movie - 2", name);
+ Assert.AreEqual(2013, year);
+ name = string.Empty;
+ year = null;
+ MovieDbProvider.ParseName("curse.of.chucky.2013.stv.unrated.multi.1080p.bluray.x264-rough", out name, out year);
+ Assert.AreEqual("curse.of.chucky", name);
+ Assert.AreEqual(2013, year);
+ }
+ }
+}
\ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs
index 2c6b5532b8..1c6cdad39b 100644
--- a/MediaBrowser.WebDashboard/Api/DashboardService.cs
+++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs
@@ -5,6 +5,7 @@ using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Logging;
@@ -118,6 +119,7 @@ namespace MediaBrowser.WebDashboard.Api
private readonly ISessionManager _sessionManager;
private readonly IDtoService _dtoService;
+ private readonly IFileSystem _fileSystem;
///
/// Initializes a new instance of the class.
@@ -126,13 +128,14 @@ namespace MediaBrowser.WebDashboard.Api
/// The app host.
/// The server configuration manager.
/// The session manager.
- public DashboardService(ITaskManager taskManager, IServerApplicationHost appHost, IServerConfigurationManager serverConfigurationManager, ISessionManager sessionManager, IDtoService dtoService)
+ public DashboardService(ITaskManager taskManager, IServerApplicationHost appHost, IServerConfigurationManager serverConfigurationManager, ISessionManager sessionManager, IDtoService dtoService, IFileSystem fileSystem)
{
_taskManager = taskManager;
_appHost = appHost;
_serverConfigurationManager = serverConfigurationManager;
_sessionManager = sessionManager;
_dtoService = dtoService;
+ _fileSystem = fileSystem;
}
///
@@ -324,7 +327,7 @@ namespace MediaBrowser.WebDashboard.Api
/// Task{Stream}.
private Stream GetRawResourceStream(string path)
{
- return new FileStream(GetDashboardResourcePath(path), FileMode.Open, FileAccess.Read, FileShare.ReadWrite, StreamDefaults.DefaultFileStreamBufferSize, true);
+ return _fileSystem.GetFileStream(GetDashboardResourcePath(path), FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true);
}
///
@@ -611,7 +614,7 @@ namespace MediaBrowser.WebDashboard.Api
{
path = GetDashboardResourcePath(path);
- using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, StreamDefaults.DefaultFileStreamBufferSize, true))
+ using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true))
{
using (var streamReader = new StreamReader(fs))
{
diff --git a/MediaBrowser.WebDashboard/ApiClient.js b/MediaBrowser.WebDashboard/ApiClient.js
index 97a443e844..3606396652 100644
--- a/MediaBrowser.WebDashboard/ApiClient.js
+++ b/MediaBrowser.WebDashboard/ApiClient.js
@@ -306,6 +306,24 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
});
};
+ self.getAvailableRemoteImages = function (itemId, imageType) {
+
+ if (!itemId) {
+ throw new Error("null itemId");
+ }
+ if (!imageType) {
+ throw new Error("null imageType");
+ }
+
+ var url = self.getUrl("Items/" + itemId + "/RemoteImages/" + imageType);
+
+ return self.ajax({
+ type: "GET",
+ url: url,
+ dataType: "json"
+ });
+ };
+
/**
* Gets the current server status
*/
@@ -2731,16 +2749,17 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
});
};
- /**
- * Marks an item as played or unplayed
- * This should not be used to update playstate following playback.
- * There are separate playstate check-in methods for that. This should be used for a
- * separate option to reset playstate.
- * @param {String} userId
- * @param {String} itemId
- * @param {Boolean} wasPlayed
- */
- self.updatePlayedStatus = function (userId, itemId, wasPlayed) {
+ self.getDateParamValue = function (date) {
+ function formatDigit(i) {
+ return i < 10 ? "0" + i : i;
+ }
+
+ var d = date;
+
+ return "" + d.getFullYear() + formatDigit(d.getMonth() + 1) + formatDigit(d.getDate()) + formatDigit(d.getHours()) + formatDigit(d.getMinutes()) + formatDigit(d.getSeconds());
+ };
+
+ self.markPlayed = function (userId, itemId, date) {
if (!userId) {
throw new Error("null userId");
@@ -2750,12 +2769,35 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
throw new Error("null itemId");
}
- var url = self.getUrl("Users/" + userId + "/PlayedItems/" + itemId);
+ var options = {};
+
+ if (date) {
+ options.DatePlayed = self.getDateParamValue(date);
+ }
- var method = wasPlayed ? "POST" : "DELETE";
+ var url = self.getUrl("Users/" + userId + "/PlayedItems/" + itemId, options);
return self.ajax({
- type: method,
+ type: "POST",
+ url: url,
+ dataType: "json"
+ });
+ };
+
+ self.markUnplayed = function (userId, itemId) {
+
+ if (!userId) {
+ throw new Error("null userId");
+ }
+
+ if (!itemId) {
+ throw new Error("null itemId");
+ }
+
+ var url = self.getUrl("Users/" + userId + "/PlayedItems/" + itemId);
+
+ return self.ajax({
+ type: "DELETE",
url: url,
dataType: "json"
});
diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config
index 9c48b38095..22560b1331 100644
--- a/MediaBrowser.WebDashboard/packages.config
+++ b/MediaBrowser.WebDashboard/packages.config
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/MediaBrowser.sln.GhostDoc.xml b/MediaBrowser.sln.GhostDoc.xml
new file mode 100644
index 0000000000..73f7a08ba7
--- /dev/null
+++ b/MediaBrowser.sln.GhostDoc.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+ D:\Development\MediaBrowser\Help
+
+
+ true
+ false
+ false
+ false
+
+
+ true
+ false
+ false
+ false
+ true
+ false
+
+
+ true
+
+
+
+
+
+
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec
index 1dd6ed0f10..0588442e1a 100644
--- a/Nuget/MediaBrowser.Common.Internal.nuspec
+++ b/Nuget/MediaBrowser.Common.Internal.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Common.Internal
- 3.0.232
+ 3.0.234
MediaBrowser.Common.Internal
Luke
ebr,Luke,scottisafool
@@ -12,10 +12,10 @@
Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.
Copyright © Media Browser 2013
-
+
-
+
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index cc3d1c7e59..6712fad0c3 100644
--- a/Nuget/MediaBrowser.Common.nuspec
+++ b/Nuget/MediaBrowser.Common.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Common
- 3.0.232
+ 3.0.234
MediaBrowser.Common
Media Browser Team
ebr,Luke,scottisafool
diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec
index 0e7fa7fbfe..c4704f9b33 100644
--- a/Nuget/MediaBrowser.Server.Core.nuspec
+++ b/Nuget/MediaBrowser.Server.Core.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Server.Core
- 3.0.232
+ 3.0.234
Media Browser.Server.Core
Media Browser Team
ebr,Luke,scottisafool
@@ -12,7 +12,7 @@
Contains core components required to build plugins for Media Browser Server.
Copyright © Media Browser 2013
-
+