commit
21edff3ac2
|
@ -96,7 +96,7 @@ namespace BDInfo
|
|||
}
|
||||
|
||||
DirectoryRoot =
|
||||
_fileSystem.GetDirectoryInfo(Path.GetDirectoryName(DirectoryBDMV.FullName));
|
||||
_fileSystem.GetDirectoryInfo(_fileSystem.GetDirectoryName(DirectoryBDMV.FullName));
|
||||
DirectoryBDJO =
|
||||
GetDirectory("BDJO", DirectoryBDMV, 0);
|
||||
DirectoryCLIPINF =
|
||||
|
@ -349,7 +349,7 @@ namespace BDInfo
|
|||
{
|
||||
return dir;
|
||||
}
|
||||
var parentFolder = Path.GetDirectoryName(dir.FullName);
|
||||
var parentFolder = _fileSystem.GetDirectoryName(dir.FullName);
|
||||
if (string.IsNullOrEmpty(parentFolder))
|
||||
{
|
||||
dir = null;
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace Emby.Common.Implementations.Devices
|
|||
{
|
||||
var path = CachePath;
|
||||
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||
|
||||
lock (_syncLock)
|
||||
{
|
||||
|
|
|
@ -418,7 +418,7 @@ namespace Emby.Common.Implementations.HttpClientManager
|
|||
|
||||
private async Task CacheResponse(HttpResponseInfo response, string responseCachePath)
|
||||
{
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(responseCachePath));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(responseCachePath));
|
||||
|
||||
using (var responseStream = response.Content)
|
||||
{
|
||||
|
|
|
@ -546,24 +546,6 @@ namespace Emby.Common.Implementations.IO
|
|||
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)
|
||||
{
|
||||
if (string.IsNullOrEmpty(parentPath))
|
||||
|
@ -588,7 +570,7 @@ namespace Emby.Common.Implementations.IO
|
|||
throw new ArgumentNullException("path");
|
||||
}
|
||||
|
||||
var parent = Path.GetDirectoryName(path);
|
||||
var parent = GetDirectoryName(path);
|
||||
|
||||
if (!string.IsNullOrEmpty(parent))
|
||||
{
|
||||
|
@ -598,6 +580,16 @@ namespace Emby.Common.Implementations.IO
|
|||
return true;
|
||||
}
|
||||
|
||||
public string GetDirectoryName(string path)
|
||||
{
|
||||
if (_sharpCifsFileSystem.IsEnabledForPath(path))
|
||||
{
|
||||
return _sharpCifsFileSystem.GetDirectoryName(path);
|
||||
}
|
||||
|
||||
return Path.GetDirectoryName(path);
|
||||
}
|
||||
|
||||
public string NormalizePath(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
|
@ -605,6 +597,11 @@ namespace Emby.Common.Implementations.IO
|
|||
throw new ArgumentNullException("path");
|
||||
}
|
||||
|
||||
if (_sharpCifsFileSystem.IsEnabledForPath(path))
|
||||
{
|
||||
return _sharpCifsFileSystem.NormalizePath(path);
|
||||
}
|
||||
|
||||
if (path.EndsWith(":\\", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return path;
|
||||
|
@ -613,6 +610,21 @@ namespace Emby.Common.Implementations.IO
|
|||
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)
|
||||
{
|
||||
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:\\
|
||||
|
||||
if (_sharpCifsFileSystem.IsEnabledForPath(path))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) != -1 &&
|
||||
!path.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
//return Path.IsPathRooted(path);
|
||||
|
|
|
@ -30,6 +30,34 @@ namespace Emby.Common.Implementations.IO
|
|||
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)
|
||||
{
|
||||
if (path.IndexOf('/') != -1)
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace Emby.Common.Implementations.Net
|
|||
#if NET46
|
||||
public Task SendFile(string path, byte[] preBuffer, byte[] postBuffer, CancellationToken cancellationToken)
|
||||
{
|
||||
var options = TransmitFileOptions.UseKernelApc;
|
||||
var options = TransmitFileOptions.UseDefaultWorkerThread;
|
||||
|
||||
var completionSource = new TaskCompletionSource<bool>();
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ namespace Emby.Common.Implementations.ScheduledTasks
|
|||
_lastExecutionResult = value;
|
||||
|
||||
var path = GetHistoryFilePath();
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||
|
||||
lock (_lastExecutionResultSyncLock)
|
||||
{
|
||||
|
@ -575,7 +575,7 @@ namespace Emby.Common.Implementations.ScheduledTasks
|
|||
{
|
||||
var path = GetConfigurationFilePath();
|
||||
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||
|
||||
JsonSerializer.SerializeToFile(triggers, path);
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace Emby.Drawing.ImageMagick
|
|||
try
|
||||
{
|
||||
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)))
|
||||
{
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace Emby.Drawing.ImageMagick
|
|||
|
||||
var namespacePath = typeof(PlayedIndicatorDrawer).Namespace + ".fonts." + name;
|
||||
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))
|
||||
{
|
||||
|
@ -78,7 +78,7 @@ namespace Emby.Drawing.ImageMagick
|
|||
}
|
||||
}
|
||||
|
||||
fileSystem.CreateDirectory(Path.GetDirectoryName(filePath));
|
||||
fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath));
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -108,7 +108,7 @@ namespace Emby.Drawing.ImageMagick
|
|||
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
fileSystem.CreateDirectory(Path.GetDirectoryName(filePath));
|
||||
fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath));
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
@ -81,7 +81,7 @@ namespace Emby.Drawing.Net
|
|||
{
|
||||
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))
|
||||
{
|
||||
|
@ -135,7 +135,7 @@ namespace Emby.Drawing.Net
|
|||
|
||||
var outputFormat = GetOutputFormat(originalImage, selectedOutputFormat);
|
||||
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
|
||||
|
||||
// Save to the cache location
|
||||
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 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));
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
|
||||
|
||||
_imageEncoder.EncodeImage(originalImagePath, tmpPath, AutoOrient(options.Item), newWidth, newHeight, quality, options, outputFormat);
|
||||
CopyFile(tmpPath, cacheFilePath);
|
||||
|
@ -418,9 +418,9 @@ namespace Emby.Drawing
|
|||
|
||||
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));
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
|
||||
|
||||
_imageEncoder.CropWhiteSpace(originalImagePath, tmpPath);
|
||||
CopyFile(tmpPath, croppedImagePath);
|
||||
|
@ -592,7 +592,7 @@ namespace Emby.Drawing
|
|||
try
|
||||
{
|
||||
var path = ImageSizeFile;
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||
_jsonSerializer.SerializeToFile(_cachedImagedSizes, path);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -765,10 +765,10 @@ namespace Emby.Drawing
|
|||
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)));
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
|
||||
|
||||
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 IImageEncoder ImageEncoder { get; private set; }
|
||||
|
||||
private readonly Action<string, string> _certificateGenerator;
|
||||
private readonly Action<string, string, string> _certificateGenerator;
|
||||
private readonly Func<string> _defaultUserNameFactory;
|
||||
|
||||
/// <summary>
|
||||
|
@ -274,7 +274,7 @@ namespace Emby.Server.Core
|
|||
ISystemEvents systemEvents,
|
||||
IMemoryStreamFactory memoryStreamFactory,
|
||||
INetworkManager networkManager,
|
||||
Action<string, string> certificateGenerator,
|
||||
Action<string, string, string> certificateGenerator,
|
||||
Func<string> defaultUsernameFactory)
|
||||
: base(applicationPaths,
|
||||
logManager,
|
||||
|
@ -609,8 +609,8 @@ namespace Emby.Server.Core
|
|||
|
||||
RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
|
||||
|
||||
CertificatePath = GetCertificatePath(true);
|
||||
Certificate = GetCertificate(CertificatePath);
|
||||
CertificateInfo = GetCertificateInfo(true);
|
||||
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.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))
|
||||
{
|
||||
return null;
|
||||
|
@ -759,7 +761,7 @@ namespace Emby.Server.Core
|
|||
return null;
|
||||
}
|
||||
|
||||
X509Certificate2 localCert = new X509Certificate2(certificateLocation);
|
||||
X509Certificate2 localCert = new X509Certificate2(certificateLocation, info.Password);
|
||||
//localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA;
|
||||
if (!localCert.HasPrivateKey)
|
||||
{
|
||||
|
@ -1064,7 +1066,7 @@ namespace Emby.Server.Core
|
|||
SyncManager.AddParts(GetExports<ISyncProvider>());
|
||||
}
|
||||
|
||||
private string CertificatePath { get; set; }
|
||||
private CertificateInfo CertificateInfo { get; set; }
|
||||
private ICertificate Certificate { get; set; }
|
||||
|
||||
private IEnumerable<string> GetUrlPrefixes()
|
||||
|
@ -1080,7 +1082,7 @@ namespace Emby.Server.Core
|
|||
"http://"+i+":" + HttpPort + "/"
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(CertificatePath))
|
||||
if (CertificateInfo != null)
|
||||
{
|
||||
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))
|
||||
{
|
||||
// Custom cert
|
||||
return ServerConfigurationManager.Configuration.CertificatePath;
|
||||
return new CertificateInfo
|
||||
{
|
||||
Path = ServerConfigurationManager.Configuration.CertificatePath
|
||||
};
|
||||
}
|
||||
|
||||
// Generate self-signed cert
|
||||
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 (!FileSystemManager.FileExists(certPath))
|
||||
{
|
||||
FileSystemManager.CreateDirectory(Path.GetDirectoryName(certPath));
|
||||
FileSystemManager.CreateDirectory(FileSystemManager.GetDirectoryName(certPath));
|
||||
|
||||
try
|
||||
{
|
||||
_certificateGenerator(certPath, certHost);
|
||||
_certificateGenerator(certPath, certHost, password);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -1153,7 +1159,11 @@ namespace Emby.Server.Core
|
|||
}
|
||||
}
|
||||
|
||||
return certPath;
|
||||
return new CertificateInfo
|
||||
{
|
||||
Path = certPath,
|
||||
Password = password
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1189,7 +1199,11 @@ namespace Emby.Server.Core
|
|||
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;
|
||||
}
|
||||
|
@ -1779,6 +1793,11 @@ namespace Emby.Server.Core
|
|||
{
|
||||
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 (tempIgnorePaths.Any(i =>
|
||||
{
|
||||
if (string.Equals(i, path, StringComparison.OrdinalIgnoreCase))
|
||||
if (_fileSystem.AreEqual(i, path))
|
||||
{
|
||||
Logger.Debug("Ignoring change to {0}", path);
|
||||
return true;
|
||||
|
@ -466,10 +466,10 @@ namespace Emby.Server.Core.IO
|
|||
}
|
||||
|
||||
// Go up a level
|
||||
var parent = Path.GetDirectoryName(i);
|
||||
var parent = _fileSystem.GetDirectoryName(i);
|
||||
if (!string.IsNullOrEmpty(parent))
|
||||
{
|
||||
if (string.Equals(parent, path, StringComparison.OrdinalIgnoreCase))
|
||||
if (_fileSystem.AreEqual(parent, path))
|
||||
{
|
||||
Logger.Debug("Ignoring change to {0}", path);
|
||||
return true;
|
||||
|
@ -492,7 +492,7 @@ namespace Emby.Server.Core.IO
|
|||
|
||||
private void CreateRefresher(string path)
|
||||
{
|
||||
var parentPath = Path.GetDirectoryName(path);
|
||||
var parentPath = _fileSystem.GetDirectoryName(path);
|
||||
|
||||
lock (_activeRefreshers)
|
||||
{
|
||||
|
@ -500,7 +500,7 @@ namespace Emby.Server.Core.IO
|
|||
foreach (var refresher in refreshers)
|
||||
{
|
||||
// Path is already being refreshed
|
||||
if (string.Equals(path, refresher.Path, StringComparison.Ordinal))
|
||||
if (_fileSystem.AreEqual(path, refresher.Path))
|
||||
{
|
||||
refresher.RestartTimer();
|
||||
return;
|
||||
|
@ -521,7 +521,7 @@ namespace Emby.Server.Core.IO
|
|||
}
|
||||
|
||||
// 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);
|
||||
return;
|
||||
|
|
|
@ -268,24 +268,14 @@ namespace Emby.Server.Implementations.Channels
|
|||
return;
|
||||
}
|
||||
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||
|
||||
_jsonSerializer.SerializeToFile(mediaSources, path);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(BaseItem item, CancellationToken cancellationToken)
|
||||
{
|
||||
IEnumerable<ChannelMediaInfo> results = new List<ChannelMediaInfo>();
|
||||
var video = item as Video;
|
||||
if (video != null)
|
||||
{
|
||||
results = video.ChannelMediaSources;
|
||||
}
|
||||
var audio = item as Audio;
|
||||
if (audio != null)
|
||||
{
|
||||
results = audio.ChannelMediaSources ?? GetSavedMediaSources(audio);
|
||||
}
|
||||
IEnumerable<ChannelMediaInfo> results = GetSavedMediaSources(item);
|
||||
|
||||
return SortMediaInfoResults(results)
|
||||
.Select(i => GetMediaSource(item, i))
|
||||
|
@ -1115,7 +1105,7 @@ namespace Emby.Server.Implementations.Channels
|
|||
{
|
||||
try
|
||||
{
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||
|
||||
_jsonSerializer.SerializeToFile(result, path);
|
||||
}
|
||||
|
@ -1378,7 +1368,6 @@ namespace Emby.Server.Implementations.Channels
|
|||
if (channelVideoItem != null)
|
||||
{
|
||||
channelVideoItem.ExtraType = info.ExtraType;
|
||||
channelVideoItem.ChannelMediaSources = info.MediaSources;
|
||||
|
||||
var mediaSource = info.MediaSources.FirstOrDefault();
|
||||
item.Path = mediaSource == null ? null : mediaSource.Path;
|
||||
|
@ -1427,7 +1416,7 @@ namespace Emby.Server.Implementations.Channels
|
|||
if (!_refreshedItems.ContainsKey(program.Id))
|
||||
{
|
||||
_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
|
||||
{
|
||||
_providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem));
|
||||
_providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.High);
|
||||
}
|
||||
|
||||
EventHelper.FireEventIfNotNull(CollectionCreated, this, new CollectionCreatedEventArgs
|
||||
|
@ -191,7 +191,7 @@ namespace Emby.Server.Implementations.Collections
|
|||
|
||||
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
_providerManager.QueueRefresh(collection.Id, refreshOptions);
|
||||
_providerManager.QueueRefresh(collection.Id, refreshOptions, RefreshPriority.High);
|
||||
|
||||
if (fireEvent)
|
||||
{
|
||||
|
@ -244,7 +244,7 @@ namespace Emby.Server.Implementations.Collections
|
|||
collection.UpdateRatingToContent();
|
||||
|
||||
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
|
||||
{
|
||||
|
|
|
@ -71,10 +71,9 @@ namespace Emby.Server.Implementations.Data
|
|||
double newPercentCommplete = 45 + .55 * p;
|
||||
progress.Report(newPercentCommplete);
|
||||
});
|
||||
await CleanDeletedItems(cancellationToken, innerProgress).ConfigureAwait(false);
|
||||
progress.Report(100);
|
||||
|
||||
await _itemRepo.UpdateInheritedValues(cancellationToken).ConfigureAwait(false);
|
||||
progress.Report(100);
|
||||
}
|
||||
|
||||
private async Task CleanDeadItems(CancellationToken cancellationToken, IProgress<double> progress)
|
||||
|
@ -115,115 +114,6 @@ namespace Emby.Server.Implementations.Data
|
|||
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>
|
||||
/// Creates the triggers that define when the task will run
|
||||
/// </summary>
|
||||
|
|
|
@ -201,7 +201,6 @@ namespace Emby.Server.Implementations.Data
|
|||
AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames);
|
||||
|
||||
AddColumn(db, "TypedBaseItems", "OfficialRatingDescription", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "HomePageUrl", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "VoteCount", "INT", 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", "ForcedSortName", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "LocationType", "Text", existingColumnNames);
|
||||
|
||||
AddColumn(db, "TypedBaseItems", "IsSeries", "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", "TrailerTypes", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "CriticRating", "Float", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "CriticRatingSummary", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "InheritedTags", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "CleanName", "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", "SeasonId", "GUID", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "SeriesId", "GUID", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "SeriesSortName", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "ExternalSeriesId", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "Tagline", "Text", existingColumnNames);
|
||||
AddColumn(db, "TypedBaseItems", "Keywords", "Text", existingColumnNames);
|
||||
|
@ -429,7 +425,6 @@ namespace Emby.Server.Implementations.Data
|
|||
"ParentIndexNumber",
|
||||
"ProductionYear",
|
||||
"OfficialRating",
|
||||
"OfficialRatingDescription",
|
||||
"HomePageUrl",
|
||||
"DisplayMediaType",
|
||||
"ForcedSortName",
|
||||
|
@ -454,13 +449,11 @@ namespace Emby.Server.Implementations.Data
|
|||
"DateLastMediaAdded",
|
||||
"Album",
|
||||
"CriticRating",
|
||||
"CriticRatingSummary",
|
||||
"IsVirtualItem",
|
||||
"SeriesName",
|
||||
"SeasonName",
|
||||
"SeasonId",
|
||||
"SeriesId",
|
||||
"SeriesSortName",
|
||||
"PresentationUniqueKey",
|
||||
"InheritedParentalRatingValue",
|
||||
"InheritedTags",
|
||||
|
@ -552,14 +545,12 @@ namespace Emby.Server.Implementations.Data
|
|||
"InheritedParentalRatingValue",
|
||||
"SortName",
|
||||
"RunTimeTicks",
|
||||
"OfficialRatingDescription",
|
||||
"HomePageUrl",
|
||||
"VoteCount",
|
||||
"DisplayMediaType",
|
||||
"DateCreated",
|
||||
"DateModified",
|
||||
"ForcedSortName",
|
||||
"LocationType",
|
||||
"PreferredMetadataLanguage",
|
||||
"PreferredMetadataCountryCode",
|
||||
"IsHD",
|
||||
|
@ -579,7 +570,6 @@ namespace Emby.Server.Implementations.Data
|
|||
"SourceType",
|
||||
"TrailerTypes",
|
||||
"CriticRating",
|
||||
"CriticRatingSummary",
|
||||
"InheritedTags",
|
||||
"CleanName",
|
||||
"PresentationUniqueKey",
|
||||
|
@ -594,7 +584,6 @@ namespace Emby.Server.Implementations.Data
|
|||
"SeasonName",
|
||||
"SeasonId",
|
||||
"SeriesId",
|
||||
"SeriesSortName",
|
||||
"ExternalSeriesId",
|
||||
"Tagline",
|
||||
"Keywords",
|
||||
|
@ -833,7 +822,6 @@ namespace Emby.Server.Implementations.Data
|
|||
saveItemStatement.TryBind("@SortName", item.SortName);
|
||||
saveItemStatement.TryBind("@RunTimeTicks", item.RunTimeTicks);
|
||||
|
||||
saveItemStatement.TryBind("@OfficialRatingDescription", item.OfficialRatingDescription);
|
||||
saveItemStatement.TryBind("@HomePageUrl", item.HomePageUrl);
|
||||
saveItemStatement.TryBind("@VoteCount", item.VoteCount);
|
||||
saveItemStatement.TryBind("@DisplayMediaType", item.DisplayMediaType);
|
||||
|
@ -841,7 +829,6 @@ namespace Emby.Server.Implementations.Data
|
|||
saveItemStatement.TryBind("@DateModified", item.DateModified);
|
||||
|
||||
saveItemStatement.TryBind("@ForcedSortName", item.ForcedSortName);
|
||||
saveItemStatement.TryBind("@LocationType", item.LocationType.ToString());
|
||||
|
||||
saveItemStatement.TryBind("@PreferredMetadataLanguage", item.PreferredMetadataLanguage);
|
||||
saveItemStatement.TryBind("@PreferredMetadataCountryCode", item.PreferredMetadataCountryCode);
|
||||
|
@ -942,7 +929,6 @@ namespace Emby.Server.Implementations.Data
|
|||
}
|
||||
|
||||
saveItemStatement.TryBind("@CriticRating", item.CriticRating);
|
||||
saveItemStatement.TryBind("@CriticRatingSummary", item.CriticRatingSummary);
|
||||
|
||||
var inheritedTags = item.InheritedTags;
|
||||
if (inheritedTags.Count > 0)
|
||||
|
@ -1024,13 +1010,11 @@ namespace Emby.Server.Implementations.Data
|
|||
if (hasSeries != null)
|
||||
{
|
||||
saveItemStatement.TryBind("@SeriesId", hasSeries.SeriesId);
|
||||
saveItemStatement.TryBind("@SeriesSortName", hasSeries.SeriesSortName);
|
||||
saveItemStatement.TryBind("@SeriesPresentationUniqueKey", hasSeries.SeriesPresentationUniqueKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
saveItemStatement.TryBindNull("@SeriesId");
|
||||
saveItemStatement.TryBindNull("@SeriesSortName");
|
||||
saveItemStatement.TryBindNull("@SeriesPresentationUniqueKey");
|
||||
}
|
||||
|
||||
|
@ -1290,22 +1274,10 @@ namespace Emby.Server.Implementations.Data
|
|||
{
|
||||
return false;
|
||||
}
|
||||
if (type == typeof(Year))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (type == typeof(Book))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (type == typeof(Person))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (type == typeof(RecordingGroup))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (type == typeof(Channel))
|
||||
{
|
||||
return false;
|
||||
|
@ -1339,16 +1311,20 @@ namespace Emby.Server.Implementations.Data
|
|||
return false;
|
||||
}
|
||||
}
|
||||
if (_config.Configuration.SkipDeserializationForPrograms)
|
||||
{
|
||||
if (type == typeof(LiveTvProgram))
|
||||
|
||||
if (type == typeof(Year))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (_config.Configuration.SkipDeserializationForAudio)
|
||||
if (type == typeof(Book))
|
||||
{
|
||||
if (type == typeof(Audio))
|
||||
return false;
|
||||
}
|
||||
if (type == typeof(RecordingGroup))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (type == typeof(LiveTvProgram))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1364,6 +1340,13 @@ namespace Emby.Server.Implementations.Data
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_config.Configuration.SkipDeserializationForAudio)
|
||||
{
|
||||
if (type == typeof(Audio))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (type == typeof(MusicAlbum))
|
||||
{
|
||||
return false;
|
||||
|
@ -1609,15 +1592,6 @@ namespace Emby.Server.Implementations.Data
|
|||
}
|
||||
index++;
|
||||
|
||||
if (query.HasField(ItemFields.OfficialRatingDescription))
|
||||
{
|
||||
if (!reader.IsDBNull(index))
|
||||
{
|
||||
item.OfficialRatingDescription = reader.GetString(index);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
if (query.HasField(ItemFields.HomePageUrl))
|
||||
{
|
||||
if (!reader.IsDBNull(index))
|
||||
|
@ -1803,15 +1777,6 @@ namespace Emby.Server.Implementations.Data
|
|||
}
|
||||
index++;
|
||||
|
||||
if (query.HasField(ItemFields.CriticRatingSummary))
|
||||
{
|
||||
if (!reader.IsDBNull(index))
|
||||
{
|
||||
item.CriticRatingSummary = reader.GetString(index);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
if (!reader.IsDBNull(index))
|
||||
{
|
||||
item.IsVirtualItem = reader.GetBoolean(index);
|
||||
|
@ -1856,15 +1821,6 @@ namespace Emby.Server.Implementations.Data
|
|||
}
|
||||
index++;
|
||||
|
||||
if (hasSeries != null)
|
||||
{
|
||||
if (!reader.IsDBNull(index))
|
||||
{
|
||||
hasSeries.SeriesSortName = reader.GetString(index);
|
||||
}
|
||||
}
|
||||
index++;
|
||||
|
||||
if (!reader.IsDBNull(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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -4100,27 +4060,6 @@ namespace Emby.Server.Implementations.Data
|
|||
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)
|
||||
{
|
||||
whereClauses.Add("IsVirtualItem=@IsVirtualItem");
|
||||
|
|
|
@ -499,7 +499,7 @@ namespace Emby.Server.Implementations.Dto
|
|||
|
||||
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))
|
||||
{
|
||||
dto.SupportsSync = true;
|
||||
|
@ -967,11 +967,6 @@ namespace Emby.Server.Implementations.Dto
|
|||
|
||||
dto.CriticRating = item.CriticRating;
|
||||
|
||||
if (fields.Contains(ItemFields.CriticRatingSummary))
|
||||
{
|
||||
dto.CriticRatingSummary = item.CriticRatingSummary;
|
||||
}
|
||||
|
||||
var hasTrailers = item as IHasTrailers;
|
||||
if (hasTrailers != null)
|
||||
{
|
||||
|
|
|
@ -352,7 +352,7 @@ namespace Emby.Server.Implementations.FileOrganization
|
|||
_libraryMonitor.ReportFileSystemChangeBeginning(path);
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -432,7 +432,7 @@ namespace Emby.Server.Implementations.FileOrganization
|
|||
|
||||
// Now find other files
|
||||
var originalFilenameWithoutExtension = Path.GetFileNameWithoutExtension(path);
|
||||
var directory = Path.GetDirectoryName(path);
|
||||
var directory = _fileSystem.GetDirectoryName(path);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(originalFilenameWithoutExtension) && !string.IsNullOrWhiteSpace(directory))
|
||||
{
|
||||
|
@ -445,7 +445,7 @@ namespace Emby.Server.Implementations.FileOrganization
|
|||
|
||||
foreach (var file in files)
|
||||
{
|
||||
directory = Path.GetDirectoryName(file);
|
||||
directory = _fileSystem.GetDirectoryName(file);
|
||||
var filename = Path.GetFileName(file);
|
||||
|
||||
filename = filename.Replace(originalFilenameWithoutExtension, targetFilenameWithoutExtension,
|
||||
|
@ -470,7 +470,7 @@ namespace Emby.Server.Implementations.FileOrganization
|
|||
return new List<string>();
|
||||
}
|
||||
|
||||
var episodePaths = series.GetRecursiveChildren()
|
||||
var episodePaths = series.GetRecursiveChildren(i => i is Episode)
|
||||
.OfType<Episode>()
|
||||
.Where(i =>
|
||||
{
|
||||
|
@ -499,7 +499,7 @@ namespace Emby.Server.Implementations.FileOrganization
|
|||
.Select(i => i.Path)
|
||||
.ToList();
|
||||
|
||||
var folder = Path.GetDirectoryName(targetPath);
|
||||
var folder = _fileSystem.GetDirectoryName(targetPath);
|
||||
var targetFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(targetPath);
|
||||
|
||||
try
|
||||
|
@ -529,7 +529,7 @@ namespace Emby.Server.Implementations.FileOrganization
|
|||
|
||||
_libraryMonitor.ReportFileSystemChangeBeginning(result.TargetPath);
|
||||
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(result.TargetPath));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(result.TargetPath));
|
||||
|
||||
var targetAlreadyExists = _fileSystem.FileExists(result.TargetPath);
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ namespace Emby.Server.Implementations.HttpServer
|
|||
Headers["Content-Type"] = contentType;
|
||||
|
||||
TotalContentLength = fileSystem.GetFileInfo(path).Length;
|
||||
Headers["Accept-Ranges"] = "bytes";
|
||||
|
||||
if (string.IsNullOrWhiteSpace(rangeHeader))
|
||||
{
|
||||
|
@ -66,7 +67,6 @@ namespace Emby.Server.Implementations.HttpServer
|
|||
}
|
||||
else
|
||||
{
|
||||
Headers["Accept-Ranges"] = "bytes";
|
||||
StatusCode = HttpStatusCode.PartialContent;
|
||||
SetRangeValues();
|
||||
}
|
||||
|
@ -96,8 +96,12 @@ namespace Emby.Server.Implementations.HttpServer
|
|||
RangeLength = 1 + RangeEnd - RangeStart;
|
||||
|
||||
// Content-Length is the length of what we're serving, not the original content
|
||||
Headers["Content-Length"] = RangeLength.ToString(UsCulture);
|
||||
Headers["Content-Range"] = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength);
|
||||
var lengthString = RangeLength.ToString(UsCulture);
|
||||
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>
|
||||
|
|
|
@ -501,7 +501,7 @@ namespace Emby.Server.Implementations.HttpServer
|
|||
private bool ShouldCompressResponse(IRequest requestContext, string contentType)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
@ -566,7 +566,7 @@ namespace Emby.Server.Implementations.HttpServer
|
|||
};
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(rangeHeader))
|
||||
if (!string.IsNullOrWhiteSpace(rangeHeader))
|
||||
{
|
||||
var stream = await factoryFn().ConfigureAwait(false);
|
||||
|
||||
|
@ -621,6 +621,7 @@ namespace Emby.Server.Implementations.HttpServer
|
|||
responseHeaders["Content-Encoding"] = requestedCompressionType;
|
||||
}
|
||||
|
||||
responseHeaders["Vary"] = "Accept-Encoding";
|
||||
responseHeaders["Content-Length"] = content.Length.ToString(UsCulture);
|
||||
|
||||
if (isHeadRequest)
|
||||
|
|
|
@ -189,10 +189,15 @@ namespace Emby.Server.Implementations.HttpServer
|
|||
private async Task CopyToInternalAsync(Stream source, Stream destination, long copyLength)
|
||||
{
|
||||
var array = new byte[BufferSize];
|
||||
int count;
|
||||
while ((count = await source.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0)
|
||||
int bytesRead;
|
||||
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);
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ namespace Emby.Server.Implementations.HttpServer
|
|||
public void FilterResponse(IRequest req, IResponse res, object dto)
|
||||
{
|
||||
// Try to prevent compatibility view
|
||||
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("X-UA-Compatible", "IE=Edge");
|
||||
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-Origin", "*");
|
||||
|
||||
|
@ -46,8 +46,6 @@ namespace Emby.Server.Implementations.HttpServer
|
|||
}
|
||||
}
|
||||
|
||||
var vary = "Accept-Encoding";
|
||||
|
||||
var hasHeaders = dto as IHasHeaders;
|
||||
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;
|
||||
|
||||
// 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>
|
||||
|
|
|
@ -207,7 +207,7 @@ namespace Emby.Server.Implementations.IO
|
|||
{
|
||||
item = LibraryManager.FindByPath(path, null);
|
||||
|
||||
path = System.IO.Path.GetDirectoryName(path);
|
||||
path = _fileSystem.GetDirectoryName(path);
|
||||
}
|
||||
|
||||
if (item != null)
|
||||
|
|
|
@ -139,7 +139,7 @@ namespace Emby.Server.Implementations.Images
|
|||
CancellationToken cancellationToken)
|
||||
{
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
|
||||
FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPath));
|
||||
|
||||
var options = new ImageCollageOptions
|
||||
{
|
||||
|
|
|
@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.Library
|
|||
{
|
||||
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))
|
||||
{
|
||||
|
|
|
@ -1962,8 +1962,34 @@ namespace Emby.Server.Implementations.Library
|
|||
return new List<Folder>();
|
||||
}
|
||||
|
||||
return GetUserRootFolder().Children
|
||||
.OfType<Folder>()
|
||||
return GetCollectionFoldersInternal(item, GetUserRootFolder().Children.OfType<Folder>().ToList());
|
||||
}
|
||||
|
||||
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))
|
||||
.ToList();
|
||||
}
|
||||
|
@ -2126,7 +2152,8 @@ namespace Emby.Server.Implementations.Library
|
|||
// Not sure why this is necessary but need to figure it out
|
||||
// View images are not getting utilized without this
|
||||
ForceSave = true
|
||||
});
|
||||
|
||||
}, RefreshPriority.Normal);
|
||||
}
|
||||
|
||||
return item;
|
||||
|
@ -2188,7 +2215,8 @@ namespace Emby.Server.Implementations.Library
|
|||
{
|
||||
// Need to force save to increment DateLastSaved
|
||||
ForceSave = true
|
||||
});
|
||||
|
||||
}, RefreshPriority.Normal);
|
||||
}
|
||||
|
||||
return item;
|
||||
|
@ -2252,7 +2280,8 @@ namespace Emby.Server.Implementations.Library
|
|||
{
|
||||
// Need to force save to increment DateLastSaved
|
||||
ForceSave = true
|
||||
});
|
||||
|
||||
}, RefreshPriority.Normal);
|
||||
}
|
||||
|
||||
return item;
|
||||
|
@ -2328,7 +2357,7 @@ namespace Emby.Server.Implementations.Library
|
|||
{
|
||||
// Need to force save to increment DateLastSaved
|
||||
ForceSave = true
|
||||
});
|
||||
}, RefreshPriority.Normal);
|
||||
}
|
||||
|
||||
return item;
|
||||
|
|
|
@ -5,6 +5,7 @@ using MediaBrowser.Controller.Playlists;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Model.Querying;
|
||||
|
||||
namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
|
@ -27,35 +28,14 @@ namespace Emby.Server.Implementations.Library
|
|||
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
|
||||
.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);
|
||||
return GetInstantMixFromGenres(item.Genres, user);
|
||||
}
|
||||
|
||||
public IEnumerable<Audio> GetInstantMixFromAlbum(MusicAlbum item, User user)
|
||||
{
|
||||
var genres = item
|
||||
.GetRecursiveChildren(user, new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(Audio).Name }
|
||||
})
|
||||
.Cast<Audio>()
|
||||
.SelectMany(i => i.Genres)
|
||||
.Concat(item.Genres)
|
||||
.DistinctNames();
|
||||
|
||||
return GetInstantMixFromGenres(genres, user);
|
||||
return GetInstantMixFromGenres(item.Genres, 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)
|
||||
{
|
||||
var genres = item
|
||||
.GetRecursiveChildren(user, new InternalItemsQuery(user)
|
||||
{
|
||||
IncludeItemTypes = new[] { typeof(Audio).Name }
|
||||
})
|
||||
.Cast<Audio>()
|
||||
.SelectMany(i => i.Genres)
|
||||
.Concat(item.Genres)
|
||||
.DistinctNames();
|
||||
|
||||
return GetInstantMixFromGenres(genres, user);
|
||||
return GetInstantMixFromGenres(item.Genres, 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 },
|
||||
|
||||
Genres = genreList.ToArray()
|
||||
GenreIds = genreIds.ToArray(),
|
||||
|
||||
});
|
||||
Limit = 200,
|
||||
|
||||
var genresDictionary = genreList.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
|
||||
SortBy = new[] { ItemSortBy.Random }
|
||||
|
||||
return inputItems
|
||||
.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());
|
||||
}).Cast<Audio>();
|
||||
}
|
||||
|
||||
public IEnumerable<Audio> GetInstantMixFromItem(BaseItem item, User user)
|
||||
|
@ -117,7 +96,7 @@ namespace Emby.Server.Implementations.Library
|
|||
var genre = item as MusicGenre;
|
||||
if (genre != null)
|
||||
{
|
||||
return GetInstantMixFromGenres(new[] { item.Name }, user);
|
||||
return GetInstantMixFromGenreIds(new[] { item.Id.ToString("N") }, user);
|
||||
}
|
||||
|
||||
var playlist = item as Playlist;
|
||||
|
|
|
@ -6,6 +6,7 @@ using System;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.IO;
|
||||
|
||||
namespace Emby.Server.Implementations.Library.Resolvers
|
||||
{
|
||||
|
@ -13,11 +14,13 @@ namespace Emby.Server.Implementations.Library.Resolvers
|
|||
{
|
||||
private readonly IImageProcessor _imageProcessor;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
public PhotoResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager)
|
||||
public PhotoResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager, IFileSystem fileSystem)
|
||||
{
|
||||
_imageProcessor = imageProcessor;
|
||||
_libraryManager = libraryManager;
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -41,7 +44,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
|
|||
var filename = Path.GetFileNameWithoutExtension(args.Path);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
|
|
@ -57,7 +57,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
|||
{
|
||||
episode.SeriesId = series.Id;
|
||||
episode.SeriesName = series.Name;
|
||||
episode.SeriesSortName = series.SortName;
|
||||
}
|
||||
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,
|
||||
SeriesId = series.Id,
|
||||
SeriesSortName = series.SortName,
|
||||
SeriesName = series.Name
|
||||
};
|
||||
|
||||
|
|
|
@ -165,7 +165,16 @@ namespace Emby.Server.Implementations.Library
|
|||
ExcludeItemTypes = excludeItemTypes.ToArray(),
|
||||
IncludeItemTypes = includeItemTypes.ToArray(),
|
||||
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
|
||||
|
|
|
@ -942,7 +942,8 @@ namespace Emby.Server.Implementations.Library
|
|||
{
|
||||
return new UserPolicy
|
||||
{
|
||||
EnableSync = true
|
||||
EnableContentDownloading = true,
|
||||
EnableSyncTranscoding = true
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -964,7 +965,7 @@ namespace Emby.Server.Implementations.Library
|
|||
|
||||
var path = GetPolifyFilePath(user);
|
||||
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||
|
||||
lock (_policySyncLock)
|
||||
{
|
||||
|
@ -1051,7 +1052,7 @@ namespace Emby.Server.Implementations.Library
|
|||
config = _jsonSerializer.DeserializeFromString<UserConfiguration>(json);
|
||||
}
|
||||
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||
|
||||
lock (_configSyncLock)
|
||||
{
|
||||
|
|
|
@ -422,7 +422,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
{
|
||||
if (!string.IsNullOrWhiteSpace(epgChannel.Name))
|
||||
{
|
||||
tunerChannel.Name = epgChannel.Name;
|
||||
//tunerChannel.Name = epgChannel.Name;
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(epgChannel.ImageUrl))
|
||||
{
|
||||
|
@ -1231,7 +1231,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
RequiresOpening = false,
|
||||
RequiresClosing = false,
|
||||
Protocol = MediaBrowser.Model.MediaInfo.MediaProtocol.Http,
|
||||
BufferMs = 0
|
||||
BufferMs = 0,
|
||||
IgnoreDts = true
|
||||
};
|
||||
|
||||
var isAudio = false;
|
||||
|
@ -1496,7 +1497,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
|
||||
_libraryManager.RegisterIgnoredPath(recordPath);
|
||||
_libraryMonitor.ReportFileSystemChangeBeginning(recordPath);
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(recordPath));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(recordPath));
|
||||
activeRecordingInfo.Path = recordPath;
|
||||
|
||||
var duration = recordingEndDate - DateTime.UtcNow;
|
||||
|
@ -1516,8 +1517,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
EnforceKeepUpTo(timer, seriesPath);
|
||||
};
|
||||
|
||||
await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
recordingStatus = RecordingStatus.Completed;
|
||||
_logger.Info("Recording completed: {0}", recordPath);
|
||||
|
@ -1725,7 +1725,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
|
||||
while (FileExists(path, timerId))
|
||||
{
|
||||
var parent = Path.GetDirectoryName(originalPath);
|
||||
var parent = _fileSystem.GetDirectoryName(originalPath);
|
||||
var name = Path.GetFileNameWithoutExtension(originalPath);
|
||||
name += "-" + index.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
|
@ -1765,7 +1765,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
var imageSavePath = Path.Combine(Path.GetDirectoryName(recordingPath), imageSaveFilenameWithoutExtension);
|
||||
var imageSavePath = Path.Combine(_fileSystem.GetDirectoryName(recordingPath), imageSaveFilenameWithoutExtension);
|
||||
|
||||
// preserve original image extension
|
||||
imageSavePath = Path.ChangeExtension(imageSavePath, Path.GetExtension(image.Path));
|
||||
|
@ -2155,11 +2155,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
writer.WriteElementString("mpaa", item.OfficialRating);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(item.OfficialRatingDescription))
|
||||
{
|
||||
writer.WriteElementString("mpaadescription", item.OfficialRatingDescription);
|
||||
}
|
||||
|
||||
var overview = (item.Overview ?? string.Empty)
|
||||
.StripHtml()
|
||||
.Replace(""", "'");
|
||||
|
@ -2251,11 +2246,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
writer.WriteElementString("criticrating", item.CriticRating.Value.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(item.CriticRatingSummary))
|
||||
{
|
||||
writer.WriteElementString("criticratingsummary", item.CriticRatingSummary);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(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)
|
||||
{
|
||||
var path = GetChannelEpgCachePath(channelId);
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||
lock (_epgLock)
|
||||
{
|
||||
_jsonSerializer.SerializeToFile(epgData, path);
|
||||
|
|
|
@ -11,14 +11,16 @@ using MediaBrowser.Model.IO;
|
|||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.MediaEncoding;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Diagnostics;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
|
||||
namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
{
|
||||
|
@ -37,8 +39,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
private readonly IProcessFactory _processFactory;
|
||||
private readonly IJsonSerializer _json;
|
||||
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;
|
||||
_fileSystem = fileSystem;
|
||||
|
@ -48,6 +51,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
_liveTvOptions = liveTvOptions;
|
||||
_httpClient = httpClient;
|
||||
_processFactory = processFactory;
|
||||
_config = config;
|
||||
}
|
||||
|
||||
private string OutputFormat
|
||||
|
@ -76,23 +80,35 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
|
||||
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)
|
||||
{
|
||||
var durationToken = new CancellationTokenSource(duration);
|
||||
cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
|
||||
//var durationToken = new CancellationTokenSource(duration);
|
||||
//cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
|
||||
|
||||
await RecordFromFile(mediaSource, mediaSource.Path, targetFile, duration, onStarted, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
_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)
|
||||
{
|
||||
_targetPath = targetFile;
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(targetFile));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(targetFile));
|
||||
|
||||
var process = _processFactory.Create(new ProcessOptions
|
||||
{
|
||||
|
@ -118,7 +134,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
_logger.Info(commandLineLogMessage);
|
||||
|
||||
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.
|
||||
_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 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;
|
||||
//if (mediaSource.DateLiveStreamOpened.HasValue)
|
||||
//{
|
||||
// var elapsed = DateTime.UtcNow - mediaSource.DateLiveStreamOpened.Value;
|
||||
// elapsed -= TimeSpan.FromSeconds(10);
|
||||
// if (elapsed.TotalSeconds >= 0)
|
||||
// {
|
||||
// startTimeTicks = elapsed.Ticks + startTimeTicks;
|
||||
// }
|
||||
//}
|
||||
var flags = new List<string>();
|
||||
if (mediaSource.IgnoreDts)
|
||||
{
|
||||
flags.Add("+igndts");
|
||||
}
|
||||
if (mediaSource.IgnoreIndex)
|
||||
{
|
||||
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)
|
||||
{
|
||||
inputModifiers += " -re";
|
||||
}
|
||||
|
||||
if (startTimeTicks > 0)
|
||||
{
|
||||
inputModifiers = "-ss " + _mediaEncoder.GetTimeParameter(startTimeTicks) + " " + inputModifiers;
|
||||
}
|
||||
|
||||
var analyzeDurationSeconds = 5;
|
||||
var analyzeDuration = " -analyzeduration " +
|
||||
(analyzeDurationSeconds * 1000000).ToString(CultureInfo.InvariantCulture);
|
||||
|
@ -193,11 +213,20 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
|
||||
var subtitleArgs = CopySubtitles ? " -codec:s copy" : " -sn";
|
||||
|
||||
var outputParam = string.Equals(Path.GetExtension(targetFile), ".mp4", StringComparison.OrdinalIgnoreCase) ?
|
||||
" -f mp4 -movflags frag_keyframe+empty_moov" :
|
||||
string.Empty;
|
||||
//var outputParam = string.Equals(Path.GetExtension(targetFile), ".mp4", StringComparison.OrdinalIgnoreCase) ?
|
||||
// " -f mp4 -movflags frag_keyframe+empty_moov" :
|
||||
// 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;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
}
|
||||
|
||||
var file = _dataPath + ".json";
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(file));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(file));
|
||||
|
||||
lock (_fileDataLock)
|
||||
{
|
||||
|
|
|
@ -86,7 +86,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFile));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFile));
|
||||
|
||||
using (var stream = _fileSystem.OpenRead(tempFile))
|
||||
{
|
||||
|
|
|
@ -857,7 +857,8 @@ namespace Emby.Server.Implementations.LiveTv
|
|||
_providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem)
|
||||
{
|
||||
MetadataRefreshMode = metadataRefreshMode
|
||||
});
|
||||
|
||||
}, RefreshPriority.Normal);
|
||||
}
|
||||
|
||||
return item.Id;
|
||||
|
@ -1395,11 +1396,11 @@ namespace Emby.Server.Implementations.LiveTv
|
|||
|
||||
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)
|
||||
{
|
||||
_providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem));
|
||||
_providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.Low);
|
||||
}
|
||||
|
||||
currentChannel.IsMovie = isMovie;
|
||||
|
|
|
@ -420,7 +420,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||
SupportsDirectPlay = false,
|
||||
SupportsDirectStream = true,
|
||||
SupportsTranscoding = true,
|
||||
IsInfiniteStream = true
|
||||
IsInfiniteStream = true,
|
||||
IgnoreDts = true
|
||||
};
|
||||
|
||||
mediaSource.InferTotalBitrate();
|
||||
|
|
|
@ -29,6 +29,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||
|
||||
byte[] buffer = new byte[BufferSize];
|
||||
|
||||
if (source == null)
|
||||
{
|
||||
throw new ArgumentNullException("source");
|
||||
}
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false);
|
||||
|
|
|
@ -29,15 +29,17 @@ namespace Emby.Server.Implementations.Logging
|
|||
_logManager.Flush();
|
||||
|
||||
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);
|
||||
|
||||
// Write to console just in case file logging fails
|
||||
_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);
|
||||
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||
|
||||
var container = video.Container;
|
||||
|
||||
|
|
|
@ -201,7 +201,8 @@ namespace Emby.Server.Implementations.Playlists
|
|||
_providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem)
|
||||
{
|
||||
ForceSave = true
|
||||
});
|
||||
|
||||
}, RefreshPriority.High);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
ForceSave = true
|
||||
});
|
||||
|
||||
}, RefreshPriority.High);
|
||||
}
|
||||
|
||||
public async Task MoveItem(string playlistId, string entryId, int newIndex)
|
||||
|
|
|
@ -136,7 +136,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
{
|
||||
previouslyFailedImages.Add(key);
|
||||
|
||||
var parentPath = Path.GetDirectoryName(failHistoryPath);
|
||||
var parentPath = _fileSystem.GetDirectoryName(failHistoryPath);
|
||||
|
||||
_fileSystem.CreateDirectory(parentPath);
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ namespace Emby.Server.Implementations.Security
|
|||
}
|
||||
|
||||
var licenseFile = Filename;
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(licenseFile));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(licenseFile));
|
||||
lock (_fileLock)
|
||||
{
|
||||
_fileSystem.WriteAllLines(licenseFile, lines);
|
||||
|
|
|
@ -129,7 +129,7 @@ namespace Emby.Server.Implementations.Session
|
|||
|
||||
public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
return SendMessage("LibraryChanged", info, cancellationToken);
|
||||
}
|
||||
|
||||
public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken)
|
||||
|
|
|
@ -715,7 +715,8 @@ namespace Emby.Server.Implementations.Session
|
|||
ClientName = session.Client,
|
||||
DeviceId = session.DeviceId,
|
||||
IsPaused = info.IsPaused,
|
||||
PlaySessionId = info.PlaySessionId
|
||||
PlaySessionId = info.PlaySessionId,
|
||||
IsAutomated = isAutomated
|
||||
|
||||
}, _logger);
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Emby.Server.Implementations.Sorting
|
|||
{
|
||||
var hasSeries = item as IHasSeries;
|
||||
|
||||
return hasSeries != null ? hasSeries.SeriesSortName : null;
|
||||
return hasSeries != null ? hasSeries.FindSeriesSortName() : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -250,7 +250,7 @@ namespace Emby.Server.Implementations.Updates
|
|||
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(PackageCachePath));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(PackageCachePath));
|
||||
|
||||
_fileSystem.CopyFile(tempFile, PackageCachePath, true);
|
||||
_lastPackageUpdateTime = DateTime.UtcNow;
|
||||
|
@ -627,7 +627,7 @@ namespace Emby.Server.Implementations.Updates
|
|||
// Success - move it to the real target
|
||||
try
|
||||
{
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(target));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(target));
|
||||
_fileSystem.CopyFile(tempFile, target, true);
|
||||
//If it is an archive - write out a version file so we know what it is
|
||||
if (isArchive)
|
||||
|
|
|
@ -633,7 +633,7 @@ namespace MediaBrowser.Api
|
|||
/// <param name="outputFilePath">The output file path.</param>
|
||||
private void DeleteHlsPartialStreamFiles(string outputFilePath)
|
||||
{
|
||||
var directory = Path.GetDirectoryName(outputFilePath);
|
||||
var directory = _fileSystem.GetDirectoryName(outputFilePath);
|
||||
var name = Path.GetFileNameWithoutExtension(outputFilePath);
|
||||
|
||||
var filesToDelete = _fileSystem.GetFilePaths(directory)
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace MediaBrowser.Api
|
|||
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);
|
||||
|
||||
|
@ -80,7 +80,7 @@ namespace MediaBrowser.Api
|
|||
throw new SecurityException("Unauthorized access.");
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (restrictUserPreferences)
|
||||
{
|
||||
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)]
|
||||
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; }
|
||||
|
||||
/// <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)]
|
||||
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; }
|
||||
|
||||
[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)
|
||||
{
|
||||
var parent = Path.GetDirectoryName(request.Path);
|
||||
var parent = _fileSystem.GetDirectoryName(request.Path);
|
||||
|
||||
if (string.IsNullOrEmpty(parent))
|
||||
{
|
||||
|
|
|
@ -160,7 +160,7 @@ namespace MediaBrowser.Api.Images
|
|||
|
||||
private string GetThemeName(string path, string rootImagePath)
|
||||
{
|
||||
var parentName = Path.GetDirectoryName(path);
|
||||
var parentName = _fileSystem.GetDirectoryName(path);
|
||||
|
||||
if (string.Equals(parentName, rootImagePath, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
|
|
|
@ -427,7 +427,7 @@ namespace MediaBrowser.Api.Images
|
|||
public void Post(PostUserImage request)
|
||||
{
|
||||
var userId = GetPathValue(1);
|
||||
AssertCanUpdateUser(_authContext, _userManager, userId);
|
||||
AssertCanUpdateUser(_authContext, _userManager, userId, true);
|
||||
|
||||
request.Type = (ImageType)Enum.Parse(typeof(ImageType), GetPathValue(3), true);
|
||||
|
||||
|
@ -462,7 +462,7 @@ namespace MediaBrowser.Api.Images
|
|||
public void Delete(DeleteUserImage request)
|
||||
{
|
||||
var userId = request.Id;
|
||||
AssertCanUpdateUser(_authContext, _userManager, userId);
|
||||
AssertCanUpdateUser(_authContext, _userManager, userId, true);
|
||||
|
||||
var item = _userManager.GetUserById(userId);
|
||||
|
||||
|
|
|
@ -278,7 +278,7 @@ namespace MediaBrowser.Api.Images
|
|||
|
||||
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
|
||||
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(fullCachePath));
|
||||
using (var stream = result.Content)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -299,7 +299,7 @@ namespace MediaBrowser.Api
|
|||
|
||||
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
|
||||
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(fullCachePath));
|
||||
using (var stream = result.Content)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,14 +62,7 @@ namespace MediaBrowser.Api
|
|||
|
||||
var options = GetRefreshOptions(request);
|
||||
|
||||
if (item is Folder)
|
||||
{
|
||||
_providerManager.QueueRefresh(item.Id, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
_providerManager.RefreshFullItem(item, options, CancellationToken.None);
|
||||
}
|
||||
_providerManager.QueueRefresh(item.Id, options, RefreshPriority.High);
|
||||
}
|
||||
|
||||
private MetadataRefreshOptions GetRefreshOptions(BaseRefreshRequest request)
|
||||
|
|
|
@ -240,7 +240,6 @@ namespace MediaBrowser.Api
|
|||
item.OriginalTitle = string.IsNullOrWhiteSpace(request.OriginalTitle) ? null : request.OriginalTitle;
|
||||
|
||||
item.CriticRating = request.CriticRating;
|
||||
item.CriticRatingSummary = request.CriticRatingSummary;
|
||||
|
||||
item.DisplayMediaType = request.DisplayMediaType;
|
||||
item.CommunityRating = request.CommunityRating;
|
||||
|
|
|
@ -98,7 +98,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||
/// Fields to return within the items, in addition to basic information
|
||||
/// </summary>
|
||||
/// <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; }
|
||||
|
||||
[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
|
||||
/// </summary>
|
||||
/// <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 bool EnableTotalRecordCount { get; set; }
|
||||
|
@ -251,7 +251,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||
/// Fields to return within the items, in addition to basic information
|
||||
/// </summary>
|
||||
/// <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 bool EnableTotalRecordCount { get; set; }
|
||||
|
@ -399,7 +399,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||
/// Fields to return within the items, in addition to basic information
|
||||
/// </summary>
|
||||
/// <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 GetPrograms()
|
||||
|
@ -459,7 +459,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||
/// Fields to return within the items, in addition to basic information
|
||||
/// </summary>
|
||||
/// <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; }
|
||||
|
||||
[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,
|
||||
string workingDirectory = null)
|
||||
{
|
||||
FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
|
||||
FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPath));
|
||||
|
||||
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");
|
||||
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.
|
||||
state.LogFileStream = FileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true);
|
||||
|
@ -315,8 +315,6 @@ namespace MediaBrowser.Api.Playback
|
|||
StartThrottler(state, transcodingJob);
|
||||
}
|
||||
|
||||
ReportUsage(state);
|
||||
|
||||
return transcodingJob;
|
||||
}
|
||||
|
||||
|
@ -677,7 +675,8 @@ namespace MediaBrowser.Api.Playback
|
|||
{
|
||||
Request = request,
|
||||
RequestedUrl = url,
|
||||
UserAgent = Request.UserAgent
|
||||
UserAgent = Request.UserAgent,
|
||||
EnableDlnaHeaders = !string.IsNullOrWhiteSpace(request.Params)
|
||||
};
|
||||
|
||||
var auth = AuthorizationContext.GetAuthorizationInfo(Request);
|
||||
|
@ -720,6 +719,13 @@ namespace MediaBrowser.Api.Playback
|
|||
|
||||
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;
|
||||
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>
|
||||
/// Adds the dlna headers.
|
||||
/// </summary>
|
||||
|
@ -1029,6 +918,11 @@ namespace MediaBrowser.Api.Playback
|
|||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
|
||||
protected void AddDlnaHeaders(StreamState state, IDictionary<string, string> responseHeaders, bool isStaticallyStreamed)
|
||||
{
|
||||
if (!state.EnableDlnaHeaders)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var profile = state.DeviceProfile;
|
||||
|
||||
var transferMode = GetHeader("transferMode.dlna.org");
|
||||
|
|
|
@ -13,10 +13,7 @@ using System.IO;
|
|||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Model.IO;
|
||||
|
||||
namespace MediaBrowser.Api.Playback.Hls
|
||||
{
|
||||
|
@ -271,7 +268,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
var useGenericSegmenter = true;
|
||||
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;
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
public string SegmentId { get; set; }
|
||||
}
|
||||
|
||||
[Authenticated]
|
||||
public class DynamicHlsService : BaseHlsService
|
||||
{
|
||||
|
||||
|
@ -378,7 +379,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
|
||||
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;
|
||||
|
||||
|
@ -415,7 +416,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
|
||||
private string GetSegmentPath(StreamState state, string playlist, int index)
|
||||
{
|
||||
var folder = Path.GetDirectoryName(playlist);
|
||||
var folder = FileSystem.GetDirectoryName(playlist);
|
||||
|
||||
var filename = Path.GetFileNameWithoutExtension(playlist);
|
||||
|
||||
|
@ -807,7 +808,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
|
||||
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;
|
||||
|
@ -925,7 +926,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
|
||||
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;
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
/// <summary>
|
||||
/// Class GetHlsAudioSegment
|
||||
/// </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.aac", "GET")]
|
||||
public class GetHlsAudioSegmentLegacy
|
||||
|
@ -38,6 +40,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
/// Class GetHlsVideoSegment
|
||||
/// </summary>
|
||||
[Route("/Videos/{Id}/hls/{PlaylistId}/stream.m3u8", "GET")]
|
||||
[Authenticated]
|
||||
public class GetHlsPlaylistLegacy
|
||||
{
|
||||
// TODO: Deprecate with new iOS app
|
||||
|
@ -52,6 +55,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
}
|
||||
|
||||
[Route("/Videos/ActiveEncodings", "DELETE")]
|
||||
[Authenticated]
|
||||
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")]
|
||||
|
@ -64,6 +68,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
/// <summary>
|
||||
/// Class GetHlsVideoSegment
|
||||
/// </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")]
|
||||
public class GetHlsVideoSegmentLegacy : VideoStreamRequest
|
||||
{
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
/// <summary>
|
||||
/// Class VideoHlsService
|
||||
/// </summary>
|
||||
[Authenticated]
|
||||
public class VideoHlsService : BaseHlsService
|
||||
{
|
||||
public object Get(GetLiveHlsStream request)
|
||||
|
|
|
@ -59,42 +59,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||
{
|
||||
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
|
||||
|
||||
var audioTranscodeParams = new List<string>();
|
||||
|
||||
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();
|
||||
return EncodingHelper.GetProgressiveAudioFullCommandLine(state, encodingOptions, outputPath);
|
||||
}
|
||||
|
||||
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>
|
||||
/// Class VideoService
|
||||
/// </summary>
|
||||
// TODO: In order to autheneticate this in the future, Dlna playback will require updating
|
||||
//[Authenticated]
|
||||
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)
|
||||
|
|
|
@ -138,6 +138,8 @@ namespace MediaBrowser.Api.Playback
|
|||
return MimeTypes.GetMimeType(outputPath);
|
||||
}
|
||||
|
||||
public bool EnableDlnaHeaders { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeTranscodingThrottler();
|
||||
|
|
|
@ -102,7 +102,7 @@ namespace MediaBrowser.Api
|
|||
/// Fields to return within the items, in addition to basic information
|
||||
/// </summary>
|
||||
/// <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; }
|
||||
|
||||
[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
|
||||
if (!string.IsNullOrWhiteSpace(request.MinOfficialRating))
|
||||
{
|
||||
|
|
|
@ -9,6 +9,7 @@ using MediaBrowser.Model.Entities;
|
|||
using MediaBrowser.Model.Search;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Model.Services;
|
||||
|
||||
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)]
|
||||
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()
|
||||
{
|
||||
IncludeArtists = true;
|
||||
|
@ -135,7 +153,14 @@ namespace MediaBrowser.Api
|
|||
IncludeStudios = request.IncludeStudios,
|
||||
StartIndex = request.StartIndex,
|
||||
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);
|
||||
|
||||
|
@ -167,11 +192,11 @@ namespace MediaBrowser.Api
|
|||
MatchedTerm = hintInfo.MatchedTerm,
|
||||
DisplayMediaType = item.DisplayMediaType,
|
||||
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);
|
||||
|
||||
if (primaryImageTag != null)
|
||||
|
@ -183,12 +208,27 @@ namespace MediaBrowser.Api
|
|||
SetThumbImageInfo(result, item);
|
||||
SetBackdropImageInfo(result, item);
|
||||
|
||||
var program = item as LiveTvProgram;
|
||||
if (program != null)
|
||||
{
|
||||
result.StartDate = program.StartDate;
|
||||
}
|
||||
|
||||
var hasSeries = item as IHasSeries;
|
||||
if (hasSeries != null)
|
||||
{
|
||||
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;
|
||||
|
||||
if (album != null)
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace MediaBrowser.Api.Session
|
|||
|
||||
void _sessionManager_PlaybackProgress(object sender, PlaybackProgressEventArgs e)
|
||||
{
|
||||
SendData(false);
|
||||
SendData(!e.IsAutomated);
|
||||
}
|
||||
|
||||
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
|
||||
/// </summary>
|
||||
/// <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; }
|
||||
}
|
||||
|
||||
|
|
|
@ -95,12 +95,12 @@ namespace MediaBrowser.Api
|
|||
config.EnableStandaloneMusicKeys = true;
|
||||
config.EnableCaseSensitiveItemIds = true;
|
||||
config.SkipDeserializationForBasicTypes = true;
|
||||
config.SkipDeserializationForPrograms = true;
|
||||
config.SkipDeserializationForAudio = true;
|
||||
config.EnableSeriesPresentationUniqueKey = true;
|
||||
config.EnableLocalizedGuids = true;
|
||||
config.EnableSimpleArtistDetection = true;
|
||||
config.EnableNormalizedItemByNameIds = true;
|
||||
config.DisableLiveTvChannelUserDataName = true;
|
||||
}
|
||||
|
||||
public void Post(UpdateStartupConfiguration request)
|
||||
|
|
|
@ -288,7 +288,7 @@ namespace MediaBrowser.Api.Subtitles
|
|||
await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
_providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(_fileSystem));
|
||||
_providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.High);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace MediaBrowser.Api
|
|||
/// Fields to return within the items, in addition to basic information
|
||||
/// </summary>
|
||||
/// <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; }
|
||||
|
||||
[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
|
||||
/// </summary>
|
||||
/// <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; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -150,7 +150,7 @@ namespace MediaBrowser.Api
|
|||
/// Fields to return within the items, in addition to basic information
|
||||
/// </summary>
|
||||
/// <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; }
|
||||
|
||||
[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
|
||||
/// </summary>
|
||||
/// <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; }
|
||||
|
||||
[ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||
|
@ -497,7 +497,7 @@ namespace MediaBrowser.Api
|
|||
}
|
||||
else
|
||||
{
|
||||
episodes = series.GetSeasonEpisodes(season, user);
|
||||
episodes = season.GetEpisodes(user);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -146,7 +146,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// Fields to return within the items, in addition to basic information
|
||||
/// </summary>
|
||||
/// <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; }
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -328,7 +328,15 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
|
||||
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
|
||||
|
|
|
@ -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")]
|
||||
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; }
|
||||
|
||||
[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)
|
||||
{
|
||||
AssertCanUpdateUser(_authContext, _userManager, request.Id);
|
||||
AssertCanUpdateUser(_authContext, _userManager, request.Id, true);
|
||||
|
||||
var user = _userManager.GetUserById(request.Id);
|
||||
|
||||
|
@ -482,7 +482,7 @@ namespace MediaBrowser.Api
|
|||
|
||||
public async Task PostAsync(UpdateUserEasyPassword request)
|
||||
{
|
||||
AssertCanUpdateUser(_authContext, _userManager, request.Id);
|
||||
AssertCanUpdateUser(_authContext, _userManager, request.Id, true);
|
||||
|
||||
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
|
||||
var id = GetPathValue(1);
|
||||
|
||||
AssertCanUpdateUser(_authContext, _userManager, id);
|
||||
AssertCanUpdateUser(_authContext, _userManager, id, false);
|
||||
|
||||
var dtoUser = request;
|
||||
|
||||
|
@ -568,7 +568,7 @@ namespace MediaBrowser.Api
|
|||
|
||||
public void Post(UpdateUserConfiguration request)
|
||||
{
|
||||
AssertCanUpdateUser(_authContext, _userManager, request.Id);
|
||||
AssertCanUpdateUser(_authContext, _userManager, request.Id, false);
|
||||
|
||||
var task = _userManager.UpdateConfiguration(request.Id, request);
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ using System.Globalization;
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Channels;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities.Audio
|
||||
|
@ -24,8 +23,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
IHasLookupInfo<SongInfo>,
|
||||
IHasMediaSources
|
||||
{
|
||||
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the artist.
|
||||
/// </summary>
|
||||
|
|
|
@ -112,7 +112,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
|
||||
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 };
|
||||
|
||||
return LibraryManager.GetItemList(query);
|
||||
|
|
|
@ -31,12 +31,10 @@ namespace MediaBrowser.Controller.Entities
|
|||
public string SeriesName { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public Guid? SeriesId { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public string SeriesSortName { get; set; }
|
||||
|
||||
public string FindSeriesSortName()
|
||||
{
|
||||
return SeriesSortName;
|
||||
return SeriesName;
|
||||
}
|
||||
public string FindSeriesName()
|
||||
{
|
||||
|
|
|
@ -84,6 +84,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
public long? Size { get; set; }
|
||||
public string Container { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
public string Tagline { get; set; }
|
||||
|
||||
|
@ -288,7 +289,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
return Path;
|
||||
}
|
||||
|
||||
return System.IO.Path.GetDirectoryName(Path);
|
||||
return FileSystem.GetDirectoryName(Path);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -834,20 +835,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
[IgnoreDataMember]
|
||||
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>
|
||||
/// Gets or sets the custom rating.
|
||||
/// </summary>
|
||||
|
@ -1824,7 +1811,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <returns>Task.</returns>
|
||||
public virtual Task ChangedExternally()
|
||||
{
|
||||
ProviderManager.QueueRefresh(Id, new MetadataRefreshOptions(FileSystem));
|
||||
ProviderManager.QueueRefresh(Id, new MetadataRefreshOptions(FileSystem), RefreshPriority.High);
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
|
@ -1924,7 +1911,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
var allFiles = ImageInfos
|
||||
.Where(i => i.IsLocalFile)
|
||||
.Select(i => System.IO.Path.GetDirectoryName(i.Path))
|
||||
.Select(i => FileSystem.GetDirectoryName(i.Path))
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.SelectMany(directoryService.GetFilePaths)
|
||||
.ToList();
|
||||
|
@ -2099,7 +2086,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
var extensions = new[] { ".nfo", ".xml", ".srt" }.ToList();
|
||||
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))
|
||||
.ToList();
|
||||
}
|
||||
|
@ -2298,16 +2285,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
ownedItem.CustomRating = item.CustomRating;
|
||||
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);
|
||||
|
|
|
@ -24,12 +24,10 @@ namespace MediaBrowser.Controller.Entities
|
|||
public string SeriesName { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public Guid? SeriesId { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public string SeriesSortName { get; set; }
|
||||
|
||||
public string FindSeriesSortName()
|
||||
{
|
||||
return SeriesSortName;
|
||||
return SeriesName;
|
||||
}
|
||||
public string FindSeriesName()
|
||||
{
|
||||
|
|
|
@ -213,7 +213,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
.SelectMany(c => c.LinkedChildren)
|
||||
.ToList();
|
||||
|
||||
var changed = !linkedChildren.SequenceEqual(LinkedChildren, new LinkedChildComparer());
|
||||
var changed = !linkedChildren.SequenceEqual(LinkedChildren, new LinkedChildComparer(FileSystem));
|
||||
|
||||
LinkedChildren = linkedChildren;
|
||||
|
||||
|
@ -332,13 +332,13 @@ namespace MediaBrowser.Controller.Entities
|
|||
.OfType<Folder>()
|
||||
.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)
|
||||
{
|
||||
var result = rootChildren
|
||||
.Where(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase))
|
||||
.Where(i => FileSystem.AreEqual(i.Path, path))
|
||||
.ToList();
|
||||
|
||||
if (result.Count == 0)
|
||||
|
|
|
@ -640,7 +640,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
return true;
|
||||
}
|
||||
|
||||
path = System.IO.Path.GetDirectoryName(path);
|
||||
path = FileSystem.GetDirectoryName(path);
|
||||
}
|
||||
|
||||
return allLibraryPaths.Any(i => ContainsPath(i, originalPath));
|
||||
|
@ -1206,11 +1206,17 @@ namespace MediaBrowser.Controller.Entities
|
|||
return GetLinkedChildren();
|
||||
}
|
||||
|
||||
var locations = user.RootFolder
|
||||
.Children
|
||||
if (LinkedChildren.Count == 0)
|
||||
{
|
||||
return new List<BaseItem>();
|
||||
}
|
||||
|
||||
var allUserRootChildren = user.RootFolder.Children.OfType<Folder>().ToList();
|
||||
|
||||
var collectionFolderIds = allUserRootChildren
|
||||
.OfType<CollectionFolder>()
|
||||
.Where(i => i.IsVisible(user))
|
||||
.SelectMany(i => i.PhysicalLocations)
|
||||
.Select(i => i.Id)
|
||||
.ToList();
|
||||
|
||||
return LinkedChildren
|
||||
|
@ -1228,11 +1234,18 @@ namespace MediaBrowser.Controller.Entities
|
|||
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 child;
|
||||
})
|
||||
|
@ -1323,7 +1336,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
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);
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
return new[] {
|
||||
new FileSystemMetadata
|
||||
{
|
||||
FullName = System.IO.Path.GetDirectoryName(Path),
|
||||
FullName = FileSystem.GetDirectoryName(Path),
|
||||
IsDirectory = true
|
||||
}
|
||||
};
|
||||
|
|
|
@ -81,7 +81,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||
{
|
||||
query.Genres = new[] { Name };
|
||||
query.GenreIds = new[] { Id.ToString("N") };
|
||||
query.IncludeItemTypes = new[] { typeof(Game).Name };
|
||||
|
||||
return LibraryManager.GetItemList(query);
|
||||
|
|
|
@ -93,7 +93,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
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 };
|
||||
|
||||
return LibraryManager.GetItemList(query);
|
||||
|
|
|
@ -11,7 +11,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <value>The name of the series.</value>
|
||||
string SeriesName { get; set; }
|
||||
string FindSeriesName();
|
||||
string SeriesSortName { get; set; }
|
||||
string FindSeriesSortName();
|
||||
Guid? SeriesId { get; set; }
|
||||
Guid? FindSeriesId();
|
||||
|
|
|
@ -129,7 +129,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
public string[] AncestorIds { get; set; }
|
||||
public string[] TopParentIds { get; set; }
|
||||
|
||||
public LocationType[] LocationTypes { get; set; }
|
||||
public string[] PresetViews { get; set; }
|
||||
public SourceType[] SourceTypes { get; set; }
|
||||
public SourceType[] ExcludeSourceTypes { get; set; }
|
||||
|
@ -176,7 +175,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
case ItemFields.DateCreated:
|
||||
case ItemFields.SortName:
|
||||
case ItemFields.Overview:
|
||||
case ItemFields.OfficialRatingDescription:
|
||||
case ItemFields.HomePageUrl:
|
||||
case ItemFields.VoteCount:
|
||||
case ItemFields.DisplayMediaType:
|
||||
|
@ -187,7 +185,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
case ItemFields.OriginalTitle:
|
||||
case ItemFields.Tags:
|
||||
case ItemFields.DateLastMediaAdded:
|
||||
case ItemFields.CriticRatingSummary:
|
||||
return fields.Count == 0 || fields.Contains(name);
|
||||
default:
|
||||
return true;
|
||||
|
@ -230,7 +227,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
TopParentIds = new string[] { };
|
||||
ExcludeTags = new string[] { };
|
||||
ExcludeInheritedTags = new string[] { };
|
||||
LocationTypes = new LocationType[] { };
|
||||
PresetViews = new string[] { };
|
||||
SourceTypes = new SourceType[] { };
|
||||
ExcludeSourceTypes = new SourceType[] { };
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
|
@ -40,11 +41,18 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
public class LinkedChildComparer : IEqualityComparer<LinkedChild>
|
||||
{
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
public LinkedChildComparer(IFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
|
||||
public bool Equals(LinkedChild x, LinkedChild y)
|
||||
{
|
||||
if (x.Type == y.Type)
|
||||
{
|
||||
return string.Equals(x.Path, y.Path, StringComparison.OrdinalIgnoreCase);
|
||||
return _fileSystem.AreEqual(x.Path, y.Path);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -152,9 +152,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||
var currentOfficialRating = OfficialRating;
|
||||
|
||||
// Gather all possible ratings
|
||||
var ratings = GetRecursiveChildren()
|
||||
.Concat(GetLinkedChildren())
|
||||
.Where(i => i is Movie || i is Series || i is MusicAlbum || i is Game)
|
||||
var ratings = GetRecursiveChildren(i => i is Movie || i is Series || i is MusicAlbum || i is Game)
|
||||
.Select(i => i.OfficialRating)
|
||||
.Where(i => !string.IsNullOrEmpty(i))
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
|
@ -205,7 +203,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||
|
||||
if (base.IsVisible(user))
|
||||
{
|
||||
return GetChildren(user, true).Any();
|
||||
return base.GetChildren(user, true).Any();
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -57,13 +57,10 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
/// <value>The index number.</value>
|
||||
public int? IndexNumberEnd { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
public string SeriesSortName { get; set; }
|
||||
|
||||
public string FindSeriesSortName()
|
||||
{
|
||||
var series = Series;
|
||||
return series == null ? SeriesSortName : series.SortName;
|
||||
return series == null ? SeriesName : series.SortName;
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
|
|
|
@ -51,9 +51,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
get { return SeriesId; }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public string SeriesSortName { get; set; }
|
||||
|
||||
public override double? GetDefaultPrimaryImageAspectRatio()
|
||||
{
|
||||
double value = 2;
|
||||
|
@ -65,7 +62,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
public string FindSeriesSortName()
|
||||
{
|
||||
var series = Series;
|
||||
return series == null ? SeriesSortName : series.SortName;
|
||||
return series == null ? SeriesName : series.SortName;
|
||||
}
|
||||
|
||||
// Genre, Rating and Stuido will all be the same
|
||||
|
@ -125,7 +122,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
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.ParentId = queryParent.Id;
|
||||
query.Genres = new[] { displayParent.Name };
|
||||
query.GenreIds = new[] { displayParent.Id.ToString("N") };
|
||||
query.SetUser(user);
|
||||
|
||||
query.IncludeItemTypes = new[] { typeof(Movie).Name };
|
||||
|
@ -729,7 +729,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
query.Recursive = true;
|
||||
query.ParentId = queryParent.Id;
|
||||
query.Genres = new[] { displayParent.Name };
|
||||
query.GenreIds = new[] { displayParent.Id.ToString("N") };
|
||||
query.SetUser(user);
|
||||
|
||||
query.IncludeItemTypes = new[] { typeof(Series).Name };
|
||||
|
@ -905,6 +905,11 @@ namespace MediaBrowser.Controller.Entities
|
|||
return false;
|
||||
}
|
||||
|
||||
if (request.GenreIds.Length > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request.HasImdbId.HasValue)
|
||||
{
|
||||
return false;
|
||||
|
@ -1768,26 +1773,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
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)
|
||||
{
|
||||
if (query.Recursive)
|
||||
|
|
|
@ -33,7 +33,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
public List<string> AdditionalParts { get; set; }
|
||||
public List<string> LocalAlternateVersions { get; set; }
|
||||
public List<LinkedChild> LinkedAlternateVersions { get; set; }
|
||||
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool SupportsPlayedStatus
|
||||
|
@ -158,7 +157,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
PlayableStreamFileNames = new List<string>();
|
||||
AdditionalParts = new List<string>();
|
||||
LocalAlternateVersions = new List<string>();
|
||||
Tags = new List<string>();
|
||||
SubtitleFiles = new List<string>();
|
||||
LinkedAlternateVersions = new List<LinkedChild>();
|
||||
}
|
||||
|
@ -313,7 +311,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
if (IsStacked)
|
||||
{
|
||||
return System.IO.Path.GetDirectoryName(Path);
|
||||
return FileSystem.GetDirectoryName(Path);
|
||||
}
|
||||
|
||||
if (!IsPlaceHolder)
|
||||
|
@ -591,41 +589,46 @@ namespace MediaBrowser.Controller.Entities
|
|||
.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();
|
||||
|
||||
var locationType = i.LocationType;
|
||||
var locationType = media.LocationType;
|
||||
|
||||
var info = new MediaSourceInfo
|
||||
{
|
||||
Id = i.Id.ToString("N"),
|
||||
IsoType = i.IsoType,
|
||||
Id = media.Id.ToString("N"),
|
||||
IsoType = media.IsoType,
|
||||
Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File,
|
||||
MediaStreams = mediaStreams,
|
||||
Name = GetMediaSourceName(i, mediaStreams),
|
||||
Path = enablePathSubstitution ? GetMappedPath(i, i.Path, locationType) : i.Path,
|
||||
RunTimeTicks = i.RunTimeTicks,
|
||||
Video3DFormat = i.Video3DFormat,
|
||||
VideoType = i.VideoType,
|
||||
Container = i.Container,
|
||||
Size = i.Size,
|
||||
Timestamp = i.Timestamp,
|
||||
Name = GetMediaSourceName(media, mediaStreams),
|
||||
Path = enablePathSubstitution ? GetMappedPath(media, media.Path, locationType) : media.Path,
|
||||
RunTimeTicks = media.RunTimeTicks,
|
||||
Video3DFormat = media.Video3DFormat,
|
||||
VideoType = media.VideoType,
|
||||
Container = media.Container,
|
||||
Size = media.Size,
|
||||
Timestamp = media.Timestamp,
|
||||
Type = type,
|
||||
PlayableStreamFileNames = i.PlayableStreamFileNames.ToList(),
|
||||
SupportsDirectStream = i.VideoType == VideoType.VideoFile,
|
||||
IsRemote = i.IsShortcut
|
||||
PlayableStreamFileNames = media.PlayableStreamFileNames.ToList(),
|
||||
SupportsDirectStream = media.VideoType == VideoType.VideoFile,
|
||||
IsRemote = media.IsShortcut
|
||||
};
|
||||
|
||||
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))
|
||||
{
|
||||
|
@ -647,16 +650,16 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
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();
|
||||
|
||||
return info;
|
||||
|
|
|
@ -456,6 +456,8 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <returns>IEnumerable<Folder>.</returns>
|
||||
List<Folder> GetCollectionFolders(BaseItem item);
|
||||
|
||||
List<Folder> GetCollectionFolders(BaseItem item, List<Folder> allUserRootChildren);
|
||||
|
||||
LibraryOptions GetLibraryOptions(BaseItem item);
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -114,7 +114,7 @@ namespace MediaBrowser.Controller.Library
|
|||
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
|
||||
&& parentDir.StartsWith(_appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase);
|
||||
|
@ -130,7 +130,7 @@ namespace MediaBrowser.Controller.Library
|
|||
{
|
||||
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.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;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user