commit
21edff3ac2
|
@ -96,7 +96,7 @@ namespace BDInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectoryRoot =
|
DirectoryRoot =
|
||||||
_fileSystem.GetDirectoryInfo(Path.GetDirectoryName(DirectoryBDMV.FullName));
|
_fileSystem.GetDirectoryInfo(_fileSystem.GetDirectoryName(DirectoryBDMV.FullName));
|
||||||
DirectoryBDJO =
|
DirectoryBDJO =
|
||||||
GetDirectory("BDJO", DirectoryBDMV, 0);
|
GetDirectory("BDJO", DirectoryBDMV, 0);
|
||||||
DirectoryCLIPINF =
|
DirectoryCLIPINF =
|
||||||
|
@ -349,7 +349,7 @@ namespace BDInfo
|
||||||
{
|
{
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
var parentFolder = Path.GetDirectoryName(dir.FullName);
|
var parentFolder = _fileSystem.GetDirectoryName(dir.FullName);
|
||||||
if (string.IsNullOrEmpty(parentFolder))
|
if (string.IsNullOrEmpty(parentFolder))
|
||||||
{
|
{
|
||||||
dir = null;
|
dir = null;
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace Emby.Common.Implementations.Devices
|
||||||
{
|
{
|
||||||
var path = CachePath;
|
var path = CachePath;
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||||
|
|
||||||
lock (_syncLock)
|
lock (_syncLock)
|
||||||
{
|
{
|
||||||
|
|
|
@ -418,7 +418,7 @@ namespace Emby.Common.Implementations.HttpClientManager
|
||||||
|
|
||||||
private async Task CacheResponse(HttpResponseInfo response, string responseCachePath)
|
private async Task CacheResponse(HttpResponseInfo response, string responseCachePath)
|
||||||
{
|
{
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(responseCachePath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(responseCachePath));
|
||||||
|
|
||||||
using (var responseStream = response.Content)
|
using (var responseStream = response.Content)
|
||||||
{
|
{
|
||||||
|
|
|
@ -546,24 +546,6 @@ namespace Emby.Common.Implementations.IO
|
||||||
return Path.DirectorySeparatorChar;
|
return Path.DirectorySeparatorChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AreEqual(string path1, string path2)
|
|
||||||
{
|
|
||||||
if (path1 == null && path2 == null)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path1 == null || path2 == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
path1 = path1.TrimEnd(GetDirectorySeparatorChar(path1));
|
|
||||||
path2 = path2.TrimEnd(GetDirectorySeparatorChar(path2));
|
|
||||||
|
|
||||||
return string.Equals(path1, path2, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ContainsSubPath(string parentPath, string path)
|
public bool ContainsSubPath(string parentPath, string path)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(parentPath))
|
if (string.IsNullOrEmpty(parentPath))
|
||||||
|
@ -588,7 +570,7 @@ namespace Emby.Common.Implementations.IO
|
||||||
throw new ArgumentNullException("path");
|
throw new ArgumentNullException("path");
|
||||||
}
|
}
|
||||||
|
|
||||||
var parent = Path.GetDirectoryName(path);
|
var parent = GetDirectoryName(path);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(parent))
|
if (!string.IsNullOrEmpty(parent))
|
||||||
{
|
{
|
||||||
|
@ -598,6 +580,16 @@ namespace Emby.Common.Implementations.IO
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetDirectoryName(string path)
|
||||||
|
{
|
||||||
|
if (_sharpCifsFileSystem.IsEnabledForPath(path))
|
||||||
|
{
|
||||||
|
return _sharpCifsFileSystem.GetDirectoryName(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Path.GetDirectoryName(path);
|
||||||
|
}
|
||||||
|
|
||||||
public string NormalizePath(string path)
|
public string NormalizePath(string path)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(path))
|
if (string.IsNullOrEmpty(path))
|
||||||
|
@ -605,6 +597,11 @@ namespace Emby.Common.Implementations.IO
|
||||||
throw new ArgumentNullException("path");
|
throw new ArgumentNullException("path");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_sharpCifsFileSystem.IsEnabledForPath(path))
|
||||||
|
{
|
||||||
|
return _sharpCifsFileSystem.NormalizePath(path);
|
||||||
|
}
|
||||||
|
|
||||||
if (path.EndsWith(":\\", StringComparison.OrdinalIgnoreCase))
|
if (path.EndsWith(":\\", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return path;
|
return path;
|
||||||
|
@ -613,6 +610,21 @@ namespace Emby.Common.Implementations.IO
|
||||||
return path.TrimEnd(GetDirectorySeparatorChar(path));
|
return path.TrimEnd(GetDirectorySeparatorChar(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool AreEqual(string path1, string path2)
|
||||||
|
{
|
||||||
|
if (path1 == null && path2 == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path1 == null || path2 == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Equals(NormalizePath(path1), NormalizePath(path2), StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
public string GetFileNameWithoutExtension(FileSystemMetadata info)
|
public string GetFileNameWithoutExtension(FileSystemMetadata info)
|
||||||
{
|
{
|
||||||
if (info.IsDirectory)
|
if (info.IsDirectory)
|
||||||
|
@ -637,11 +649,17 @@ namespace Emby.Common.Implementations.IO
|
||||||
|
|
||||||
// Cannot use Path.IsPathRooted because it returns false under mono when using windows-based paths, e.g. C:\\
|
// Cannot use Path.IsPathRooted because it returns false under mono when using windows-based paths, e.g. C:\\
|
||||||
|
|
||||||
|
if (_sharpCifsFileSystem.IsEnabledForPath(path))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) != -1 &&
|
if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) != -1 &&
|
||||||
!path.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
|
!path.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
//return Path.IsPathRooted(path);
|
//return Path.IsPathRooted(path);
|
||||||
|
|
|
@ -30,6 +30,34 @@ namespace Emby.Common.Implementations.IO
|
||||||
return path.StartsWith("smb://", StringComparison.OrdinalIgnoreCase) || IsUncPath(path);
|
return path.StartsWith("smb://", StringComparison.OrdinalIgnoreCase) || IsUncPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string NormalizePath(string path)
|
||||||
|
{
|
||||||
|
if (path.StartsWith("smb://", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsUncPath(path))
|
||||||
|
{
|
||||||
|
return ConvertUncToSmb(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDirectoryName(string path)
|
||||||
|
{
|
||||||
|
var separator = GetDirectorySeparatorChar(path);
|
||||||
|
var result = Path.GetDirectoryName(path);
|
||||||
|
|
||||||
|
if (separator == '/')
|
||||||
|
{
|
||||||
|
result = result.Replace('\\', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public char GetDirectorySeparatorChar(string path)
|
public char GetDirectorySeparatorChar(string path)
|
||||||
{
|
{
|
||||||
if (path.IndexOf('/') != -1)
|
if (path.IndexOf('/') != -1)
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace Emby.Common.Implementations.Net
|
||||||
#if NET46
|
#if NET46
|
||||||
public Task SendFile(string path, byte[] preBuffer, byte[] postBuffer, CancellationToken cancellationToken)
|
public Task SendFile(string path, byte[] preBuffer, byte[] postBuffer, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var options = TransmitFileOptions.UseKernelApc;
|
var options = TransmitFileOptions.UseDefaultWorkerThread;
|
||||||
|
|
||||||
var completionSource = new TaskCompletionSource<bool>();
|
var completionSource = new TaskCompletionSource<bool>();
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ namespace Emby.Common.Implementations.ScheduledTasks
|
||||||
_lastExecutionResult = value;
|
_lastExecutionResult = value;
|
||||||
|
|
||||||
var path = GetHistoryFilePath();
|
var path = GetHistoryFilePath();
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||||
|
|
||||||
lock (_lastExecutionResultSyncLock)
|
lock (_lastExecutionResultSyncLock)
|
||||||
{
|
{
|
||||||
|
@ -575,7 +575,7 @@ namespace Emby.Common.Implementations.ScheduledTasks
|
||||||
{
|
{
|
||||||
var path = GetConfigurationFilePath();
|
var path = GetConfigurationFilePath();
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||||
|
|
||||||
JsonSerializer.SerializeToFile(triggers, path);
|
JsonSerializer.SerializeToFile(triggers, path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ namespace Emby.Drawing.ImageMagick
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var tmpPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".webp");
|
var tmpPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".webp");
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
|
||||||
|
|
||||||
using (var wand = new MagickWand(1, 1, new PixelWand("none", 1)))
|
using (var wand = new MagickWand(1, 1, new PixelWand("none", 1)))
|
||||||
{
|
{
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace Emby.Drawing.ImageMagick
|
||||||
|
|
||||||
var namespacePath = typeof(PlayedIndicatorDrawer).Namespace + ".fonts." + name;
|
var namespacePath = typeof(PlayedIndicatorDrawer).Namespace + ".fonts." + name;
|
||||||
var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".ttf");
|
var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".ttf");
|
||||||
fileSystem.CreateDirectory(Path.GetDirectoryName(tempPath));
|
fileSystem.CreateDirectory(fileSystem.GetDirectoryName(tempPath));
|
||||||
|
|
||||||
using (var stream = typeof(PlayedIndicatorDrawer).Assembly.GetManifestResourceStream(namespacePath))
|
using (var stream = typeof(PlayedIndicatorDrawer).Assembly.GetManifestResourceStream(namespacePath))
|
||||||
{
|
{
|
||||||
|
@ -78,7 +78,7 @@ namespace Emby.Drawing.ImageMagick
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fileSystem.CreateDirectory(Path.GetDirectoryName(filePath));
|
fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -108,7 +108,7 @@ namespace Emby.Drawing.ImageMagick
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
fileSystem.CreateDirectory(Path.GetDirectoryName(filePath));
|
fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace Emby.Drawing.Net
|
||||||
{
|
{
|
||||||
using (var croppedImage = image.CropWhitespace())
|
using (var croppedImage = image.CropWhitespace())
|
||||||
{
|
{
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath));
|
||||||
|
|
||||||
using (var outputStream = _fileSystem.GetFileStream(outputPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false))
|
using (var outputStream = _fileSystem.GetFileStream(outputPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false))
|
||||||
{
|
{
|
||||||
|
@ -135,7 +135,7 @@ namespace Emby.Drawing.Net
|
||||||
|
|
||||||
var outputFormat = GetOutputFormat(originalImage, selectedOutputFormat);
|
var outputFormat = GetOutputFormat(originalImage, selectedOutputFormat);
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
|
||||||
|
|
||||||
// Save to the cache location
|
// Save to the cache location
|
||||||
using (var cacheFileStream = _fileSystem.GetFileStream(cacheFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false))
|
using (var cacheFileStream = _fileSystem.GetFileStream(cacheFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false))
|
||||||
|
|
|
@ -244,9 +244,9 @@ namespace Emby.Drawing
|
||||||
var newWidth = Convert.ToInt32(newSize.Width);
|
var newWidth = Convert.ToInt32(newSize.Width);
|
||||||
var newHeight = Convert.ToInt32(newSize.Height);
|
var newHeight = Convert.ToInt32(newSize.Height);
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
|
||||||
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
|
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
|
||||||
|
|
||||||
_imageEncoder.EncodeImage(originalImagePath, tmpPath, AutoOrient(options.Item), newWidth, newHeight, quality, options, outputFormat);
|
_imageEncoder.EncodeImage(originalImagePath, tmpPath, AutoOrient(options.Item), newWidth, newHeight, quality, options, outputFormat);
|
||||||
CopyFile(tmpPath, cacheFilePath);
|
CopyFile(tmpPath, cacheFilePath);
|
||||||
|
@ -418,9 +418,9 @@ namespace Emby.Drawing
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(croppedImagePath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(croppedImagePath));
|
||||||
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(croppedImagePath));
|
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(croppedImagePath));
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
|
||||||
|
|
||||||
_imageEncoder.CropWhiteSpace(originalImagePath, tmpPath);
|
_imageEncoder.CropWhiteSpace(originalImagePath, tmpPath);
|
||||||
CopyFile(tmpPath, croppedImagePath);
|
CopyFile(tmpPath, croppedImagePath);
|
||||||
|
@ -592,7 +592,7 @@ namespace Emby.Drawing
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var path = ImageSizeFile;
|
var path = ImageSizeFile;
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||||
_jsonSerializer.SerializeToFile(_cachedImagedSizes, path);
|
_jsonSerializer.SerializeToFile(_cachedImagedSizes, path);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -765,10 +765,10 @@ namespace Emby.Drawing
|
||||||
return enhancedImagePath;
|
return enhancedImagePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(enhancedImagePath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(enhancedImagePath));
|
||||||
|
|
||||||
var tmpPath = Path.Combine(_appPaths.TempDirectory, Path.ChangeExtension(Guid.NewGuid().ToString(), Path.GetExtension(enhancedImagePath)));
|
var tmpPath = Path.Combine(_appPaths.TempDirectory, Path.ChangeExtension(Guid.NewGuid().ToString(), Path.GetExtension(enhancedImagePath)));
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
|
||||||
|
|
||||||
await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, tmpPath, item, imageType, imageIndex).ConfigureAwait(false);
|
await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, tmpPath, item, imageType, imageIndex).ConfigureAwait(false);
|
||||||
|
|
||||||
|
|
|
@ -257,7 +257,7 @@ namespace Emby.Server.Core
|
||||||
internal IPowerManagement PowerManagement { get; private set; }
|
internal IPowerManagement PowerManagement { get; private set; }
|
||||||
internal IImageEncoder ImageEncoder { get; private set; }
|
internal IImageEncoder ImageEncoder { get; private set; }
|
||||||
|
|
||||||
private readonly Action<string, string> _certificateGenerator;
|
private readonly Action<string, string, string> _certificateGenerator;
|
||||||
private readonly Func<string> _defaultUserNameFactory;
|
private readonly Func<string> _defaultUserNameFactory;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -274,7 +274,7 @@ namespace Emby.Server.Core
|
||||||
ISystemEvents systemEvents,
|
ISystemEvents systemEvents,
|
||||||
IMemoryStreamFactory memoryStreamFactory,
|
IMemoryStreamFactory memoryStreamFactory,
|
||||||
INetworkManager networkManager,
|
INetworkManager networkManager,
|
||||||
Action<string, string> certificateGenerator,
|
Action<string, string, string> certificateGenerator,
|
||||||
Func<string> defaultUsernameFactory)
|
Func<string> defaultUsernameFactory)
|
||||||
: base(applicationPaths,
|
: base(applicationPaths,
|
||||||
logManager,
|
logManager,
|
||||||
|
@ -609,8 +609,8 @@ namespace Emby.Server.Core
|
||||||
|
|
||||||
RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
|
RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
|
||||||
|
|
||||||
CertificatePath = GetCertificatePath(true);
|
CertificateInfo = GetCertificateInfo(true);
|
||||||
Certificate = GetCertificate(CertificatePath);
|
Certificate = GetCertificate(CertificateInfo);
|
||||||
|
|
||||||
HttpServer = HttpServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, NetworkManager, MemoryStreamFactory, "Emby", "web/index.html", textEncoding, SocketFactory, CryptographyProvider, JsonSerializer, XmlSerializer, EnvironmentInfo, Certificate, FileSystemManager, SupportsDualModeSockets);
|
HttpServer = HttpServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, NetworkManager, MemoryStreamFactory, "Emby", "web/index.html", textEncoding, SocketFactory, CryptographyProvider, JsonSerializer, XmlSerializer, EnvironmentInfo, Certificate, FileSystemManager, SupportsDualModeSockets);
|
||||||
HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading");
|
HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading");
|
||||||
|
@ -745,8 +745,10 @@ namespace Emby.Server.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ICertificate GetCertificate(string certificateLocation)
|
private ICertificate GetCertificate(CertificateInfo info)
|
||||||
{
|
{
|
||||||
|
var certificateLocation = info == null ? null : info.Path;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(certificateLocation))
|
if (string.IsNullOrWhiteSpace(certificateLocation))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
|
@ -759,7 +761,7 @@ namespace Emby.Server.Core
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
X509Certificate2 localCert = new X509Certificate2(certificateLocation);
|
X509Certificate2 localCert = new X509Certificate2(certificateLocation, info.Password);
|
||||||
//localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA;
|
//localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA;
|
||||||
if (!localCert.HasPrivateKey)
|
if (!localCert.HasPrivateKey)
|
||||||
{
|
{
|
||||||
|
@ -1064,7 +1066,7 @@ namespace Emby.Server.Core
|
||||||
SyncManager.AddParts(GetExports<ISyncProvider>());
|
SyncManager.AddParts(GetExports<ISyncProvider>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private string CertificatePath { get; set; }
|
private CertificateInfo CertificateInfo { get; set; }
|
||||||
private ICertificate Certificate { get; set; }
|
private ICertificate Certificate { get; set; }
|
||||||
|
|
||||||
private IEnumerable<string> GetUrlPrefixes()
|
private IEnumerable<string> GetUrlPrefixes()
|
||||||
|
@ -1080,7 +1082,7 @@ namespace Emby.Server.Core
|
||||||
"http://"+i+":" + HttpPort + "/"
|
"http://"+i+":" + HttpPort + "/"
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(CertificatePath))
|
if (CertificateInfo != null)
|
||||||
{
|
{
|
||||||
prefixes.Add("https://" + i + ":" + HttpsPort + "/");
|
prefixes.Add("https://" + i + ":" + HttpsPort + "/");
|
||||||
}
|
}
|
||||||
|
@ -1123,27 +1125,31 @@ namespace Emby.Server.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetCertificatePath(bool generateCertificate)
|
private CertificateInfo GetCertificateInfo(bool generateCertificate)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(ServerConfigurationManager.Configuration.CertificatePath))
|
if (!string.IsNullOrWhiteSpace(ServerConfigurationManager.Configuration.CertificatePath))
|
||||||
{
|
{
|
||||||
// Custom cert
|
// Custom cert
|
||||||
return ServerConfigurationManager.Configuration.CertificatePath;
|
return new CertificateInfo
|
||||||
|
{
|
||||||
|
Path = ServerConfigurationManager.Configuration.CertificatePath
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate self-signed cert
|
// Generate self-signed cert
|
||||||
var certHost = GetHostnameFromExternalDns(ServerConfigurationManager.Configuration.WanDdns);
|
var certHost = GetHostnameFromExternalDns(ServerConfigurationManager.Configuration.WanDdns);
|
||||||
var certPath = Path.Combine(ServerConfigurationManager.ApplicationPaths.ProgramDataPath, "ssl", "cert_" + (certHost + "1").GetMD5().ToString("N") + ".pfx");
|
var certPath = Path.Combine(ServerConfigurationManager.ApplicationPaths.ProgramDataPath, "ssl", "cert_" + (certHost + "2").GetMD5().ToString("N") + ".pfx");
|
||||||
|
var password = "embycert";
|
||||||
|
|
||||||
if (generateCertificate)
|
if (generateCertificate)
|
||||||
{
|
{
|
||||||
if (!FileSystemManager.FileExists(certPath))
|
if (!FileSystemManager.FileExists(certPath))
|
||||||
{
|
{
|
||||||
FileSystemManager.CreateDirectory(Path.GetDirectoryName(certPath));
|
FileSystemManager.CreateDirectory(FileSystemManager.GetDirectoryName(certPath));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_certificateGenerator(certPath, certHost);
|
_certificateGenerator(certPath, certHost, password);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -1153,7 +1159,11 @@ namespace Emby.Server.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return certPath;
|
return new CertificateInfo
|
||||||
|
{
|
||||||
|
Path = certPath,
|
||||||
|
Password = password
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1189,7 +1199,11 @@ namespace Emby.Server.Core
|
||||||
requiresRestart = true;
|
requiresRestart = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.Equals(CertificatePath, GetCertificatePath(false), StringComparison.OrdinalIgnoreCase))
|
var currentCertPath = CertificateInfo == null ? null : CertificateInfo.Path;
|
||||||
|
var newCertInfo = GetCertificateInfo(false);
|
||||||
|
var newCertPath = newCertInfo == null ? null : newCertInfo.Path;
|
||||||
|
|
||||||
|
if (!string.Equals(currentCertPath, newCertPath, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
requiresRestart = true;
|
requiresRestart = true;
|
||||||
}
|
}
|
||||||
|
@ -1779,6 +1793,11 @@ namespace Emby.Server.Core
|
||||||
{
|
{
|
||||||
Container.Register(typeInterface, typeImplementation);
|
Container.Register(typeInterface, typeImplementation);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CertificateInfo
|
||||||
|
{
|
||||||
|
public string Path { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -453,7 +453,7 @@ namespace Emby.Server.Core.IO
|
||||||
// If the parent of an ignored path has a change event, ignore that too
|
// If the parent of an ignored path has a change event, ignore that too
|
||||||
if (tempIgnorePaths.Any(i =>
|
if (tempIgnorePaths.Any(i =>
|
||||||
{
|
{
|
||||||
if (string.Equals(i, path, StringComparison.OrdinalIgnoreCase))
|
if (_fileSystem.AreEqual(i, path))
|
||||||
{
|
{
|
||||||
Logger.Debug("Ignoring change to {0}", path);
|
Logger.Debug("Ignoring change to {0}", path);
|
||||||
return true;
|
return true;
|
||||||
|
@ -466,10 +466,10 @@ namespace Emby.Server.Core.IO
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go up a level
|
// Go up a level
|
||||||
var parent = Path.GetDirectoryName(i);
|
var parent = _fileSystem.GetDirectoryName(i);
|
||||||
if (!string.IsNullOrEmpty(parent))
|
if (!string.IsNullOrEmpty(parent))
|
||||||
{
|
{
|
||||||
if (string.Equals(parent, path, StringComparison.OrdinalIgnoreCase))
|
if (_fileSystem.AreEqual(parent, path))
|
||||||
{
|
{
|
||||||
Logger.Debug("Ignoring change to {0}", path);
|
Logger.Debug("Ignoring change to {0}", path);
|
||||||
return true;
|
return true;
|
||||||
|
@ -492,7 +492,7 @@ namespace Emby.Server.Core.IO
|
||||||
|
|
||||||
private void CreateRefresher(string path)
|
private void CreateRefresher(string path)
|
||||||
{
|
{
|
||||||
var parentPath = Path.GetDirectoryName(path);
|
var parentPath = _fileSystem.GetDirectoryName(path);
|
||||||
|
|
||||||
lock (_activeRefreshers)
|
lock (_activeRefreshers)
|
||||||
{
|
{
|
||||||
|
@ -500,7 +500,7 @@ namespace Emby.Server.Core.IO
|
||||||
foreach (var refresher in refreshers)
|
foreach (var refresher in refreshers)
|
||||||
{
|
{
|
||||||
// Path is already being refreshed
|
// Path is already being refreshed
|
||||||
if (string.Equals(path, refresher.Path, StringComparison.Ordinal))
|
if (_fileSystem.AreEqual(path, refresher.Path))
|
||||||
{
|
{
|
||||||
refresher.RestartTimer();
|
refresher.RestartTimer();
|
||||||
return;
|
return;
|
||||||
|
@ -521,7 +521,7 @@ namespace Emby.Server.Core.IO
|
||||||
}
|
}
|
||||||
|
|
||||||
// They are siblings. Rebase the refresher to the parent folder.
|
// They are siblings. Rebase the refresher to the parent folder.
|
||||||
if (string.Equals(parentPath, Path.GetDirectoryName(refresher.Path), StringComparison.Ordinal))
|
if (string.Equals(parentPath, _fileSystem.GetDirectoryName(refresher.Path), StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
refresher.ResetPath(parentPath, path);
|
refresher.ResetPath(parentPath, path);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -268,24 +268,14 @@ namespace Emby.Server.Implementations.Channels
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||||
|
|
||||||
_jsonSerializer.SerializeToFile(mediaSources, path);
|
_jsonSerializer.SerializeToFile(mediaSources, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(BaseItem item, CancellationToken cancellationToken)
|
public async Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(BaseItem item, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
IEnumerable<ChannelMediaInfo> results = new List<ChannelMediaInfo>();
|
IEnumerable<ChannelMediaInfo> results = GetSavedMediaSources(item);
|
||||||
var video = item as Video;
|
|
||||||
if (video != null)
|
|
||||||
{
|
|
||||||
results = video.ChannelMediaSources;
|
|
||||||
}
|
|
||||||
var audio = item as Audio;
|
|
||||||
if (audio != null)
|
|
||||||
{
|
|
||||||
results = audio.ChannelMediaSources ?? GetSavedMediaSources(audio);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SortMediaInfoResults(results)
|
return SortMediaInfoResults(results)
|
||||||
.Select(i => GetMediaSource(item, i))
|
.Select(i => GetMediaSource(item, i))
|
||||||
|
@ -1115,7 +1105,7 @@ namespace Emby.Server.Implementations.Channels
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||||
|
|
||||||
_jsonSerializer.SerializeToFile(result, path);
|
_jsonSerializer.SerializeToFile(result, path);
|
||||||
}
|
}
|
||||||
|
@ -1378,7 +1368,6 @@ namespace Emby.Server.Implementations.Channels
|
||||||
if (channelVideoItem != null)
|
if (channelVideoItem != null)
|
||||||
{
|
{
|
||||||
channelVideoItem.ExtraType = info.ExtraType;
|
channelVideoItem.ExtraType = info.ExtraType;
|
||||||
channelVideoItem.ChannelMediaSources = info.MediaSources;
|
|
||||||
|
|
||||||
var mediaSource = info.MediaSources.FirstOrDefault();
|
var mediaSource = info.MediaSources.FirstOrDefault();
|
||||||
item.Path = mediaSource == null ? null : mediaSource.Path;
|
item.Path = mediaSource == null ? null : mediaSource.Path;
|
||||||
|
@ -1427,7 +1416,7 @@ namespace Emby.Server.Implementations.Channels
|
||||||
if (!_refreshedItems.ContainsKey(program.Id))
|
if (!_refreshedItems.ContainsKey(program.Id))
|
||||||
{
|
{
|
||||||
_refreshedItems.TryAdd(program.Id, true);
|
_refreshedItems.TryAdd(program.Id, true);
|
||||||
_providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem));
|
_providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.Low);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,7 @@ namespace Emby.Server.Implementations.Collections
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem));
|
_providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.High);
|
||||||
}
|
}
|
||||||
|
|
||||||
EventHelper.FireEventIfNotNull(CollectionCreated, this, new CollectionCreatedEventArgs
|
EventHelper.FireEventIfNotNull(CollectionCreated, this, new CollectionCreatedEventArgs
|
||||||
|
@ -191,7 +191,7 @@ namespace Emby.Server.Implementations.Collections
|
||||||
|
|
||||||
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
_providerManager.QueueRefresh(collection.Id, refreshOptions);
|
_providerManager.QueueRefresh(collection.Id, refreshOptions, RefreshPriority.High);
|
||||||
|
|
||||||
if (fireEvent)
|
if (fireEvent)
|
||||||
{
|
{
|
||||||
|
@ -244,7 +244,7 @@ namespace Emby.Server.Implementations.Collections
|
||||||
collection.UpdateRatingToContent();
|
collection.UpdateRatingToContent();
|
||||||
|
|
||||||
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
_providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem));
|
_providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.High);
|
||||||
|
|
||||||
EventHelper.FireEventIfNotNull(ItemsRemovedFromCollection, this, new CollectionModifiedEventArgs
|
EventHelper.FireEventIfNotNull(ItemsRemovedFromCollection, this, new CollectionModifiedEventArgs
|
||||||
{
|
{
|
||||||
|
|
|
@ -71,10 +71,9 @@ namespace Emby.Server.Implementations.Data
|
||||||
double newPercentCommplete = 45 + .55 * p;
|
double newPercentCommplete = 45 + .55 * p;
|
||||||
progress.Report(newPercentCommplete);
|
progress.Report(newPercentCommplete);
|
||||||
});
|
});
|
||||||
await CleanDeletedItems(cancellationToken, innerProgress).ConfigureAwait(false);
|
|
||||||
progress.Report(100);
|
|
||||||
|
|
||||||
await _itemRepo.UpdateInheritedValues(cancellationToken).ConfigureAwait(false);
|
await _itemRepo.UpdateInheritedValues(cancellationToken).ConfigureAwait(false);
|
||||||
|
progress.Report(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CleanDeadItems(CancellationToken cancellationToken, IProgress<double> progress)
|
private async Task CleanDeadItems(CancellationToken cancellationToken, IProgress<double> progress)
|
||||||
|
@ -115,115 +114,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
progress.Report(100);
|
progress.Report(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CleanDeletedItems(CancellationToken cancellationToken, IProgress<double> progress)
|
|
||||||
{
|
|
||||||
var result = _itemRepo.GetItemIdsWithPath(new InternalItemsQuery
|
|
||||||
{
|
|
||||||
LocationTypes = new[] { LocationType.FileSystem },
|
|
||||||
//Limit = limit,
|
|
||||||
|
|
||||||
// These have their own cleanup routines
|
|
||||||
ExcludeItemTypes = new[]
|
|
||||||
{
|
|
||||||
typeof(Person).Name,
|
|
||||||
typeof(Genre).Name,
|
|
||||||
typeof(MusicGenre).Name,
|
|
||||||
typeof(GameGenre).Name,
|
|
||||||
typeof(Studio).Name,
|
|
||||||
typeof(Year).Name,
|
|
||||||
typeof(Channel).Name,
|
|
||||||
typeof(AggregateFolder).Name,
|
|
||||||
typeof(CollectionFolder).Name
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var numComplete = 0;
|
|
||||||
var numItems = result.Count;
|
|
||||||
|
|
||||||
var allLibraryPaths = _libraryManager
|
|
||||||
.GetVirtualFolders()
|
|
||||||
.SelectMany(i => i.Locations)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
foreach (var item in result)
|
|
||||||
{
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
var path = item.Item2;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var isPathInLibrary = false;
|
|
||||||
|
|
||||||
if (allLibraryPaths.Any(i => path.StartsWith(i, StringComparison.Ordinal)) ||
|
|
||||||
allLibraryPaths.Contains(path, StringComparer.Ordinal) ||
|
|
||||||
path.StartsWith(_appPaths.ProgramDataPath, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
isPathInLibrary = true;
|
|
||||||
|
|
||||||
if (_fileSystem.FileExists(path) || _fileSystem.DirectoryExists(path))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var libraryItem = _libraryManager.GetItemById(item.Item1);
|
|
||||||
|
|
||||||
if (libraryItem == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (libraryItem.IsTopParent)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasDualAccess = libraryItem as IHasDualAccess;
|
|
||||||
if (hasDualAccess != null && hasDualAccess.IsAccessedByName)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var libraryItemPath = libraryItem.Path;
|
|
||||||
if (!string.Equals(libraryItemPath, path, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
_logger.Error("CleanDeletedItems aborting delete for item {0}-{1} because paths don't match. {2}---{3}", libraryItem.Id, libraryItem.Name, libraryItem.Path ?? string.Empty, path ?? string.Empty);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Folder.IsPathOffline(path, allLibraryPaths))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isPathInLibrary)
|
|
||||||
{
|
|
||||||
_logger.Info("Deleting item from database {0} because path no longer exists. type: {1} path: {2}", libraryItem.Name, libraryItem.GetType().Name, libraryItemPath ?? string.Empty);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.Info("Deleting item from database {0} because path is no longer in the server library. type: {1} path: {2}", libraryItem.Name, libraryItem.GetType().Name, libraryItemPath ?? string.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
await libraryItem.OnFileDeleted().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.ErrorException("Error in CleanDeletedItems. File {0}", ex, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
numComplete++;
|
|
||||||
double percent = numComplete;
|
|
||||||
percent /= numItems;
|
|
||||||
progress.Report(percent * 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the triggers that define when the task will run
|
/// Creates the triggers that define when the task will run
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -201,7 +201,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames);
|
||||||
|
|
||||||
AddColumn(db, "TypedBaseItems", "OfficialRatingDescription", "Text", existingColumnNames);
|
|
||||||
AddColumn(db, "TypedBaseItems", "HomePageUrl", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "HomePageUrl", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "VoteCount", "INT", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "VoteCount", "INT", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "DisplayMediaType", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "DisplayMediaType", "Text", existingColumnNames);
|
||||||
|
@ -209,7 +208,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
AddColumn(db, "TypedBaseItems", "DateModified", "DATETIME", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "DateModified", "DATETIME", existingColumnNames);
|
||||||
|
|
||||||
AddColumn(db, "TypedBaseItems", "ForcedSortName", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "ForcedSortName", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "LocationType", "Text", existingColumnNames);
|
|
||||||
|
|
||||||
AddColumn(db, "TypedBaseItems", "IsSeries", "BIT", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "IsSeries", "BIT", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "IsLive", "BIT", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "IsLive", "BIT", existingColumnNames);
|
||||||
|
@ -240,7 +238,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
AddColumn(db, "TypedBaseItems", "SourceType", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "SourceType", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "TrailerTypes", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "TrailerTypes", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "CriticRating", "Float", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "CriticRating", "Float", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "CriticRatingSummary", "Text", existingColumnNames);
|
|
||||||
AddColumn(db, "TypedBaseItems", "InheritedTags", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "InheritedTags", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "CleanName", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "CleanName", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "PresentationUniqueKey", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "PresentationUniqueKey", "Text", existingColumnNames);
|
||||||
|
@ -255,7 +252,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
AddColumn(db, "TypedBaseItems", "SeasonName", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "SeasonName", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "SeasonId", "GUID", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "SeasonId", "GUID", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "SeriesId", "GUID", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "SeriesId", "GUID", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "SeriesSortName", "Text", existingColumnNames);
|
|
||||||
AddColumn(db, "TypedBaseItems", "ExternalSeriesId", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "ExternalSeriesId", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "Tagline", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "Tagline", "Text", existingColumnNames);
|
||||||
AddColumn(db, "TypedBaseItems", "Keywords", "Text", existingColumnNames);
|
AddColumn(db, "TypedBaseItems", "Keywords", "Text", existingColumnNames);
|
||||||
|
@ -429,7 +425,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
"ParentIndexNumber",
|
"ParentIndexNumber",
|
||||||
"ProductionYear",
|
"ProductionYear",
|
||||||
"OfficialRating",
|
"OfficialRating",
|
||||||
"OfficialRatingDescription",
|
|
||||||
"HomePageUrl",
|
"HomePageUrl",
|
||||||
"DisplayMediaType",
|
"DisplayMediaType",
|
||||||
"ForcedSortName",
|
"ForcedSortName",
|
||||||
|
@ -454,13 +449,11 @@ namespace Emby.Server.Implementations.Data
|
||||||
"DateLastMediaAdded",
|
"DateLastMediaAdded",
|
||||||
"Album",
|
"Album",
|
||||||
"CriticRating",
|
"CriticRating",
|
||||||
"CriticRatingSummary",
|
|
||||||
"IsVirtualItem",
|
"IsVirtualItem",
|
||||||
"SeriesName",
|
"SeriesName",
|
||||||
"SeasonName",
|
"SeasonName",
|
||||||
"SeasonId",
|
"SeasonId",
|
||||||
"SeriesId",
|
"SeriesId",
|
||||||
"SeriesSortName",
|
|
||||||
"PresentationUniqueKey",
|
"PresentationUniqueKey",
|
||||||
"InheritedParentalRatingValue",
|
"InheritedParentalRatingValue",
|
||||||
"InheritedTags",
|
"InheritedTags",
|
||||||
|
@ -552,14 +545,12 @@ namespace Emby.Server.Implementations.Data
|
||||||
"InheritedParentalRatingValue",
|
"InheritedParentalRatingValue",
|
||||||
"SortName",
|
"SortName",
|
||||||
"RunTimeTicks",
|
"RunTimeTicks",
|
||||||
"OfficialRatingDescription",
|
|
||||||
"HomePageUrl",
|
"HomePageUrl",
|
||||||
"VoteCount",
|
"VoteCount",
|
||||||
"DisplayMediaType",
|
"DisplayMediaType",
|
||||||
"DateCreated",
|
"DateCreated",
|
||||||
"DateModified",
|
"DateModified",
|
||||||
"ForcedSortName",
|
"ForcedSortName",
|
||||||
"LocationType",
|
|
||||||
"PreferredMetadataLanguage",
|
"PreferredMetadataLanguage",
|
||||||
"PreferredMetadataCountryCode",
|
"PreferredMetadataCountryCode",
|
||||||
"IsHD",
|
"IsHD",
|
||||||
|
@ -579,7 +570,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
"SourceType",
|
"SourceType",
|
||||||
"TrailerTypes",
|
"TrailerTypes",
|
||||||
"CriticRating",
|
"CriticRating",
|
||||||
"CriticRatingSummary",
|
|
||||||
"InheritedTags",
|
"InheritedTags",
|
||||||
"CleanName",
|
"CleanName",
|
||||||
"PresentationUniqueKey",
|
"PresentationUniqueKey",
|
||||||
|
@ -594,7 +584,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
"SeasonName",
|
"SeasonName",
|
||||||
"SeasonId",
|
"SeasonId",
|
||||||
"SeriesId",
|
"SeriesId",
|
||||||
"SeriesSortName",
|
|
||||||
"ExternalSeriesId",
|
"ExternalSeriesId",
|
||||||
"Tagline",
|
"Tagline",
|
||||||
"Keywords",
|
"Keywords",
|
||||||
|
@ -833,7 +822,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
saveItemStatement.TryBind("@SortName", item.SortName);
|
saveItemStatement.TryBind("@SortName", item.SortName);
|
||||||
saveItemStatement.TryBind("@RunTimeTicks", item.RunTimeTicks);
|
saveItemStatement.TryBind("@RunTimeTicks", item.RunTimeTicks);
|
||||||
|
|
||||||
saveItemStatement.TryBind("@OfficialRatingDescription", item.OfficialRatingDescription);
|
|
||||||
saveItemStatement.TryBind("@HomePageUrl", item.HomePageUrl);
|
saveItemStatement.TryBind("@HomePageUrl", item.HomePageUrl);
|
||||||
saveItemStatement.TryBind("@VoteCount", item.VoteCount);
|
saveItemStatement.TryBind("@VoteCount", item.VoteCount);
|
||||||
saveItemStatement.TryBind("@DisplayMediaType", item.DisplayMediaType);
|
saveItemStatement.TryBind("@DisplayMediaType", item.DisplayMediaType);
|
||||||
|
@ -841,7 +829,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
saveItemStatement.TryBind("@DateModified", item.DateModified);
|
saveItemStatement.TryBind("@DateModified", item.DateModified);
|
||||||
|
|
||||||
saveItemStatement.TryBind("@ForcedSortName", item.ForcedSortName);
|
saveItemStatement.TryBind("@ForcedSortName", item.ForcedSortName);
|
||||||
saveItemStatement.TryBind("@LocationType", item.LocationType.ToString());
|
|
||||||
|
|
||||||
saveItemStatement.TryBind("@PreferredMetadataLanguage", item.PreferredMetadataLanguage);
|
saveItemStatement.TryBind("@PreferredMetadataLanguage", item.PreferredMetadataLanguage);
|
||||||
saveItemStatement.TryBind("@PreferredMetadataCountryCode", item.PreferredMetadataCountryCode);
|
saveItemStatement.TryBind("@PreferredMetadataCountryCode", item.PreferredMetadataCountryCode);
|
||||||
|
@ -942,7 +929,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
saveItemStatement.TryBind("@CriticRating", item.CriticRating);
|
saveItemStatement.TryBind("@CriticRating", item.CriticRating);
|
||||||
saveItemStatement.TryBind("@CriticRatingSummary", item.CriticRatingSummary);
|
|
||||||
|
|
||||||
var inheritedTags = item.InheritedTags;
|
var inheritedTags = item.InheritedTags;
|
||||||
if (inheritedTags.Count > 0)
|
if (inheritedTags.Count > 0)
|
||||||
|
@ -1024,13 +1010,11 @@ namespace Emby.Server.Implementations.Data
|
||||||
if (hasSeries != null)
|
if (hasSeries != null)
|
||||||
{
|
{
|
||||||
saveItemStatement.TryBind("@SeriesId", hasSeries.SeriesId);
|
saveItemStatement.TryBind("@SeriesId", hasSeries.SeriesId);
|
||||||
saveItemStatement.TryBind("@SeriesSortName", hasSeries.SeriesSortName);
|
|
||||||
saveItemStatement.TryBind("@SeriesPresentationUniqueKey", hasSeries.SeriesPresentationUniqueKey);
|
saveItemStatement.TryBind("@SeriesPresentationUniqueKey", hasSeries.SeriesPresentationUniqueKey);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
saveItemStatement.TryBindNull("@SeriesId");
|
saveItemStatement.TryBindNull("@SeriesId");
|
||||||
saveItemStatement.TryBindNull("@SeriesSortName");
|
|
||||||
saveItemStatement.TryBindNull("@SeriesPresentationUniqueKey");
|
saveItemStatement.TryBindNull("@SeriesPresentationUniqueKey");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1290,22 +1274,10 @@ namespace Emby.Server.Implementations.Data
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (type == typeof(Year))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (type == typeof(Book))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (type == typeof(Person))
|
if (type == typeof(Person))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (type == typeof(RecordingGroup))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (type == typeof(Channel))
|
if (type == typeof(Channel))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -1339,16 +1311,20 @@ namespace Emby.Server.Implementations.Data
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_config.Configuration.SkipDeserializationForPrograms)
|
|
||||||
{
|
if (type == typeof(Year))
|
||||||
if (type == typeof(LiveTvProgram))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
if (type == typeof(Book))
|
||||||
if (_config.Configuration.SkipDeserializationForAudio)
|
|
||||||
{
|
{
|
||||||
if (type == typeof(Audio))
|
return false;
|
||||||
|
}
|
||||||
|
if (type == typeof(RecordingGroup))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (type == typeof(LiveTvProgram))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1364,6 +1340,13 @@ namespace Emby.Server.Implementations.Data
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_config.Configuration.SkipDeserializationForAudio)
|
||||||
|
{
|
||||||
|
if (type == typeof(Audio))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (type == typeof(MusicAlbum))
|
if (type == typeof(MusicAlbum))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -1609,15 +1592,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
if (query.HasField(ItemFields.OfficialRatingDescription))
|
|
||||||
{
|
|
||||||
if (!reader.IsDBNull(index))
|
|
||||||
{
|
|
||||||
item.OfficialRatingDescription = reader.GetString(index);
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.HasField(ItemFields.HomePageUrl))
|
if (query.HasField(ItemFields.HomePageUrl))
|
||||||
{
|
{
|
||||||
if (!reader.IsDBNull(index))
|
if (!reader.IsDBNull(index))
|
||||||
|
@ -1803,15 +1777,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
if (query.HasField(ItemFields.CriticRatingSummary))
|
|
||||||
{
|
|
||||||
if (!reader.IsDBNull(index))
|
|
||||||
{
|
|
||||||
item.CriticRatingSummary = reader.GetString(index);
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!reader.IsDBNull(index))
|
if (!reader.IsDBNull(index))
|
||||||
{
|
{
|
||||||
item.IsVirtualItem = reader.GetBoolean(index);
|
item.IsVirtualItem = reader.GetBoolean(index);
|
||||||
|
@ -1856,15 +1821,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
if (hasSeries != null)
|
|
||||||
{
|
|
||||||
if (!reader.IsDBNull(index))
|
|
||||||
{
|
|
||||||
hasSeries.SeriesSortName = reader.GetString(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
|
|
||||||
if (!reader.IsDBNull(index))
|
if (!reader.IsDBNull(index))
|
||||||
{
|
{
|
||||||
item.PresentationUniqueKey = reader.GetString(index);
|
item.PresentationUniqueKey = reader.GetString(index);
|
||||||
|
@ -2893,6 +2849,10 @@ namespace Emby.Server.Implementations.Data
|
||||||
{
|
{
|
||||||
return new Tuple<string, bool>("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)", false);
|
return new Tuple<string, bool>("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)", false);
|
||||||
}
|
}
|
||||||
|
if (string.Equals(name, ItemSortBy.SeriesSortName, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return new Tuple<string, bool>("(Select SortName from TypedBaseItems where B.Guid=A.SeriesId)", false);
|
||||||
|
}
|
||||||
|
|
||||||
return new Tuple<string, bool>(name, false);
|
return new Tuple<string, bool>(name, false);
|
||||||
}
|
}
|
||||||
|
@ -4100,27 +4060,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
whereClauses.Add("ProductionYear in (" + val + ")");
|
whereClauses.Add("ProductionYear in (" + val + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.LocationTypes.Length == 1)
|
|
||||||
{
|
|
||||||
if (query.LocationTypes[0] == LocationType.Virtual && _config.Configuration.SchemaVersion >= 90)
|
|
||||||
{
|
|
||||||
query.IsVirtualItem = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
whereClauses.Add("LocationType=@LocationType");
|
|
||||||
if (statement != null)
|
|
||||||
{
|
|
||||||
statement.TryBind("@LocationType", query.LocationTypes[0].ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (query.LocationTypes.Length > 1)
|
|
||||||
{
|
|
||||||
var val = string.Join(",", query.LocationTypes.Select(i => "'" + i + "'").ToArray());
|
|
||||||
|
|
||||||
whereClauses.Add("LocationType in (" + val + ")");
|
|
||||||
}
|
|
||||||
if (query.IsVirtualItem.HasValue)
|
if (query.IsVirtualItem.HasValue)
|
||||||
{
|
{
|
||||||
whereClauses.Add("IsVirtualItem=@IsVirtualItem");
|
whereClauses.Add("IsVirtualItem=@IsVirtualItem");
|
||||||
|
|
|
@ -499,7 +499,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
|
|
||||||
if (fields.Contains(ItemFields.BasicSyncInfo) || fields.Contains(ItemFields.SyncInfo))
|
if (fields.Contains(ItemFields.BasicSyncInfo) || fields.Contains(ItemFields.SyncInfo))
|
||||||
{
|
{
|
||||||
var userCanSync = user != null && user.Policy.EnableSync;
|
var userCanSync = user != null && user.Policy.EnableContentDownloading;
|
||||||
if (userCanSync && _syncManager.SupportsSync(item))
|
if (userCanSync && _syncManager.SupportsSync(item))
|
||||||
{
|
{
|
||||||
dto.SupportsSync = true;
|
dto.SupportsSync = true;
|
||||||
|
@ -967,11 +967,6 @@ namespace Emby.Server.Implementations.Dto
|
||||||
|
|
||||||
dto.CriticRating = item.CriticRating;
|
dto.CriticRating = item.CriticRating;
|
||||||
|
|
||||||
if (fields.Contains(ItemFields.CriticRatingSummary))
|
|
||||||
{
|
|
||||||
dto.CriticRatingSummary = item.CriticRatingSummary;
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasTrailers = item as IHasTrailers;
|
var hasTrailers = item as IHasTrailers;
|
||||||
if (hasTrailers != null)
|
if (hasTrailers != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -352,7 +352,7 @@ namespace Emby.Server.Implementations.FileOrganization
|
||||||
_libraryMonitor.ReportFileSystemChangeBeginning(path);
|
_libraryMonitor.ReportFileSystemChangeBeginning(path);
|
||||||
|
|
||||||
var renameRelatedFiles = !hasRenamedFiles &&
|
var renameRelatedFiles = !hasRenamedFiles &&
|
||||||
string.Equals(Path.GetDirectoryName(path), Path.GetDirectoryName(result.TargetPath), StringComparison.OrdinalIgnoreCase);
|
string.Equals(_fileSystem.GetDirectoryName(path), _fileSystem.GetDirectoryName(result.TargetPath), StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
if (renameRelatedFiles)
|
if (renameRelatedFiles)
|
||||||
{
|
{
|
||||||
|
@ -432,7 +432,7 @@ namespace Emby.Server.Implementations.FileOrganization
|
||||||
|
|
||||||
// Now find other files
|
// Now find other files
|
||||||
var originalFilenameWithoutExtension = Path.GetFileNameWithoutExtension(path);
|
var originalFilenameWithoutExtension = Path.GetFileNameWithoutExtension(path);
|
||||||
var directory = Path.GetDirectoryName(path);
|
var directory = _fileSystem.GetDirectoryName(path);
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(originalFilenameWithoutExtension) && !string.IsNullOrWhiteSpace(directory))
|
if (!string.IsNullOrWhiteSpace(originalFilenameWithoutExtension) && !string.IsNullOrWhiteSpace(directory))
|
||||||
{
|
{
|
||||||
|
@ -445,7 +445,7 @@ namespace Emby.Server.Implementations.FileOrganization
|
||||||
|
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
directory = Path.GetDirectoryName(file);
|
directory = _fileSystem.GetDirectoryName(file);
|
||||||
var filename = Path.GetFileName(file);
|
var filename = Path.GetFileName(file);
|
||||||
|
|
||||||
filename = filename.Replace(originalFilenameWithoutExtension, targetFilenameWithoutExtension,
|
filename = filename.Replace(originalFilenameWithoutExtension, targetFilenameWithoutExtension,
|
||||||
|
@ -470,7 +470,7 @@ namespace Emby.Server.Implementations.FileOrganization
|
||||||
return new List<string>();
|
return new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var episodePaths = series.GetRecursiveChildren()
|
var episodePaths = series.GetRecursiveChildren(i => i is Episode)
|
||||||
.OfType<Episode>()
|
.OfType<Episode>()
|
||||||
.Where(i =>
|
.Where(i =>
|
||||||
{
|
{
|
||||||
|
@ -499,7 +499,7 @@ namespace Emby.Server.Implementations.FileOrganization
|
||||||
.Select(i => i.Path)
|
.Select(i => i.Path)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var folder = Path.GetDirectoryName(targetPath);
|
var folder = _fileSystem.GetDirectoryName(targetPath);
|
||||||
var targetFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(targetPath);
|
var targetFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(targetPath);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -529,7 +529,7 @@ namespace Emby.Server.Implementations.FileOrganization
|
||||||
|
|
||||||
_libraryMonitor.ReportFileSystemChangeBeginning(result.TargetPath);
|
_libraryMonitor.ReportFileSystemChangeBeginning(result.TargetPath);
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(result.TargetPath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(result.TargetPath));
|
||||||
|
|
||||||
var targetAlreadyExists = _fileSystem.FileExists(result.TargetPath);
|
var targetAlreadyExists = _fileSystem.FileExists(result.TargetPath);
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
Headers["Content-Type"] = contentType;
|
Headers["Content-Type"] = contentType;
|
||||||
|
|
||||||
TotalContentLength = fileSystem.GetFileInfo(path).Length;
|
TotalContentLength = fileSystem.GetFileInfo(path).Length;
|
||||||
|
Headers["Accept-Ranges"] = "bytes";
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(rangeHeader))
|
if (string.IsNullOrWhiteSpace(rangeHeader))
|
||||||
{
|
{
|
||||||
|
@ -66,7 +67,6 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Headers["Accept-Ranges"] = "bytes";
|
|
||||||
StatusCode = HttpStatusCode.PartialContent;
|
StatusCode = HttpStatusCode.PartialContent;
|
||||||
SetRangeValues();
|
SetRangeValues();
|
||||||
}
|
}
|
||||||
|
@ -96,8 +96,12 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
RangeLength = 1 + RangeEnd - RangeStart;
|
RangeLength = 1 + RangeEnd - RangeStart;
|
||||||
|
|
||||||
// Content-Length is the length of what we're serving, not the original content
|
// Content-Length is the length of what we're serving, not the original content
|
||||||
Headers["Content-Length"] = RangeLength.ToString(UsCulture);
|
var lengthString = RangeLength.ToString(UsCulture);
|
||||||
Headers["Content-Range"] = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength);
|
Headers["Content-Length"] = lengthString;
|
||||||
|
var rangeString = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength);
|
||||||
|
Headers["Content-Range"] = rangeString;
|
||||||
|
|
||||||
|
Logger.Info("Setting range response values for {0}. RangeRequest: {1} Content-Length: {2}, Content-Range: {3}", Path, RangeHeader, lengthString, rangeString);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -501,7 +501,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
private bool ShouldCompressResponse(IRequest requestContext, string contentType)
|
private bool ShouldCompressResponse(IRequest requestContext, string contentType)
|
||||||
{
|
{
|
||||||
// It will take some work to support compression with byte range requests
|
// It will take some work to support compression with byte range requests
|
||||||
if (!string.IsNullOrEmpty(requestContext.Headers.Get("Range")))
|
if (!string.IsNullOrWhiteSpace(requestContext.Headers.Get("Range")))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -566,7 +566,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(rangeHeader))
|
if (!string.IsNullOrWhiteSpace(rangeHeader))
|
||||||
{
|
{
|
||||||
var stream = await factoryFn().ConfigureAwait(false);
|
var stream = await factoryFn().ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -621,6 +621,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
responseHeaders["Content-Encoding"] = requestedCompressionType;
|
responseHeaders["Content-Encoding"] = requestedCompressionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
responseHeaders["Vary"] = "Accept-Encoding";
|
||||||
responseHeaders["Content-Length"] = content.Length.ToString(UsCulture);
|
responseHeaders["Content-Length"] = content.Length.ToString(UsCulture);
|
||||||
|
|
||||||
if (isHeadRequest)
|
if (isHeadRequest)
|
||||||
|
|
|
@ -189,10 +189,15 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
private async Task CopyToInternalAsync(Stream source, Stream destination, long copyLength)
|
private async Task CopyToInternalAsync(Stream source, Stream destination, long copyLength)
|
||||||
{
|
{
|
||||||
var array = new byte[BufferSize];
|
var array = new byte[BufferSize];
|
||||||
int count;
|
int bytesRead;
|
||||||
while ((count = await source.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0)
|
while ((bytesRead = await source.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0)
|
||||||
{
|
{
|
||||||
var bytesToCopy = Math.Min(count, copyLength);
|
if (bytesRead == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bytesToCopy = Math.Min(bytesRead, copyLength);
|
||||||
|
|
||||||
await destination.WriteAsync(array, 0, Convert.ToInt32(bytesToCopy)).ConfigureAwait(false);
|
await destination.WriteAsync(array, 0, Convert.ToInt32(bytesToCopy)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,8 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
public void FilterResponse(IRequest req, IResponse res, object dto)
|
public void FilterResponse(IRequest req, IResponse res, object dto)
|
||||||
{
|
{
|
||||||
// Try to prevent compatibility view
|
// Try to prevent compatibility view
|
||||||
res.AddHeader("X-UA-Compatible", "IE=Edge");
|
//res.AddHeader("X-UA-Compatible", "IE=Edge");
|
||||||
res.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization");
|
res.AddHeader("Access-Control-Allow-Headers", "Accept, Accept-Language, Authorization, Cache-Control, Content-Disposition, Content-Encoding, Content-Language, Content-Length, Content-MD5, Content-Range, Content-Type, Date, Host, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, Origin, OriginToken, Pragma, Range, Slug, Transfer-Encoding, Want-Digest, X-MediaBrowser-Token, X-Emby-Authorization");
|
||||||
res.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS");
|
res.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS");
|
||||||
res.AddHeader("Access-Control-Allow-Origin", "*");
|
res.AddHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
|
||||||
|
@ -46,8 +46,6 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var vary = "Accept-Encoding";
|
|
||||||
|
|
||||||
var hasHeaders = dto as IHasHeaders;
|
var hasHeaders = dto as IHasHeaders;
|
||||||
var sharpResponse = res as WebSocketSharpResponse;
|
var sharpResponse = res as WebSocketSharpResponse;
|
||||||
|
|
||||||
|
@ -86,23 +84,9 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string hasHeadersVary;
|
|
||||||
if (hasHeaders.Headers.TryGetValue("Vary", out hasHeadersVary))
|
|
||||||
{
|
|
||||||
vary = hasHeadersVary;
|
|
||||||
}
|
|
||||||
|
|
||||||
hasHeaders.Headers["Vary"] = vary;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//res.KeepAlive = false;
|
//res.KeepAlive = false;
|
||||||
|
|
||||||
// Per Google PageSpeed
|
|
||||||
// This instructs the proxies to cache two versions of the resource: one compressed, and one uncompressed.
|
|
||||||
// The correct version of the resource is delivered based on the client request header.
|
|
||||||
// This is a good choice for applications that are singly homed and depend on public proxies for user locality.
|
|
||||||
res.AddHeader("Vary", vary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -207,7 +207,7 @@ namespace Emby.Server.Implementations.IO
|
||||||
{
|
{
|
||||||
item = LibraryManager.FindByPath(path, null);
|
item = LibraryManager.FindByPath(path, null);
|
||||||
|
|
||||||
path = System.IO.Path.GetDirectoryName(path);
|
path = _fileSystem.GetDirectoryName(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item != null)
|
if (item != null)
|
||||||
|
|
|
@ -139,7 +139,7 @@ namespace Emby.Server.Implementations.Images
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var outputPathWithoutExtension = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid().ToString("N"));
|
var outputPathWithoutExtension = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid().ToString("N"));
|
||||||
FileSystem.CreateDirectory(Path.GetDirectoryName(outputPathWithoutExtension));
|
FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPathWithoutExtension));
|
||||||
string outputPath = await CreateImage(item, itemsWithImages, outputPathWithoutExtension, imageType, 0).ConfigureAwait(false);
|
string outputPath = await CreateImage(item, itemsWithImages, outputPathWithoutExtension, imageType, 0).ConfigureAwait(false);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(outputPath))
|
if (string.IsNullOrWhiteSpace(outputPath))
|
||||||
|
@ -205,7 +205,7 @@ namespace Emby.Server.Implementations.Images
|
||||||
|
|
||||||
private async Task<string> CreateCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height)
|
private async Task<string> CreateCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height)
|
||||||
{
|
{
|
||||||
FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
|
FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPath));
|
||||||
|
|
||||||
var options = new ImageCollageOptions
|
var options = new ImageCollageOptions
|
||||||
{
|
{
|
||||||
|
|
|
@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
if (parent == null)
|
if (parent == null)
|
||||||
{
|
{
|
||||||
var parentFolderName = Path.GetFileName(Path.GetDirectoryName(path));
|
var parentFolderName = Path.GetFileName(_fileSystem.GetDirectoryName(path));
|
||||||
|
|
||||||
if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1962,8 +1962,34 @@ namespace Emby.Server.Implementations.Library
|
||||||
return new List<Folder>();
|
return new List<Folder>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetUserRootFolder().Children
|
return GetCollectionFoldersInternal(item, GetUserRootFolder().Children.OfType<Folder>().ToList());
|
||||||
.OfType<Folder>()
|
}
|
||||||
|
|
||||||
|
public List<Folder> GetCollectionFolders(BaseItem item, List<Folder> allUserRootChildren)
|
||||||
|
{
|
||||||
|
while (item != null)
|
||||||
|
{
|
||||||
|
var parent = item.GetParent();
|
||||||
|
|
||||||
|
if (parent == null || parent is AggregateFolder)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
item = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
return new List<Folder>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetCollectionFoldersInternal(item, allUserRootChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Folder> GetCollectionFoldersInternal(BaseItem item, List<Folder> allUserRootChildren)
|
||||||
|
{
|
||||||
|
return allUserRootChildren
|
||||||
.Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path, StringComparer.OrdinalIgnoreCase))
|
.Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path, StringComparer.OrdinalIgnoreCase))
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
@ -2126,7 +2152,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
// Not sure why this is necessary but need to figure it out
|
// Not sure why this is necessary but need to figure it out
|
||||||
// View images are not getting utilized without this
|
// View images are not getting utilized without this
|
||||||
ForceSave = true
|
ForceSave = true
|
||||||
});
|
|
||||||
|
}, RefreshPriority.Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
|
@ -2188,7 +2215,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
// Need to force save to increment DateLastSaved
|
// Need to force save to increment DateLastSaved
|
||||||
ForceSave = true
|
ForceSave = true
|
||||||
});
|
|
||||||
|
}, RefreshPriority.Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
|
@ -2252,7 +2280,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
// Need to force save to increment DateLastSaved
|
// Need to force save to increment DateLastSaved
|
||||||
ForceSave = true
|
ForceSave = true
|
||||||
});
|
|
||||||
|
}, RefreshPriority.Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
|
@ -2328,7 +2357,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
// Need to force save to increment DateLastSaved
|
// Need to force save to increment DateLastSaved
|
||||||
ForceSave = true
|
ForceSave = true
|
||||||
});
|
}, RefreshPriority.Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
|
|
|
@ -5,6 +5,7 @@ using MediaBrowser.Controller.Playlists;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.Library
|
namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
|
@ -27,35 +28,14 @@ namespace Emby.Server.Implementations.Library
|
||||||
return list.Concat(GetInstantMixFromGenres(item.Genres, user));
|
return list.Concat(GetInstantMixFromGenres(item.Genres, user));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Audio> GetInstantMixFromArtist(MusicArtist artist, User user)
|
public IEnumerable<Audio> GetInstantMixFromArtist(MusicArtist item, User user)
|
||||||
{
|
{
|
||||||
var genres = user.RootFolder
|
return GetInstantMixFromGenres(item.Genres, user);
|
||||||
.GetRecursiveChildren(user, new InternalItemsQuery(user)
|
|
||||||
{
|
|
||||||
IncludeItemTypes = new[] { typeof(Audio).Name }
|
|
||||||
})
|
|
||||||
.Cast<Audio>()
|
|
||||||
.Where(i => i.HasAnyArtist(artist.Name))
|
|
||||||
.SelectMany(i => i.Genres)
|
|
||||||
.Concat(artist.Genres)
|
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
return GetInstantMixFromGenres(genres, user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Audio> GetInstantMixFromAlbum(MusicAlbum item, User user)
|
public IEnumerable<Audio> GetInstantMixFromAlbum(MusicAlbum item, User user)
|
||||||
{
|
{
|
||||||
var genres = item
|
return GetInstantMixFromGenres(item.Genres, user);
|
||||||
.GetRecursiveChildren(user, new InternalItemsQuery(user)
|
|
||||||
{
|
|
||||||
IncludeItemTypes = new[] { typeof(Audio).Name }
|
|
||||||
})
|
|
||||||
.Cast<Audio>()
|
|
||||||
.SelectMany(i => i.Genres)
|
|
||||||
.Concat(item.Genres)
|
|
||||||
.DistinctNames();
|
|
||||||
|
|
||||||
return GetInstantMixFromGenres(genres, user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Audio> GetInstantMixFromFolder(Folder item, User user)
|
public IEnumerable<Audio> GetInstantMixFromFolder(Folder item, User user)
|
||||||
|
@ -75,41 +55,40 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
public IEnumerable<Audio> GetInstantMixFromPlaylist(Playlist item, User user)
|
public IEnumerable<Audio> GetInstantMixFromPlaylist(Playlist item, User user)
|
||||||
{
|
{
|
||||||
var genres = item
|
return GetInstantMixFromGenres(item.Genres, user);
|
||||||
.GetRecursiveChildren(user, new InternalItemsQuery(user)
|
|
||||||
{
|
|
||||||
IncludeItemTypes = new[] { typeof(Audio).Name }
|
|
||||||
})
|
|
||||||
.Cast<Audio>()
|
|
||||||
.SelectMany(i => i.Genres)
|
|
||||||
.Concat(item.Genres)
|
|
||||||
.DistinctNames();
|
|
||||||
|
|
||||||
return GetInstantMixFromGenres(genres, user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Audio> GetInstantMixFromGenres(IEnumerable<string> genres, User user)
|
public IEnumerable<Audio> GetInstantMixFromGenres(IEnumerable<string> genres, User user)
|
||||||
{
|
{
|
||||||
var genreList = genres.ToList();
|
var genreIds = genres.DistinctNames().Select(i =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return _libraryManager.GetMusicGenre(i).Id.ToString("N");
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var inputItems = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
}).Where(i => i != null);
|
||||||
|
|
||||||
|
return GetInstantMixFromGenreIds(genreIds, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Audio> GetInstantMixFromGenreIds(IEnumerable<string> genreIds, User user)
|
||||||
|
{
|
||||||
|
return _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Audio).Name },
|
IncludeItemTypes = new[] { typeof(Audio).Name },
|
||||||
|
|
||||||
Genres = genreList.ToArray()
|
GenreIds = genreIds.ToArray(),
|
||||||
|
|
||||||
});
|
Limit = 200,
|
||||||
|
|
||||||
var genresDictionary = genreList.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
|
SortBy = new[] { ItemSortBy.Random }
|
||||||
|
|
||||||
return inputItems
|
}).Cast<Audio>();
|
||||||
.Cast<Audio>()
|
|
||||||
.Select(i => new Tuple<Audio, int>(i, i.Genres.Count(genresDictionary.ContainsKey)))
|
|
||||||
.OrderByDescending(i => i.Item2)
|
|
||||||
.ThenBy(i => Guid.NewGuid())
|
|
||||||
.Select(i => i.Item1)
|
|
||||||
.Take(200)
|
|
||||||
.OrderBy(i => Guid.NewGuid());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Audio> GetInstantMixFromItem(BaseItem item, User user)
|
public IEnumerable<Audio> GetInstantMixFromItem(BaseItem item, User user)
|
||||||
|
@ -117,7 +96,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
var genre = item as MusicGenre;
|
var genre = item as MusicGenre;
|
||||||
if (genre != null)
|
if (genre != null)
|
||||||
{
|
{
|
||||||
return GetInstantMixFromGenres(new[] { item.Name }, user);
|
return GetInstantMixFromGenreIds(new[] { item.Id.ToString("N") }, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
var playlist = item as Playlist;
|
var playlist = item as Playlist;
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
|
using MediaBrowser.Model.IO;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.Library.Resolvers
|
namespace Emby.Server.Implementations.Library.Resolvers
|
||||||
{
|
{
|
||||||
|
@ -13,11 +14,13 @@ namespace Emby.Server.Implementations.Library.Resolvers
|
||||||
{
|
{
|
||||||
private readonly IImageProcessor _imageProcessor;
|
private readonly IImageProcessor _imageProcessor;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
public PhotoResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager)
|
public PhotoResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager, IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
_imageProcessor = imageProcessor;
|
_imageProcessor = imageProcessor;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
_fileSystem = fileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -41,7 +44,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
|
||||||
var filename = Path.GetFileNameWithoutExtension(args.Path);
|
var filename = Path.GetFileNameWithoutExtension(args.Path);
|
||||||
|
|
||||||
// Make sure the image doesn't belong to a video file
|
// Make sure the image doesn't belong to a video file
|
||||||
if (args.DirectoryService.GetFilePaths(Path.GetDirectoryName(args.Path)).Any(i => IsOwnedByMedia(args.GetLibraryOptions(), i, filename)))
|
if (args.DirectoryService.GetFilePaths(_fileSystem.GetDirectoryName(args.Path)).Any(i => IsOwnedByMedia(args.GetLibraryOptions(), i, filename)))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||||
{
|
{
|
||||||
episode.SeriesId = series.Id;
|
episode.SeriesId = series.Id;
|
||||||
episode.SeriesName = series.Name;
|
episode.SeriesName = series.Name;
|
||||||
episode.SeriesSortName = series.SortName;
|
|
||||||
}
|
}
|
||||||
if (season != null)
|
if (season != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -44,7 +44,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||||
{
|
{
|
||||||
IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(args.Path, true, true).SeasonNumber,
|
IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(args.Path, true, true).SeasonNumber,
|
||||||
SeriesId = series.Id,
|
SeriesId = series.Id,
|
||||||
SeriesSortName = series.SortName,
|
|
||||||
SeriesName = series.Name
|
SeriesName = series.Name
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,16 @@ namespace Emby.Server.Implementations.Library
|
||||||
ExcludeItemTypes = excludeItemTypes.ToArray(),
|
ExcludeItemTypes = excludeItemTypes.ToArray(),
|
||||||
IncludeItemTypes = includeItemTypes.ToArray(),
|
IncludeItemTypes = includeItemTypes.ToArray(),
|
||||||
Limit = query.Limit,
|
Limit = query.Limit,
|
||||||
IncludeItemsByName = true
|
IncludeItemsByName = string.IsNullOrWhiteSpace(query.ParentId),
|
||||||
|
ParentId = string.IsNullOrWhiteSpace(query.ParentId) ? (Guid?)null : new Guid(query.ParentId),
|
||||||
|
SortBy = new[] { ItemSortBy.SortName },
|
||||||
|
Recursive = true,
|
||||||
|
|
||||||
|
IsKids = query.IsKids,
|
||||||
|
IsMovie = query.IsMovie,
|
||||||
|
IsNews = query.IsNews,
|
||||||
|
IsSeries = query.IsSeries,
|
||||||
|
IsSports = query.IsSports
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add search hints based on item name
|
// Add search hints based on item name
|
||||||
|
|
|
@ -942,7 +942,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
return new UserPolicy
|
return new UserPolicy
|
||||||
{
|
{
|
||||||
EnableSync = true
|
EnableContentDownloading = true,
|
||||||
|
EnableSyncTranscoding = true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -964,7 +965,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
var path = GetPolifyFilePath(user);
|
var path = GetPolifyFilePath(user);
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||||
|
|
||||||
lock (_policySyncLock)
|
lock (_policySyncLock)
|
||||||
{
|
{
|
||||||
|
@ -1051,7 +1052,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
config = _jsonSerializer.DeserializeFromString<UserConfiguration>(json);
|
config = _jsonSerializer.DeserializeFromString<UserConfiguration>(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||||
|
|
||||||
lock (_configSyncLock)
|
lock (_configSyncLock)
|
||||||
{
|
{
|
||||||
|
|
|
@ -422,7 +422,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(epgChannel.Name))
|
if (!string.IsNullOrWhiteSpace(epgChannel.Name))
|
||||||
{
|
{
|
||||||
tunerChannel.Name = epgChannel.Name;
|
//tunerChannel.Name = epgChannel.Name;
|
||||||
}
|
}
|
||||||
if (!string.IsNullOrWhiteSpace(epgChannel.ImageUrl))
|
if (!string.IsNullOrWhiteSpace(epgChannel.ImageUrl))
|
||||||
{
|
{
|
||||||
|
@ -1231,7 +1231,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
RequiresOpening = false,
|
RequiresOpening = false,
|
||||||
RequiresClosing = false,
|
RequiresClosing = false,
|
||||||
Protocol = MediaBrowser.Model.MediaInfo.MediaProtocol.Http,
|
Protocol = MediaBrowser.Model.MediaInfo.MediaProtocol.Http,
|
||||||
BufferMs = 0
|
BufferMs = 0,
|
||||||
|
IgnoreDts = true
|
||||||
};
|
};
|
||||||
|
|
||||||
var isAudio = false;
|
var isAudio = false;
|
||||||
|
@ -1496,7 +1497,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
|
|
||||||
_libraryManager.RegisterIgnoredPath(recordPath);
|
_libraryManager.RegisterIgnoredPath(recordPath);
|
||||||
_libraryMonitor.ReportFileSystemChangeBeginning(recordPath);
|
_libraryMonitor.ReportFileSystemChangeBeginning(recordPath);
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(recordPath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(recordPath));
|
||||||
activeRecordingInfo.Path = recordPath;
|
activeRecordingInfo.Path = recordPath;
|
||||||
|
|
||||||
var duration = recordingEndDate - DateTime.UtcNow;
|
var duration = recordingEndDate - DateTime.UtcNow;
|
||||||
|
@ -1516,8 +1517,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
EnforceKeepUpTo(timer, seriesPath);
|
EnforceKeepUpTo(timer, seriesPath);
|
||||||
};
|
};
|
||||||
|
|
||||||
await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken)
|
await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken).ConfigureAwait(false);
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
recordingStatus = RecordingStatus.Completed;
|
recordingStatus = RecordingStatus.Completed;
|
||||||
_logger.Info("Recording completed: {0}", recordPath);
|
_logger.Info("Recording completed: {0}", recordPath);
|
||||||
|
@ -1725,7 +1725,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
|
|
||||||
while (FileExists(path, timerId))
|
while (FileExists(path, timerId))
|
||||||
{
|
{
|
||||||
var parent = Path.GetDirectoryName(originalPath);
|
var parent = _fileSystem.GetDirectoryName(originalPath);
|
||||||
var name = Path.GetFileNameWithoutExtension(originalPath);
|
var name = Path.GetFileNameWithoutExtension(originalPath);
|
||||||
name += "-" + index.ToString(CultureInfo.InvariantCulture);
|
name += "-" + index.ToString(CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
|
@ -1765,7 +1765,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
|
|
||||||
if (regInfo.IsValid)
|
if (regInfo.IsValid)
|
||||||
{
|
{
|
||||||
return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, config, _httpClient, _processFactory);
|
return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, config, _httpClient, _processFactory, _config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1892,7 +1892,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var imageSavePath = Path.Combine(Path.GetDirectoryName(recordingPath), imageSaveFilenameWithoutExtension);
|
var imageSavePath = Path.Combine(_fileSystem.GetDirectoryName(recordingPath), imageSaveFilenameWithoutExtension);
|
||||||
|
|
||||||
// preserve original image extension
|
// preserve original image extension
|
||||||
imageSavePath = Path.ChangeExtension(imageSavePath, Path.GetExtension(image.Path));
|
imageSavePath = Path.ChangeExtension(imageSavePath, Path.GetExtension(image.Path));
|
||||||
|
@ -2155,11 +2155,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
writer.WriteElementString("mpaa", item.OfficialRating);
|
writer.WriteElementString("mpaa", item.OfficialRating);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(item.OfficialRatingDescription))
|
|
||||||
{
|
|
||||||
writer.WriteElementString("mpaadescription", item.OfficialRatingDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
var overview = (item.Overview ?? string.Empty)
|
var overview = (item.Overview ?? string.Empty)
|
||||||
.StripHtml()
|
.StripHtml()
|
||||||
.Replace(""", "'");
|
.Replace(""", "'");
|
||||||
|
@ -2251,11 +2246,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
writer.WriteElementString("criticrating", item.CriticRating.Value.ToString(CultureInfo.InvariantCulture));
|
writer.WriteElementString("criticrating", item.CriticRating.Value.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(item.CriticRatingSummary))
|
|
||||||
{
|
|
||||||
writer.WriteElementString("criticratingsummary", item.CriticRatingSummary);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(item.Tagline))
|
if (!string.IsNullOrWhiteSpace(item.Tagline))
|
||||||
{
|
{
|
||||||
writer.WriteElementString("tagline", item.Tagline);
|
writer.WriteElementString("tagline", item.Tagline);
|
||||||
|
@ -2550,7 +2540,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
private void SaveEpgDataForChannel(string channelId, List<ProgramInfo> epgData)
|
private void SaveEpgDataForChannel(string channelId, List<ProgramInfo> epgData)
|
||||||
{
|
{
|
||||||
var path = GetChannelEpgCachePath(channelId);
|
var path = GetChannelEpgCachePath(channelId);
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||||
lock (_epgLock)
|
lock (_epgLock)
|
||||||
{
|
{
|
||||||
_jsonSerializer.SerializeToFile(epgData, path);
|
_jsonSerializer.SerializeToFile(epgData, path);
|
||||||
|
|
|
@ -11,14 +11,16 @@ using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.IO;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.MediaEncoding;
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Diagnostics;
|
using MediaBrowser.Model.Diagnostics;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
|
using MediaBrowser.Common.Configuration;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
{
|
{
|
||||||
|
@ -37,8 +39,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
private readonly IProcessFactory _processFactory;
|
private readonly IProcessFactory _processFactory;
|
||||||
private readonly IJsonSerializer _json;
|
private readonly IJsonSerializer _json;
|
||||||
private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>();
|
private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>();
|
||||||
|
private readonly IServerConfigurationManager _config;
|
||||||
|
|
||||||
public EncodedRecorder(ILogger logger, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IServerApplicationPaths appPaths, IJsonSerializer json, LiveTvOptions liveTvOptions, IHttpClient httpClient, IProcessFactory processFactory)
|
public EncodedRecorder(ILogger logger, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IServerApplicationPaths appPaths, IJsonSerializer json, LiveTvOptions liveTvOptions, IHttpClient httpClient, IProcessFactory processFactory, IServerConfigurationManager config)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
|
@ -48,6 +51,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
_liveTvOptions = liveTvOptions;
|
_liveTvOptions = liveTvOptions;
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_processFactory = processFactory;
|
_processFactory = processFactory;
|
||||||
|
_config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string OutputFormat
|
private string OutputFormat
|
||||||
|
@ -76,23 +80,35 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
|
|
||||||
public string GetOutputPath(MediaSourceInfo mediaSource, string targetFile)
|
public string GetOutputPath(MediaSourceInfo mediaSource, string targetFile)
|
||||||
{
|
{
|
||||||
return Path.ChangeExtension(targetFile, "." + OutputFormat);
|
var extension = OutputFormat;
|
||||||
|
|
||||||
|
if (string.Equals(extension, "mpegts", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
extension = "ts";
|
||||||
|
}
|
||||||
|
|
||||||
|
return Path.ChangeExtension(targetFile, "." + extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
|
public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var durationToken = new CancellationTokenSource(duration);
|
//var durationToken = new CancellationTokenSource(duration);
|
||||||
cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
|
//cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
|
||||||
|
|
||||||
await RecordFromFile(mediaSource, mediaSource.Path, targetFile, duration, onStarted, cancellationToken).ConfigureAwait(false);
|
await RecordFromFile(mediaSource, mediaSource.Path, targetFile, duration, onStarted, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
_logger.Info("Recording completed to file {0}", targetFile);
|
_logger.Info("Recording completed to file {0}", targetFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private EncodingOptions GetEncodingOptions()
|
||||||
|
{
|
||||||
|
return _config.GetConfiguration<EncodingOptions>("encoding");
|
||||||
|
}
|
||||||
|
|
||||||
private Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
|
private Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_targetPath = targetFile;
|
_targetPath = targetFile;
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(targetFile));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(targetFile));
|
||||||
|
|
||||||
var process = _processFactory.Create(new ProcessOptions
|
var process = _processFactory.Create(new ProcessOptions
|
||||||
{
|
{
|
||||||
|
@ -118,7 +134,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
_logger.Info(commandLineLogMessage);
|
_logger.Info(commandLineLogMessage);
|
||||||
|
|
||||||
var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "record-transcode-" + Guid.NewGuid() + ".txt");
|
var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "record-transcode-" + Guid.NewGuid() + ".txt");
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(logFilePath));
|
||||||
|
|
||||||
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
|
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
|
||||||
_logFileStream = _fileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true);
|
_logFileStream = _fileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true);
|
||||||
|
@ -162,30 +178,34 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
}
|
}
|
||||||
|
|
||||||
var durationParam = " -t " + _mediaEncoder.GetTimeParameter(duration.Ticks);
|
var durationParam = " -t " + _mediaEncoder.GetTimeParameter(duration.Ticks);
|
||||||
var inputModifiers = "-fflags +genpts -async 1 -vsync -1";
|
|
||||||
var commandLineArgs = "-i \"{0}\"{5} {2} -map_metadata -1 -threads 0 {3}{4}{6} -y \"{1}\"";
|
|
||||||
|
|
||||||
long startTimeTicks = 0;
|
var flags = new List<string>();
|
||||||
//if (mediaSource.DateLiveStreamOpened.HasValue)
|
if (mediaSource.IgnoreDts)
|
||||||
//{
|
{
|
||||||
// var elapsed = DateTime.UtcNow - mediaSource.DateLiveStreamOpened.Value;
|
flags.Add("+igndts");
|
||||||
// elapsed -= TimeSpan.FromSeconds(10);
|
}
|
||||||
// if (elapsed.TotalSeconds >= 0)
|
if (mediaSource.IgnoreIndex)
|
||||||
// {
|
{
|
||||||
// startTimeTicks = elapsed.Ticks + startTimeTicks;
|
flags.Add("+ignidx");
|
||||||
// }
|
}
|
||||||
//}
|
|
||||||
|
var inputModifiers = "-async 1 -vsync -1";
|
||||||
|
|
||||||
|
if (flags.Count > 0)
|
||||||
|
{
|
||||||
|
inputModifiers += " -fflags " + string.Join("", flags.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(GetEncodingOptions().HardwareAccelerationType))
|
||||||
|
{
|
||||||
|
inputModifiers += " -hwaccel auto";
|
||||||
|
}
|
||||||
|
|
||||||
if (mediaSource.ReadAtNativeFramerate)
|
if (mediaSource.ReadAtNativeFramerate)
|
||||||
{
|
{
|
||||||
inputModifiers += " -re";
|
inputModifiers += " -re";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startTimeTicks > 0)
|
|
||||||
{
|
|
||||||
inputModifiers = "-ss " + _mediaEncoder.GetTimeParameter(startTimeTicks) + " " + inputModifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
var analyzeDurationSeconds = 5;
|
var analyzeDurationSeconds = 5;
|
||||||
var analyzeDuration = " -analyzeduration " +
|
var analyzeDuration = " -analyzeduration " +
|
||||||
(analyzeDurationSeconds * 1000000).ToString(CultureInfo.InvariantCulture);
|
(analyzeDurationSeconds * 1000000).ToString(CultureInfo.InvariantCulture);
|
||||||
|
@ -193,11 +213,20 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
|
|
||||||
var subtitleArgs = CopySubtitles ? " -codec:s copy" : " -sn";
|
var subtitleArgs = CopySubtitles ? " -codec:s copy" : " -sn";
|
||||||
|
|
||||||
var outputParam = string.Equals(Path.GetExtension(targetFile), ".mp4", StringComparison.OrdinalIgnoreCase) ?
|
//var outputParam = string.Equals(Path.GetExtension(targetFile), ".mp4", StringComparison.OrdinalIgnoreCase) ?
|
||||||
" -f mp4 -movflags frag_keyframe+empty_moov" :
|
// " -f mp4 -movflags frag_keyframe+empty_moov" :
|
||||||
string.Empty;
|
// string.Empty;
|
||||||
|
|
||||||
commandLineArgs = string.Format(commandLineArgs, inputTempFile, targetFile, videoArgs, GetAudioArgs(mediaSource), subtitleArgs, durationParam, outputParam);
|
var outputParam = string.Empty;
|
||||||
|
|
||||||
|
var commandLineArgs = string.Format("-i \"{0}\"{5} {2} -map_metadata -1 -threads 0 {3}{4}{6} -y \"{1}\"",
|
||||||
|
inputTempFile,
|
||||||
|
targetFile,
|
||||||
|
videoArgs,
|
||||||
|
GetAudioArgs(mediaSource),
|
||||||
|
subtitleArgs,
|
||||||
|
durationParam,
|
||||||
|
outputParam);
|
||||||
|
|
||||||
return inputModifiers + " " + commandLineArgs;
|
return inputModifiers + " " + commandLineArgs;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
}
|
}
|
||||||
|
|
||||||
var file = _dataPath + ".json";
|
var file = _dataPath + ".json";
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(file));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(file));
|
||||||
|
|
||||||
lock (_fileDataLock)
|
lock (_fileDataLock)
|
||||||
{
|
{
|
||||||
|
|
|
@ -86,7 +86,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFile));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFile));
|
||||||
|
|
||||||
using (var stream = _fileSystem.OpenRead(tempFile))
|
using (var stream = _fileSystem.OpenRead(tempFile))
|
||||||
{
|
{
|
||||||
|
|
|
@ -857,7 +857,8 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
_providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem)
|
_providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem)
|
||||||
{
|
{
|
||||||
MetadataRefreshMode = metadataRefreshMode
|
MetadataRefreshMode = metadataRefreshMode
|
||||||
});
|
|
||||||
|
}, RefreshPriority.Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
return item.Id;
|
return item.Id;
|
||||||
|
@ -1395,11 +1396,11 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
|
|
||||||
foreach (var program in newPrograms)
|
foreach (var program in newPrograms)
|
||||||
{
|
{
|
||||||
_providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem));
|
_providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.Low);
|
||||||
}
|
}
|
||||||
foreach (var program in updatedPrograms)
|
foreach (var program in updatedPrograms)
|
||||||
{
|
{
|
||||||
_providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem));
|
_providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.Low);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChannel.IsMovie = isMovie;
|
currentChannel.IsMovie = isMovie;
|
||||||
|
|
|
@ -420,7 +420,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
SupportsDirectPlay = false,
|
SupportsDirectPlay = false,
|
||||||
SupportsDirectStream = true,
|
SupportsDirectStream = true,
|
||||||
SupportsTranscoding = true,
|
SupportsTranscoding = true,
|
||||||
IsInfiniteStream = true
|
IsInfiniteStream = true,
|
||||||
|
IgnoreDts = true
|
||||||
};
|
};
|
||||||
|
|
||||||
mediaSource.InferTotalBitrate();
|
mediaSource.InferTotalBitrate();
|
||||||
|
|
|
@ -29,6 +29,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
|
|
||||||
byte[] buffer = new byte[BufferSize];
|
byte[] buffer = new byte[BufferSize];
|
||||||
|
|
||||||
|
if (source == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("source");
|
||||||
|
}
|
||||||
|
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
var bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false);
|
var bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
|
@ -29,15 +29,17 @@ namespace Emby.Server.Implementations.Logging
|
||||||
_logManager.Flush();
|
_logManager.Flush();
|
||||||
|
|
||||||
var path = Path.Combine(_appPaths.LogDirectoryPath, "unhandled_" + Guid.NewGuid() + ".txt");
|
var path = Path.Combine(_appPaths.LogDirectoryPath, "unhandled_" + Guid.NewGuid() + ".txt");
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||||
|
|
||||||
var builder = LogHelper.GetLogMessage(ex);
|
var builder = LogHelper.GetLogMessage(ex);
|
||||||
|
|
||||||
// Write to console just in case file logging fails
|
// Write to console just in case file logging fails
|
||||||
_console.WriteLine("UnhandledException");
|
_console.WriteLine("UnhandledException");
|
||||||
_console.WriteLine(builder.ToString());
|
|
||||||
|
|
||||||
_fileSystem.WriteAllText(path, builder.ToString());
|
var logMessage = builder.ToString();
|
||||||
|
_console.WriteLine(logMessage);
|
||||||
|
|
||||||
|
_fileSystem.WriteAllText(path, logMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,7 +138,7 @@ namespace Emby.Server.Implementations.MediaEncoder
|
||||||
|
|
||||||
var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, video.PlayableStreamFileNames);
|
var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, video.PlayableStreamFileNames);
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||||
|
|
||||||
var container = video.Container;
|
var container = video.Container;
|
||||||
|
|
||||||
|
|
|
@ -201,7 +201,8 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
_providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem)
|
_providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem)
|
||||||
{
|
{
|
||||||
ForceSave = true
|
ForceSave = true
|
||||||
});
|
|
||||||
|
}, RefreshPriority.High);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RemoveFromPlaylist(string playlistId, IEnumerable<string> entryIds)
|
public async Task RemoveFromPlaylist(string playlistId, IEnumerable<string> entryIds)
|
||||||
|
@ -228,7 +229,8 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
_providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem)
|
_providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem)
|
||||||
{
|
{
|
||||||
ForceSave = true
|
ForceSave = true
|
||||||
});
|
|
||||||
|
}, RefreshPriority.High);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task MoveItem(string playlistId, string entryId, int newIndex)
|
public async Task MoveItem(string playlistId, string entryId, int newIndex)
|
||||||
|
|
|
@ -136,7 +136,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||||
{
|
{
|
||||||
previouslyFailedImages.Add(key);
|
previouslyFailedImages.Add(key);
|
||||||
|
|
||||||
var parentPath = Path.GetDirectoryName(failHistoryPath);
|
var parentPath = _fileSystem.GetDirectoryName(failHistoryPath);
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(parentPath);
|
_fileSystem.CreateDirectory(parentPath);
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ namespace Emby.Server.Implementations.Security
|
||||||
}
|
}
|
||||||
|
|
||||||
var licenseFile = Filename;
|
var licenseFile = Filename;
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(licenseFile));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(licenseFile));
|
||||||
lock (_fileLock)
|
lock (_fileLock)
|
||||||
{
|
{
|
||||||
_fileSystem.WriteAllLines(licenseFile, lines);
|
_fileSystem.WriteAllLines(licenseFile, lines);
|
||||||
|
|
|
@ -129,7 +129,7 @@ namespace Emby.Server.Implementations.Session
|
||||||
|
|
||||||
public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken)
|
public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return Task.FromResult(true);
|
return SendMessage("LibraryChanged", info, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken)
|
public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken)
|
||||||
|
|
|
@ -715,7 +715,8 @@ namespace Emby.Server.Implementations.Session
|
||||||
ClientName = session.Client,
|
ClientName = session.Client,
|
||||||
DeviceId = session.DeviceId,
|
DeviceId = session.DeviceId,
|
||||||
IsPaused = info.IsPaused,
|
IsPaused = info.IsPaused,
|
||||||
PlaySessionId = info.PlaySessionId
|
PlaySessionId = info.PlaySessionId,
|
||||||
|
IsAutomated = isAutomated
|
||||||
|
|
||||||
}, _logger);
|
}, _logger);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace Emby.Server.Implementations.Sorting
|
||||||
{
|
{
|
||||||
var hasSeries = item as IHasSeries;
|
var hasSeries = item as IHasSeries;
|
||||||
|
|
||||||
return hasSeries != null ? hasSeries.SeriesSortName : null;
|
return hasSeries != null ? hasSeries.FindSeriesSortName() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -250,7 +250,7 @@ namespace Emby.Server.Implementations.Updates
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(PackageCachePath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(PackageCachePath));
|
||||||
|
|
||||||
_fileSystem.CopyFile(tempFile, PackageCachePath, true);
|
_fileSystem.CopyFile(tempFile, PackageCachePath, true);
|
||||||
_lastPackageUpdateTime = DateTime.UtcNow;
|
_lastPackageUpdateTime = DateTime.UtcNow;
|
||||||
|
@ -627,7 +627,7 @@ namespace Emby.Server.Implementations.Updates
|
||||||
// Success - move it to the real target
|
// Success - move it to the real target
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(target));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(target));
|
||||||
_fileSystem.CopyFile(tempFile, target, true);
|
_fileSystem.CopyFile(tempFile, target, true);
|
||||||
//If it is an archive - write out a version file so we know what it is
|
//If it is an archive - write out a version file so we know what it is
|
||||||
if (isArchive)
|
if (isArchive)
|
||||||
|
|
|
@ -633,7 +633,7 @@ namespace MediaBrowser.Api
|
||||||
/// <param name="outputFilePath">The output file path.</param>
|
/// <param name="outputFilePath">The output file path.</param>
|
||||||
private void DeleteHlsPartialStreamFiles(string outputFilePath)
|
private void DeleteHlsPartialStreamFiles(string outputFilePath)
|
||||||
{
|
{
|
||||||
var directory = Path.GetDirectoryName(outputFilePath);
|
var directory = _fileSystem.GetDirectoryName(outputFilePath);
|
||||||
var name = Path.GetFileNameWithoutExtension(outputFilePath);
|
var name = Path.GetFileNameWithoutExtension(outputFilePath);
|
||||||
|
|
||||||
var filesToDelete = _fileSystem.GetFilePaths(directory)
|
var filesToDelete = _fileSystem.GetFilePaths(directory)
|
||||||
|
|
|
@ -66,7 +66,7 @@ namespace MediaBrowser.Api
|
||||||
return ResultFactory.GetOptimizedResult(Request, result);
|
return ResultFactory.GetOptimizedResult(Request, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void AssertCanUpdateUser(IAuthorizationContext authContext, IUserManager userManager, string userId)
|
protected void AssertCanUpdateUser(IAuthorizationContext authContext, IUserManager userManager, string userId, bool restrictUserPreferences)
|
||||||
{
|
{
|
||||||
var auth = authContext.GetAuthorizationInfo(Request);
|
var auth = authContext.GetAuthorizationInfo(Request);
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ namespace MediaBrowser.Api
|
||||||
throw new SecurityException("Unauthorized access.");
|
throw new SecurityException("Unauthorized access.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (restrictUserPreferences)
|
||||||
{
|
{
|
||||||
if (!authenticatedUser.Policy.EnableUserPreferenceAccess)
|
if (!authenticatedUser.Policy.EnableUserPreferenceAccess)
|
||||||
{
|
{
|
||||||
|
|
|
@ -98,7 +98,7 @@ namespace MediaBrowser.Api
|
||||||
[ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string SortBy { get; set; }
|
public string SortBy { get; set; }
|
||||||
|
|
||||||
[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, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string Fields { get; set; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -145,7 +145,7 @@ namespace MediaBrowser.Api
|
||||||
[ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string Filters { get; set; }
|
public string Filters { get; set; }
|
||||||
|
|
||||||
[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, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string Fields { get; set; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "ChannelIds", Description = "Optional. Specify one or more channel id's, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "ChannelIds", Description = "Optional. Specify one or more channel id's, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
|
|
@ -278,7 +278,7 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
public object Get(GetParentPath request)
|
public object Get(GetParentPath request)
|
||||||
{
|
{
|
||||||
var parent = Path.GetDirectoryName(request.Path);
|
var parent = _fileSystem.GetDirectoryName(request.Path);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(parent))
|
if (string.IsNullOrEmpty(parent))
|
||||||
{
|
{
|
||||||
|
|
|
@ -160,7 +160,7 @@ namespace MediaBrowser.Api.Images
|
||||||
|
|
||||||
private string GetThemeName(string path, string rootImagePath)
|
private string GetThemeName(string path, string rootImagePath)
|
||||||
{
|
{
|
||||||
var parentName = Path.GetDirectoryName(path);
|
var parentName = _fileSystem.GetDirectoryName(path);
|
||||||
|
|
||||||
if (string.Equals(parentName, rootImagePath, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(parentName, rootImagePath, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
|
|
|
@ -427,7 +427,7 @@ namespace MediaBrowser.Api.Images
|
||||||
public void Post(PostUserImage request)
|
public void Post(PostUserImage request)
|
||||||
{
|
{
|
||||||
var userId = GetPathValue(1);
|
var userId = GetPathValue(1);
|
||||||
AssertCanUpdateUser(_authContext, _userManager, userId);
|
AssertCanUpdateUser(_authContext, _userManager, userId, true);
|
||||||
|
|
||||||
request.Type = (ImageType)Enum.Parse(typeof(ImageType), GetPathValue(3), true);
|
request.Type = (ImageType)Enum.Parse(typeof(ImageType), GetPathValue(3), true);
|
||||||
|
|
||||||
|
@ -462,7 +462,7 @@ namespace MediaBrowser.Api.Images
|
||||||
public void Delete(DeleteUserImage request)
|
public void Delete(DeleteUserImage request)
|
||||||
{
|
{
|
||||||
var userId = request.Id;
|
var userId = request.Id;
|
||||||
AssertCanUpdateUser(_authContext, _userManager, userId);
|
AssertCanUpdateUser(_authContext, _userManager, userId, true);
|
||||||
|
|
||||||
var item = _userManager.GetUserById(userId);
|
var item = _userManager.GetUserById(userId);
|
||||||
|
|
||||||
|
|
|
@ -278,7 +278,7 @@ namespace MediaBrowser.Api.Images
|
||||||
|
|
||||||
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
|
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(fullCachePath));
|
||||||
using (var stream = result.Content)
|
using (var stream = result.Content)
|
||||||
{
|
{
|
||||||
using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
|
using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
|
||||||
|
@ -287,7 +287,7 @@ namespace MediaBrowser.Api.Images
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(pointerCachePath));
|
||||||
_fileSystem.WriteAllText(pointerCachePath, fullCachePath);
|
_fileSystem.WriteAllText(pointerCachePath, fullCachePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -299,7 +299,7 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
|
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(fullCachePath));
|
||||||
using (var stream = result.Content)
|
using (var stream = result.Content)
|
||||||
{
|
{
|
||||||
using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
|
using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
|
||||||
|
@ -308,7 +308,7 @@ namespace MediaBrowser.Api
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(pointerCachePath));
|
||||||
_fileSystem.WriteAllText(pointerCachePath, fullCachePath);
|
_fileSystem.WriteAllText(pointerCachePath, fullCachePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,14 +62,7 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
var options = GetRefreshOptions(request);
|
var options = GetRefreshOptions(request);
|
||||||
|
|
||||||
if (item is Folder)
|
_providerManager.QueueRefresh(item.Id, options, RefreshPriority.High);
|
||||||
{
|
|
||||||
_providerManager.QueueRefresh(item.Id, options);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_providerManager.RefreshFullItem(item, options, CancellationToken.None);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private MetadataRefreshOptions GetRefreshOptions(BaseRefreshRequest request)
|
private MetadataRefreshOptions GetRefreshOptions(BaseRefreshRequest request)
|
||||||
|
|
|
@ -240,7 +240,6 @@ namespace MediaBrowser.Api
|
||||||
item.OriginalTitle = string.IsNullOrWhiteSpace(request.OriginalTitle) ? null : request.OriginalTitle;
|
item.OriginalTitle = string.IsNullOrWhiteSpace(request.OriginalTitle) ? null : request.OriginalTitle;
|
||||||
|
|
||||||
item.CriticRating = request.CriticRating;
|
item.CriticRating = request.CriticRating;
|
||||||
item.CriticRatingSummary = request.CriticRatingSummary;
|
|
||||||
|
|
||||||
item.DisplayMediaType = request.DisplayMediaType;
|
item.DisplayMediaType = request.DisplayMediaType;
|
||||||
item.CommunityRating = request.CommunityRating;
|
item.CommunityRating = request.CommunityRating;
|
||||||
|
|
|
@ -98,7 +98,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
/// Fields to return within the items, in addition to basic information
|
/// Fields to return within the items, in addition to basic information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The fields.</value>
|
/// <value>The fields.</value>
|
||||||
[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, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string Fields { get; set; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "AddCurrentProgram", Description = "Optional. Adds current program info to each channel", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "AddCurrentProgram", Description = "Optional. Adds current program info to each channel", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
@ -189,7 +189,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
/// Fields to return within the items, in addition to basic information
|
/// Fields to return within the items, in addition to basic information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The fields.</value>
|
/// <value>The fields.</value>
|
||||||
[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, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string Fields { get; set; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
public bool EnableTotalRecordCount { get; set; }
|
public bool EnableTotalRecordCount { get; set; }
|
||||||
|
@ -251,7 +251,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
/// Fields to return within the items, in addition to basic information
|
/// Fields to return within the items, in addition to basic information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The fields.</value>
|
/// <value>The fields.</value>
|
||||||
[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, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string Fields { get; set; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
public bool EnableTotalRecordCount { get; set; }
|
public bool EnableTotalRecordCount { get; set; }
|
||||||
|
@ -399,7 +399,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
/// Fields to return within the items, in addition to basic information
|
/// Fields to return within the items, in addition to basic information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The fields.</value>
|
/// <value>The fields.</value>
|
||||||
[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, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string Fields { get; set; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
public GetPrograms()
|
public GetPrograms()
|
||||||
|
@ -459,7 +459,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
/// Fields to return within the items, in addition to basic information
|
/// Fields to return within the items, in addition to basic information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The fields.</value>
|
/// <value>The fields.</value>
|
||||||
[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, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string Fields { get; set; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
||||||
|
|
|
@ -198,7 +198,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
CancellationTokenSource cancellationTokenSource,
|
CancellationTokenSource cancellationTokenSource,
|
||||||
string workingDirectory = null)
|
string workingDirectory = null)
|
||||||
{
|
{
|
||||||
FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
|
FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPath));
|
||||||
|
|
||||||
await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false);
|
await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
|
|
||||||
var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, logFilePrefix + "-" + Guid.NewGuid() + ".txt");
|
var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, logFilePrefix + "-" + Guid.NewGuid() + ".txt");
|
||||||
FileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath));
|
FileSystem.CreateDirectory(FileSystem.GetDirectoryName(logFilePath));
|
||||||
|
|
||||||
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
|
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
|
||||||
state.LogFileStream = FileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true);
|
state.LogFileStream = FileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true);
|
||||||
|
@ -315,8 +315,6 @@ namespace MediaBrowser.Api.Playback
|
||||||
StartThrottler(state, transcodingJob);
|
StartThrottler(state, transcodingJob);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReportUsage(state);
|
|
||||||
|
|
||||||
return transcodingJob;
|
return transcodingJob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -677,7 +675,8 @@ namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
Request = request,
|
Request = request,
|
||||||
RequestedUrl = url,
|
RequestedUrl = url,
|
||||||
UserAgent = Request.UserAgent
|
UserAgent = Request.UserAgent,
|
||||||
|
EnableDlnaHeaders = !string.IsNullOrWhiteSpace(request.Params)
|
||||||
};
|
};
|
||||||
|
|
||||||
var auth = AuthorizationContext.GetAuthorizationInfo(Request);
|
var auth = AuthorizationContext.GetAuthorizationInfo(Request);
|
||||||
|
@ -720,6 +719,13 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
|
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
//var primaryImage = item.GetImageInfo(ImageType.Primary, 0) ??
|
||||||
|
// item.Parents.Select(i => i.GetImageInfo(ImageType.Primary, 0)).FirstOrDefault(i => i != null);
|
||||||
|
//if (primaryImage != null)
|
||||||
|
//{
|
||||||
|
// state.AlbumCoverPath = primaryImage.Path;
|
||||||
|
//}
|
||||||
|
|
||||||
MediaSourceInfo mediaSource = null;
|
MediaSourceInfo mediaSource = null;
|
||||||
if (string.IsNullOrWhiteSpace(request.LiveStreamId))
|
if (string.IsNullOrWhiteSpace(request.LiveStreamId))
|
||||||
{
|
{
|
||||||
|
@ -903,123 +909,6 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void ReportUsage(StreamState state)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await ReportUsageInternal(state).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task ReportUsageInternal(StreamState state)
|
|
||||||
{
|
|
||||||
if (!ServerConfigurationManager.Configuration.EnableAnonymousUsageReporting)
|
|
||||||
{
|
|
||||||
return Task.FromResult(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!MediaEncoder.IsDefaultEncoderPath)
|
|
||||||
{
|
|
||||||
return Task.FromResult(true);
|
|
||||||
}
|
|
||||||
return Task.FromResult(true);
|
|
||||||
|
|
||||||
//var dict = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
//var outputAudio = GetAudioEncoder(state);
|
|
||||||
//if (!string.IsNullOrWhiteSpace(outputAudio))
|
|
||||||
//{
|
|
||||||
// dict["outputAudio"] = outputAudio;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//var outputVideo = GetVideoEncoder(state);
|
|
||||||
//if (!string.IsNullOrWhiteSpace(outputVideo))
|
|
||||||
//{
|
|
||||||
// dict["outputVideo"] = outputVideo;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if (ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputAudio ?? string.Empty, StringComparer.OrdinalIgnoreCase) &&
|
|
||||||
// ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputVideo ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
|
||||||
//{
|
|
||||||
// return Task.FromResult(true);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//dict["id"] = AppHost.SystemId;
|
|
||||||
//dict["type"] = state.VideoRequest == null ? "Audio" : "Video";
|
|
||||||
|
|
||||||
//var audioStream = state.AudioStream;
|
|
||||||
//if (audioStream != null && !string.IsNullOrWhiteSpace(audioStream.Codec))
|
|
||||||
//{
|
|
||||||
// dict["inputAudio"] = audioStream.Codec;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//var videoStream = state.VideoStream;
|
|
||||||
//if (videoStream != null && !string.IsNullOrWhiteSpace(videoStream.Codec))
|
|
||||||
//{
|
|
||||||
// dict["inputVideo"] = videoStream.Codec;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//var cert = GetType().Assembly.GetModules().First().GetSignerCertificate();
|
|
||||||
//if (cert != null)
|
|
||||||
//{
|
|
||||||
// dict["assemblySig"] = cert.GetCertHashString();
|
|
||||||
// dict["certSubject"] = cert.Subject ?? string.Empty;
|
|
||||||
// dict["certIssuer"] = cert.Issuer ?? string.Empty;
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// return Task.FromResult(true);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if (state.SupportedAudioCodecs.Count > 0)
|
|
||||||
//{
|
|
||||||
// dict["supportedAudioCodecs"] = string.Join(",", state.SupportedAudioCodecs.ToArray());
|
|
||||||
//}
|
|
||||||
|
|
||||||
//var auth = AuthorizationContext.GetAuthorizationInfo(Request);
|
|
||||||
|
|
||||||
//dict["appName"] = auth.Client ?? string.Empty;
|
|
||||||
//dict["appVersion"] = auth.Version ?? string.Empty;
|
|
||||||
//dict["device"] = auth.Device ?? string.Empty;
|
|
||||||
//dict["deviceId"] = auth.DeviceId ?? string.Empty;
|
|
||||||
//dict["context"] = "streaming";
|
|
||||||
|
|
||||||
////Logger.Info(JsonSerializer.SerializeToString(dict));
|
|
||||||
//if (!ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputAudio ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
|
||||||
//{
|
|
||||||
// var list = ServerConfigurationManager.Configuration.CodecsUsed.ToList();
|
|
||||||
// list.Add(outputAudio);
|
|
||||||
// ServerConfigurationManager.Configuration.CodecsUsed = list.ToArray();
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if (!ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputVideo ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
|
||||||
//{
|
|
||||||
// var list = ServerConfigurationManager.Configuration.CodecsUsed.ToList();
|
|
||||||
// list.Add(outputVideo);
|
|
||||||
// ServerConfigurationManager.Configuration.CodecsUsed = list.ToArray();
|
|
||||||
//}
|
|
||||||
|
|
||||||
//ServerConfigurationManager.SaveConfiguration();
|
|
||||||
|
|
||||||
////Logger.Info(JsonSerializer.SerializeToString(dict));
|
|
||||||
//var options = new HttpRequestOptions()
|
|
||||||
//{
|
|
||||||
// Url = "https://mb3admin.com/admin/service/transcoding/report",
|
|
||||||
// CancellationToken = CancellationToken.None,
|
|
||||||
// LogRequest = false,
|
|
||||||
// LogErrors = false,
|
|
||||||
// BufferContent = false
|
|
||||||
//};
|
|
||||||
//options.RequestContent = JsonSerializer.SerializeToString(dict);
|
|
||||||
//options.RequestContentType = "application/json";
|
|
||||||
|
|
||||||
//return HttpClient.Post(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the dlna headers.
|
/// Adds the dlna headers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1029,6 +918,11 @@ namespace MediaBrowser.Api.Playback
|
||||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
||||||
protected void AddDlnaHeaders(StreamState state, IDictionary<string, string> responseHeaders, bool isStaticallyStreamed)
|
protected void AddDlnaHeaders(StreamState state, IDictionary<string, string> responseHeaders, bool isStaticallyStreamed)
|
||||||
{
|
{
|
||||||
|
if (!state.EnableDlnaHeaders)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var profile = state.DeviceProfile;
|
var profile = state.DeviceProfile;
|
||||||
|
|
||||||
var transferMode = GetHeader("transferMode.dlna.org");
|
var transferMode = GetHeader("transferMode.dlna.org");
|
||||||
|
|
|
@ -13,10 +13,7 @@ using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.IO;
|
|
||||||
using MediaBrowser.Controller.IO;
|
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Playback.Hls
|
namespace MediaBrowser.Api.Playback.Hls
|
||||||
{
|
{
|
||||||
|
@ -271,7 +268,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
var useGenericSegmenter = true;
|
var useGenericSegmenter = true;
|
||||||
if (useGenericSegmenter)
|
if (useGenericSegmenter)
|
||||||
{
|
{
|
||||||
var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request);
|
var outputTsArg = Path.Combine(FileSystem.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request);
|
||||||
|
|
||||||
var timeDeltaParam = String.Empty;
|
var timeDeltaParam = String.Empty;
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
public string SegmentId { get; set; }
|
public string SegmentId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Authenticated]
|
||||||
public class DynamicHlsService : BaseHlsService
|
public class DynamicHlsService : BaseHlsService
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -378,7 +379,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
private static FileSystemMetadata GetLastTranscodingFile(string playlist, string segmentExtension, IFileSystem fileSystem)
|
private static FileSystemMetadata GetLastTranscodingFile(string playlist, string segmentExtension, IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
var folder = Path.GetDirectoryName(playlist);
|
var folder = fileSystem.GetDirectoryName(playlist);
|
||||||
|
|
||||||
var filePrefix = Path.GetFileNameWithoutExtension(playlist) ?? string.Empty;
|
var filePrefix = Path.GetFileNameWithoutExtension(playlist) ?? string.Empty;
|
||||||
|
|
||||||
|
@ -415,7 +416,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
private string GetSegmentPath(StreamState state, string playlist, int index)
|
private string GetSegmentPath(StreamState state, string playlist, int index)
|
||||||
{
|
{
|
||||||
var folder = Path.GetDirectoryName(playlist);
|
var folder = FileSystem.GetDirectoryName(playlist);
|
||||||
|
|
||||||
var filename = Path.GetFileNameWithoutExtension(playlist);
|
var filename = Path.GetFileNameWithoutExtension(playlist);
|
||||||
|
|
||||||
|
@ -807,7 +808,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return "-codec:a:0 copy";
|
return "-codec:a:0 copy -copypriorss:a:0 0";
|
||||||
}
|
}
|
||||||
|
|
||||||
var args = "-codec:a:0 " + codec;
|
var args = "-codec:a:0 " + codec;
|
||||||
|
@ -925,7 +926,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
if (useGenericSegmenter)
|
if (useGenericSegmenter)
|
||||||
{
|
{
|
||||||
var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request);
|
var outputTsArg = Path.Combine(FileSystem.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request);
|
||||||
|
|
||||||
var timeDeltaParam = String.Empty;
|
var timeDeltaParam = String.Empty;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetHlsAudioSegment
|
/// Class GetHlsAudioSegment
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
// Can't require authentication just yet due to seeing some requests come from Chrome without full query string
|
||||||
|
//[Authenticated]
|
||||||
[Route("/Audio/{Id}/hls/{SegmentId}/stream.mp3", "GET")]
|
[Route("/Audio/{Id}/hls/{SegmentId}/stream.mp3", "GET")]
|
||||||
[Route("/Audio/{Id}/hls/{SegmentId}/stream.aac", "GET")]
|
[Route("/Audio/{Id}/hls/{SegmentId}/stream.aac", "GET")]
|
||||||
public class GetHlsAudioSegmentLegacy
|
public class GetHlsAudioSegmentLegacy
|
||||||
|
@ -38,6 +40,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
/// Class GetHlsVideoSegment
|
/// Class GetHlsVideoSegment
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Videos/{Id}/hls/{PlaylistId}/stream.m3u8", "GET")]
|
[Route("/Videos/{Id}/hls/{PlaylistId}/stream.m3u8", "GET")]
|
||||||
|
[Authenticated]
|
||||||
public class GetHlsPlaylistLegacy
|
public class GetHlsPlaylistLegacy
|
||||||
{
|
{
|
||||||
// TODO: Deprecate with new iOS app
|
// TODO: Deprecate with new iOS app
|
||||||
|
@ -52,6 +55,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Videos/ActiveEncodings", "DELETE")]
|
[Route("/Videos/ActiveEncodings", "DELETE")]
|
||||||
|
[Authenticated]
|
||||||
public class StopEncodingProcess
|
public class StopEncodingProcess
|
||||||
{
|
{
|
||||||
[ApiMember(Name = "DeviceId", Description = "The device id of the client requesting. Used to stop encoding processes when needed.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
|
[ApiMember(Name = "DeviceId", Description = "The device id of the client requesting. Used to stop encoding processes when needed.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
|
||||||
|
@ -64,6 +68,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetHlsVideoSegment
|
/// Class GetHlsVideoSegment
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
// Can't require authentication just yet due to seeing some requests come from Chrome without full query string
|
||||||
|
//[Authenticated]
|
||||||
[Route("/Videos/{Id}/hls/{PlaylistId}/{SegmentId}.{SegmentContainer}", "GET")]
|
[Route("/Videos/{Id}/hls/{PlaylistId}/{SegmentId}.{SegmentContainer}", "GET")]
|
||||||
public class GetHlsVideoSegmentLegacy : VideoStreamRequest
|
public class GetHlsVideoSegmentLegacy : VideoStreamRequest
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class VideoHlsService
|
/// Class VideoHlsService
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Authenticated]
|
||||||
public class VideoHlsService : BaseHlsService
|
public class VideoHlsService : BaseHlsService
|
||||||
{
|
{
|
||||||
public object Get(GetLiveHlsStream request)
|
public object Get(GetLiveHlsStream request)
|
||||||
|
|
|
@ -59,42 +59,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
{
|
{
|
||||||
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
|
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
|
||||||
|
|
||||||
var audioTranscodeParams = new List<string>();
|
return EncodingHelper.GetProgressiveAudioFullCommandLine(state, encodingOptions, outputPath);
|
||||||
|
|
||||||
var bitrate = state.OutputAudioBitrate;
|
|
||||||
|
|
||||||
if (bitrate.HasValue)
|
|
||||||
{
|
|
||||||
audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(UsCulture));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.OutputAudioChannels.HasValue)
|
|
||||||
{
|
|
||||||
audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(UsCulture));
|
|
||||||
}
|
|
||||||
|
|
||||||
// opus will fail on 44100
|
|
||||||
if (!string.Equals(state.OutputAudioCodec, "opus", global::System.StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
if (state.OutputAudioSampleRate.HasValue)
|
|
||||||
{
|
|
||||||
audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const string vn = " -vn";
|
|
||||||
|
|
||||||
var threads = EncodingHelper.GetNumberOfThreads(state, encodingOptions, false);
|
|
||||||
|
|
||||||
var inputModifier = EncodingHelper.GetInputModifier(state, encodingOptions);
|
|
||||||
|
|
||||||
return string.Format("{0} {1} -threads {2}{3} {4} -id3v2_version 3 -write_id3v1 1 -y \"{5}\"",
|
|
||||||
inputModifier,
|
|
||||||
EncodingHelper.GetInputArgument(state, encodingOptions),
|
|
||||||
threads,
|
|
||||||
vn,
|
|
||||||
string.Join(" ", audioTranscodeParams.ToArray()),
|
|
||||||
outputPath).Trim();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext, imageProcessor)
|
public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext, imageProcessor)
|
||||||
|
|
|
@ -62,6 +62,8 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class VideoService
|
/// Class VideoService
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
// TODO: In order to autheneticate this in the future, Dlna playback will require updating
|
||||||
|
//[Authenticated]
|
||||||
public class VideoService : BaseProgressiveStreamingService
|
public class VideoService : BaseProgressiveStreamingService
|
||||||
{
|
{
|
||||||
public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext, imageProcessor)
|
public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext, imageProcessor)
|
||||||
|
|
|
@ -138,6 +138,8 @@ namespace MediaBrowser.Api.Playback
|
||||||
return MimeTypes.GetMimeType(outputPath);
|
return MimeTypes.GetMimeType(outputPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool EnableDlnaHeaders { get; set; }
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
DisposeTranscodingThrottler();
|
DisposeTranscodingThrottler();
|
||||||
|
|
|
@ -102,7 +102,7 @@ namespace MediaBrowser.Api
|
||||||
/// Fields to return within the items, in addition to basic information
|
/// Fields to return within the items, in addition to basic information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The fields.</value>
|
/// <value>The fields.</value>
|
||||||
[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, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string Fields { get; set; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
||||||
|
|
|
@ -300,11 +300,6 @@ namespace MediaBrowser.Api.Reports
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.LocationTypes))
|
|
||||||
{
|
|
||||||
query.LocationTypes = request.LocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Min official rating
|
// Min official rating
|
||||||
if (!string.IsNullOrWhiteSpace(request.MinOfficialRating))
|
if (!string.IsNullOrWhiteSpace(request.MinOfficialRating))
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,6 +9,7 @@ using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Search;
|
using MediaBrowser.Model.Search;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
|
@ -66,6 +67,23 @@ namespace MediaBrowser.Api
|
||||||
[ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string IncludeItemTypes { get; set; }
|
public string IncludeItemTypes { get; set; }
|
||||||
|
|
||||||
|
public string ParentId { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
public bool? IsMovie { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
public bool? IsSeries { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
public bool? IsNews { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
public bool? IsKids { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
public bool? IsSports { get; set; }
|
||||||
|
|
||||||
public GetSearchHints()
|
public GetSearchHints()
|
||||||
{
|
{
|
||||||
IncludeArtists = true;
|
IncludeArtists = true;
|
||||||
|
@ -135,7 +153,14 @@ namespace MediaBrowser.Api
|
||||||
IncludeStudios = request.IncludeStudios,
|
IncludeStudios = request.IncludeStudios,
|
||||||
StartIndex = request.StartIndex,
|
StartIndex = request.StartIndex,
|
||||||
UserId = request.UserId,
|
UserId = request.UserId,
|
||||||
IncludeItemTypes = (request.IncludeItemTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray()
|
IncludeItemTypes = (request.IncludeItemTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray(),
|
||||||
|
ParentId = request.ParentId,
|
||||||
|
|
||||||
|
IsKids = request.IsKids,
|
||||||
|
IsMovie = request.IsMovie,
|
||||||
|
IsNews = request.IsNews,
|
||||||
|
IsSeries = request.IsSeries,
|
||||||
|
IsSports = request.IsSports
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -167,11 +192,11 @@ namespace MediaBrowser.Api
|
||||||
MatchedTerm = hintInfo.MatchedTerm,
|
MatchedTerm = hintInfo.MatchedTerm,
|
||||||
DisplayMediaType = item.DisplayMediaType,
|
DisplayMediaType = item.DisplayMediaType,
|
||||||
RunTimeTicks = item.RunTimeTicks,
|
RunTimeTicks = item.RunTimeTicks,
|
||||||
ProductionYear = item.ProductionYear
|
ProductionYear = item.ProductionYear,
|
||||||
|
ChannelId = item.ChannelId,
|
||||||
|
EndDate = item.EndDate
|
||||||
};
|
};
|
||||||
|
|
||||||
result.ChannelId = item.ChannelId;
|
|
||||||
|
|
||||||
var primaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
|
var primaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
|
||||||
|
|
||||||
if (primaryImageTag != null)
|
if (primaryImageTag != null)
|
||||||
|
@ -183,12 +208,27 @@ namespace MediaBrowser.Api
|
||||||
SetThumbImageInfo(result, item);
|
SetThumbImageInfo(result, item);
|
||||||
SetBackdropImageInfo(result, item);
|
SetBackdropImageInfo(result, item);
|
||||||
|
|
||||||
|
var program = item as LiveTvProgram;
|
||||||
|
if (program != null)
|
||||||
|
{
|
||||||
|
result.StartDate = program.StartDate;
|
||||||
|
}
|
||||||
|
|
||||||
var hasSeries = item as IHasSeries;
|
var hasSeries = item as IHasSeries;
|
||||||
if (hasSeries != null)
|
if (hasSeries != null)
|
||||||
{
|
{
|
||||||
result.Series = hasSeries.SeriesName;
|
result.Series = hasSeries.SeriesName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var series = item as Series;
|
||||||
|
if (series != null)
|
||||||
|
{
|
||||||
|
if (series.Status.HasValue)
|
||||||
|
{
|
||||||
|
result.Status = series.Status.Value.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var album = item as MusicAlbum;
|
var album = item as MusicAlbum;
|
||||||
|
|
||||||
if (album != null)
|
if (album != null)
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace MediaBrowser.Api.Session
|
||||||
|
|
||||||
void _sessionManager_PlaybackProgress(object sender, PlaybackProgressEventArgs e)
|
void _sessionManager_PlaybackProgress(object sender, PlaybackProgressEventArgs e)
|
||||||
{
|
{
|
||||||
SendData(false);
|
SendData(!e.IsAutomated);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e)
|
void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e)
|
||||||
|
|
|
@ -61,7 +61,7 @@ namespace MediaBrowser.Api
|
||||||
/// Fields to return within the items, in addition to basic information
|
/// Fields to return within the items, in addition to basic information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The fields.</value>
|
/// <value>The fields.</value>
|
||||||
[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, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, 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; }
|
public string Fields { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,12 +95,12 @@ namespace MediaBrowser.Api
|
||||||
config.EnableStandaloneMusicKeys = true;
|
config.EnableStandaloneMusicKeys = true;
|
||||||
config.EnableCaseSensitiveItemIds = true;
|
config.EnableCaseSensitiveItemIds = true;
|
||||||
config.SkipDeserializationForBasicTypes = true;
|
config.SkipDeserializationForBasicTypes = true;
|
||||||
config.SkipDeserializationForPrograms = true;
|
|
||||||
config.SkipDeserializationForAudio = true;
|
config.SkipDeserializationForAudio = true;
|
||||||
config.EnableSeriesPresentationUniqueKey = true;
|
config.EnableSeriesPresentationUniqueKey = true;
|
||||||
config.EnableLocalizedGuids = true;
|
config.EnableLocalizedGuids = true;
|
||||||
config.EnableSimpleArtistDetection = true;
|
config.EnableSimpleArtistDetection = true;
|
||||||
config.EnableNormalizedItemByNameIds = true;
|
config.EnableNormalizedItemByNameIds = true;
|
||||||
|
config.DisableLiveTvChannelUserDataName = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(UpdateStartupConfiguration request)
|
public void Post(UpdateStartupConfiguration request)
|
||||||
|
|
|
@ -288,7 +288,7 @@ namespace MediaBrowser.Api.Subtitles
|
||||||
await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None)
|
await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
_providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(_fileSystem));
|
_providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.High);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace MediaBrowser.Api
|
||||||
/// Fields to return within the items, in addition to basic information
|
/// Fields to return within the items, in addition to basic information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The fields.</value>
|
/// <value>The fields.</value>
|
||||||
[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, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, 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; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "SeriesId", Description = "Optional. Filter by series id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "SeriesId", Description = "Optional. Filter by series id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
@ -108,7 +108,7 @@ namespace MediaBrowser.Api
|
||||||
/// Fields to return within the items, in addition to basic information
|
/// Fields to return within the items, in addition to basic information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The fields.</value>
|
/// <value>The fields.</value>
|
||||||
[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, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, 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; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -150,7 +150,7 @@ namespace MediaBrowser.Api
|
||||||
/// Fields to return within the items, in addition to basic information
|
/// Fields to return within the items, in addition to basic information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The fields.</value>
|
/// <value>The fields.</value>
|
||||||
[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, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, 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; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
@ -215,7 +215,7 @@ namespace MediaBrowser.Api
|
||||||
/// Fields to return within the items, in addition to basic information
|
/// Fields to return within the items, in addition to basic information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The fields.</value>
|
/// <value>The fields.</value>
|
||||||
[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, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, 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; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
|
@ -497,7 +497,7 @@ namespace MediaBrowser.Api
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
episodes = series.GetSeasonEpisodes(season, user);
|
episodes = season.GetEpisodes(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -146,7 +146,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
/// Fields to return within the items, in addition to basic information
|
/// Fields to return within the items, in addition to basic information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The fields.</value>
|
/// <value>The fields.</value>
|
||||||
[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, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string Fields { get; set; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -328,7 +328,15 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.LocationTypes))
|
if (!string.IsNullOrEmpty(request.LocationTypes))
|
||||||
{
|
{
|
||||||
query.LocationTypes = request.LocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
|
var requestedLocationTypes =
|
||||||
|
request.LocationTypes.Split(',')
|
||||||
|
.Select(d => (LocationType) Enum.Parse(typeof (LocationType), d, true))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (requestedLocationTypes.Count > 0 && requestedLocationTypes.Count < 4)
|
||||||
|
{
|
||||||
|
query.IsVirtualItem = requestedLocationTypes.Contains(LocationType.Virtual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Min official rating
|
// Min official rating
|
||||||
|
|
|
@ -225,7 +225,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
[ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string ParentId { get; set; }
|
public string ParentId { get; set; }
|
||||||
|
|
||||||
[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, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string Fields { get; set; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
|
|
|
@ -444,7 +444,7 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
public async Task PostAsync(UpdateUserPassword request)
|
public async Task PostAsync(UpdateUserPassword request)
|
||||||
{
|
{
|
||||||
AssertCanUpdateUser(_authContext, _userManager, request.Id);
|
AssertCanUpdateUser(_authContext, _userManager, request.Id, true);
|
||||||
|
|
||||||
var user = _userManager.GetUserById(request.Id);
|
var user = _userManager.GetUserById(request.Id);
|
||||||
|
|
||||||
|
@ -482,7 +482,7 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
public async Task PostAsync(UpdateUserEasyPassword request)
|
public async Task PostAsync(UpdateUserEasyPassword request)
|
||||||
{
|
{
|
||||||
AssertCanUpdateUser(_authContext, _userManager, request.Id);
|
AssertCanUpdateUser(_authContext, _userManager, request.Id, true);
|
||||||
|
|
||||||
var user = _userManager.GetUserById(request.Id);
|
var user = _userManager.GetUserById(request.Id);
|
||||||
|
|
||||||
|
@ -518,7 +518,7 @@ namespace MediaBrowser.Api
|
||||||
// https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
|
// https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
|
||||||
var id = GetPathValue(1);
|
var id = GetPathValue(1);
|
||||||
|
|
||||||
AssertCanUpdateUser(_authContext, _userManager, id);
|
AssertCanUpdateUser(_authContext, _userManager, id, false);
|
||||||
|
|
||||||
var dtoUser = request;
|
var dtoUser = request;
|
||||||
|
|
||||||
|
@ -568,7 +568,7 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
public void Post(UpdateUserConfiguration request)
|
public void Post(UpdateUserConfiguration request)
|
||||||
{
|
{
|
||||||
AssertCanUpdateUser(_authContext, _userManager, request.Id);
|
AssertCanUpdateUser(_authContext, _userManager, request.Id, false);
|
||||||
|
|
||||||
var task = _userManager.UpdateConfiguration(request.Id, request);
|
var task = _userManager.UpdateConfiguration(request.Id, request);
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Controller.Channels;
|
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.Audio
|
namespace MediaBrowser.Controller.Entities.Audio
|
||||||
|
@ -24,8 +23,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
IHasLookupInfo<SongInfo>,
|
IHasLookupInfo<SongInfo>,
|
||||||
IHasMediaSources
|
IHasMediaSources
|
||||||
{
|
{
|
||||||
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the artist.
|
/// Gets or sets the artist.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -112,7 +112,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
|
|
||||||
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
query.Genres = new[] { Name };
|
query.GenreIds = new[] { Id.ToString("N") };
|
||||||
query.IncludeItemTypes = new[] { typeof(MusicVideo).Name, typeof(Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
|
query.IncludeItemTypes = new[] { typeof(MusicVideo).Name, typeof(Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
|
||||||
|
|
||||||
return LibraryManager.GetItemList(query);
|
return LibraryManager.GetItemList(query);
|
||||||
|
|
|
@ -31,12 +31,10 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public string SeriesName { get; set; }
|
public string SeriesName { get; set; }
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public Guid? SeriesId { get; set; }
|
public Guid? SeriesId { get; set; }
|
||||||
[IgnoreDataMember]
|
|
||||||
public string SeriesSortName { get; set; }
|
|
||||||
|
|
||||||
public string FindSeriesSortName()
|
public string FindSeriesSortName()
|
||||||
{
|
{
|
||||||
return SeriesSortName;
|
return SeriesName;
|
||||||
}
|
}
|
||||||
public string FindSeriesName()
|
public string FindSeriesName()
|
||||||
{
|
{
|
||||||
|
|
|
@ -84,6 +84,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public long? Size { get; set; }
|
public long? Size { get; set; }
|
||||||
public string Container { get; set; }
|
public string Container { get; set; }
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public string Tagline { get; set; }
|
public string Tagline { get; set; }
|
||||||
|
|
||||||
|
@ -288,7 +289,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return Path;
|
return Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
return System.IO.Path.GetDirectoryName(Path);
|
return FileSystem.GetDirectoryName(Path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -834,20 +835,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public float? CriticRating { get; set; }
|
public float? CriticRating { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the critic rating summary.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The critic rating summary.</value>
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public string CriticRatingSummary { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the official rating description.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The official rating description.</value>
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public string OfficialRatingDescription { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the custom rating.
|
/// Gets or sets the custom rating.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1824,7 +1811,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
public virtual Task ChangedExternally()
|
public virtual Task ChangedExternally()
|
||||||
{
|
{
|
||||||
ProviderManager.QueueRefresh(Id, new MetadataRefreshOptions(FileSystem));
|
ProviderManager.QueueRefresh(Id, new MetadataRefreshOptions(FileSystem), RefreshPriority.High);
|
||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1924,7 +1911,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
var allFiles = ImageInfos
|
var allFiles = ImageInfos
|
||||||
.Where(i => i.IsLocalFile)
|
.Where(i => i.IsLocalFile)
|
||||||
.Select(i => System.IO.Path.GetDirectoryName(i.Path))
|
.Select(i => FileSystem.GetDirectoryName(i.Path))
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
.SelectMany(directoryService.GetFilePaths)
|
.SelectMany(directoryService.GetFilePaths)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
@ -2099,7 +2086,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
var extensions = new[] { ".nfo", ".xml", ".srt" }.ToList();
|
var extensions = new[] { ".nfo", ".xml", ".srt" }.ToList();
|
||||||
extensions.AddRange(SupportedImageExtensionsList);
|
extensions.AddRange(SupportedImageExtensionsList);
|
||||||
|
|
||||||
return FileSystem.GetFiles(System.IO.Path.GetDirectoryName(Path), extensions.ToArray(), false, false)
|
return FileSystem.GetFiles(FileSystem.GetDirectoryName(Path), extensions.ToArray(), false, false)
|
||||||
.Where(i => System.IO.Path.GetFileNameWithoutExtension(i.FullName).StartsWith(filename, StringComparison.OrdinalIgnoreCase))
|
.Where(i => System.IO.Path.GetFileNameWithoutExtension(i.FullName).StartsWith(filename, StringComparison.OrdinalIgnoreCase))
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
@ -2298,16 +2285,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
ownedItem.CustomRating = item.CustomRating;
|
ownedItem.CustomRating = item.CustomRating;
|
||||||
newOptions.ForceSave = true;
|
newOptions.ForceSave = true;
|
||||||
}
|
}
|
||||||
if (!string.Equals(item.CriticRatingSummary, ownedItem.CriticRatingSummary, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
ownedItem.CriticRatingSummary = item.CriticRatingSummary;
|
|
||||||
newOptions.ForceSave = true;
|
|
||||||
}
|
|
||||||
if (!string.Equals(item.OfficialRatingDescription, ownedItem.OfficialRatingDescription, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
ownedItem.OfficialRatingDescription = item.OfficialRatingDescription;
|
|
||||||
newOptions.ForceSave = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ownedItem.RefreshMetadata(newOptions, cancellationToken);
|
return ownedItem.RefreshMetadata(newOptions, cancellationToken);
|
||||||
|
|
|
@ -24,12 +24,10 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public string SeriesName { get; set; }
|
public string SeriesName { get; set; }
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public Guid? SeriesId { get; set; }
|
public Guid? SeriesId { get; set; }
|
||||||
[IgnoreDataMember]
|
|
||||||
public string SeriesSortName { get; set; }
|
|
||||||
|
|
||||||
public string FindSeriesSortName()
|
public string FindSeriesSortName()
|
||||||
{
|
{
|
||||||
return SeriesSortName;
|
return SeriesName;
|
||||||
}
|
}
|
||||||
public string FindSeriesName()
|
public string FindSeriesName()
|
||||||
{
|
{
|
||||||
|
|
|
@ -213,7 +213,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
.SelectMany(c => c.LinkedChildren)
|
.SelectMany(c => c.LinkedChildren)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var changed = !linkedChildren.SequenceEqual(LinkedChildren, new LinkedChildComparer());
|
var changed = !linkedChildren.SequenceEqual(LinkedChildren, new LinkedChildComparer(FileSystem));
|
||||||
|
|
||||||
LinkedChildren = linkedChildren;
|
LinkedChildren = linkedChildren;
|
||||||
|
|
||||||
|
@ -332,13 +332,13 @@ namespace MediaBrowser.Controller.Entities
|
||||||
.OfType<Folder>()
|
.OfType<Folder>()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
return PhysicalLocations.Where(i => !string.Equals(i, Path, StringComparison.OrdinalIgnoreCase)).SelectMany(i => GetPhysicalParents(i, rootChildren)).DistinctBy(i => i.Id);
|
return PhysicalLocations.Where(i => !FileSystem.AreEqual(i, Path)).SelectMany(i => GetPhysicalParents(i, rootChildren)).DistinctBy(i => i.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<Folder> GetPhysicalParents(string path, List<Folder> rootChildren)
|
private IEnumerable<Folder> GetPhysicalParents(string path, List<Folder> rootChildren)
|
||||||
{
|
{
|
||||||
var result = rootChildren
|
var result = rootChildren
|
||||||
.Where(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase))
|
.Where(i => FileSystem.AreEqual(i.Path, path))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (result.Count == 0)
|
if (result.Count == 0)
|
||||||
|
|
|
@ -640,7 +640,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
path = System.IO.Path.GetDirectoryName(path);
|
path = FileSystem.GetDirectoryName(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
return allLibraryPaths.Any(i => ContainsPath(i, originalPath));
|
return allLibraryPaths.Any(i => ContainsPath(i, originalPath));
|
||||||
|
@ -1206,11 +1206,17 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return GetLinkedChildren();
|
return GetLinkedChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
var locations = user.RootFolder
|
if (LinkedChildren.Count == 0)
|
||||||
.Children
|
{
|
||||||
|
return new List<BaseItem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
var allUserRootChildren = user.RootFolder.Children.OfType<Folder>().ToList();
|
||||||
|
|
||||||
|
var collectionFolderIds = allUserRootChildren
|
||||||
.OfType<CollectionFolder>()
|
.OfType<CollectionFolder>()
|
||||||
.Where(i => i.IsVisible(user))
|
.Where(i => i.IsVisible(user))
|
||||||
.SelectMany(i => i.PhysicalLocations)
|
.Select(i => i.Id)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
return LinkedChildren
|
return LinkedChildren
|
||||||
|
@ -1228,11 +1234,18 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (childLocationType == LocationType.FileSystem && !locations.Any(l => FileSystem.ContainsSubPath(l, child.Path)))
|
else if (childLocationType == LocationType.FileSystem)
|
||||||
|
{
|
||||||
|
var itemCollectionFolderIds =
|
||||||
|
LibraryManager.GetCollectionFolders(child, allUserRootChildren)
|
||||||
|
.Select(f => f.Id).ToList();
|
||||||
|
|
||||||
|
if (!itemCollectionFolderIds.Any(collectionFolderIds.Contains))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return child;
|
return child;
|
||||||
})
|
})
|
||||||
|
@ -1323,7 +1336,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
else { newShortcutLinks = new List<LinkedChild>(); }
|
else { newShortcutLinks = new List<LinkedChild>(); }
|
||||||
|
|
||||||
if (!newShortcutLinks.SequenceEqual(currentShortcutLinks, new LinkedChildComparer()))
|
if (!newShortcutLinks.SequenceEqual(currentShortcutLinks, new LinkedChildComparer(FileSystem)))
|
||||||
{
|
{
|
||||||
Logger.Info("Shortcut links have changed for {0}", Path);
|
Logger.Info("Shortcut links have changed for {0}", Path);
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return new[] {
|
return new[] {
|
||||||
new FileSystemMetadata
|
new FileSystemMetadata
|
||||||
{
|
{
|
||||||
FullName = System.IO.Path.GetDirectoryName(Path),
|
FullName = FileSystem.GetDirectoryName(Path),
|
||||||
IsDirectory = true
|
IsDirectory = true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
query.Genres = new[] { Name };
|
query.GenreIds = new[] { Id.ToString("N") };
|
||||||
query.IncludeItemTypes = new[] { typeof(Game).Name };
|
query.IncludeItemTypes = new[] { typeof(Game).Name };
|
||||||
|
|
||||||
return LibraryManager.GetItemList(query);
|
return LibraryManager.GetItemList(query);
|
||||||
|
|
|
@ -93,7 +93,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
query.Genres = new[] { Name };
|
query.GenreIds = new[] { Id.ToString("N") };
|
||||||
query.ExcludeItemTypes = new[] { typeof(Game).Name, typeof(MusicVideo).Name, typeof(Audio.Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
|
query.ExcludeItemTypes = new[] { typeof(Game).Name, typeof(MusicVideo).Name, typeof(Audio.Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
|
||||||
|
|
||||||
return LibraryManager.GetItemList(query);
|
return LibraryManager.GetItemList(query);
|
||||||
|
|
|
@ -11,7 +11,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// <value>The name of the series.</value>
|
/// <value>The name of the series.</value>
|
||||||
string SeriesName { get; set; }
|
string SeriesName { get; set; }
|
||||||
string FindSeriesName();
|
string FindSeriesName();
|
||||||
string SeriesSortName { get; set; }
|
|
||||||
string FindSeriesSortName();
|
string FindSeriesSortName();
|
||||||
Guid? SeriesId { get; set; }
|
Guid? SeriesId { get; set; }
|
||||||
Guid? FindSeriesId();
|
Guid? FindSeriesId();
|
||||||
|
|
|
@ -129,7 +129,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public string[] AncestorIds { get; set; }
|
public string[] AncestorIds { get; set; }
|
||||||
public string[] TopParentIds { get; set; }
|
public string[] TopParentIds { get; set; }
|
||||||
|
|
||||||
public LocationType[] LocationTypes { get; set; }
|
|
||||||
public string[] PresetViews { get; set; }
|
public string[] PresetViews { get; set; }
|
||||||
public SourceType[] SourceTypes { get; set; }
|
public SourceType[] SourceTypes { get; set; }
|
||||||
public SourceType[] ExcludeSourceTypes { get; set; }
|
public SourceType[] ExcludeSourceTypes { get; set; }
|
||||||
|
@ -176,7 +175,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
case ItemFields.DateCreated:
|
case ItemFields.DateCreated:
|
||||||
case ItemFields.SortName:
|
case ItemFields.SortName:
|
||||||
case ItemFields.Overview:
|
case ItemFields.Overview:
|
||||||
case ItemFields.OfficialRatingDescription:
|
|
||||||
case ItemFields.HomePageUrl:
|
case ItemFields.HomePageUrl:
|
||||||
case ItemFields.VoteCount:
|
case ItemFields.VoteCount:
|
||||||
case ItemFields.DisplayMediaType:
|
case ItemFields.DisplayMediaType:
|
||||||
|
@ -187,7 +185,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
case ItemFields.OriginalTitle:
|
case ItemFields.OriginalTitle:
|
||||||
case ItemFields.Tags:
|
case ItemFields.Tags:
|
||||||
case ItemFields.DateLastMediaAdded:
|
case ItemFields.DateLastMediaAdded:
|
||||||
case ItemFields.CriticRatingSummary:
|
|
||||||
return fields.Count == 0 || fields.Contains(name);
|
return fields.Count == 0 || fields.Contains(name);
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
|
@ -230,7 +227,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
TopParentIds = new string[] { };
|
TopParentIds = new string[] { };
|
||||||
ExcludeTags = new string[] { };
|
ExcludeTags = new string[] { };
|
||||||
ExcludeInheritedTags = new string[] { };
|
ExcludeInheritedTags = new string[] { };
|
||||||
LocationTypes = new LocationType[] { };
|
|
||||||
PresetViews = new string[] { };
|
PresetViews = new string[] { };
|
||||||
SourceTypes = new SourceType[] { };
|
SourceTypes = new SourceType[] { };
|
||||||
ExcludeSourceTypes = new SourceType[] { };
|
ExcludeSourceTypes = new SourceType[] { };
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
|
@ -40,11 +41,18 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public class LinkedChildComparer : IEqualityComparer<LinkedChild>
|
public class LinkedChildComparer : IEqualityComparer<LinkedChild>
|
||||||
{
|
{
|
||||||
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
|
public LinkedChildComparer(IFileSystem fileSystem)
|
||||||
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
}
|
||||||
|
|
||||||
public bool Equals(LinkedChild x, LinkedChild y)
|
public bool Equals(LinkedChild x, LinkedChild y)
|
||||||
{
|
{
|
||||||
if (x.Type == y.Type)
|
if (x.Type == y.Type)
|
||||||
{
|
{
|
||||||
return string.Equals(x.Path, y.Path, StringComparison.OrdinalIgnoreCase);
|
return _fileSystem.AreEqual(x.Path, y.Path);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,9 +152,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
var currentOfficialRating = OfficialRating;
|
var currentOfficialRating = OfficialRating;
|
||||||
|
|
||||||
// Gather all possible ratings
|
// Gather all possible ratings
|
||||||
var ratings = GetRecursiveChildren()
|
var ratings = GetRecursiveChildren(i => i is Movie || i is Series || i is MusicAlbum || i is Game)
|
||||||
.Concat(GetLinkedChildren())
|
|
||||||
.Where(i => i is Movie || i is Series || i is MusicAlbum || i is Game)
|
|
||||||
.Select(i => i.OfficialRating)
|
.Select(i => i.OfficialRating)
|
||||||
.Where(i => !string.IsNullOrEmpty(i))
|
.Where(i => !string.IsNullOrEmpty(i))
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
|
@ -205,7 +203,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
|
|
||||||
if (base.IsVisible(user))
|
if (base.IsVisible(user))
|
||||||
{
|
{
|
||||||
return GetChildren(user, true).Any();
|
return base.GetChildren(user, true).Any();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -57,13 +57,10 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
/// <value>The index number.</value>
|
/// <value>The index number.</value>
|
||||||
public int? IndexNumberEnd { get; set; }
|
public int? IndexNumberEnd { get; set; }
|
||||||
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public string SeriesSortName { get; set; }
|
|
||||||
|
|
||||||
public string FindSeriesSortName()
|
public string FindSeriesSortName()
|
||||||
{
|
{
|
||||||
var series = Series;
|
var series = Series;
|
||||||
return series == null ? SeriesSortName : series.SortName;
|
return series == null ? SeriesName : series.SortName;
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
|
|
@ -51,9 +51,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
get { return SeriesId; }
|
get { return SeriesId; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public string SeriesSortName { get; set; }
|
|
||||||
|
|
||||||
public override double? GetDefaultPrimaryImageAspectRatio()
|
public override double? GetDefaultPrimaryImageAspectRatio()
|
||||||
{
|
{
|
||||||
double value = 2;
|
double value = 2;
|
||||||
|
@ -65,7 +62,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
public string FindSeriesSortName()
|
public string FindSeriesSortName()
|
||||||
{
|
{
|
||||||
var series = Series;
|
var series = Series;
|
||||||
return series == null ? SeriesSortName : series.SortName;
|
return series == null ? SeriesName : series.SortName;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Genre, Rating and Stuido will all be the same
|
// Genre, Rating and Stuido will all be the same
|
||||||
|
@ -125,7 +122,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
return series.Path;
|
return series.Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
return System.IO.Path.GetDirectoryName(Path);
|
return FileSystem.GetDirectoryName(Path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -586,7 +586,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
query.Recursive = true;
|
query.Recursive = true;
|
||||||
query.ParentId = queryParent.Id;
|
query.ParentId = queryParent.Id;
|
||||||
query.Genres = new[] { displayParent.Name };
|
query.GenreIds = new[] { displayParent.Id.ToString("N") };
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
|
|
||||||
query.IncludeItemTypes = new[] { typeof(Movie).Name };
|
query.IncludeItemTypes = new[] { typeof(Movie).Name };
|
||||||
|
@ -729,7 +729,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
query.Recursive = true;
|
query.Recursive = true;
|
||||||
query.ParentId = queryParent.Id;
|
query.ParentId = queryParent.Id;
|
||||||
query.Genres = new[] { displayParent.Name };
|
query.GenreIds = new[] { displayParent.Id.ToString("N") };
|
||||||
query.SetUser(user);
|
query.SetUser(user);
|
||||||
|
|
||||||
query.IncludeItemTypes = new[] { typeof(Series).Name };
|
query.IncludeItemTypes = new[] { typeof(Series).Name };
|
||||||
|
@ -905,6 +905,11 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request.GenreIds.Length > 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (request.HasImdbId.HasValue)
|
if (request.HasImdbId.HasValue)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -1768,26 +1773,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return new List<Folder> { parent };
|
return new List<Folder> { parent };
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<BaseItem> GetRecursiveChildren(Folder parent, User user, IEnumerable<string> viewTypes)
|
|
||||||
{
|
|
||||||
if (parent == null || parent is UserView)
|
|
||||||
{
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return GetMediaFolders(null, viewTypes).SelectMany(i => i.GetRecursiveChildren());
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetMediaFolders(user, viewTypes).SelectMany(i => i.GetRecursiveChildren(user));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return parent.GetRecursiveChildren();
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent.GetRecursiveChildren(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<QueryResult<BaseItem>> GetLiveTvView(Folder queryParent, User user, InternalItemsQuery query)
|
private async Task<QueryResult<BaseItem>> GetLiveTvView(Folder queryParent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
if (query.Recursive)
|
if (query.Recursive)
|
||||||
|
|
|
@ -33,7 +33,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public List<string> AdditionalParts { get; set; }
|
public List<string> AdditionalParts { get; set; }
|
||||||
public List<string> LocalAlternateVersions { get; set; }
|
public List<string> LocalAlternateVersions { get; set; }
|
||||||
public List<LinkedChild> LinkedAlternateVersions { get; set; }
|
public List<LinkedChild> LinkedAlternateVersions { get; set; }
|
||||||
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool SupportsPlayedStatus
|
public override bool SupportsPlayedStatus
|
||||||
|
@ -158,7 +157,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
PlayableStreamFileNames = new List<string>();
|
PlayableStreamFileNames = new List<string>();
|
||||||
AdditionalParts = new List<string>();
|
AdditionalParts = new List<string>();
|
||||||
LocalAlternateVersions = new List<string>();
|
LocalAlternateVersions = new List<string>();
|
||||||
Tags = new List<string>();
|
|
||||||
SubtitleFiles = new List<string>();
|
SubtitleFiles = new List<string>();
|
||||||
LinkedAlternateVersions = new List<LinkedChild>();
|
LinkedAlternateVersions = new List<LinkedChild>();
|
||||||
}
|
}
|
||||||
|
@ -313,7 +311,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
if (IsStacked)
|
if (IsStacked)
|
||||||
{
|
{
|
||||||
return System.IO.Path.GetDirectoryName(Path);
|
return FileSystem.GetDirectoryName(Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsPlaceHolder)
|
if (!IsPlaceHolder)
|
||||||
|
@ -591,41 +589,46 @@ namespace MediaBrowser.Controller.Entities
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaSourceInfo GetVersionInfo(bool enablePathSubstitution, Video i, MediaSourceType type)
|
private static MediaSourceInfo GetVersionInfo(bool enablePathSubstitution, Video media, MediaSourceType type)
|
||||||
{
|
{
|
||||||
var mediaStreams = MediaSourceManager.GetMediaStreams(i.Id)
|
if (media == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("media");
|
||||||
|
}
|
||||||
|
|
||||||
|
var mediaStreams = MediaSourceManager.GetMediaStreams(media.Id)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var locationType = i.LocationType;
|
var locationType = media.LocationType;
|
||||||
|
|
||||||
var info = new MediaSourceInfo
|
var info = new MediaSourceInfo
|
||||||
{
|
{
|
||||||
Id = i.Id.ToString("N"),
|
Id = media.Id.ToString("N"),
|
||||||
IsoType = i.IsoType,
|
IsoType = media.IsoType,
|
||||||
Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File,
|
Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File,
|
||||||
MediaStreams = mediaStreams,
|
MediaStreams = mediaStreams,
|
||||||
Name = GetMediaSourceName(i, mediaStreams),
|
Name = GetMediaSourceName(media, mediaStreams),
|
||||||
Path = enablePathSubstitution ? GetMappedPath(i, i.Path, locationType) : i.Path,
|
Path = enablePathSubstitution ? GetMappedPath(media, media.Path, locationType) : media.Path,
|
||||||
RunTimeTicks = i.RunTimeTicks,
|
RunTimeTicks = media.RunTimeTicks,
|
||||||
Video3DFormat = i.Video3DFormat,
|
Video3DFormat = media.Video3DFormat,
|
||||||
VideoType = i.VideoType,
|
VideoType = media.VideoType,
|
||||||
Container = i.Container,
|
Container = media.Container,
|
||||||
Size = i.Size,
|
Size = media.Size,
|
||||||
Timestamp = i.Timestamp,
|
Timestamp = media.Timestamp,
|
||||||
Type = type,
|
Type = type,
|
||||||
PlayableStreamFileNames = i.PlayableStreamFileNames.ToList(),
|
PlayableStreamFileNames = media.PlayableStreamFileNames.ToList(),
|
||||||
SupportsDirectStream = i.VideoType == VideoType.VideoFile,
|
SupportsDirectStream = media.VideoType == VideoType.VideoFile,
|
||||||
IsRemote = i.IsShortcut
|
IsRemote = media.IsShortcut
|
||||||
};
|
};
|
||||||
|
|
||||||
if (info.Protocol == MediaProtocol.File)
|
if (info.Protocol == MediaProtocol.File)
|
||||||
{
|
{
|
||||||
info.ETag = i.DateModified.Ticks.ToString(CultureInfo.InvariantCulture).GetMD5().ToString("N");
|
info.ETag = media.DateModified.Ticks.ToString(CultureInfo.InvariantCulture).GetMD5().ToString("N");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i.IsShortcut)
|
if (media.IsShortcut)
|
||||||
{
|
{
|
||||||
info.Path = i.ShortcutPath;
|
info.Path = media.ShortcutPath;
|
||||||
|
|
||||||
if (info.Path.StartsWith("Http", StringComparison.OrdinalIgnoreCase))
|
if (info.Path.StartsWith("Http", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
|
@ -647,16 +650,16 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(info.Container))
|
if (string.IsNullOrEmpty(info.Container))
|
||||||
{
|
{
|
||||||
if (i.VideoType == VideoType.VideoFile || i.VideoType == VideoType.Iso)
|
if (media.VideoType == VideoType.VideoFile || media.VideoType == VideoType.Iso)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(i.Path) && locationType != LocationType.Remote && locationType != LocationType.Virtual)
|
if (!string.IsNullOrWhiteSpace(media.Path) && locationType != LocationType.Remote && locationType != LocationType.Virtual)
|
||||||
{
|
{
|
||||||
info.Container = System.IO.Path.GetExtension(i.Path).TrimStart('.');
|
info.Container = System.IO.Path.GetExtension(media.Path).TrimStart('.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info.Bitrate = i.TotalBitrate;
|
info.Bitrate = media.TotalBitrate;
|
||||||
info.InferTotalBitrate();
|
info.InferTotalBitrate();
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
|
|
|
@ -456,6 +456,8 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// <returns>IEnumerable<Folder>.</returns>
|
/// <returns>IEnumerable<Folder>.</returns>
|
||||||
List<Folder> GetCollectionFolders(BaseItem item);
|
List<Folder> GetCollectionFolders(BaseItem item);
|
||||||
|
|
||||||
|
List<Folder> GetCollectionFolders(BaseItem item, List<Folder> allUserRootChildren);
|
||||||
|
|
||||||
LibraryOptions GetLibraryOptions(BaseItem item);
|
LibraryOptions GetLibraryOptions(BaseItem item);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -114,7 +114,7 @@ namespace MediaBrowser.Controller.Library
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var parentDir = System.IO.Path.GetDirectoryName(Path) ?? string.Empty;
|
var parentDir = BaseItem.FileSystem.GetDirectoryName(Path) ?? string.Empty;
|
||||||
|
|
||||||
return parentDir.Length > _appPaths.RootFolderPath.Length
|
return parentDir.Length > _appPaths.RootFolderPath.Length
|
||||||
&& parentDir.StartsWith(_appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase);
|
&& parentDir.StartsWith(_appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase);
|
||||||
|
@ -130,7 +130,7 @@ namespace MediaBrowser.Controller.Library
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return IsDirectory && string.Equals(Path, _appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase);
|
return IsDirectory && BaseItem.FileSystem.AreEqual(Path, _appPaths.RootFolderPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ namespace MediaBrowser.Controller.Library
|
||||||
if (args != null)
|
if (args != null)
|
||||||
{
|
{
|
||||||
if (args.Path == null && Path == null) return true;
|
if (args.Path == null && Path == null) return true;
|
||||||
return args.Path != null && args.Path.Equals(Path, StringComparison.OrdinalIgnoreCase);
|
return args.Path != null && BaseItem.FileSystem.AreEqual(args.Path, Path);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user