commit
890069d312
|
@ -203,10 +203,9 @@ namespace Emby.Drawing
|
|||
}
|
||||
|
||||
private static readonly string[] TransparentImageTypes = new string[] { ".png", ".webp" };
|
||||
private bool SupportsTransparency(string path)
|
||||
public bool SupportsTransparency(string path)
|
||||
{
|
||||
return TransparentImageTypes.Contains(Path.GetExtension(path) ?? string.Empty);
|
||||
;
|
||||
}
|
||||
|
||||
public async Task<Tuple<string, string, DateTime>> ProcessImage(ImageProcessingOptions options)
|
||||
|
@ -239,6 +238,7 @@ namespace Emby.Drawing
|
|||
var supportedImageInfo = await GetSupportedImage(originalImagePath, dateModified).ConfigureAwait(false);
|
||||
originalImagePath = supportedImageInfo.Item1;
|
||||
dateModified = supportedImageInfo.Item2;
|
||||
var requiresTransparency = TransparentImageTypes.Contains(Path.GetExtension(originalImagePath) ?? string.Empty);
|
||||
|
||||
if (options.Enhancers.Count > 0)
|
||||
{
|
||||
|
@ -253,10 +253,11 @@ namespace Emby.Drawing
|
|||
Type = originalImage.Type,
|
||||
Path = originalImagePath
|
||||
|
||||
}, item, options.ImageIndex, options.Enhancers).ConfigureAwait(false);
|
||||
}, requiresTransparency, item, options.ImageIndex, options.Enhancers).ConfigureAwait(false);
|
||||
|
||||
originalImagePath = tuple.Item1;
|
||||
dateModified = tuple.Item2;
|
||||
requiresTransparency = tuple.Item3;
|
||||
}
|
||||
|
||||
var photo = item as Photo;
|
||||
|
@ -268,7 +269,7 @@ namespace Emby.Drawing
|
|||
orientation = photo.Orientation;
|
||||
}
|
||||
|
||||
if (options.HasDefaultOptions(originalImagePath) && !autoOrient)
|
||||
if (options.HasDefaultOptions(originalImagePath) && (!autoOrient || !options.RequiresAutoOrientation))
|
||||
{
|
||||
// Just spit out the original file if all the options are default
|
||||
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
|
||||
|
@ -285,7 +286,7 @@ namespace Emby.Drawing
|
|||
var newSize = ImageHelper.GetNewImageSize(options, originalImageSize);
|
||||
var quality = options.Quality;
|
||||
|
||||
var outputFormat = GetOutputFormat(options.SupportedOutputFormats[0]);
|
||||
var outputFormat = GetOutputFormat(options.SupportedOutputFormats, requiresTransparency);
|
||||
var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.Blur, options.BackgroundColor, options.ForegroundLayer);
|
||||
|
||||
try
|
||||
|
@ -336,6 +337,34 @@ namespace Emby.Drawing
|
|||
}
|
||||
}
|
||||
|
||||
private ImageFormat GetOutputFormat(ImageFormat[] clientSupportedFormats, bool requiresTransparency)
|
||||
{
|
||||
var serverFormats = GetSupportedImageOutputFormats();
|
||||
|
||||
// Client doesn't care about format, so start with webp if supported
|
||||
if (serverFormats.Contains(ImageFormat.Webp) && clientSupportedFormats.Contains(ImageFormat.Webp))
|
||||
{
|
||||
return ImageFormat.Webp;
|
||||
}
|
||||
|
||||
// If transparency is needed and webp isn't supported, than png is the only option
|
||||
if (requiresTransparency)
|
||||
{
|
||||
return ImageFormat.Png;
|
||||
}
|
||||
|
||||
foreach (var format in clientSupportedFormats)
|
||||
{
|
||||
if (serverFormats.Contains(format))
|
||||
{
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
// We should never actually get here
|
||||
return ImageFormat.Jpg;
|
||||
}
|
||||
|
||||
private void CopyFile(string src, string destination)
|
||||
{
|
||||
try
|
||||
|
@ -389,21 +418,6 @@ namespace Emby.Drawing
|
|||
return MimeTypes.GetMimeType(path);
|
||||
}
|
||||
|
||||
private ImageFormat GetOutputFormat(ImageFormat requestedFormat)
|
||||
{
|
||||
if (requestedFormat == ImageFormat.Webp && !_imageEncoder.SupportedOutputFormats.Contains(ImageFormat.Webp))
|
||||
{
|
||||
return ImageFormat.Png;
|
||||
}
|
||||
|
||||
return requestedFormat;
|
||||
}
|
||||
|
||||
private Tuple<string, DateTime> GetResult(string path)
|
||||
{
|
||||
return new Tuple<string, DateTime>(path, _fileSystem.GetLastWriteTimeUtc(path));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increment this when there's a change requiring caches to be invalidated
|
||||
/// </summary>
|
||||
|
@ -753,12 +767,15 @@ namespace Emby.Drawing
|
|||
|
||||
var imageInfo = item.GetImageInfo(imageType, imageIndex);
|
||||
|
||||
var result = await GetEnhancedImage(imageInfo, item, imageIndex, enhancers);
|
||||
var inputImageSupportsTransparency = SupportsTransparency(imageInfo.Path);
|
||||
|
||||
var result = await GetEnhancedImage(imageInfo, inputImageSupportsTransparency, item, imageIndex, enhancers);
|
||||
|
||||
return result.Item1;
|
||||
}
|
||||
|
||||
private async Task<Tuple<string, DateTime>> GetEnhancedImage(ItemImageInfo image,
|
||||
private async Task<Tuple<string, DateTime, bool>> GetEnhancedImage(ItemImageInfo image,
|
||||
bool inputImageSupportsTransparency,
|
||||
IHasMetadata item,
|
||||
int imageIndex,
|
||||
List<IImageEnhancer> enhancers)
|
||||
|
@ -772,12 +789,16 @@ namespace Emby.Drawing
|
|||
var cacheGuid = GetImageCacheTag(item, image, enhancers);
|
||||
|
||||
// Enhance if we have enhancers
|
||||
var ehnancedImagePath = await GetEnhancedImageInternal(originalImagePath, item, imageType, imageIndex, enhancers, cacheGuid).ConfigureAwait(false);
|
||||
var ehnancedImageInfo = await GetEnhancedImageInternal(originalImagePath, item, imageType, imageIndex, enhancers, cacheGuid).ConfigureAwait(false);
|
||||
|
||||
var ehnancedImagePath = ehnancedImageInfo.Item1;
|
||||
|
||||
// If the path changed update dateModified
|
||||
if (!string.Equals(ehnancedImagePath, originalImagePath, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return GetResult(ehnancedImagePath);
|
||||
var treatmentRequiresTransparency = ehnancedImageInfo.Item2;
|
||||
|
||||
return new Tuple<string, DateTime, bool>(ehnancedImagePath, _fileSystem.GetLastWriteTimeUtc(ehnancedImagePath), treatmentRequiresTransparency);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -785,7 +806,7 @@ namespace Emby.Drawing
|
|||
_logger.Error("Error enhancing image", ex);
|
||||
}
|
||||
|
||||
return new Tuple<string, DateTime>(originalImagePath, dateModified);
|
||||
return new Tuple<string, DateTime, bool>(originalImagePath, dateModified, inputImageSupportsTransparency);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -803,11 +824,11 @@ namespace Emby.Drawing
|
|||
/// or
|
||||
/// item
|
||||
/// </exception>
|
||||
private async Task<string> GetEnhancedImageInternal(string originalImagePath,
|
||||
private async Task<Tuple<string, bool>> GetEnhancedImageInternal(string originalImagePath,
|
||||
IHasMetadata item,
|
||||
ImageType imageType,
|
||||
int imageIndex,
|
||||
IEnumerable<IImageEnhancer> supportedEnhancers,
|
||||
List<IImageEnhancer> supportedEnhancers,
|
||||
string cacheGuid)
|
||||
{
|
||||
if (string.IsNullOrEmpty(originalImagePath))
|
||||
|
@ -820,13 +841,26 @@ namespace Emby.Drawing
|
|||
throw new ArgumentNullException("item");
|
||||
}
|
||||
|
||||
var treatmentRequiresTransparency = false;
|
||||
foreach (var enhancer in supportedEnhancers)
|
||||
{
|
||||
if (!treatmentRequiresTransparency)
|
||||
{
|
||||
treatmentRequiresTransparency = enhancer.GetEnhancedImageInfo(item, originalImagePath, imageType, imageIndex).RequiresTransparency;
|
||||
}
|
||||
}
|
||||
|
||||
// All enhanced images are saved as png to allow transparency
|
||||
var enhancedImagePath = GetCachePath(EnhancedImageCachePath, cacheGuid + ".png");
|
||||
var cacheExtension = _imageEncoder.SupportedOutputFormats.Contains(ImageFormat.Webp) ?
|
||||
".webp" :
|
||||
(treatmentRequiresTransparency ? ".png" : ".jpg");
|
||||
|
||||
var enhancedImagePath = GetCachePath(EnhancedImageCachePath, cacheGuid + cacheExtension);
|
||||
|
||||
// Check again in case of contention
|
||||
if (_fileSystem.FileExists(enhancedImagePath))
|
||||
{
|
||||
return enhancedImagePath;
|
||||
return new Tuple<string, bool>(enhancedImagePath, treatmentRequiresTransparency);
|
||||
}
|
||||
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(enhancedImagePath));
|
||||
|
@ -845,7 +879,7 @@ namespace Emby.Drawing
|
|||
|
||||
}
|
||||
|
||||
return tmpPath;
|
||||
return new Tuple<string, bool>(tmpPath, treatmentRequiresTransparency);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1861,7 +1861,9 @@ namespace Emby.Server.Implementations
|
|||
{
|
||||
"mbplus.dll",
|
||||
"mbintros.dll",
|
||||
"embytv.dll"
|
||||
"embytv.dll",
|
||||
"Messenger.dll",
|
||||
"MediaBrowser.Plugins.TvMazeProvider.dll"
|
||||
};
|
||||
|
||||
return !exclude.Contains(filename ?? string.Empty, StringComparer.OrdinalIgnoreCase);
|
||||
|
|
|
@ -114,7 +114,7 @@ namespace Emby.Server.Implementations.Data
|
|||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.Data
|
|||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -275,8 +275,7 @@ namespace Emby.Server.Implementations.Dto
|
|||
{
|
||||
var hasFullSyncInfo = options.Fields.Contains(ItemFields.SyncInfo);
|
||||
|
||||
if (!options.Fields.Contains(ItemFields.BasicSyncInfo) &&
|
||||
!hasFullSyncInfo)
|
||||
if (!hasFullSyncInfo && !options.Fields.Contains(ItemFields.BasicSyncInfo))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -496,6 +496,7 @@
|
|||
<Compile Include="Services\ServiceController.cs" />
|
||||
<Compile Include="Services\ServiceExec.cs" />
|
||||
<Compile Include="Services\StringMapTypeDeserializer.cs" />
|
||||
<Compile Include="Services\SwaggerService.cs" />
|
||||
<Compile Include="Services\UrlExtensions.cs" />
|
||||
<Compile Include="Session\HttpSessionController.cs" />
|
||||
<Compile Include="Session\SessionManager.cs" />
|
||||
|
|
183
Emby.Server.Implementations/Services/SwaggerService.cs
Normal file
183
Emby.Server.Implementations/Services/SwaggerService.cs
Normal file
|
@ -0,0 +1,183 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Services;
|
||||
|
||||
namespace Emby.Server.Implementations.Services
|
||||
{
|
||||
[Route("/swagger", "GET", Summary = "Gets the swagger specifications")]
|
||||
[Route("/swagger.json", "GET", Summary = "Gets the swagger specifications")]
|
||||
public class GetSwaggerSpec : IReturn<SwaggerSpec>
|
||||
{
|
||||
}
|
||||
|
||||
public class SwaggerSpec
|
||||
{
|
||||
public string swagger { get; set; }
|
||||
public string[] schemes { get; set; }
|
||||
public SwaggerInfo info { get; set; }
|
||||
public string host { get; set; }
|
||||
public string basePath { get; set; }
|
||||
public SwaggerTag[] tags { get; set; }
|
||||
public Dictionary<string, Dictionary<string, SwaggerMethod>> paths { get; set; }
|
||||
public Dictionary<string, SwaggerDefinition> definitions { get; set; }
|
||||
}
|
||||
|
||||
public class SwaggerInfo
|
||||
{
|
||||
public string description { get; set; }
|
||||
public string version { get; set; }
|
||||
public string title { get; set; }
|
||||
|
||||
public SwaggerConcactInfo contact { get; set; }
|
||||
}
|
||||
|
||||
public class SwaggerConcactInfo
|
||||
{
|
||||
public string email { get; set; }
|
||||
}
|
||||
|
||||
public class SwaggerTag
|
||||
{
|
||||
public string description { get; set; }
|
||||
public string name { get; set; }
|
||||
}
|
||||
|
||||
public class SwaggerMethod
|
||||
{
|
||||
public string summary { get; set; }
|
||||
public string description { get; set; }
|
||||
public string[] tags { get; set; }
|
||||
public string operationId { get; set; }
|
||||
public string[] consumes { get; set; }
|
||||
public string[] produces { get; set; }
|
||||
public SwaggerParam[] parameters { get; set; }
|
||||
public Dictionary<string, SwaggerResponse> responses { get; set; }
|
||||
}
|
||||
|
||||
public class SwaggerParam
|
||||
{
|
||||
public string @in { get; set; }
|
||||
public string name { get; set; }
|
||||
public string description { get; set; }
|
||||
public bool required { get; set; }
|
||||
public string type { get; set; }
|
||||
public string collectionFormat { get; set; }
|
||||
}
|
||||
|
||||
public class SwaggerResponse
|
||||
{
|
||||
public string description { get; set; }
|
||||
|
||||
// ex. "$ref":"#/definitions/Pet"
|
||||
public Dictionary<string, string> schema { get; set; }
|
||||
}
|
||||
|
||||
public class SwaggerDefinition
|
||||
{
|
||||
public string type { get; set; }
|
||||
public Dictionary<string, SwaggerProperty> properties { get; set; }
|
||||
}
|
||||
|
||||
public class SwaggerProperty
|
||||
{
|
||||
public string type { get; set; }
|
||||
public string format { get; set; }
|
||||
public string description { get; set; }
|
||||
public string[] @enum { get; set; }
|
||||
public string @default { get; set; }
|
||||
}
|
||||
|
||||
public class SwaggerService : IService
|
||||
{
|
||||
private SwaggerSpec _spec;
|
||||
|
||||
public object Get(GetSwaggerSpec request)
|
||||
{
|
||||
return _spec ?? (_spec = GetSpec());
|
||||
}
|
||||
|
||||
private SwaggerSpec GetSpec()
|
||||
{
|
||||
var spec = new SwaggerSpec
|
||||
{
|
||||
schemes = new[] { "http" },
|
||||
tags = GetTags(),
|
||||
swagger = "2.0",
|
||||
info = new SwaggerInfo
|
||||
{
|
||||
title = "Emby Server API",
|
||||
version = "1",
|
||||
description = "Explore the Emby Server API",
|
||||
contact = new SwaggerConcactInfo
|
||||
{
|
||||
email = "api@emby.media"
|
||||
}
|
||||
},
|
||||
paths = GetPaths(),
|
||||
definitions = GetDefinitions()
|
||||
};
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
|
||||
private SwaggerTag[] GetTags()
|
||||
{
|
||||
return new SwaggerTag[] { };
|
||||
}
|
||||
|
||||
private Dictionary<string, SwaggerDefinition> GetDefinitions()
|
||||
{
|
||||
return new Dictionary<string, SwaggerDefinition>();
|
||||
}
|
||||
|
||||
private Dictionary<string, Dictionary<string, SwaggerMethod>> GetPaths()
|
||||
{
|
||||
var paths = new Dictionary<string, Dictionary<string, SwaggerMethod>>();
|
||||
|
||||
var all = ServiceController.Instance.RestPathMap.ToList();
|
||||
|
||||
foreach (var current in all)
|
||||
{
|
||||
foreach (var info in current.Value)
|
||||
{
|
||||
paths[info.Path] = GetPathInfo(info);
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
private Dictionary<string, SwaggerMethod> GetPathInfo(RestPath info)
|
||||
{
|
||||
var result = new Dictionary<string, SwaggerMethod>();
|
||||
|
||||
foreach (var verb in info.Verbs)
|
||||
{
|
||||
result[verb] = new SwaggerMethod
|
||||
{
|
||||
summary = info.Summary,
|
||||
produces = new[]
|
||||
{
|
||||
"application/json",
|
||||
"application/xml"
|
||||
},
|
||||
consumes = new[]
|
||||
{
|
||||
"application/json",
|
||||
"application/xml"
|
||||
},
|
||||
operationId = info.RequestType.Name,
|
||||
tags = new string[] { },
|
||||
|
||||
parameters = new SwaggerParam[] { }
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -567,7 +567,7 @@ namespace MediaBrowser.Api.Images
|
|||
cropwhitespace = request.CropWhitespace.Value;
|
||||
}
|
||||
|
||||
var outputFormats = GetOutputFormats(request, imageInfo, cropwhitespace, supportedImageEnhancers);
|
||||
var outputFormats = GetOutputFormats(request);
|
||||
|
||||
TimeSpan? cacheDuration = null;
|
||||
|
||||
|
@ -597,7 +597,7 @@ namespace MediaBrowser.Api.Images
|
|||
ImageRequest request,
|
||||
ItemImageInfo image,
|
||||
bool cropwhitespace,
|
||||
List<ImageFormat> supportedFormats,
|
||||
ImageFormat[] supportedFormats,
|
||||
List<IImageEnhancer> enhancers,
|
||||
TimeSpan? cacheDuration,
|
||||
IDictionary<string, string> headers,
|
||||
|
@ -644,55 +644,18 @@ namespace MediaBrowser.Api.Images
|
|||
}).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private List<ImageFormat> GetOutputFormats(ImageRequest request, ItemImageInfo image, bool cropwhitespace, List<IImageEnhancer> enhancers)
|
||||
private ImageFormat[] GetOutputFormats(ImageRequest request)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(request.Format))
|
||||
{
|
||||
ImageFormat format;
|
||||
if (Enum.TryParse(request.Format, true, out format))
|
||||
{
|
||||
return new List<ImageFormat> { format };
|
||||
return new ImageFormat[] { format };
|
||||
}
|
||||
}
|
||||
|
||||
var extension = Path.GetExtension(image.Path);
|
||||
ImageFormat? inputFormat = null;
|
||||
|
||||
if (string.Equals(extension, ".jpg", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(extension, ".jpeg", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
inputFormat = ImageFormat.Jpg;
|
||||
}
|
||||
else if (string.Equals(extension, ".png", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
inputFormat = ImageFormat.Png;
|
||||
}
|
||||
|
||||
var clientSupportedFormats = GetClientSupportedFormats();
|
||||
|
||||
var serverFormats = _imageProcessor.GetSupportedImageOutputFormats();
|
||||
var outputFormats = new List<ImageFormat>();
|
||||
|
||||
// Client doesn't care about format, so start with webp if supported
|
||||
if (serverFormats.Contains(ImageFormat.Webp) && clientSupportedFormats.Contains(ImageFormat.Webp))
|
||||
{
|
||||
outputFormats.Add(ImageFormat.Webp);
|
||||
}
|
||||
|
||||
if (enhancers.Count > 0)
|
||||
{
|
||||
outputFormats.Add(ImageFormat.Png);
|
||||
}
|
||||
|
||||
if (inputFormat.HasValue && inputFormat.Value == ImageFormat.Jpg)
|
||||
{
|
||||
outputFormats.Add(ImageFormat.Jpg);
|
||||
}
|
||||
|
||||
// We can't predict if there will be transparency or not, so play it safe
|
||||
outputFormats.Add(ImageFormat.Png);
|
||||
|
||||
return outputFormats;
|
||||
return GetClientSupportedFormats();
|
||||
}
|
||||
|
||||
private ImageFormat[] GetClientSupportedFormats()
|
||||
|
|
|
@ -408,6 +408,20 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
}).Where(i => i != null).Select(i => i.Id.ToString("N")).ToArray();
|
||||
}
|
||||
|
||||
// Apply default sorting if none requested
|
||||
if (query.OrderBy.Length == 0)
|
||||
{
|
||||
// Albums by artist
|
||||
if (query.ArtistIds.Length > 0 && query.IncludeItemTypes.Length == 1 && string.Equals(query.IncludeItemTypes[0], "MusicAlbum", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
query.OrderBy = new Tuple<string, SortOrder>[]
|
||||
{
|
||||
new Tuple<string, SortOrder>(ItemSortBy.ProductionYear, SortOrder.Descending),
|
||||
new Tuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,5 +118,7 @@ namespace MediaBrowser.Controller.Drawing
|
|||
IImageEncoder ImageEncoder { get; set; }
|
||||
|
||||
void SaveImageSize(string path, DateTime imageDateModified, ImageSize size);
|
||||
|
||||
bool SupportsTransparency(string path);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,11 @@ namespace MediaBrowser.Controller.Drawing
|
|||
{
|
||||
public class ImageProcessingOptions
|
||||
{
|
||||
public ImageProcessingOptions()
|
||||
{
|
||||
RequiresAutoOrientation = true;
|
||||
}
|
||||
|
||||
public string ItemId { get; set; }
|
||||
public string ItemType { get; set; }
|
||||
public IHasMetadata Item { get; set; }
|
||||
|
@ -32,7 +37,7 @@ namespace MediaBrowser.Controller.Drawing
|
|||
|
||||
public List<IImageEnhancer> Enhancers { get; set; }
|
||||
|
||||
public List<ImageFormat> SupportedOutputFormats { get; set; }
|
||||
public ImageFormat[] SupportedOutputFormats { get; set; }
|
||||
|
||||
public bool AddPlayedIndicator { get; set; }
|
||||
|
||||
|
@ -43,6 +48,7 @@ namespace MediaBrowser.Controller.Drawing
|
|||
|
||||
public string BackgroundColor { get; set; }
|
||||
public string ForegroundLayer { get; set; }
|
||||
public bool RequiresAutoOrientation { get; set; }
|
||||
|
||||
public bool HasDefaultOptions(string originalImagePath)
|
||||
{
|
||||
|
|
|
@ -80,15 +80,43 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||
|
||||
protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
|
||||
{
|
||||
if (IsLegacyBoxSet)
|
||||
{
|
||||
return base.GetNonCachedChildren(directoryService);
|
||||
}
|
||||
return new List<BaseItem>();
|
||||
}
|
||||
|
||||
protected override List<BaseItem> LoadChildren()
|
||||
{
|
||||
if (IsLegacyBoxSet)
|
||||
{
|
||||
return base.LoadChildren();
|
||||
}
|
||||
|
||||
// Save a trip to the database
|
||||
return new List<BaseItem>();
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
private bool IsLegacyBoxSet
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Path))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LinkedChildren.Length > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return !FileSystem.ContainsSubPath(ConfigurationManager.ApplicationPaths.DataPath, Path);
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override bool IsPreSorted
|
||||
{
|
||||
|
|
|
@ -1568,6 +1568,11 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
inputModifier += " " + GetFastSeekCommandLineParameter(state.BaseRequest);
|
||||
inputModifier = inputModifier.Trim();
|
||||
|
||||
if (state.InputProtocol == MediaProtocol.Rtsp)
|
||||
{
|
||||
inputModifier += " -rtsp_transport tcp";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(state.InputAudioSync))
|
||||
{
|
||||
inputModifier += " -async " + state.InputAudioSync;
|
||||
|
@ -1578,7 +1583,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
inputModifier += " -vsync " + state.InputVideoSync;
|
||||
}
|
||||
|
||||
if (state.ReadInputAtNativeFramerate)
|
||||
if (state.ReadInputAtNativeFramerate && state.InputProtocol != MediaProtocol.Rtsp)
|
||||
{
|
||||
inputModifier += " -re";
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ namespace MediaBrowser.Controller.Providers
|
|||
/// <returns>ImageSize.</returns>
|
||||
ImageSize GetEnhancedImageSize(IHasMetadata item, ImageType imageType, int imageIndex, ImageSize originalImageSize);
|
||||
|
||||
EnhancedImageInfo GetEnhancedImageInfo(IHasMetadata item, string inputFile, ImageType imageType, int imageIndex);
|
||||
|
||||
/// <summary>
|
||||
/// Enhances the image async.
|
||||
/// </summary>
|
||||
|
@ -51,4 +53,9 @@ namespace MediaBrowser.Controller.Providers
|
|||
/// <exception cref="System.ArgumentNullException"></exception>
|
||||
Task EnhanceImageAsync(IHasMetadata item, string inputFile, string outputFile, ImageType imageType, int imageIndex);
|
||||
}
|
||||
|
||||
public class EnhancedImageInfo
|
||||
{
|
||||
public bool RequiresTransparency { get; set; }
|
||||
}
|
||||
}
|
|
@ -849,8 +849,6 @@ namespace MediaBrowser.Model.Dlna
|
|||
}
|
||||
}
|
||||
}
|
||||
ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);
|
||||
|
||||
// Honor requested max channels
|
||||
if (options.MaxAudioChannels.HasValue)
|
||||
{
|
||||
|
@ -878,6 +876,9 @@ namespace MediaBrowser.Model.Dlna
|
|||
var longBitrate = Math.Max(Math.Min(videoBitrate, currentValue), 64000);
|
||||
playlistItem.VideoBitrate = longBitrate > int.MaxValue ? int.MaxValue : Convert.ToInt32(longBitrate);
|
||||
}
|
||||
|
||||
// Do this after initial values are set to account for greater than/less than conditions
|
||||
ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);
|
||||
}
|
||||
|
||||
playlistItem.TranscodeReasons = transcodeReasons;
|
||||
|
@ -1429,18 +1430,40 @@ namespace MediaBrowser.Model.Dlna
|
|||
{
|
||||
int num;
|
||||
if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
|
||||
{
|
||||
if (condition.Condition == ProfileConditionType.Equals)
|
||||
{
|
||||
item.AudioBitrate = num;
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.LessThanEqual)
|
||||
{
|
||||
item.AudioBitrate = Math.Min(num, item.AudioBitrate ?? num);
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.GreaterThanEqual)
|
||||
{
|
||||
item.AudioBitrate = Math.Max(num, item.AudioBitrate ?? num);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ProfileConditionValue.AudioChannels:
|
||||
{
|
||||
int num;
|
||||
if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
|
||||
{
|
||||
if (condition.Condition == ProfileConditionType.Equals)
|
||||
{
|
||||
item.MaxAudioChannels = num;
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.LessThanEqual)
|
||||
{
|
||||
item.MaxAudioChannels = Math.Min(num, item.MaxAudioChannels ?? num);
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.GreaterThanEqual)
|
||||
{
|
||||
item.MaxAudioChannels = Math.Max(num, item.MaxAudioChannels ?? num);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ProfileConditionValue.IsAvc:
|
||||
|
@ -1506,18 +1529,40 @@ namespace MediaBrowser.Model.Dlna
|
|||
{
|
||||
int num;
|
||||
if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
|
||||
{
|
||||
if (condition.Condition == ProfileConditionType.Equals)
|
||||
{
|
||||
item.MaxRefFrames = num;
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.LessThanEqual)
|
||||
{
|
||||
item.MaxRefFrames = Math.Min(num, item.MaxRefFrames ?? num);
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.GreaterThanEqual)
|
||||
{
|
||||
item.MaxRefFrames = Math.Max(num, item.MaxRefFrames ?? num);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ProfileConditionValue.VideoBitDepth:
|
||||
{
|
||||
int num;
|
||||
if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
|
||||
{
|
||||
if (condition.Condition == ProfileConditionType.Equals)
|
||||
{
|
||||
item.MaxVideoBitDepth = num;
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.LessThanEqual)
|
||||
{
|
||||
item.MaxVideoBitDepth = Math.Min(num, item.MaxVideoBitDepth ?? num);
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.GreaterThanEqual)
|
||||
{
|
||||
item.MaxVideoBitDepth = Math.Max(num, item.MaxVideoBitDepth ?? num);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ProfileConditionValue.VideoProfile:
|
||||
|
@ -1529,45 +1574,100 @@ namespace MediaBrowser.Model.Dlna
|
|||
{
|
||||
int num;
|
||||
if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
|
||||
{
|
||||
if (condition.Condition == ProfileConditionType.Equals)
|
||||
{
|
||||
item.MaxHeight = num;
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.LessThanEqual)
|
||||
{
|
||||
item.MaxHeight = Math.Min(num, item.MaxHeight ?? num);
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.GreaterThanEqual)
|
||||
{
|
||||
item.MaxHeight = Math.Max(num, item.MaxHeight ?? num);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ProfileConditionValue.VideoBitrate:
|
||||
{
|
||||
int num;
|
||||
if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
|
||||
{
|
||||
if (condition.Condition == ProfileConditionType.Equals)
|
||||
{
|
||||
item.VideoBitrate = num;
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.LessThanEqual)
|
||||
{
|
||||
item.VideoBitrate = Math.Min(num, item.VideoBitrate ?? num);
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.GreaterThanEqual)
|
||||
{
|
||||
item.VideoBitrate = Math.Max(num, item.VideoBitrate ?? num);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ProfileConditionValue.VideoFramerate:
|
||||
{
|
||||
float num;
|
||||
if (float.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
|
||||
{
|
||||
if (condition.Condition == ProfileConditionType.Equals)
|
||||
{
|
||||
item.MaxFramerate = num;
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.LessThanEqual)
|
||||
{
|
||||
item.MaxFramerate = Math.Min(num, item.MaxFramerate ?? num);
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.GreaterThanEqual)
|
||||
{
|
||||
item.MaxFramerate = Math.Max(num, item.MaxFramerate ?? num);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ProfileConditionValue.VideoLevel:
|
||||
{
|
||||
int num;
|
||||
if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
|
||||
{
|
||||
if (condition.Condition == ProfileConditionType.Equals)
|
||||
{
|
||||
item.VideoLevel = num;
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.LessThanEqual)
|
||||
{
|
||||
item.VideoLevel = Math.Min(num, item.VideoLevel ?? num);
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.GreaterThanEqual)
|
||||
{
|
||||
item.VideoLevel = Math.Max(num, item.VideoLevel ?? num);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ProfileConditionValue.Width:
|
||||
{
|
||||
int num;
|
||||
if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
|
||||
{
|
||||
if (condition.Condition == ProfileConditionType.Equals)
|
||||
{
|
||||
item.MaxWidth = num;
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.LessThanEqual)
|
||||
{
|
||||
item.MaxWidth = Math.Min(num, item.MaxWidth ?? num);
|
||||
}
|
||||
else if (condition.Condition == ProfileConditionType.GreaterThanEqual)
|
||||
{
|
||||
item.MaxWidth = Math.Max(num, item.MaxWidth ?? num);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyVersion("3.2.30.8")]
|
||||
[assembly: AssemblyVersion("3.2.30.9")]
|
||||
|
|
Loading…
Reference in New Issue
Block a user