mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-03-12 05:06:23 +00:00
Merge branch 'master' into sessionmanager
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
#pragma warning disable SA1600
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Activity;
|
||||
using MediaBrowser.Model.Events;
|
||||
|
||||
@@ -599,7 +599,7 @@ namespace Emby.Server.Implementations
|
||||
HttpsPort = ServerConfiguration.DefaultHttpsPort;
|
||||
}
|
||||
|
||||
JsonSerializer = new JsonSerializer(FileSystemManager);
|
||||
JsonSerializer = new JsonSerializer();
|
||||
|
||||
if (Plugins != null)
|
||||
{
|
||||
@@ -1018,7 +1018,7 @@ namespace Emby.Server.Implementations
|
||||
{
|
||||
string dir = Path.Combine(ApplicationPaths.PluginsPath, args.Argument.name);
|
||||
var types = Directory.EnumerateFiles(dir, "*.dll", SearchOption.AllDirectories)
|
||||
.Select(x => Assembly.LoadFrom(x))
|
||||
.Select(Assembly.LoadFrom)
|
||||
.SelectMany(x => x.ExportedTypes)
|
||||
.Where(x => x.IsClass && !x.IsAbstract && !x.IsInterface && !x.IsGenericType)
|
||||
.ToArray();
|
||||
@@ -1718,29 +1718,6 @@ namespace Emby.Server.Implementations
|
||||
_plugins = list.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This returns localhost in the case of no external dns, and the hostname if the
|
||||
/// dns is prefixed with a valid Uri prefix.
|
||||
/// </summary>
|
||||
/// <param name="externalDns">The external dns prefix to get the hostname of.</param>
|
||||
/// <returns>The hostname in <paramref name="externalDns"/>.</returns>
|
||||
private static string GetHostnameFromExternalDns(string externalDns)
|
||||
{
|
||||
if (string.IsNullOrEmpty(externalDns))
|
||||
{
|
||||
return "localhost";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return new Uri(externalDns).Host;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return externalDns;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void LaunchUrl(string url)
|
||||
{
|
||||
if (!CanLaunchWebBrowser)
|
||||
|
||||
@@ -35,14 +35,6 @@ namespace Emby.Server.Implementations.Channels
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public static string GetUserDistinctValue(User user)
|
||||
{
|
||||
var channels = user.Policy.EnabledChannels
|
||||
.OrderBy(i => i);
|
||||
|
||||
return string.Join("|", channels);
|
||||
}
|
||||
|
||||
private void CleanDatabase(CancellationToken cancellationToken)
|
||||
{
|
||||
var installedChannelIds = ((ChannelManager)_channelManager).GetInstalledChannelIds();
|
||||
@@ -75,19 +67,23 @@ namespace Emby.Server.Implementations.Channels
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
_libraryManager.DeleteItem(item, new DeleteOptions
|
||||
{
|
||||
DeleteFileLocation = false
|
||||
|
||||
}, false);
|
||||
_libraryManager.DeleteItem(
|
||||
item,
|
||||
new DeleteOptions
|
||||
{
|
||||
DeleteFileLocation = false
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
// Finally, delete the channel itself
|
||||
_libraryManager.DeleteItem(channel, new DeleteOptions
|
||||
{
|
||||
DeleteFileLocation = false
|
||||
|
||||
}, false);
|
||||
_libraryManager.DeleteItem(
|
||||
channel,
|
||||
new DeleteOptions
|
||||
{
|
||||
DeleteFileLocation = false
|
||||
},
|
||||
false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,18 +28,28 @@ namespace Emby.Server.Implementations.Channels
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => "Refresh Channels";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => "Refreshes internet channel information.";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Category => "Internet Channels";
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsHidden => ((ChannelManager)_channelManager).Channels.Length == 0;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEnabled => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsLogged => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => "RefreshInternetChannels";
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
|
||||
{
|
||||
var manager = (ChannelManager)_channelManager;
|
||||
@@ -50,18 +60,18 @@ namespace Emby.Server.Implementations.Channels
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the triggers that define when the task will run
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
|
||||
{
|
||||
return new[] {
|
||||
return new[]
|
||||
{
|
||||
|
||||
// Every so often
|
||||
new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks}
|
||||
new TaskTriggerInfo
|
||||
{
|
||||
Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public string Key => "RefreshInternetChannels";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma warning disable CS1591
|
||||
#pragma warning disable SA1600
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Emby.Server.Implementations.Images;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using Emby.Server.Implementations.AppBase;
|
||||
|
||||
@@ -243,7 +243,7 @@ namespace Emby.Server.Implementations.Devices
|
||||
|
||||
try
|
||||
{
|
||||
using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
|
||||
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
await stream.CopyToAsync(fs).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -29,11 +29,11 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.1" />
|
||||
<PackageReference Include="Mono.Nat" Version="2.0.0" />
|
||||
<PackageReference Include="ServiceStack.Text.Core" Version="5.7.0" />
|
||||
<PackageReference Include="ServiceStack.Text.Core" Version="5.8.0" />
|
||||
<PackageReference Include="sharpcompress" Version="0.24.0" />
|
||||
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.1.0" />
|
||||
<PackageReference Include="System.Interactive.Async" Version="4.0.0" />
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
#pragma warning disable CS1591
|
||||
#pragma warning disable SA1600
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Controller.Plugins;
|
||||
using MediaBrowser.Controller.Session;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Emby.Server.Implementations.EntryPoints
|
||||
{
|
||||
public class AutomaticRestartEntryPoint : IServerEntryPoint
|
||||
{
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
private readonly ILogger _logger;
|
||||
private readonly ITaskManager _iTaskManager;
|
||||
private readonly ISessionManager _sessionManager;
|
||||
private readonly IServerConfigurationManager _config;
|
||||
private readonly ILiveTvManager _liveTvManager;
|
||||
|
||||
private Timer _timer;
|
||||
|
||||
public AutomaticRestartEntryPoint(IServerApplicationHost appHost, ILogger logger, ITaskManager iTaskManager, ISessionManager sessionManager, IServerConfigurationManager config, ILiveTvManager liveTvManager)
|
||||
{
|
||||
_appHost = appHost;
|
||||
_logger = logger;
|
||||
_iTaskManager = iTaskManager;
|
||||
_sessionManager = sessionManager;
|
||||
_config = config;
|
||||
_liveTvManager = liveTvManager;
|
||||
}
|
||||
|
||||
public Task RunAsync()
|
||||
{
|
||||
if (_appHost.CanSelfRestart)
|
||||
{
|
||||
_appHost.HasPendingRestartChanged += _appHost_HasPendingRestartChanged;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
void _appHost_HasPendingRestartChanged(object sender, EventArgs e)
|
||||
{
|
||||
DisposeTimer();
|
||||
|
||||
if (_appHost.HasPendingRestart)
|
||||
{
|
||||
_timer = new Timer(TimerCallback, null, TimeSpan.FromMinutes(15), TimeSpan.FromMinutes(15));
|
||||
}
|
||||
}
|
||||
|
||||
private async void TimerCallback(object state)
|
||||
{
|
||||
if (_config.Configuration.EnableAutomaticRestart)
|
||||
{
|
||||
var isIdle = await IsIdle().ConfigureAwait(false);
|
||||
|
||||
if (isIdle)
|
||||
{
|
||||
DisposeTimer();
|
||||
|
||||
_logger.LogInformation("Automatically restarting the system because it is idle and a restart is required.");
|
||||
|
||||
try
|
||||
{
|
||||
_appHost.Restart();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error restarting server");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> IsIdle()
|
||||
{
|
||||
if (_iTaskManager.ScheduledTasks.Any(i => i.State != TaskState.Idle))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_liveTvManager.Services.Count == 1)
|
||||
{
|
||||
try
|
||||
{
|
||||
var timers = await _liveTvManager.GetTimers(new TimerQuery(), CancellationToken.None).ConfigureAwait(false);
|
||||
if (timers.Items.Any(i => i.Status == RecordingStatus.InProgress))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error getting timers");
|
||||
}
|
||||
}
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
return !_sessionManager.Sessions.Any(i => (now - i.LastActivityDate).TotalMinutes < 30);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_appHost.HasPendingRestartChanged -= _appHost_HasPendingRestartChanged;
|
||||
|
||||
DisposeTimer();
|
||||
}
|
||||
|
||||
private void DisposeTimer()
|
||||
{
|
||||
if (_timer != null)
|
||||
{
|
||||
_timer.Dispose();
|
||||
_timer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@ using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Controller.Session;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Events;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Emby.Server.Implementations.EntryPoints
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Emby.Server.Implementations.Udp;
|
||||
|
||||
@@ -197,7 +197,7 @@ namespace Emby.Server.Implementations.HttpClientManager
|
||||
if (File.Exists(responseCachePath)
|
||||
&& _fileSystem.GetLastWriteTimeUtc(responseCachePath).Add(cacheLength) > DateTime.UtcNow)
|
||||
{
|
||||
var stream = _fileSystem.GetFileStream(responseCachePath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read, true);
|
||||
var stream = new FileStream(responseCachePath, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, true);
|
||||
|
||||
return new HttpResponseInfo
|
||||
{
|
||||
@@ -220,7 +220,7 @@ namespace Emby.Server.Implementations.HttpClientManager
|
||||
FileMode.Create,
|
||||
FileAccess.Write,
|
||||
FileShare.None,
|
||||
StreamDefaults.DefaultFileStreamBufferSize,
|
||||
IODefaults.FileStreamBufferSize,
|
||||
true))
|
||||
{
|
||||
await response.Content.CopyToAsync(fileStream).ConfigureAwait(false);
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
SetRangeValues();
|
||||
}
|
||||
|
||||
FileShare = FileShareMode.Read;
|
||||
FileShare = FileShare.Read;
|
||||
Cookies = new List<Cookie>();
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
|
||||
public List<Cookie> Cookies { get; private set; }
|
||||
|
||||
public FileShareMode FileShare { get; set; }
|
||||
public FileShare FileShare { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the options.
|
||||
@@ -222,17 +222,17 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
}
|
||||
}
|
||||
|
||||
public async Task TransmitFile(Stream stream, string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
|
||||
public async Task TransmitFile(Stream stream, string path, long offset, long count, FileShare fileShare, CancellationToken cancellationToken)
|
||||
{
|
||||
var fileOpenOptions = FileOpenOptions.SequentialScan;
|
||||
var fileOptions = FileOptions.SequentialScan;
|
||||
|
||||
// use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
fileOpenOptions |= FileOpenOptions.Asynchronous;
|
||||
fileOptions |= FileOptions.Asynchronous;
|
||||
}
|
||||
|
||||
using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, fileShareMode, fileOpenOptions))
|
||||
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, fileShare, IODefaults.FileStreamBufferSize, fileOptions))
|
||||
{
|
||||
if (offset > 0)
|
||||
{
|
||||
@@ -245,7 +245,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
}
|
||||
else
|
||||
{
|
||||
await fs.CopyToAsync(stream, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false);
|
||||
await fs.CopyToAsync(stream, IODefaults.CopyToBufferSize, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,7 +440,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
|
||||
public Task<object> GetStaticFileResult(IRequest requestContext,
|
||||
string path,
|
||||
FileShareMode fileShare = FileShareMode.Read)
|
||||
FileShare fileShare = FileShare.Read)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
@@ -464,7 +464,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
throw new ArgumentException("Path can't be empty.", nameof(options));
|
||||
}
|
||||
|
||||
if (fileShare != FileShareMode.Read && fileShare != FileShareMode.ReadWrite)
|
||||
if (fileShare != FileShare.Read && fileShare != FileShare.ReadWrite)
|
||||
{
|
||||
throw new ArgumentException("FileShare must be either Read or ReadWrite");
|
||||
}
|
||||
@@ -492,9 +492,9 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
/// <param name="path">The path.</param>
|
||||
/// <param name="fileShare">The file share.</param>
|
||||
/// <returns>Stream.</returns>
|
||||
private Stream GetFileStream(string path, FileShareMode fileShare)
|
||||
private Stream GetFileStream(string path, FileShare fileShare)
|
||||
{
|
||||
return _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, fileShare);
|
||||
return new FileStream(path, FileMode.Open, FileAccess.Read, fileShare);
|
||||
}
|
||||
|
||||
public Task<object> GetStaticResult(IRequest requestContext,
|
||||
|
||||
@@ -365,87 +365,6 @@ namespace Emby.Server.Implementations.IO
|
||||
return GetLastWriteTimeUtc(GetFileSystemInfo(path));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the file stream.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <param name="mode">The mode.</param>
|
||||
/// <param name="access">The access.</param>
|
||||
/// <param name="share">The share.</param>
|
||||
/// <param name="isAsync">if set to <c>true</c> [is asynchronous].</param>
|
||||
/// <returns>FileStream.</returns>
|
||||
public virtual Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, bool isAsync = false)
|
||||
{
|
||||
if (isAsync)
|
||||
{
|
||||
return GetFileStream(path, mode, access, share, FileOpenOptions.Asynchronous);
|
||||
}
|
||||
|
||||
return GetFileStream(path, mode, access, share, FileOpenOptions.None);
|
||||
}
|
||||
|
||||
public virtual Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, FileOpenOptions fileOpenOptions)
|
||||
=> new FileStream(path, GetFileMode(mode), GetFileAccess(access), GetFileShare(share), 4096, GetFileOptions(fileOpenOptions));
|
||||
|
||||
private static FileOptions GetFileOptions(FileOpenOptions mode)
|
||||
{
|
||||
var val = (int)mode;
|
||||
return (FileOptions)val;
|
||||
}
|
||||
|
||||
private static FileMode GetFileMode(FileOpenMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
//case FileOpenMode.Append:
|
||||
// return FileMode.Append;
|
||||
case FileOpenMode.Create:
|
||||
return FileMode.Create;
|
||||
case FileOpenMode.CreateNew:
|
||||
return FileMode.CreateNew;
|
||||
case FileOpenMode.Open:
|
||||
return FileMode.Open;
|
||||
case FileOpenMode.OpenOrCreate:
|
||||
return FileMode.OpenOrCreate;
|
||||
//case FileOpenMode.Truncate:
|
||||
// return FileMode.Truncate;
|
||||
default:
|
||||
throw new Exception("Unrecognized FileOpenMode");
|
||||
}
|
||||
}
|
||||
|
||||
private static FileAccess GetFileAccess(FileAccessMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
//case FileAccessMode.ReadWrite:
|
||||
// return FileAccess.ReadWrite;
|
||||
case FileAccessMode.Write:
|
||||
return FileAccess.Write;
|
||||
case FileAccessMode.Read:
|
||||
return FileAccess.Read;
|
||||
default:
|
||||
throw new Exception("Unrecognized FileAccessMode");
|
||||
}
|
||||
}
|
||||
|
||||
private static FileShare GetFileShare(FileShareMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case FileShareMode.ReadWrite:
|
||||
return FileShare.ReadWrite;
|
||||
case FileShareMode.Write:
|
||||
return FileShare.Write;
|
||||
case FileShareMode.Read:
|
||||
return FileShare.Read;
|
||||
case FileShareMode.None:
|
||||
return FileShare.None;
|
||||
default:
|
||||
throw new Exception("Unrecognized FileShareMode");
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void SetHidden(string path, bool isHidden)
|
||||
{
|
||||
if (OperatingSystem.Id != OperatingSystemId.Windows)
|
||||
|
||||
@@ -36,7 +36,6 @@ using MediaBrowser.Controller.Sorting;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Library;
|
||||
using MediaBrowser.Model.Net;
|
||||
@@ -54,6 +53,9 @@ namespace Emby.Server.Implementations.Library
|
||||
/// </summary>
|
||||
public class LibraryManager : ILibraryManager
|
||||
{
|
||||
private NamingOptions _namingOptions;
|
||||
private string[] _videoFileExtensions;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the postscan tasks.
|
||||
/// </summary>
|
||||
@@ -708,10 +710,10 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the root media folder
|
||||
/// Creates the root media folder.
|
||||
/// </summary>
|
||||
/// <returns>AggregateFolder.</returns>
|
||||
/// <exception cref="InvalidOperationException">Cannot create the root folder until plugins have loaded</exception>
|
||||
/// <exception cref="InvalidOperationException">Cannot create the root folder until plugins have loaded.</exception>
|
||||
public AggregateFolder CreateRootFolder()
|
||||
{
|
||||
var rootFolderPath = ConfigurationManager.ApplicationPaths.RootFolderPath;
|
||||
@@ -822,7 +824,6 @@ namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
// If this returns multiple items it could be tricky figuring out which one is correct.
|
||||
// In most cases, the newest one will be and the others obsolete but not yet cleaned up
|
||||
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
@@ -842,7 +843,7 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a Person
|
||||
/// Gets the person.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns>Task{Person}.</returns>
|
||||
@@ -852,7 +853,7 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a Studio
|
||||
/// Gets the studio.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns>Task{Studio}.</returns>
|
||||
@@ -877,7 +878,7 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a Genre
|
||||
/// Gets the genre.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns>Task{Genre}.</returns>
|
||||
@@ -887,7 +888,7 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the genre.
|
||||
/// Gets the music genre.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns>Task{MusicGenre}.</returns>
|
||||
@@ -897,7 +898,7 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a Year
|
||||
/// Gets the year.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns>Task{Year}.</returns>
|
||||
@@ -1074,9 +1075,9 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
var innerProgress = new ActionableProgress<double>();
|
||||
|
||||
innerProgress.RegisterAction(pct => progress.Report(pct * .96));
|
||||
innerProgress.RegisterAction(pct => progress.Report(pct * pct * 0.96));
|
||||
|
||||
// Now validate the entire media library
|
||||
// Validate the entire media library
|
||||
await RootFolder.ValidateChildren(innerProgress, cancellationToken, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), recursive: true).ConfigureAwait(false);
|
||||
|
||||
progress.Report(96);
|
||||
@@ -1085,7 +1086,6 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
innerProgress.RegisterAction(pct => progress.Report(96 + (pct * .04)));
|
||||
|
||||
// Run post-scan tasks
|
||||
await RunPostScanTasks(innerProgress, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
progress.Report(100);
|
||||
@@ -1136,7 +1136,7 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error running postscan task");
|
||||
_logger.LogError(ex, "Error running post-scan task");
|
||||
}
|
||||
|
||||
numComplete++;
|
||||
@@ -2382,7 +2382,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
public int? GetSeasonNumberFromPath(string path)
|
||||
{
|
||||
return new SeasonPathParser().Parse(path, true, true).SeasonNumber;
|
||||
return SeasonPathParser.Parse(path, true, true).SeasonNumber;
|
||||
}
|
||||
|
||||
public bool FillMissingEpisodeNumbersFromPath(Episode episode, bool forceRefresh)
|
||||
@@ -2508,21 +2508,11 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
|
||||
public NamingOptions GetNamingOptions()
|
||||
{
|
||||
return GetNamingOptionsInternal();
|
||||
}
|
||||
|
||||
private NamingOptions _namingOptions;
|
||||
private string[] _videoFileExtensions;
|
||||
|
||||
private NamingOptions GetNamingOptionsInternal()
|
||||
{
|
||||
if (_namingOptions == null)
|
||||
{
|
||||
var options = new NamingOptions();
|
||||
|
||||
_namingOptions = options;
|
||||
_videoFileExtensions = _namingOptions.VideoFileExtensions.ToArray();
|
||||
_namingOptions = new NamingOptions();
|
||||
_videoFileExtensions = _namingOptions.VideoFileExtensions;
|
||||
}
|
||||
|
||||
return _namingOptions;
|
||||
@@ -2533,11 +2523,10 @@ namespace Emby.Server.Implementations.Library
|
||||
var resolver = new VideoResolver(GetNamingOptions());
|
||||
|
||||
var result = resolver.CleanDateTime(name);
|
||||
var cleanName = resolver.CleanString(result.Name);
|
||||
|
||||
return new ItemLookupInfo
|
||||
{
|
||||
Name = cleanName.Name,
|
||||
Name = resolver.TryCleanString(result.Name, out var newName) ? newName.ToString() : result.Name,
|
||||
Year = result.Year
|
||||
};
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the supplied file data points to a music album
|
||||
/// Determine if the supplied file data points to a music album.
|
||||
/// </summary>
|
||||
public bool IsMusicAlbum(string path, IDirectoryService directoryService, LibraryOptions libraryOptions)
|
||||
{
|
||||
@@ -84,7 +84,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the supplied resolve args should be considered a music album
|
||||
/// Determine if the supplied resolve args should be considered a music album.
|
||||
/// </summary>
|
||||
/// <param name="args">The args.</param>
|
||||
/// <returns><c>true</c> if [is music album] [the specified args]; otherwise, <c>false</c>.</returns>
|
||||
@@ -104,7 +104,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the supplied list contains what we should consider music
|
||||
/// Determine if the supplied list contains what we should consider music.
|
||||
/// </summary>
|
||||
private bool ContainsMusic(
|
||||
IEnumerable<FileSystemMetadata> list,
|
||||
@@ -118,6 +118,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
var discSubfolderCount = 0;
|
||||
var notMultiDisc = false;
|
||||
|
||||
var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
|
||||
var parser = new AlbumParser(namingOptions);
|
||||
foreach (var fileSystemInfo in list)
|
||||
{
|
||||
if (fileSystemInfo.IsDirectory)
|
||||
@@ -134,7 +136,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
|
||||
if (hasMusic)
|
||||
{
|
||||
if (IsMultiDiscFolder(path, libraryOptions))
|
||||
if (parser.IsMultiPart(path))
|
||||
{
|
||||
logger.LogDebug("Found multi-disc folder: " + path);
|
||||
discSubfolderCount++;
|
||||
@@ -165,15 +167,5 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
|
||||
return discSubfolderCount > 0;
|
||||
}
|
||||
|
||||
private bool IsMultiDiscFolder(string path, LibraryOptions libraryOptions)
|
||||
{
|
||||
var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
|
||||
|
||||
var parser = new AlbumParser(namingOptions);
|
||||
var result = parser.ParseMultiPart(path);
|
||||
|
||||
return result.IsMultiPart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,28 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
/// </summary>
|
||||
public class MovieResolver : BaseVideoResolver<Video>, IMultiItemResolver
|
||||
{
|
||||
private string[] _validCollectionTypes = new[]
|
||||
{
|
||||
CollectionType.Movies,
|
||||
CollectionType.HomeVideos,
|
||||
CollectionType.MusicVideos,
|
||||
CollectionType.Movies,
|
||||
CollectionType.Photos
|
||||
};
|
||||
|
||||
private readonly IImageProcessor _imageProcessor;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MovieResolver"/> class.
|
||||
/// </summary>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
/// <param name="imageProcessor">The image processor.</param>
|
||||
public MovieResolver(ILibraryManager libraryManager, IImageProcessor imageProcessor)
|
||||
: base(libraryManager)
|
||||
{
|
||||
_imageProcessor = imageProcessor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the priority.
|
||||
/// </summary>
|
||||
@@ -144,7 +166,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
|
||||
foreach (var video in resolverResult)
|
||||
{
|
||||
var firstVideo = video.Files.First();
|
||||
var firstVideo = video.Files[0];
|
||||
|
||||
var videoItem = new T
|
||||
{
|
||||
@@ -230,7 +252,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
// Owned items will be caught by the plain video resolver
|
||||
if (args.Parent == null)
|
||||
{
|
||||
//return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
|
||||
// return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -275,7 +297,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
{
|
||||
item = ResolveVideo<Movie>(args, true);
|
||||
}
|
||||
|
||||
else if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -319,7 +340,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
{
|
||||
if (item is Movie || item is MusicVideo)
|
||||
{
|
||||
//we need to only look at the name of this actual item (not parents)
|
||||
// We need to only look at the name of this actual item (not parents)
|
||||
var justName = item.IsInMixedFolder ? Path.GetFileName(item.Path) : Path.GetFileName(item.ContainingFolderPath);
|
||||
|
||||
if (!string.IsNullOrEmpty(justName))
|
||||
@@ -347,9 +368,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds a movie based on a child file system entries
|
||||
/// Finds a movie based on a child file system entries.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns>Movie.</returns>
|
||||
private T FindMovie<T>(ItemResolveArgs args, string path, Folder parent, List<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, string collectionType, bool parseName)
|
||||
where T : Video, new()
|
||||
@@ -377,6 +397,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
Set3DFormat(movie);
|
||||
return movie;
|
||||
}
|
||||
|
||||
if (IsBluRayDirectory(child.FullName, filename, directoryService))
|
||||
{
|
||||
var movie = new T
|
||||
@@ -407,9 +428,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
}
|
||||
|
||||
// TODO: Allow GetMultiDiscMovie in here
|
||||
const bool supportsMultiVersion = true;
|
||||
const bool SupportsMultiVersion = true;
|
||||
|
||||
var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, supportsMultiVersion, collectionType, parseName) ??
|
||||
var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, SupportsMultiVersion, collectionType, parseName) ??
|
||||
new MultiItemResolverResult();
|
||||
|
||||
if (result.Items.Count == 1)
|
||||
@@ -437,7 +458,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
/// <summary>
|
||||
/// Gets the multi disc movie.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="multiDiscFolders">The folders.</param>
|
||||
/// <param name="directoryService">The directory service.</param>
|
||||
/// <returns>``0.</returns>
|
||||
@@ -451,7 +471,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
var subFileEntries = directoryService.GetFileSystemEntries(i);
|
||||
|
||||
var subfolders = subFileEntries
|
||||
.Where(e => e.IsDirectory)
|
||||
.Where(e => e.IsDirectory)
|
||||
.ToList();
|
||||
|
||||
if (subfolders.Any(s => IsDvdDirectory(s.FullName, s.Name, directoryService)))
|
||||
@@ -459,6 +479,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
videoTypes.Add(VideoType.Dvd);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (subfolders.Any(s => IsBluRayDirectory(s.FullName, s.Name, directoryService)))
|
||||
{
|
||||
videoTypes.Add(VideoType.BluRay);
|
||||
@@ -476,7 +497,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}).OrderBy(i => i).ToList();
|
||||
|
||||
// If different video types were found, don't allow this
|
||||
@@ -491,11 +511,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
}
|
||||
|
||||
var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions();
|
||||
var resolver = new StackResolver(namingOptions);
|
||||
|
||||
var result = resolver.ResolveDirectories(folderPaths);
|
||||
var result = new StackResolver(namingOptions).ResolveDirectories(folderPaths).ToList();
|
||||
|
||||
if (result.Stacks.Count != 1)
|
||||
if (result.Count != 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -508,7 +527,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
|
||||
VideoType = videoTypes[0],
|
||||
|
||||
Name = result.Stacks[0].Name
|
||||
Name = result[0].Name
|
||||
};
|
||||
|
||||
SetIsoType(returnVideo);
|
||||
@@ -516,15 +535,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
return returnVideo;
|
||||
}
|
||||
|
||||
private string[] ValidCollectionTypes = new[]
|
||||
{
|
||||
CollectionType.Movies,
|
||||
CollectionType.HomeVideos,
|
||||
CollectionType.MusicVideos,
|
||||
CollectionType.Movies,
|
||||
CollectionType.Photos
|
||||
};
|
||||
|
||||
private bool IsInvalid(Folder parent, string collectionType)
|
||||
{
|
||||
if (parent != null)
|
||||
@@ -540,20 +550,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
return false;
|
||||
}
|
||||
|
||||
return !ValidCollectionTypes.Contains(collectionType, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private IImageProcessor _imageProcessor;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MovieResolver"/> class.
|
||||
/// </summary>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
/// <param name="imageProcessor">The image processor.</param>
|
||||
public MovieResolver(ILibraryManager libraryManager, IImageProcessor imageProcessor)
|
||||
: base(libraryManager)
|
||||
{
|
||||
_imageProcessor = imageProcessor;
|
||||
return !_validCollectionTypes.Contains(collectionType, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,17 +9,12 @@ using Microsoft.Extensions.Logging;
|
||||
namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
{
|
||||
/// <summary>
|
||||
/// Class SeasonResolver
|
||||
/// Class SeasonResolver.
|
||||
/// </summary>
|
||||
public class SeasonResolver : FolderResolver<Season>
|
||||
{
|
||||
/// <summary>
|
||||
/// The _config
|
||||
/// </summary>
|
||||
private readonly IServerConfigurationManager _config;
|
||||
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||
private readonly ILocalizationManager _localization;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
@@ -45,14 +40,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
/// <returns>Season.</returns>
|
||||
protected override Season Resolve(ItemResolveArgs args)
|
||||
{
|
||||
if (args.Parent is Series && args.IsDirectory)
|
||||
if (args.Parent is Series series && args.IsDirectory)
|
||||
{
|
||||
var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
|
||||
var series = ((Series)args.Parent);
|
||||
|
||||
var path = args.Path;
|
||||
|
||||
var seasonParserResult = new SeasonPathParser().Parse(path, true, true);
|
||||
var seasonParserResult = SeasonPathParser.Parse(path, true, true);
|
||||
|
||||
var season = new Season
|
||||
{
|
||||
@@ -74,7 +68,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
{
|
||||
if (episodeInfo.EpisodeNumber.HasValue && episodeInfo.SeasonNumber.HasValue)
|
||||
{
|
||||
_logger.LogDebug("Found folder underneath series with episode number: {0}. Season {1}. Episode {2}",
|
||||
_logger.LogDebug(
|
||||
"Found folder underneath series with episode number: {0}. Season {1}. Episode {2}",
|
||||
path,
|
||||
episodeInfo.SeasonNumber.Value,
|
||||
episodeInfo.EpisodeNumber.Value);
|
||||
@@ -90,7 +85,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
|
||||
season.Name = seasonNumber == 0 ?
|
||||
args.LibraryOptions.SeasonZeroDisplayName :
|
||||
string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture), args.GetLibraryOptions().PreferredMetadataLanguage);
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
_localization.GetLocalizedString("NameSeasonNumber"),
|
||||
seasonNumber,
|
||||
args.GetLibraryOptions().PreferredMetadataLanguage);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
/// <returns><c>true</c> if [is season folder] [the specified path]; otherwise, <c>false</c>.</returns>
|
||||
private static bool IsSeasonFolder(string path, bool isTvContentType, ILibraryManager libraryManager)
|
||||
{
|
||||
var seasonNumber = new SeasonPathParser().Parse(path, isTvContentType, isTvContentType).SeasonNumber;
|
||||
var seasonNumber = SeasonPathParser.Parse(path, isTvContentType, isTvContentType).SeasonNumber;
|
||||
|
||||
return seasonNumber.HasValue;
|
||||
}
|
||||
|
||||
@@ -291,10 +291,11 @@ namespace Emby.Server.Implementations.Library
|
||||
&& authenticationProvider != null
|
||||
&& !(authenticationProvider is DefaultAuthenticationProvider))
|
||||
{
|
||||
// We should trust the user that the authprovider says, not what was typed
|
||||
// Trust the username returned by the authentication provider
|
||||
username = updatedUsername;
|
||||
|
||||
// Search the database for the user again; the authprovider might have created it
|
||||
// Search the database for the user again
|
||||
// the authentication provider might have created it
|
||||
user = Users
|
||||
.FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
@@ -667,7 +668,7 @@ namespace Emby.Server.Implementations.Library
|
||||
throw new ArgumentException("Invalid username", nameof(newName));
|
||||
}
|
||||
|
||||
if (user.Name.Equals(newName, StringComparison.OrdinalIgnoreCase))
|
||||
if (user.Name.Equals(newName, StringComparison.Ordinal))
|
||||
{
|
||||
throw new ArgumentException("The new and old names must be different.");
|
||||
}
|
||||
|
||||
@@ -15,14 +15,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly IStreamHelper _streamHelper;
|
||||
|
||||
public DirectRecorder(ILogger logger, IHttpClient httpClient, IFileSystem fileSystem, IStreamHelper streamHelper)
|
||||
public DirectRecorder(ILogger logger, IHttpClient httpClient, IStreamHelper streamHelper)
|
||||
{
|
||||
_logger = logger;
|
||||
_httpClient = httpClient;
|
||||
_fileSystem = fileSystem;
|
||||
_streamHelper = streamHelper;
|
||||
}
|
||||
|
||||
@@ -45,7 +43,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(targetFile));
|
||||
|
||||
using (var output = _fileSystem.GetFileStream(targetFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
|
||||
using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
onStarted();
|
||||
|
||||
@@ -81,7 +79,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(targetFile));
|
||||
|
||||
using (var output = _fileSystem.GetFileStream(targetFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
|
||||
using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
onStarted();
|
||||
|
||||
|
||||
@@ -427,7 +427,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
{
|
||||
foreach (NameValuePair mapping in mappings)
|
||||
{
|
||||
if (StringHelper.EqualsIgnoreCase(mapping.Name, channelId))
|
||||
if (string.Equals(mapping.Name, channelId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return mapping.Value;
|
||||
}
|
||||
@@ -1664,10 +1664,10 @@ 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, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, _processFactory, _config);
|
||||
return new EncodedRecorder(_logger, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, _processFactory, _config);
|
||||
}
|
||||
|
||||
return new DirectRecorder(_logger, _httpClient, _fileSystem, _streamHelper);
|
||||
return new DirectRecorder(_logger, _httpClient, _streamHelper);
|
||||
}
|
||||
|
||||
private void OnSuccessfulRecording(TimerInfo timer, string path)
|
||||
@@ -1888,7 +1888,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
return;
|
||||
}
|
||||
|
||||
using (var stream = _fileSystem.GetFileStream(nfoPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
|
||||
using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
var settings = new XmlWriterSettings
|
||||
{
|
||||
@@ -1952,7 +1952,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
return;
|
||||
}
|
||||
|
||||
using (var stream = _fileSystem.GetFileStream(nfoPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
|
||||
using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
var settings = new XmlWriterSettings
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -14,7 +13,6 @@ using MediaBrowser.Controller.MediaEncoding;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Diagnostics;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -24,7 +22,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
public class EncodedRecorder : IRecorder
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly IMediaEncoder _mediaEncoder;
|
||||
private readonly IServerApplicationPaths _appPaths;
|
||||
private bool _hasExited;
|
||||
@@ -38,7 +35,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
|
||||
public EncodedRecorder(
|
||||
ILogger logger,
|
||||
IFileSystem fileSystem,
|
||||
IMediaEncoder mediaEncoder,
|
||||
IServerApplicationPaths appPaths,
|
||||
IJsonSerializer json,
|
||||
@@ -46,7 +42,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
IServerConfigurationManager config)
|
||||
{
|
||||
_logger = logger;
|
||||
_fileSystem = fileSystem;
|
||||
_mediaEncoder = mediaEncoder;
|
||||
_appPaths = appPaths;
|
||||
_json = json;
|
||||
@@ -107,7 +102,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
|
||||
|
||||
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
|
||||
_logFileStream = _fileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true);
|
||||
_logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true);
|
||||
|
||||
var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(_json.SerializeToString(mediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine);
|
||||
_logFileStream.Write(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length);
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
FileMode.Open,
|
||||
FileAccess.Read,
|
||||
FileShare.ReadWrite,
|
||||
StreamDefaults.DefaultFileStreamBufferSize,
|
||||
IODefaults.FileStreamBufferSize,
|
||||
allowAsyncFileRead ? FileOptions.SequentialScan | FileOptions.Asynchronous : FileOptions.SequentialScan);
|
||||
|
||||
public Task DeleteTempFiles()
|
||||
@@ -199,7 +199,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
await StreamHelper.CopyToAsync(
|
||||
inputStream,
|
||||
stream,
|
||||
StreamDefaults.DefaultCopyToBufferSize,
|
||||
IODefaults.CopyToBufferSize,
|
||||
emptyReadLimit,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
|
||||
@@ -127,12 +127,12 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath);
|
||||
using (response)
|
||||
using (var stream = response.Content)
|
||||
using (var fileStream = FileSystem.GetFileStream(TempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None))
|
||||
using (var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
await StreamHelper.CopyToAsync(
|
||||
stream,
|
||||
fileStream,
|
||||
StreamDefaults.DefaultCopyToBufferSize,
|
||||
IODefaults.CopyToBufferSize,
|
||||
() => Resolve(openTaskCompletionSource),
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"Channels": "القنوات",
|
||||
"ChapterNameValue": "الباب {0}",
|
||||
"Collections": "مجموعات",
|
||||
"DeviceOfflineWithName": "تم قطع الاتصال بـ{0}",
|
||||
"DeviceOfflineWithName": "تم قطع اتصال {0}",
|
||||
"DeviceOnlineWithName": "{0} متصل",
|
||||
"FailedLoginAttemptWithUserName": "عملية تسجيل الدخول فشلت من {0}",
|
||||
"Favorites": "التفضيلات",
|
||||
@@ -75,8 +75,8 @@
|
||||
"Songs": "الأغاني",
|
||||
"StartupEmbyServerIsLoading": "سيرفر Jellyfin قيد التشغيل . الرجاء المحاولة بعد قليل.",
|
||||
"SubtitleDownloadFailureForItem": "عملية إنزال الترجمة فشلت لـ{0}",
|
||||
"SubtitleDownloadFailureFromForItem": "الترجمات فشلت في التحميل من {0} لـ {1}",
|
||||
"SubtitlesDownloadedForItem": "تم تحميل الترجمات لـ {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "الترجمات فشلت في التحميل من {0} الى {1}",
|
||||
"SubtitlesDownloadedForItem": "تم تحميل الترجمات الى {0}",
|
||||
"Sync": "مزامنة",
|
||||
"System": "النظام",
|
||||
"TvShows": "البرامج التلفزيونية",
|
||||
@@ -88,7 +88,7 @@
|
||||
"UserOfflineFromDevice": "تم قطع اتصال {0} من {1}",
|
||||
"UserOnlineFromDevice": "{0} متصل عبر {1}",
|
||||
"UserPasswordChangedWithName": "تم تغيير كلمة السر للمستخدم {0}",
|
||||
"UserPolicyUpdatedWithName": "سياسة المستخدمين تم تحديثها لـ {0}",
|
||||
"UserPolicyUpdatedWithName": "تم تحديث سياسة المستخدم {0}",
|
||||
"UserStartedPlayingItemWithValues": "قام {0} ببدء تشغيل {1} على {2}",
|
||||
"UserStoppedPlayingItemWithValues": "قام {0} بإيقاف تشغيل {1} على {2}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} تم اضافتها الى مكتبة الوسائط",
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
"AppDeviceValues": "Aplicació: {0}, Dispositiu: {1}",
|
||||
"Application": "Aplicació",
|
||||
"Artists": "Artistes",
|
||||
"AuthenticationSucceededWithUserName": "{0} s'ha autenticat correctament",
|
||||
"AuthenticationSucceededWithUserName": "{0} s'ha autentificat correctament",
|
||||
"Books": "Llibres",
|
||||
"CameraImageUploadedFrom": "Una nova imatge de càmera ha sigut pujada des de {0}",
|
||||
"CameraImageUploadedFrom": "Una nova imatge de la càmera ha sigut pujada des de {0}",
|
||||
"Channels": "Canals",
|
||||
"ChapterNameValue": "Episodi {0}",
|
||||
"Collections": "Col·leccions",
|
||||
|
||||
95
Emby.Server.Implementations/Localization/Core/fil.json
Normal file
95
Emby.Server.Implementations/Localization/Core/fil.json
Normal file
@@ -0,0 +1,95 @@
|
||||
{
|
||||
"VersionNumber": "Bersyon {0}",
|
||||
"ValueSpecialEpisodeName": "Espesyal - {0}",
|
||||
"ValueHasBeenAddedToLibrary": "Naidagdag na ang {0} sa iyong media library",
|
||||
"UserStoppedPlayingItemWithValues": "Natapos ni {0} ang {1} sa {2}",
|
||||
"UserStartedPlayingItemWithValues": "Si {0} ay nagplaplay ng {1} sa {2}",
|
||||
"UserPolicyUpdatedWithName": "Ang user policy ay naiupdate para kay {0}",
|
||||
"UserPasswordChangedWithName": "Napalitan na ang password ni {0}",
|
||||
"UserOnlineFromDevice": "Si {0} ay nakakonekta galing sa {1}",
|
||||
"UserOfflineFromDevice": "Si {0} ay nadiskonekta galing sa {1}",
|
||||
"UserLockedOutWithName": "Si {0} ay nalock out",
|
||||
"UserDownloadingItemWithValues": "Nagdadownload si {0} ng {1}",
|
||||
"UserDeletedWithName": "Natanggal na is user {0}",
|
||||
"UserCreatedWithName": "Nagawa na si user {0}",
|
||||
"User": "User",
|
||||
"TvShows": "Pelikula",
|
||||
"System": "Sistema",
|
||||
"Sync": "Pag-sync",
|
||||
"SubtitlesDownloadedForItem": "Naidownload na ang subtitles {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Hindi naidownload ang subtitles {0} para sa {1}",
|
||||
"StartupEmbyServerIsLoading": "Nagloload ang Jellyfin Server. Sandaling maghintay.",
|
||||
"Songs": "Kanta",
|
||||
"Shows": "Pelikula",
|
||||
"ServerNameNeedsToBeRestarted": "Kailangan irestart ang {0}",
|
||||
"ScheduledTaskStartedWithName": "Nagsimula na ang {0}",
|
||||
"ScheduledTaskFailedWithName": "Hindi gumana and {0}",
|
||||
"ProviderValue": "Ang provider ay {0}",
|
||||
"PluginUpdatedWithName": "Naiupdate na ang {0}",
|
||||
"PluginUninstalledWithName": "Naiuninstall na ang {0}",
|
||||
"PluginInstalledWithName": "Nainstall na ang {0}",
|
||||
"Plugin": "Plugin",
|
||||
"Playlists": "Playlists",
|
||||
"Photos": "Larawan",
|
||||
"NotificationOptionVideoPlaybackStopped": "Huminto na ang pelikula",
|
||||
"NotificationOptionVideoPlayback": "Nagsimula na ang pelikula",
|
||||
"NotificationOptionUserLockedOut": "Nakalock out ang user",
|
||||
"NotificationOptionTaskFailed": "Hindi gumana ang scheduled task",
|
||||
"NotificationOptionServerRestartRequired": "Kailangan irestart ang server",
|
||||
"NotificationOptionPluginUpdateInstalled": "Naiupdate na ang plugin",
|
||||
"NotificationOptionPluginUninstalled": "Naiuninstall na ang plugin",
|
||||
"NotificationOptionPluginInstalled": "Nainstall na ang plugin",
|
||||
"NotificationOptionPluginError": "Hindi gumagana ang plugin",
|
||||
"NotificationOptionNewLibraryContent": "May bagong content na naidagdag",
|
||||
"NotificationOptionInstallationFailed": "Hindi nainstall ng mabuti",
|
||||
"NotificationOptionCameraImageUploaded": "Naiupload na ang picture",
|
||||
"NotificationOptionAudioPlaybackStopped": "Huminto na ang patugtog",
|
||||
"NotificationOptionAudioPlayback": "Nagsimula na ang patugtog",
|
||||
"NotificationOptionApplicationUpdateInstalled": "Naiupdate na ang aplikasyon",
|
||||
"NotificationOptionApplicationUpdateAvailable": "May bagong update ang aplikasyon",
|
||||
"NewVersionIsAvailable": "May bagong version ng Jellyfin Server na pwede idownload.",
|
||||
"NameSeasonUnknown": "Hindi alam ang season",
|
||||
"NameSeasonNumber": "Season {0}",
|
||||
"NameInstallFailed": "Hindi nainstall ang {0}",
|
||||
"MusicVideos": "Music video",
|
||||
"Music": "Kanta",
|
||||
"Movies": "Pelikula",
|
||||
"MixedContent": "Halo-halong content",
|
||||
"MessageServerConfigurationUpdated": "Naiupdate na ang server configuration",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "Naiupdate na ang server configuration section {0}",
|
||||
"MessageApplicationUpdatedTo": "Ang Jellyfin Server ay naiupdate to {0}",
|
||||
"MessageApplicationUpdated": "Naiupdate na ang Jellyfin Server",
|
||||
"Latest": "Pinakabago",
|
||||
"LabelRunningTimeValue": "Oras: {0}",
|
||||
"LabelIpAddressValue": "Ang IP Address ay {0}",
|
||||
"ItemRemovedWithName": "Naitanggal ang {0} sa library",
|
||||
"ItemAddedWithName": "Naidagdag ang {0} sa library",
|
||||
"Inherit": "Manahin",
|
||||
"HeaderRecordingGroups": "Pagtatalang Grupo",
|
||||
"HeaderNextUp": "Susunod",
|
||||
"HeaderLiveTV": "Live TV",
|
||||
"HeaderFavoriteSongs": "Paboritong Kanta",
|
||||
"HeaderFavoriteShows": "Paboritong Pelikula",
|
||||
"HeaderFavoriteEpisodes": "Paboritong Episodes",
|
||||
"HeaderFavoriteArtists": "Paboritong Artista",
|
||||
"HeaderFavoriteAlbums": "Paboritong Albums",
|
||||
"HeaderContinueWatching": "Ituloy Manood",
|
||||
"HeaderCameraUploads": "Camera Uploads",
|
||||
"HeaderAlbumArtists": "Artista ng Album",
|
||||
"Genres": "Kategorya",
|
||||
"Folders": "Folders",
|
||||
"Favorites": "Paborito",
|
||||
"FailedLoginAttemptWithUserName": "maling login galing {0}",
|
||||
"DeviceOnlineWithName": "nakakonekta si {0}",
|
||||
"DeviceOfflineWithName": "nadiskonekta si {0}",
|
||||
"Collections": "Koleksyon",
|
||||
"ChapterNameValue": "Kabanata {0}",
|
||||
"Channels": "Channel",
|
||||
"CameraImageUploadedFrom": "May bagong larawan na naupload galing {0}",
|
||||
"Books": "Libro",
|
||||
"AuthenticationSucceededWithUserName": "{0} na patunayan",
|
||||
"Artists": "Artista",
|
||||
"Application": "Aplikasyon",
|
||||
"AppDeviceValues": "Aplikasyon: {0}, Aparato: {1}",
|
||||
"Albums": "Albums"
|
||||
}
|
||||
1
Emby.Server.Implementations/Localization/Core/gl.json
Normal file
1
Emby.Server.Implementations/Localization/Core/gl.json
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -6,7 +6,7 @@
|
||||
"MessageApplicationUpdatedTo": "Jellyfin Server sudah diperbarui ke {0}",
|
||||
"MessageApplicationUpdated": "Jellyfin Server sudah diperbarui",
|
||||
"Latest": "Terbaru",
|
||||
"LabelIpAddressValue": "IP address: {0}",
|
||||
"LabelIpAddressValue": "Alamat IP: {0}",
|
||||
"ItemRemovedWithName": "{0} sudah dikeluarkan dari perpustakaan",
|
||||
"ItemAddedWithName": "{0} sudah dimasukkan ke dalam perpustakaan",
|
||||
"Inherit": "Warisan",
|
||||
@@ -28,5 +28,63 @@
|
||||
"Collections": "Koleksi",
|
||||
"Books": "Buku",
|
||||
"Artists": "Artis",
|
||||
"Application": "Aplikasi"
|
||||
"Application": "Aplikasi",
|
||||
"ChapterNameValue": "Bagian {0}",
|
||||
"Channels": "Saluran",
|
||||
"TvShows": "Seri TV",
|
||||
"SubtitleDownloadFailureFromForItem": "Talop gagal diunduh dari {0} untuk {1}",
|
||||
"StartupEmbyServerIsLoading": "Peladen Jellyfin sedang dimuat. Silakan coba kembali beberapa saat lagi.",
|
||||
"Songs": "Lagu",
|
||||
"Playlists": "Daftar putar",
|
||||
"NotificationOptionPluginUninstalled": "Plugin dilepas",
|
||||
"MusicVideos": "Video musik",
|
||||
"VersionNumber": "Versi {0}",
|
||||
"ValueSpecialEpisodeName": "Spesial - {0}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} telah ditambahkan ke pustaka media Anda",
|
||||
"UserStoppedPlayingItemWithValues": "{0} telah selesai memutar {1} pada {2}",
|
||||
"UserStartedPlayingItemWithValues": "{0} sedang memutar {1} pada {2}",
|
||||
"UserPolicyUpdatedWithName": "Kebijakan pengguna telah diperbarui untuk {0}",
|
||||
"UserPasswordChangedWithName": "Kata sandi telah diubah untuk pengguna {0}",
|
||||
"UserOnlineFromDevice": "{0} sedang daring dari {1}",
|
||||
"UserOfflineFromDevice": "{0} telah terputus dari {1}",
|
||||
"UserLockedOutWithName": "Pengguna {0} telah dikunci",
|
||||
"UserDownloadingItemWithValues": "{0} sedang mengunduh {1}",
|
||||
"UserDeletedWithName": "Pengguna {0} telah dihapus",
|
||||
"UserCreatedWithName": "Pengguna {0} telah dibuat",
|
||||
"User": "Pengguna",
|
||||
"System": "Sistem",
|
||||
"Sync": "Sinkron",
|
||||
"SubtitlesDownloadedForItem": "Talop telah diunduh untuk {0}",
|
||||
"Shows": "Tayangan",
|
||||
"ServerNameNeedsToBeRestarted": "{0} perlu dimuat ulang",
|
||||
"ScheduledTaskStartedWithName": "{0} dimulai",
|
||||
"ScheduledTaskFailedWithName": "{0} gagal",
|
||||
"ProviderValue": "Penyedia: {0}",
|
||||
"PluginUpdatedWithName": "{0} telah diperbarui",
|
||||
"PluginInstalledWithName": "{0} telah dipasang",
|
||||
"Plugin": "Plugin",
|
||||
"Photos": "Foto",
|
||||
"NotificationOptionUserLockedOut": "Pengguna terkunci",
|
||||
"NotificationOptionTaskFailed": "Kegagalan tugas terjadwal",
|
||||
"NotificationOptionServerRestartRequired": "Restart peladen dibutuhkan",
|
||||
"NotificationOptionPluginUpdateInstalled": "Pembaruan plugin terpasang",
|
||||
"NotificationOptionPluginInstalled": "Plugin terpasang",
|
||||
"NotificationOptionPluginError": "Kegagalan plugin",
|
||||
"NotificationOptionNewLibraryContent": "Konten baru ditambahkan",
|
||||
"NotificationOptionInstallationFailed": "Kegagalan pemasangan",
|
||||
"NotificationOptionCameraImageUploaded": "Gambar kamera terunggah",
|
||||
"NotificationOptionApplicationUpdateInstalled": "Pembaruan aplikasi terpasang",
|
||||
"NotificationOptionApplicationUpdateAvailable": "Pembaruan aplikasi tersedia",
|
||||
"NewVersionIsAvailable": "Sebuah versi baru dari Peladen Jellyfin tersedia untuk diunduh.",
|
||||
"NameSeasonUnknown": "Musim tak diketahui",
|
||||
"NameSeasonNumber": "Musim {0}",
|
||||
"NameInstallFailed": "{0} instalasi gagal",
|
||||
"Music": "Musik",
|
||||
"Movies": "Film",
|
||||
"MessageServerConfigurationUpdated": "Konfigurasi peladen telah diperbarui",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "Konfigurasi peladen bagian {0} telah diperbarui",
|
||||
"FailedLoginAttemptWithUserName": "Percobaan login gagal dari {0}",
|
||||
"CameraImageUploadedFrom": "Sebuah gambar baru telah diunggah dari {0}",
|
||||
"DeviceOfflineWithName": "{0} telah terputus",
|
||||
"DeviceOnlineWithName": "{0} telah terhubung"
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"Channels": "Canali",
|
||||
"ChapterNameValue": "Capitolo {0}",
|
||||
"Collections": "Collezioni",
|
||||
"DeviceOfflineWithName": "{0} ha disconnesso",
|
||||
"DeviceOfflineWithName": "{0} si è disconnesso",
|
||||
"DeviceOnlineWithName": "{0} è connesso",
|
||||
"FailedLoginAttemptWithUserName": "Tentativo di accesso fallito da {0}",
|
||||
"Favorites": "Preferiti",
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
"ItemRemovedWithName": "{0} a fost eliminat din bibliotecă",
|
||||
"ItemAddedWithName": "{0} a fost adăugat în bibliotecă",
|
||||
"Inherit": "Moștenit",
|
||||
"HomeVideos": "Videoclipuri personale",
|
||||
"HomeVideos": "Filme personale",
|
||||
"HeaderRecordingGroups": "Grupuri de înregistrare",
|
||||
"HeaderLiveTV": "TV în Direct",
|
||||
"HeaderFavoriteSongs": "Melodii Favorite",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"DeviceOfflineWithName": "{0} je prekinil povezavo",
|
||||
"DeviceOnlineWithName": "{0} je povezan",
|
||||
"FailedLoginAttemptWithUserName": "Neuspešen poskus prijave z {0}",
|
||||
"Favorites": "Priljubljeni",
|
||||
"Favorites": "Priljubljeno",
|
||||
"Folders": "Mape",
|
||||
"Genres": "Zvrsti",
|
||||
"HeaderAlbumArtists": "Izvajalci albuma",
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
"SubtitlesDownloadedForItem": "已为 {0} 下载了字幕",
|
||||
"Sync": "同步",
|
||||
"System": "系统",
|
||||
"TvShows": "电视节目",
|
||||
"TvShows": "电视剧",
|
||||
"User": "用户",
|
||||
"UserCreatedWithName": "用户 {0} 已创建",
|
||||
"UserDeletedWithName": "用户 {0} 已删除",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using MediaBrowser.Model.Net;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Net.WebSockets;
|
||||
using MediaBrowser.Model.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Emby.Server.Implementations.Net
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Emby.Server.Implementations.Images;
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the task to be executed
|
||||
/// Returns the task to be executed.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <param name="progress">The progress.</param>
|
||||
@@ -89,7 +89,6 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
SourceTypes = new SourceType[] { SourceType.Library },
|
||||
HasChapterImages = false,
|
||||
IsVirtualItem = false
|
||||
|
||||
})
|
||||
.OfType<Video>()
|
||||
.ToList();
|
||||
@@ -160,7 +159,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
}
|
||||
}
|
||||
|
||||
public string Name => "Chapter image extraction";
|
||||
public string Name => "Extract Chapter Images";
|
||||
|
||||
public string Description => "Creates thumbnails for videos that have chapters.";
|
||||
|
||||
|
||||
@@ -158,9 +158,9 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
public string Name => "Cache file cleanup";
|
||||
public string Name => "Clean Cache Directory";
|
||||
|
||||
public string Description => "Deletes cache files no longer needed by the system";
|
||||
public string Description => "Deletes cache files no longer needed by the system.";
|
||||
|
||||
public string Category => "Maintenance";
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ using MediaBrowser.Model.Tasks;
|
||||
namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||
{
|
||||
/// <summary>
|
||||
/// Deletes old log files
|
||||
/// Deletes old log files.
|
||||
/// </summary>
|
||||
public class DeleteLogFileTask : IScheduledTask, IConfigurableScheduledTask
|
||||
{
|
||||
@@ -33,20 +33,18 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the triggers that define when the task will run
|
||||
/// Creates the triggers that define when the task will run.
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable{BaseTaskTrigger}.</returns>
|
||||
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
|
||||
{
|
||||
return new[] {
|
||||
|
||||
// Every so often
|
||||
new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the task to be executed
|
||||
/// Returns the task to be executed.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <param name="progress">The progress.</param>
|
||||
@@ -81,7 +79,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public string Name => "Log file cleanup";
|
||||
public string Name => "Clean Log Directory";
|
||||
|
||||
public string Description => string.Format("Deletes log files that are more than {0} days old.", ConfigurationManager.CommonConfiguration.LogFileRetentionDays);
|
||||
|
||||
|
||||
@@ -125,9 +125,9 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
public string Name => "Transcode file cleanup";
|
||||
public string Name => "Clean Transcode Directory";
|
||||
|
||||
public string Description => "Deletes transcode files more than 24 hours old.";
|
||||
public string Description => "Deletes transcode files more than one day old.";
|
||||
|
||||
public string Category => "Maintenance";
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@ using MediaBrowser.Model.Tasks;
|
||||
namespace Emby.Server.Implementations.ScheduledTasks
|
||||
{
|
||||
/// <summary>
|
||||
/// Class PeopleValidationTask
|
||||
/// Class PeopleValidationTask.
|
||||
/// </summary>
|
||||
public class PeopleValidationTask : IScheduledTask
|
||||
{
|
||||
/// <summary>
|
||||
/// The _library manager
|
||||
/// The library manager.
|
||||
/// </summary>
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
@@ -32,13 +32,12 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the triggers that define when the task will run
|
||||
/// Creates the triggers that define when the task will run.
|
||||
/// </summary>
|
||||
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
// Every so often
|
||||
new TaskTriggerInfo
|
||||
{
|
||||
Type = TaskTriggerInfo.TriggerInterval,
|
||||
@@ -48,7 +47,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the task to be executed
|
||||
/// Returns the task to be executed.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <param name="progress">The progress.</param>
|
||||
@@ -58,7 +57,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
return _libraryManager.ValidatePeople(cancellationToken, progress);
|
||||
}
|
||||
|
||||
public string Name => "Refresh people";
|
||||
public string Name => "Refresh People";
|
||||
|
||||
public string Description => "Updates metadata for actors and directors in your media library.";
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => "Check for plugin updates";
|
||||
public string Name => "Update Plugins";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => "Downloads and installs updates for plugins that are configured to update automatically.";
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
return ((LibraryManager)_libraryManager).ValidateMediaLibraryInternal(progress, cancellationToken);
|
||||
}
|
||||
|
||||
public string Name => "Scan media library";
|
||||
public string Name => "Scan Media Library";
|
||||
|
||||
public string Description => "Scans your media library for new files and refreshes metadata.";
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
||||
namespace Emby.Server.Implementations.Serialization
|
||||
@@ -12,13 +11,15 @@ namespace Emby.Server.Implementations.Serialization
|
||||
/// </summary>
|
||||
public class JsonSerializer : IJsonSerializer
|
||||
{
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
public JsonSerializer(
|
||||
IFileSystem fileSystem)
|
||||
public JsonSerializer()
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
Configure();
|
||||
ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.DateHandler.ISO8601;
|
||||
ServiceStack.Text.JsConfig.ExcludeTypeInfo = true;
|
||||
ServiceStack.Text.JsConfig.IncludeNullValues = false;
|
||||
ServiceStack.Text.JsConfig.AlwaysUseUtc = true;
|
||||
ServiceStack.Text.JsConfig.AssumeUtc = true;
|
||||
|
||||
ServiceStack.Text.JsConfig<Guid>.SerializeFn = SerializeGuid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -81,7 +82,7 @@ namespace Emby.Server.Implementations.Serialization
|
||||
throw new ArgumentNullException(nameof(file));
|
||||
}
|
||||
|
||||
using (var stream = _fileSystem.GetFileStream(file, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
|
||||
using (var stream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
SerializeToStream(obj, stream);
|
||||
}
|
||||
@@ -162,7 +163,6 @@ namespace Emby.Server.Implementations.Serialization
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
|
||||
return ServiceStack.Text.JsonSerializer.DeserializeFromStreamAsync<T>(stream);
|
||||
}
|
||||
|
||||
@@ -225,20 +225,6 @@ namespace Emby.Server.Implementations.Serialization
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures this instance.
|
||||
/// </summary>
|
||||
private void Configure()
|
||||
{
|
||||
ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.DateHandler.ISO8601;
|
||||
ServiceStack.Text.JsConfig.ExcludeTypeInfo = true;
|
||||
ServiceStack.Text.JsConfig.IncludeNullValues = false;
|
||||
ServiceStack.Text.JsConfig.AlwaysUseUtc = true;
|
||||
ServiceStack.Text.JsConfig.AssumeUtc = true;
|
||||
|
||||
ServiceStack.Text.JsConfig<Guid>.SerializeFn = SerializeGuid;
|
||||
}
|
||||
|
||||
private static string SerializeGuid(Guid guid)
|
||||
{
|
||||
if (guid.Equals(Guid.Empty))
|
||||
|
||||
@@ -1704,7 +1704,7 @@ namespace Emby.Server.Implementations.Session
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Error getting {0} image info", ex, type);
|
||||
_logger.LogError(ex, "Error getting image information for {Type}", type);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Services;
|
||||
|
||||
public sealed class HttpPostedFile : IDisposable
|
||||
{
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Emby.Server.Implementations.HttpServer;
|
||||
using Emby.Server.Implementations.Net;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Model.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Model.Net;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
Reference in New Issue
Block a user