Conflicts:
	MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
This commit is contained in:
Tavares André 2015-04-20 19:07:29 +02:00
commit 64b8be1b39
24 changed files with 204 additions and 126 deletions

View file

@ -158,22 +158,19 @@ namespace Emby.Drawing
} }
var dateModified = options.Image.DateModified; var dateModified = options.Image.DateModified;
var length = options.Image.Length;
if (options.CropWhiteSpace) if (options.CropWhiteSpace)
{ {
var tuple = await GetWhitespaceCroppedImage(originalImagePath, dateModified, length).ConfigureAwait(false); var tuple = await GetWhitespaceCroppedImage(originalImagePath, dateModified).ConfigureAwait(false);
originalImagePath = tuple.Item1; originalImagePath = tuple.Item1;
dateModified = tuple.Item2; dateModified = tuple.Item2;
length = tuple.Item3;
} }
if (options.Enhancers.Count > 0) if (options.Enhancers.Count > 0)
{ {
var tuple = await GetEnhancedImage(new ItemImageInfo var tuple = await GetEnhancedImage(new ItemImageInfo
{ {
Length = length,
DateModified = dateModified, DateModified = dateModified,
Type = options.Image.Type, Type = options.Image.Type,
Path = originalImagePath Path = originalImagePath
@ -182,7 +179,6 @@ namespace Emby.Drawing
originalImagePath = tuple.Item1; originalImagePath = tuple.Item1;
dateModified = tuple.Item2; dateModified = tuple.Item2;
length = tuple.Item3;
} }
var originalImageSize = GetImageSize(originalImagePath, dateModified); var originalImageSize = GetImageSize(originalImagePath, dateModified);
@ -199,7 +195,7 @@ namespace Emby.Drawing
var quality = options.Quality ?? 90; var quality = options.Quality ?? 90;
var outputFormat = GetOutputFormat(options.OutputFormat); var outputFormat = GetOutputFormat(options.OutputFormat);
var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, length, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.BackgroundColor); var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.BackgroundColor);
var semaphore = GetLock(cacheFilePath); var semaphore = GetLock(cacheFilePath);
@ -240,11 +236,10 @@ namespace Emby.Drawing
/// <summary> /// <summary>
/// Crops whitespace from an image, caches the result, and returns the cached path /// Crops whitespace from an image, caches the result, and returns the cached path
/// </summary> /// </summary>
private async Task<Tuple<string, DateTime, long>> GetWhitespaceCroppedImage(string originalImagePath, DateTime dateModified, long length) private async Task<Tuple<string, DateTime>> GetWhitespaceCroppedImage(string originalImagePath, DateTime dateModified)
{ {
var name = originalImagePath; var name = originalImagePath;
name += "datemodified=" + dateModified.Ticks; name += "datemodified=" + dateModified.Ticks;
name += "length=" + length;
var croppedImagePath = GetCachePath(CroppedWhitespaceImageCachePath, name, Path.GetExtension(originalImagePath)); var croppedImagePath = GetCachePath(CroppedWhitespaceImageCachePath, name, Path.GetExtension(originalImagePath));
@ -270,7 +265,7 @@ namespace Emby.Drawing
// We have to have a catch-all here because some of the .net image methods throw a plain old Exception // We have to have a catch-all here because some of the .net image methods throw a plain old Exception
_logger.ErrorException("Error cropping image {0}", ex, originalImagePath); _logger.ErrorException("Error cropping image {0}", ex, originalImagePath);
return new Tuple<string, DateTime, long>(originalImagePath, dateModified, length); return new Tuple<string, DateTime>(originalImagePath, dateModified);
} }
finally finally
{ {
@ -280,11 +275,9 @@ namespace Emby.Drawing
return GetResult(croppedImagePath); return GetResult(croppedImagePath);
} }
private Tuple<string, DateTime, long> GetResult(string path) private Tuple<string, DateTime> GetResult(string path)
{ {
var file = new FileInfo(path); return new Tuple<string, DateTime>(path, _fileSystem.GetLastWriteTimeUtc(path));
return new Tuple<string, DateTime, long>(path, _fileSystem.GetLastWriteTimeUtc(file), file.Length);
} }
/// <summary> /// <summary>
@ -295,7 +288,7 @@ namespace Emby.Drawing
/// <summary> /// <summary>
/// Gets the cache file path based on a set of parameters /// Gets the cache file path based on a set of parameters
/// </summary> /// </summary>
private string GetCacheFilePath(string originalPath, ImageSize outputSize, int quality, DateTime dateModified, long length, ImageFormat format, bool addPlayedIndicator, double percentPlayed, int? unwatchedCount, string backgroundColor) private string GetCacheFilePath(string originalPath, ImageSize outputSize, int quality, DateTime dateModified, ImageFormat format, bool addPlayedIndicator, double percentPlayed, int? unwatchedCount, string backgroundColor)
{ {
var filename = originalPath; var filename = originalPath;
@ -306,7 +299,6 @@ namespace Emby.Drawing
filename += "quality=" + quality; filename += "quality=" + quality;
filename += "datemodified=" + dateModified.Ticks; filename += "datemodified=" + dateModified.Ticks;
filename += "length=" + length;
filename += "f=" + format; filename += "f=" + format;
@ -492,17 +484,16 @@ namespace Emby.Drawing
var originalImagePath = image.Path; var originalImagePath = image.Path;
var dateModified = image.DateModified; var dateModified = image.DateModified;
var imageType = image.Type; var imageType = image.Type;
var length = image.Length;
// Optimization // Optimization
if (imageEnhancers.Count == 0) if (imageEnhancers.Count == 0)
{ {
return (originalImagePath + dateModified.Ticks + string.Empty + length).GetMD5().ToString("N"); return (originalImagePath + dateModified.Ticks).GetMD5().ToString("N");
} }
// Cache name is created with supported enhancers combined with the last config change so we pick up new config changes // Cache name is created with supported enhancers combined with the last config change so we pick up new config changes
var cacheKeys = imageEnhancers.Select(i => i.GetConfigurationCacheKey(item, imageType)).ToList(); var cacheKeys = imageEnhancers.Select(i => i.GetConfigurationCacheKey(item, imageType)).ToList();
cacheKeys.Add(originalImagePath + dateModified.Ticks + string.Empty + length); cacheKeys.Add(originalImagePath + dateModified.Ticks);
return string.Join("|", cacheKeys.ToArray()).GetMD5().ToString("N"); return string.Join("|", cacheKeys.ToArray()).GetMD5().ToString("N");
} }
@ -525,7 +516,7 @@ namespace Emby.Drawing
return result.Item1; return result.Item1;
} }
private async Task<Tuple<string, DateTime, long>> GetEnhancedImage(ItemImageInfo image, private async Task<Tuple<string, DateTime>> GetEnhancedImage(ItemImageInfo image,
IHasImages item, IHasImages item,
int imageIndex, int imageIndex,
List<IImageEnhancer> enhancers) List<IImageEnhancer> enhancers)
@ -533,7 +524,6 @@ namespace Emby.Drawing
var originalImagePath = image.Path; var originalImagePath = image.Path;
var dateModified = image.DateModified; var dateModified = image.DateModified;
var imageType = image.Type; var imageType = image.Type;
var length = image.Length;
try try
{ {
@ -553,7 +543,7 @@ namespace Emby.Drawing
_logger.Error("Error enhancing image", ex); _logger.Error("Error enhancing image", ex);
} }
return new Tuple<string, DateTime, long>(originalImagePath, dateModified, length); return new Tuple<string, DateTime>(originalImagePath, dateModified);
} }
/// <summary> /// <summary>

