Merge pull request #2618 from MediaBrowser/beta

Beta
This commit is contained in:
Luke 2017-05-06 16:20:25 -04:00 committed by GitHub
commit 21edff3ac2
199 changed files with 1934 additions and 1466 deletions

View File

@ -96,7 +96,7 @@ namespace BDInfo
} }
DirectoryRoot = DirectoryRoot =
_fileSystem.GetDirectoryInfo(Path.GetDirectoryName(DirectoryBDMV.FullName)); _fileSystem.GetDirectoryInfo(_fileSystem.GetDirectoryName(DirectoryBDMV.FullName));
DirectoryBDJO = DirectoryBDJO =
GetDirectory("BDJO", DirectoryBDMV, 0); GetDirectory("BDJO", DirectoryBDMV, 0);
DirectoryCLIPINF = DirectoryCLIPINF =
@ -349,7 +349,7 @@ namespace BDInfo
{ {
return dir; return dir;
} }
var parentFolder = Path.GetDirectoryName(dir.FullName); var parentFolder = _fileSystem.GetDirectoryName(dir.FullName);
if (string.IsNullOrEmpty(parentFolder)) if (string.IsNullOrEmpty(parentFolder))
{ {
dir = null; dir = null;

View File

@ -57,7 +57,7 @@ namespace Emby.Common.Implementations.Devices
{ {
var path = CachePath; var path = CachePath;
_fileSystem.CreateDirectory(Path.GetDirectoryName(path)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
lock (_syncLock) lock (_syncLock)
{ {

View File

@ -131,4 +131,4 @@ namespace Emby.Common.Implementations.EnvironmentInfo
Environment.SetEnvironmentVariable(name, value); Environment.SetEnvironmentVariable(name, value);
} }
} }
} }

View File

@ -418,7 +418,7 @@ namespace Emby.Common.Implementations.HttpClientManager
private async Task CacheResponse(HttpResponseInfo response, string responseCachePath) private async Task CacheResponse(HttpResponseInfo response, string responseCachePath)
{ {
_fileSystem.CreateDirectory(Path.GetDirectoryName(responseCachePath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(responseCachePath));
using (var responseStream = response.Content) using (var responseStream = response.Content)
{ {

View File

@ -546,24 +546,6 @@ namespace Emby.Common.Implementations.IO
return Path.DirectorySeparatorChar; return Path.DirectorySeparatorChar;
} }
public bool AreEqual(string path1, string path2)
{
if (path1 == null && path2 == null)
{
return true;
}
if (path1 == null || path2 == null)
{
return false;
}
path1 = path1.TrimEnd(GetDirectorySeparatorChar(path1));
path2 = path2.TrimEnd(GetDirectorySeparatorChar(path2));
return string.Equals(path1, path2, StringComparison.OrdinalIgnoreCase);
}
public bool ContainsSubPath(string parentPath, string path) public bool ContainsSubPath(string parentPath, string path)
{ {
if (string.IsNullOrEmpty(parentPath)) if (string.IsNullOrEmpty(parentPath))
@ -588,7 +570,7 @@ namespace Emby.Common.Implementations.IO
throw new ArgumentNullException("path"); throw new ArgumentNullException("path");
} }
var parent = Path.GetDirectoryName(path); var parent = GetDirectoryName(path);
if (!string.IsNullOrEmpty(parent)) if (!string.IsNullOrEmpty(parent))
{ {
@ -598,6 +580,16 @@ namespace Emby.Common.Implementations.IO
return true; return true;
} }
public string GetDirectoryName(string path)
{
if (_sharpCifsFileSystem.IsEnabledForPath(path))
{
return _sharpCifsFileSystem.GetDirectoryName(path);
}
return Path.GetDirectoryName(path);
}
public string NormalizePath(string path) public string NormalizePath(string path)
{ {
if (string.IsNullOrEmpty(path)) if (string.IsNullOrEmpty(path))
@ -605,6 +597,11 @@ namespace Emby.Common.Implementations.IO
throw new ArgumentNullException("path"); throw new ArgumentNullException("path");
} }
if (_sharpCifsFileSystem.IsEnabledForPath(path))
{
return _sharpCifsFileSystem.NormalizePath(path);
}
if (path.EndsWith(":\\", StringComparison.OrdinalIgnoreCase)) if (path.EndsWith(":\\", StringComparison.OrdinalIgnoreCase))
{ {
return path; return path;
@ -613,6 +610,21 @@ namespace Emby.Common.Implementations.IO
return path.TrimEnd(GetDirectorySeparatorChar(path)); return path.TrimEnd(GetDirectorySeparatorChar(path));
} }
public bool AreEqual(string path1, string path2)
{
if (path1 == null && path2 == null)
{
return true;
}
if (path1 == null || path2 == null)
{
return false;
}
return string.Equals(NormalizePath(path1), NormalizePath(path2), StringComparison.OrdinalIgnoreCase);
}
public string GetFileNameWithoutExtension(FileSystemMetadata info) public string GetFileNameWithoutExtension(FileSystemMetadata info)
{ {
if (info.IsDirectory) if (info.IsDirectory)
@ -637,11 +649,17 @@ namespace Emby.Common.Implementations.IO
// Cannot use Path.IsPathRooted because it returns false under mono when using windows-based paths, e.g. C:\\ // Cannot use Path.IsPathRooted because it returns false under mono when using windows-based paths, e.g. C:\\
if (_sharpCifsFileSystem.IsEnabledForPath(path))
{
return true;
}
if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) != -1 && if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) != -1 &&
!path.StartsWith("file://", StringComparison.OrdinalIgnoreCase)) !path.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
{ {
return false; return false;
} }
return true; return true;
//return Path.IsPathRooted(path); //return Path.IsPathRooted(path);

View File

@ -30,6 +30,34 @@ namespace Emby.Common.Implementations.IO
return path.StartsWith("smb://", StringComparison.OrdinalIgnoreCase) || IsUncPath(path); return path.StartsWith("smb://", StringComparison.OrdinalIgnoreCase) || IsUncPath(path);
} }
public string NormalizePath(string path)
{
if (path.StartsWith("smb://", StringComparison.OrdinalIgnoreCase))
{
return path;
}
if (IsUncPath(path))
{
return ConvertUncToSmb(path);
}
return path;
}
public string GetDirectoryName(string path)
{
var separator = GetDirectorySeparatorChar(path);
var result = Path.GetDirectoryName(path);
if (separator == '/')
{
result = result.Replace('\\', '/');
}
return result;
}
public char GetDirectorySeparatorChar(string path) public char GetDirectorySeparatorChar(string path)
{ {
if (path.IndexOf('/') != -1) if (path.IndexOf('/') != -1)

View File

@ -100,7 +100,7 @@ namespace Emby.Common.Implementations.Net
#if NET46 #if NET46
public Task SendFile(string path, byte[] preBuffer, byte[] postBuffer, CancellationToken cancellationToken) public Task SendFile(string path, byte[] preBuffer, byte[] postBuffer, CancellationToken cancellationToken)
{ {
var options = TransmitFileOptions.UseKernelApc; var options = TransmitFileOptions.UseDefaultWorkerThread;
var completionSource = new TaskCompletionSource<bool>(); var completionSource = new TaskCompletionSource<bool>();

View File

@ -158,7 +158,7 @@ namespace Emby.Common.Implementations.ScheduledTasks
_lastExecutionResult = value; _lastExecutionResult = value;
var path = GetHistoryFilePath(); var path = GetHistoryFilePath();
_fileSystem.CreateDirectory(Path.GetDirectoryName(path)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
lock (_lastExecutionResultSyncLock) lock (_lastExecutionResultSyncLock)
{ {
@ -575,7 +575,7 @@ namespace Emby.Common.Implementations.ScheduledTasks
{ {
var path = GetConfigurationFilePath(); var path = GetConfigurationFilePath();
_fileSystem.CreateDirectory(Path.GetDirectoryName(path)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
JsonSerializer.SerializeToFile(triggers, path); JsonSerializer.SerializeToFile(triggers, path);
} }

View File

@ -91,7 +91,7 @@ namespace Emby.Drawing.ImageMagick
try try
{ {
var tmpPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".webp"); var tmpPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".webp");
_fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
using (var wand = new MagickWand(1, 1, new PixelWand("none", 1))) using (var wand = new MagickWand(1, 1, new PixelWand("none", 1)))
{ {

View File

@ -68,7 +68,7 @@ namespace Emby.Drawing.ImageMagick
var namespacePath = typeof(PlayedIndicatorDrawer).Namespace + ".fonts." + name; var namespacePath = typeof(PlayedIndicatorDrawer).Namespace + ".fonts." + name;
var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".ttf"); var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".ttf");
fileSystem.CreateDirectory(Path.GetDirectoryName(tempPath)); fileSystem.CreateDirectory(fileSystem.GetDirectoryName(tempPath));
using (var stream = typeof(PlayedIndicatorDrawer).Assembly.GetManifestResourceStream(namespacePath)) using (var stream = typeof(PlayedIndicatorDrawer).Assembly.GetManifestResourceStream(namespacePath))
{ {
@ -78,7 +78,7 @@ namespace Emby.Drawing.ImageMagick
} }
} }
fileSystem.CreateDirectory(Path.GetDirectoryName(filePath)); fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath));
try try
{ {
@ -108,7 +108,7 @@ namespace Emby.Drawing.ImageMagick
}).ConfigureAwait(false); }).ConfigureAwait(false);
fileSystem.CreateDirectory(Path.GetDirectoryName(filePath)); fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath));
try try
{ {

View File

@ -81,7 +81,7 @@ namespace Emby.Drawing.Net
{ {
using (var croppedImage = image.CropWhitespace()) using (var croppedImage = image.CropWhitespace())
{ {
_fileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath));
using (var outputStream = _fileSystem.GetFileStream(outputPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false)) using (var outputStream = _fileSystem.GetFileStream(outputPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false))
{ {
@ -135,7 +135,7 @@ namespace Emby.Drawing.Net
var outputFormat = GetOutputFormat(originalImage, selectedOutputFormat); var outputFormat = GetOutputFormat(originalImage, selectedOutputFormat);
_fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
// Save to the cache location // Save to the cache location
using (var cacheFileStream = _fileSystem.GetFileStream(cacheFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false)) using (var cacheFileStream = _fileSystem.GetFileStream(cacheFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false))

View File

@ -244,9 +244,9 @@ namespace Emby.Drawing
var newWidth = Convert.ToInt32(newSize.Width); var newWidth = Convert.ToInt32(newSize.Width);
var newHeight = Convert.ToInt32(newSize.Height); var newHeight = Convert.ToInt32(newSize.Height);
_fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath)); var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
_fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
_imageEncoder.EncodeImage(originalImagePath, tmpPath, AutoOrient(options.Item), newWidth, newHeight, quality, options, outputFormat); _imageEncoder.EncodeImage(originalImagePath, tmpPath, AutoOrient(options.Item), newWidth, newHeight, quality, options, outputFormat);
CopyFile(tmpPath, cacheFilePath); CopyFile(tmpPath, cacheFilePath);
@ -418,9 +418,9 @@ namespace Emby.Drawing
try try
{ {
_fileSystem.CreateDirectory(Path.GetDirectoryName(croppedImagePath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(croppedImagePath));
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(croppedImagePath)); var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(croppedImagePath));
_fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
_imageEncoder.CropWhiteSpace(originalImagePath, tmpPath); _imageEncoder.CropWhiteSpace(originalImagePath, tmpPath);
CopyFile(tmpPath, croppedImagePath); CopyFile(tmpPath, croppedImagePath);
@ -592,7 +592,7 @@ namespace Emby.Drawing
try try
{ {
var path = ImageSizeFile; var path = ImageSizeFile;
_fileSystem.CreateDirectory(Path.GetDirectoryName(path)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
_jsonSerializer.SerializeToFile(_cachedImagedSizes, path); _jsonSerializer.SerializeToFile(_cachedImagedSizes, path);
} }
catch (Exception ex) catch (Exception ex)
@ -765,10 +765,10 @@ namespace Emby.Drawing
return enhancedImagePath; return enhancedImagePath;
} }
_fileSystem.CreateDirectory(Path.GetDirectoryName(enhancedImagePath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(enhancedImagePath));
var tmpPath = Path.Combine(_appPaths.TempDirectory, Path.ChangeExtension(Guid.NewGuid().ToString(), Path.GetExtension(enhancedImagePath))); var tmpPath = Path.Combine(_appPaths.TempDirectory, Path.ChangeExtension(Guid.NewGuid().ToString(), Path.GetExtension(enhancedImagePath)));
_fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, tmpPath, item, imageType, imageIndex).ConfigureAwait(false); await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, tmpPath, item, imageType, imageIndex).ConfigureAwait(false);

View File

@ -257,7 +257,7 @@ namespace Emby.Server.Core
internal IPowerManagement PowerManagement { get; private set; } internal IPowerManagement PowerManagement { get; private set; }
internal IImageEncoder ImageEncoder { get; private set; } internal IImageEncoder ImageEncoder { get; private set; }
private readonly Action<string, string> _certificateGenerator; private readonly Action<string, string, string> _certificateGenerator;
private readonly Func<string> _defaultUserNameFactory; private readonly Func<string> _defaultUserNameFactory;
/// <summary> /// <summary>
@ -274,7 +274,7 @@ namespace Emby.Server.Core
ISystemEvents systemEvents, ISystemEvents systemEvents,
IMemoryStreamFactory memoryStreamFactory, IMemoryStreamFactory memoryStreamFactory,
INetworkManager networkManager, INetworkManager networkManager,
Action<string, string> certificateGenerator, Action<string, string, string> certificateGenerator,
Func<string> defaultUsernameFactory) Func<string> defaultUsernameFactory)
: base(applicationPaths, : base(applicationPaths,
logManager, logManager,
@ -609,8 +609,8 @@ namespace Emby.Server.Core
RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager)); RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
CertificatePath = GetCertificatePath(true); CertificateInfo = GetCertificateInfo(true);
Certificate = GetCertificate(CertificatePath); Certificate = GetCertificate(CertificateInfo);
HttpServer = HttpServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, NetworkManager, MemoryStreamFactory, "Emby", "web/index.html", textEncoding, SocketFactory, CryptographyProvider, JsonSerializer, XmlSerializer, EnvironmentInfo, Certificate, FileSystemManager, SupportsDualModeSockets); HttpServer = HttpServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, NetworkManager, MemoryStreamFactory, "Emby", "web/index.html", textEncoding, SocketFactory, CryptographyProvider, JsonSerializer, XmlSerializer, EnvironmentInfo, Certificate, FileSystemManager, SupportsDualModeSockets);
HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading"); HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading");
@ -745,8 +745,10 @@ namespace Emby.Server.Core
} }
} }
private ICertificate GetCertificate(string certificateLocation) private ICertificate GetCertificate(CertificateInfo info)
{ {
var certificateLocation = info == null ? null : info.Path;
if (string.IsNullOrWhiteSpace(certificateLocation)) if (string.IsNullOrWhiteSpace(certificateLocation))
{ {
return null; return null;
@ -759,7 +761,7 @@ namespace Emby.Server.Core
return null; return null;
} }
X509Certificate2 localCert = new X509Certificate2(certificateLocation); X509Certificate2 localCert = new X509Certificate2(certificateLocation, info.Password);
//localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA; //localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA;
if (!localCert.HasPrivateKey) if (!localCert.HasPrivateKey)
{ {
@ -1064,7 +1066,7 @@ namespace Emby.Server.Core
SyncManager.AddParts(GetExports<ISyncProvider>()); SyncManager.AddParts(GetExports<ISyncProvider>());
} }
private string CertificatePath { get; set; } private CertificateInfo CertificateInfo { get; set; }
private ICertificate Certificate { get; set; } private ICertificate Certificate { get; set; }
private IEnumerable<string> GetUrlPrefixes() private IEnumerable<string> GetUrlPrefixes()
@ -1080,7 +1082,7 @@ namespace Emby.Server.Core
"http://"+i+":" + HttpPort + "/" "http://"+i+":" + HttpPort + "/"
}; };
if (!string.IsNullOrWhiteSpace(CertificatePath)) if (CertificateInfo != null)
{ {
prefixes.Add("https://" + i + ":" + HttpsPort + "/"); prefixes.Add("https://" + i + ":" + HttpsPort + "/");
} }
@ -1123,27 +1125,31 @@ namespace Emby.Server.Core
} }
} }
private string GetCertificatePath(bool generateCertificate) private CertificateInfo GetCertificateInfo(bool generateCertificate)
{ {
if (!string.IsNullOrWhiteSpace(ServerConfigurationManager.Configuration.CertificatePath)) if (!string.IsNullOrWhiteSpace(ServerConfigurationManager.Configuration.CertificatePath))
{ {
// Custom cert // Custom cert
return ServerConfigurationManager.Configuration.CertificatePath; return new CertificateInfo
{
Path = ServerConfigurationManager.Configuration.CertificatePath
};
} }
// Generate self-signed cert // Generate self-signed cert
var certHost = GetHostnameFromExternalDns(ServerConfigurationManager.Configuration.WanDdns); var certHost = GetHostnameFromExternalDns(ServerConfigurationManager.Configuration.WanDdns);
var certPath = Path.Combine(ServerConfigurationManager.ApplicationPaths.ProgramDataPath, "ssl", "cert_" + (certHost + "1").GetMD5().ToString("N") + ".pfx"); var certPath = Path.Combine(ServerConfigurationManager.ApplicationPaths.ProgramDataPath, "ssl", "cert_" + (certHost + "2").GetMD5().ToString("N") + ".pfx");
var password = "embycert";
if (generateCertificate) if (generateCertificate)
{ {
if (!FileSystemManager.FileExists(certPath)) if (!FileSystemManager.FileExists(certPath))
{ {
FileSystemManager.CreateDirectory(Path.GetDirectoryName(certPath)); FileSystemManager.CreateDirectory(FileSystemManager.GetDirectoryName(certPath));
try try
{ {
_certificateGenerator(certPath, certHost); _certificateGenerator(certPath, certHost, password);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -1153,7 +1159,11 @@ namespace Emby.Server.Core
} }
} }
return certPath; return new CertificateInfo
{
Path = certPath,
Password = password
};
} }
/// <summary> /// <summary>
@ -1189,7 +1199,11 @@ namespace Emby.Server.Core
requiresRestart = true; requiresRestart = true;
} }
if (!string.Equals(CertificatePath, GetCertificatePath(false), StringComparison.OrdinalIgnoreCase)) var currentCertPath = CertificateInfo == null ? null : CertificateInfo.Path;
var newCertInfo = GetCertificateInfo(false);
var newCertPath = newCertInfo == null ? null : newCertInfo.Path;
if (!string.Equals(currentCertPath, newCertPath, StringComparison.OrdinalIgnoreCase))
{ {
requiresRestart = true; requiresRestart = true;
} }
@ -1779,6 +1793,11 @@ namespace Emby.Server.Core
{ {
Container.Register(typeInterface, typeImplementation); Container.Register(typeInterface, typeImplementation);
} }
}
internal class CertificateInfo
{
public string Path { get; set; }
public string Password { get; set; }
} }
} }

