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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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,
SeriesId = series.Id,
SeriesSortName = series.SortName,
SeriesName = series.Name
};

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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
if (!string.IsNullOrWhiteSpace(request.MinOfficialRating))
{

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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")]
public string ParentId { get; set; }
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
[ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -640,7 +640,7 @@ namespace MediaBrowser.Controller.Entities
return true;
}
path = System.IO.Path.GetDirectoryName(path);
path = FileSystem.GetDirectoryName(path);
}
return allLibraryPaths.Any(i => ContainsPath(i, originalPath));
@ -1206,11 +1206,17 @@ namespace MediaBrowser.Controller.Entities
return GetLinkedChildren();
}
var locations = user.RootFolder
.Children
if (LinkedChildren.Count == 0)
{
return new List<BaseItem>();
}
var allUserRootChildren = user.RootFolder.Children.OfType<Folder>().ToList();
var collectionFolderIds = allUserRootChildren
.OfType<CollectionFolder>()
.Where(i => i.IsVisible(user))
.SelectMany(i => i.PhysicalLocations)
.Select(i => i.Id)
.ToList();
return LinkedChildren
@ -1228,9 +1234,16 @@ namespace MediaBrowser.Controller.Entities
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>(); }
if (!newShortcutLinks.SequenceEqual(currentShortcutLinks, new LinkedChildComparer()))
if (!newShortcutLinks.SequenceEqual(currentShortcutLinks, new LinkedChildComparer(FileSystem)))
{
Logger.Info("Shortcut links have changed for {0}", Path);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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