View file

@ -331,7 +331,6 @@ namespace MediaBrowser.Api
return; return;
} }
// TODO: Lower this hls timeout
var timerDuration = job.Type == TranscodingJobType.Progressive ? var timerDuration = job.Type == TranscodingJobType.Progressive ?
1000 : 1000 :
1800000; 1800000;
@ -342,14 +341,17 @@ namespace MediaBrowser.Api
timerDuration = 60000; timerDuration = 60000;
} }
job.PingTimeout = timerDuration;
job.LastPingDate = DateTime.UtcNow;
// Don't start the timer for playback checkins with progressive streaming // Don't start the timer for playback checkins with progressive streaming
if (job.Type != TranscodingJobType.Progressive || !isProgressCheckIn) if (job.Type != TranscodingJobType.Progressive || !isProgressCheckIn)
{ {
job.StartKillTimer(timerDuration, OnTranscodeKillTimerStopped); job.StartKillTimer(OnTranscodeKillTimerStopped);
} }
else else
{ {
job.ChangeKillTimerIfStarted(timerDuration); job.ChangeKillTimerIfStarted();
} }
} }
@ -361,6 +363,15 @@ namespace MediaBrowser.Api
{ {
var job = (TranscodingJob)state; var job = (TranscodingJob)state;
if (!job.HasExited && job.Type != TranscodingJobType.Progressive)
{
if ((DateTime.UtcNow - job.LastPingDate).TotalMilliseconds < job.PingTimeout)
{
job.StartKillTimer(OnTranscodeKillTimerStopped);
return;
}
}
Logger.Debug("Transcoding kill timer stopped for JobId {0} PlaySessionId {1}. Killing transcoding", job.Id, job.PlaySessionId); Logger.Debug("Transcoding kill timer stopped for JobId {0} PlaySessionId {1}. Killing transcoding", job.Id, job.PlaySessionId);
KillTranscodingJob(job, path => true); KillTranscodingJob(job, path => true);
@ -627,6 +638,9 @@ namespace MediaBrowser.Api
private readonly object _timerLock = new object(); private readonly object _timerLock = new object();
public DateTime LastPingDate { get; set; }
public int PingTimeout { get; set; }
public TranscodingJob(ILogger logger) public TranscodingJob(ILogger logger)
{ {
Logger = logger; Logger = logger;
@ -655,12 +669,14 @@ namespace MediaBrowser.Api
} }
} }
public void StartKillTimer(int intervalMs, TimerCallback callback) public void StartKillTimer(TimerCallback callback)
{ {
CheckHasExited(); CheckHasExited();
lock (_timerLock) lock (_timerLock)
{ {
var intervalMs = PingTimeout;
if (KillTimer == null) if (KillTimer == null)
{ {
Logger.Debug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId); Logger.Debug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
@ -674,7 +690,7 @@ namespace MediaBrowser.Api
} }
} }
public void ChangeKillTimerIfStarted(int intervalMs) public void ChangeKillTimerIfStarted()
{ {
CheckHasExited(); CheckHasExited();
@ -682,6 +698,8 @@ namespace MediaBrowser.Api
{ {
if (KillTimer != null) if (KillTimer != null)
{ {
var intervalMs = PingTimeout;
Logger.Debug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId); Logger.Debug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
KillTimer.Change(intervalMs, Timeout.Infinite); KillTimer.Change(intervalMs, Timeout.Infinite);
} }

View file

@ -88,7 +88,7 @@ namespace MediaBrowser.Api.UserLibrary
var views = user.RootFolder var views = user.RootFolder
.GetChildren(user, true) .GetChildren(user, true)
.OfType<CollectionFolder>() .OfType<ICollectionFolder>()
.Where(i => IsEligibleForSpecialView(i)) .Where(i => IsEligibleForSpecialView(i))
.ToList(); .ToList();
@ -105,9 +105,9 @@ namespace MediaBrowser.Api.UserLibrary
return ToOptimizedResult(list); return ToOptimizedResult(list);
} }
private bool IsEligibleForSpecialView(CollectionFolder view) private bool IsEligibleForSpecialView(ICollectionFolder view)
{ {
var types = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Games, CollectionType.Music }; var types = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Games, CollectionType.Music, CollectionType.Photos };
return types.Contains(view.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase); return types.Contains(view.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
} }

View file

@ -1512,7 +1512,6 @@ namespace MediaBrowser.Controller.Entities
image.Path = file.FullName; image.Path = file.FullName;
image.DateModified = imageInfo.DateModified; image.DateModified = imageInfo.DateModified;
image.Length = imageInfo.Length;
} }
} }
@ -1622,14 +1621,11 @@ namespace MediaBrowser.Controller.Entities
return null; return null;
} }
var fileInfo = new FileInfo(path);
return new ItemImageInfo return new ItemImageInfo
{ {
Path = path, Path = path,
DateModified = FileSystem.GetLastWriteTimeUtc(fileInfo), DateModified = FileSystem.GetLastWriteTimeUtc(path),
Type = imageType, Type = imageType
Length = fileInfo.Length
}; };
} }
@ -1690,7 +1686,6 @@ namespace MediaBrowser.Controller.Entities
else else
{ {
existing.DateModified = FileSystem.GetLastWriteTimeUtc(newImage); existing.DateModified = FileSystem.GetLastWriteTimeUtc(newImage);
existing.Length = ((FileInfo)newImage).Length;
} }
} }
@ -1716,8 +1711,7 @@ namespace MediaBrowser.Controller.Entities
{ {
Path = file.FullName, Path = file.FullName,
Type = type, Type = type,
DateModified = FileSystem.GetLastWriteTimeUtc(file), DateModified = FileSystem.GetLastWriteTimeUtc(file)
Length = ((FileInfo)file).Length
}; };
} }
@ -1756,15 +1750,9 @@ namespace MediaBrowser.Controller.Entities
FileSystem.SwapFiles(path1, path2); FileSystem.SwapFiles(path1, path2);
var file1 = new FileInfo(info1.Path);
var file2 = new FileInfo(info2.Path);
// Refresh these values // Refresh these values
info1.DateModified = FileSystem.GetLastWriteTimeUtc(file1); info1.DateModified = FileSystem.GetLastWriteTimeUtc(info1.Path);
info2.DateModified = FileSystem.GetLastWriteTimeUtc(file2); info2.DateModified = FileSystem.GetLastWriteTimeUtc(info2.Path);
info1.Length = file1.Length;
info2.Length = file2.Length;
return UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); return UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
} }