View File

@ -453,7 +453,7 @@ namespace Emby.Server.Core.IO
// If the parent of an ignored path has a change event, ignore that too // If the parent of an ignored path has a change event, ignore that too
if (tempIgnorePaths.Any(i => if (tempIgnorePaths.Any(i =>
{ {
if (string.Equals(i, path, StringComparison.OrdinalIgnoreCase)) if (_fileSystem.AreEqual(i, path))
{ {
Logger.Debug("Ignoring change to {0}", path); Logger.Debug("Ignoring change to {0}", path);
return true; return true;
@ -466,10 +466,10 @@ namespace Emby.Server.Core.IO
} }
// Go up a level // Go up a level
var parent = Path.GetDirectoryName(i); var parent = _fileSystem.GetDirectoryName(i);
if (!string.IsNullOrEmpty(parent)) if (!string.IsNullOrEmpty(parent))
{ {
if (string.Equals(parent, path, StringComparison.OrdinalIgnoreCase)) if (_fileSystem.AreEqual(parent, path))
{ {
Logger.Debug("Ignoring change to {0}", path); Logger.Debug("Ignoring change to {0}", path);
return true; return true;
@ -492,7 +492,7 @@ namespace Emby.Server.Core.IO
private void CreateRefresher(string path) private void CreateRefresher(string path)
{ {
var parentPath = Path.GetDirectoryName(path); var parentPath = _fileSystem.GetDirectoryName(path);
lock (_activeRefreshers) lock (_activeRefreshers)
{ {
@ -500,7 +500,7 @@ namespace Emby.Server.Core.IO
foreach (var refresher in refreshers) foreach (var refresher in refreshers)
{ {
// Path is already being refreshed // Path is already being refreshed
if (string.Equals(path, refresher.Path, StringComparison.Ordinal)) if (_fileSystem.AreEqual(path, refresher.Path))
{ {
refresher.RestartTimer(); refresher.RestartTimer();
return; return;
@ -521,7 +521,7 @@ namespace Emby.Server.Core.IO
} }
// They are siblings. Rebase the refresher to the parent folder. // They are siblings. Rebase the refresher to the parent folder.
if (string.Equals(parentPath, Path.GetDirectoryName(refresher.Path), StringComparison.Ordinal)) if (string.Equals(parentPath, _fileSystem.GetDirectoryName(refresher.Path), StringComparison.Ordinal))
{ {
refresher.ResetPath(parentPath, path); refresher.ResetPath(parentPath, path);
return; return;

View File

@ -268,24 +268,14 @@ namespace Emby.Server.Implementations.Channels
return; return;
} }
_fileSystem.CreateDirectory(Path.GetDirectoryName(path)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
_jsonSerializer.SerializeToFile(mediaSources, path); _jsonSerializer.SerializeToFile(mediaSources, path);
} }
public async Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(BaseItem item, CancellationToken cancellationToken) public async Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(BaseItem item, CancellationToken cancellationToken)
{ {
IEnumerable<ChannelMediaInfo> results = new List<ChannelMediaInfo>(); IEnumerable<ChannelMediaInfo> results = GetSavedMediaSources(item);
var video = item as Video;
if (video != null)
{
results = video.ChannelMediaSources;
}
var audio = item as Audio;
if (audio != null)
{
results = audio.ChannelMediaSources ?? GetSavedMediaSources(audio);
}
return SortMediaInfoResults(results) return SortMediaInfoResults(results)
.Select(i => GetMediaSource(item, i)) .Select(i => GetMediaSource(item, i))
@ -1115,7 +1105,7 @@ namespace Emby.Server.Implementations.Channels
{ {
try try
{ {
_fileSystem.CreateDirectory(Path.GetDirectoryName(path)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
_jsonSerializer.SerializeToFile(result, path); _jsonSerializer.SerializeToFile(result, path);
} }
@ -1378,7 +1368,6 @@ namespace Emby.Server.Implementations.Channels
if (channelVideoItem != null) if (channelVideoItem != null)
{ {
channelVideoItem.ExtraType = info.ExtraType; channelVideoItem.ExtraType = info.ExtraType;
channelVideoItem.ChannelMediaSources = info.MediaSources;
var mediaSource = info.MediaSources.FirstOrDefault(); var mediaSource = info.MediaSources.FirstOrDefault();
item.Path = mediaSource == null ? null : mediaSource.Path; item.Path = mediaSource == null ? null : mediaSource.Path;
@ -1427,7 +1416,7 @@ namespace Emby.Server.Implementations.Channels
if (!_refreshedItems.ContainsKey(program.Id)) if (!_refreshedItems.ContainsKey(program.Id))
{ {
_refreshedItems.TryAdd(program.Id, true); _refreshedItems.TryAdd(program.Id, true);
_providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem)); _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.Low);
} }
} }

View File

@ -102,7 +102,7 @@ namespace Emby.Server.Implementations.Collections
} }
else else
{ {
_providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem)); _providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.High);
} }
EventHelper.FireEventIfNotNull(CollectionCreated, this, new CollectionCreatedEventArgs EventHelper.FireEventIfNotNull(CollectionCreated, this, new CollectionCreatedEventArgs
@ -191,7 +191,7 @@ namespace Emby.Server.Implementations.Collections
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
_providerManager.QueueRefresh(collection.Id, refreshOptions); _providerManager.QueueRefresh(collection.Id, refreshOptions, RefreshPriority.High);
if (fireEvent) if (fireEvent)
{ {
@ -244,7 +244,7 @@ namespace Emby.Server.Implementations.Collections
collection.UpdateRatingToContent(); collection.UpdateRatingToContent();
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
_providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem)); _providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.High);
EventHelper.FireEventIfNotNull(ItemsRemovedFromCollection, this, new CollectionModifiedEventArgs EventHelper.FireEventIfNotNull(ItemsRemovedFromCollection, this, new CollectionModifiedEventArgs
{ {

View File

@ -71,10 +71,9 @@ namespace Emby.Server.Implementations.Data
double newPercentCommplete = 45 + .55 * p; double newPercentCommplete = 45 + .55 * p;
progress.Report(newPercentCommplete); progress.Report(newPercentCommplete);
}); });
await CleanDeletedItems(cancellationToken, innerProgress).ConfigureAwait(false);
progress.Report(100);
await _itemRepo.UpdateInheritedValues(cancellationToken).ConfigureAwait(false); await _itemRepo.UpdateInheritedValues(cancellationToken).ConfigureAwait(false);
progress.Report(100);
} }
private async Task CleanDeadItems(CancellationToken cancellationToken, IProgress<double> progress) private async Task CleanDeadItems(CancellationToken cancellationToken, IProgress<double> progress)
@ -115,115 +114,6 @@ namespace Emby.Server.Implementations.Data
progress.Report(100); progress.Report(100);
} }
private async Task CleanDeletedItems(CancellationToken cancellationToken, IProgress<double> progress)
{
var result = _itemRepo.GetItemIdsWithPath(new InternalItemsQuery
{
LocationTypes = new[] { LocationType.FileSystem },
//Limit = limit,
// These have their own cleanup routines
ExcludeItemTypes = new[]
{
typeof(Person).Name,
typeof(Genre).Name,
typeof(MusicGenre).Name,
typeof(GameGenre).Name,
typeof(Studio).Name,
typeof(Year).Name,
typeof(Channel).Name,
typeof(AggregateFolder).Name,
typeof(CollectionFolder).Name
}
});
var numComplete = 0;
var numItems = result.Count;
var allLibraryPaths = _libraryManager
.GetVirtualFolders()
.SelectMany(i => i.Locations)
.ToList();
foreach (var item in result)
{
cancellationToken.ThrowIfCancellationRequested();
var path = item.Item2;
try
{
var isPathInLibrary = false;
if (allLibraryPaths.Any(i => path.StartsWith(i, StringComparison.Ordinal)) ||
allLibraryPaths.Contains(path, StringComparer.Ordinal) ||
path.StartsWith(_appPaths.ProgramDataPath, StringComparison.Ordinal))
{
isPathInLibrary = true;
if (_fileSystem.FileExists(path) || _fileSystem.DirectoryExists(path))
{
continue;
}
}
var libraryItem = _libraryManager.GetItemById(item.Item1);
if (libraryItem == null)
{
continue;
}
if (libraryItem.IsTopParent)
{
continue;
}
var hasDualAccess = libraryItem as IHasDualAccess;
if (hasDualAccess != null && hasDualAccess.IsAccessedByName)
{
continue;
}
var libraryItemPath = libraryItem.Path;
if (!string.Equals(libraryItemPath, path, StringComparison.OrdinalIgnoreCase))
{
_logger.Error("CleanDeletedItems aborting delete for item {0}-{1} because paths don't match. {2}---{3}", libraryItem.Id, libraryItem.Name, libraryItem.Path ?? string.Empty, path ?? string.Empty);
continue;
}
if (Folder.IsPathOffline(path, allLibraryPaths))
{
continue;
}
if (isPathInLibrary)
{
_logger.Info("Deleting item from database {0} because path no longer exists. type: {1} path: {2}", libraryItem.Name, libraryItem.GetType().Name, libraryItemPath ?? string.Empty);
}
else
{
_logger.Info("Deleting item from database {0} because path is no longer in the server library. type: {1} path: {2}", libraryItem.Name, libraryItem.GetType().Name, libraryItemPath ?? string.Empty);
}
await libraryItem.OnFileDeleted().ConfigureAwait(false);
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
_logger.ErrorException("Error in CleanDeletedItems. File {0}", ex, path);
}
numComplete++;
double percent = numComplete;
percent /= numItems;
progress.Report(percent * 100);
}
}
/// <summary> /// <summary>
/// Creates the triggers that define when the task will run /// Creates the triggers that define when the task will run
/// </summary> /// </summary>

View File

@ -201,7 +201,6 @@ namespace Emby.Server.Implementations.Data
AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames); AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames);
AddColumn(db, "TypedBaseItems", "OfficialRatingDescription", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "HomePageUrl", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "HomePageUrl", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "VoteCount", "INT", existingColumnNames); AddColumn(db, "TypedBaseItems", "VoteCount", "INT", existingColumnNames);
AddColumn(db, "TypedBaseItems", "DisplayMediaType", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "DisplayMediaType", "Text", existingColumnNames);
@ -209,7 +208,6 @@ namespace Emby.Server.Implementations.Data
AddColumn(db, "TypedBaseItems", "DateModified", "DATETIME", existingColumnNames); AddColumn(db, "TypedBaseItems", "DateModified", "DATETIME", existingColumnNames);
AddColumn(db, "TypedBaseItems", "ForcedSortName", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "ForcedSortName", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "LocationType", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "IsSeries", "BIT", existingColumnNames); AddColumn(db, "TypedBaseItems", "IsSeries", "BIT", existingColumnNames);
AddColumn(db, "TypedBaseItems", "IsLive", "BIT", existingColumnNames); AddColumn(db, "TypedBaseItems", "IsLive", "BIT", existingColumnNames);
@ -240,7 +238,6 @@ namespace Emby.Server.Implementations.Data
AddColumn(db, "TypedBaseItems", "SourceType", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "SourceType", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "TrailerTypes", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "TrailerTypes", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "CriticRating", "Float", existingColumnNames); AddColumn(db, "TypedBaseItems", "CriticRating", "Float", existingColumnNames);
AddColumn(db, "TypedBaseItems", "CriticRatingSummary", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "InheritedTags", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "InheritedTags", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "CleanName", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "CleanName", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "PresentationUniqueKey", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "PresentationUniqueKey", "Text", existingColumnNames);
@ -255,7 +252,6 @@ namespace Emby.Server.Implementations.Data
AddColumn(db, "TypedBaseItems", "SeasonName", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "SeasonName", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "SeasonId", "GUID", existingColumnNames); AddColumn(db, "TypedBaseItems", "SeasonId", "GUID", existingColumnNames);
AddColumn(db, "TypedBaseItems", "SeriesId", "GUID", existingColumnNames); AddColumn(db, "TypedBaseItems", "SeriesId", "GUID", existingColumnNames);
AddColumn(db, "TypedBaseItems", "SeriesSortName", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "ExternalSeriesId", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "ExternalSeriesId", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "Tagline", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "Tagline", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "Keywords", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "Keywords", "Text", existingColumnNames);
@ -429,7 +425,6 @@ namespace Emby.Server.Implementations.Data
"ParentIndexNumber", "ParentIndexNumber",
"ProductionYear", "ProductionYear",
"OfficialRating", "OfficialRating",
"OfficialRatingDescription",
"HomePageUrl", "HomePageUrl",
"DisplayMediaType", "DisplayMediaType",
"ForcedSortName", "ForcedSortName",
@ -454,13 +449,11 @@ namespace Emby.Server.Implementations.Data
"DateLastMediaAdded", "DateLastMediaAdded",
"Album", "Album",
"CriticRating", "CriticRating",
"CriticRatingSummary",
"IsVirtualItem", "IsVirtualItem",
"SeriesName", "SeriesName",
"SeasonName", "SeasonName",
"SeasonId", "SeasonId",
"SeriesId", "SeriesId",
"SeriesSortName",
"PresentationUniqueKey", "PresentationUniqueKey",
"InheritedParentalRatingValue", "InheritedParentalRatingValue",
"InheritedTags", "InheritedTags",
@ -552,14 +545,12 @@ namespace Emby.Server.Implementations.Data
"InheritedParentalRatingValue", "InheritedParentalRatingValue",
"SortName", "SortName",
"RunTimeTicks", "RunTimeTicks",
"OfficialRatingDescription",
"HomePageUrl", "HomePageUrl",
"VoteCount", "VoteCount",
"DisplayMediaType", "DisplayMediaType",
"DateCreated", "DateCreated",
"DateModified", "DateModified",
"ForcedSortName", "ForcedSortName",
"LocationType",
"PreferredMetadataLanguage", "PreferredMetadataLanguage",
"PreferredMetadataCountryCode", "PreferredMetadataCountryCode",
"IsHD", "IsHD",
@ -579,7 +570,6 @@ namespace Emby.Server.Implementations.Data
"SourceType", "SourceType",
"TrailerTypes", "TrailerTypes",
"CriticRating", "CriticRating",
"CriticRatingSummary",
"InheritedTags", "InheritedTags",
"CleanName", "CleanName",
"PresentationUniqueKey", "PresentationUniqueKey",
@ -594,7 +584,6 @@ namespace Emby.Server.Implementations.Data
"SeasonName", "SeasonName",
"SeasonId", "SeasonId",
"SeriesId", "SeriesId",
"SeriesSortName",
"ExternalSeriesId", "ExternalSeriesId",
"Tagline", "Tagline",
"Keywords", "Keywords",
@ -833,7 +822,6 @@ namespace Emby.Server.Implementations.Data
saveItemStatement.TryBind("@SortName", item.SortName); saveItemStatement.TryBind("@SortName", item.SortName);
saveItemStatement.TryBind("@RunTimeTicks", item.RunTimeTicks); saveItemStatement.TryBind("@RunTimeTicks", item.RunTimeTicks);
saveItemStatement.TryBind("@OfficialRatingDescription", item.OfficialRatingDescription);
saveItemStatement.TryBind("@HomePageUrl", item.HomePageUrl); saveItemStatement.TryBind("@HomePageUrl", item.HomePageUrl);
saveItemStatement.TryBind("@VoteCount", item.VoteCount); saveItemStatement.TryBind("@VoteCount", item.VoteCount);
saveItemStatement.TryBind("@DisplayMediaType", item.DisplayMediaType); saveItemStatement.TryBind("@DisplayMediaType", item.DisplayMediaType);
@ -841,7 +829,6 @@ namespace Emby.Server.Implementations.Data
saveItemStatement.TryBind("@DateModified", item.DateModified); saveItemStatement.TryBind("@DateModified", item.DateModified);
saveItemStatement.TryBind("@ForcedSortName", item.ForcedSortName); saveItemStatement.TryBind("@ForcedSortName", item.ForcedSortName);
saveItemStatement.TryBind("@LocationType", item.LocationType.ToString());
saveItemStatement.TryBind("@PreferredMetadataLanguage", item.PreferredMetadataLanguage); saveItemStatement.TryBind("@PreferredMetadataLanguage", item.PreferredMetadataLanguage);
saveItemStatement.TryBind("@PreferredMetadataCountryCode", item.PreferredMetadataCountryCode); saveItemStatement.TryBind("@PreferredMetadataCountryCode", item.PreferredMetadataCountryCode);
@ -942,7 +929,6 @@ namespace Emby.Server.Implementations.Data
} }
saveItemStatement.TryBind("@CriticRating", item.CriticRating); saveItemStatement.TryBind("@CriticRating", item.CriticRating);
saveItemStatement.TryBind("@CriticRatingSummary", item.CriticRatingSummary);
var inheritedTags = item.InheritedTags; var inheritedTags = item.InheritedTags;
if (inheritedTags.Count > 0) if (inheritedTags.Count > 0)
@ -1024,13 +1010,11 @@ namespace Emby.Server.Implementations.Data
if (hasSeries != null) if (hasSeries != null)
{ {
saveItemStatement.TryBind("@SeriesId", hasSeries.SeriesId); saveItemStatement.TryBind("@SeriesId", hasSeries.SeriesId);
saveItemStatement.TryBind("@SeriesSortName", hasSeries.SeriesSortName);
saveItemStatement.TryBind("@SeriesPresentationUniqueKey", hasSeries.SeriesPresentationUniqueKey); saveItemStatement.TryBind("@SeriesPresentationUniqueKey", hasSeries.SeriesPresentationUniqueKey);
} }
else else
{ {
saveItemStatement.TryBindNull("@SeriesId"); saveItemStatement.TryBindNull("@SeriesId");
saveItemStatement.TryBindNull("@SeriesSortName");
saveItemStatement.TryBindNull("@SeriesPresentationUniqueKey"); saveItemStatement.TryBindNull("@SeriesPresentationUniqueKey");
} }
@ -1290,22 +1274,10 @@ namespace Emby.Server.Implementations.Data
{ {
return false; return false;
} }
if (type == typeof(Year))
{
return false;
}
if (type == typeof(Book))
{
return false;
}
if (type == typeof(Person)) if (type == typeof(Person))
{ {
return false; return false;
} }
if (type == typeof(RecordingGroup))
{
return false;
}
if (type == typeof(Channel)) if (type == typeof(Channel))
{ {
return false; return false;
@ -1339,31 +1311,42 @@ namespace Emby.Server.Implementations.Data
return false; return false;
} }
} }
if (_config.Configuration.SkipDeserializationForPrograms)
if (type == typeof(Year))
{ {
if (type == typeof(LiveTvProgram)) return false;
{
return false;
}
} }
if (type == typeof(Book))
{
return false;
}
if (type == typeof(RecordingGroup))
{
return false;
}
if (type == typeof(LiveTvProgram))
{
return false;
}
if (type == typeof(LiveTvAudioRecording))
{
return false;
}
if (type == typeof(AudioPodcast))
{
return false;
}
if (type == typeof(AudioBook))
{
return false;
}
if (_config.Configuration.SkipDeserializationForAudio) if (_config.Configuration.SkipDeserializationForAudio)
{ {
if (type == typeof(Audio)) if (type == typeof(Audio))
{ {
return false; return false;
} }
if (type == typeof(LiveTvAudioRecording))
{
return false;
}
if (type == typeof(AudioPodcast))
{
return false;
}
if (type == typeof(AudioBook))
{
return false;
}
if (type == typeof(MusicAlbum)) if (type == typeof(MusicAlbum))
{ {
return false; return false;
@ -1609,15 +1592,6 @@ namespace Emby.Server.Implementations.Data
} }
index++; index++;
if (query.HasField(ItemFields.OfficialRatingDescription))
{
if (!reader.IsDBNull(index))
{
item.OfficialRatingDescription = reader.GetString(index);
}
index++;
}
if (query.HasField(ItemFields.HomePageUrl)) if (query.HasField(ItemFields.HomePageUrl))
{ {
if (!reader.IsDBNull(index)) if (!reader.IsDBNull(index))
@ -1803,15 +1777,6 @@ namespace Emby.Server.Implementations.Data
} }
index++; index++;
if (query.HasField(ItemFields.CriticRatingSummary))
{
if (!reader.IsDBNull(index))
{
item.CriticRatingSummary = reader.GetString(index);
}
index++;
}
if (!reader.IsDBNull(index)) if (!reader.IsDBNull(index))
{ {
item.IsVirtualItem = reader.GetBoolean(index); item.IsVirtualItem = reader.GetBoolean(index);
@ -1856,15 +1821,6 @@ namespace Emby.Server.Implementations.Data
} }
index++; index++;
if (hasSeries != null)
{
if (!reader.IsDBNull(index))
{
hasSeries.SeriesSortName = reader.GetString(index);
}
}
index++;
if (!reader.IsDBNull(index)) if (!reader.IsDBNull(index))
{ {
item.PresentationUniqueKey = reader.GetString(index); item.PresentationUniqueKey = reader.GetString(index);
@ -2893,6 +2849,10 @@ namespace Emby.Server.Implementations.Data
{ {
return new Tuple<string, bool>("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)", false); return new Tuple<string, bool>("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)", false);
} }
if (string.Equals(name, ItemSortBy.SeriesSortName, StringComparison.OrdinalIgnoreCase))
{
return new Tuple<string, bool>("(Select SortName from TypedBaseItems where B.Guid=A.SeriesId)", false);
}
return new Tuple<string, bool>(name, false); return new Tuple<string, bool>(name, false);
} }
@ -4100,27 +4060,6 @@ namespace Emby.Server.Implementations.Data
whereClauses.Add("ProductionYear in (" + val + ")"); whereClauses.Add("ProductionYear in (" + val + ")");
} }
if (query.LocationTypes.Length == 1)
{
if (query.LocationTypes[0] == LocationType.Virtual && _config.Configuration.SchemaVersion >= 90)
{
query.IsVirtualItem = true;
}
else
{
whereClauses.Add("LocationType=@LocationType");
if (statement != null)
{
statement.TryBind("@LocationType", query.LocationTypes[0].ToString());
}
}
}
else if (query.LocationTypes.Length > 1)
{
var val = string.Join(",", query.LocationTypes.Select(i => "'" + i + "'").ToArray());
whereClauses.Add("LocationType in (" + val + ")");
}
if (query.IsVirtualItem.HasValue) if (query.IsVirtualItem.HasValue)
{ {
whereClauses.Add("IsVirtualItem=@IsVirtualItem"); whereClauses.Add("IsVirtualItem=@IsVirtualItem");

View File

@ -499,7 +499,7 @@ namespace Emby.Server.Implementations.Dto
if (fields.Contains(ItemFields.BasicSyncInfo) || fields.Contains(ItemFields.SyncInfo)) if (fields.Contains(ItemFields.BasicSyncInfo) || fields.Contains(ItemFields.SyncInfo))
{ {
var userCanSync = user != null && user.Policy.EnableSync; var userCanSync = user != null && user.Policy.EnableContentDownloading;
if (userCanSync && _syncManager.SupportsSync(item)) if (userCanSync && _syncManager.SupportsSync(item))
{ {
dto.SupportsSync = true; dto.SupportsSync = true;
@ -967,11 +967,6 @@ namespace Emby.Server.Implementations.Dto
dto.CriticRating = item.CriticRating; dto.CriticRating = item.CriticRating;
if (fields.Contains(ItemFields.CriticRatingSummary))
{
dto.CriticRatingSummary = item.CriticRatingSummary;
}
var hasTrailers = item as IHasTrailers; var hasTrailers = item as IHasTrailers;
if (hasTrailers != null) if (hasTrailers != null)
{ {

View File

@ -352,7 +352,7 @@ namespace Emby.Server.Implementations.FileOrganization
_libraryMonitor.ReportFileSystemChangeBeginning(path); _libraryMonitor.ReportFileSystemChangeBeginning(path);
var renameRelatedFiles = !hasRenamedFiles && var renameRelatedFiles = !hasRenamedFiles &&
string.Equals(Path.GetDirectoryName(path), Path.GetDirectoryName(result.TargetPath), StringComparison.OrdinalIgnoreCase); string.Equals(_fileSystem.GetDirectoryName(path), _fileSystem.GetDirectoryName(result.TargetPath), StringComparison.OrdinalIgnoreCase);
if (renameRelatedFiles) if (renameRelatedFiles)
{ {
@ -432,7 +432,7 @@ namespace Emby.Server.Implementations.FileOrganization
// Now find other files // Now find other files
var originalFilenameWithoutExtension = Path.GetFileNameWithoutExtension(path); var originalFilenameWithoutExtension = Path.GetFileNameWithoutExtension(path);
var directory = Path.GetDirectoryName(path); var directory = _fileSystem.GetDirectoryName(path);
if (!string.IsNullOrWhiteSpace(originalFilenameWithoutExtension) && !string.IsNullOrWhiteSpace(directory)) if (!string.IsNullOrWhiteSpace(originalFilenameWithoutExtension) && !string.IsNullOrWhiteSpace(directory))
{ {
@ -445,7 +445,7 @@ namespace Emby.Server.Implementations.FileOrganization
foreach (var file in files) foreach (var file in files)
{ {
directory = Path.GetDirectoryName(file); directory = _fileSystem.GetDirectoryName(file);
var filename = Path.GetFileName(file); var filename = Path.GetFileName(file);
filename = filename.Replace(originalFilenameWithoutExtension, targetFilenameWithoutExtension, filename = filename.Replace(originalFilenameWithoutExtension, targetFilenameWithoutExtension,
@ -470,7 +470,7 @@ namespace Emby.Server.Implementations.FileOrganization
return new List<string>(); return new List<string>();
} }
var episodePaths = series.GetRecursiveChildren() var episodePaths = series.GetRecursiveChildren(i => i is Episode)
.OfType<Episode>() .OfType<Episode>()
.Where(i => .Where(i =>
{ {
@ -499,7 +499,7 @@ namespace Emby.Server.Implementations.FileOrganization
.Select(i => i.Path) .Select(i => i.Path)
.ToList(); .ToList();
var folder = Path.GetDirectoryName(targetPath); var folder = _fileSystem.GetDirectoryName(targetPath);
var targetFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(targetPath); var targetFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(targetPath);
try try
@ -529,7 +529,7 @@ namespace Emby.Server.Implementations.FileOrganization
_libraryMonitor.ReportFileSystemChangeBeginning(result.TargetPath); _libraryMonitor.ReportFileSystemChangeBeginning(result.TargetPath);
_fileSystem.CreateDirectory(Path.GetDirectoryName(result.TargetPath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(result.TargetPath));
var targetAlreadyExists = _fileSystem.FileExists(result.TargetPath); var targetAlreadyExists = _fileSystem.FileExists(result.TargetPath);

View File

@ -58,6 +58,7 @@ namespace Emby.Server.Implementations.HttpServer
Headers["Content-Type"] = contentType; Headers["Content-Type"] = contentType;
TotalContentLength = fileSystem.GetFileInfo(path).Length; TotalContentLength = fileSystem.GetFileInfo(path).Length;
Headers["Accept-Ranges"] = "bytes";
if (string.IsNullOrWhiteSpace(rangeHeader)) if (string.IsNullOrWhiteSpace(rangeHeader))
{ {
@ -66,7 +67,6 @@ namespace Emby.Server.Implementations.HttpServer
} }
else else
{ {
Headers["Accept-Ranges"] = "bytes";
StatusCode = HttpStatusCode.PartialContent; StatusCode = HttpStatusCode.PartialContent;
SetRangeValues(); SetRangeValues();
} }
@ -96,8 +96,12 @@ namespace Emby.Server.Implementations.HttpServer
RangeLength = 1 + RangeEnd - RangeStart; RangeLength = 1 + RangeEnd - RangeStart;
// Content-Length is the length of what we're serving, not the original content // Content-Length is the length of what we're serving, not the original content
Headers["Content-Length"] = RangeLength.ToString(UsCulture); var lengthString = RangeLength.ToString(UsCulture);
Headers["Content-Range"] = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength); Headers["Content-Length"] = lengthString;
var rangeString = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength);
Headers["Content-Range"] = rangeString;
Logger.Info("Setting range response values for {0}. RangeRequest: {1} Content-Length: {2}, Content-Range: {3}", Path, RangeHeader, lengthString, rangeString);
} }
/// <summary> /// <summary>

View File

@ -501,7 +501,7 @@ namespace Emby.Server.Implementations.HttpServer
private bool ShouldCompressResponse(IRequest requestContext, string contentType) private bool ShouldCompressResponse(IRequest requestContext, string contentType)
{ {
// It will take some work to support compression with byte range requests // It will take some work to support compression with byte range requests
if (!string.IsNullOrEmpty(requestContext.Headers.Get("Range"))) if (!string.IsNullOrWhiteSpace(requestContext.Headers.Get("Range")))
{ {
return false; return false;
} }
@ -566,7 +566,7 @@ namespace Emby.Server.Implementations.HttpServer
}; };
} }
if (!string.IsNullOrEmpty(rangeHeader)) if (!string.IsNullOrWhiteSpace(rangeHeader))
{ {
var stream = await factoryFn().ConfigureAwait(false); var stream = await factoryFn().ConfigureAwait(false);
@ -621,6 +621,7 @@ namespace Emby.Server.Implementations.HttpServer
responseHeaders["Content-Encoding"] = requestedCompressionType; responseHeaders["Content-Encoding"] = requestedCompressionType;
} }
responseHeaders["Vary"] = "Accept-Encoding";
responseHeaders["Content-Length"] = content.Length.ToString(UsCulture); responseHeaders["Content-Length"] = content.Length.ToString(UsCulture);
if (isHeadRequest) if (isHeadRequest)

View File

@ -189,10 +189,15 @@ namespace Emby.Server.Implementations.HttpServer
private async Task CopyToInternalAsync(Stream source, Stream destination, long copyLength) private async Task CopyToInternalAsync(Stream source, Stream destination, long copyLength)
{ {
var array = new byte[BufferSize]; var array = new byte[BufferSize];
int count; int bytesRead;
while ((count = await source.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0) while ((bytesRead = await source.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0)
{ {
var bytesToCopy = Math.Min(count, copyLength); if (bytesRead == 0)
{
break;
}
var bytesToCopy = Math.Min(bytesRead, copyLength);
await destination.WriteAsync(array, 0, Convert.ToInt32(bytesToCopy)).ConfigureAwait(false); await destination.WriteAsync(array, 0, Convert.ToInt32(bytesToCopy)).ConfigureAwait(false);

View File

@ -26,8 +26,8 @@ namespace Emby.Server.Implementations.HttpServer
public void FilterResponse(IRequest req, IResponse res, object dto) public void FilterResponse(IRequest req, IResponse res, object dto)
{ {
// Try to prevent compatibility view // Try to prevent compatibility view
res.AddHeader("X-UA-Compatible", "IE=Edge"); //res.AddHeader("X-UA-Compatible", "IE=Edge");
res.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization"); res.AddHeader("Access-Control-Allow-Headers", "Accept, Accept-Language, Authorization, Cache-Control, Content-Disposition, Content-Encoding, Content-Language, Content-Length, Content-MD5, Content-Range, Content-Type, Date, Host, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, Origin, OriginToken, Pragma, Range, Slug, Transfer-Encoding, Want-Digest, X-MediaBrowser-Token, X-Emby-Authorization");
res.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS"); res.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS");
res.AddHeader("Access-Control-Allow-Origin", "*"); res.AddHeader("Access-Control-Allow-Origin", "*");
@ -46,8 +46,6 @@ namespace Emby.Server.Implementations.HttpServer
} }
} }
var vary = "Accept-Encoding";
var hasHeaders = dto as IHasHeaders; var hasHeaders = dto as IHasHeaders;
var sharpResponse = res as WebSocketSharpResponse; var sharpResponse = res as WebSocketSharpResponse;
@ -86,23 +84,9 @@ namespace Emby.Server.Implementations.HttpServer
} }
} }
} }
string hasHeadersVary;
if (hasHeaders.Headers.TryGetValue("Vary", out hasHeadersVary))
{
vary = hasHeadersVary;
}
hasHeaders.Headers["Vary"] = vary;
} }
//res.KeepAlive = false; //res.KeepAlive = false;
// Per Google PageSpeed
// This instructs the proxies to cache two versions of the resource: one compressed, and one uncompressed.
// The correct version of the resource is delivered based on the client request header.
// This is a good choice for applications that are singly homed and depend on public proxies for user locality.
res.AddHeader("Vary", vary);
} }
/// <summary> /// <summary>

View File

@ -207,7 +207,7 @@ namespace Emby.Server.Implementations.IO
{ {
item = LibraryManager.FindByPath(path, null); item = LibraryManager.FindByPath(path, null);
path = System.IO.Path.GetDirectoryName(path); path = _fileSystem.GetDirectoryName(path);
} }
if (item != null) if (item != null)

View File

@ -139,7 +139,7 @@ namespace Emby.Server.Implementations.Images
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var outputPathWithoutExtension = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid().ToString("N")); var outputPathWithoutExtension = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid().ToString("N"));
FileSystem.CreateDirectory(Path.GetDirectoryName(outputPathWithoutExtension)); FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPathWithoutExtension));
string outputPath = await CreateImage(item, itemsWithImages, outputPathWithoutExtension, imageType, 0).ConfigureAwait(false); string outputPath = await CreateImage(item, itemsWithImages, outputPathWithoutExtension, imageType, 0).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(outputPath)) if (string.IsNullOrWhiteSpace(outputPath))
@ -205,7 +205,7 @@ namespace Emby.Server.Implementations.Images
private async Task<string> CreateCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height) private async Task<string> CreateCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height)
{ {
FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPath));
var options = new ImageCollageOptions var options = new ImageCollageOptions
{ {

View File

@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.Library
{ {
if (parent == null) if (parent == null)
{ {
var parentFolderName = Path.GetFileName(Path.GetDirectoryName(path)); var parentFolderName = Path.GetFileName(_fileSystem.GetDirectoryName(path));
if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
{ {

View File

@ -1962,8 +1962,34 @@ namespace Emby.Server.Implementations.Library
return new List<Folder>(); return new List<Folder>();
} }
return GetUserRootFolder().Children return GetCollectionFoldersInternal(item, GetUserRootFolder().Children.OfType<Folder>().ToList());
.OfType<Folder>() }
public List<Folder> GetCollectionFolders(BaseItem item, List<Folder> allUserRootChildren)
{
while (item != null)
{
var parent = item.GetParent();
if (parent == null || parent is AggregateFolder)
{
break;
}
item = parent;
}
if (item == null)
{
return new List<Folder>();
}
return GetCollectionFoldersInternal(item, allUserRootChildren);
}
private List<Folder> GetCollectionFoldersInternal(BaseItem item, List<Folder> allUserRootChildren)
{
return allUserRootChildren
.Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path, StringComparer.OrdinalIgnoreCase)) .Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path, StringComparer.OrdinalIgnoreCase))
.ToList(); .ToList();
} }
@ -2126,7 +2152,8 @@ namespace Emby.Server.Implementations.Library
// Not sure why this is necessary but need to figure it out // Not sure why this is necessary but need to figure it out
// View images are not getting utilized without this // View images are not getting utilized without this
ForceSave = true ForceSave = true
});
}, RefreshPriority.Normal);
} }
return item; return item;
@ -2188,7 +2215,8 @@ namespace Emby.Server.Implementations.Library
{ {
// Need to force save to increment DateLastSaved // Need to force save to increment DateLastSaved
ForceSave = true ForceSave = true
});
}, RefreshPriority.Normal);
} }
return item; return item;
@ -2252,7 +2280,8 @@ namespace Emby.Server.Implementations.Library
{ {
// Need to force save to increment DateLastSaved // Need to force save to increment DateLastSaved
ForceSave = true ForceSave = true
});
}, RefreshPriority.Normal);
} }
return item; return item;
@ -2328,7 +2357,7 @@ namespace Emby.Server.Implementations.Library
{ {
// Need to force save to increment DateLastSaved // Need to force save to increment DateLastSaved
ForceSave = true ForceSave = true
}); }, RefreshPriority.Normal);
} }
return item; return item;

