mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-06-03 13:44:22 -04:00
Merge branch 'master' into userdb-efcore
# Conflicts: # Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs # Emby.Server.Implementations/Library/UserManager.cs # Emby.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs # Emby.Server.Implementations/Sorting/IsPlayedComparer.cs # Emby.Server.Implementations/Sorting/IsUnplayedComparer.cs # Emby.Server.Implementations/TV/TVSeriesManager.cs # Jellyfin.Server.Implementations/Users/DefaultAuthenticationProvider.cs
This commit is contained in:
commit
06f9cde22f
12
.vscode/tasks.json
vendored
12
.vscode/tasks.json
vendored
@ -10,6 +10,16 @@
|
|||||||
"${workspaceFolder}/Jellyfin.Server/Jellyfin.Server.csproj"
|
"${workspaceFolder}/Jellyfin.Server/Jellyfin.Server.csproj"
|
||||||
],
|
],
|
||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "api tests",
|
||||||
|
"command": "dotnet",
|
||||||
|
"type": "process",
|
||||||
|
"args": [
|
||||||
|
"test",
|
||||||
|
"${workspaceFolder}/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ namespace DvdLib.Ifo
|
|||||||
{
|
{
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
public readonly List<Cell> Cells;
|
public IReadOnlyList<Cell> Cells { get; }
|
||||||
|
|
||||||
public Program(List<Cell> cells)
|
public Program(List<Cell> cells)
|
||||||
{
|
{
|
||||||
|
@ -133,20 +133,20 @@ namespace Emby.Dlna.Main
|
|||||||
{
|
{
|
||||||
await ((DlnaManager)_dlnaManager).InitProfilesAsync().ConfigureAwait(false);
|
await ((DlnaManager)_dlnaManager).InitProfilesAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
ReloadComponents();
|
await ReloadComponents().ConfigureAwait(false);
|
||||||
|
|
||||||
_config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated;
|
_config.NamedConfigurationUpdated += OnNamedConfigurationUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
|
private async void OnNamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
|
||||||
{
|
{
|
||||||
if (string.Equals(e.Key, "dlna", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(e.Key, "dlna", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
ReloadComponents();
|
await ReloadComponents().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void ReloadComponents()
|
private async Task ReloadComponents()
|
||||||
{
|
{
|
||||||
var options = _config.GetDlnaConfiguration();
|
var options = _config.GetDlnaConfiguration();
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
RefreshVolumeIfNeeded();
|
RefreshVolumeIfNeeded().GetAwaiter().GetResult();
|
||||||
return _volume;
|
return _volume;
|
||||||
}
|
}
|
||||||
set => _volume = value;
|
set => _volume = value;
|
||||||
@ -76,24 +76,24 @@ namespace Emby.Dlna.PlayTo
|
|||||||
|
|
||||||
private DateTime _lastVolumeRefresh;
|
private DateTime _lastVolumeRefresh;
|
||||||
private bool _volumeRefreshActive;
|
private bool _volumeRefreshActive;
|
||||||
private void RefreshVolumeIfNeeded()
|
private Task RefreshVolumeIfNeeded()
|
||||||
{
|
{
|
||||||
if (!_volumeRefreshActive)
|
if (_volumeRefreshActive
|
||||||
{
|
&& DateTime.UtcNow >= _lastVolumeRefresh.AddSeconds(5))
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DateTime.UtcNow >= _lastVolumeRefresh.AddSeconds(5))
|
|
||||||
{
|
{
|
||||||
_lastVolumeRefresh = DateTime.UtcNow;
|
_lastVolumeRefresh = DateTime.UtcNow;
|
||||||
RefreshVolume(CancellationToken.None);
|
return RefreshVolume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void RefreshVolume(CancellationToken cancellationToken)
|
private async Task RefreshVolume(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -148,11 +148,14 @@ namespace Emby.Dlna.PlayTo
|
|||||||
{
|
{
|
||||||
var positionTicks = GetProgressPositionTicks(streamInfo);
|
var positionTicks = GetProgressPositionTicks(streamInfo);
|
||||||
|
|
||||||
ReportPlaybackStopped(streamInfo, positionTicks);
|
await ReportPlaybackStopped(streamInfo, positionTicks).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
streamInfo = StreamParams.ParseFromUrl(e.NewMediaInfo.Url, _libraryManager, _mediaSourceManager);
|
streamInfo = StreamParams.ParseFromUrl(e.NewMediaInfo.Url, _libraryManager, _mediaSourceManager);
|
||||||
if (streamInfo.Item == null) return;
|
if (streamInfo.Item == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var newItemProgress = GetProgressInfo(streamInfo);
|
var newItemProgress = GetProgressInfo(streamInfo);
|
||||||
|
|
||||||
@ -175,11 +178,14 @@ namespace Emby.Dlna.PlayTo
|
|||||||
{
|
{
|
||||||
var streamInfo = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager, _mediaSourceManager);
|
var streamInfo = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager, _mediaSourceManager);
|
||||||
|
|
||||||
if (streamInfo.Item == null) return;
|
if (streamInfo.Item == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var positionTicks = GetProgressPositionTicks(streamInfo);
|
var positionTicks = GetProgressPositionTicks(streamInfo);
|
||||||
|
|
||||||
ReportPlaybackStopped(streamInfo, positionTicks);
|
await ReportPlaybackStopped(streamInfo, positionTicks).ConfigureAwait(false);
|
||||||
|
|
||||||
var mediaSource = await streamInfo.GetMediaSource(CancellationToken.None).ConfigureAwait(false);
|
var mediaSource = await streamInfo.GetMediaSource(CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -187,7 +193,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
(_device.Duration == null ? (long?)null : _device.Duration.Value.Ticks) :
|
(_device.Duration == null ? (long?)null : _device.Duration.Value.Ticks) :
|
||||||
mediaSource.RunTimeTicks;
|
mediaSource.RunTimeTicks;
|
||||||
|
|
||||||
var playedToCompletion = (positionTicks.HasValue && positionTicks.Value == 0);
|
var playedToCompletion = positionTicks.HasValue && positionTicks.Value == 0;
|
||||||
|
|
||||||
if (!playedToCompletion && duration.HasValue && positionTicks.HasValue)
|
if (!playedToCompletion && duration.HasValue && positionTicks.HasValue)
|
||||||
{
|
{
|
||||||
@ -212,7 +218,7 @@ namespace Emby.Dlna.PlayTo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void ReportPlaybackStopped(StreamParams streamInfo, long? positionTicks)
|
private async Task ReportPlaybackStopped(StreamParams streamInfo, long? positionTicks)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -222,7 +228,6 @@ namespace Emby.Dlna.PlayTo
|
|||||||
SessionId = _session.Id,
|
SessionId = _session.Id,
|
||||||
PositionTicks = positionTicks,
|
PositionTicks = positionTicks,
|
||||||
MediaSourceId = streamInfo.MediaSourceId
|
MediaSourceId = streamInfo.MediaSourceId
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -100,15 +100,13 @@ namespace Emby.Dlna.Ssdp
|
|||||||
|
|
||||||
var headers = headerDict.ToDictionary(i => i.Key, i => i.Value.Value.FirstOrDefault(), StringComparer.OrdinalIgnoreCase);
|
var headers = headerDict.ToDictionary(i => i.Key, i => i.Value.Value.FirstOrDefault(), StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var args = new GenericEventArgs<UpnpDeviceInfo>
|
var args = new GenericEventArgs<UpnpDeviceInfo>(
|
||||||
{
|
new UpnpDeviceInfo
|
||||||
Argument = new UpnpDeviceInfo
|
|
||||||
{
|
{
|
||||||
Location = e.DiscoveredDevice.DescriptionLocation,
|
Location = e.DiscoveredDevice.DescriptionLocation,
|
||||||
Headers = headers,
|
Headers = headers,
|
||||||
LocalIpAddress = e.LocalIpAddress
|
LocalIpAddress = e.LocalIpAddress
|
||||||
}
|
});
|
||||||
};
|
|
||||||
|
|
||||||
DeviceDiscoveredInternal?.Invoke(this, args);
|
DeviceDiscoveredInternal?.Invoke(this, args);
|
||||||
}
|
}
|
||||||
@ -121,14 +119,12 @@ namespace Emby.Dlna.Ssdp
|
|||||||
|
|
||||||
var headers = headerDict.ToDictionary(i => i.Key, i => i.Value.Value.FirstOrDefault(), StringComparer.OrdinalIgnoreCase);
|
var headers = headerDict.ToDictionary(i => i.Key, i => i.Value.Value.FirstOrDefault(), StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var args = new GenericEventArgs<UpnpDeviceInfo>
|
var args = new GenericEventArgs<UpnpDeviceInfo>(
|
||||||
{
|
new UpnpDeviceInfo
|
||||||
Argument = new UpnpDeviceInfo
|
|
||||||
{
|
{
|
||||||
Location = e.DiscoveredDevice.DescriptionLocation,
|
Location = e.DiscoveredDevice.DescriptionLocation,
|
||||||
Headers = headers
|
Headers = headers
|
||||||
}
|
});
|
||||||
};
|
|
||||||
|
|
||||||
DeviceLeft?.Invoke(this, args);
|
DeviceLeft?.Invoke(this, args);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Emby.Dlna.Ssdp
|
namespace Emby.Dlna.Ssdp
|
||||||
@ -10,24 +11,17 @@ namespace Emby.Dlna.Ssdp
|
|||||||
{
|
{
|
||||||
var node = container.Element(name);
|
var node = container.Element(name);
|
||||||
|
|
||||||
return node == null ? null : node.Value;
|
return node?.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetAttributeValue(this XElement container, XName name)
|
public static string GetAttributeValue(this XElement container, XName name)
|
||||||
{
|
{
|
||||||
var node = container.Attribute(name);
|
var node = container.Attribute(name);
|
||||||
|
|
||||||
return node == null ? null : node.Value;
|
return node?.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetDescendantValue(this XElement container, XName name)
|
public static string GetDescendantValue(this XElement container, XName name)
|
||||||
{
|
=> container.Descendants(name).FirstOrDefault()?.Value;
|
||||||
foreach (var node in container.Descendants(name))
|
|
||||||
{
|
|
||||||
return node.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ namespace Emby.Drawing
|
|||||||
=> _transparentImageTypes.Contains(Path.GetExtension(path));
|
=> _transparentImageTypes.Contains(Path.GetExtension(path));
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<(string path, string mimeType, DateTime dateModified)> ProcessImage(ImageProcessingOptions options)
|
public async Task<(string path, string? mimeType, DateTime dateModified)> ProcessImage(ImageProcessingOptions options)
|
||||||
{
|
{
|
||||||
ItemImageInfo originalImage = options.Image;
|
ItemImageInfo originalImage = options.Image;
|
||||||
BaseItem item = options.Item;
|
BaseItem item = options.Item;
|
||||||
@ -232,7 +232,7 @@ namespace Emby.Drawing
|
|||||||
return ImageFormat.Jpg;
|
return ImageFormat.Jpg;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetMimeType(ImageFormat format, string path)
|
private string? GetMimeType(ImageFormat format, string path)
|
||||||
=> format switch
|
=> format switch
|
||||||
{
|
{
|
||||||
ImageFormat.Bmp => MimeTypes.GetMimeType("i.bmp"),
|
ImageFormat.Bmp => MimeTypes.GetMimeType("i.bmp"),
|
||||||
@ -315,6 +315,27 @@ namespace Emby.Drawing
|
|||||||
public ImageDimensions GetImageDimensions(string path)
|
public ImageDimensions GetImageDimensions(string path)
|
||||||
=> _imageEncoder.GetImageSize(path);
|
=> _imageEncoder.GetImageSize(path);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string GetImageBlurHash(string path)
|
||||||
|
{
|
||||||
|
var size = GetImageDimensions(path);
|
||||||
|
if (size.Width <= 0 || size.Height <= 0)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want tiles to be as close to square as possible, and to *mostly* keep under 16 tiles for performance.
|
||||||
|
// One tile is (width / xComp) x (height / yComp) pixels, which means that ideally yComp = xComp * height / width.
|
||||||
|
// See more at https://github.com/woltapp/blurhash/#how-do-i-pick-the-number-of-x-and-y-components
|
||||||
|
float xCompF = MathF.Sqrt(16.0f * size.Width / size.Height);
|
||||||
|
float yCompF = xCompF * size.Height / size.Width;
|
||||||
|
|
||||||
|
int xComp = Math.Min((int)xCompF + 1, 9);
|
||||||
|
int yComp = Math.Min((int)yCompF + 1, 9);
|
||||||
|
|
||||||
|
return _imageEncoder.GetImageBlurHash(xComp, yComp, path);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string GetImageCacheTag(BaseItem item, ItemImageInfo image)
|
public string GetImageCacheTag(BaseItem item, ItemImageInfo image)
|
||||||
=> (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
|
=> (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
|
||||||
|
@ -42,5 +42,11 @@ namespace Emby.Drawing
|
|||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string GetImageBlurHash(int xComp, int yComp, string path)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ namespace Emby.Naming.Common
|
|||||||
|
|
||||||
CleanStrings = new[]
|
CleanStrings = new[]
|
||||||
{
|
{
|
||||||
@"[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|cd[1-9]|r3|r5|bd5|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|2160p|hrhd|hrhdtv|hddvd|bluray|x264|h264|xvid|xvidvd|xxx|www.www|\[.*\])([ _\,\.\(\)\[\]\-]|$)",
|
@"[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|cd[1-9]|r3|r5|bd5|bd|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|2160p|hrhd|hrhdtv|hddvd|bluray|x264|h264|xvid|xvidvd|xxx|www.www|\[.*\])([ _\,\.\(\)\[\]\-]|$)",
|
||||||
@"(\[.*\])"
|
@"(\[.*\])"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -366,50 +366,50 @@ namespace Emby.Server.Implementations.Activity
|
|||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnPluginUpdated(object sender, GenericEventArgs<(IPlugin, VersionInfo)> e)
|
private async void OnPluginUpdated(object sender, InstallationInfo e)
|
||||||
{
|
{
|
||||||
await CreateLogEntry(new ActivityLog(
|
await CreateLogEntry(new ActivityLog(
|
||||||
string.Format(
|
string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
_localization.GetLocalizedString("PluginUpdatedWithName"),
|
_localization.GetLocalizedString("PluginUpdatedWithName"),
|
||||||
e.Argument.Item1.Name),
|
e.Name),
|
||||||
NotificationType.PluginUpdateInstalled.ToString(),
|
NotificationType.PluginUpdateInstalled.ToString(),
|
||||||
Guid.Empty)
|
Guid.Empty)
|
||||||
{
|
{
|
||||||
ShortOverview = string.Format(
|
ShortOverview = string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
_localization.GetLocalizedString("VersionNumber"),
|
_localization.GetLocalizedString("VersionNumber"),
|
||||||
e.Argument.Item2.version),
|
e.Version),
|
||||||
Overview = e.Argument.Item2.changelog
|
Overview = e.Changelog
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnPluginUninstalled(object sender, GenericEventArgs<IPlugin> e)
|
private async void OnPluginUninstalled(object sender, IPlugin e)
|
||||||
{
|
{
|
||||||
await CreateLogEntry(new ActivityLog(
|
await CreateLogEntry(new ActivityLog(
|
||||||
string.Format(
|
string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
_localization.GetLocalizedString("PluginUninstalledWithName"),
|
_localization.GetLocalizedString("PluginUninstalledWithName"),
|
||||||
e.Argument.Name),
|
e.Name),
|
||||||
NotificationType.PluginUninstalled.ToString(),
|
NotificationType.PluginUninstalled.ToString(),
|
||||||
Guid.Empty))
|
Guid.Empty))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnPluginInstalled(object sender, GenericEventArgs<VersionInfo> e)
|
private async void OnPluginInstalled(object sender, InstallationInfo e)
|
||||||
{
|
{
|
||||||
await CreateLogEntry(new ActivityLog(
|
await CreateLogEntry(new ActivityLog(
|
||||||
string.Format(
|
string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
_localization.GetLocalizedString("PluginInstalledWithName"),
|
_localization.GetLocalizedString("PluginInstalledWithName"),
|
||||||
e.Argument.name),
|
e.Name),
|
||||||
NotificationType.PluginInstalled.ToString(),
|
NotificationType.PluginInstalled.ToString(),
|
||||||
Guid.Empty)
|
Guid.Empty)
|
||||||
{
|
{
|
||||||
ShortOverview = string.Format(
|
ShortOverview = string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
_localization.GetLocalizedString("VersionNumber"),
|
_localization.GetLocalizedString("VersionNumber"),
|
||||||
e.Argument.version)
|
e.Version)
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ namespace Emby.Server.Implementations.Channels
|
|||||||
/// <param name="userManager">The user manager.</param>
|
/// <param name="userManager">The user manager.</param>
|
||||||
/// <param name="dtoService">The dto service.</param>
|
/// <param name="dtoService">The dto service.</param>
|
||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
/// <param name="loggerFactory">The logger factory.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
/// <param name="config">The server configuration manager.</param>
|
/// <param name="config">The server configuration manager.</param>
|
||||||
/// <param name="fileSystem">The filesystem.</param>
|
/// <param name="fileSystem">The filesystem.</param>
|
||||||
/// <param name="userDataManager">The user data manager.</param>
|
/// <param name="userDataManager">The user data manager.</param>
|
||||||
|
@ -90,7 +90,7 @@ namespace Emby.Server.Implementations.Configuration
|
|||||||
ValidateMetadataPath(newConfig);
|
ValidateMetadataPath(newConfig);
|
||||||
ValidateSslCertificate(newConfig);
|
ValidateSslCertificate(newConfig);
|
||||||
|
|
||||||
ConfigurationUpdating?.Invoke(this, new GenericEventArgs<ServerConfiguration> { Argument = newConfig });
|
ConfigurationUpdating?.Invoke(this, new GenericEventArgs<ServerConfiguration>(newConfig));
|
||||||
|
|
||||||
base.ReplaceConfiguration(newConfiguration);
|
base.ReplaceConfiguration(newConfiguration);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#nullable enable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
@ -129,8 +131,6 @@ namespace Emby.Server.Implementations.Cryptography
|
|||||||
_randomNumberGenerator.Dispose();
|
_randomNumberGenerator.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
_randomNumberGenerator = null;
|
|
||||||
|
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@ -33,7 +35,7 @@ using SQLitePCL.pretty;
|
|||||||
namespace Emby.Server.Implementations.Data
|
namespace Emby.Server.Implementations.Data
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class SQLiteItemRepository
|
/// Class SQLiteItemRepository.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SqliteItemRepository : BaseSqliteRepository, IItemRepository
|
public class SqliteItemRepository : BaseSqliteRepository, IItemRepository
|
||||||
{
|
{
|
||||||
@ -1141,24 +1143,24 @@ namespace Emby.Server.Implementations.Data
|
|||||||
|
|
||||||
public string ToValueString(ItemImageInfo image)
|
public string ToValueString(ItemImageInfo image)
|
||||||
{
|
{
|
||||||
var delimeter = "*";
|
const string Delimeter = "*";
|
||||||
|
|
||||||
var path = image.Path;
|
var path = image.Path ?? string.Empty;
|
||||||
|
var hash = image.BlurHash ?? string.Empty;
|
||||||
if (path == null)
|
|
||||||
{
|
|
||||||
path = string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetPathToSave(path) +
|
return GetPathToSave(path) +
|
||||||
delimeter +
|
Delimeter +
|
||||||
image.DateModified.Ticks.ToString(CultureInfo.InvariantCulture) +
|
image.DateModified.Ticks.ToString(CultureInfo.InvariantCulture) +
|
||||||
delimeter +
|
Delimeter +
|
||||||
image.Type +
|
image.Type +
|
||||||
delimeter +
|
Delimeter +
|
||||||
image.Width.ToString(CultureInfo.InvariantCulture) +
|
image.Width.ToString(CultureInfo.InvariantCulture) +
|
||||||
delimeter +
|
Delimeter +
|
||||||
image.Height.ToString(CultureInfo.InvariantCulture);
|
image.Height.ToString(CultureInfo.InvariantCulture) +
|
||||||
|
Delimeter +
|
||||||
|
// Replace delimiters with other characters.
|
||||||
|
// This can be removed when we migrate to a proper DB.
|
||||||
|
hash.Replace('*', '/').Replace('|', '\\');
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemImageInfo ItemImageInfoFromValueString(string value)
|
public ItemImageInfo ItemImageInfoFromValueString(string value)
|
||||||
@ -1192,6 +1194,11 @@ namespace Emby.Server.Implementations.Data
|
|||||||
image.Width = width;
|
image.Width = width;
|
||||||
image.Height = height;
|
image.Height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parts.Length >= 6)
|
||||||
|
{
|
||||||
|
image.BlurHash = parts[5].Replace('/', '*').Replace('\\', '|');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
@ -1971,6 +1978,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
/// Gets the chapter.
|
/// Gets the chapter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="reader">The reader.</param>
|
/// <param name="reader">The reader.</param>
|
||||||
|
/// <param name="item">The item.</param>
|
||||||
/// <returns>ChapterInfo.</returns>
|
/// <returns>ChapterInfo.</returns>
|
||||||
private ChapterInfo GetChapter(IReadOnlyList<IResultSetValue> reader, BaseItem item)
|
private ChapterInfo GetChapter(IReadOnlyList<IResultSetValue> reader, BaseItem item)
|
||||||
{
|
{
|
||||||
|
@ -61,13 +61,7 @@ namespace Emby.Server.Implementations.Devices
|
|||||||
{
|
{
|
||||||
_authRepo.UpdateDeviceOptions(deviceId, options);
|
_authRepo.UpdateDeviceOptions(deviceId, options);
|
||||||
|
|
||||||
if (DeviceOptionsUpdated != null)
|
DeviceOptionsUpdated?.Invoke(this, new GenericEventArgs<Tuple<string, DeviceOptions>>(new Tuple<string, DeviceOptions>(deviceId, options)));
|
||||||
{
|
|
||||||
DeviceOptionsUpdated(this, new GenericEventArgs<Tuple<string, DeviceOptions>>()
|
|
||||||
{
|
|
||||||
Argument = new Tuple<string, DeviceOptions>(deviceId, options)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceOptions GetDeviceOptions(string deviceId)
|
public DeviceOptions GetDeviceOptions(string deviceId)
|
||||||
|
@ -613,7 +613,7 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
|
|
||||||
if (dictionary.TryGetValue(person.Name, out Person entity))
|
if (dictionary.TryGetValue(person.Name, out Person entity))
|
||||||
{
|
{
|
||||||
baseItemPerson.PrimaryImageTag = GetImageCacheTag(entity, ImageType.Primary);
|
baseItemPerson.PrimaryImageTag = GetTagAndFillBlurhash(dto, entity, ImageType.Primary);
|
||||||
baseItemPerson.Id = entity.Id.ToString("N", CultureInfo.InvariantCulture);
|
baseItemPerson.Id = entity.Id.ToString("N", CultureInfo.InvariantCulture);
|
||||||
list.Add(baseItemPerson);
|
list.Add(baseItemPerson);
|
||||||
}
|
}
|
||||||
@ -662,6 +662,70 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
return _libraryManager.GetGenreId(name);
|
return _libraryManager.GetGenreId(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetTagAndFillBlurhash(BaseItemDto dto, BaseItem item, ImageType imageType, int imageIndex = 0)
|
||||||
|
{
|
||||||
|
var image = item.GetImageInfo(imageType, imageIndex);
|
||||||
|
if (image != null)
|
||||||
|
{
|
||||||
|
return GetTagAndFillBlurhash(dto, item, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetTagAndFillBlurhash(BaseItemDto dto, BaseItem item, ItemImageInfo image)
|
||||||
|
{
|
||||||
|
var tag = GetImageCacheTag(item, image);
|
||||||
|
if (!string.IsNullOrEmpty(image.BlurHash))
|
||||||
|
{
|
||||||
|
if (dto.ImageBlurHashes == null)
|
||||||
|
{
|
||||||
|
dto.ImageBlurHashes = new Dictionary<ImageType, Dictionary<string, string>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dto.ImageBlurHashes.ContainsKey(image.Type))
|
||||||
|
{
|
||||||
|
dto.ImageBlurHashes[image.Type] = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
dto.ImageBlurHashes[image.Type][tag] = image.BlurHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string[] GetTagsAndFillBlurhashes(BaseItemDto dto, BaseItem item, ImageType imageType, int limit)
|
||||||
|
{
|
||||||
|
return GetTagsAndFillBlurhashes(dto, item, imageType, item.GetImages(imageType).Take(limit).ToList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private string[] GetTagsAndFillBlurhashes(BaseItemDto dto, BaseItem item, ImageType imageType, List<ItemImageInfo> images)
|
||||||
|
{
|
||||||
|
var tags = GetImageTags(item, images);
|
||||||
|
var hashes = new Dictionary<string, string>();
|
||||||
|
for (int i = 0; i < images.Count; i++)
|
||||||
|
{
|
||||||
|
var img = images[i];
|
||||||
|
if (!string.IsNullOrEmpty(img.BlurHash))
|
||||||
|
{
|
||||||
|
var tag = tags[i];
|
||||||
|
hashes[tag] = img.BlurHash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hashes.Count > 0)
|
||||||
|
{
|
||||||
|
if (dto.ImageBlurHashes == null)
|
||||||
|
{
|
||||||
|
dto.ImageBlurHashes = new Dictionary<ImageType, Dictionary<string, string>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
dto.ImageBlurHashes[imageType] = hashes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets simple property values on a DTOBaseItem
|
/// Sets simple property values on a DTOBaseItem
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -682,8 +746,8 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
dto.LockData = item.IsLocked;
|
dto.LockData = item.IsLocked;
|
||||||
dto.ForcedSortName = item.ForcedSortName;
|
dto.ForcedSortName = item.ForcedSortName;
|
||||||
}
|
}
|
||||||
dto.Container = item.Container;
|
|
||||||
|
|
||||||
|
dto.Container = item.Container;
|
||||||
dto.EndDate = item.EndDate;
|
dto.EndDate = item.EndDate;
|
||||||
|
|
||||||
if (options.ContainsField(ItemFields.ExternalUrls))
|
if (options.ContainsField(ItemFields.ExternalUrls))
|
||||||
@ -702,10 +766,12 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
dto.AspectRatio = hasAspectRatio.AspectRatio;
|
dto.AspectRatio = hasAspectRatio.AspectRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dto.ImageBlurHashes = new Dictionary<ImageType, Dictionary<string, string>>();
|
||||||
|
|
||||||
var backdropLimit = options.GetImageLimit(ImageType.Backdrop);
|
var backdropLimit = options.GetImageLimit(ImageType.Backdrop);
|
||||||
if (backdropLimit > 0)
|
if (backdropLimit > 0)
|
||||||
{
|
{
|
||||||
dto.BackdropImageTags = GetImageTags(item, item.GetImages(ImageType.Backdrop).Take(backdropLimit).ToList());
|
dto.BackdropImageTags = GetTagsAndFillBlurhashes(dto, item, ImageType.Backdrop, backdropLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.ContainsField(ItemFields.ScreenshotImageTags))
|
if (options.ContainsField(ItemFields.ScreenshotImageTags))
|
||||||
@ -713,7 +779,7 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
var screenshotLimit = options.GetImageLimit(ImageType.Screenshot);
|
var screenshotLimit = options.GetImageLimit(ImageType.Screenshot);
|
||||||
if (screenshotLimit > 0)
|
if (screenshotLimit > 0)
|
||||||
{
|
{
|
||||||
dto.ScreenshotImageTags = GetImageTags(item, item.GetImages(ImageType.Screenshot).Take(screenshotLimit).ToList());
|
dto.ScreenshotImageTags = GetTagsAndFillBlurhashes(dto, item, ImageType.Screenshot, screenshotLimit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -729,12 +795,11 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
|
|
||||||
// Prevent implicitly captured closure
|
// Prevent implicitly captured closure
|
||||||
var currentItem = item;
|
var currentItem = item;
|
||||||
foreach (var image in currentItem.ImageInfos.Where(i => !currentItem.AllowsMultipleImages(i.Type))
|
foreach (var image in currentItem.ImageInfos.Where(i => !currentItem.AllowsMultipleImages(i.Type)))
|
||||||
.ToList())
|
|
||||||
{
|
{
|
||||||
if (options.GetImageLimit(image.Type) > 0)
|
if (options.GetImageLimit(image.Type) > 0)
|
||||||
{
|
{
|
||||||
var tag = GetImageCacheTag(item, image);
|
var tag = GetTagAndFillBlurhash(dto, item, image);
|
||||||
|
|
||||||
if (tag != null)
|
if (tag != null)
|
||||||
{
|
{
|
||||||
@ -879,8 +944,7 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
if (albumParent != null)
|
if (albumParent != null)
|
||||||
{
|
{
|
||||||
dto.AlbumId = albumParent.Id;
|
dto.AlbumId = albumParent.Id;
|
||||||
|
dto.AlbumPrimaryImageTag = GetTagAndFillBlurhash(dto, albumParent, ImageType.Primary);
|
||||||
dto.AlbumPrimaryImageTag = GetImageCacheTag(albumParent, ImageType.Primary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (options.ContainsField(ItemFields.MediaSourceCount))
|
//if (options.ContainsField(ItemFields.MediaSourceCount))
|
||||||
@ -1107,7 +1171,7 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
episodeSeries = episodeSeries ?? episode.Series;
|
episodeSeries = episodeSeries ?? episode.Series;
|
||||||
if (episodeSeries != null)
|
if (episodeSeries != null)
|
||||||
{
|
{
|
||||||
dto.SeriesPrimaryImageTag = GetImageCacheTag(episodeSeries, ImageType.Primary);
|
dto.SeriesPrimaryImageTag = GetTagAndFillBlurhash(dto, episodeSeries, ImageType.Primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1153,7 +1217,7 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
series = series ?? season.Series;
|
series = series ?? season.Series;
|
||||||
if (series != null)
|
if (series != null)
|
||||||
{
|
{
|
||||||
dto.SeriesPrimaryImageTag = GetImageCacheTag(series, ImageType.Primary);
|
dto.SeriesPrimaryImageTag = GetTagAndFillBlurhash(dto, series, ImageType.Primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1283,7 +1347,7 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
if (image != null)
|
if (image != null)
|
||||||
{
|
{
|
||||||
dto.ParentLogoItemId = GetDtoId(parent);
|
dto.ParentLogoItemId = GetDtoId(parent);
|
||||||
dto.ParentLogoImageTag = GetImageCacheTag(parent, image);
|
dto.ParentLogoImageTag = GetTagAndFillBlurhash(dto, parent, image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (artLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Art)) && dto.ParentArtItemId == null)
|
if (artLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Art)) && dto.ParentArtItemId == null)
|
||||||
@ -1293,7 +1357,7 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
if (image != null)
|
if (image != null)
|
||||||
{
|
{
|
||||||
dto.ParentArtItemId = GetDtoId(parent);
|
dto.ParentArtItemId = GetDtoId(parent);
|
||||||
dto.ParentArtImageTag = GetImageCacheTag(parent, image);
|
dto.ParentArtImageTag = GetTagAndFillBlurhash(dto, parent, image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (thumbLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && (dto.ParentThumbItemId == null || parent is Series) && !(parent is ICollectionFolder) && !(parent is UserView))
|
if (thumbLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && (dto.ParentThumbItemId == null || parent is Series) && !(parent is ICollectionFolder) && !(parent is UserView))
|
||||||
@ -1303,7 +1367,7 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
if (image != null)
|
if (image != null)
|
||||||
{
|
{
|
||||||
dto.ParentThumbItemId = GetDtoId(parent);
|
dto.ParentThumbItemId = GetDtoId(parent);
|
||||||
dto.ParentThumbImageTag = GetImageCacheTag(parent, image);
|
dto.ParentThumbImageTag = GetTagAndFillBlurhash(dto, parent, image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (backdropLimit > 0 && !((dto.BackdropImageTags != null && dto.BackdropImageTags.Length > 0) || (dto.ParentBackdropImageTags != null && dto.ParentBackdropImageTags.Length > 0)))
|
if (backdropLimit > 0 && !((dto.BackdropImageTags != null && dto.BackdropImageTags.Length > 0) || (dto.ParentBackdropImageTags != null && dto.ParentBackdropImageTags.Length > 0)))
|
||||||
@ -1313,7 +1377,7 @@ namespace Emby.Server.Implementations.Dto
|
|||||||
if (images.Count > 0)
|
if (images.Count > 0)
|
||||||
{
|
{
|
||||||
dto.ParentBackdropItemId = GetDtoId(parent);
|
dto.ParentBackdropItemId = GetDtoId(parent);
|
||||||
dto.ParentBackdropImageTags = GetImageTags(parent, images);
|
dto.ParentBackdropImageTags = GetTagsAndFillBlurhashes(dto, parent, ImageType.Backdrop, images);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release'" >true</TreatWarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Code Analyzers-->
|
<!-- Code Analyzers-->
|
||||||
|
@ -303,7 +303,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
.Select(x => x.First())
|
.Select(x => x.First())
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
SendChangeNotifications(_itemsAdded.ToList(), itemsUpdated, _itemsRemoved.ToList(), foldersAddedTo, foldersRemovedFrom, CancellationToken.None);
|
SendChangeNotifications(_itemsAdded.ToList(), itemsUpdated, _itemsRemoved.ToList(), foldersAddedTo, foldersRemovedFrom, CancellationToken.None).GetAwaiter().GetResult();
|
||||||
|
|
||||||
if (LibraryUpdateTimer != null)
|
if (LibraryUpdateTimer != null)
|
||||||
{
|
{
|
||||||
@ -328,7 +328,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
/// <param name="foldersAddedTo">The folders added to.</param>
|
/// <param name="foldersAddedTo">The folders added to.</param>
|
||||||
/// <param name="foldersRemovedFrom">The folders removed from.</param>
|
/// <param name="foldersRemovedFrom">The folders removed from.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
private async void SendChangeNotifications(List<BaseItem> itemsAdded, List<BaseItem> itemsUpdated, List<BaseItem> itemsRemoved, List<Folder> foldersAddedTo, List<Folder> foldersRemovedFrom, CancellationToken cancellationToken)
|
private async Task SendChangeNotifications(List<BaseItem> itemsAdded, List<BaseItem> itemsUpdated, List<BaseItem> itemsRemoved, List<Folder> foldersAddedTo, List<Folder> foldersRemovedFrom, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var userIds = _sessionManager.Sessions
|
var userIds = _sessionManager.Sessions
|
||||||
.Select(i => i.UserId)
|
.Select(i => i.UserId)
|
||||||
|
@ -43,27 +43,27 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLiveTvManagerSeriesTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
|
private async void OnLiveTvManagerSeriesTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
|
||||||
{
|
{
|
||||||
SendMessage("SeriesTimerCreated", e.Argument);
|
await SendMessage("SeriesTimerCreated", e.Argument).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLiveTvManagerTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
|
private async void OnLiveTvManagerTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
|
||||||
{
|
{
|
||||||
SendMessage("TimerCreated", e.Argument);
|
await SendMessage("TimerCreated", e.Argument).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLiveTvManagerSeriesTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
|
private async void OnLiveTvManagerSeriesTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
|
||||||
{
|
{
|
||||||
SendMessage("SeriesTimerCancelled", e.Argument);
|
await SendMessage("SeriesTimerCancelled", e.Argument).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLiveTvManagerTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
|
private async void OnLiveTvManagerTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
|
||||||
{
|
{
|
||||||
SendMessage("TimerCancelled", e.Argument);
|
await SendMessage("TimerCancelled", e.Argument).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SendMessage(string name, TimerEventInfo info)
|
private async Task SendMessage(string name, TimerEventInfo info)
|
||||||
{
|
{
|
||||||
var users = _userManager.Users.Where(i => i.HasPermission(PermissionKind.EnableLiveTvAccess)).Select(i => i.Id).ToList();
|
var users = _userManager.Users.Where(i => i.HasPermission(PermissionKind.EnableLiveTvAccess)).Select(i => i.Id).ToList();
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ using MediaBrowser.Controller.Plugins;
|
|||||||
using MediaBrowser.Controller.Session;
|
using MediaBrowser.Controller.Session;
|
||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Tasks;
|
||||||
|
using MediaBrowser.Model.Updates;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.EntryPoints
|
namespace Emby.Server.Implementations.EntryPoints
|
||||||
{
|
{
|
||||||
@ -83,29 +84,29 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPackageInstalling(object sender, InstallationEventArgs e)
|
private async void OnPackageInstalling(object sender, InstallationInfo e)
|
||||||
{
|
{
|
||||||
SendMessageToAdminSessions("PackageInstalling", e.InstallationInfo);
|
await SendMessageToAdminSessions("PackageInstalling", e).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPackageInstallationCancelled(object sender, InstallationEventArgs e)
|
private async void OnPackageInstallationCancelled(object sender, InstallationInfo e)
|
||||||
{
|
{
|
||||||
SendMessageToAdminSessions("PackageInstallationCancelled", e.InstallationInfo);
|
await SendMessageToAdminSessions("PackageInstallationCancelled", e).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPackageInstallationCompleted(object sender, InstallationEventArgs e)
|
private async void OnPackageInstallationCompleted(object sender, InstallationInfo e)
|
||||||
{
|
{
|
||||||
SendMessageToAdminSessions("PackageInstallationCompleted", e.InstallationInfo);
|
await SendMessageToAdminSessions("PackageInstallationCompleted", e).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e)
|
private async void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e)
|
||||||
{
|
{
|
||||||
SendMessageToAdminSessions("PackageInstallationFailed", e.InstallationInfo);
|
await SendMessageToAdminSessions("PackageInstallationFailed", e.InstallationInfo).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTaskCompleted(object sender, TaskCompletionEventArgs e)
|
private async void OnTaskCompleted(object sender, TaskCompletionEventArgs e)
|
||||||
{
|
{
|
||||||
SendMessageToAdminSessions("ScheduledTaskEnded", e.Result);
|
await SendMessageToAdminSessions("ScheduledTaskEnded", e.Result).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -113,9 +114,9 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender">The sender.</param>
|
/// <param name="sender">The sender.</param>
|
||||||
/// <param name="e">The e.</param>
|
/// <param name="e">The e.</param>
|
||||||
private void OnPluginUninstalled(object sender, GenericEventArgs<IPlugin> e)
|
private async void OnPluginUninstalled(object sender, IPlugin e)
|
||||||
{
|
{
|
||||||
SendMessageToAdminSessions("PluginUninstalled", e.Argument.GetPluginInfo());
|
await SendMessageToAdminSessions("PluginUninstalled", e).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -123,9 +124,9 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender">The source of the event.</param>
|
/// <param name="sender">The source of the event.</param>
|
||||||
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
|
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
|
||||||
private void OnHasPendingRestartChanged(object sender, EventArgs e)
|
private async void OnHasPendingRestartChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
_sessionManager.SendRestartRequiredNotification(CancellationToken.None);
|
await _sessionManager.SendRestartRequiredNotification(CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -133,11 +134,11 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender">The sender.</param>
|
/// <param name="sender">The sender.</param>
|
||||||
/// <param name="e">The e.</param>
|
/// <param name="e">The e.</param>
|
||||||
private void OnUserUpdated(object sender, GenericEventArgs<User> e)
|
private async void OnUserUpdated(object sender, GenericEventArgs<User> e)
|
||||||
{
|
{
|
||||||
var dto = _userManager.GetUserDto(e.Argument);
|
var dto = _userManager.GetUserDto(e.Argument);
|
||||||
|
|
||||||
SendMessageToUserSession(e.Argument, "UserUpdated", dto);
|
await SendMessageToUserSession(e.Argument, "UserUpdated", dto).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -145,12 +146,12 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender">The sender.</param>
|
/// <param name="sender">The sender.</param>
|
||||||
/// <param name="e">The e.</param>
|
/// <param name="e">The e.</param>
|
||||||
private void OnUserDeleted(object sender, GenericEventArgs<User> e)
|
private async void OnUserDeleted(object sender, GenericEventArgs<User> e)
|
||||||
{
|
{
|
||||||
SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N", CultureInfo.InvariantCulture));
|
await SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N", CultureInfo.InvariantCulture)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SendMessageToAdminSessions<T>(string name, T data)
|
private async Task SendMessageToAdminSessions<T>(string name, T data)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -162,7 +163,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SendMessageToUserSession<T>(User user, string name, T data)
|
private async Task SendMessageToUserSession<T>(User user, string name, T data)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -196,7 +197,6 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
_userManager.OnUserDeleted -= OnUserDeleted;
|
_userManager.OnUserDeleted -= OnUserDeleted;
|
||||||
_userManager.OnUserUpdated -= OnUserUpdated;
|
_userManager.OnUserUpdated -= OnUserUpdated;
|
||||||
|
|
||||||
|
|
||||||
_installationManager.PluginUninstalled -= OnPluginUninstalled;
|
_installationManager.PluginUninstalled -= OnPluginUninstalled;
|
||||||
_installationManager.PackageInstalling -= OnPackageInstalling;
|
_installationManager.PackageInstalling -= OnPackageInstalling;
|
||||||
_installationManager.PackageInstallationCancelled -= OnPackageInstallationCancelled;
|
_installationManager.PackageInstallationCancelled -= OnPackageInstallationCancelled;
|
||||||
|
@ -47,10 +47,11 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task RunAsync()
|
public Task RunAsync()
|
||||||
{
|
{
|
||||||
_udpServer = new UdpServer(_logger, _appHost, _config);
|
_udpServer = new UdpServer(_logger, _appHost, _config);
|
||||||
_udpServer.Start(PortNumber, _cancellationTokenSource.Token);
|
_udpServer.Start(PortNumber, _cancellationTokenSource.Token);
|
||||||
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -56,6 +56,7 @@ namespace Emby.Server.Implementations.HttpServer
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the result.
|
/// Gets the result.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="requestContext">The request context.</param>
|
||||||
/// <param name="content">The content.</param>
|
/// <param name="content">The content.</param>
|
||||||
/// <param name="contentType">Type of the content.</param>
|
/// <param name="contentType">Type of the content.</param>
|
||||||
/// <param name="responseHeaders">The response headers.</param>
|
/// <param name="responseHeaders">The response headers.</param>
|
||||||
@ -255,16 +256,20 @@ namespace Emby.Server.Implementations.HttpServer
|
|||||||
{
|
{
|
||||||
var acceptEncoding = request.Headers[HeaderNames.AcceptEncoding].ToString();
|
var acceptEncoding = request.Headers[HeaderNames.AcceptEncoding].ToString();
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(acceptEncoding))
|
if (!string.IsNullOrEmpty(acceptEncoding))
|
||||||
{
|
{
|
||||||
//if (_brotliCompressor != null && acceptEncoding.IndexOf("br", StringComparison.OrdinalIgnoreCase) != -1)
|
// if (_brotliCompressor != null && acceptEncoding.IndexOf("br", StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
// return "br";
|
// return "br";
|
||||||
|
|
||||||
if (acceptEncoding.IndexOf("deflate", StringComparison.OrdinalIgnoreCase) != -1)
|
if (acceptEncoding.Contains("deflate", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
return "deflate";
|
return "deflate";
|
||||||
|
}
|
||||||
|
|
||||||
if (acceptEncoding.IndexOf("gzip", StringComparison.OrdinalIgnoreCase) != -1)
|
if (acceptEncoding.Contains("gzip", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
return "gzip";
|
return "gzip";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations
|
namespace Emby.Server.Implementations
|
||||||
|
47
Emby.Server.Implementations/Images/ArtistImageProvider.cs
Normal file
47
Emby.Server.Implementations/Images/ArtistImageProvider.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Emby.Server.Implementations.Images;
|
||||||
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Controller.Drawing;
|
||||||
|
using MediaBrowser.Controller.Dto;
|
||||||
|
using MediaBrowser.Controller.Entities;
|
||||||
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Controller.Playlists;
|
||||||
|
using MediaBrowser.Controller.Providers;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.IO;
|
||||||
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
|
namespace Emby.Server.Implementations.Images
|
||||||
|
{
|
||||||
|
public class ArtistImageProvider : BaseDynamicImageProvider<MusicArtist>
|
||||||
|
{
|
||||||
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
|
public ArtistImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) : base(fileSystem, providerManager, applicationPaths, imageProcessor)
|
||||||
|
{
|
||||||
|
_libraryManager = libraryManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IReadOnlyList<BaseItem> GetItemsWithImages(BaseItem item)
|
||||||
|
{
|
||||||
|
return Array.Empty<BaseItem>();
|
||||||
|
|
||||||
|
// TODO enable this when BaseDynamicImageProvider objects are configurable
|
||||||
|
// return _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
|
// {
|
||||||
|
// ArtistIds = new[] { item.Id },
|
||||||
|
// IncludeItemTypes = new[] { typeof(MusicAlbum).Name },
|
||||||
|
// OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) },
|
||||||
|
// Limit = 4,
|
||||||
|
// Recursive = true,
|
||||||
|
// ImageTypes = new[] { ImageType.Primary },
|
||||||
|
// DtoOptions = new DtoOptions(false)
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -194,7 +194,8 @@ namespace Emby.Server.Implementations.Images
|
|||||||
return outputPath;
|
return outputPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual string CreateImage(BaseItem item,
|
protected virtual string CreateImage(
|
||||||
|
BaseItem item,
|
||||||
IReadOnlyCollection<BaseItem> itemsWithImages,
|
IReadOnlyCollection<BaseItem> itemsWithImages,
|
||||||
string outputPathWithoutExtension,
|
string outputPathWithoutExtension,
|
||||||
ImageType imageType,
|
ImageType imageType,
|
||||||
@ -214,7 +215,12 @@ namespace Emby.Server.Implementations.Images
|
|||||||
|
|
||||||
if (imageType == ImageType.Primary)
|
if (imageType == ImageType.Primary)
|
||||||
{
|
{
|
||||||
if (item is UserView || item is Playlist || item is MusicGenre || item is Genre || item is PhotoAlbum)
|
if (item is UserView
|
||||||
|
|| item is Playlist
|
||||||
|
|| item is MusicGenre
|
||||||
|
|| item is Genre
|
||||||
|
|| item is PhotoAlbum
|
||||||
|
|| item is MusicArtist)
|
||||||
{
|
{
|
||||||
return CreateSquareCollage(item, itemsWithImages, outputPath);
|
return CreateSquareCollage(item, itemsWithImages, outputPath);
|
||||||
}
|
}
|
||||||
@ -225,7 +231,7 @@ namespace Emby.Server.Implementations.Images
|
|||||||
throw new ArgumentException("Unexpected image type", nameof(imageType));
|
throw new ArgumentException("Unexpected image type", nameof(imageType));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasChanged(BaseItem item, IDirectoryService directoryServicee)
|
public bool HasChanged(BaseItem item, IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
if (!Supports(item))
|
if (!Supports(item))
|
||||||
{
|
{
|
||||||
@ -236,6 +242,7 @@ namespace Emby.Server.Implementations.Images
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SupportedImages.Contains(ImageType.Thumb) && HasChanged(item, ImageType.Thumb))
|
if (SupportedImages.Contains(ImageType.Thumb) && HasChanged(item, ImageType.Thumb))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -11,7 +13,7 @@ using MediaBrowser.Model.Entities;
|
|||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.UserViews
|
namespace Emby.Server.Implementations.Images
|
||||||
{
|
{
|
||||||
public class CollectionFolderImageProvider : BaseDynamicImageProvider<CollectionFolder>
|
public class CollectionFolderImageProvider : BaseDynamicImageProvider<CollectionFolder>
|
||||||
{
|
{
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -14,18 +16,16 @@ using MediaBrowser.Controller.Providers;
|
|||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.UserViews
|
namespace Emby.Server.Implementations.Images
|
||||||
{
|
{
|
||||||
public class DynamicImageProvider : BaseDynamicImageProvider<UserView>
|
public class DynamicImageProvider : BaseDynamicImageProvider<UserView>
|
||||||
{
|
{
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly ILibraryManager _libraryManager;
|
|
||||||
|
|
||||||
public DynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, IUserManager userManager, ILibraryManager libraryManager)
|
public DynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, IUserManager userManager)
|
||||||
: base(fileSystem, providerManager, applicationPaths, imageProcessor)
|
: base(fileSystem, providerManager, applicationPaths, imageProcessor)
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_libraryManager = libraryManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IReadOnlyList<BaseItem> GetItemsWithImages(BaseItem item)
|
protected override IReadOnlyList<BaseItem> GetItemsWithImages(BaseItem item)
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Emby.Server.Implementations.Images;
|
using Emby.Server.Implementations.Images;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
@ -11,7 +13,7 @@ using MediaBrowser.Model.Entities;
|
|||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.UserViews
|
namespace Emby.Server.Implementations.Images
|
||||||
{
|
{
|
||||||
public abstract class BaseFolderImageProvider<T> : BaseDynamicImageProvider<T>
|
public abstract class BaseFolderImageProvider<T> : BaseDynamicImageProvider<T>
|
||||||
where T : Folder, new()
|
where T : Folder, new()
|
||||||
@ -75,16 +77,12 @@ namespace Emby.Server.Implementations.UserViews
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var folder = item as Folder;
|
if (item is Folder && item.IsTopParent)
|
||||||
if (folder != null)
|
|
||||||
{
|
{
|
||||||
if (folder.IsTopParent)
|
return false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
//return item.SourceType == SourceType.Library;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Emby.Server.Implementations.Images;
|
using Emby.Server.Implementations.Images;
|
||||||
@ -15,58 +16,8 @@ using MediaBrowser.Model.Entities;
|
|||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.Playlists
|
namespace Emby.Server.Implementations.Images
|
||||||
{
|
{
|
||||||
public class PlaylistImageProvider : BaseDynamicImageProvider<Playlist>
|
|
||||||
{
|
|
||||||
public PlaylistImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override IReadOnlyList<BaseItem> GetItemsWithImages(BaseItem item)
|
|
||||||
{
|
|
||||||
var playlist = (Playlist)item;
|
|
||||||
|
|
||||||
return playlist.GetManageableItems()
|
|
||||||
.Select(i =>
|
|
||||||
{
|
|
||||||
var subItem = i.Item2;
|
|
||||||
|
|
||||||
var episode = subItem as Episode;
|
|
||||||
|
|
||||||
if (episode != null)
|
|
||||||
{
|
|
||||||
var series = episode.Series;
|
|
||||||
if (series != null && series.HasImage(ImageType.Primary))
|
|
||||||
{
|
|
||||||
return series;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subItem.HasImage(ImageType.Primary))
|
|
||||||
{
|
|
||||||
return subItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
var parent = subItem.GetOwner() ?? subItem.GetParent();
|
|
||||||
|
|
||||||
if (parent != null && parent.HasImage(ImageType.Primary))
|
|
||||||
{
|
|
||||||
if (parent is MusicAlbum)
|
|
||||||
{
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
})
|
|
||||||
.Where(i => i != null)
|
|
||||||
.GroupBy(x => x.Id)
|
|
||||||
.Select(x => x.First())
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MusicGenreImageProvider : BaseDynamicImageProvider<MusicGenre>
|
public class MusicGenreImageProvider : BaseDynamicImageProvider<MusicGenre>
|
||||||
{
|
{
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
66
Emby.Server.Implementations/Images/PlaylistImageProvider.cs
Normal file
66
Emby.Server.Implementations/Images/PlaylistImageProvider.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Controller.Drawing;
|
||||||
|
using MediaBrowser.Controller.Entities;
|
||||||
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
|
using MediaBrowser.Controller.Playlists;
|
||||||
|
using MediaBrowser.Controller.Providers;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.IO;
|
||||||
|
|
||||||
|
namespace Emby.Server.Implementations.Images
|
||||||
|
{
|
||||||
|
public class PlaylistImageProvider : BaseDynamicImageProvider<Playlist>
|
||||||
|
{
|
||||||
|
public PlaylistImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IReadOnlyList<BaseItem> GetItemsWithImages(BaseItem item)
|
||||||
|
{
|
||||||
|
var playlist = (Playlist)item;
|
||||||
|
|
||||||
|
return playlist.GetManageableItems()
|
||||||
|
.Select(i =>
|
||||||
|
{
|
||||||
|
var subItem = i.Item2;
|
||||||
|
|
||||||
|
var episode = subItem as Episode;
|
||||||
|
|
||||||
|
if (episode != null)
|
||||||
|
{
|
||||||
|
var series = episode.Series;
|
||||||
|
if (series != null && series.HasImage(ImageType.Primary))
|
||||||
|
{
|
||||||
|
return series;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subItem.HasImage(ImageType.Primary))
|
||||||
|
{
|
||||||
|
return subItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
var parent = subItem.GetOwner() ?? subItem.GetParent();
|
||||||
|
|
||||||
|
if (parent != null && parent.HasImage(ImageType.Primary))
|
||||||
|
{
|
||||||
|
if (parent is MusicAlbum)
|
||||||
|
{
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
.Where(i => i != null)
|
||||||
|
.GroupBy(x => x.Id)
|
||||||
|
.Select(x => x.First())
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ using MediaBrowser.Common.Extensions;
|
|||||||
using MediaBrowser.Common.Progress;
|
using MediaBrowser.Common.Progress;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Drawing;
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
@ -36,6 +37,7 @@ using MediaBrowser.Controller.Resolvers;
|
|||||||
using MediaBrowser.Controller.Sorting;
|
using MediaBrowser.Controller.Sorting;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
using MediaBrowser.Model.Drawing;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
@ -54,7 +56,7 @@ using VideoResolver = Emby.Naming.Video.VideoResolver;
|
|||||||
namespace Emby.Server.Implementations.Library
|
namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class LibraryManager
|
/// Class LibraryManager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class LibraryManager : ILibraryManager
|
public class LibraryManager : ILibraryManager
|
||||||
{
|
{
|
||||||
@ -71,6 +73,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly IItemRepository _itemRepository;
|
private readonly IItemRepository _itemRepository;
|
||||||
private readonly ConcurrentDictionary<Guid, BaseItem> _libraryItemsCache;
|
private readonly ConcurrentDictionary<Guid, BaseItem> _libraryItemsCache;
|
||||||
|
private readonly IImageProcessor _imageProcessor;
|
||||||
|
|
||||||
private NamingOptions _namingOptions;
|
private NamingOptions _namingOptions;
|
||||||
private string[] _videoFileExtensions;
|
private string[] _videoFileExtensions;
|
||||||
@ -139,6 +142,13 @@ namespace Emby.Server.Implementations.Library
|
|||||||
/// <param name="userManager">The user manager.</param>
|
/// <param name="userManager">The user manager.</param>
|
||||||
/// <param name="configurationManager">The configuration manager.</param>
|
/// <param name="configurationManager">The configuration manager.</param>
|
||||||
/// <param name="userDataRepository">The user data repository.</param>
|
/// <param name="userDataRepository">The user data repository.</param>
|
||||||
|
/// <param name="libraryMonitorFactory">The library monitor.</param>
|
||||||
|
/// <param name="fileSystem">The file system.</param>
|
||||||
|
/// <param name="providerManagerFactory">The provider manager.</param>
|
||||||
|
/// <param name="userviewManagerFactory">The userview manager.</param>
|
||||||
|
/// <param name="mediaEncoder">The media encoder.</param>
|
||||||
|
/// <param name="itemRepository">The item repository.</param>
|
||||||
|
/// <param name="imageProcessor">The image processor.</param>
|
||||||
public LibraryManager(
|
public LibraryManager(
|
||||||
IServerApplicationHost appHost,
|
IServerApplicationHost appHost,
|
||||||
ILogger<LibraryManager> logger,
|
ILogger<LibraryManager> logger,
|
||||||
@ -151,7 +161,8 @@ namespace Emby.Server.Implementations.Library
|
|||||||
Lazy<IProviderManager> providerManagerFactory,
|
Lazy<IProviderManager> providerManagerFactory,
|
||||||
Lazy<IUserViewManager> userviewManagerFactory,
|
Lazy<IUserViewManager> userviewManagerFactory,
|
||||||
IMediaEncoder mediaEncoder,
|
IMediaEncoder mediaEncoder,
|
||||||
IItemRepository itemRepository)
|
IItemRepository itemRepository,
|
||||||
|
IImageProcessor imageProcessor)
|
||||||
{
|
{
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@ -165,6 +176,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
_userviewManagerFactory = userviewManagerFactory;
|
_userviewManagerFactory = userviewManagerFactory;
|
||||||
_mediaEncoder = mediaEncoder;
|
_mediaEncoder = mediaEncoder;
|
||||||
_itemRepository = itemRepository;
|
_itemRepository = itemRepository;
|
||||||
|
_imageProcessor = imageProcessor;
|
||||||
|
|
||||||
_libraryItemsCache = new ConcurrentDictionary<Guid, BaseItem>();
|
_libraryItemsCache = new ConcurrentDictionary<Guid, BaseItem>();
|
||||||
|
|
||||||
@ -1820,10 +1832,90 @@ namespace Emby.Server.Implementations.Library
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateImages(BaseItem item)
|
private bool ImageNeedsRefresh(ItemImageInfo image)
|
||||||
{
|
{
|
||||||
_itemRepository.SaveImages(item);
|
if (image.Path != null && image.IsLocalFile)
|
||||||
|
{
|
||||||
|
if (image.Width == 0 || image.Height == 0 || string.IsNullOrEmpty(image.BlurHash))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return _fileSystem.GetLastWriteTimeUtc(image.Path) != image.DateModified;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Cannot get file info for {0}", image.Path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return image.Path != null && !image.IsLocalFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateImages(BaseItem item, bool forceUpdate = false)
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
var outdated = forceUpdate ? item.ImageInfos.Where(i => i.Path != null).ToArray() : item.ImageInfos.Where(ImageNeedsRefresh).ToArray();
|
||||||
|
if (outdated.Length == 0)
|
||||||
|
{
|
||||||
|
RegisterItem(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var img in outdated)
|
||||||
|
{
|
||||||
|
var image = img;
|
||||||
|
if (!img.IsLocalFile)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var index = item.GetImageIndex(img);
|
||||||
|
image = ConvertImageToLocal(item, img, index).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
catch (ArgumentException)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Cannot get image index for {0}", img.Path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Cannot fetch image from {0}", img.Path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageDimensions size = _imageProcessor.GetImageDimensions(item, image);
|
||||||
|
image.Width = size.Width;
|
||||||
|
image.Height = size.Height;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
image.BlurHash = _imageProcessor.GetImageBlurHash(image.Path);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Cannot compute blurhash for {0}", image.Path);
|
||||||
|
image.BlurHash = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
image.DateModified = _fileSystem.GetLastWriteTimeUtc(image.Path);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Cannot update DateModified for {0}", image.Path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_itemRepository.SaveImages(item);
|
||||||
RegisterItem(item);
|
RegisterItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1844,7 +1936,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
|
|
||||||
item.DateLastSaved = DateTime.UtcNow;
|
item.DateLastSaved = DateTime.UtcNow;
|
||||||
|
|
||||||
RegisterItem(item);
|
UpdateImages(item, updateReason >= ItemUpdateType.ImageUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
_itemRepository.SaveItems(itemsList, cancellationToken);
|
_itemRepository.SaveItems(itemsList, cancellationToken);
|
||||||
|
@ -522,11 +522,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
SetDefaultAudioAndSubtitleStreamIndexes(item, clone, user);
|
SetDefaultAudioAndSubtitleStreamIndexes(item, clone, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Tuple<LiveStreamResponse, IDirectStreamProvider>(new LiveStreamResponse
|
return new Tuple<LiveStreamResponse, IDirectStreamProvider>(new LiveStreamResponse(clone), liveStream as IDirectStreamProvider);
|
||||||
{
|
|
||||||
MediaSource = clone
|
|
||||||
|
|
||||||
}, liveStream as IDirectStreamProvider);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio)
|
private static void AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio)
|
||||||
|
@ -140,11 +140,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnNamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
|
private async void OnNamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
|
||||||
{
|
{
|
||||||
if (string.Equals(e.Key, "livetv", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(e.Key, "livetv", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
OnRecordingFoldersChanged();
|
await CreateRecordingFolders().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,11 +155,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
return CreateRecordingFolders();
|
return CreateRecordingFolders();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnRecordingFoldersChanged()
|
|
||||||
{
|
|
||||||
await CreateRecordingFolders().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal async Task CreateRecordingFolders()
|
internal async Task CreateRecordingFolders()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -1334,7 +1329,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
await CreateRecordingFolders().ConfigureAwait(false);
|
await CreateRecordingFolders().ConfigureAwait(false);
|
||||||
|
|
||||||
TriggerRefresh(recordPath);
|
TriggerRefresh(recordPath);
|
||||||
EnforceKeepUpTo(timer, seriesPath);
|
await EnforceKeepUpTo(timer, seriesPath).ConfigureAwait(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
await recorder.Record(directStreamProvider, mediaStreamInfo, recordPath, duration, onStarted, activeRecordingInfo.CancellationTokenSource.Token).ConfigureAwait(false);
|
await recorder.Record(directStreamProvider, mediaStreamInfo, recordPath, duration, onStarted, activeRecordingInfo.CancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
@ -1494,7 +1489,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void EnforceKeepUpTo(TimerInfo timer, string seriesPath)
|
private async Task EnforceKeepUpTo(TimerInfo timer, string seriesPath)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(timer.SeriesTimerId))
|
if (string.IsNullOrWhiteSpace(timer.SeriesTimerId))
|
||||||
{
|
{
|
||||||
|
@ -117,7 +117,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
onStarted();
|
onStarted();
|
||||||
|
|
||||||
// Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback
|
// Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback
|
||||||
StartStreamingLog(_process.StandardError.BaseStream, _logFileStream);
|
_ = StartStreamingLog(_process.StandardError.BaseStream, _logFileStream);
|
||||||
|
|
||||||
_logger.LogInformation("ffmpeg recording process started for {0}", _targetPath);
|
_logger.LogInformation("ffmpeg recording process started for {0}", _targetPath);
|
||||||
|
|
||||||
@ -321,7 +321,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void StartStreamingLog(Stream source, Stream target)
|
private async Task StartStreamingLog(Stream source, Stream target)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -109,7 +109,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
|
|
||||||
if (startDate < now)
|
if (startDate < now)
|
||||||
{
|
{
|
||||||
TimerFired?.Invoke(this, new GenericEventArgs<TimerInfo> { Argument = item });
|
TimerFired?.Invoke(this, new GenericEventArgs<TimerInfo>(item));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
var timer = GetAll().FirstOrDefault(i => string.Equals(i.Id, timerId, StringComparison.OrdinalIgnoreCase));
|
var timer = GetAll().FirstOrDefault(i => string.Equals(i.Id, timerId, StringComparison.OrdinalIgnoreCase));
|
||||||
if (timer != null)
|
if (timer != null)
|
||||||
{
|
{
|
||||||
TimerFired?.Invoke(this, new GenericEventArgs<TimerInfo> { Argument = timer });
|
TimerFired?.Invoke(this, new GenericEventArgs<TimerInfo>(timer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,27 +148,18 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
{
|
{
|
||||||
var timerId = e.Argument;
|
var timerId = e.Argument;
|
||||||
|
|
||||||
TimerCancelled?.Invoke(this, new GenericEventArgs<TimerEventInfo>
|
TimerCancelled?.Invoke(this, new GenericEventArgs<TimerEventInfo>(new TimerEventInfo(timerId)));
|
||||||
{
|
|
||||||
Argument = new TimerEventInfo
|
|
||||||
{
|
|
||||||
Id = timerId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEmbyTvTimerCreated(object sender, GenericEventArgs<TimerInfo> e)
|
private void OnEmbyTvTimerCreated(object sender, GenericEventArgs<TimerInfo> e)
|
||||||
{
|
{
|
||||||
var timer = e.Argument;
|
var timer = e.Argument;
|
||||||
|
|
||||||
TimerCreated?.Invoke(this, new GenericEventArgs<TimerEventInfo>
|
TimerCreated?.Invoke(this, new GenericEventArgs<TimerEventInfo>(
|
||||||
{
|
new TimerEventInfo(timer.Id)
|
||||||
Argument = new TimerEventInfo
|
|
||||||
{
|
{
|
||||||
ProgramId = _tvDtoService.GetInternalProgramId(timer.ProgramId),
|
ProgramId = _tvDtoService.GetInternalProgramId(timer.ProgramId)
|
||||||
Id = timer.Id
|
}));
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<NameIdPair> GetTunerHostTypes()
|
public List<NameIdPair> GetTunerHostTypes()
|
||||||
@ -786,22 +777,12 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
if (query.OrderBy.Count == 0)
|
if (query.OrderBy.Count == 0)
|
||||||
{
|
{
|
||||||
if (query.IsAiring ?? false)
|
|
||||||
|
// Unless something else was specified, order by start date to take advantage of a specialized index
|
||||||
|
query.OrderBy = new[]
|
||||||
{
|
{
|
||||||
// Unless something else was specified, order by start date to take advantage of a specialized index
|
(ItemSortBy.StartDate, SortOrder.Ascending)
|
||||||
query.OrderBy = new[]
|
};
|
||||||
{
|
|
||||||
(ItemSortBy.StartDate, SortOrder.Ascending)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Unless something else was specified, order by start date to take advantage of a specialized index
|
|
||||||
query.OrderBy = new[]
|
|
||||||
{
|
|
||||||
(ItemSortBy.StartDate, SortOrder.Ascending)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveFields(options);
|
RemoveFields(options);
|
||||||
@ -1732,13 +1713,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
if (!(service is EmbyTV.EmbyTV))
|
if (!(service is EmbyTV.EmbyTV))
|
||||||
{
|
{
|
||||||
TimerCancelled?.Invoke(this, new GenericEventArgs<TimerEventInfo>
|
TimerCancelled?.Invoke(this, new GenericEventArgs<TimerEventInfo>(new TimerEventInfo(id)));
|
||||||
{
|
|
||||||
Argument = new TimerEventInfo
|
|
||||||
{
|
|
||||||
Id = id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1755,13 +1730,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
await service.CancelSeriesTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false);
|
await service.CancelSeriesTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
SeriesTimerCancelled?.Invoke(this, new GenericEventArgs<TimerEventInfo>
|
SeriesTimerCancelled?.Invoke(this, new GenericEventArgs<TimerEventInfo>(new TimerEventInfo(id)));
|
||||||
{
|
|
||||||
Argument = new TimerEventInfo
|
|
||||||
{
|
|
||||||
Id = id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<TimerInfoDto> GetTimer(string id, CancellationToken cancellationToken)
|
public async Task<TimerInfoDto> GetTimer(string id, CancellationToken cancellationToken)
|
||||||
@ -2080,14 +2049,11 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
|
|
||||||
if (!(service is EmbyTV.EmbyTV))
|
if (!(service is EmbyTV.EmbyTV))
|
||||||
{
|
{
|
||||||
TimerCreated?.Invoke(this, new GenericEventArgs<TimerEventInfo>
|
TimerCreated?.Invoke(this, new GenericEventArgs<TimerEventInfo>(
|
||||||
{
|
new TimerEventInfo(newTimerId)
|
||||||
Argument = new TimerEventInfo
|
|
||||||
{
|
{
|
||||||
ProgramId = _tvDtoService.GetInternalProgramId(info.ProgramId),
|
ProgramId = _tvDtoService.GetInternalProgramId(info.ProgramId)
|
||||||
Id = newTimerId
|
}));
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2112,14 +2078,11 @@ namespace Emby.Server.Implementations.LiveTv
|
|||||||
await service.CreateSeriesTimerAsync(info, cancellationToken).ConfigureAwait(false);
|
await service.CreateSeriesTimerAsync(info, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
SeriesTimerCreated?.Invoke(this, new GenericEventArgs<TimerEventInfo>
|
SeriesTimerCreated?.Invoke(this, new GenericEventArgs<TimerEventInfo>(
|
||||||
{
|
new TimerEventInfo(newTimerId)
|
||||||
Argument = new TimerEventInfo
|
|
||||||
{
|
{
|
||||||
ProgramId = _tvDtoService.GetInternalProgramId(info.ProgramId),
|
ProgramId = _tvDtoService.GetInternalProgramId(info.ProgramId)
|
||||||
Id = newTimerId
|
}));
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateTimer(TimerInfoDto timer, CancellationToken cancellationToken)
|
public async Task UpdateTimer(TimerInfoDto timer, CancellationToken cancellationToken)
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -92,5 +92,27 @@
|
|||||||
"UserStoppedPlayingItemWithValues": "{0} ha parat de reproduir {1}",
|
"UserStoppedPlayingItemWithValues": "{0} ha parat de reproduir {1}",
|
||||||
"ValueHasBeenAddedToLibrary": "{0} ha sigut afegit a la teva llibreria",
|
"ValueHasBeenAddedToLibrary": "{0} ha sigut afegit a la teva llibreria",
|
||||||
"ValueSpecialEpisodeName": "Especial - {0}",
|
"ValueSpecialEpisodeName": "Especial - {0}",
|
||||||
"VersionNumber": "Versió {0}"
|
"VersionNumber": "Versió {0}",
|
||||||
|
"TaskDownloadMissingSubtitlesDescription": "Cerca a internet els subtítols que faltin a partir de la configuració de metadades.",
|
||||||
|
"TaskDownloadMissingSubtitles": "Descarrega els subtítols que faltin",
|
||||||
|
"TaskRefreshChannelsDescription": "Actualitza la informació dels canals d'internet.",
|
||||||
|
"TaskRefreshChannels": "Actualitza Canals",
|
||||||
|
"TaskCleanTranscodeDescription": "Elimina els arxius temporals de transcodificacions que tinguin més d'un dia.",
|
||||||
|
"TaskCleanTranscode": "Neteja les transcodificacions",
|
||||||
|
"TaskUpdatePluginsDescription": "Actualitza les extensions que estan configurades per actualitzar-se automàticament.",
|
||||||
|
"TaskUpdatePlugins": "Actualitza les extensions",
|
||||||
|
"TaskRefreshPeopleDescription": "Actualitza les metadades dels actors i directors de la teva mediateca.",
|
||||||
|
"TaskRefreshPeople": "Actualitza Persones",
|
||||||
|
"TaskCleanLogsDescription": "Esborra els logs que tinguin més de {0} dies.",
|
||||||
|
"TaskCleanLogs": "Neteja els registres",
|
||||||
|
"TaskRefreshLibraryDescription": "Escaneja la mediateca buscant fitxers nous i refresca les metadades.",
|
||||||
|
"TaskRefreshLibrary": "Escaneja la biblioteca de mitjans",
|
||||||
|
"TaskRefreshChapterImagesDescription": "Crea les miniatures dels vídeos que tinguin capítols.",
|
||||||
|
"TaskRefreshChapterImages": "Extreure les imatges dels capítols",
|
||||||
|
"TaskCleanCacheDescription": "Elimina els arxius temporals que ja no són necessaris per al servidor.",
|
||||||
|
"TaskCleanCache": "Elimina arxius temporals",
|
||||||
|
"TasksChannelsCategory": "Canals d'internet",
|
||||||
|
"TasksApplicationCategory": "Aplicació",
|
||||||
|
"TasksLibraryCategory": "Biblioteca",
|
||||||
|
"TasksMaintenanceCategory": "Manteniment"
|
||||||
}
|
}
|
||||||
|
117
Emby.Server.Implementations/Localization/Core/es_419.json
Normal file
117
Emby.Server.Implementations/Localization/Core/es_419.json
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
{
|
||||||
|
"LabelRunningTimeValue": "Duración: {0}",
|
||||||
|
"ValueSpecialEpisodeName": "Especial - {0}",
|
||||||
|
"Sync": "Sincronizar",
|
||||||
|
"Songs": "Canciones",
|
||||||
|
"Shows": "Programas",
|
||||||
|
"Playlists": "Listas de reproducción",
|
||||||
|
"Photos": "Fotos",
|
||||||
|
"Movies": "Películas",
|
||||||
|
"HeaderNextUp": "A continuación",
|
||||||
|
"HeaderLiveTV": "TV en vivo",
|
||||||
|
"HeaderFavoriteSongs": "Canciones favoritas",
|
||||||
|
"HeaderFavoriteArtists": "Artistas favoritos",
|
||||||
|
"HeaderFavoriteAlbums": "Álbumes favoritos",
|
||||||
|
"HeaderFavoriteEpisodes": "Episodios favoritos",
|
||||||
|
"HeaderFavoriteShows": "Programas favoritos",
|
||||||
|
"HeaderContinueWatching": "Continuar viendo",
|
||||||
|
"HeaderAlbumArtists": "Artistas del álbum",
|
||||||
|
"Genres": "Géneros",
|
||||||
|
"Folders": "Carpetas",
|
||||||
|
"Favorites": "Favoritos",
|
||||||
|
"Collections": "Colecciones",
|
||||||
|
"Channels": "Canales",
|
||||||
|
"Books": "Libros",
|
||||||
|
"Artists": "Artistas",
|
||||||
|
"Albums": "Álbumes",
|
||||||
|
"TaskDownloadMissingSubtitlesDescription": "Busca subtítulos faltantes en Internet basándose en la configuración de metadatos.",
|
||||||
|
"TaskDownloadMissingSubtitles": "Descargar subtítulos faltantes",
|
||||||
|
"TaskRefreshChannelsDescription": "Actualiza la información de canales de Internet.",
|
||||||
|
"TaskRefreshChannels": "Actualizar canales",
|
||||||
|
"TaskCleanTranscodeDescription": "Elimina archivos transcodificados que tengan más de un día.",
|
||||||
|
"TaskCleanTranscode": "Limpiar directorio de transcodificado",
|
||||||
|
"TaskUpdatePluginsDescription": "Descarga e instala actualizaciones para complementos que están configurados para actualizarse automáticamente.",
|
||||||
|
"TaskUpdatePlugins": "Actualizar complementos",
|
||||||
|
"TaskRefreshPeopleDescription": "Actualiza metadatos de actores y directores en tu biblioteca de medios.",
|
||||||
|
"TaskRefreshPeople": "Actualizar personas",
|
||||||
|
"TaskCleanLogsDescription": "Elimina archivos de registro con más de {0} días de antigüedad.",
|
||||||
|
"TaskCleanLogs": "Limpiar directorio de registros",
|
||||||
|
"TaskRefreshLibraryDescription": "Escanea tu biblioteca de medios por archivos nuevos y actualiza los metadatos.",
|
||||||
|
"TaskRefreshLibrary": "Escanear biblioteca de medios",
|
||||||
|
"TaskRefreshChapterImagesDescription": "Crea miniaturas para videos que tienen capítulos.",
|
||||||
|
"TaskRefreshChapterImages": "Extraer imágenes de los capítulos",
|
||||||
|
"TaskCleanCacheDescription": "Elimina archivos caché que ya no son necesarios para el sistema.",
|
||||||
|
"TaskCleanCache": "Limpiar directorio caché",
|
||||||
|
"TasksChannelsCategory": "Canales de Internet",
|
||||||
|
"TasksApplicationCategory": "Aplicación",
|
||||||
|
"TasksLibraryCategory": "Biblioteca",
|
||||||
|
"TasksMaintenanceCategory": "Mantenimiento",
|
||||||
|
"VersionNumber": "Versión {0}",
|
||||||
|
"ValueHasBeenAddedToLibrary": "{0} se ha añadido a tu biblioteca de medios",
|
||||||
|
"UserStoppedPlayingItemWithValues": "{0} ha terminado de reproducir {1} en {2}",
|
||||||
|
"UserStartedPlayingItemWithValues": "{0} está reproduciendo {1} en {2}",
|
||||||
|
"UserPolicyUpdatedWithName": "La política de usuario ha sido actualizada para {0}",
|
||||||
|
"UserPasswordChangedWithName": "Se ha cambiado la contraseña para el usuario {0}",
|
||||||
|
"UserOnlineFromDevice": "{0} está en línea desde {1}",
|
||||||
|
"UserOfflineFromDevice": "{0} se ha desconectado desde {1}",
|
||||||
|
"UserLockedOutWithName": "El usuario {0} ha sido bloqueado",
|
||||||
|
"UserDownloadingItemWithValues": "{0} está descargando {1}",
|
||||||
|
"UserDeletedWithName": "El usuario {0} ha sido eliminado",
|
||||||
|
"UserCreatedWithName": "El usuario {0} ha sido creado",
|
||||||
|
"User": "Usuario",
|
||||||
|
"TvShows": "Programas de TV",
|
||||||
|
"System": "Sistema",
|
||||||
|
"SubtitleDownloadFailureFromForItem": "Falló la descarga de subtítulos desde {0} para {1}",
|
||||||
|
"StartupEmbyServerIsLoading": "El servidor Jellyfin está cargando. Por favor, intente de nuevo pronto.",
|
||||||
|
"ServerNameNeedsToBeRestarted": "{0} debe ser reiniciado",
|
||||||
|
"ScheduledTaskStartedWithName": "{0} iniciado",
|
||||||
|
"ScheduledTaskFailedWithName": "{0} falló",
|
||||||
|
"ProviderValue": "Proveedor: {0}",
|
||||||
|
"PluginUpdatedWithName": "{0} fue actualizado",
|
||||||
|
"PluginUninstalledWithName": "{0} fue desinstalado",
|
||||||
|
"PluginInstalledWithName": "{0} fue instalado",
|
||||||
|
"Plugin": "Complemento",
|
||||||
|
"NotificationOptionVideoPlaybackStopped": "Reproducción de video detenida",
|
||||||
|
"NotificationOptionVideoPlayback": "Reproducción de video iniciada",
|
||||||
|
"NotificationOptionUserLockedOut": "Usuario bloqueado",
|
||||||
|
"NotificationOptionTaskFailed": "Falla de tarea programada",
|
||||||
|
"NotificationOptionServerRestartRequired": "Se necesita reiniciar el servidor",
|
||||||
|
"NotificationOptionPluginUpdateInstalled": "Actualización de complemento instalada",
|
||||||
|
"NotificationOptionPluginUninstalled": "Complemento desinstalado",
|
||||||
|
"NotificationOptionPluginInstalled": "Complemento instalado",
|
||||||
|
"NotificationOptionPluginError": "Falla de complemento",
|
||||||
|
"NotificationOptionNewLibraryContent": "Nuevo contenido agregado",
|
||||||
|
"NotificationOptionInstallationFailed": "Falla de instalación",
|
||||||
|
"NotificationOptionCameraImageUploaded": "Imagen de la cámara subida",
|
||||||
|
"NotificationOptionAudioPlaybackStopped": "Reproducción de audio detenida",
|
||||||
|
"NotificationOptionAudioPlayback": "Reproducción de audio iniciada",
|
||||||
|
"NotificationOptionApplicationUpdateInstalled": "Actualización de la aplicación instalada",
|
||||||
|
"NotificationOptionApplicationUpdateAvailable": "Actualización de la aplicación disponible",
|
||||||
|
"NewVersionIsAvailable": "Una nueva versión del Servidor Jellyfin está disponible para descargar.",
|
||||||
|
"NameSeasonUnknown": "Temporada desconocida",
|
||||||
|
"NameSeasonNumber": "Temporada {0}",
|
||||||
|
"NameInstallFailed": "Falló la instalación de {0}",
|
||||||
|
"MusicVideos": "Videos musicales",
|
||||||
|
"Music": "Música",
|
||||||
|
"MixedContent": "Contenido mezclado",
|
||||||
|
"MessageServerConfigurationUpdated": "Se ha actualizado la configuración del servidor",
|
||||||
|
"MessageNamedServerConfigurationUpdatedWithValue": "Se ha actualizado la sección {0} de la configuración del servidor",
|
||||||
|
"MessageApplicationUpdatedTo": "El servidor Jellyfin ha sido actualizado a {0}",
|
||||||
|
"MessageApplicationUpdated": "El servidor Jellyfin ha sido actualizado",
|
||||||
|
"Latest": "Recientes",
|
||||||
|
"LabelIpAddressValue": "Dirección IP: {0}",
|
||||||
|
"ItemRemovedWithName": "{0} fue removido de la biblioteca",
|
||||||
|
"ItemAddedWithName": "{0} fue agregado a la biblioteca",
|
||||||
|
"Inherit": "Heredar",
|
||||||
|
"HomeVideos": "Videos caseros",
|
||||||
|
"HeaderRecordingGroups": "Grupos de grabación",
|
||||||
|
"HeaderCameraUploads": "Subidas desde la cámara",
|
||||||
|
"FailedLoginAttemptWithUserName": "Intento fallido de inicio de sesión desde {0}",
|
||||||
|
"DeviceOnlineWithName": "{0} está conectado",
|
||||||
|
"DeviceOfflineWithName": "{0} se ha desconectado",
|
||||||
|
"ChapterNameValue": "Capítulo {0}",
|
||||||
|
"CameraImageUploadedFrom": "Una nueva imagen de cámara ha sido subida desde {0}",
|
||||||
|
"AuthenticationSucceededWithUserName": "{0} autenticado con éxito",
|
||||||
|
"Application": "Aplicación",
|
||||||
|
"AppDeviceValues": "App: {0}, Dispositivo: {1}"
|
||||||
|
}
|
@ -5,7 +5,7 @@
|
|||||||
"Artists": "Artistes",
|
"Artists": "Artistes",
|
||||||
"AuthenticationSucceededWithUserName": "{0} authentifié avec succès",
|
"AuthenticationSucceededWithUserName": "{0} authentifié avec succès",
|
||||||
"Books": "Livres",
|
"Books": "Livres",
|
||||||
"CameraImageUploadedFrom": "Une nouvelle photographie a été chargée depuis {0}",
|
"CameraImageUploadedFrom": "Une photo a été chargée depuis {0}",
|
||||||
"Channels": "Chaînes",
|
"Channels": "Chaînes",
|
||||||
"ChapterNameValue": "Chapitre {0}",
|
"ChapterNameValue": "Chapitre {0}",
|
||||||
"Collections": "Collections",
|
"Collections": "Collections",
|
||||||
@ -15,7 +15,7 @@
|
|||||||
"Favorites": "Favoris",
|
"Favorites": "Favoris",
|
||||||
"Folders": "Dossiers",
|
"Folders": "Dossiers",
|
||||||
"Genres": "Genres",
|
"Genres": "Genres",
|
||||||
"HeaderAlbumArtists": "Artistes de l'album",
|
"HeaderAlbumArtists": "Artistes",
|
||||||
"HeaderCameraUploads": "Photos transférées",
|
"HeaderCameraUploads": "Photos transférées",
|
||||||
"HeaderContinueWatching": "Continuer à regarder",
|
"HeaderContinueWatching": "Continuer à regarder",
|
||||||
"HeaderFavoriteAlbums": "Albums favoris",
|
"HeaderFavoriteAlbums": "Albums favoris",
|
||||||
|
99
Emby.Server.Implementations/Localization/Core/ta.json
Normal file
99
Emby.Server.Implementations/Localization/Core/ta.json
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
{
|
||||||
|
"VersionNumber": "பதிப்பு {0}",
|
||||||
|
"ValueSpecialEpisodeName": "சிறப்பு - {0}",
|
||||||
|
"TasksMaintenanceCategory": "பராமரிப்பு",
|
||||||
|
"TaskCleanCache": "தற்காலிக சேமிப்பு கோப்பகத்தை சுத்தம் செய்யவும்",
|
||||||
|
"TaskRefreshChapterImages": "அத்தியாயப் படங்களை பிரித்தெடுக்கவும்",
|
||||||
|
"TaskRefreshPeople": "மக்களைப் புதுப்பிக்கவும்",
|
||||||
|
"TaskCleanTranscode": "டிரான்ஸ்கோட் கோப்பகத்தை சுத்தம் செய்யவும்",
|
||||||
|
"TaskRefreshChannelsDescription": "இணையச் சேனல் தகவல்களைப் புதுப்பிக்கிறது.",
|
||||||
|
"System": "ஒருங்கியம்",
|
||||||
|
"NotificationOptionTaskFailed": "திட்டமிடப்பட்ட பணி தோல்வியடைந்தது",
|
||||||
|
"NotificationOptionPluginUpdateInstalled": "உட்செருகி புதுப்பிக்கப்பட்டது",
|
||||||
|
"NotificationOptionPluginUninstalled": "உட்செருகி நீக்கப்பட்டது",
|
||||||
|
"NotificationOptionPluginInstalled": "உட்செருகி நிறுவப்பட்டது",
|
||||||
|
"NotificationOptionPluginError": "உட்செருகி செயலிழந்தது",
|
||||||
|
"NotificationOptionCameraImageUploaded": "புகைப்படம் பதிவேற்றப்பட்டது",
|
||||||
|
"MixedContent": "கலப்பு உள்ளடக்கங்கள்",
|
||||||
|
"MessageServerConfigurationUpdated": "சேவையக அமைப்புகள் புதுப்பிக்கப்பட்டன",
|
||||||
|
"MessageApplicationUpdatedTo": "ஜெல்லிஃபின் சேவையகம் {0} இற்கு புதுப்பிக்கப்பட்டது",
|
||||||
|
"MessageApplicationUpdated": "ஜெல்லிஃபின் சேவையகம் புதுப்பிக்கப்பட்டது",
|
||||||
|
"Inherit": "மரபரிமையாகப் பெறு",
|
||||||
|
"HeaderRecordingGroups": "பதிவு குழுக்கள்",
|
||||||
|
"HeaderCameraUploads": "புகைப்பட பதிவேற்றங்கள்",
|
||||||
|
"Folders": "கோப்புறைகள்",
|
||||||
|
"FailedLoginAttemptWithUserName": "{0} இலிருந்து உள்நுழைவு முயற்சி தோல்வியடைந்தது",
|
||||||
|
"DeviceOnlineWithName": "{0} இணைக்கப்பட்டது",
|
||||||
|
"DeviceOfflineWithName": "{0} துண்டிக்கப்பட்டது",
|
||||||
|
"Collections": "தொகுப்புகள்",
|
||||||
|
"CameraImageUploadedFrom": "{0} இலிருந்து புதிய புகைப்படம் பதிவேற்றப்பட்டது",
|
||||||
|
"AppDeviceValues": "செயலி: {0}, சாதனம்: {1}",
|
||||||
|
"TaskDownloadMissingSubtitles": "விடுபட்டுபோன வசன வரிகளைப் பதிவிறக்கு",
|
||||||
|
"TaskRefreshChannels": "சேனல்களை புதுப்பி",
|
||||||
|
"TaskUpdatePlugins": "உட்செருகிகளை புதுப்பி",
|
||||||
|
"TaskRefreshLibrary": "மீடியா நூலகத்தை ஆராய்",
|
||||||
|
"TasksChannelsCategory": "இணைய சேனல்கள்",
|
||||||
|
"TasksApplicationCategory": "செயலி",
|
||||||
|
"TasksLibraryCategory": "நூலகம்",
|
||||||
|
"UserPolicyUpdatedWithName": "பயனர் கொள்கை {0} இற்கு புதுப்பிக்கப்பட்டுள்ளது",
|
||||||
|
"UserPasswordChangedWithName": "{0} பயனருக்கு கடவுச்சொல் மாற்றப்பட்டுள்ளது",
|
||||||
|
"UserLockedOutWithName": "பயனர் {0} முடக்கப்பட்டார்",
|
||||||
|
"UserDownloadingItemWithValues": "{0} ஆல் {1} பதிவிறக்கப்படுகிறது",
|
||||||
|
"UserDeletedWithName": "பயனர் {0} நீக்கப்பட்டார்",
|
||||||
|
"UserCreatedWithName": "பயனர் {0} உருவாக்கப்பட்டார்",
|
||||||
|
"User": "பயனர்",
|
||||||
|
"TvShows": "தொலைக்காட்சித் தொடர்கள்",
|
||||||
|
"Sync": "ஒத்திசைவு",
|
||||||
|
"StartupEmbyServerIsLoading": "ஜெல்லிஃபின் சேவையகம் துவங்குகிறது. சிறிது நேரம் கழித்து முயற்சிக்கவும்.",
|
||||||
|
"Songs": "பாட்டுகள்",
|
||||||
|
"Shows": "தொடர்கள்",
|
||||||
|
"ServerNameNeedsToBeRestarted": "{0} மறுதொடக்கம் செய்யப்பட வேண்டும்",
|
||||||
|
"ScheduledTaskStartedWithName": "{0} துவங்கியது",
|
||||||
|
"ScheduledTaskFailedWithName": "{0} தோல்வியடைந்தது",
|
||||||
|
"ProviderValue": "வழங்குநர்: {0}",
|
||||||
|
"PluginUpdatedWithName": "{0} புதுப்பிக்கப்பட்டது",
|
||||||
|
"PluginUninstalledWithName": "{0} நீக்கப்பட்டது",
|
||||||
|
"PluginInstalledWithName": "{0} நிறுவப்பட்டது",
|
||||||
|
"Plugin": "உட்செருகி",
|
||||||
|
"Playlists": "தொடர் பட்டியல்கள்",
|
||||||
|
"Photos": "புகைப்படங்கள்",
|
||||||
|
"NotificationOptionVideoPlaybackStopped": "நிகழ்பட ஒளிபரப்பு நிறுத்தப்பட்டது",
|
||||||
|
"NotificationOptionVideoPlayback": "நிகழ்பட ஒளிபரப்பு துவங்கியது",
|
||||||
|
"NotificationOptionUserLockedOut": "பயனர் கணக்கு முடக்கப்பட்டது",
|
||||||
|
"NotificationOptionServerRestartRequired": "சேவையக மறுதொடக்கம் தேவை",
|
||||||
|
"NotificationOptionNewLibraryContent": "புதிய உள்ளடக்கங்கள் சேர்க்கப்பட்டன",
|
||||||
|
"NotificationOptionInstallationFailed": "நிறுவல் தோல்வியடைந்தது",
|
||||||
|
"NotificationOptionAudioPlaybackStopped": "ஒலி இசைத்தல் நிறுத்தப்பட்டது",
|
||||||
|
"NotificationOptionAudioPlayback": "ஒலி இசைக்கத் துவங்கியுள்ளது",
|
||||||
|
"NotificationOptionApplicationUpdateInstalled": "செயலி புதுப்பிக்கப்பட்டது",
|
||||||
|
"NotificationOptionApplicationUpdateAvailable": "செயலியினை புதுப்பிக்கலாம்",
|
||||||
|
"NameSeasonUnknown": "பருவம் அறியப்படாதவை",
|
||||||
|
"NameSeasonNumber": "பருவம் {0}",
|
||||||
|
"NameInstallFailed": "{0} நிறுவல் தோல்வியடைந்தது",
|
||||||
|
"MusicVideos": "இசைப்படங்கள்",
|
||||||
|
"Music": "இசை",
|
||||||
|
"Movies": "திரைப்படங்கள்",
|
||||||
|
"Latest": "புதியன",
|
||||||
|
"LabelRunningTimeValue": "ஓடும் நேரம்: {0}",
|
||||||
|
"LabelIpAddressValue": "ஐபி முகவரி: {0}",
|
||||||
|
"ItemRemovedWithName": "{0} நூலகத்திலிருந்து அகற்றப்பட்டது",
|
||||||
|
"ItemAddedWithName": "{0} நூலகத்தில் சேர்க்கப்பட்டது",
|
||||||
|
"HeaderNextUp": "அடுத்ததாக",
|
||||||
|
"HeaderLiveTV": "நேரடித் தொலைக்காட்சி",
|
||||||
|
"HeaderFavoriteSongs": "பிடித்த பாட்டுகள்",
|
||||||
|
"HeaderFavoriteShows": "பிடித்த தொடர்கள்",
|
||||||
|
"HeaderFavoriteEpisodes": "பிடித்த அத்தியாயங்கள்",
|
||||||
|
"HeaderFavoriteArtists": "பிடித்த கலைஞர்கள்",
|
||||||
|
"HeaderFavoriteAlbums": "பிடித்த ஆல்பங்கள்",
|
||||||
|
"HeaderContinueWatching": "தொடர்ந்து பார்",
|
||||||
|
"HeaderAlbumArtists": "இசைக் கலைஞர்கள்",
|
||||||
|
"Genres": "வகைகள்",
|
||||||
|
"Favorites": "பிடித்தவை",
|
||||||
|
"ChapterNameValue": "அத்தியாயம் {0}",
|
||||||
|
"Channels": "சேனல்கள்",
|
||||||
|
"Books": "புத்தகங்கள்",
|
||||||
|
"AuthenticationSucceededWithUserName": "{0} வெற்றிகரமாக அங்கீகரிக்கப்பட்டது",
|
||||||
|
"Artists": "கலைஞர்கள்",
|
||||||
|
"Application": "செயலி",
|
||||||
|
"Albums": "ஆல்பங்கள்"
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@ -156,10 +158,7 @@ namespace Emby.Server.Implementations.Playlists
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return new PlaylistCreationResult
|
return new PlaylistCreationResult(playlist.Id.ToString("N", CultureInfo.InvariantCulture));
|
||||||
{
|
|
||||||
Id = playlist.Id.ToString("N", CultureInfo.InvariantCulture)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -51,7 +53,6 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The task manager.</value>
|
/// <value>The task manager.</value>
|
||||||
private ITaskManager TaskManager { get; set; }
|
private ITaskManager TaskManager { get; set; }
|
||||||
private readonly IFileSystem _fileSystem;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ScheduledTaskWorker" /> class.
|
/// Initializes a new instance of the <see cref="ScheduledTaskWorker" /> class.
|
||||||
@ -72,24 +73,28 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
/// or
|
/// or
|
||||||
/// logger
|
/// logger
|
||||||
/// </exception>
|
/// </exception>
|
||||||
public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger, IFileSystem fileSystem)
|
public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger)
|
||||||
{
|
{
|
||||||
if (scheduledTask == null)
|
if (scheduledTask == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(scheduledTask));
|
throw new ArgumentNullException(nameof(scheduledTask));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (applicationPaths == null)
|
if (applicationPaths == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(applicationPaths));
|
throw new ArgumentNullException(nameof(applicationPaths));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (taskManager == null)
|
if (taskManager == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(taskManager));
|
throw new ArgumentNullException(nameof(taskManager));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jsonSerializer == null)
|
if (jsonSerializer == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(jsonSerializer));
|
throw new ArgumentNullException(nameof(jsonSerializer));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logger == null)
|
if (logger == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(logger));
|
throw new ArgumentNullException(nameof(logger));
|
||||||
@ -100,7 +105,6 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
TaskManager = taskManager;
|
TaskManager = taskManager;
|
||||||
JsonSerializer = jsonSerializer;
|
JsonSerializer = jsonSerializer;
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
_fileSystem = fileSystem;
|
|
||||||
|
|
||||||
InitTriggerEvents();
|
InitTriggerEvents();
|
||||||
}
|
}
|
||||||
@ -392,7 +396,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
|
|
||||||
((TaskManager)TaskManager).OnTaskExecuting(this);
|
((TaskManager)TaskManager).OnTaskExecuting(this);
|
||||||
|
|
||||||
progress.ProgressChanged += progress_ProgressChanged;
|
progress.ProgressChanged += OnProgressChanged;
|
||||||
|
|
||||||
TaskCompletionStatus status;
|
TaskCompletionStatus status;
|
||||||
CurrentExecutionStartTime = DateTime.UtcNow;
|
CurrentExecutionStartTime = DateTime.UtcNow;
|
||||||
@ -426,7 +430,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
var startTime = CurrentExecutionStartTime;
|
var startTime = CurrentExecutionStartTime;
|
||||||
var endTime = DateTime.UtcNow;
|
var endTime = DateTime.UtcNow;
|
||||||
|
|
||||||
progress.ProgressChanged -= progress_ProgressChanged;
|
progress.ProgressChanged -= OnProgressChanged;
|
||||||
CurrentCancellationTokenSource.Dispose();
|
CurrentCancellationTokenSource.Dispose();
|
||||||
CurrentCancellationTokenSource = null;
|
CurrentCancellationTokenSource = null;
|
||||||
CurrentProgress = null;
|
CurrentProgress = null;
|
||||||
@ -439,16 +443,13 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender">The sender.</param>
|
/// <param name="sender">The sender.</param>
|
||||||
/// <param name="e">The e.</param>
|
/// <param name="e">The e.</param>
|
||||||
void progress_ProgressChanged(object sender, double e)
|
private void OnProgressChanged(object sender, double e)
|
||||||
{
|
{
|
||||||
e = Math.Min(e, 100);
|
e = Math.Min(e, 100);
|
||||||
|
|
||||||
CurrentProgress = e;
|
CurrentProgress = e;
|
||||||
|
|
||||||
TaskProgress?.Invoke(this, new GenericEventArgs<double>
|
TaskProgress?.Invoke(this, new GenericEventArgs<double>(e));
|
||||||
{
|
|
||||||
Argument = e
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -576,6 +577,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
/// <param name="startTime">The start time.</param>
|
/// <param name="startTime">The start time.</param>
|
||||||
/// <param name="endTime">The end time.</param>
|
/// <param name="endTime">The end time.</param>
|
||||||
/// <param name="status">The status.</param>
|
/// <param name="status">The status.</param>
|
||||||
|
/// <param name="ex">The exception.</param>
|
||||||
private void OnTaskCompleted(DateTime startTime, DateTime endTime, TaskCompletionStatus status, Exception ex)
|
private void OnTaskCompleted(DateTime startTime, DateTime endTime, TaskCompletionStatus status, Exception ex)
|
||||||
{
|
{
|
||||||
var elapsedTime = endTime - startTime;
|
var elapsedTime = endTime - startTime;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -199,7 +201,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
/// <param name="tasks">The tasks.</param>
|
/// <param name="tasks">The tasks.</param>
|
||||||
public void AddTasks(IEnumerable<IScheduledTask> tasks)
|
public void AddTasks(IEnumerable<IScheduledTask> tasks)
|
||||||
{
|
{
|
||||||
var list = tasks.Select(t => new ScheduledTaskWorker(t, _applicationPaths, this, _jsonSerializer, _logger, _fileSystem));
|
var list = tasks.Select(t => new ScheduledTaskWorker(t, _applicationPaths, this, _jsonSerializer, _logger));
|
||||||
|
|
||||||
ScheduledTasks = ScheduledTasks.Concat(list).ToArray();
|
ScheduledTasks = ScheduledTasks.Concat(list).ToArray();
|
||||||
}
|
}
|
||||||
@ -240,10 +242,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
/// <param name="task">The task.</param>
|
/// <param name="task">The task.</param>
|
||||||
internal void OnTaskExecuting(IScheduledTaskWorker task)
|
internal void OnTaskExecuting(IScheduledTaskWorker task)
|
||||||
{
|
{
|
||||||
TaskExecuting?.Invoke(this, new GenericEventArgs<IScheduledTaskWorker>
|
TaskExecuting?.Invoke(this, new GenericEventArgs<IScheduledTaskWorker>(task));
|
||||||
{
|
|
||||||
Argument = task
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -253,11 +252,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
/// <param name="result">The result.</param>
|
/// <param name="result">The result.</param>
|
||||||
internal void OnTaskCompleted(IScheduledTaskWorker task, TaskResult result)
|
internal void OnTaskCompleted(IScheduledTaskWorker task, TaskResult result)
|
||||||
{
|
{
|
||||||
TaskCompleted?.Invoke(task, new TaskCompletionEventArgs
|
TaskCompleted?.Invoke(task, new TaskCompletionEventArgs(task, result));
|
||||||
{
|
|
||||||
Result = result,
|
|
||||||
Task = task
|
|
||||||
});
|
|
||||||
|
|
||||||
ExecuteQueuedTasks();
|
ExecuteQueuedTasks();
|
||||||
}
|
}
|
||||||
|
@ -169,18 +169,25 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Name => _localization.GetLocalizedString("TaskRefreshChapterImages");
|
public string Name => _localization.GetLocalizedString("TaskRefreshChapterImages");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Description => _localization.GetLocalizedString("TaskRefreshChapterImagesDescription");
|
public string Description => _localization.GetLocalizedString("TaskRefreshChapterImagesDescription");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
|
public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Key => "RefreshChapterImages";
|
public string Key => "RefreshChapterImages";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool IsHidden => false;
|
public bool IsHidden => false;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool IsEnabled => true;
|
public bool IsEnabled => true;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool IsLogged => true;
|
public bool IsLogged => true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,18 +165,25 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Name => _localization.GetLocalizedString("TaskCleanCache");
|
public string Name => _localization.GetLocalizedString("TaskCleanCache");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Description => _localization.GetLocalizedString("TaskCleanCacheDescription");
|
public string Description => _localization.GetLocalizedString("TaskCleanCacheDescription");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
|
public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Key => "DeleteCacheFiles";
|
public string Key => "DeleteCacheFiles";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool IsHidden => false;
|
public bool IsHidden => false;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool IsEnabled => true;
|
public bool IsEnabled => true;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool IsLogged => true;
|
public bool IsLogged => true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,8 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||||||
/// Initializes a new instance of the <see cref="DeleteLogFileTask" /> class.
|
/// Initializes a new instance of the <see cref="DeleteLogFileTask" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="configurationManager">The configuration manager.</param>
|
/// <param name="configurationManager">The configuration manager.</param>
|
||||||
|
/// <param name="fileSystem">The file system.</param>
|
||||||
|
/// <param name="localization">The localization manager.</param>
|
||||||
public DeleteLogFileTask(IConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization)
|
public DeleteLogFileTask(IConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization)
|
||||||
{
|
{
|
||||||
ConfigurationManager = configurationManager;
|
ConfigurationManager = configurationManager;
|
||||||
@ -82,18 +84,25 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Name => _localization.GetLocalizedString("TaskCleanLogs");
|
public string Name => _localization.GetLocalizedString("TaskCleanLogs");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Description => string.Format(_localization.GetLocalizedString("TaskCleanLogsDescription"), ConfigurationManager.CommonConfiguration.LogFileRetentionDays);
|
public string Description => string.Format(_localization.GetLocalizedString("TaskCleanLogsDescription"), ConfigurationManager.CommonConfiguration.LogFileRetentionDays);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
|
public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Key => "CleanLogFiles";
|
public string Key => "CleanLogFiles";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool IsHidden => false;
|
public bool IsHidden => false;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool IsEnabled => true;
|
public bool IsEnabled => true;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool IsLogged => true;
|
public bool IsLogged => true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,18 +132,25 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Name => _localization.GetLocalizedString("TaskCleanTranscode");
|
public string Name => _localization.GetLocalizedString("TaskCleanTranscode");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Description => _localization.GetLocalizedString("TaskCleanTranscodeDescription");
|
public string Description => _localization.GetLocalizedString("TaskCleanTranscodeDescription");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
|
public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Key => "DeleteTranscodeFiles";
|
public string Key => "DeleteTranscodeFiles";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool IsHidden => false;
|
public bool IsHidden => false;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool IsEnabled => false;
|
public bool IsEnabled => false;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool IsLogged => true;
|
public bool IsLogged => true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Controller;
|
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Tasks;
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
@ -18,19 +19,16 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
/// The library manager.
|
/// The library manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
private readonly IServerApplicationHost _appHost;
|
|
||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="PeopleValidationTask" /> class.
|
/// Initializes a new instance of the <see cref="PeopleValidationTask" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
/// <param name="appHost">The server application host</param>
|
/// <param name="localization">The localization manager.</param>
|
||||||
public PeopleValidationTask(ILibraryManager libraryManager, IServerApplicationHost appHost, ILocalizationManager localization)
|
public PeopleValidationTask(ILibraryManager libraryManager, ILocalizationManager localization)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_appHost = appHost;
|
|
||||||
_localization = localization;
|
_localization = localization;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -80,11 +82,11 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
}
|
}
|
||||||
catch (HttpException ex)
|
catch (HttpException ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Error downloading {0}", package.name);
|
_logger.LogError(ex, "Error downloading {0}", package.Name);
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Error updating {0}", package.name);
|
_logger.LogError(ex, "Error updating {0}", package.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update progress
|
// Update progress
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Emby.Server.Implementations.Library;
|
using Emby.Server.Implementations.Library;
|
||||||
using MediaBrowser.Controller.Configuration;
|
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Tasks;
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
@ -16,20 +17,19 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
public class RefreshMediaLibraryTask : IScheduledTask
|
public class RefreshMediaLibraryTask : IScheduledTask
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _library manager
|
/// The _library manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IServerConfigurationManager _config;
|
|
||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="RefreshMediaLibraryTask" /> class.
|
/// Initializes a new instance of the <see cref="RefreshMediaLibraryTask" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
public RefreshMediaLibraryTask(ILibraryManager libraryManager, IServerConfigurationManager config, ILocalizationManager localization)
|
/// <param name="localization">The localization manager.</param>
|
||||||
|
public RefreshMediaLibraryTask(ILibraryManager libraryManager, ILocalizationManager localization)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_config = config;
|
|
||||||
_localization = localization;
|
_localization = localization;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,18 +61,25 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
return ((LibraryManager)_libraryManager).ValidateMediaLibraryInternal(progress, cancellationToken);
|
return ((LibraryManager)_libraryManager).ValidateMediaLibraryInternal(progress, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Name => _localization.GetLocalizedString("TaskRefreshLibrary");
|
public string Name => _localization.GetLocalizedString("TaskRefreshLibrary");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Description => _localization.GetLocalizedString("TaskRefreshLibraryDescription");
|
public string Description => _localization.GetLocalizedString("TaskRefreshLibraryDescription");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
|
public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Key => "RefreshLibrary";
|
public string Key => "RefreshLibrary";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool IsHidden => false;
|
public bool IsHidden => false;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool IsEnabled => true;
|
public bool IsEnabled => true;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool IsLogged => true;
|
public bool IsLogged => true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,8 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
/// Stars waiting for the trigger action
|
/// Stars waiting for the trigger action
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lastResult">The last result.</param>
|
/// <param name="lastResult">The last result.</param>
|
||||||
|
/// <param name="logger">The logger.</param>
|
||||||
|
/// <param name="taskName">The name of the task.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
|
public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
|
||||||
{
|
{
|
||||||
@ -77,10 +79,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnTriggered()
|
private void OnTriggered()
|
||||||
{
|
{
|
||||||
if (Triggered != null)
|
Triggered?.Invoke(this, EventArgs.Empty);
|
||||||
{
|
|
||||||
Triggered(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,8 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
/// Stars waiting for the trigger action
|
/// Stars waiting for the trigger action
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lastResult">The last result.</param>
|
/// <param name="lastResult">The last result.</param>
|
||||||
|
/// <param name="logger">The logger.</param>
|
||||||
|
/// <param name="taskName">The name of the task.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
|
public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Tasks;
|
||||||
@ -6,7 +8,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
namespace Emby.Server.Implementations.ScheduledTasks
|
namespace Emby.Server.Implementations.ScheduledTasks
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class StartupTaskTrigger
|
/// Class StartupTaskTrigger.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class StartupTrigger : ITaskTrigger
|
public class StartupTrigger : ITaskTrigger
|
||||||
{
|
{
|
||||||
@ -26,6 +28,8 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
/// Stars waiting for the trigger action
|
/// Stars waiting for the trigger action
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lastResult">The last result.</param>
|
/// <param name="lastResult">The last result.</param>
|
||||||
|
/// <param name="logger">The logger.</param>
|
||||||
|
/// <param name="taskName">The name of the task.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
public async void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
|
public async void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
|
||||||
{
|
{
|
||||||
|
@ -37,6 +37,8 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
/// Stars waiting for the trigger action
|
/// Stars waiting for the trigger action
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lastResult">The last result.</param>
|
/// <param name="lastResult">The last result.</param>
|
||||||
|
/// <param name="logger">The logger.</param>
|
||||||
|
/// <param name="taskName">The name of the task.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
|
public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -11,6 +13,9 @@ namespace Emby.Server.Implementations.Serialization
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class JsonSerializer : IJsonSerializer
|
public class JsonSerializer : IJsonSerializer
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="JsonSerializer" /> class.
|
||||||
|
/// </summary>
|
||||||
public JsonSerializer()
|
public JsonSerializer()
|
||||||
{
|
{
|
||||||
ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.DateHandler.ISO8601;
|
ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.DateHandler.ISO8601;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -43,10 +45,7 @@ namespace Emby.Server.Implementations.Services
|
|||||||
|
|
||||||
private static string GetContentTypeWithoutEncoding(string contentType)
|
private static string GetContentTypeWithoutEncoding(string contentType)
|
||||||
{
|
{
|
||||||
return contentType == null
|
return contentType?.Split(';')[0].ToLowerInvariant().Trim();
|
||||||
? null
|
|
||||||
: contentType.Split(';')[0].ToLowerInvariant().Trim();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -43,8 +45,7 @@ namespace Emby.Server.Implementations.Services
|
|||||||
response.StatusCode = httpResult.Status;
|
response.StatusCode = httpResult.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
var responseOptions = result as IHasHeaders;
|
if (result is IHasHeaders responseOptions)
|
||||||
if (responseOptions != null)
|
|
||||||
{
|
{
|
||||||
foreach (var responseHeaders in responseOptions.Headers)
|
foreach (var responseHeaders in responseOptions.Headers)
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.Services
|
namespace Emby.Server.Implementations.Services
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using MediaBrowser.Model.Services;
|
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.SocketSharp
|
|
||||||
{
|
|
||||||
public class HttpFile : IHttpFile
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
public string FileName { get; set; }
|
|
||||||
|
|
||||||
public long ContentLength { get; set; }
|
|
||||||
|
|
||||||
public string ContentType { get; set; }
|
|
||||||
|
|
||||||
public Stream InputStream { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,198 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
public sealed class HttpPostedFile : IDisposable
|
|
||||||
{
|
|
||||||
private string _name;
|
|
||||||
private string _contentType;
|
|
||||||
private Stream _stream;
|
|
||||||
private bool _disposed = false;
|
|
||||||
|
|
||||||
internal HttpPostedFile(string name, string content_type, Stream base_stream, long offset, long length)
|
|
||||||
{
|
|
||||||
_name = name;
|
|
||||||
_contentType = content_type;
|
|
||||||
_stream = new ReadSubStream(base_stream, offset, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ContentType => _contentType;
|
|
||||||
|
|
||||||
public int ContentLength => (int)_stream.Length;
|
|
||||||
|
|
||||||
public string FileName => _name;
|
|
||||||
|
|
||||||
public Stream InputStream => _stream;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Releases the unmanaged resources and disposes of the managed resources used.
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_stream.Dispose();
|
|
||||||
_stream = null;
|
|
||||||
|
|
||||||
_name = null;
|
|
||||||
_contentType = null;
|
|
||||||
|
|
||||||
_disposed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ReadSubStream : Stream
|
|
||||||
{
|
|
||||||
private Stream _stream;
|
|
||||||
private long _offset;
|
|
||||||
private long _end;
|
|
||||||
private long _position;
|
|
||||||
|
|
||||||
public ReadSubStream(Stream s, long offset, long length)
|
|
||||||
{
|
|
||||||
_stream = s;
|
|
||||||
_offset = offset;
|
|
||||||
_end = offset + length;
|
|
||||||
_position = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanRead => true;
|
|
||||||
|
|
||||||
public override bool CanSeek => true;
|
|
||||||
|
|
||||||
public override bool CanWrite => false;
|
|
||||||
|
|
||||||
public override long Length => _end - _offset;
|
|
||||||
|
|
||||||
public override long Position
|
|
||||||
{
|
|
||||||
get => _position - _offset;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value > Length)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
_position = Seek(value, SeekOrigin.Begin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Flush()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int Read(byte[] buffer, int dest_offset, int count)
|
|
||||||
{
|
|
||||||
if (buffer == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dest_offset < 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(dest_offset), "< 0");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count < 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(count), "< 0");
|
|
||||||
}
|
|
||||||
|
|
||||||
int len = buffer.Length;
|
|
||||||
if (dest_offset > len)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("destination offset is beyond array size", nameof(dest_offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
// reordered to avoid possible integer overflow
|
|
||||||
if (dest_offset > len - count)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Reading would overrun buffer", nameof(count));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count > _end - _position)
|
|
||||||
{
|
|
||||||
count = (int)(_end - _position);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count <= 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
_stream.Position = _position;
|
|
||||||
int result = _stream.Read(buffer, dest_offset, count);
|
|
||||||
if (result > 0)
|
|
||||||
{
|
|
||||||
_position += result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_position = _end;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int ReadByte()
|
|
||||||
{
|
|
||||||
if (_position >= _end)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
_stream.Position = _position;
|
|
||||||
int result = _stream.ReadByte();
|
|
||||||
if (result < 0)
|
|
||||||
{
|
|
||||||
_position = _end;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_position++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Seek(long d, SeekOrigin origin)
|
|
||||||
{
|
|
||||||
long real;
|
|
||||||
switch (origin)
|
|
||||||
{
|
|
||||||
case SeekOrigin.Begin:
|
|
||||||
real = _offset + d;
|
|
||||||
break;
|
|
||||||
case SeekOrigin.End:
|
|
||||||
real = _end + d;
|
|
||||||
break;
|
|
||||||
case SeekOrigin.Current:
|
|
||||||
real = _position + d;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentException("Unknown SeekOrigin value", nameof(origin));
|
|
||||||
}
|
|
||||||
|
|
||||||
long virt = real - _offset;
|
|
||||||
if (virt < 0 || virt > Length)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Invalid position", nameof(d));
|
|
||||||
}
|
|
||||||
|
|
||||||
_position = _stream.Seek(real, SeekOrigin.Begin);
|
|
||||||
return _position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetLength(long value)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -209,7 +211,7 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||||||
private static string GetQueryStringContentType(HttpRequest httpReq)
|
private static string GetQueryStringContentType(HttpRequest httpReq)
|
||||||
{
|
{
|
||||||
ReadOnlySpan<char> format = httpReq.Query["format"].ToString();
|
ReadOnlySpan<char> format = httpReq.Query["format"].ToString();
|
||||||
if (format == null)
|
if (format == ReadOnlySpan<char>.Empty)
|
||||||
{
|
{
|
||||||
const int FormatMaxLength = 4;
|
const int FormatMaxLength = 4;
|
||||||
ReadOnlySpan<char> pi = httpReq.Path.ToString();
|
ReadOnlySpan<char> pi = httpReq.Path.ToString();
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Sorting;
|
using MediaBrowser.Controller.Sorting;
|
||||||
@ -7,6 +9,12 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
{
|
{
|
||||||
public class CommunityRatingComparer : IBaseItemComparer
|
public class CommunityRatingComparer : IBaseItemComparer
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name.</value>
|
||||||
|
public string Name => ItemSortBy.CommunityRating;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compares the specified x.
|
/// Compares the specified x.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -16,18 +24,16 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
public int Compare(BaseItem x, BaseItem y)
|
public int Compare(BaseItem x, BaseItem y)
|
||||||
{
|
{
|
||||||
if (x == null)
|
if (x == null)
|
||||||
|
{
|
||||||
throw new ArgumentNullException(nameof(x));
|
throw new ArgumentNullException(nameof(x));
|
||||||
|
}
|
||||||
|
|
||||||
if (y == null)
|
if (y == null)
|
||||||
|
{
|
||||||
throw new ArgumentNullException(nameof(y));
|
throw new ArgumentNullException(nameof(y));
|
||||||
|
}
|
||||||
|
|
||||||
return (x.CommunityRating ?? 0).CompareTo(y.CommunityRating ?? 0);
|
return (x.CommunityRating ?? 0).CompareTo(y.CommunityRating ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The name.</value>
|
|
||||||
public string Name => ItemSortBy.CommunityRating;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
@ -27,6 +29,12 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
/// <value>The user data repository.</value>
|
/// <value>The user data repository.</value>
|
||||||
public IUserDataManager UserDataRepository { get; set; }
|
public IUserDataManager UserDataRepository { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name.</value>
|
||||||
|
public string Name => ItemSortBy.DateLastContentAdded;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compares the specified x.
|
/// Compares the specified x.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -45,9 +53,7 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
/// <returns>DateTime.</returns>
|
/// <returns>DateTime.</returns>
|
||||||
private static DateTime GetDate(BaseItem x)
|
private static DateTime GetDate(BaseItem x)
|
||||||
{
|
{
|
||||||
var folder = x as Folder;
|
if (x is Folder folder)
|
||||||
|
|
||||||
if (folder != null)
|
|
||||||
{
|
{
|
||||||
if (folder.DateLastMediaAdded.HasValue)
|
if (folder.DateLastMediaAdded.HasValue)
|
||||||
{
|
{
|
||||||
@ -57,11 +63,5 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
|
|
||||||
return DateTime.MinValue;
|
return DateTime.MinValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The name.</value>
|
|
||||||
public string Name => ItemSortBy.DateLastContentAdded;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
@ -14,6 +16,24 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
/// <value>The user.</value>
|
/// <value>The user.</value>
|
||||||
public User User { get; set; }
|
public User User { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name.</value>
|
||||||
|
public string Name => ItemSortBy.IsFavoriteOrLiked;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the user data repository.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The user data repository.</value>
|
||||||
|
public IUserDataManager UserDataRepository { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the user manager.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The user manager.</value>
|
||||||
|
public IUserManager UserManager { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compares the specified x.
|
/// Compares the specified x.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -34,23 +54,5 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
{
|
{
|
||||||
return x.IsFavoriteOrLiked(User) ? 0 : 1;
|
return x.IsFavoriteOrLiked(User) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The name.</value>
|
|
||||||
public string Name => ItemSortBy.IsFavoriteOrLiked;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the user data repository.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The user data repository.</value>
|
|
||||||
public IUserDataManager UserDataRepository { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the user manager.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The user manager.</value>
|
|
||||||
public IUserManager UserManager { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Sorting;
|
using MediaBrowser.Controller.Sorting;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
@ -6,6 +8,12 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
{
|
{
|
||||||
public class IsFolderComparer : IBaseItemComparer
|
public class IsFolderComparer : IBaseItemComparer
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name.</value>
|
||||||
|
public string Name => ItemSortBy.IsFolder;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compares the specified x.
|
/// Compares the specified x.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -26,11 +34,5 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
{
|
{
|
||||||
return x.IsFolder ? 0 : 1;
|
return x.IsFolder ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The name.</value>
|
|
||||||
public string Name => ItemSortBy.IsFolder;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
@ -14,6 +16,24 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
/// <value>The user.</value>
|
/// <value>The user.</value>
|
||||||
public User User { get; set; }
|
public User User { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name.</value>
|
||||||
|
public string Name => ItemSortBy.IsUnplayed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the user data repository.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The user data repository.</value>
|
||||||
|
public IUserDataManager UserDataRepository { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the user manager.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The user manager.</value>
|
||||||
|
public IUserManager UserManager { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compares the specified x.
|
/// Compares the specified x.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -34,23 +54,5 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
{
|
{
|
||||||
return x.IsPlayed(User) ? 0 : 1;
|
return x.IsPlayed(User) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The name.</value>
|
|
||||||
public string Name => ItemSortBy.IsUnplayed;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the user data repository.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The user data repository.</value>
|
|
||||||
public IUserDataManager UserDataRepository { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the user manager.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The user manager.</value>
|
|
||||||
public IUserManager UserManager { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
@ -14,6 +16,24 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
/// <value>The user.</value>
|
/// <value>The user.</value>
|
||||||
public User User { get; set; }
|
public User User { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name.</value>
|
||||||
|
public string Name => ItemSortBy.IsUnplayed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the user data repository.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The user data repository.</value>
|
||||||
|
public IUserDataManager UserDataRepository { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the user manager.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The user manager.</value>
|
||||||
|
public IUserManager UserManager { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compares the specified x.
|
/// Compares the specified x.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -34,23 +54,5 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
{
|
{
|
||||||
return x.IsUnplayed(User) ? 0 : 1;
|
return x.IsUnplayed(User) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The name.</value>
|
|
||||||
public string Name => ItemSortBy.IsUnplayed;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the user data repository.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The user data repository.</value>
|
|
||||||
public IUserDataManager UserDataRepository { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the user manager.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The user manager.</value>
|
|
||||||
public IUserManager UserManager { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Sorting;
|
using MediaBrowser.Controller.Sorting;
|
||||||
@ -15,6 +17,12 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
_localization = localization;
|
_localization = localization;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name.</value>
|
||||||
|
public string Name => ItemSortBy.OfficialRating;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compares the specified x.
|
/// Compares the specified x.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -38,11 +46,5 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
|
|
||||||
return levelX.CompareTo(levelY);
|
return levelX.CompareTo(levelY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The name.</value>
|
|
||||||
public string Name => ItemSortBy.OfficialRating;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Sorting;
|
using MediaBrowser.Controller.Sorting;
|
||||||
@ -7,6 +9,12 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
{
|
{
|
||||||
public class SeriesSortNameComparer : IBaseItemComparer
|
public class SeriesSortNameComparer : IBaseItemComparer
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name.</value>
|
||||||
|
public string Name => ItemSortBy.SeriesSortName;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compares the specified x.
|
/// Compares the specified x.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -18,12 +26,6 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase);
|
return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The name.</value>
|
|
||||||
public string Name => ItemSortBy.SeriesSortName;
|
|
||||||
|
|
||||||
private static string GetValue(BaseItem item)
|
private static string GetValue(BaseItem item)
|
||||||
{
|
{
|
||||||
var hasSeries = item as IHasSeries;
|
var hasSeries = item as IHasSeries;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
@ -8,6 +10,12 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
{
|
{
|
||||||
public class StartDateComparer : IBaseItemComparer
|
public class StartDateComparer : IBaseItemComparer
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name.</value>
|
||||||
|
public string Name => ItemSortBy.StartDate;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compares the specified x.
|
/// Compares the specified x.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -26,19 +34,12 @@ namespace Emby.Server.Implementations.Sorting
|
|||||||
/// <returns>DateTime.</returns>
|
/// <returns>DateTime.</returns>
|
||||||
private static DateTime GetDate(BaseItem x)
|
private static DateTime GetDate(BaseItem x)
|
||||||
{
|
{
|
||||||
var hasStartDate = x as LiveTvProgram;
|
if (x is LiveTvProgram hasStartDate)
|
||||||
|
|
||||||
if (hasStartDate != null)
|
|
||||||
{
|
{
|
||||||
return hasStartDate.StartDate;
|
return hasStartDate.StartDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DateTime.MinValue;
|
return DateTime.MinValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The name.</value>
|
|
||||||
public string Name => ItemSortBy.StartDate;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
|
@ -65,6 +65,11 @@ namespace Emby.Server.Implementations.SyncPlay
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool IsGroupEmpty() => _group.IsEmpty();
|
public bool IsGroupEmpty() => _group.IsEmpty();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SyncPlayController" /> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sessionManager">The session manager.</param>
|
||||||
|
/// <param name="syncPlayManager">The SyncPlay manager.</param>
|
||||||
public SyncPlayController(
|
public SyncPlayController(
|
||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
ISyncPlayManager syncPlayManager)
|
ISyncPlayManager syncPlayManager)
|
||||||
|
@ -57,6 +57,13 @@ namespace Emby.Server.Implementations.SyncPlay
|
|||||||
|
|
||||||
private bool _disposed = false;
|
private bool _disposed = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SyncPlayManager" /> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">The logger.</param>
|
||||||
|
/// <param name="userManager">The user manager.</param>
|
||||||
|
/// <param name="sessionManager">The session manager.</param>
|
||||||
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
public SyncPlayManager(
|
public SyncPlayManager(
|
||||||
ILogger<SyncPlayManager> logger,
|
ILogger<SyncPlayManager> logger,
|
||||||
IUserManager userManager,
|
IUserManager userManager,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@ -21,14 +23,12 @@ namespace Emby.Server.Implementations.TV
|
|||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly IUserDataManager _userDataManager;
|
private readonly IUserDataManager _userDataManager;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IServerConfigurationManager _config;
|
|
||||||
|
|
||||||
public TVSeriesManager(IUserManager userManager, IUserDataManager userDataManager, ILibraryManager libraryManager, IServerConfigurationManager config)
|
public TVSeriesManager(IUserManager userManager, IUserDataManager userDataManager, ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_userDataManager = userDataManager;
|
_userDataManager = userDataManager;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_config = config;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryResult<BaseItem> GetNextUp(NextUpQuery request, DtoOptions dtoOptions)
|
public QueryResult<BaseItem> GetNextUp(NextUpQuery request, DtoOptions dtoOptions)
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -95,25 +98,25 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public event EventHandler<InstallationEventArgs> PackageInstalling;
|
public event EventHandler<InstallationInfo> PackageInstalling;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public event EventHandler<InstallationEventArgs> PackageInstallationCompleted;
|
public event EventHandler<InstallationInfo> PackageInstallationCompleted;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public event EventHandler<InstallationFailedEventArgs> PackageInstallationFailed;
|
public event EventHandler<InstallationFailedEventArgs> PackageInstallationFailed;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public event EventHandler<InstallationEventArgs> PackageInstallationCancelled;
|
public event EventHandler<InstallationInfo> PackageInstallationCancelled;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public event EventHandler<GenericEventArgs<IPlugin>> PluginUninstalled;
|
public event EventHandler<IPlugin> PluginUninstalled;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public event EventHandler<GenericEventArgs<(IPlugin, VersionInfo)>> PluginUpdated;
|
public event EventHandler<InstallationInfo> PluginUpdated;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public event EventHandler<GenericEventArgs<VersionInfo>> PluginInstalled;
|
public event EventHandler<InstallationInfo> PluginInstalled;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IEnumerable<InstallationInfo> CompletedInstallations => _completedInstallationsInternal;
|
public IEnumerable<InstallationInfo> CompletedInstallations => _completedInstallationsInternal;
|
||||||
@ -181,24 +184,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IEnumerable<VersionInfo> GetCompatibleVersions(
|
public IEnumerable<InstallationInfo> GetCompatibleVersions(
|
||||||
IEnumerable<VersionInfo> availableVersions,
|
|
||||||
Version minVersion = null)
|
|
||||||
{
|
|
||||||
var appVer = _applicationHost.ApplicationVersion;
|
|
||||||
availableVersions = availableVersions
|
|
||||||
.Where(x => Version.Parse(x.targetAbi) <= appVer);
|
|
||||||
|
|
||||||
if (minVersion != null)
|
|
||||||
{
|
|
||||||
availableVersions = availableVersions.Where(x => x.version >= minVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
return availableVersions.OrderByDescending(x => x.version);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public IEnumerable<VersionInfo> GetCompatibleVersions(
|
|
||||||
IEnumerable<PackageInfo> availablePackages,
|
IEnumerable<PackageInfo> availablePackages,
|
||||||
string name = null,
|
string name = null,
|
||||||
Guid guid = default,
|
Guid guid = default,
|
||||||
@ -209,28 +195,46 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
// Package not found in repository
|
// Package not found in repository
|
||||||
if (package == null)
|
if (package == null)
|
||||||
{
|
{
|
||||||
return Enumerable.Empty<VersionInfo>();
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetCompatibleVersions(
|
var appVer = _applicationHost.ApplicationVersion;
|
||||||
package.versions,
|
var availableVersions = package.versions
|
||||||
minVersion);
|
.Where(x => Version.Parse(x.targetAbi) <= appVer);
|
||||||
|
|
||||||
|
if (minVersion != null)
|
||||||
|
{
|
||||||
|
availableVersions = availableVersions.Where(x => new Version(x.version) >= minVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var v in availableVersions.OrderByDescending(x => x.version))
|
||||||
|
{
|
||||||
|
yield return new InstallationInfo
|
||||||
|
{
|
||||||
|
Changelog = v.changelog,
|
||||||
|
Guid = new Guid(package.guid),
|
||||||
|
Name = package.name,
|
||||||
|
Version = new Version(v.version),
|
||||||
|
SourceUrl = v.sourceUrl,
|
||||||
|
Checksum = v.checksum
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<IEnumerable<VersionInfo>> GetAvailablePluginUpdates(CancellationToken cancellationToken = default)
|
public async Task<IEnumerable<InstallationInfo>> GetAvailablePluginUpdates(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var catalog = await GetAvailablePackages(cancellationToken).ConfigureAwait(false);
|
var catalog = await GetAvailablePackages(cancellationToken).ConfigureAwait(false);
|
||||||
return GetAvailablePluginUpdates(catalog);
|
return GetAvailablePluginUpdates(catalog);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<VersionInfo> GetAvailablePluginUpdates(IReadOnlyList<PackageInfo> pluginCatalog)
|
private IEnumerable<InstallationInfo> GetAvailablePluginUpdates(IReadOnlyList<PackageInfo> pluginCatalog)
|
||||||
{
|
{
|
||||||
foreach (var plugin in _applicationHost.Plugins)
|
foreach (var plugin in _applicationHost.Plugins)
|
||||||
{
|
{
|
||||||
var compatibleversions = GetCompatibleVersions(pluginCatalog, plugin.Name, plugin.Id, plugin.Version);
|
var compatibleversions = GetCompatibleVersions(pluginCatalog, plugin.Name, plugin.Id, plugin.Version);
|
||||||
var version = compatibleversions.FirstOrDefault(y => y.version > plugin.Version);
|
var version = compatibleversions.FirstOrDefault(y => y.Version > plugin.Version);
|
||||||
if (version != null && !CompletedInstallations.Any(x => string.Equals(x.Guid, version.guid, StringComparison.OrdinalIgnoreCase)))
|
if (version != null && CompletedInstallations.All(x => x.Guid != version.Guid))
|
||||||
{
|
{
|
||||||
yield return version;
|
yield return version;
|
||||||
}
|
}
|
||||||
@ -238,23 +242,16 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task InstallPackage(VersionInfo package, CancellationToken cancellationToken)
|
public async Task InstallPackage(InstallationInfo package, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (package == null)
|
if (package == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(package));
|
throw new ArgumentNullException(nameof(package));
|
||||||
}
|
}
|
||||||
|
|
||||||
var installationInfo = new InstallationInfo
|
|
||||||
{
|
|
||||||
Guid = package.guid,
|
|
||||||
Name = package.name,
|
|
||||||
Version = package.version.ToString()
|
|
||||||
};
|
|
||||||
|
|
||||||
var innerCancellationTokenSource = new CancellationTokenSource();
|
var innerCancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
var tuple = (installationInfo, innerCancellationTokenSource);
|
var tuple = (package, innerCancellationTokenSource);
|
||||||
|
|
||||||
// Add it to the in-progress list
|
// Add it to the in-progress list
|
||||||
lock (_currentInstallationsLock)
|
lock (_currentInstallationsLock)
|
||||||
@ -264,13 +261,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
|
|
||||||
var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, innerCancellationTokenSource.Token).Token;
|
var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, innerCancellationTokenSource.Token).Token;
|
||||||
|
|
||||||
var installationEventArgs = new InstallationEventArgs
|
PackageInstalling?.Invoke(this, package);
|
||||||
{
|
|
||||||
InstallationInfo = installationInfo,
|
|
||||||
VersionInfo = package
|
|
||||||
};
|
|
||||||
|
|
||||||
PackageInstalling?.Invoke(this, installationEventArgs);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -281,9 +272,9 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
_currentInstallations.Remove(tuple);
|
_currentInstallations.Remove(tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
_completedInstallationsInternal.Add(installationInfo);
|
_completedInstallationsInternal.Add(package);
|
||||||
|
|
||||||
PackageInstallationCompleted?.Invoke(this, installationEventArgs);
|
PackageInstallationCompleted?.Invoke(this, package);
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
@ -292,9 +283,9 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
_currentInstallations.Remove(tuple);
|
_currentInstallations.Remove(tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation("Package installation cancelled: {0} {1}", package.name, package.version);
|
_logger.LogInformation("Package installation cancelled: {0} {1}", package.Name, package.Version);
|
||||||
|
|
||||||
PackageInstallationCancelled?.Invoke(this, installationEventArgs);
|
PackageInstallationCancelled?.Invoke(this, package);
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@ -309,7 +300,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
|
|
||||||
PackageInstallationFailed?.Invoke(this, new InstallationFailedEventArgs
|
PackageInstallationFailed?.Invoke(this, new InstallationFailedEventArgs
|
||||||
{
|
{
|
||||||
InstallationInfo = installationInfo,
|
InstallationInfo = package,
|
||||||
Exception = ex
|
Exception = ex
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -328,11 +319,11 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
/// <param name="package">The package.</param>
|
/// <param name="package">The package.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns><see cref="Task" />.</returns>
|
/// <returns><see cref="Task" />.</returns>
|
||||||
private async Task InstallPackageInternal(VersionInfo package, CancellationToken cancellationToken)
|
private async Task InstallPackageInternal(InstallationInfo package, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// Set last update time if we were installed before
|
// Set last update time if we were installed before
|
||||||
IPlugin plugin = _applicationHost.Plugins.FirstOrDefault(p => string.Equals(p.Id.ToString(), package.guid, StringComparison.OrdinalIgnoreCase))
|
IPlugin plugin = _applicationHost.Plugins.FirstOrDefault(p => p.Id == package.Guid)
|
||||||
?? _applicationHost.Plugins.FirstOrDefault(p => p.Name.Equals(package.name, StringComparison.OrdinalIgnoreCase));
|
?? _applicationHost.Plugins.FirstOrDefault(p => p.Name.Equals(package.Name, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
// Do the install
|
// Do the install
|
||||||
await PerformPackageInstallation(package, cancellationToken).ConfigureAwait(false);
|
await PerformPackageInstallation(package, cancellationToken).ConfigureAwait(false);
|
||||||
@ -340,38 +331,38 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
// Do plugin-specific processing
|
// Do plugin-specific processing
|
||||||
if (plugin == null)
|
if (plugin == null)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("New plugin installed: {0} {1} {2}", package.name, package.version);
|
_logger.LogInformation("New plugin installed: {0} {1}", package.Name, package.Version);
|
||||||
|
|
||||||
PluginInstalled?.Invoke(this, new GenericEventArgs<VersionInfo>(package));
|
PluginInstalled?.Invoke(this, package);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Plugin updated: {0} {1} {2}", package.name, package.version);
|
_logger.LogInformation("Plugin updated: {0} {1}", package.Name, package.Version);
|
||||||
|
|
||||||
PluginUpdated?.Invoke(this, new GenericEventArgs<(IPlugin, VersionInfo)>((plugin, package)));
|
PluginUpdated?.Invoke(this, package);
|
||||||
}
|
}
|
||||||
|
|
||||||
_applicationHost.NotifyPendingRestart();
|
_applicationHost.NotifyPendingRestart();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task PerformPackageInstallation(VersionInfo package, CancellationToken cancellationToken)
|
private async Task PerformPackageInstallation(InstallationInfo package, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var extension = Path.GetExtension(package.filename);
|
var extension = Path.GetExtension(package.SourceUrl);
|
||||||
if (!string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase))
|
if (!string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
_logger.LogError("Only zip packages are supported. {Filename} is not a zip archive.", package.filename);
|
_logger.LogError("Only zip packages are supported. {SourceUrl} is not a zip archive.", package.SourceUrl);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always override the passed-in target (which is a file) and figure it out again
|
// Always override the passed-in target (which is a file) and figure it out again
|
||||||
string targetDir = Path.Combine(_appPaths.PluginsPath, package.name);
|
string targetDir = Path.Combine(_appPaths.PluginsPath, package.Name);
|
||||||
|
|
||||||
// CA5351: Do Not Use Broken Cryptographic Algorithms
|
// CA5351: Do Not Use Broken Cryptographic Algorithms
|
||||||
#pragma warning disable CA5351
|
#pragma warning disable CA5351
|
||||||
using (var res = await _httpClient.SendAsync(
|
using (var res = await _httpClient.SendAsync(
|
||||||
new HttpRequestOptions
|
new HttpRequestOptions
|
||||||
{
|
{
|
||||||
Url = package.sourceUrl,
|
Url = package.SourceUrl,
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
// We need it to be buffered for setting the position
|
// We need it to be buffered for setting the position
|
||||||
BufferContent = true
|
BufferContent = true
|
||||||
@ -383,12 +374,12 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var hash = Hex.Encode(md5.ComputeHash(stream));
|
var hash = Hex.Encode(md5.ComputeHash(stream));
|
||||||
if (!string.Equals(package.checksum, hash, StringComparison.OrdinalIgnoreCase))
|
if (!string.Equals(package.Checksum, hash, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
_logger.LogError(
|
_logger.LogError(
|
||||||
"The checksums didn't match while installing {Package}, expected: {Expected}, got: {Received}",
|
"The checksums didn't match while installing {Package}, expected: {Expected}, got: {Received}",
|
||||||
package.name,
|
package.Name,
|
||||||
package.checksum,
|
package.Checksum,
|
||||||
hash);
|
hash);
|
||||||
throw new InvalidDataException("The checksum of the received data doesn't match.");
|
throw new InvalidDataException("The checksum of the received data doesn't match.");
|
||||||
}
|
}
|
||||||
@ -454,7 +445,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
_config.SaveConfiguration();
|
_config.SaveConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginUninstalled?.Invoke(this, new GenericEventArgs<IPlugin> { Argument = plugin });
|
PluginUninstalled?.Invoke(this, plugin);
|
||||||
|
|
||||||
_applicationHost.NotifyPendingRestart();
|
_applicationHost.NotifyPendingRestart();
|
||||||
}
|
}
|
||||||
@ -464,7 +455,7 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
{
|
{
|
||||||
lock (_currentInstallationsLock)
|
lock (_currentInstallationsLock)
|
||||||
{
|
{
|
||||||
var install = _currentInstallations.Find(x => x.info.Guid == id.ToString());
|
var install = _currentInstallations.Find(x => x.info.Guid == id);
|
||||||
if (install == default((InstallationInfo, CancellationTokenSource)))
|
if (install == default((InstallationInfo, CancellationTokenSource)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -484,9 +475,9 @@ namespace Emby.Server.Implementations.Updates
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Releases unmanaged and - optionally - managed resources.
|
/// Releases unmanaged and optionally managed resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources or <c>false</c> to release only unmanaged resources.</param>
|
||||||
protected virtual void Dispose(bool dispose)
|
protected virtual void Dispose(bool dispose)
|
||||||
{
|
{
|
||||||
if (dispose)
|
if (dispose)
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#nullable disable
|
||||||
|
|
||||||
namespace Jellyfin.Api.Models.StartupDtos
|
namespace Jellyfin.Api.Models.StartupDtos
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#nullable disable
|
||||||
|
|
||||||
namespace Jellyfin.Api.Models.StartupDtos
|
namespace Jellyfin.Api.Models.StartupDtos
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release' ">true</TreatWarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="BlurHashSharp" Version="1.0.1" />
|
||||||
|
<PackageReference Include="BlurHashSharp.SkiaSharp" Version="1.0.0" />
|
||||||
<PackageReference Include="SkiaSharp" Version="1.68.1" />
|
<PackageReference Include="SkiaSharp" Version="1.68.1" />
|
||||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="1.68.1" />
|
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="1.68.1" />
|
||||||
<PackageReference Include="Jellyfin.SkiaSharp.NativeAssets.LinuxArm" Version="1.68.1" />
|
<PackageReference Include="Jellyfin.SkiaSharp.NativeAssets.LinuxArm" Version="1.68.1" />
|
||||||
|
@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using BlurHashSharp.SkiaSharp;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Controller.Drawing;
|
using MediaBrowser.Controller.Drawing;
|
||||||
using MediaBrowser.Controller.Extensions;
|
using MediaBrowser.Controller.Extensions;
|
||||||
@ -52,9 +53,7 @@ namespace Jellyfin.Drawing.Skia
|
|||||||
"jpeg",
|
"jpeg",
|
||||||
"jpg",
|
"jpg",
|
||||||
"png",
|
"png",
|
||||||
|
|
||||||
"dng",
|
"dng",
|
||||||
|
|
||||||
"webp",
|
"webp",
|
||||||
"gif",
|
"gif",
|
||||||
"bmp",
|
"bmp",
|
||||||
@ -63,10 +62,8 @@ namespace Jellyfin.Drawing.Skia
|
|||||||
"ktx",
|
"ktx",
|
||||||
"pkm",
|
"pkm",
|
||||||
"wbmp",
|
"wbmp",
|
||||||
|
// TODO: check if these are supported on multiple platforms
|
||||||
// TODO
|
// https://github.com/google/skia/blob/master/infra/bots/recipes/test.py#L454
|
||||||
// Are all of these supported? https://github.com/google/skia/blob/master/infra/bots/recipes/test.py#L454
|
|
||||||
|
|
||||||
// working on windows at least
|
// working on windows at least
|
||||||
"cr2",
|
"cr2",
|
||||||
"nef",
|
"nef",
|
||||||
@ -229,6 +226,20 @@ namespace Jellyfin.Drawing.Skia
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <exception cref="ArgumentNullException">The path is null.</exception>
|
||||||
|
/// <exception cref="FileNotFoundException">The path is not valid.</exception>
|
||||||
|
/// <exception cref="SkiaCodecException">The file at the specified path could not be used to generate a codec.</exception>
|
||||||
|
public string GetImageBlurHash(int xComp, int yComp, string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
return BlurHashEncoder.Encode(xComp, yComp, path);
|
||||||
|
}
|
||||||
|
|
||||||
private static bool HasDiacritics(string text)
|
private static bool HasDiacritics(string text)
|
||||||
=> !string.Equals(text, text.RemoveDiacritics(), StringComparison.Ordinal);
|
=> !string.Equals(text, text.RemoveDiacritics(), StringComparison.Ordinal);
|
||||||
|
|
||||||
@ -257,7 +268,7 @@ namespace Jellyfin.Drawing.Skia
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
var tempPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + Path.GetExtension(path) ?? string.Empty);
|
var tempPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + Path.GetExtension(path));
|
||||||
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(tempPath));
|
Directory.CreateDirectory(Path.GetDirectoryName(tempPath));
|
||||||
File.Copy(path, tempPath, true);
|
File.Copy(path, tempPath, true);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user