View file

@ -11,12 +11,6 @@ namespace MediaBrowser.Controller.Entities
/// <value>The path.</value> /// <value>The path.</value>
public string Path { get; set; } public string Path { get; set; }
/// <summary>
/// Gets or sets the length.
/// </summary>
/// <value>The length.</value>
public long Length { get; set; }
/// <summary> /// <summary>
/// Gets or sets the type. /// Gets or sets the type.
/// </summary> /// </summary>

View file

@ -121,7 +121,6 @@ namespace MediaBrowser.Controller.Entities
} }
case CollectionType.Books: case CollectionType.Books:
case CollectionType.Photos:
case CollectionType.HomeVideos: case CollectionType.HomeVideos:
case CollectionType.MusicVideos: case CollectionType.MusicVideos:
return GetResult(queryParent.GetChildren(user, true), queryParent, query); return GetResult(queryParent.GetChildren(user, true), queryParent, query);
@ -138,6 +137,9 @@ namespace MediaBrowser.Controller.Entities
case CollectionType.BoxSets: case CollectionType.BoxSets:
return await GetBoxsetView(queryParent, user, query).ConfigureAwait(false); return await GetBoxsetView(queryParent, user, query).ConfigureAwait(false);
case CollectionType.Photos:
return await GetPhotosView(queryParent, user, query).ConfigureAwait(false);
case CollectionType.TvShows: case CollectionType.TvShows:
return await GetTvView(queryParent, user, query).ConfigureAwait(false); return await GetTvView(queryParent, user, query).ConfigureAwait(false);
@ -247,16 +249,16 @@ namespace MediaBrowser.Controller.Entities
return GetFavoriteSongs(queryParent, user, query); return GetFavoriteSongs(queryParent, user, query);
default: default:
{
if (queryParent is UserView)
{ {
return GetResult(GetMediaFolders(user).SelectMany(i => i.GetChildren(user, true)), queryParent, query); if (queryParent is UserView)
{
return GetResult(GetMediaFolders(user).SelectMany(i => i.GetChildren(user, true)), queryParent, query);
}
else
{
return GetResult(queryParent.GetChildren(user, true), queryParent, query);
}
} }
else
{
return GetResult(queryParent.GetChildren(user, true), queryParent, query);
}
}
} }
} }
@ -645,6 +647,19 @@ namespace MediaBrowser.Controller.Entities
}), parent, query); }), parent, query);
} }
private async Task<QueryResult<BaseItem>> GetPhotosView(Folder queryParent, User user, InternalItemsQuery query)
{
if (query.Recursive)
{
var mediaTypes = new[] { MediaType.Video, MediaType.Photo };
var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Photos, string.Empty }, i => (i is PhotoAlbum || mediaTypes.Contains(i.MediaType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) && FilterItem(i, query));
return PostFilterAndSort(items, queryParent, null, query);
}
return GetResult(queryParent.GetChildren(user, true), queryParent, query);
}
private async Task<QueryResult<BaseItem>> GetTvView(Folder parent, User user, InternalItemsQuery query) private async Task<QueryResult<BaseItem>> GetTvView(Folder parent, User user, InternalItemsQuery query)
{ {
if (query.Recursive) if (query.Recursive)

View file

@ -488,6 +488,9 @@
<Compile Include="..\MediaBrowser.Model\Dto\ItemIndex.cs"> <Compile Include="..\MediaBrowser.Model\Dto\ItemIndex.cs">
<Link>Dto\ItemIndex.cs</Link> <Link>Dto\ItemIndex.cs</Link>
</Compile> </Compile>
<Compile Include="..\MediaBrowser.Model\Dto\ItemLayout.cs">
<Link>Dto\ItemLayout.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Dto\MediaSourceInfo.cs"> <Compile Include="..\MediaBrowser.Model\Dto\MediaSourceInfo.cs">
<Link>Dto\MediaSourceInfo.cs</Link> <Link>Dto\MediaSourceInfo.cs</Link>
</Compile> </Compile>

View file

@ -453,6 +453,9 @@
<Compile Include="..\MediaBrowser.Model\Dto\ItemIndex.cs"> <Compile Include="..\MediaBrowser.Model\Dto\ItemIndex.cs">
<Link>Dto\ItemIndex.cs</Link> <Link>Dto\ItemIndex.cs</Link>
</Compile> </Compile>
<Compile Include="..\MediaBrowser.Model\Dto\ItemLayout.cs">
<Link>Dto\ItemLayout.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Dto\MediaSourceInfo.cs"> <Compile Include="..\MediaBrowser.Model\Dto\MediaSourceInfo.cs">
<Link>Dto\MediaSourceInfo.cs</Link> <Link>Dto\MediaSourceInfo.cs</Link>
</Compile> </Compile>

View file

@ -98,7 +98,7 @@ namespace MediaBrowser.Model.ApiClient
{ {
var index = 0; var index = 0;
foreach (var server in servers) foreach (ServerInfo server in servers)
{ {
if (StringHelper.EqualsIgnoreCase(id, server.Id)) if (StringHelper.EqualsIgnoreCase(id, server.Id))
{ {
@ -110,5 +110,18 @@ namespace MediaBrowser.Model.ApiClient
return -1; return -1;
} }
public ServerInfo GetServer(string id)
{
foreach (ServerInfo server in Servers)
{
if (StringHelper.EqualsIgnoreCase(id, server.Id))
{
return server;
}
}
return null;
}
} }
} }

View file

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
namespace MediaBrowser.Model.Dto
{
public static class ItemLayout
{
public static double? GetDisplayAspectRatio(BaseItemDto item)
{
List<BaseItemDto> items = new List<BaseItemDto>();
items.Add(item);
return GetDisplayAspectRatio(items);
}
public static double? GetDisplayAspectRatio(List<BaseItemDto> items)
{
List<double> values = new List<double>();
foreach (BaseItemDto item in items)
{
if (item.PrimaryImageAspectRatio.HasValue)
{
values.Add(item.PrimaryImageAspectRatio.Value);
}
}
if (values.Count == 0)
{
return null;
}
values.Sort();
double halfDouble = values.Count;
halfDouble /= 2;
int half = Convert.ToInt32(Math.Floor(halfDouble));
double result;
if (values.Count % 2 > 0)
result = values[half];
else
result = (values[half - 1] + values[half]) / 2.0;
// If really close to 2:3 (poster image), just return 2:3
if (Math.Abs(0.66666666667 - result) <= .15)
{
return 0.66666666667;
}
// If really close to 16:9 (episode image), just return 16:9
if (Math.Abs(1.777777778 - result) <= .2)
{
return 1.777777778;
}
// If really close to 1 (square image), just return 1
if (Math.Abs(1 - result) <= .15)
{
return 1.0;
}
// If really close to 4:3 (poster image), just return 2:3
if (Math.Abs(1.33333333333 - result) <= .15)
{
return 1.33333333333;
}
return result;
}
}
}

View file

@ -139,6 +139,7 @@
<Compile Include="Drawing\ImageOrientation.cs" /> <Compile Include="Drawing\ImageOrientation.cs" />
<Compile Include="Dto\IHasServerId.cs" /> <Compile Include="Dto\IHasServerId.cs" />
<Compile Include="Dto\IHasSyncInfo.cs" /> <Compile Include="Dto\IHasSyncInfo.cs" />
<Compile Include="Dto\ItemLayout.cs" />
<Compile Include="Dto\MetadataEditorInfo.cs" /> <Compile Include="Dto\MetadataEditorInfo.cs" />
<Compile Include="Dto\NameIdPair.cs" /> <Compile Include="Dto\NameIdPair.cs" />
<Compile Include="Dto\NameValuePair.cs" /> <Compile Include="Dto\NameValuePair.cs" />

View file

@ -384,7 +384,6 @@ namespace MediaBrowser.Providers.Manager
else else
{ {
currentImage.DateModified = _fileSystem.GetLastWriteTimeUtc(image.FileInfo); currentImage.DateModified = _fileSystem.GetLastWriteTimeUtc(image.FileInfo);
currentImage.Length = ((FileInfo) image.FileInfo).Length;
} }
} }
else else