View File

@ -5,6 +5,7 @@ using MediaBrowser.Controller.Playlists;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using MediaBrowser.Model.Querying;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {
@ -27,53 +28,17 @@ namespace Emby.Server.Implementations.Library
return list.Concat(GetInstantMixFromGenres(item.Genres, user)); return list.Concat(GetInstantMixFromGenres(item.Genres, user));
} }
public IEnumerable<Audio> GetInstantMixFromArtist(MusicArtist artist, User user) public IEnumerable<Audio> GetInstantMixFromArtist(MusicArtist item, User user)
{ {
var genres = user.RootFolder return GetInstantMixFromGenres(item.Genres, user);
.GetRecursiveChildren(user, new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Audio).Name }
})
.Cast<Audio>()
.Where(i => i.HasAnyArtist(artist.Name))
.SelectMany(i => i.Genres)
.Concat(artist.Genres)
.Distinct(StringComparer.OrdinalIgnoreCase);
return GetInstantMixFromGenres(genres, user);
} }
public IEnumerable<Audio> GetInstantMixFromAlbum(MusicAlbum item, User user) public IEnumerable<Audio> GetInstantMixFromAlbum(MusicAlbum item, User user)
{ {
var genres = item return GetInstantMixFromGenres(item.Genres, user);
.GetRecursiveChildren(user, new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Audio).Name }
})
.Cast<Audio>()
.SelectMany(i => i.Genres)
.Concat(item.Genres)
.DistinctNames();
return GetInstantMixFromGenres(genres, user);
} }
public IEnumerable<Audio> GetInstantMixFromFolder(Folder item, User user) public IEnumerable<Audio> GetInstantMixFromFolder(Folder item, User user)
{
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);
}
public IEnumerable<Audio> GetInstantMixFromPlaylist(Playlist item, User user)
{ {
var genres = item var genres = item
.GetRecursiveChildren(user, new InternalItemsQuery(user) .GetRecursiveChildren(user, new InternalItemsQuery(user)
@ -88,28 +53,42 @@ namespace Emby.Server.Implementations.Library
return GetInstantMixFromGenres(genres, user); return GetInstantMixFromGenres(genres, user);
} }
public IEnumerable<Audio> GetInstantMixFromPlaylist(Playlist item, User user)
{
return GetInstantMixFromGenres(item.Genres, user);
}
public IEnumerable<Audio> GetInstantMixFromGenres(IEnumerable<string> genres, User user) public IEnumerable<Audio> GetInstantMixFromGenres(IEnumerable<string> genres, User user)
{ {
var genreList = genres.ToList(); var genreIds = genres.DistinctNames().Select(i =>
{
try
{
return _libraryManager.GetMusicGenre(i).Id.ToString("N");
}
catch
{
return null;
}
var inputItems = _libraryManager.GetItemList(new InternalItemsQuery(user) }).Where(i => i != null);
return GetInstantMixFromGenreIds(genreIds, user);
}
public IEnumerable<Audio> GetInstantMixFromGenreIds(IEnumerable<string> genreIds, User user)
{
return _libraryManager.GetItemList(new InternalItemsQuery(user)
{ {
IncludeItemTypes = new[] { typeof(Audio).Name }, IncludeItemTypes = new[] { typeof(Audio).Name },
Genres = genreList.ToArray() GenreIds = genreIds.ToArray(),
}); Limit = 200,
var genresDictionary = genreList.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); SortBy = new[] { ItemSortBy.Random }
return inputItems }).Cast<Audio>();
.Cast<Audio>()
.Select(i => new Tuple<Audio, int>(i, i.Genres.Count(genresDictionary.ContainsKey)))
.OrderByDescending(i => i.Item2)
.ThenBy(i => Guid.NewGuid())
.Select(i => i.Item1)
.Take(200)
.OrderBy(i => Guid.NewGuid());
} }
public IEnumerable<Audio> GetInstantMixFromItem(BaseItem item, User user) public IEnumerable<Audio> GetInstantMixFromItem(BaseItem item, User user)
@ -117,7 +96,7 @@ namespace Emby.Server.Implementations.Library
var genre = item as MusicGenre; var genre = item as MusicGenre;
if (genre != null) if (genre != null)
{ {
return GetInstantMixFromGenres(new[] { item.Name }, user); return GetInstantMixFromGenreIds(new[] { item.Id.ToString("N") }, user);
} }
var playlist = item as Playlist; var playlist = item as Playlist;

View File

@ -6,6 +6,7 @@ using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.IO;
namespace Emby.Server.Implementations.Library.Resolvers namespace Emby.Server.Implementations.Library.Resolvers
{ {
@ -13,11 +14,13 @@ namespace Emby.Server.Implementations.Library.Resolvers
{ {
private readonly IImageProcessor _imageProcessor; private readonly IImageProcessor _imageProcessor;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IFileSystem _fileSystem;
public PhotoResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager) public PhotoResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager, IFileSystem fileSystem)
{ {
_imageProcessor = imageProcessor; _imageProcessor = imageProcessor;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_fileSystem = fileSystem;
} }
/// <summary> /// <summary>
@ -41,7 +44,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
var filename = Path.GetFileNameWithoutExtension(args.Path); var filename = Path.GetFileNameWithoutExtension(args.Path);
// Make sure the image doesn't belong to a video file // Make sure the image doesn't belong to a video file
if (args.DirectoryService.GetFilePaths(Path.GetDirectoryName(args.Path)).Any(i => IsOwnedByMedia(args.GetLibraryOptions(), i, filename))) if (args.DirectoryService.GetFilePaths(_fileSystem.GetDirectoryName(args.Path)).Any(i => IsOwnedByMedia(args.GetLibraryOptions(), i, filename)))
{ {
return null; return null;
} }

View File

@ -57,7 +57,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
{ {
episode.SeriesId = series.Id; episode.SeriesId = series.Id;
episode.SeriesName = series.Name; episode.SeriesName = series.Name;
episode.SeriesSortName = series.SortName;
} }
if (season != null) if (season != null)
{ {

View File

@ -44,7 +44,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
{ {
IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(args.Path, true, true).SeasonNumber, IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(args.Path, true, true).SeasonNumber,
SeriesId = series.Id, SeriesId = series.Id,
SeriesSortName = series.SortName,
SeriesName = series.Name SeriesName = series.Name
}; };

View File

@ -165,7 +165,16 @@ namespace Emby.Server.Implementations.Library
ExcludeItemTypes = excludeItemTypes.ToArray(), ExcludeItemTypes = excludeItemTypes.ToArray(),
IncludeItemTypes = includeItemTypes.ToArray(), IncludeItemTypes = includeItemTypes.ToArray(),
Limit = query.Limit, Limit = query.Limit,
IncludeItemsByName = true IncludeItemsByName = string.IsNullOrWhiteSpace(query.ParentId),
ParentId = string.IsNullOrWhiteSpace(query.ParentId) ? (Guid?)null : new Guid(query.ParentId),
SortBy = new[] { ItemSortBy.SortName },
Recursive = true,
IsKids = query.IsKids,
IsMovie = query.IsMovie,
IsNews = query.IsNews,
IsSeries = query.IsSeries,
IsSports = query.IsSports
}); });
// Add search hints based on item name // Add search hints based on item name

View File

@ -942,7 +942,8 @@ namespace Emby.Server.Implementations.Library
{ {
return new UserPolicy return new UserPolicy
{ {
EnableSync = true EnableContentDownloading = true,
EnableSyncTranscoding = true
}; };
} }
@ -964,7 +965,7 @@ namespace Emby.Server.Implementations.Library
var path = GetPolifyFilePath(user); var path = GetPolifyFilePath(user);
_fileSystem.CreateDirectory(Path.GetDirectoryName(path)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
lock (_policySyncLock) lock (_policySyncLock)
{ {
@ -1051,7 +1052,7 @@ namespace Emby.Server.Implementations.Library
config = _jsonSerializer.DeserializeFromString<UserConfiguration>(json); config = _jsonSerializer.DeserializeFromString<UserConfiguration>(json);
} }
_fileSystem.CreateDirectory(Path.GetDirectoryName(path)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
lock (_configSyncLock) lock (_configSyncLock)
{ {

View File

@ -422,7 +422,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{ {
if (!string.IsNullOrWhiteSpace(epgChannel.Name)) if (!string.IsNullOrWhiteSpace(epgChannel.Name))
{ {
tunerChannel.Name = epgChannel.Name; //tunerChannel.Name = epgChannel.Name;
} }
if (!string.IsNullOrWhiteSpace(epgChannel.ImageUrl)) if (!string.IsNullOrWhiteSpace(epgChannel.ImageUrl))
{ {
@ -1231,7 +1231,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
RequiresOpening = false, RequiresOpening = false,
RequiresClosing = false, RequiresClosing = false,
Protocol = MediaBrowser.Model.MediaInfo.MediaProtocol.Http, Protocol = MediaBrowser.Model.MediaInfo.MediaProtocol.Http,
BufferMs = 0 BufferMs = 0,
IgnoreDts = true
}; };
var isAudio = false; var isAudio = false;
@ -1496,7 +1497,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_libraryManager.RegisterIgnoredPath(recordPath); _libraryManager.RegisterIgnoredPath(recordPath);
_libraryMonitor.ReportFileSystemChangeBeginning(recordPath); _libraryMonitor.ReportFileSystemChangeBeginning(recordPath);
_fileSystem.CreateDirectory(Path.GetDirectoryName(recordPath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(recordPath));
activeRecordingInfo.Path = recordPath; activeRecordingInfo.Path = recordPath;
var duration = recordingEndDate - DateTime.UtcNow; var duration = recordingEndDate - DateTime.UtcNow;
@ -1516,8 +1517,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
EnforceKeepUpTo(timer, seriesPath); EnforceKeepUpTo(timer, seriesPath);
}; };
await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken) await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken).ConfigureAwait(false);
.ConfigureAwait(false);
recordingStatus = RecordingStatus.Completed; recordingStatus = RecordingStatus.Completed;
_logger.Info("Recording completed: {0}", recordPath); _logger.Info("Recording completed: {0}", recordPath);
@ -1725,7 +1725,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
while (FileExists(path, timerId)) while (FileExists(path, timerId))
{ {
var parent = Path.GetDirectoryName(originalPath); var parent = _fileSystem.GetDirectoryName(originalPath);
var name = Path.GetFileNameWithoutExtension(originalPath); var name = Path.GetFileNameWithoutExtension(originalPath);
name += "-" + index.ToString(CultureInfo.InvariantCulture); name += "-" + index.ToString(CultureInfo.InvariantCulture);
@ -1765,7 +1765,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
if (regInfo.IsValid) if (regInfo.IsValid)
{ {
return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, config, _httpClient, _processFactory); return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, config, _httpClient, _processFactory, _config);
} }
} }
@ -1892,7 +1892,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return; return;
} }
var imageSavePath = Path.Combine(Path.GetDirectoryName(recordingPath), imageSaveFilenameWithoutExtension); var imageSavePath = Path.Combine(_fileSystem.GetDirectoryName(recordingPath), imageSaveFilenameWithoutExtension);
// preserve original image extension // preserve original image extension
imageSavePath = Path.ChangeExtension(imageSavePath, Path.GetExtension(image.Path)); imageSavePath = Path.ChangeExtension(imageSavePath, Path.GetExtension(image.Path));
@ -2155,11 +2155,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
writer.WriteElementString("mpaa", item.OfficialRating); writer.WriteElementString("mpaa", item.OfficialRating);
} }
if (!string.IsNullOrEmpty(item.OfficialRatingDescription))
{
writer.WriteElementString("mpaadescription", item.OfficialRatingDescription);
}
var overview = (item.Overview ?? string.Empty) var overview = (item.Overview ?? string.Empty)
.StripHtml() .StripHtml()
.Replace("&quot;", "'"); .Replace("&quot;", "'");
@ -2251,11 +2246,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
writer.WriteElementString("criticrating", item.CriticRating.Value.ToString(CultureInfo.InvariantCulture)); writer.WriteElementString("criticrating", item.CriticRating.Value.ToString(CultureInfo.InvariantCulture));
} }
if (!string.IsNullOrEmpty(item.CriticRatingSummary))
{
writer.WriteElementString("criticratingsummary", item.CriticRatingSummary);
}
if (!string.IsNullOrWhiteSpace(item.Tagline)) if (!string.IsNullOrWhiteSpace(item.Tagline))
{ {
writer.WriteElementString("tagline", item.Tagline); writer.WriteElementString("tagline", item.Tagline);
@ -2550,7 +2540,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
private void SaveEpgDataForChannel(string channelId, List<ProgramInfo> epgData) private void SaveEpgDataForChannel(string channelId, List<ProgramInfo> epgData)
{ {
var path = GetChannelEpgCachePath(channelId); var path = GetChannelEpgCachePath(channelId);
_fileSystem.CreateDirectory(Path.GetDirectoryName(path)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
lock (_epgLock) lock (_epgLock)
{ {
_jsonSerializer.SerializeToFile(epgData, path); _jsonSerializer.SerializeToFile(epgData, path);

View File

@ -11,14 +11,16 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Common.IO; using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Diagnostics;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
using MediaBrowser.Common.Configuration;
namespace Emby.Server.Implementations.LiveTv.EmbyTV namespace Emby.Server.Implementations.LiveTv.EmbyTV
{ {
@ -37,8 +39,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
private readonly IProcessFactory _processFactory; private readonly IProcessFactory _processFactory;
private readonly IJsonSerializer _json; private readonly IJsonSerializer _json;
private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>(); private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>();
private readonly IServerConfigurationManager _config;
public EncodedRecorder(ILogger logger, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IServerApplicationPaths appPaths, IJsonSerializer json, LiveTvOptions liveTvOptions, IHttpClient httpClient, IProcessFactory processFactory) public EncodedRecorder(ILogger logger, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IServerApplicationPaths appPaths, IJsonSerializer json, LiveTvOptions liveTvOptions, IHttpClient httpClient, IProcessFactory processFactory, IServerConfigurationManager config)
{ {
_logger = logger; _logger = logger;
_fileSystem = fileSystem; _fileSystem = fileSystem;
@ -48,6 +51,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_liveTvOptions = liveTvOptions; _liveTvOptions = liveTvOptions;
_httpClient = httpClient; _httpClient = httpClient;
_processFactory = processFactory; _processFactory = processFactory;
_config = config;
} }
private string OutputFormat private string OutputFormat
@ -76,23 +80,35 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
public string GetOutputPath(MediaSourceInfo mediaSource, string targetFile) public string GetOutputPath(MediaSourceInfo mediaSource, string targetFile)
{ {
return Path.ChangeExtension(targetFile, "." + OutputFormat); var extension = OutputFormat;
if (string.Equals(extension, "mpegts", StringComparison.OrdinalIgnoreCase))
{
extension = "ts";
}
return Path.ChangeExtension(targetFile, "." + extension);
} }
public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
{ {
var durationToken = new CancellationTokenSource(duration); //var durationToken = new CancellationTokenSource(duration);
cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; //cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
await RecordFromFile(mediaSource, mediaSource.Path, targetFile, duration, onStarted, cancellationToken).ConfigureAwait(false); await RecordFromFile(mediaSource, mediaSource.Path, targetFile, duration, onStarted, cancellationToken).ConfigureAwait(false);
_logger.Info("Recording completed to file {0}", targetFile); _logger.Info("Recording completed to file {0}", targetFile);
} }
private EncodingOptions GetEncodingOptions()
{
return _config.GetConfiguration<EncodingOptions>("encoding");
}
private Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) private Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
{ {
_targetPath = targetFile; _targetPath = targetFile;
_fileSystem.CreateDirectory(Path.GetDirectoryName(targetFile)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(targetFile));
var process = _processFactory.Create(new ProcessOptions var process = _processFactory.Create(new ProcessOptions
{ {
@ -118,7 +134,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_logger.Info(commandLineLogMessage); _logger.Info(commandLineLogMessage);
var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "record-transcode-" + Guid.NewGuid() + ".txt"); var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "record-transcode-" + Guid.NewGuid() + ".txt");
_fileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(logFilePath));
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
_logFileStream = _fileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true); _logFileStream = _fileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true);
@ -162,30 +178,34 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
} }
var durationParam = " -t " + _mediaEncoder.GetTimeParameter(duration.Ticks); var durationParam = " -t " + _mediaEncoder.GetTimeParameter(duration.Ticks);
var inputModifiers = "-fflags +genpts -async 1 -vsync -1";
var commandLineArgs = "-i \"{0}\"{5} {2} -map_metadata -1 -threads 0 {3}{4}{6} -y \"{1}\"";
long startTimeTicks = 0; var flags = new List<string>();
//if (mediaSource.DateLiveStreamOpened.HasValue) if (mediaSource.IgnoreDts)
//{ {
// var elapsed = DateTime.UtcNow - mediaSource.DateLiveStreamOpened.Value; flags.Add("+igndts");
// elapsed -= TimeSpan.FromSeconds(10); }
// if (elapsed.TotalSeconds >= 0) if (mediaSource.IgnoreIndex)
// { {
// startTimeTicks = elapsed.Ticks + startTimeTicks; flags.Add("+ignidx");
// } }
//}
var inputModifiers = "-async 1 -vsync -1";
if (flags.Count > 0)
{
inputModifiers += " -fflags " + string.Join("", flags.ToArray());
}
if (!string.IsNullOrWhiteSpace(GetEncodingOptions().HardwareAccelerationType))
{
inputModifiers += " -hwaccel auto";
}
if (mediaSource.ReadAtNativeFramerate) if (mediaSource.ReadAtNativeFramerate)
{ {
inputModifiers += " -re"; inputModifiers += " -re";
} }
if (startTimeTicks > 0)
{
inputModifiers = "-ss " + _mediaEncoder.GetTimeParameter(startTimeTicks) + " " + inputModifiers;
}
var analyzeDurationSeconds = 5; var analyzeDurationSeconds = 5;
var analyzeDuration = " -analyzeduration " + var analyzeDuration = " -analyzeduration " +
(analyzeDurationSeconds * 1000000).ToString(CultureInfo.InvariantCulture); (analyzeDurationSeconds * 1000000).ToString(CultureInfo.InvariantCulture);
@ -193,11 +213,20 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var subtitleArgs = CopySubtitles ? " -codec:s copy" : " -sn"; var subtitleArgs = CopySubtitles ? " -codec:s copy" : " -sn";
var outputParam = string.Equals(Path.GetExtension(targetFile), ".mp4", StringComparison.OrdinalIgnoreCase) ? //var outputParam = string.Equals(Path.GetExtension(targetFile), ".mp4", StringComparison.OrdinalIgnoreCase) ?
" -f mp4 -movflags frag_keyframe+empty_moov" : // " -f mp4 -movflags frag_keyframe+empty_moov" :
string.Empty; // string.Empty;
commandLineArgs = string.Format(commandLineArgs, inputTempFile, targetFile, videoArgs, GetAudioArgs(mediaSource), subtitleArgs, durationParam, outputParam); var outputParam = string.Empty;
var commandLineArgs = string.Format("-i \"{0}\"{5} {2} -map_metadata -1 -threads 0 {3}{4}{6} -y \"{1}\"",
inputTempFile,
targetFile,
videoArgs,
GetAudioArgs(mediaSource),
subtitleArgs,
durationParam,
outputParam);
return inputModifiers + " " + commandLineArgs; return inputModifiers + " " + commandLineArgs;
} }

View File

@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
} }
var file = _dataPath + ".json"; var file = _dataPath + ".json";
_fileSystem.CreateDirectory(Path.GetDirectoryName(file)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(file));
lock (_fileDataLock) lock (_fileDataLock)
{ {

View File

@ -86,7 +86,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
}).ConfigureAwait(false); }).ConfigureAwait(false);
_fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFile)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFile));
using (var stream = _fileSystem.OpenRead(tempFile)) using (var stream = _fileSystem.OpenRead(tempFile))
{ {

View File

@ -857,7 +857,8 @@ namespace Emby.Server.Implementations.LiveTv
_providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem) _providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem)
{ {
MetadataRefreshMode = metadataRefreshMode MetadataRefreshMode = metadataRefreshMode
});
}, RefreshPriority.Normal);
} }
return item.Id; return item.Id;
@ -1395,11 +1396,11 @@ namespace Emby.Server.Implementations.LiveTv
foreach (var program in newPrograms) foreach (var program in newPrograms)
{ {
_providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem)); _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.Low);
} }
foreach (var program in updatedPrograms) foreach (var program in updatedPrograms)
{ {
_providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem)); _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.Low);
} }
currentChannel.IsMovie = isMovie; currentChannel.IsMovie = isMovie;

