commit
52aea85e7f
|
@ -1363,7 +1363,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||
};
|
||||
}
|
||||
|
||||
Logger.LogError("Error parsing item Id: {id}. Returning user root folder.", id);
|
||||
Logger.LogError("Error parsing item Id: {Id}. Returning user root folder.", id);
|
||||
|
||||
return new ServerItem(_libraryManager.GetUserRootFolder());
|
||||
}
|
||||
|
|
|
@ -948,7 +948,7 @@ namespace Emby.Dlna.Didl
|
|||
}
|
||||
catch (XmlException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error adding xml value: {value}", name);
|
||||
_logger.LogError(ex, "Error adding xml value: {Value}", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -960,7 +960,7 @@ namespace Emby.Dlna.Didl
|
|||
}
|
||||
catch (XmlException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error adding xml value: {value}", value);
|
||||
_logger.LogError(ex, "Error adding xml value: {Value}", value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -308,7 +308,7 @@ namespace Emby.Server.Implementations.AppBase
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error loading configuration file: {path}", path);
|
||||
Logger.LogError(ex, "Error loading configuration file: {Path}", path);
|
||||
|
||||
return Activator.CreateInstance(configurationType);
|
||||
}
|
||||
|
|
|
@ -279,6 +279,10 @@ namespace Emby.Server.Implementations
|
|||
Password = ServerConfigurationManager.Configuration.CertificatePassword
|
||||
};
|
||||
Certificate = GetCertificate(CertificateInfo);
|
||||
|
||||
ApplicationVersion = typeof(ApplicationHost).Assembly.GetName().Version;
|
||||
ApplicationVersionString = ApplicationVersion.ToString(3);
|
||||
ApplicationUserAgent = Name.Replace(' ', '-') + "/" + ApplicationVersionString;
|
||||
}
|
||||
|
||||
public string ExpandVirtualPath(string path)
|
||||
|
@ -308,16 +312,16 @@ namespace Emby.Server.Implementations
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Version ApplicationVersion { get; } = typeof(ApplicationHost).Assembly.GetName().Version;
|
||||
public Version ApplicationVersion { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string ApplicationVersionString { get; } = typeof(ApplicationHost).Assembly.GetName().Version.ToString(3);
|
||||
public string ApplicationVersionString { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current application user agent.
|
||||
/// </summary>
|
||||
/// <value>The application user agent.</value>
|
||||
public string ApplicationUserAgent => Name.Replace(' ', '-') + "/" + ApplicationVersionString;
|
||||
public string ApplicationUserAgent { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the email address for use within a comment section of a user agent field.
|
||||
|
@ -1401,7 +1405,7 @@ namespace Emby.Server.Implementations
|
|||
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
Logger.LogDebug("Found API endpoints in plugin {name}", assembly.FullName);
|
||||
Logger.LogDebug("Found API endpoints in plugin {Name}", assembly.FullName);
|
||||
yield return assembly;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -890,7 +890,7 @@ namespace Emby.Server.Implementations.Channels
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error writing to channel cache file: {path}", path);
|
||||
_logger.LogError(ex, "Error writing to channel cache file: {Path}", path);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -197,7 +197,7 @@ namespace Emby.Server.Implementations.Dto
|
|||
catch (Exception ex)
|
||||
{
|
||||
// Have to use a catch-all unfortunately because some .net image methods throw plain Exceptions
|
||||
_logger.LogError(ex, "Error generating PrimaryImageAspectRatio for {itemName}", item.Name);
|
||||
_logger.LogError(ex, "Error generating PrimaryImageAspectRatio for {ItemName}", item.Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -149,7 +149,7 @@ namespace Emby.Server.Implementations.IO
|
|||
continue;
|
||||
}
|
||||
|
||||
_logger.LogInformation("{name} ({path}) will be refreshed.", item.Name, item.Path);
|
||||
_logger.LogInformation("{Name} ({Path}) will be refreshed.", item.Name, item.Path);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -160,11 +160,11 @@ namespace Emby.Server.Implementations.IO
|
|||
// For now swallow and log.
|
||||
// Research item: If an IOException occurs, the item may be in a disconnected state (media unavailable)
|
||||
// Should we remove it from it's parent?
|
||||
_logger.LogError(ex, "Error refreshing {name}", item.Name);
|
||||
_logger.LogError(ex, "Error refreshing {Name}", item.Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error refreshing {name}", item.Name);
|
||||
_logger.LogError(ex, "Error refreshing {Name}", item.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -214,6 +214,7 @@ namespace Emby.Server.Implementations.IO
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
_disposed = true;
|
||||
|
|
|
@ -88,7 +88,7 @@ namespace Emby.Server.Implementations.IO
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error in ReportFileSystemChanged for {path}", path);
|
||||
_logger.LogError(ex, "Error in ReportFileSystemChanged for {Path}", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -398,30 +398,6 @@ namespace Emby.Server.Implementations.IO
|
|||
}
|
||||
}
|
||||
|
||||
public virtual void SetReadOnly(string path, bool isReadOnly)
|
||||
{
|
||||
if (OperatingSystem.Id != OperatingSystemId.Windows)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var info = GetExtendedFileSystemInfo(path);
|
||||
|
||||
if (info.Exists && info.IsReadOnly != isReadOnly)
|
||||
{
|
||||
if (isReadOnly)
|
||||
{
|
||||
File.SetAttributes(path, File.GetAttributes(path) | FileAttributes.ReadOnly);
|
||||
}
|
||||
else
|
||||
{
|
||||
var attributes = File.GetAttributes(path);
|
||||
attributes = RemoveAttribute(attributes, FileAttributes.ReadOnly);
|
||||
File.SetAttributes(path, attributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void SetAttributes(string path, bool isHidden, bool isReadOnly)
|
||||
{
|
||||
if (OperatingSystem.Id != OperatingSystemId.Windows)
|
||||
|
@ -707,14 +683,6 @@ namespace Emby.Server.Implementations.IO
|
|||
return Directory.EnumerateFileSystemEntries(path, "*", searchOption);
|
||||
}
|
||||
|
||||
public virtual void SetExecutable(string path)
|
||||
{
|
||||
if (OperatingSystem.Id == OperatingSystemId.Darwin)
|
||||
{
|
||||
RunProcess("chmod", "+x \"" + path + "\"", Path.GetDirectoryName(path));
|
||||
}
|
||||
}
|
||||
|
||||
private static void RunProcess(string path, string args, string workingDirectory)
|
||||
{
|
||||
using (var process = Process.Start(new ProcessStartInfo
|
||||
|
|
|
@ -11,8 +11,6 @@ namespace Emby.Server.Implementations.IO
|
|||
{
|
||||
public class StreamHelper : IStreamHelper
|
||||
{
|
||||
private const int StreamCopyToBufferSize = 81920;
|
||||
|
||||
public async Task CopyToAsync(Stream source, Stream destination, int bufferSize, Action onStarted, CancellationToken cancellationToken)
|
||||
{
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
|
||||
|
@ -83,37 +81,9 @@ namespace Emby.Server.Implementations.IO
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<int> CopyToAsync(Stream source, Stream destination, CancellationToken cancellationToken)
|
||||
{
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(StreamCopyToBufferSize);
|
||||
try
|
||||
{
|
||||
int totalBytesRead = 0;
|
||||
|
||||
int bytesRead;
|
||||
while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
|
||||
{
|
||||
var bytesToWrite = bytesRead;
|
||||
|
||||
if (bytesToWrite > 0)
|
||||
{
|
||||
await destination.WriteAsync(buffer, 0, Convert.ToInt32(bytesToWrite), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
totalBytesRead += bytesRead;
|
||||
}
|
||||
}
|
||||
|
||||
return totalBytesRead;
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task CopyToAsync(Stream source, Stream destination, long copyLength, CancellationToken cancellationToken)
|
||||
{
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(StreamCopyToBufferSize);
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(IODefaults.CopyToBufferSize);
|
||||
try
|
||||
{
|
||||
int bytesRead;
|
||||
|
|
|
@ -52,10 +52,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
_logger.LogInformation("Copying recording stream to file {0}", targetFile);
|
||||
|
||||
// The media source is infinite so we need to handle stopping ourselves
|
||||
var durationToken = new CancellationTokenSource(duration);
|
||||
cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
|
||||
using var durationToken = new CancellationTokenSource(duration);
|
||||
using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token);
|
||||
|
||||
await directStreamProvider.CopyToAsync(output, cancellationToken).ConfigureAwait(false);
|
||||
await directStreamProvider.CopyToAsync(output, cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Recording completed to file {0}", targetFile);
|
||||
|
@ -72,7 +72,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
UserAgent = "Emby/3.0",
|
||||
|
||||
// Shouldn't matter but may cause issues
|
||||
DecompressionMethod = CompressionMethods.None
|
||||
DecompressionMethod = CompressionMethods.None,
|
||||
CancellationToken = cancellationToken
|
||||
};
|
||||
|
||||
using (var response = await _httpClient.SendAsync(httpRequestOptions, HttpMethod.Get).ConfigureAwait(false))
|
||||
|
@ -88,10 +89,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
_logger.LogInformation("Copying recording stream to file {0}", targetFile);
|
||||
|
||||
// The media source if infinite so we need to handle stopping ourselves
|
||||
var durationToken = new CancellationTokenSource(duration);
|
||||
cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
|
||||
using var durationToken = new CancellationTokenSource(duration);
|
||||
using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token);
|
||||
|
||||
await _streamHelper.CopyUntilCancelled(response.Content, output, 81920, cancellationToken).ConfigureAwait(false);
|
||||
await _streamHelper.CopyUntilCancelled(
|
||||
response.Content,
|
||||
output,
|
||||
IODefaults.CopyToBufferSize,
|
||||
cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -604,11 +604,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task DeleteRecordingAsync(string recordingId, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task CreateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
@ -808,11 +803,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<ActiveRecordingInfo> GetAllActiveRecordings()
|
||||
{
|
||||
return _activeRecordings.Values.Where(i => i.Timer.Status == RecordingStatus.InProgress && !i.CancellationTokenSource.IsCancellationRequested);
|
||||
}
|
||||
|
||||
public ActiveRecordingInfo GetActiveRecordingInfo(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
|
@ -1015,16 +1005,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
throw new Exception("Tuner not found.");
|
||||
}
|
||||
|
||||
private MediaSourceInfo CloneMediaSource(MediaSourceInfo mediaSource, bool enableStreamSharing)
|
||||
{
|
||||
var json = _jsonSerializer.SerializeToString(mediaSource);
|
||||
mediaSource = _jsonSerializer.DeserializeFromString<MediaSourceInfo>(json);
|
||||
|
||||
mediaSource.Id = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture) + "_" + mediaSource.Id;
|
||||
|
||||
return mediaSource;
|
||||
}
|
||||
|
||||
public async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(channelId))
|
||||
|
@ -1654,7 +1634,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
{
|
||||
if (mediaSource.RequiresLooping || !(mediaSource.Container ?? string.Empty).EndsWith("ts", StringComparison.OrdinalIgnoreCase) || (mediaSource.Protocol != MediaProtocol.File && mediaSource.Protocol != MediaProtocol.Http))
|
||||
{
|
||||
return new EncodedRecorder(_logger, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, _config);
|
||||
return new EncodedRecorder(_logger, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer);
|
||||
}
|
||||
|
||||
return new DirectRecorder(_logger, _httpClient, _streamHelper);
|
||||
|
|
|
@ -8,12 +8,9 @@ using System.IO;
|
|||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.MediaEncoding;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
@ -26,26 +23,24 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
private readonly ILogger _logger;
|
||||
private readonly IMediaEncoder _mediaEncoder;
|
||||
private readonly IServerApplicationPaths _appPaths;
|
||||
private readonly IJsonSerializer _json;
|
||||
private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>();
|
||||
|
||||
private bool _hasExited;
|
||||
private Stream _logFileStream;
|
||||
private string _targetPath;
|
||||
private Process _process;
|
||||
private readonly IJsonSerializer _json;
|
||||
private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>();
|
||||
private readonly IServerConfigurationManager _config;
|
||||
|
||||
public EncodedRecorder(
|
||||
ILogger logger,
|
||||
IMediaEncoder mediaEncoder,
|
||||
IServerApplicationPaths appPaths,
|
||||
IJsonSerializer json,
|
||||
IServerConfigurationManager config)
|
||||
IJsonSerializer json)
|
||||
{
|
||||
_logger = logger;
|
||||
_mediaEncoder = mediaEncoder;
|
||||
_appPaths = appPaths;
|
||||
_json = json;
|
||||
_config = config;
|
||||
}
|
||||
|
||||
private static bool CopySubtitles => false;
|
||||
|
@ -58,19 +53,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
public async Task Record(IDirectStreamProvider directStreamProvider, MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
|
||||
{
|
||||
// The media source is infinite so we need to handle stopping ourselves
|
||||
var durationToken = new CancellationTokenSource(duration);
|
||||
cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
|
||||
using var durationToken = new CancellationTokenSource(duration);
|
||||
using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token);
|
||||
|
||||
await RecordFromFile(mediaSource, mediaSource.Path, targetFile, duration, onStarted, cancellationToken).ConfigureAwait(false);
|
||||
await RecordFromFile(mediaSource, mediaSource.Path, targetFile, duration, onStarted, cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
|
||||
_logger.LogInformation("Recording completed to file {0}", targetFile);
|
||||
}
|
||||
|
||||
private EncodingOptions GetEncodingOptions()
|
||||
{
|
||||
return _config.GetConfiguration<EncodingOptions>("encoding");
|
||||
}
|
||||
|
||||
private Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
|
||||
{
|
||||
_targetPath = targetFile;
|
||||
|
@ -108,7 +98,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
StartInfo = processStartInfo,
|
||||
EnableRaisingEvents = true
|
||||
};
|
||||
_process.Exited += (sender, args) => OnFfMpegProcessExited(_process, inputFile);
|
||||
_process.Exited += (sender, args) => OnFfMpegProcessExited(_process);
|
||||
|
||||
_process.Start();
|
||||
|
||||
|
@ -221,20 +211,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
}
|
||||
|
||||
protected string GetOutputSizeParam()
|
||||
{
|
||||
var filters = new List<string>();
|
||||
|
||||
filters.Add("yadif=0:-1:0");
|
||||
|
||||
var output = string.Empty;
|
||||
|
||||
if (filters.Count > 0)
|
||||
{
|
||||
output += string.Format(CultureInfo.InvariantCulture, " -vf \"{0}\"", string.Join(",", filters.ToArray()));
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
=> "-vf \"yadif=0:-1:0\"";
|
||||
|
||||
private void Stop()
|
||||
{
|
||||
|
@ -291,7 +268,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
/// <summary>
|
||||
/// Processes the exited.
|
||||
/// </summary>
|
||||
private void OnFfMpegProcessExited(Process process, string inputFile)
|
||||
private void OnFfMpegProcessExited(Process process)
|
||||
{
|
||||
using (process)
|
||||
{
|
||||
|
|
|
@ -24,14 +24,14 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
{
|
||||
public class SchedulesDirect : IListingsProvider
|
||||
{
|
||||
private const string ApiUrl = "https://json.schedulesdirect.org/20141201";
|
||||
|
||||
private readonly ILogger<SchedulesDirect> _logger;
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly SemaphoreSlim _tokenSemaphore = new SemaphoreSlim(1, 1);
|
||||
private readonly IApplicationHost _appHost;
|
||||
|
||||
private const string ApiUrl = "https://json.schedulesdirect.org/20141201";
|
||||
|
||||
public SchedulesDirect(
|
||||
ILogger<SchedulesDirect> logger,
|
||||
IJsonSerializer jsonSerializer,
|
||||
|
@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
|
||||
while (start <= end)
|
||||
{
|
||||
dates.Add(start.ToString("yyyy-MM-dd"));
|
||||
dates.Add(start.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
|
||||
start = start.AddDays(1);
|
||||
}
|
||||
|
||||
|
@ -367,13 +367,14 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
|
||||
if (!string.IsNullOrWhiteSpace(details.originalAirDate))
|
||||
{
|
||||
info.OriginalAirDate = DateTime.Parse(details.originalAirDate);
|
||||
info.OriginalAirDate = DateTime.Parse(details.originalAirDate, CultureInfo.InvariantCulture);
|
||||
info.ProductionYear = info.OriginalAirDate.Value.Year;
|
||||
}
|
||||
|
||||
if (details.movie != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(details.movie.year) && int.TryParse(details.movie.year, out int year))
|
||||
if (!string.IsNullOrEmpty(details.movie.year)
|
||||
&& int.TryParse(details.movie.year, out int year))
|
||||
{
|
||||
info.ProductionYear = year;
|
||||
}
|
||||
|
@ -587,7 +588,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
return null;
|
||||
}
|
||||
|
||||
NameValuePair savedToken = null;
|
||||
NameValuePair savedToken;
|
||||
if (!_tokens.TryGetValue(username, out savedToken))
|
||||
{
|
||||
savedToken = new NameValuePair();
|
||||
|
@ -633,7 +634,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
}
|
||||
}
|
||||
|
||||
private async Task<HttpResponseInfo> Post(HttpRequestOptions options,
|
||||
private async Task<HttpResponseInfo> Post(
|
||||
HttpRequestOptions options,
|
||||
bool enableRetry,
|
||||
ListingsProviderInfo providerInfo)
|
||||
{
|
||||
|
@ -663,7 +665,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
return await Post(options, false, providerInfo).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<HttpResponseInfo> Get(HttpRequestOptions options,
|
||||
private async Task<HttpResponseInfo> Get(
|
||||
HttpRequestOptions options,
|
||||
bool enableRetry,
|
||||
ListingsProviderInfo providerInfo)
|
||||
{
|
||||
|
@ -693,7 +696,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
return await Get(options, false, providerInfo).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<string> GetTokenInternal(string username, string password,
|
||||
private async Task<string> GetTokenInternal(
|
||||
string username,
|
||||
string password,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var httpOptions = new HttpRequestOptions()
|
||||
|
|
|
@ -5,10 +5,10 @@ using System.Linq;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
|
||||
namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||
{
|
||||
|
@ -21,10 +21,8 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
/// Gets or sets the application paths.
|
||||
/// </summary>
|
||||
/// <value>The application paths.</value>
|
||||
private IApplicationPaths ApplicationPaths { get; set; }
|
||||
|
||||
private readonly IApplicationPaths _applicationPaths;
|
||||
private readonly ILogger<DeleteCacheFileTask> _logger;
|
||||
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly ILocalizationManager _localization;
|
||||
|
||||
|
@ -37,20 +35,41 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
IFileSystem fileSystem,
|
||||
ILocalizationManager localization)
|
||||
{
|
||||
ApplicationPaths = appPaths;
|
||||
_applicationPaths = appPaths;
|
||||
_logger = logger;
|
||||
_fileSystem = fileSystem;
|
||||
_localization = localization;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => _localization.GetLocalizedString("TaskCleanCache");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => _localization.GetLocalizedString("TaskCleanCacheDescription");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => "DeleteCacheFiles";
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsHidden => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEnabled => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsLogged => true;
|
||||
|
||||
/// <summary>
|
||||
/// Creates the triggers that define when the task will run.
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable{BaseTaskTrigger}.</returns>
|
||||
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
|
||||
{
|
||||
return new[] {
|
||||
|
||||
return new[]
|
||||
{
|
||||
// Every so often
|
||||
new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks}
|
||||
};
|
||||
|
@ -68,7 +87,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
|
||||
try
|
||||
{
|
||||
DeleteCacheFilesFromDirectory(cancellationToken, ApplicationPaths.CachePath, minDateModified, progress);
|
||||
DeleteCacheFilesFromDirectory(cancellationToken, _applicationPaths.CachePath, minDateModified, progress);
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
|
@ -81,7 +100,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
|
||||
try
|
||||
{
|
||||
DeleteCacheFilesFromDirectory(cancellationToken, ApplicationPaths.TempDirectory, minDateModified, progress);
|
||||
DeleteCacheFilesFromDirectory(cancellationToken, _applicationPaths.TempDirectory, minDateModified, progress);
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
|
@ -91,7 +110,6 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the cache files from directory with a last write time less than a given date.
|
||||
/// </summary>
|
||||
|
@ -164,26 +182,5 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
_logger.LogError(ex, "Error deleting file {path}", path);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => _localization.GetLocalizedString("TaskCleanCache");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => _localization.GetLocalizedString("TaskCleanCacheDescription");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => "DeleteCacheFiles";
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsHidden => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEnabled => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsLogged => true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,27 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
_localization = localization;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => _localization.GetLocalizedString("TaskUpdatePlugins");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => _localization.GetLocalizedString("TaskUpdatePluginsDescription");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Category => _localization.GetLocalizedString("TasksApplicationCategory");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => "PluginUpdates";
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsHidden => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEnabled => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsLogged => true;
|
||||
|
||||
/// <summary>
|
||||
/// Creates the triggers that define when the task will run.
|
||||
/// </summary>
|
||||
|
@ -98,26 +119,5 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
|
||||
progress.Report(100);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => _localization.GetLocalizedString("TaskUpdatePlugins");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => _localization.GetLocalizedString("TaskUpdatePluginsDescription");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Category => _localization.GetLocalizedString("TasksApplicationCategory");
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => "PluginUpdates";
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsHidden => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEnabled => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsLogged => true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,12 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
public class DailyTrigger : ITaskTrigger
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the time of day to trigger the task to run.
|
||||
/// Occurs when [triggered].
|
||||
/// </summary>
|
||||
public event EventHandler<EventArgs> Triggered;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time of day to trigger the task to run.
|
||||
/// </summary>
|
||||
/// <value>The time of day.</value>
|
||||
public TimeSpan TimeOfDay { get; set; }
|
||||
|
@ -69,11 +74,6 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [triggered].
|
||||
/// </summary>
|
||||
public event EventHandler<EventArgs> Triggered;
|
||||
|
||||
/// <summary>
|
||||
/// Called when [triggered].
|
||||
/// </summary>
|
||||
|
|
|
@ -11,6 +11,13 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
/// </summary>
|
||||
public class IntervalTrigger : ITaskTrigger
|
||||
{
|
||||
private DateTime _lastStartDate;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [triggered].
|
||||
/// </summary>
|
||||
public event EventHandler<EventArgs> Triggered;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the interval.
|
||||
/// </summary>
|
||||
|
@ -28,8 +35,6 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
/// <value>The timer.</value>
|
||||
private Timer Timer { get; set; }
|
||||
|
||||
private DateTime _lastStartDate;
|
||||
|
||||
/// <summary>
|
||||
/// Stars waiting for the trigger action.
|
||||
/// </summary>
|
||||
|
@ -88,11 +93,6 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [triggered].
|
||||
/// </summary>
|
||||
public event EventHandler<EventArgs> Triggered;
|
||||
|
||||
/// <summary>
|
||||
/// Called when [triggered].
|
||||
/// </summary>
|
||||
|
|
|
@ -12,6 +12,11 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
/// </summary>
|
||||
public class StartupTrigger : ITaskTrigger
|
||||
{
|
||||
/// <summary>
|
||||
/// Occurs when [triggered].
|
||||
/// </summary>
|
||||
public event EventHandler<EventArgs> Triggered;
|
||||
|
||||
public int DelayMs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -48,20 +53,12 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [triggered].
|
||||
/// </summary>
|
||||
public event EventHandler<EventArgs> Triggered;
|
||||
|
||||
/// <summary>
|
||||
/// Called when [triggered].
|
||||
/// </summary>
|
||||
private void OnTriggered()
|
||||
{
|
||||
if (Triggered != null)
|
||||
{
|
||||
Triggered(this, EventArgs.Empty);
|
||||
}
|
||||
Triggered?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,12 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
public class WeeklyTrigger : ITaskTrigger
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the time of day to trigger the task to run.
|
||||
/// Occurs when [triggered].
|
||||
/// </summary>
|
||||
public event EventHandler<EventArgs> Triggered;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time of day to trigger the task to run.
|
||||
/// </summary>
|
||||
/// <value>The time of day.</value>
|
||||
public TimeSpan TimeOfDay { get; set; }
|
||||
|
@ -95,20 +100,12 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [triggered].
|
||||
/// </summary>
|
||||
public event EventHandler<EventArgs> Triggered;
|
||||
|
||||
/// <summary>
|
||||
/// Called when [triggered].
|
||||
/// </summary>
|
||||
private void OnTriggered()
|
||||
{
|
||||
if (Triggered != null)
|
||||
{
|
||||
Triggered(this, EventArgs.Empty);
|
||||
}
|
||||
Triggered?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
/// </summary>
|
||||
/// <value><c>null</c> if [has image] contains no value, <c>true</c> if [has image]; otherwise, <c>false</c>.</value>
|
||||
public bool? HasImage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is favorite.
|
||||
/// </summary>
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace MediaBrowser.Model.IO
|
|||
public DateTime CreationTimeUtc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is directory.
|
||||
/// Gets or sets a value indicating whether this instance is directory.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is directory; otherwise, <c>false</c>.</value>
|
||||
public bool IsDirectory { get; set; }
|
||||
|
|
|
@ -201,9 +201,9 @@ namespace MediaBrowser.Model.IO
|
|||
IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false);
|
||||
|
||||
void SetHidden(string path, bool isHidden);
|
||||
void SetReadOnly(string path, bool readOnly);
|
||||
|
||||
void SetAttributes(string path, bool isHidden, bool readOnly);
|
||||
|
||||
List<FileSystemMetadata> GetDrives();
|
||||
void SetExecutable(string path);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ namespace MediaBrowser.Model.IO
|
|||
/// </summary>
|
||||
/// <param name="shortcutPath">The shortcut path.</param>
|
||||
/// <param name="targetPath">The target path.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
void Create(string shortcutPath, string targetPath);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,6 @@ namespace MediaBrowser.Model.IO
|
|||
|
||||
Task CopyToAsync(Stream source, Stream destination, int bufferSize, int emptyReadLimit, CancellationToken cancellationToken);
|
||||
|
||||
Task<int> CopyToAsync(Stream source, Stream destination, CancellationToken cancellationToken);
|
||||
|
||||
Task CopyToAsync(Stream source, Stream destination, long copyLength, CancellationToken cancellationToken);
|
||||
|
||||
Task CopyUntilCancelled(Stream source, Stream target, int bufferSize, CancellationToken cancellationToken);
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace MediaBrowser.Model.IO
|
|||
void ExtractAll(Stream source, string targetPath, bool overwriteExistingFiles);
|
||||
|
||||
void ExtractAllFromGz(Stream source, string targetPath, bool overwriteExistingFiles);
|
||||
|
||||
void ExtractFirstFileFromGz(Stream source, string targetPath, string defaultFileName);
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -31,9 +31,13 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
|
|||
_httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
public static string ProviderName => TmdbUtils.ProviderName;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => ProviderName;
|
||||
|
||||
public static string ProviderName => TmdbUtils.ProviderName;
|
||||
/// <inheritdoc />
|
||||
public int Order => 0;
|
||||
|
||||
public bool Supports(BaseItem item)
|
||||
{
|
||||
|
@ -125,8 +129,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
|
|||
return profile.Iso_639_1?.ToString();
|
||||
}
|
||||
|
||||
public int Order => 0;
|
||||
|
||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||
{
|
||||
return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
|
|||
{
|
||||
const string DataFileName = "info.json";
|
||||
|
||||
internal static TmdbPersonProvider Current { get; private set; }
|
||||
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
@ -55,6 +55,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
|
|||
Current = this;
|
||||
}
|
||||
|
||||
internal static TmdbPersonProvider Current { get; private set; }
|
||||
|
||||
public string Name => TmdbUtils.ProviderName;
|
||||
|
||||
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(PersonLookupInfo searchInfo, CancellationToken cancellationToken)
|
||||
|
@ -95,7 +97,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
|
|||
return new List<RemoteSearchResult>();
|
||||
}
|
||||
|
||||
var url = string.Format(TmdbUtils.BaseTmdbApiUrl + @"3/search/person?api_key={1}&query={0}", WebUtility.UrlEncode(searchInfo.Name), TmdbUtils.ApiKey);
|
||||
var url = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
TmdbUtils.BaseTmdbApiUrl + @"3/search/person?api_key={1}&query={0}",
|
||||
WebUtility.UrlEncode(searchInfo.Name),
|
||||
TmdbUtils.ApiKey);
|
||||
|
||||
using var requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
foreach (var header in TmdbUtils.AcceptHeaders)
|
||||
|
@ -200,8 +206,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
|
|||
return result;
|
||||
}
|
||||
|
||||
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the TMDB id.
|
||||
/// </summary>
|
||||
|
@ -226,7 +230,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
|
|||
return;
|
||||
}
|
||||
|
||||
var url = string.Format(TmdbUtils.BaseTmdbApiUrl + @"3/person/{1}?api_key={0}&append_to_response=credits,images,external_ids", TmdbUtils.ApiKey, id);
|
||||
var url = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
TmdbUtils.BaseTmdbApiUrl + @"3/person/{1}?api_key={0}&append_to_response=credits,images,external_ids",
|
||||
TmdbUtils.ApiKey,
|
||||
id);
|
||||
|
||||
using var requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
foreach (var header in TmdbUtils.AcceptHeaders)
|
||||
|
|
Loading…
Reference in New Issue
Block a user