mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-21 17:44:43 +01:00
Merge branch 'master' of https://github.com/MediaBrowser/MediaBrowser
This commit is contained in:
@@ -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; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String" /> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<BaseItem, bool>(currentChild, true));
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Episode>().All(i => i.IsMissingEpisode); }
|
||||
}
|
||||
|
||||
public bool IsUnaired
|
||||
{
|
||||
get { return Children.OfType<Episode>().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<Episode>().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <param name="fileSystem">The file system.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="args">The args.</param>
|
||||
/// <param name="searchPattern">The search pattern.</param>
|
||||
@@ -22,7 +24,7 @@ namespace MediaBrowser.Controller.IO
|
||||
/// <param name="resolveShortcuts">if set to <c>true</c> [resolve shortcuts].</param>
|
||||
/// <returns>Dictionary{System.StringFileSystemInfo}.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">path</exception>
|
||||
public static Dictionary<string, FileSystemInfo> GetFilteredFileSystemEntries(string path, ILogger logger, ItemResolveArgs args, string searchPattern = "*", int flattenFolderDepth = 0, bool resolveShortcuts = true)
|
||||
public static Dictionary<string, FileSystemInfo> 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;
|
||||
}
|
||||
|
||||
@@ -1,384 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace MediaBrowser.Controller.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// Class FileSystem
|
||||
/// </summary>
|
||||
public static class FileSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the file system info.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns>FileSystemInfo.</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
return new FileInfo(path);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the creation time UTC.
|
||||
/// </summary>
|
||||
/// <param name="info">The info.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <returns>DateTime.</returns>
|
||||
public static DateTime GetLastWriteTimeUtc(FileSystemInfo info, ILogger logger)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the creation time UTC.
|
||||
/// </summary>
|
||||
/// <param name="info">The info.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <returns>DateTime.</returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The space char
|
||||
/// </summary>
|
||||
private const char SpaceChar = ' ';
|
||||
/// <summary>
|
||||
/// The invalid file name chars
|
||||
/// </summary>
|
||||
private static readonly char[] InvalidFileNameChars = Path.GetInvalidFileNameChars();
|
||||
|
||||
/// <summary>
|
||||
/// Takes a filename and removes invalid characters
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">filename</exception>
|
||||
public static string GetValidFilename(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);
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolves the shortcut.
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">filename</exception>
|
||||
public static string ResolveShortcut(string filename)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filename))
|
||||
{
|
||||
throw new ArgumentNullException("filename");
|
||||
}
|
||||
|
||||
if (string.Equals(Path.GetExtension(filename), ".mblink", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a shortcut file pointing to a specified path
|
||||
/// </summary>
|
||||
/// <param name="shortcutPath">The shortcut path.</param>
|
||||
/// <param name="target">The target.</param>
|
||||
/// <exception cref="System.ArgumentNullException">shortcutPath</exception>
|
||||
public static void CreateShortcut(string shortcutPath, string target)
|
||||
{
|
||||
if (string.IsNullOrEmpty(shortcutPath))
|
||||
{
|
||||
throw new ArgumentNullException("shortcutPath");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(target))
|
||||
{
|
||||
throw new ArgumentNullException("target");
|
||||
}
|
||||
|
||||
File.WriteAllText(shortcutPath, target);
|
||||
|
||||
//var link = new ShellLink();
|
||||
|
||||
//((IShellLinkW)link).SetPath(target);
|
||||
|
||||
//((IPersistFile)link).Save(shortcutPath, true);
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, string> ShortcutExtensionsDictionary = new[] { ".mblink", ".lnk" }
|
||||
.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified filename is shortcut.
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename.</param>
|
||||
/// <returns><c>true</c> if the specified filename is shortcut; otherwise, <c>false</c>.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">filename</exception>
|
||||
public static bool IsShortcut(string filename)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filename))
|
||||
{
|
||||
throw new ArgumentNullException("filename");
|
||||
}
|
||||
|
||||
var extension = Path.GetExtension(filename);
|
||||
|
||||
return !string.IsNullOrEmpty(extension) && ShortcutExtensionsDictionary.ContainsKey(extension);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies all.
|
||||
/// </summary>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="target">The target.</param>
|
||||
/// <exception cref="System.ArgumentNullException">source</exception>
|
||||
/// <exception cref="System.ArgumentException">The source and target directories are the same</exception>
|
||||
public static void CopyAll(string source, string target)
|
||||
{
|
||||
if (string.IsNullOrEmpty(source))
|
||||
{
|
||||
throw new ArgumentNullException("source");
|
||||
}
|
||||
if (string.IsNullOrEmpty(target))
|
||||
{
|
||||
throw new ArgumentNullException("target");
|
||||
}
|
||||
|
||||
if (source.Equals(target, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new ArgumentException("The source and target directories are the same");
|
||||
}
|
||||
|
||||
// Check if the target directory exists, if not, create it.
|
||||
Directory.CreateDirectory(target);
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(source))
|
||||
{
|
||||
File.Copy(file, Path.Combine(target, Path.GetFileName(file)), true);
|
||||
}
|
||||
|
||||
// Copy each subdirectory using recursion.
|
||||
foreach (var dir in Directory.EnumerateDirectories(source))
|
||||
{
|
||||
CopyAll(dir, Path.Combine(target, Path.GetFileName(dir)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the ini file.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns>NameValueCollection.</returns>
|
||||
public static NameValueCollection ParseIniFile(string path)
|
||||
{
|
||||
var values = new NameValueCollection();
|
||||
|
||||
foreach (var line in File.ReadAllLines(path))
|
||||
{
|
||||
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 values;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adapted from http://stackoverflow.com/questions/309495/windows-shortcut-lnk-parser-in-java
|
||||
/// </summary>
|
||||
internal class WindowsShortcut
|
||||
{
|
||||
public bool IsDirectory { get; private set; }
|
||||
public bool IsLocal { get; private set; }
|
||||
public string ResolvedPath { get; private set; }
|
||||
|
||||
public WindowsShortcut(string file)
|
||||
{
|
||||
ParseLink(File.ReadAllBytes(file), Encoding.UTF8);
|
||||
}
|
||||
|
||||
private static bool isMagicPresent(byte[] link)
|
||||
{
|
||||
|
||||
const int magic = 0x0000004C;
|
||||
const int magic_offset = 0x00;
|
||||
|
||||
return link.Length >= 32 && bytesToDword(link, magic_offset) == magic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gobbles up link data by parsing it and storing info in member fields
|
||||
* @param link all the bytes from the .lnk file
|
||||
*/
|
||||
private void ParseLink(byte[] link, Encoding encoding)
|
||||
{
|
||||
if (!isMagicPresent(link))
|
||||
throw new IOException("Invalid shortcut; magic is missing", 0);
|
||||
|
||||
// get the flags byte
|
||||
byte flags = link[0x14];
|
||||
|
||||
// get the file attributes byte
|
||||
const int file_atts_offset = 0x18;
|
||||
byte file_atts = link[file_atts_offset];
|
||||
byte is_dir_mask = (byte)0x10;
|
||||
if ((file_atts & is_dir_mask) > 0)
|
||||
{
|
||||
IsDirectory = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsDirectory = false;
|
||||
}
|
||||
|
||||
// if the shell settings are present, skip them
|
||||
const int shell_offset = 0x4c;
|
||||
const byte has_shell_mask = (byte)0x01;
|
||||
int shell_len = 0;
|
||||
if ((flags & has_shell_mask) > 0)
|
||||
{
|
||||
// the plus 2 accounts for the length marker itself
|
||||
shell_len = bytesToWord(link, shell_offset) + 2;
|
||||
}
|
||||
|
||||
// get to the file settings
|
||||
int file_start = 0x4c + shell_len;
|
||||
|
||||
const int file_location_info_flag_offset_offset = 0x08;
|
||||
int file_location_info_flag = link[file_start + file_location_info_flag_offset_offset];
|
||||
IsLocal = (file_location_info_flag & 2) == 0;
|
||||
// get the local volume and local system values
|
||||
//final int localVolumeTable_offset_offset = 0x0C;
|
||||
const int basename_offset_offset = 0x10;
|
||||
const int networkVolumeTable_offset_offset = 0x14;
|
||||
const int finalname_offset_offset = 0x18;
|
||||
int finalname_offset = link[file_start + finalname_offset_offset] + file_start;
|
||||
String finalname = getNullDelimitedString(link, finalname_offset, encoding);
|
||||
if (IsLocal)
|
||||
{
|
||||
int basename_offset = link[file_start + basename_offset_offset] + file_start;
|
||||
String basename = getNullDelimitedString(link, basename_offset, encoding);
|
||||
ResolvedPath = basename + finalname;
|
||||
}
|
||||
else
|
||||
{
|
||||
int networkVolumeTable_offset = link[file_start + networkVolumeTable_offset_offset] + file_start;
|
||||
int shareName_offset_offset = 0x08;
|
||||
int shareName_offset = link[networkVolumeTable_offset + shareName_offset_offset]
|
||||
+ networkVolumeTable_offset;
|
||||
String shareName = getNullDelimitedString(link, shareName_offset, encoding);
|
||||
ResolvedPath = shareName + "\\" + finalname;
|
||||
}
|
||||
}
|
||||
|
||||
private static string getNullDelimitedString(byte[] bytes, int off, Encoding encoding)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
// count bytes until the null character (0)
|
||||
while (true)
|
||||
{
|
||||
if (bytes[off + len] == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
len++;
|
||||
}
|
||||
|
||||
return encoding.GetString(bytes, off, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* convert two bytes into a short note, this is little endian because it's
|
||||
* for an Intel only OS.
|
||||
*/
|
||||
private static int bytesToWord(byte[] bytes, int off)
|
||||
{
|
||||
return ((bytes[off + 1] & 0xff) << 8) | (bytes[off] & 0xff);
|
||||
}
|
||||
|
||||
private static int bytesToDword(byte[] bytes, int off)
|
||||
{
|
||||
return (bytesToWord(bytes, off + 2) << 16) | bytesToWord(bytes, off);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,377 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
|
||||
namespace MediaBrowser.Controller.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// Class NativeMethods
|
||||
/// </summary>
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public static class NativeMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// The MA x_ PATH
|
||||
/// </summary>
|
||||
public const int MAX_PATH = 260;
|
||||
/// <summary>
|
||||
/// The MA x_ ALTERNATE
|
||||
/// </summary>
|
||||
public const int MAX_ALTERNATE = 14;
|
||||
/// <summary>
|
||||
/// The INVALI d_ HANDL e_ VALUE
|
||||
/// </summary>
|
||||
public static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
|
||||
/// <summary>
|
||||
/// The STG m_ READ
|
||||
/// </summary>
|
||||
public const uint STGM_READ = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Struct FILETIME
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct FILETIME
|
||||
{
|
||||
/// <summary>
|
||||
/// The dw low date time
|
||||
/// </summary>
|
||||
public uint dwLowDateTime;
|
||||
/// <summary>
|
||||
/// The dw high date time
|
||||
/// </summary>
|
||||
public uint dwHighDateTime;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Struct WIN32_FIND_DATA
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct WIN32_FIND_DATA
|
||||
{
|
||||
/// <summary>
|
||||
/// The dw file attributes
|
||||
/// </summary>
|
||||
public FileAttributes dwFileAttributes;
|
||||
/// <summary>
|
||||
/// The ft creation time
|
||||
/// </summary>
|
||||
public FILETIME ftCreationTime;
|
||||
/// <summary>
|
||||
/// The ft last access time
|
||||
/// </summary>
|
||||
public FILETIME ftLastAccessTime;
|
||||
/// <summary>
|
||||
/// The ft last write time
|
||||
/// </summary>
|
||||
public FILETIME ftLastWriteTime;
|
||||
/// <summary>
|
||||
/// The n file size high
|
||||
/// </summary>
|
||||
public int nFileSizeHigh;
|
||||
/// <summary>
|
||||
/// The n file size low
|
||||
/// </summary>
|
||||
public int nFileSizeLow;
|
||||
/// <summary>
|
||||
/// The dw reserved0
|
||||
/// </summary>
|
||||
public int dwReserved0;
|
||||
/// <summary>
|
||||
/// The dw reserved1
|
||||
/// </summary>
|
||||
public int dwReserved1;
|
||||
|
||||
/// <summary>
|
||||
/// The c file name
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = NativeMethods.MAX_PATH)]
|
||||
public string cFileName;
|
||||
|
||||
/// <summary>
|
||||
/// This will always be null when FINDEX_INFO_LEVELS = basic
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = NativeMethods.MAX_ALTERNATE)]
|
||||
public string cAlternate;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the path.
|
||||
/// </summary>
|
||||
/// <value>The path.</value>
|
||||
public string Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String" /> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="System.String" /> that represents this instance.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return Path ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enum SLGP_FLAGS
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum SLGP_FLAGS
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves the standard short (8.3 format) file name
|
||||
/// </summary>
|
||||
SLGP_SHORTPATH = 0x1,
|
||||
/// <summary>
|
||||
/// Retrieves the Universal Naming Convention (UNC) path name of the file
|
||||
/// </summary>
|
||||
SLGP_UNCPRIORITY = 0x2,
|
||||
/// <summary>
|
||||
/// Retrieves the raw path name. A raw path is something that might not exist and may include environment variables that need to be expanded
|
||||
/// </summary>
|
||||
SLGP_RAWPATH = 0x4
|
||||
}
|
||||
/// <summary>
|
||||
/// Enum SLR_FLAGS
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum SLR_FLAGS
|
||||
{
|
||||
/// <summary>
|
||||
/// Do not display a dialog box if the link cannot be resolved. When SLR_NO_UI is set,
|
||||
/// the high-order word of fFlags can be set to a time-out value that specifies the
|
||||
/// maximum amount of time to be spent resolving the link. The function returns if the
|
||||
/// link cannot be resolved within the time-out duration. If the high-order word is set
|
||||
/// to zero, the time-out duration will be set to the default value of 3,000 milliseconds
|
||||
/// (3 seconds). To specify a value, set the high word of fFlags to the desired time-out
|
||||
/// duration, in milliseconds.
|
||||
/// </summary>
|
||||
SLR_NO_UI = 0x1,
|
||||
/// <summary>
|
||||
/// Obsolete and no longer used
|
||||
/// </summary>
|
||||
SLR_ANY_MATCH = 0x2,
|
||||
/// <summary>
|
||||
/// If the link object has changed, update its path and list of identifiers.
|
||||
/// If SLR_UPDATE is set, you do not need to call IPersistFile::IsDirty to determine
|
||||
/// whether or not the link object has changed.
|
||||
/// </summary>
|
||||
SLR_UPDATE = 0x4,
|
||||
/// <summary>
|
||||
/// Do not update the link information
|
||||
/// </summary>
|
||||
SLR_NOUPDATE = 0x8,
|
||||
/// <summary>
|
||||
/// Do not execute the search heuristics
|
||||
/// </summary>
|
||||
SLR_NOSEARCH = 0x10,
|
||||
/// <summary>
|
||||
/// Do not use distributed link tracking
|
||||
/// </summary>
|
||||
SLR_NOTRACK = 0x20,
|
||||
/// <summary>
|
||||
/// Disable distributed link tracking. By default, distributed link tracking tracks
|
||||
/// removable media across multiple devices based on the volume name. It also uses the
|
||||
/// Universal Naming Convention (UNC) path to track remote file systems whose drive letter
|
||||
/// has changed. Setting SLR_NOLINKINFO disables both types of tracking.
|
||||
/// </summary>
|
||||
SLR_NOLINKINFO = 0x40,
|
||||
/// <summary>
|
||||
/// Call the Microsoft Windows Installer
|
||||
/// </summary>
|
||||
SLR_INVOKE_MSI = 0x80
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The IShellLink interface allows Shell links to be created, modified, and resolved
|
||||
/// </summary>
|
||||
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F9-0000-0000-C000-000000000046")]
|
||||
public interface IShellLinkW
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves the path and file name of a Shell link object
|
||||
/// </summary>
|
||||
/// <param name="pszFile">The PSZ file.</param>
|
||||
/// <param name="cchMaxPath">The CCH max path.</param>
|
||||
/// <param name="pfd">The PFD.</param>
|
||||
/// <param name="fFlags">The f flags.</param>
|
||||
void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out WIN32_FIND_DATA pfd, SLGP_FLAGS fFlags);
|
||||
/// <summary>
|
||||
/// Retrieves the list of item identifiers for a Shell link object
|
||||
/// </summary>
|
||||
/// <param name="ppidl">The ppidl.</param>
|
||||
void GetIDList(out IntPtr ppidl);
|
||||
/// <summary>
|
||||
/// Sets the pointer to an item identifier list (PIDL) for a Shell link object.
|
||||
/// </summary>
|
||||
/// <param name="pidl">The pidl.</param>
|
||||
void SetIDList(IntPtr pidl);
|
||||
/// <summary>
|
||||
/// Retrieves the description string for a Shell link object
|
||||
/// </summary>
|
||||
/// <param name="pszName">Name of the PSZ.</param>
|
||||
/// <param name="cchMaxName">Name of the CCH max.</param>
|
||||
void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
|
||||
/// <summary>
|
||||
/// Sets the description for a Shell link object. The description can be any application-defined string
|
||||
/// </summary>
|
||||
/// <param name="pszName">Name of the PSZ.</param>
|
||||
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
|
||||
/// <summary>
|
||||
/// Retrieves the name of the working directory for a Shell link object
|
||||
/// </summary>
|
||||
/// <param name="pszDir">The PSZ dir.</param>
|
||||
/// <param name="cchMaxPath">The CCH max path.</param>
|
||||
void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
|
||||
/// <summary>
|
||||
/// Sets the name of the working directory for a Shell link object
|
||||
/// </summary>
|
||||
/// <param name="pszDir">The PSZ dir.</param>
|
||||
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
|
||||
/// <summary>
|
||||
/// Retrieves the command-line arguments associated with a Shell link object
|
||||
/// </summary>
|
||||
/// <param name="pszArgs">The PSZ args.</param>
|
||||
/// <param name="cchMaxPath">The CCH max path.</param>
|
||||
void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
|
||||
/// <summary>
|
||||
/// Sets the command-line arguments for a Shell link object
|
||||
/// </summary>
|
||||
/// <param name="pszArgs">The PSZ args.</param>
|
||||
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
|
||||
/// <summary>
|
||||
/// Retrieves the hot key for a Shell link object
|
||||
/// </summary>
|
||||
/// <param name="pwHotkey">The pw hotkey.</param>
|
||||
void GetHotkey(out short pwHotkey);
|
||||
/// <summary>
|
||||
/// Sets a hot key for a Shell link object
|
||||
/// </summary>
|
||||
/// <param name="wHotkey">The w hotkey.</param>
|
||||
void SetHotkey(short wHotkey);
|
||||
/// <summary>
|
||||
/// Retrieves the show command for a Shell link object
|
||||
/// </summary>
|
||||
/// <param name="piShowCmd">The pi show CMD.</param>
|
||||
void GetShowCmd(out int piShowCmd);
|
||||
/// <summary>
|
||||
/// Sets the show command for a Shell link object. The show command sets the initial show state of the window.
|
||||
/// </summary>
|
||||
/// <param name="iShowCmd">The i show CMD.</param>
|
||||
void SetShowCmd(int iShowCmd);
|
||||
/// <summary>
|
||||
/// Retrieves the location (path and index) of the icon for a Shell link object
|
||||
/// </summary>
|
||||
/// <param name="pszIconPath">The PSZ icon path.</param>
|
||||
/// <param name="cchIconPath">The CCH icon path.</param>
|
||||
/// <param name="piIcon">The pi icon.</param>
|
||||
void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
|
||||
int cchIconPath, out int piIcon);
|
||||
/// <summary>
|
||||
/// Sets the location (path and index) of the icon for a Shell link object
|
||||
/// </summary>
|
||||
/// <param name="pszIconPath">The PSZ icon path.</param>
|
||||
/// <param name="iIcon">The i icon.</param>
|
||||
void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
|
||||
/// <summary>
|
||||
/// Sets the relative path to the Shell link object
|
||||
/// </summary>
|
||||
/// <param name="pszPathRel">The PSZ path rel.</param>
|
||||
/// <param name="dwReserved">The dw reserved.</param>
|
||||
void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved);
|
||||
/// <summary>
|
||||
/// Attempts to find the target of a Shell link, even if it has been moved or renamed
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The HWND.</param>
|
||||
/// <param name="fFlags">The f flags.</param>
|
||||
void Resolve(IntPtr hwnd, SLR_FLAGS fFlags);
|
||||
/// <summary>
|
||||
/// Sets the path and file name of a Shell link object
|
||||
/// </summary>
|
||||
/// <param name="pszFile">The PSZ file.</param>
|
||||
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface IPersist
|
||||
/// </summary>
|
||||
[ComImport, Guid("0000010c-0000-0000-c000-000000000046"),
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IPersist
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the class ID.
|
||||
/// </summary>
|
||||
/// <param name="pClassID">The p class ID.</param>
|
||||
[PreserveSig]
|
||||
void GetClassID(out Guid pClassID);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Interface IPersistFile
|
||||
/// </summary>
|
||||
[ComImport, Guid("0000010b-0000-0000-C000-000000000046"),
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IPersistFile : IPersist
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the class ID.
|
||||
/// </summary>
|
||||
/// <param name="pClassID">The p class ID.</param>
|
||||
new void GetClassID(out Guid pClassID);
|
||||
/// <summary>
|
||||
/// Determines whether this instance is dirty.
|
||||
/// </summary>
|
||||
[PreserveSig]
|
||||
int IsDirty();
|
||||
|
||||
/// <summary>
|
||||
/// Loads the specified PSZ file name.
|
||||
/// </summary>
|
||||
/// <param name="pszFileName">Name of the PSZ file.</param>
|
||||
/// <param name="dwMode">The dw mode.</param>
|
||||
[PreserveSig]
|
||||
void Load([In, MarshalAs(UnmanagedType.LPWStr)]
|
||||
string pszFileName, uint dwMode);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the specified PSZ file name.
|
||||
/// </summary>
|
||||
/// <param name="pszFileName">Name of the PSZ file.</param>
|
||||
/// <param name="remember">if set to <c>true</c> [remember].</param>
|
||||
[PreserveSig]
|
||||
void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName,
|
||||
[In, MarshalAs(UnmanagedType.Bool)] bool remember);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the completed.
|
||||
/// </summary>
|
||||
/// <param name="pszFileName">Name of the PSZ file.</param>
|
||||
[PreserveSig]
|
||||
void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cur file.
|
||||
/// </summary>
|
||||
/// <param name="ppszFileName">Name of the PPSZ file.</param>
|
||||
[PreserveSig]
|
||||
void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName);
|
||||
}
|
||||
|
||||
// CLSID_ShellLink from ShlGuid.h
|
||||
/// <summary>
|
||||
/// Class ShellLink
|
||||
/// </summary>
|
||||
[
|
||||
ComImport,
|
||||
Guid("00021401-0000-0000-C000-000000000046")
|
||||
]
|
||||
public class ShellLink
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -108,6 +108,7 @@
|
||||
<Compile Include="Notifications\INotificationsRepository.cs" />
|
||||
<Compile Include="Notifications\NotificationUpdateEventArgs.cs" />
|
||||
<Compile Include="Providers\IDynamicInfoProvider.cs" />
|
||||
<Compile Include="Providers\IImageProvider.cs" />
|
||||
<Compile Include="Session\ISessionManager.cs" />
|
||||
<Compile Include="Drawing\ImageExtensions.cs" />
|
||||
<Compile Include="Entities\AggregateFolder.cs" />
|
||||
@@ -139,9 +140,7 @@
|
||||
<Compile Include="Entities\Video.cs" />
|
||||
<Compile Include="Entities\CollectionFolder.cs" />
|
||||
<Compile Include="Entities\Year.cs" />
|
||||
<Compile Include="IO\FileSystem.cs" />
|
||||
<Compile Include="IO\IDirectoryWatchers.cs" />
|
||||
<Compile Include="IO\NativeMethods.cs" />
|
||||
<Compile Include="IServerApplicationHost.cs" />
|
||||
<Compile Include="IServerApplicationPaths.cs" />
|
||||
<Compile Include="Library\SearchHintInfo.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;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FFMpegManager" /> class.
|
||||
/// </summary>
|
||||
@@ -43,12 +46,13 @@ namespace MediaBrowser.Controller.MediaInfo
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="itemRepo">The item repo.</param>
|
||||
/// <exception cref="System.ArgumentNullException">zipClient</exception>
|
||||
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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
38
MediaBrowser.Controller/Providers/IImageProvider.cs
Normal file
38
MediaBrowser.Controller/Providers/IImageProvider.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface IImageProvider
|
||||
/// </summary>
|
||||
public interface IImageProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Supportses the specified item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="imageType">Type of the image.</param>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
||||
bool Supports(BaseItem item, ImageType imageType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the available images.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="imageType">Type of the image.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns>
|
||||
Task<IEnumerable<RemoteImageInfo>> GetAvailableImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
/// </summary>
|
||||
/// <param name="providers">The providers.</param>
|
||||
void AddParts(IEnumerable<BaseMetadataProvider> providers);
|
||||
/// <param name="imageProviders">The image providers.</param>
|
||||
void AddParts(IEnumerable<BaseMetadataProvider> providers, IEnumerable<IImageProvider> imageProviders);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the available remote images.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns>
|
||||
Task<IEnumerable<RemoteImageInfo>> GetAvailableRemoteImages(BaseItem item, ImageType type, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -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<string, string> VideoFileExtensionsDictionary = VideoFileExtensions.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
|
||||
@@ -125,10 +127,11 @@ namespace MediaBrowser.Controller.Resolvers
|
||||
/// <summary>
|
||||
/// Ensures DateCreated and DateModified have values
|
||||
/// </summary>
|
||||
/// <param name="fileSystem">The file system.</param>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="args">The args.</param>
|
||||
/// <param name="includeCreationTime">if set to <c>true</c> [include creation time].</param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user