View File

@ -420,7 +420,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
SupportsDirectPlay = false, SupportsDirectPlay = false,
SupportsDirectStream = true, SupportsDirectStream = true,
SupportsTranscoding = true, SupportsTranscoding = true,
IsInfiniteStream = true IsInfiniteStream = true,
IgnoreDts = true
}; };
mediaSource.InferTotalBitrate(); mediaSource.InferTotalBitrate();

View File

@ -29,6 +29,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
byte[] buffer = new byte[BufferSize]; byte[] buffer = new byte[BufferSize];
if (source == null)
{
throw new ArgumentNullException("source");
}
while (!cancellationToken.IsCancellationRequested) while (!cancellationToken.IsCancellationRequested)
{ {
var bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); var bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false);

View File

@ -29,15 +29,17 @@ namespace Emby.Server.Implementations.Logging
_logManager.Flush(); _logManager.Flush();
var path = Path.Combine(_appPaths.LogDirectoryPath, "unhandled_" + Guid.NewGuid() + ".txt"); var path = Path.Combine(_appPaths.LogDirectoryPath, "unhandled_" + Guid.NewGuid() + ".txt");
_fileSystem.CreateDirectory(Path.GetDirectoryName(path)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
var builder = LogHelper.GetLogMessage(ex); var builder = LogHelper.GetLogMessage(ex);
// Write to console just in case file logging fails // Write to console just in case file logging fails
_console.WriteLine("UnhandledException"); _console.WriteLine("UnhandledException");
_console.WriteLine(builder.ToString());
_fileSystem.WriteAllText(path, builder.ToString()); var logMessage = builder.ToString();
_console.WriteLine(logMessage);
_fileSystem.WriteAllText(path, logMessage);
} }
} }
} }