View file

@ -482,6 +482,11 @@ namespace MediaBrowser.Providers.Manager
protected virtual bool IsFullLocalMetadata(TItemType item) protected virtual bool IsFullLocalMetadata(TItemType item)
{ {
if (string.IsNullOrWhiteSpace(item.Name))
{
return false;
}
return true; return true;
} }

View file

@ -36,10 +36,6 @@ namespace MediaBrowser.Providers.Movies
protected override bool IsFullLocalMetadata(Movie item) protected override bool IsFullLocalMetadata(Movie item)
{ {
if (string.IsNullOrWhiteSpace(item.Name))
{
return false;
}
if (string.IsNullOrWhiteSpace(item.Overview)) if (string.IsNullOrWhiteSpace(item.Overview))
{ {
return false; return false;

View file

@ -77,10 +77,6 @@ namespace MediaBrowser.Providers.TV
protected override bool IsFullLocalMetadata(Series item) protected override bool IsFullLocalMetadata(Series item)
{ {
if (string.IsNullOrWhiteSpace(item.Name))
{
return false;
}
if (string.IsNullOrWhiteSpace(item.Overview)) if (string.IsNullOrWhiteSpace(item.Overview))
{ {
return false; return false;

View file

@ -243,7 +243,15 @@ namespace MediaBrowser.Providers.TV
await SanitizeXmlFile(file).ConfigureAwait(false); await SanitizeXmlFile(file).ConfigureAwait(false);
} }
await ExtractEpisodes(seriesDataPath, Path.Combine(seriesDataPath, saveAsMetadataLanguage + ".xml"), lastTvDbUpdateTime).ConfigureAwait(false); var downloadLangaugeXmlFile = Path.Combine(seriesDataPath, preferredMetadataLanguage + ".xml");
var saveAsLanguageXmlFile = Path.Combine(seriesDataPath, saveAsMetadataLanguage + ".xml");
if (!string.Equals(downloadLangaugeXmlFile, saveAsLanguageXmlFile, StringComparison.OrdinalIgnoreCase))
{
File.Copy(downloadLangaugeXmlFile, saveAsLanguageXmlFile, true);
}
await ExtractEpisodes(seriesDataPath, downloadLangaugeXmlFile, lastTvDbUpdateTime).ConfigureAwait(false);
} }
public TvdbOptions GetTvDbOptions() public TvdbOptions GetTvDbOptions()

View file

@ -828,14 +828,11 @@ namespace MediaBrowser.Server.Implementations.Dto
if (!string.IsNullOrEmpty(chapterInfo.ImagePath)) if (!string.IsNullOrEmpty(chapterInfo.ImagePath))
{ {
var file = new FileInfo(chapterInfo.ImagePath);
dto.ImageTag = GetImageCacheTag(item, new ItemImageInfo dto.ImageTag = GetImageCacheTag(item, new ItemImageInfo
{ {
Path = chapterInfo.ImagePath, Path = chapterInfo.ImagePath,
Type = ImageType.Chapter, Type = ImageType.Chapter,
DateModified = _fileSystem.GetLastWriteTimeUtc(file), DateModified = _fileSystem.GetLastWriteTimeUtc(chapterInfo.ImagePath)
Length = file.Length
}); });
} }

View file

@ -1,5 +1,4 @@
using System.Linq; using MediaBrowser.Controller;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
@ -139,55 +138,24 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
// On some systems the device discovered event seems to fire repeatedly // On some systems the device discovered event seems to fire repeatedly
// This check will help ensure we're not trying to port map the same device over and over // This check will help ensure we're not trying to port map the same device over and over
List<Mapping> currentMappings = null;
try
{
currentMappings = device.GetAllMappings().ToList();
}
catch (NotSupportedException)
{
}
var address = device.LocalAddress.ToString(); var address = device.LocalAddress.ToString();
if (!_createdRules.Contains(address)) if (!_createdRules.Contains(address))
{ {
_createdRules.Add(address); _createdRules.Add(address);
CreatePortMap(device, currentMappings, _appHost.HttpPort, _config.Configuration.PublicPort); CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort);
CreatePortMap(device, currentMappings, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort); CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort);
} }
} }
private void CreatePortMap(INatDevice device, List<Mapping> currentMappings, int privatePort, int publicPort) private void CreatePortMap(INatDevice device, int privatePort, int publicPort)
{ {
var hasMapping = false; _logger.Debug("Creating port map on port {0}", privatePort);
device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort)
if (currentMappings != null)
{ {
hasMapping = currentMappings.Any(i => i.PublicPort == publicPort && i.PrivatePort == privatePort); Description = _appHost.Name
} });
else
{
try
{
var mapping = device.GetSpecificMapping(Protocol.Tcp, publicPort);
hasMapping = mapping != null;
}
catch (NotSupportedException)
{
}
}
if (!hasMapping)
{
_logger.Debug("Creating port map on port {0}", privatePort);
device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort)
{
Description = _appHost.Name
});
}
} }
// As I said before, this method will be never invoked. You can remove it. // As I said before, this method will be never invoked. You can remove it.