View File

@ -138,7 +138,7 @@ namespace Emby.Server.Implementations.MediaEncoder
var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, video.PlayableStreamFileNames); var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, video.PlayableStreamFileNames);
_fileSystem.CreateDirectory(Path.GetDirectoryName(path)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
var container = video.Container; var container = video.Container;

View File

@ -201,7 +201,8 @@ namespace Emby.Server.Implementations.Playlists
_providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem) _providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem)
{ {
ForceSave = true ForceSave = true
});
}, RefreshPriority.High);
} }
public async Task RemoveFromPlaylist(string playlistId, IEnumerable<string> entryIds) public async Task RemoveFromPlaylist(string playlistId, IEnumerable<string> entryIds)
@ -228,7 +229,8 @@ namespace Emby.Server.Implementations.Playlists
_providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem) _providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem)
{ {
ForceSave = true ForceSave = true
});
}, RefreshPriority.High);
} }
public async Task MoveItem(string playlistId, string entryId, int newIndex) public async Task MoveItem(string playlistId, string entryId, int newIndex)

View File

@ -136,7 +136,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
{ {
previouslyFailedImages.Add(key); previouslyFailedImages.Add(key);
var parentPath = Path.GetDirectoryName(failHistoryPath); var parentPath = _fileSystem.GetDirectoryName(failHistoryPath);
_fileSystem.CreateDirectory(parentPath); _fileSystem.CreateDirectory(parentPath);

View File

@ -193,7 +193,7 @@ namespace Emby.Server.Implementations.Security
} }
var licenseFile = Filename; var licenseFile = Filename;
_fileSystem.CreateDirectory(Path.GetDirectoryName(licenseFile)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(licenseFile));
lock (_fileLock) lock (_fileLock)
{ {
_fileSystem.WriteAllLines(licenseFile, lines); _fileSystem.WriteAllLines(licenseFile, lines);

View File

@ -129,7 +129,7 @@ namespace Emby.Server.Implementations.Session
public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken) public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken)
{ {
return Task.FromResult(true); return SendMessage("LibraryChanged", info, cancellationToken);
} }
public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken) public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken)

View File

@ -715,7 +715,8 @@ namespace Emby.Server.Implementations.Session
ClientName = session.Client, ClientName = session.Client,
DeviceId = session.DeviceId, DeviceId = session.DeviceId,
IsPaused = info.IsPaused, IsPaused = info.IsPaused,
PlaySessionId = info.PlaySessionId PlaySessionId = info.PlaySessionId,
IsAutomated = isAutomated
}, _logger); }, _logger);

View File

@ -22,7 +22,7 @@ namespace Emby.Server.Implementations.Sorting
{ {
var hasSeries = item as IHasSeries; var hasSeries = item as IHasSeries;
return hasSeries != null ? hasSeries.SeriesSortName : null; return hasSeries != null ? hasSeries.FindSeriesSortName() : null;
} }
/// <summary> /// <summary>

View File