View file

@ -1723,7 +1723,7 @@ namespace MediaBrowser.Server.Implementations.Library
await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false); await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
} }
var refresh = isNew || (DateTime.UtcNow - item.DateLastSaved).TotalHours >= 12; var refresh = isNew || (DateTime.UtcNow - item.DateLastSaved).TotalHours >= 24;
if (refresh) if (refresh)
{ {

View file

@ -202,9 +202,15 @@ namespace MediaBrowser.Server.Implementations.Library
public async Task<UserView> GetUserView(List<ICollectionFolder> parents, string viewType, string sortName, User user, CancellationToken cancellationToken) public async Task<UserView> GetUserView(List<ICollectionFolder> parents, string viewType, string sortName, User user, CancellationToken cancellationToken)
{ {
var name = _localizationManager.GetLocalizedString("ViewType" + viewType);
if (parents.Count == 1 && parents.All(i => string.Equals(i.CollectionType, viewType, StringComparison.OrdinalIgnoreCase))) if (parents.Count == 1 && parents.All(i => string.Equals(i.CollectionType, viewType, StringComparison.OrdinalIgnoreCase)))
{ {
var name = parents[0].Name; if (!string.IsNullOrWhiteSpace(parents[0].Name))
{
name = parents[0].Name;
}
var parentId = parents[0].Id; var parentId = parents[0].Id;
var enableRichView = !user.Configuration.PlainFolderViews.Contains(parentId.ToString("N"), StringComparer.OrdinalIgnoreCase); var enableRichView = !user.Configuration.PlainFolderViews.Contains(parentId.ToString("N"), StringComparer.OrdinalIgnoreCase);
@ -226,8 +232,6 @@ namespace MediaBrowser.Server.Implementations.Library
} }
else else
{ {
var name = _localizationManager.GetLocalizedString("ViewType" + viewType);
return await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false); return await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false);
} }
} }