@ -250,7 +250,7 @@ namespace Emby.Server.Implementations.Updates
}).ConfigureAwait(false); }).ConfigureAwait(false);
_fileSystem.CreateDirectory(Path.GetDirectoryName(PackageCachePath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(PackageCachePath));
_fileSystem.CopyFile(tempFile, PackageCachePath, true); _fileSystem.CopyFile(tempFile, PackageCachePath, true);
_lastPackageUpdateTime = DateTime.UtcNow; _lastPackageUpdateTime = DateTime.UtcNow;
@ -627,7 +627,7 @@ namespace Emby.Server.Implementations.Updates
// Success - move it to the real target // Success - move it to the real target
try try
{ {
_fileSystem.CreateDirectory(Path.GetDirectoryName(target)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(target));
_fileSystem.CopyFile(tempFile, target, true); _fileSystem.CopyFile(tempFile, target, true);
//If it is an archive - write out a version file so we know what it is //If it is an archive - write out a version file so we know what it is
if (isArchive) if (isArchive)

View File

@ -633,7 +633,7 @@ namespace MediaBrowser.Api
/// <param name="outputFilePath">The output file path.</param> /// <param name="outputFilePath">The output file path.</param>
private void DeleteHlsPartialStreamFiles(string outputFilePath) private void DeleteHlsPartialStreamFiles(string outputFilePath)
{ {
var directory = Path.GetDirectoryName(outputFilePath); var directory = _fileSystem.GetDirectoryName(outputFilePath);
var name = Path.GetFileNameWithoutExtension(outputFilePath); var name = Path.GetFileNameWithoutExtension(outputFilePath);
var filesToDelete = _fileSystem.GetFilePaths(directory) var filesToDelete = _fileSystem.GetFilePaths(directory)

View File

@ -66,7 +66,7 @@ namespace MediaBrowser.Api
return ResultFactory.GetOptimizedResult(Request, result); return ResultFactory.GetOptimizedResult(Request, result);
} }
protected void AssertCanUpdateUser(IAuthorizationContext authContext, IUserManager userManager, string userId) protected void AssertCanUpdateUser(IAuthorizationContext authContext, IUserManager userManager, string userId, bool restrictUserPreferences)
{ {
var auth = authContext.GetAuthorizationInfo(Request); var auth = authContext.GetAuthorizationInfo(Request);
@ -80,7 +80,7 @@ namespace MediaBrowser.Api
throw new SecurityException("Unauthorized access."); throw new SecurityException("Unauthorized access.");
} }
} }
else else if (restrictUserPreferences)
{ {
if (!authenticatedUser.Policy.EnableUserPreferenceAccess) if (!authenticatedUser.Policy.EnableUserPreferenceAccess)
{ {

View File

@ -98,7 +98,7 @@ namespace MediaBrowser.Api
[ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string SortBy { get; set; } public string SortBy { get; set; }
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; } public string Fields { get; set; }
/// <summary> /// <summary>
@ -145,7 +145,7 @@ namespace MediaBrowser.Api
[ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Filters { get; set; } public string Filters { get; set; }
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; } public string Fields { get; set; }
[ApiMember(Name = "ChannelIds", Description = "Optional. Specify one or more channel id's, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "ChannelIds", Description = "Optional. Specify one or more channel id's, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]

View File

@ -278,7 +278,7 @@ namespace MediaBrowser.Api
public object Get(GetParentPath request) public object Get(GetParentPath request)
{ {
var parent = Path.GetDirectoryName(request.Path); var parent = _fileSystem.GetDirectoryName(request.Path);
if (string.IsNullOrEmpty(parent)) if (string.IsNullOrEmpty(parent))
{ {

View File

@ -160,7 +160,7 @@ namespace MediaBrowser.Api.Images
private string GetThemeName(string path, string rootImagePath) private string GetThemeName(string path, string rootImagePath)
{ {
var parentName = Path.GetDirectoryName(path); var parentName = _fileSystem.GetDirectoryName(path);
if (string.Equals(parentName, rootImagePath, StringComparison.OrdinalIgnoreCase)) if (string.Equals(parentName, rootImagePath, StringComparison.OrdinalIgnoreCase))
{ {

View File

@ -427,7 +427,7 @@ namespace MediaBrowser.Api.Images
public void Post(PostUserImage request) public void Post(PostUserImage request)
{ {
var userId = GetPathValue(1); var userId = GetPathValue(1);
AssertCanUpdateUser(_authContext, _userManager, userId); AssertCanUpdateUser(_authContext, _userManager, userId, true);
request.Type = (ImageType)Enum.Parse(typeof(ImageType), GetPathValue(3), true); request.Type = (ImageType)Enum.Parse(typeof(ImageType), GetPathValue(3), true);
@ -462,7 +462,7 @@ namespace MediaBrowser.Api.Images
public void Delete(DeleteUserImage request) public void Delete(DeleteUserImage request)
{ {
var userId = request.Id; var userId = request.Id;
AssertCanUpdateUser(_authContext, _userManager, userId); AssertCanUpdateUser(_authContext, _userManager, userId, true);
var item = _userManager.GetUserById(userId); var item = _userManager.GetUserById(userId);

View File

@ -278,7 +278,7 @@ namespace MediaBrowser.Api.Images
var fullCachePath = GetFullCachePath(urlHash + "." + ext); var fullCachePath = GetFullCachePath(urlHash + "." + ext);
_fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(fullCachePath));
using (var stream = result.Content) using (var stream = result.Content)
{ {
using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
@ -287,7 +287,7 @@ namespace MediaBrowser.Api.Images
} }
} }
_fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(pointerCachePath));
_fileSystem.WriteAllText(pointerCachePath, fullCachePath); _fileSystem.WriteAllText(pointerCachePath, fullCachePath);
} }

View File

@ -299,7 +299,7 @@ namespace MediaBrowser.Api
var fullCachePath = GetFullCachePath(urlHash + "." + ext); var fullCachePath = GetFullCachePath(urlHash + "." + ext);
_fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(fullCachePath));
using (var stream = result.Content) using (var stream = result.Content)
{ {
using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
@ -308,7 +308,7 @@ namespace MediaBrowser.Api
} }
} }
_fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(pointerCachePath));
_fileSystem.WriteAllText(pointerCachePath, fullCachePath); _fileSystem.WriteAllText(pointerCachePath, fullCachePath);
} }

View File

@ -62,14 +62,7 @@ namespace MediaBrowser.Api
var options = GetRefreshOptions(request); var options = GetRefreshOptions(request);
if (item is Folder) _providerManager.QueueRefresh(item.Id, options, RefreshPriority.High);
{
_providerManager.QueueRefresh(item.Id, options);
}
else
{
_providerManager.RefreshFullItem(item, options, CancellationToken.None);
}
} }
private MetadataRefreshOptions GetRefreshOptions(BaseRefreshRequest request) private MetadataRefreshOptions GetRefreshOptions(BaseRefreshRequest request)

View File

@ -240,7 +240,6 @@ namespace MediaBrowser.Api
item.OriginalTitle = string.IsNullOrWhiteSpace(request.OriginalTitle) ? null : request.OriginalTitle; item.OriginalTitle = string.IsNullOrWhiteSpace(request.OriginalTitle) ? null : request.OriginalTitle;
item.CriticRating = request.CriticRating; item.CriticRating = request.CriticRating;
item.CriticRatingSummary = request.CriticRatingSummary;
item.DisplayMediaType = request.DisplayMediaType; item.DisplayMediaType = request.DisplayMediaType;
item.CommunityRating = request.CommunityRating; item.CommunityRating = request.CommunityRating;

View File

@ -98,7 +98,7 @@ namespace MediaBrowser.Api.LiveTv
/// Fields to return within the items, in addition to basic information /// Fields to return within the items, in addition to basic information
/// </summary> /// </summary>
/// <value>The fields.</value> /// <value>The fields.</value>
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; } public string Fields { get; set; }
[ApiMember(Name = "AddCurrentProgram", Description = "Optional. Adds current program info to each channel", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "AddCurrentProgram", Description = "Optional. Adds current program info to each channel", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
@ -189,7 +189,7 @@ namespace MediaBrowser.Api.LiveTv
/// Fields to return within the items, in addition to basic information /// Fields to return within the items, in addition to basic information
/// </summary> /// </summary>
/// <value>The fields.</value> /// <value>The fields.</value>
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; } public string Fields { get; set; }
public bool EnableTotalRecordCount { get; set; } public bool EnableTotalRecordCount { get; set; }
@ -251,7 +251,7 @@ namespace MediaBrowser.Api.LiveTv
/// Fields to return within the items, in addition to basic information /// Fields to return within the items, in addition to basic information
/// </summary> /// </summary>
/// <value>The fields.</value> /// <value>The fields.</value>
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; } public string Fields { get; set; }
public bool EnableTotalRecordCount { get; set; } public bool EnableTotalRecordCount { get; set; }
@ -399,7 +399,7 @@ namespace MediaBrowser.Api.LiveTv
/// Fields to return within the items, in addition to basic information /// Fields to return within the items, in addition to basic information
/// </summary> /// </summary>
/// <value>The fields.</value> /// <value>The fields.</value>
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; } public string Fields { get; set; }
public GetPrograms() public GetPrograms()
@ -459,7 +459,7 @@ namespace MediaBrowser.Api.LiveTv
/// Fields to return within the items, in addition to basic information /// Fields to return within the items, in addition to basic information
/// </summary> /// </summary>
/// <value>The fields.</value> /// <value>The fields.</value>
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; } public string Fields { get; set; }
[ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]

View File

@ -198,7 +198,7 @@ namespace MediaBrowser.Api.Playback
CancellationTokenSource cancellationTokenSource, CancellationTokenSource cancellationTokenSource,
string workingDirectory = null) string workingDirectory = null)
{ {
FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPath));
await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false); await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false);
@ -263,7 +263,7 @@ namespace MediaBrowser.Api.Playback
} }
var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, logFilePrefix + "-" + Guid.NewGuid() + ".txt"); var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, logFilePrefix + "-" + Guid.NewGuid() + ".txt");
FileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath)); FileSystem.CreateDirectory(FileSystem.GetDirectoryName(logFilePath));
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
state.LogFileStream = FileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true); state.LogFileStream = FileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true);
@ -315,8 +315,6 @@ namespace MediaBrowser.Api.Playback
StartThrottler(state, transcodingJob); StartThrottler(state, transcodingJob);
} }
ReportUsage(state);
return transcodingJob; return transcodingJob;
} }
@ -677,7 +675,8 @@ namespace MediaBrowser.Api.Playback
{ {
Request = request, Request = request,
RequestedUrl = url, RequestedUrl = url,
UserAgent = Request.UserAgent UserAgent = Request.UserAgent,
EnableDlnaHeaders = !string.IsNullOrWhiteSpace(request.Params)
}; };
var auth = AuthorizationContext.GetAuthorizationInfo(Request); var auth = AuthorizationContext.GetAuthorizationInfo(Request);
@ -720,6 +719,13 @@ namespace MediaBrowser.Api.Playback
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase); state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
//var primaryImage = item.GetImageInfo(ImageType.Primary, 0) ??
// item.Parents.Select(i => i.GetImageInfo(ImageType.Primary, 0)).FirstOrDefault(i => i != null);
//if (primaryImage != null)
//{
// state.AlbumCoverPath = primaryImage.Path;
//}
MediaSourceInfo mediaSource = null; MediaSourceInfo mediaSource = null;
if (string.IsNullOrWhiteSpace(request.LiveStreamId)) if (string.IsNullOrWhiteSpace(request.LiveStreamId))
{ {
@ -903,123 +909,6 @@ namespace MediaBrowser.Api.Playback
} }
} }
private async void ReportUsage(StreamState state)
{
try
{
await ReportUsageInternal(state).ConfigureAwait(false);
}
catch
{
}
}
private Task ReportUsageInternal(StreamState state)
{
if (!ServerConfigurationManager.Configuration.EnableAnonymousUsageReporting)
{
return Task.FromResult(true);
}
if (!MediaEncoder.IsDefaultEncoderPath)
{
return Task.FromResult(true);
}
return Task.FromResult(true);
//var dict = new Dictionary<string, string>();
//var outputAudio = GetAudioEncoder(state);
//if (!string.IsNullOrWhiteSpace(outputAudio))
//{
// dict["outputAudio"] = outputAudio;
//}
//var outputVideo = GetVideoEncoder(state);
//if (!string.IsNullOrWhiteSpace(outputVideo))
//{
// dict["outputVideo"] = outputVideo;
//}
//if (ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputAudio ?? string.Empty, StringComparer.OrdinalIgnoreCase) &&
// ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputVideo ?? string.Empty, StringComparer.OrdinalIgnoreCase))
//{
// return Task.FromResult(true);
//}
//dict["id"] = AppHost.SystemId;
//dict["type"] = state.VideoRequest == null ? "Audio" : "Video";
//var audioStream = state.AudioStream;
//if (audioStream != null && !string.IsNullOrWhiteSpace(audioStream.Codec))
//{
// dict["inputAudio"] = audioStream.Codec;
//}
//var videoStream = state.VideoStream;
//if (videoStream != null && !string.IsNullOrWhiteSpace(videoStream.Codec))
//{
// dict["inputVideo"] = videoStream.Codec;
//}
//var cert = GetType().Assembly.GetModules().First().GetSignerCertificate();
//if (cert != null)
//{
// dict["assemblySig"] = cert.GetCertHashString();
// dict["certSubject"] = cert.Subject ?? string.Empty;
// dict["certIssuer"] = cert.Issuer ?? string.Empty;
//}
//else
//{
// return Task.FromResult(true);
//}
//if (state.SupportedAudioCodecs.Count > 0)
//{
// dict["supportedAudioCodecs"] = string.Join(",", state.SupportedAudioCodecs.ToArray());
//}
//var auth = AuthorizationContext.GetAuthorizationInfo(Request);
//dict["appName"] = auth.Client ?? string.Empty;
//dict["appVersion"] = auth.Version ?? string.Empty;
//dict["device"] = auth.Device ?? string.Empty;
//dict["deviceId"] = auth.DeviceId ?? string.Empty;
//dict["context"] = "streaming";
////Logger.Info(JsonSerializer.SerializeToString(dict));
//if (!ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputAudio ?? string.Empty, StringComparer.OrdinalIgnoreCase))
//{
// var list = ServerConfigurationManager.Configuration.CodecsUsed.ToList();
// list.Add(outputAudio);
// ServerConfigurationManager.Configuration.CodecsUsed = list.ToArray();
//}
//if (!ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputVideo ?? string.Empty, StringComparer.OrdinalIgnoreCase))
//{
// var list = ServerConfigurationManager.Configuration.CodecsUsed.ToList();
// list.Add(outputVideo);
// ServerConfigurationManager.Configuration.CodecsUsed = list.ToArray();
//}
//ServerConfigurationManager.SaveConfiguration();
////Logger.Info(JsonSerializer.SerializeToString(dict));
//var options = new HttpRequestOptions()
//{
// Url = "https://mb3admin.com/admin/service/transcoding/report",
// CancellationToken = CancellationToken.None,
// LogRequest = false,
// LogErrors = false,
// BufferContent = false
//};
//options.RequestContent = JsonSerializer.SerializeToString(dict);
//options.RequestContentType = "application/json";
//return HttpClient.Post(options);
}
/// <summary> /// <summary>
/// Adds the dlna headers. /// Adds the dlna headers.
/// </summary> /// </summary>
@ -1029,6 +918,11 @@ namespace MediaBrowser.Api.Playback
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
protected void AddDlnaHeaders(StreamState state, IDictionary<string, string> responseHeaders, bool isStaticallyStreamed) protected void AddDlnaHeaders(StreamState state, IDictionary<string, string> responseHeaders, bool isStaticallyStreamed)
{ {
if (!state.EnableDlnaHeaders)
{
return;
}
var profile = state.DeviceProfile; var profile = state.DeviceProfile;
var transferMode = GetHeader("transferMode.dlna.org"); var transferMode = GetHeader("transferMode.dlna.org");

View File

@ -13,10 +13,7 @@ using System.IO;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Model.IO;
namespace MediaBrowser.Api.Playback.Hls namespace MediaBrowser.Api.Playback.Hls
{ {
@ -271,7 +268,7 @@ namespace MediaBrowser.Api.Playback.Hls
var useGenericSegmenter = true; var useGenericSegmenter = true;
if (useGenericSegmenter) if (useGenericSegmenter)
{ {
var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request); var outputTsArg = Path.Combine(FileSystem.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request);
var timeDeltaParam = String.Empty; var timeDeltaParam = String.Empty;

View File

@ -89,6 +89,7 @@ namespace MediaBrowser.Api.Playback.Hls
public string SegmentId { get; set; } public string SegmentId { get; set; }
} }
[Authenticated]
public class DynamicHlsService : BaseHlsService public class DynamicHlsService : BaseHlsService
{ {
@ -378,7 +379,7 @@ namespace MediaBrowser.Api.Playback.Hls
private static FileSystemMetadata GetLastTranscodingFile(string playlist, string segmentExtension, IFileSystem fileSystem) private static FileSystemMetadata GetLastTranscodingFile(string playlist, string segmentExtension, IFileSystem fileSystem)
{ {
var folder = Path.GetDirectoryName(playlist); var folder = fileSystem.GetDirectoryName(playlist);
var filePrefix = Path.GetFileNameWithoutExtension(playlist) ?? string.Empty; var filePrefix = Path.GetFileNameWithoutExtension(playlist) ?? string.Empty;
@ -415,7 +416,7 @@ namespace MediaBrowser.Api.Playback.Hls
private string GetSegmentPath(StreamState state, string playlist, int index) private string GetSegmentPath(StreamState state, string playlist, int index)
{ {
var folder = Path.GetDirectoryName(playlist); var folder = FileSystem.GetDirectoryName(playlist);
var filename = Path.GetFileNameWithoutExtension(playlist); var filename = Path.GetFileNameWithoutExtension(playlist);
@ -807,7 +808,7 @@ namespace MediaBrowser.Api.Playback.Hls
if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
{ {
return "-codec:a:0 copy"; return "-codec:a:0 copy -copypriorss:a:0 0";
} }
var args = "-codec:a:0 " + codec; var args = "-codec:a:0 " + codec;
@ -925,7 +926,7 @@ namespace MediaBrowser.Api.Playback.Hls
if (useGenericSegmenter) if (useGenericSegmenter)
{ {
var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request); var outputTsArg = Path.Combine(FileSystem.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request);
var timeDeltaParam = String.Empty; var timeDeltaParam = String.Empty;

View File

@ -15,6 +15,8 @@ namespace MediaBrowser.Api.Playback.Hls
/// <summary> /// <summary>
/// Class GetHlsAudioSegment /// Class GetHlsAudioSegment
/// </summary> /// </summary>
// Can't require authentication just yet due to seeing some requests come from Chrome without full query string
//[Authenticated]
[Route("/Audio/{Id}/hls/{SegmentId}/stream.mp3", "GET")] [Route("/Audio/{Id}/hls/{SegmentId}/stream.mp3", "GET")]
[Route("/Audio/{Id}/hls/{SegmentId}/stream.aac", "GET")] [Route("/Audio/{Id}/hls/{SegmentId}/stream.aac", "GET")]
public class GetHlsAudioSegmentLegacy public class GetHlsAudioSegmentLegacy
@ -38,6 +40,7 @@ namespace MediaBrowser.Api.Playback.Hls
/// Class GetHlsVideoSegment /// Class GetHlsVideoSegment
/// </summary> /// </summary>
[Route("/Videos/{Id}/hls/{PlaylistId}/stream.m3u8", "GET")] [Route("/Videos/{Id}/hls/{PlaylistId}/stream.m3u8", "GET")]
[Authenticated]
public class GetHlsPlaylistLegacy public class GetHlsPlaylistLegacy
{ {
// TODO: Deprecate with new iOS app // TODO: Deprecate with new iOS app
@ -52,6 +55,7 @@ namespace MediaBrowser.Api.Playback.Hls
} }
[Route("/Videos/ActiveEncodings", "DELETE")] [Route("/Videos/ActiveEncodings", "DELETE")]
[Authenticated]
public class StopEncodingProcess public class StopEncodingProcess
{ {
[ApiMember(Name = "DeviceId", Description = "The device id of the client requesting. Used to stop encoding processes when needed.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")] [ApiMember(Name = "DeviceId", Description = "The device id of the client requesting. Used to stop encoding processes when needed.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
@ -64,6 +68,8 @@ namespace MediaBrowser.Api.Playback.Hls
/// <summary> /// <summary>
/// Class GetHlsVideoSegment /// Class GetHlsVideoSegment
/// </summary> /// </summary>
// Can't require authentication just yet due to seeing some requests come from Chrome without full query string
//[Authenticated]
[Route("/Videos/{Id}/hls/{PlaylistId}/{SegmentId}.{SegmentContainer}", "GET")] [Route("/Videos/{Id}/hls/{PlaylistId}/{SegmentId}.{SegmentContainer}", "GET")]
public class GetHlsVideoSegmentLegacy : VideoStreamRequest public class GetHlsVideoSegmentLegacy : VideoStreamRequest
{ {

View File

@ -20,6 +20,7 @@ namespace MediaBrowser.Api.Playback.Hls
/// <summary> /// <summary>
/// Class VideoHlsService /// Class VideoHlsService
/// </summary> /// </summary>
[Authenticated]
public class VideoHlsService : BaseHlsService public class VideoHlsService : BaseHlsService
{ {
public object Get(GetLiveHlsStream request) public object Get(GetLiveHlsStream request)

View File

@ -59,42 +59,7 @@ namespace MediaBrowser.Api.Playback.Progressive
{ {
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
var audioTranscodeParams = new List<string>(); return EncodingHelper.GetProgressiveAudioFullCommandLine(state, encodingOptions, outputPath);
var bitrate = state.OutputAudioBitrate;
if (bitrate.HasValue)
{
audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(UsCulture));
}
if (state.OutputAudioChannels.HasValue)
{
audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(UsCulture));
}
// opus will fail on 44100
if (!string.Equals(state.OutputAudioCodec, "opus", global::System.StringComparison.OrdinalIgnoreCase))
{
if (state.OutputAudioSampleRate.HasValue)
{
audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture));
}
}
const string vn = " -vn";
var threads = EncodingHelper.GetNumberOfThreads(state, encodingOptions, false);
var inputModifier = EncodingHelper.GetInputModifier(state, encodingOptions);
return string.Format("{0} {1} -threads {2}{3} {4} -id3v2_version 3 -write_id3v1 1 -y \"{5}\"",
inputModifier,
EncodingHelper.GetInputArgument(state, encodingOptions),
threads,
vn,
string.Join(" ", audioTranscodeParams.ToArray()),
outputPath).Trim();
} }
public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext, imageProcessor) public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext, imageProcessor)

View File

@ -62,6 +62,8 @@ namespace MediaBrowser.Api.Playback.Progressive
/// <summary> /// <summary>
/// Class VideoService /// Class VideoService
/// </summary> /// </summary>
// TODO: In order to autheneticate this in the future, Dlna playback will require updating
//[Authenticated]
public class VideoService : BaseProgressiveStreamingService public class VideoService : BaseProgressiveStreamingService
{ {
public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext, imageProcessor) public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext, imageProcessor)

View File

@ -138,6 +138,8 @@ namespace MediaBrowser.Api.Playback
return MimeTypes.GetMimeType(outputPath); return MimeTypes.GetMimeType(outputPath);
} }
public bool EnableDlnaHeaders { get; set; }
public void Dispose() public void Dispose()
{ {
DisposeTranscodingThrottler(); DisposeTranscodingThrottler();

View File

@ -102,7 +102,7 @@ namespace MediaBrowser.Api
/// Fields to return within the items, in addition to basic information /// Fields to return within the items, in addition to basic information
/// </summary> /// </summary>
/// <value>The fields.</value> /// <value>The fields.</value>
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; } public string Fields { get; set; }
[ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]

View File

@ -300,11 +300,6 @@ namespace MediaBrowser.Api.Reports
} }
} }
if (!string.IsNullOrEmpty(request.LocationTypes))
{
query.LocationTypes = request.LocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
}
// Min official rating // Min official rating
if (!string.IsNullOrWhiteSpace(request.MinOfficialRating)) if (!string.IsNullOrWhiteSpace(request.MinOfficialRating))
{ {

View File

@ -9,6 +9,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Search; using MediaBrowser.Model.Search;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.Services; using MediaBrowser.Model.Services;
namespace MediaBrowser.Api namespace MediaBrowser.Api
@ -66,6 +67,23 @@ namespace MediaBrowser.Api
[ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string IncludeItemTypes { get; set; } public string IncludeItemTypes { get; set; }
public string ParentId { get; set; }
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
public bool? IsMovie { get; set; }
[ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
public bool? IsSeries { get; set; }
[ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
public bool? IsNews { get; set; }
[ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
public bool? IsKids { get; set; }
[ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
public bool? IsSports { get; set; }
public GetSearchHints() public GetSearchHints()
{ {
IncludeArtists = true; IncludeArtists = true;
@ -135,7 +153,14 @@ namespace MediaBrowser.Api
IncludeStudios = request.IncludeStudios, IncludeStudios = request.IncludeStudios,
StartIndex = request.StartIndex, StartIndex = request.StartIndex,
UserId = request.UserId, UserId = request.UserId,
IncludeItemTypes = (request.IncludeItemTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray() IncludeItemTypes = (request.IncludeItemTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray(),
ParentId = request.ParentId,
IsKids = request.IsKids,
IsMovie = request.IsMovie,
IsNews = request.IsNews,
IsSeries = request.IsSeries,
IsSports = request.IsSports
}).ConfigureAwait(false); }).ConfigureAwait(false);
@ -167,11 +192,11 @@ namespace MediaBrowser.Api
MatchedTerm = hintInfo.MatchedTerm, MatchedTerm = hintInfo.MatchedTerm,
DisplayMediaType = item.DisplayMediaType, DisplayMediaType = item.DisplayMediaType,
RunTimeTicks = item.RunTimeTicks, RunTimeTicks = item.RunTimeTicks,
ProductionYear = item.ProductionYear ProductionYear = item.ProductionYear,
ChannelId = item.ChannelId,
EndDate = item.EndDate
}; };
result.ChannelId = item.ChannelId;
var primaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary); var primaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
if (primaryImageTag != null) if (primaryImageTag != null)
@ -183,12 +208,27 @@ namespace MediaBrowser.Api
SetThumbImageInfo(result, item); SetThumbImageInfo(result, item);
SetBackdropImageInfo(result, item); SetBackdropImageInfo(result, item);
var program = item as LiveTvProgram;
if (program != null)
{
result.StartDate = program.StartDate;
}
var hasSeries = item as IHasSeries; var hasSeries = item as IHasSeries;
if (hasSeries != null) if (hasSeries != null)
{ {
result.Series = hasSeries.SeriesName; result.Series = hasSeries.SeriesName;
} }
var series = item as Series;
if (series != null)
{
if (series.Status.HasValue)
{
result.Status = series.Status.Value.ToString();
}
}
var album = item as MusicAlbum; var album = item as MusicAlbum;
if (album != null) if (album != null)

View File

@ -58,7 +58,7 @@ namespace MediaBrowser.Api.Session
void _sessionManager_PlaybackProgress(object sender, PlaybackProgressEventArgs e) void _sessionManager_PlaybackProgress(object sender, PlaybackProgressEventArgs e)
{ {
SendData(false); SendData(!e.IsAutomated);
} }
void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e) void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e)

View File

@ -61,7 +61,7 @@ namespace MediaBrowser.Api
/// Fields to return within the items, in addition to basic information /// Fields to return within the items, in addition to basic information
/// </summary> /// </summary>
/// <value>The fields.</value> /// <value>The fields.</value>
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; } public string Fields { get; set; }
} }

View File

@ -95,12 +95,12 @@ namespace MediaBrowser.Api
config.EnableStandaloneMusicKeys = true; config.EnableStandaloneMusicKeys = true;
config.EnableCaseSensitiveItemIds = true; config.EnableCaseSensitiveItemIds = true;
config.SkipDeserializationForBasicTypes = true; config.SkipDeserializationForBasicTypes = true;
config.SkipDeserializationForPrograms = true;
config.SkipDeserializationForAudio = true; config.SkipDeserializationForAudio = true;
config.EnableSeriesPresentationUniqueKey = true; config.EnableSeriesPresentationUniqueKey = true;
config.EnableLocalizedGuids = true; config.EnableLocalizedGuids = true;
config.EnableSimpleArtistDetection = true; config.EnableSimpleArtistDetection = true;
config.EnableNormalizedItemByNameIds = true; config.EnableNormalizedItemByNameIds = true;
config.DisableLiveTvChannelUserDataName = true;
} }
public void Post(UpdateStartupConfiguration request) public void Post(UpdateStartupConfiguration request)

View File

@ -288,7 +288,7 @@ namespace MediaBrowser.Api.Subtitles
await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None) await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None)
.ConfigureAwait(false); .ConfigureAwait(false);
_providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(_fileSystem)); _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.High);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -48,7 +48,7 @@ namespace MediaBrowser.Api
/// Fields to return within the items, in addition to basic information /// Fields to return within the items, in addition to basic information
/// </summary> /// </summary>
/// <value>The fields.</value> /// <value>The fields.</value>
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; } public string Fields { get; set; }
[ApiMember(Name = "SeriesId", Description = "Optional. Filter by series id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "SeriesId", Description = "Optional. Filter by series id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
@ -108,7 +108,7 @@ namespace MediaBrowser.Api
/// Fields to return within the items, in addition to basic information /// Fields to return within the items, in addition to basic information
/// </summary> /// </summary>
/// <value>The fields.</value> /// <value>The fields.</value>
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; } public string Fields { get; set; }
/// <summary> /// <summary>
@ -150,7 +150,7 @@ namespace MediaBrowser.Api
/// Fields to return within the items, in addition to basic information /// Fields to return within the items, in addition to basic information
/// </summary> /// </summary>
/// <value>The fields.</value> /// <value>The fields.</value>
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; } public string Fields { get; set; }
[ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@ -215,7 +215,7 @@ namespace MediaBrowser.Api
/// Fields to return within the items, in addition to basic information /// Fields to return within the items, in addition to basic information
/// </summary> /// </summary>
/// <value>The fields.</value> /// <value>The fields.</value>
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; } public string Fields { get; set; }
[ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@ -497,7 +497,7 @@ namespace MediaBrowser.Api
} }
else else
{ {
episodes = series.GetSeasonEpisodes(season, user); episodes = season.GetEpisodes(user);
} }
} }
else else