View file

@ -122,7 +122,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private async Task AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken) private async Task AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken)
{ {
var inputPaths = new[] { mediaSource.Path }; var originalRuntime = mediaSource.RunTimeTicks;
var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
{ {
@ -131,8 +131,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video, MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video,
ExtractChapters = false ExtractChapters = false
}, cancellationToken) }, cancellationToken).ConfigureAwait(false);
.ConfigureAwait(false);
mediaSource.Bitrate = info.Bitrate; mediaSource.Bitrate = info.Bitrate;
mediaSource.Container = info.Container; mediaSource.Container = info.Container;
@ -146,6 +145,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
mediaSource.DefaultSubtitleStreamIndex = null; mediaSource.DefaultSubtitleStreamIndex = null;
// Null this out so that it will be treated like a live stream
if (!originalRuntime.HasValue)
{
mediaSource.RunTimeTicks = null;
}
var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio); var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio);
if (audioStream == null || audioStream.Index == -1) if (audioStream == null || audioStream.Index == -1)

View file

@ -1433,5 +1433,7 @@
"ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences.", "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences.",
"HeaderViewStyles": "View Styles", "HeaderViewStyles": "View Styles",
"LabelSelectViewStyles": "Enable rich presentations for:", "LabelSelectViewStyles": "Enable rich presentations for:",
"LabelSelectViewStylesHelp": "If enabled, views will be built with metadata to offer categories such as Suggestions, Latest, Genres, and more. If disabled, they'll be displayed with simple folders." "LabelSelectViewStylesHelp": "If enabled, views will be built with metadata to offer categories such as Suggestions, Latest, Genres, and more. If disabled, they'll be displayed with simple folders.",
"TabPhotos": "Photos",
"TabVideos": "Videos"
} }

View file

@ -470,6 +470,7 @@ namespace MediaBrowser.WebDashboard.Api
"notificationlist.js", "notificationlist.js",
"notificationsetting.js", "notificationsetting.js",
"notificationsettings.js", "notificationsettings.js",
"photos.js",
"playlists.js", "playlists.js",
"playlistedit.js", "playlistedit.js",

View file

@ -132,7 +132,7 @@
<Content Include="dashboard-ui\mysyncjob.html"> <Content Include="dashboard-ui\mysyncjob.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\ReportManager.html"> <Content Include="dashboard-ui\photos.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\scripts\dashboardhosting.js"> <Content Include="dashboard-ui\scripts\dashboardhosting.js">
@ -150,7 +150,7 @@
<Content Include="dashboard-ui\scripts\livetvitems.js"> <Content Include="dashboard-ui\scripts\livetvitems.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\scripts\reportmanager.js"> <Content Include="dashboard-ui\scripts\photos.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\scripts\selectserver.js"> <Content Include="dashboard-ui\scripts\selectserver.js">