View File

@ -146,7 +146,7 @@ namespace MediaBrowser.Api.UserLibrary
/// Fields to return within the items, in addition to basic information /// Fields to return within the items, in addition to basic information
/// </summary> /// </summary>
/// <value>The fields.</value> /// <value>The fields.</value>
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; } public string Fields { get; set; }
/// <summary> /// <summary>

View File

@ -328,7 +328,15 @@ namespace MediaBrowser.Api.UserLibrary
if (!string.IsNullOrEmpty(request.LocationTypes)) if (!string.IsNullOrEmpty(request.LocationTypes))
{ {
query.LocationTypes = request.LocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray(); var requestedLocationTypes =
request.LocationTypes.Split(',')
.Select(d => (LocationType) Enum.Parse(typeof (LocationType), d, true))
.ToList();
if (requestedLocationTypes.Count > 0 && requestedLocationTypes.Count < 4)
{
query.IsVirtualItem = requestedLocationTypes.Contains(LocationType.Virtual);
}
} }
// Min official rating // Min official rating

View File

@ -225,7 +225,7 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string ParentId { get; set; } public string ParentId { get; set; }
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; } public string Fields { get; set; }
[ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]

View File

@ -444,7 +444,7 @@ namespace MediaBrowser.Api
public async Task PostAsync(UpdateUserPassword request) public async Task PostAsync(UpdateUserPassword request)
{ {
AssertCanUpdateUser(_authContext, _userManager, request.Id); AssertCanUpdateUser(_authContext, _userManager, request.Id, true);
var user = _userManager.GetUserById(request.Id); var user = _userManager.GetUserById(request.Id);
@ -482,7 +482,7 @@ namespace MediaBrowser.Api
public async Task PostAsync(UpdateUserEasyPassword request) public async Task PostAsync(UpdateUserEasyPassword request)
{ {
AssertCanUpdateUser(_authContext, _userManager, request.Id); AssertCanUpdateUser(_authContext, _userManager, request.Id, true);
var user = _userManager.GetUserById(request.Id); var user = _userManager.GetUserById(request.Id);
@ -518,7 +518,7 @@ namespace MediaBrowser.Api
// https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs // https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
var id = GetPathValue(1); var id = GetPathValue(1);
AssertCanUpdateUser(_authContext, _userManager, id); AssertCanUpdateUser(_authContext, _userManager, id, false);
var dtoUser = request; var dtoUser = request;
@ -568,7 +568,7 @@ namespace MediaBrowser.Api
public void Post(UpdateUserConfiguration request) public void Post(UpdateUserConfiguration request)
{ {
AssertCanUpdateUser(_authContext, _userManager, request.Id); AssertCanUpdateUser(_authContext, _userManager, request.Id, false);
var task = _userManager.UpdateConfiguration(request.Id, request); var task = _userManager.UpdateConfiguration(request.Id, request);

View File

@ -9,7 +9,6 @@ using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
namespace MediaBrowser.Controller.Entities.Audio namespace MediaBrowser.Controller.Entities.Audio
@ -24,8 +23,6 @@ namespace MediaBrowser.Controller.Entities.Audio
IHasLookupInfo<SongInfo>, IHasLookupInfo<SongInfo>,
IHasMediaSources IHasMediaSources
{ {
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
/// <summary> /// <summary>
/// Gets or sets the artist. /// Gets or sets the artist.
/// </summary> /// </summary>

View File

@ -112,7 +112,7 @@ namespace MediaBrowser.Controller.Entities.Audio
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query) public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
{ {
query.Genres = new[] { Name }; query.GenreIds = new[] { Id.ToString("N") };
query.IncludeItemTypes = new[] { typeof(MusicVideo).Name, typeof(Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name }; query.IncludeItemTypes = new[] { typeof(MusicVideo).Name, typeof(Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
return LibraryManager.GetItemList(query); return LibraryManager.GetItemList(query);

View File

@ -31,12 +31,10 @@ namespace MediaBrowser.Controller.Entities
public string SeriesName { get; set; } public string SeriesName { get; set; }
[IgnoreDataMember] [IgnoreDataMember]
public Guid? SeriesId { get; set; } public Guid? SeriesId { get; set; }
[IgnoreDataMember]
public string SeriesSortName { get; set; }
public string FindSeriesSortName() public string FindSeriesSortName()
{ {
return SeriesSortName; return SeriesName;
} }
public string FindSeriesName() public string FindSeriesName()
{ {

View File

@ -84,6 +84,7 @@ namespace MediaBrowser.Controller.Entities
public long? Size { get; set; } public long? Size { get; set; }
public string Container { get; set; } public string Container { get; set; }
[IgnoreDataMember] [IgnoreDataMember]
public string Tagline { get; set; } public string Tagline { get; set; }
@ -288,7 +289,7 @@ namespace MediaBrowser.Controller.Entities
return Path; return Path;
} }
return System.IO.Path.GetDirectoryName(Path); return FileSystem.GetDirectoryName(Path);
} }
} }
@ -834,20 +835,6 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember] [IgnoreDataMember]
public float? CriticRating { get; set; } public float? CriticRating { get; set; }
/// <summary>
/// Gets or sets the critic rating summary.
/// </summary>
/// <value>The critic rating summary.</value>
[IgnoreDataMember]
public string CriticRatingSummary { get; set; }
/// <summary>
/// Gets or sets the official rating description.
/// </summary>
/// <value>The official rating description.</value>
[IgnoreDataMember]
public string OfficialRatingDescription { get; set; }
/// <summary> /// <summary>
/// Gets or sets the custom rating. /// Gets or sets the custom rating.
/// </summary> /// </summary>
@ -1824,7 +1811,7 @@ namespace MediaBrowser.Controller.Entities
/// <returns>Task.</returns> /// <returns>Task.</returns>
public virtual Task ChangedExternally() public virtual Task ChangedExternally()
{ {
ProviderManager.QueueRefresh(Id, new MetadataRefreshOptions(FileSystem)); ProviderManager.QueueRefresh(Id, new MetadataRefreshOptions(FileSystem), RefreshPriority.High);
return Task.FromResult(true); return Task.FromResult(true);
} }
@ -1924,7 +1911,7 @@ namespace MediaBrowser.Controller.Entities
{ {
var allFiles = ImageInfos var allFiles = ImageInfos
.Where(i => i.IsLocalFile) .Where(i => i.IsLocalFile)
.Select(i => System.IO.Path.GetDirectoryName(i.Path)) .Select(i => FileSystem.GetDirectoryName(i.Path))
.Distinct(StringComparer.OrdinalIgnoreCase) .Distinct(StringComparer.OrdinalIgnoreCase)
.SelectMany(directoryService.GetFilePaths) .SelectMany(directoryService.GetFilePaths)
.ToList(); .ToList();
@ -2099,7 +2086,7 @@ namespace MediaBrowser.Controller.Entities
var extensions = new[] { ".nfo", ".xml", ".srt" }.ToList(); var extensions = new[] { ".nfo", ".xml", ".srt" }.ToList();
extensions.AddRange(SupportedImageExtensionsList); extensions.AddRange(SupportedImageExtensionsList);
return FileSystem.GetFiles(System.IO.Path.GetDirectoryName(Path), extensions.ToArray(), false, false) return FileSystem.GetFiles(FileSystem.GetDirectoryName(Path), extensions.ToArray(), false, false)
.Where(i => System.IO.Path.GetFileNameWithoutExtension(i.FullName).StartsWith(filename, StringComparison.OrdinalIgnoreCase)) .Where(i => System.IO.Path.GetFileNameWithoutExtension(i.FullName).StartsWith(filename, StringComparison.OrdinalIgnoreCase))
.ToList(); .ToList();
} }
@ -2298,16 +2285,6 @@ namespace MediaBrowser.Controller.Entities
ownedItem.CustomRating = item.CustomRating; ownedItem.CustomRating = item.CustomRating;
newOptions.ForceSave = true; newOptions.ForceSave = true;
} }
if (!string.Equals(item.CriticRatingSummary, ownedItem.CriticRatingSummary, StringComparison.Ordinal))
{
ownedItem.CriticRatingSummary = item.CriticRatingSummary;
newOptions.ForceSave = true;
}
if (!string.Equals(item.OfficialRatingDescription, ownedItem.OfficialRatingDescription, StringComparison.Ordinal))
{
ownedItem.OfficialRatingDescription = item.OfficialRatingDescription;
newOptions.ForceSave = true;
}
} }
return ownedItem.RefreshMetadata(newOptions, cancellationToken); return ownedItem.RefreshMetadata(newOptions, cancellationToken);

View File

@ -24,12 +24,10 @@ namespace MediaBrowser.Controller.Entities
public string SeriesName { get; set; } public string SeriesName { get; set; }
[IgnoreDataMember] [IgnoreDataMember]
public Guid? SeriesId { get; set; } public Guid? SeriesId { get; set; }
[IgnoreDataMember]
public string SeriesSortName { get; set; }
public string FindSeriesSortName() public string FindSeriesSortName()
{ {
return SeriesSortName; return SeriesName;
} }
public string FindSeriesName() public string FindSeriesName()
{ {

View File

@ -213,7 +213,7 @@ namespace MediaBrowser.Controller.Entities
.SelectMany(c => c.LinkedChildren) .SelectMany(c => c.LinkedChildren)
.ToList(); .ToList();
var changed = !linkedChildren.SequenceEqual(LinkedChildren, new LinkedChildComparer()); var changed = !linkedChildren.SequenceEqual(LinkedChildren, new LinkedChildComparer(FileSystem));
LinkedChildren = linkedChildren; LinkedChildren = linkedChildren;
@ -332,13 +332,13 @@ namespace MediaBrowser.Controller.Entities
.OfType<Folder>() .OfType<Folder>()
.ToList(); .ToList();
return PhysicalLocations.Where(i => !string.Equals(i, Path, StringComparison.OrdinalIgnoreCase)).SelectMany(i => GetPhysicalParents(i, rootChildren)).DistinctBy(i => i.Id); return PhysicalLocations.Where(i => !FileSystem.AreEqual(i, Path)).SelectMany(i => GetPhysicalParents(i, rootChildren)).DistinctBy(i => i.Id);
} }
private IEnumerable<Folder> GetPhysicalParents(string path, List<Folder> rootChildren) private IEnumerable<Folder> GetPhysicalParents(string path, List<Folder> rootChildren)
{ {
var result = rootChildren var result = rootChildren
.Where(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase)) .Where(i => FileSystem.AreEqual(i.Path, path))
.ToList(); .ToList();
if (result.Count == 0) if (result.Count == 0)

View File

@ -640,7 +640,7 @@ namespace MediaBrowser.Controller.Entities
return true; return true;
} }
path = System.IO.Path.GetDirectoryName(path); path = FileSystem.GetDirectoryName(path);
} }
return allLibraryPaths.Any(i => ContainsPath(i, originalPath)); return allLibraryPaths.Any(i => ContainsPath(i, originalPath));
@ -1206,11 +1206,17 @@ namespace MediaBrowser.Controller.Entities
return GetLinkedChildren(); return GetLinkedChildren();
} }
var locations = user.RootFolder if (LinkedChildren.Count == 0)
.Children {
return new List<BaseItem>();
}
var allUserRootChildren = user.RootFolder.Children.OfType<Folder>().ToList();
var collectionFolderIds = allUserRootChildren
.OfType<CollectionFolder>() .OfType<CollectionFolder>()
.Where(i => i.IsVisible(user)) .Where(i => i.IsVisible(user))
.SelectMany(i => i.PhysicalLocations) .Select(i => i.Id)
.ToList(); .ToList();
return LinkedChildren return LinkedChildren
@ -1228,9 +1234,16 @@ namespace MediaBrowser.Controller.Entities
return null; return null;
} }
} }
else if (childLocationType == LocationType.FileSystem && !locations.Any(l => FileSystem.ContainsSubPath(l, child.Path))) else if (childLocationType == LocationType.FileSystem)
{ {
return null; var itemCollectionFolderIds =
LibraryManager.GetCollectionFolders(child, allUserRootChildren)
.Select(f => f.Id).ToList();
if (!itemCollectionFolderIds.Any(collectionFolderIds.Contains))
{
return null;
}
} }
} }
@ -1323,7 +1336,7 @@ namespace MediaBrowser.Controller.Entities
} }
else { newShortcutLinks = new List<LinkedChild>(); } else { newShortcutLinks = new List<LinkedChild>(); }
if (!newShortcutLinks.SequenceEqual(currentShortcutLinks, new LinkedChildComparer())) if (!newShortcutLinks.SequenceEqual(currentShortcutLinks, new LinkedChildComparer(FileSystem)))
{ {
Logger.Info("Shortcut links have changed for {0}", Path); Logger.Info("Shortcut links have changed for {0}", Path);

View File

@ -105,7 +105,7 @@ namespace MediaBrowser.Controller.Entities
return new[] { return new[] {
new FileSystemMetadata new FileSystemMetadata
{ {
FullName = System.IO.Path.GetDirectoryName(Path), FullName = FileSystem.GetDirectoryName(Path),
IsDirectory = true IsDirectory = true
} }
}; };

View File

@ -81,7 +81,7 @@ namespace MediaBrowser.Controller.Entities
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query) public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
{ {
query.Genres = new[] { Name }; query.GenreIds = new[] { Id.ToString("N") };
query.IncludeItemTypes = new[] { typeof(Game).Name }; query.IncludeItemTypes = new[] { typeof(Game).Name };
return LibraryManager.GetItemList(query); return LibraryManager.GetItemList(query);

View File

@ -93,7 +93,7 @@ namespace MediaBrowser.Controller.Entities
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query) public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
{ {
query.Genres = new[] { Name }; query.GenreIds = new[] { Id.ToString("N") };
query.ExcludeItemTypes = new[] { typeof(Game).Name, typeof(MusicVideo).Name, typeof(Audio.Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name }; query.ExcludeItemTypes = new[] { typeof(Game).Name, typeof(MusicVideo).Name, typeof(Audio.Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
return LibraryManager.GetItemList(query); return LibraryManager.GetItemList(query);

View File

@ -11,7 +11,6 @@ namespace MediaBrowser.Controller.Entities
/// <value>The name of the series.</value> /// <value>The name of the series.</value>
string SeriesName { get; set; } string SeriesName { get; set; }
string FindSeriesName(); string FindSeriesName();
string SeriesSortName { get; set; }
string FindSeriesSortName(); string FindSeriesSortName();
Guid? SeriesId { get; set; } Guid? SeriesId { get; set; }
Guid? FindSeriesId(); Guid? FindSeriesId();

View File

@ -129,7 +129,6 @@ namespace MediaBrowser.Controller.Entities
public string[] AncestorIds { get; set; } public string[] AncestorIds { get; set; }
public string[] TopParentIds { get; set; } public string[] TopParentIds { get; set; }
public LocationType[] LocationTypes { get; set; }
public string[] PresetViews { get; set; } public string[] PresetViews { get; set; }
public SourceType[] SourceTypes { get; set; } public SourceType[] SourceTypes { get; set; }
public SourceType[] ExcludeSourceTypes { get; set; } public SourceType[] ExcludeSourceTypes { get; set; }
@ -176,7 +175,6 @@ namespace MediaBrowser.Controller.Entities
case ItemFields.DateCreated: case ItemFields.DateCreated:
case ItemFields.SortName: case ItemFields.SortName:
case ItemFields.Overview: case ItemFields.Overview:
case ItemFields.OfficialRatingDescription:
case ItemFields.HomePageUrl: case ItemFields.HomePageUrl:
case ItemFields.VoteCount: case ItemFields.VoteCount:
case ItemFields.DisplayMediaType: case ItemFields.DisplayMediaType:
@ -187,7 +185,6 @@ namespace MediaBrowser.Controller.Entities
case ItemFields.OriginalTitle: case ItemFields.OriginalTitle:
case ItemFields.Tags: case ItemFields.Tags:
case ItemFields.DateLastMediaAdded: case ItemFields.DateLastMediaAdded:
case ItemFields.CriticRatingSummary:
return fields.Count == 0 || fields.Contains(name); return fields.Count == 0 || fields.Contains(name);
default: default:
return true; return true;
@ -230,7 +227,6 @@ namespace MediaBrowser.Controller.Entities
TopParentIds = new string[] { }; TopParentIds = new string[] { };
ExcludeTags = new string[] { }; ExcludeTags = new string[] { };
ExcludeInheritedTags = new string[] { }; ExcludeInheritedTags = new string[] { };
LocationTypes = new LocationType[] { };
PresetViews = new string[] { }; PresetViews = new string[] { };
SourceTypes = new SourceType[] { }; SourceTypes = new SourceType[] { };
ExcludeSourceTypes = new SourceType[] { }; ExcludeSourceTypes = new SourceType[] { };

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
namespace MediaBrowser.Controller.Entities namespace MediaBrowser.Controller.Entities
@ -40,11 +41,18 @@ namespace MediaBrowser.Controller.Entities
public class LinkedChildComparer : IEqualityComparer<LinkedChild> public class LinkedChildComparer : IEqualityComparer<LinkedChild>
{ {
private readonly IFileSystem _fileSystem;
public LinkedChildComparer(IFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
public bool Equals(LinkedChild x, LinkedChild y) public bool Equals(LinkedChild x, LinkedChild y)
{ {
if (x.Type == y.Type) if (x.Type == y.Type)
{ {
return string.Equals(x.Path, y.Path, StringComparison.OrdinalIgnoreCase); return _fileSystem.AreEqual(x.Path, y.Path);
} }
return false; return false;
} }

View File

@ -152,9 +152,7 @@ namespace MediaBrowser.Controller.Entities.Movies
var currentOfficialRating = OfficialRating; var currentOfficialRating = OfficialRating;
// Gather all possible ratings // Gather all possible ratings
var ratings = GetRecursiveChildren() var ratings = GetRecursiveChildren(i => i is Movie || i is Series || i is MusicAlbum || i is Game)
.Concat(GetLinkedChildren())
.Where(i => i is Movie || i is Series || i is MusicAlbum || i is Game)
.Select(i => i.OfficialRating) .Select(i => i.OfficialRating)
.Where(i => !string.IsNullOrEmpty(i)) .Where(i => !string.IsNullOrEmpty(i))
.Distinct(StringComparer.OrdinalIgnoreCase) .Distinct(StringComparer.OrdinalIgnoreCase)
@ -205,7 +203,7 @@ namespace MediaBrowser.Controller.Entities.Movies
if (base.IsVisible(user)) if (base.IsVisible(user))
{ {
return GetChildren(user, true).Any(); return base.GetChildren(user, true).Any();
} }
return false; return false;

View File

@ -57,13 +57,10 @@ namespace MediaBrowser.Controller.Entities.TV
/// <value>The index number.</value> /// <value>The index number.</value>
public int? IndexNumberEnd { get; set; } public int? IndexNumberEnd { get; set; }
[IgnoreDataMember]
public string SeriesSortName { get; set; }
public string FindSeriesSortName() public string FindSeriesSortName()
{ {
var series = Series; var series = Series;
return series == null ? SeriesSortName : series.SortName; return series == null ? SeriesName : series.SortName;
} }
[IgnoreDataMember] [IgnoreDataMember]

View File

@ -51,9 +51,6 @@ namespace MediaBrowser.Controller.Entities.TV
get { return SeriesId; } get { return SeriesId; }
} }
[IgnoreDataMember]
public string SeriesSortName { get; set; }
public override double? GetDefaultPrimaryImageAspectRatio() public override double? GetDefaultPrimaryImageAspectRatio()
{ {
double value = 2; double value = 2;
@ -65,7 +62,7 @@ namespace MediaBrowser.Controller.Entities.TV
public string FindSeriesSortName() public string FindSeriesSortName()
{ {
var series = Series; var series = Series;
return series == null ? SeriesSortName : series.SortName; return series == null ? SeriesName : series.SortName;
} }
// Genre, Rating and Stuido will all be the same // Genre, Rating and Stuido will all be the same
@ -125,7 +122,7 @@ namespace MediaBrowser.Controller.Entities.TV
return series.Path; return series.Path;
} }
return System.IO.Path.GetDirectoryName(Path); return FileSystem.GetDirectoryName(Path);
} }
} }

View File

@ -586,7 +586,7 @@ namespace MediaBrowser.Controller.Entities
{ {
query.Recursive = true; query.Recursive = true;
query.ParentId = queryParent.Id; query.ParentId = queryParent.Id;
query.Genres = new[] { displayParent.Name }; query.GenreIds = new[] { displayParent.Id.ToString("N") };
query.SetUser(user); query.SetUser(user);
query.IncludeItemTypes = new[] { typeof(Movie).Name }; query.IncludeItemTypes = new[] { typeof(Movie).Name };
@ -729,7 +729,7 @@ namespace MediaBrowser.Controller.Entities
{ {
query.Recursive = true; query.Recursive = true;
query.ParentId = queryParent.Id; query.ParentId = queryParent.Id;
query.Genres = new[] { displayParent.Name }; query.GenreIds = new[] { displayParent.Id.ToString("N") };
query.SetUser(user); query.SetUser(user);
query.IncludeItemTypes = new[] { typeof(Series).Name }; query.IncludeItemTypes = new[] { typeof(Series).Name };
@ -905,6 +905,11 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
if (request.GenreIds.Length > 0)
{
return false;
}
if (request.HasImdbId.HasValue) if (request.HasImdbId.HasValue)
{ {
return false; return false;
@ -1768,26 +1773,6 @@ namespace MediaBrowser.Controller.Entities
return new List<Folder> { parent }; return new List<Folder> { parent };
} }
private IEnumerable<BaseItem> GetRecursiveChildren(Folder parent, User user, IEnumerable<string> viewTypes)
{
if (parent == null || parent is UserView)
{
if (user == null)
{
return GetMediaFolders(null, viewTypes).SelectMany(i => i.GetRecursiveChildren());
}
return GetMediaFolders(user, viewTypes).SelectMany(i => i.GetRecursiveChildren(user));
}
if (user == null)
{
return parent.GetRecursiveChildren();
}
return parent.GetRecursiveChildren(user);
}
private async Task<QueryResult<BaseItem>> GetLiveTvView(Folder queryParent, User user, InternalItemsQuery query) private async Task<QueryResult<BaseItem>> GetLiveTvView(Folder queryParent, User user, InternalItemsQuery query)
{ {
if (query.Recursive) if (query.Recursive)

View File

@ -33,7 +33,6 @@ namespace MediaBrowser.Controller.Entities
public List<string> AdditionalParts { get; set; } public List<string> AdditionalParts { get; set; }
public List<string> LocalAlternateVersions { get; set; } public List<string> LocalAlternateVersions { get; set; }
public List<LinkedChild> LinkedAlternateVersions { get; set; } public List<LinkedChild> LinkedAlternateVersions { get; set; }
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
[IgnoreDataMember] [IgnoreDataMember]
public override bool SupportsPlayedStatus public override bool SupportsPlayedStatus
@ -158,7 +157,6 @@ namespace MediaBrowser.Controller.Entities
PlayableStreamFileNames = new List<string>(); PlayableStreamFileNames = new List<string>();
AdditionalParts = new List<string>(); AdditionalParts = new List<string>();
LocalAlternateVersions = new List<string>(); LocalAlternateVersions = new List<string>();
Tags = new List<string>();
SubtitleFiles = new List<string>(); SubtitleFiles = new List<string>();
LinkedAlternateVersions = new List<LinkedChild>(); LinkedAlternateVersions = new List<LinkedChild>();
} }
@ -313,7 +311,7 @@ namespace MediaBrowser.Controller.Entities
{ {
if (IsStacked) if (IsStacked)
{ {
return System.IO.Path.GetDirectoryName(Path); return FileSystem.GetDirectoryName(Path);
} }
if (!IsPlaceHolder) if (!IsPlaceHolder)
@ -591,41 +589,46 @@ namespace MediaBrowser.Controller.Entities
.ToList(); .ToList();
} }
private static MediaSourceInfo GetVersionInfo(bool enablePathSubstitution, Video i, MediaSourceType type) private static MediaSourceInfo GetVersionInfo(bool enablePathSubstitution, Video media, MediaSourceType type)
{ {
var mediaStreams = MediaSourceManager.GetMediaStreams(i.Id) if (media == null)
{
throw new ArgumentNullException("media");
}
var mediaStreams = MediaSourceManager.GetMediaStreams(media.Id)
.ToList(); .ToList();
var locationType = i.LocationType; var locationType = media.LocationType;
var info = new MediaSourceInfo var info = new MediaSourceInfo
{ {
Id = i.Id.ToString("N"), Id = media.Id.ToString("N"),
IsoType = i.IsoType, IsoType = media.IsoType,
Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File, Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File,
MediaStreams = mediaStreams, MediaStreams = mediaStreams,
Name = GetMediaSourceName(i, mediaStreams), Name = GetMediaSourceName(media, mediaStreams),
Path = enablePathSubstitution ? GetMappedPath(i, i.Path, locationType) : i.Path, Path = enablePathSubstitution ? GetMappedPath(media, media.Path, locationType) : media.Path,
RunTimeTicks = i.RunTimeTicks, RunTimeTicks = media.RunTimeTicks,
Video3DFormat = i.Video3DFormat, Video3DFormat = media.Video3DFormat,
VideoType = i.VideoType, VideoType = media.VideoType,
Container = i.Container, Container = media.Container,
Size = i.Size, Size = media.Size,
Timestamp = i.Timestamp, Timestamp = media.Timestamp,
Type = type, Type = type,
PlayableStreamFileNames = i.PlayableStreamFileNames.ToList(), PlayableStreamFileNames = media.PlayableStreamFileNames.ToList(),
SupportsDirectStream = i.VideoType == VideoType.VideoFile, SupportsDirectStream = media.VideoType == VideoType.VideoFile,
IsRemote = i.IsShortcut IsRemote = media.IsShortcut
}; };
if (info.Protocol == MediaProtocol.File) if (info.Protocol == MediaProtocol.File)
{ {
info.ETag = i.DateModified.Ticks.ToString(CultureInfo.InvariantCulture).GetMD5().ToString("N"); info.ETag = media.DateModified.Ticks.ToString(CultureInfo.InvariantCulture).GetMD5().ToString("N");
} }
if (i.IsShortcut) if (media.IsShortcut)
{ {
info.Path = i.ShortcutPath; info.Path = media.ShortcutPath;
if (info.Path.StartsWith("Http", StringComparison.OrdinalIgnoreCase)) if (info.Path.StartsWith("Http", StringComparison.OrdinalIgnoreCase))
{ {
@ -647,16 +650,16 @@ namespace MediaBrowser.Controller.Entities
if (string.IsNullOrEmpty(info.Container)) if (string.IsNullOrEmpty(info.Container))
{ {
if (i.VideoType == VideoType.VideoFile || i.VideoType == VideoType.Iso) if (media.VideoType == VideoType.VideoFile || media.VideoType == VideoType.Iso)
{ {
if (!string.IsNullOrWhiteSpace(i.Path) && locationType != LocationType.Remote && locationType != LocationType.Virtual) if (!string.IsNullOrWhiteSpace(media.Path) && locationType != LocationType.Remote && locationType != LocationType.Virtual)
{ {
info.Container = System.IO.Path.GetExtension(i.Path).TrimStart('.'); info.Container = System.IO.Path.GetExtension(media.Path).TrimStart('.');
} }
} }
} }
info.Bitrate = i.TotalBitrate; info.Bitrate = media.TotalBitrate;
info.InferTotalBitrate(); info.InferTotalBitrate();
return info; return info;

View File

@ -456,6 +456,8 @@ namespace MediaBrowser.Controller.Library
/// <returns>IEnumerable&lt;Folder&gt;.</returns> /// <returns>IEnumerable&lt;Folder&gt;.</returns>
List<Folder> GetCollectionFolders(BaseItem item); List<Folder> GetCollectionFolders(BaseItem item);
List<Folder> GetCollectionFolders(BaseItem item, List<Folder> allUserRootChildren);
LibraryOptions GetLibraryOptions(BaseItem item); LibraryOptions GetLibraryOptions(BaseItem item);
/// <summary> /// <summary>

Some files were not shown because too many files have changed in this diff Show More