mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-20 17:14:42 +01:00
Merge branch 'master' into NetworkPR2
This commit is contained in:
@@ -98,7 +98,6 @@ using MediaBrowser.Model.System;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using MediaBrowser.Providers.Chapters;
|
||||
using MediaBrowser.Providers.Manager;
|
||||
using MediaBrowser.Providers.Plugins.TheTvdb;
|
||||
using MediaBrowser.Providers.Plugins.Tmdb;
|
||||
using MediaBrowser.Providers.Subtitles;
|
||||
using MediaBrowser.XbmcMetadata.Providers;
|
||||
@@ -531,7 +530,6 @@ namespace Emby.Server.Implementations
|
||||
ServiceCollection.AddSingleton<IJsonSerializer, JsonSerializer>();
|
||||
|
||||
ServiceCollection.AddSingleton(_fileSystemManager);
|
||||
ServiceCollection.AddSingleton<TvdbClientManager>();
|
||||
ServiceCollection.AddSingleton<TmdbClientManager>();
|
||||
|
||||
ServiceCollection.AddSingleton(NetManager);
|
||||
|
||||
@@ -634,7 +634,7 @@ namespace Emby.Server.Implementations.Channels
|
||||
{
|
||||
var channels = GetAllChannels().Where(i => i is ISupportsLatestMedia).ToArray();
|
||||
|
||||
if (query.ChannelIds.Length > 0)
|
||||
if (query.ChannelIds.Count > 0)
|
||||
{
|
||||
// Avoid implicitly captured closure
|
||||
var ids = query.ChannelIds;
|
||||
|
||||
@@ -3611,12 +3611,12 @@ namespace Emby.Server.Implementations.Data
|
||||
whereClauses.Add($"type in ({inClause})");
|
||||
}
|
||||
|
||||
if (query.ChannelIds.Length == 1)
|
||||
if (query.ChannelIds.Count == 1)
|
||||
{
|
||||
whereClauses.Add("ChannelId=@ChannelId");
|
||||
statement?.TryBind("@ChannelId", query.ChannelIds[0].ToString("N", CultureInfo.InvariantCulture));
|
||||
}
|
||||
else if (query.ChannelIds.Length > 1)
|
||||
else if (query.ChannelIds.Count > 1)
|
||||
{
|
||||
var inClause = string.Join(",", query.ChannelIds.Select(i => "'" + i.ToString("N", CultureInfo.InvariantCulture) + "'"));
|
||||
whereClauses.Add($"ChannelId in ({inClause})");
|
||||
@@ -4076,7 +4076,7 @@ namespace Emby.Server.Implementations.Data
|
||||
whereClauses.Add(clause);
|
||||
}
|
||||
|
||||
if (query.GenreIds.Length > 0)
|
||||
if (query.GenreIds.Count > 0)
|
||||
{
|
||||
var clauses = new List<string>();
|
||||
var index = 0;
|
||||
@@ -4097,7 +4097,7 @@ namespace Emby.Server.Implementations.Data
|
||||
whereClauses.Add(clause);
|
||||
}
|
||||
|
||||
if (query.Genres.Length > 0)
|
||||
if (query.Genres.Count > 0)
|
||||
{
|
||||
var clauses = new List<string>();
|
||||
var index = 0;
|
||||
|
||||
@@ -1,61 +1,38 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Jellyfin.Data.Entities;
|
||||
using Jellyfin.Data.Enums;
|
||||
using Jellyfin.Data.Events;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Devices;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Security;
|
||||
using MediaBrowser.Model.Devices;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Model.Session;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace Emby.Server.Implementations.Devices
|
||||
{
|
||||
public class DeviceManager : IDeviceManager
|
||||
{
|
||||
private readonly IMemoryCache _memoryCache;
|
||||
private readonly IJsonSerializer _json;
|
||||
private readonly IUserManager _userManager;
|
||||
private readonly IServerConfigurationManager _config;
|
||||
private readonly IAuthenticationRepository _authRepo;
|
||||
private readonly object _capabilitiesSyncLock = new object();
|
||||
private readonly ConcurrentDictionary<string, ClientCapabilities> _capabilitiesMap = new ();
|
||||
|
||||
public event EventHandler<GenericEventArgs<Tuple<string, DeviceOptions>>> DeviceOptionsUpdated;
|
||||
|
||||
public DeviceManager(
|
||||
IAuthenticationRepository authRepo,
|
||||
IJsonSerializer json,
|
||||
IUserManager userManager,
|
||||
IServerConfigurationManager config,
|
||||
IMemoryCache memoryCache)
|
||||
public DeviceManager(IAuthenticationRepository authRepo, IUserManager userManager)
|
||||
{
|
||||
_json = json;
|
||||
_userManager = userManager;
|
||||
_config = config;
|
||||
_memoryCache = memoryCache;
|
||||
_authRepo = authRepo;
|
||||
}
|
||||
|
||||
public event EventHandler<GenericEventArgs<Tuple<string, DeviceOptions>>> DeviceOptionsUpdated;
|
||||
|
||||
public void SaveCapabilities(string deviceId, ClientCapabilities capabilities)
|
||||
{
|
||||
var path = Path.Combine(GetDevicePath(deviceId), "capabilities.json");
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||
|
||||
lock (_capabilitiesSyncLock)
|
||||
{
|
||||
_memoryCache.Set(deviceId, capabilities);
|
||||
_json.SerializeToFile(capabilities, path);
|
||||
}
|
||||
_capabilitiesMap[deviceId] = capabilities;
|
||||
}
|
||||
|
||||
public void UpdateDeviceOptions(string deviceId, DeviceOptions options)
|
||||
@@ -72,32 +49,12 @@ namespace Emby.Server.Implementations.Devices
|
||||
|
||||
public ClientCapabilities GetCapabilities(string id)
|
||||
{
|
||||
if (_memoryCache.TryGetValue(id, out ClientCapabilities result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
lock (_capabilitiesSyncLock)
|
||||
{
|
||||
var path = Path.Combine(GetDevicePath(id), "capabilities.json");
|
||||
try
|
||||
{
|
||||
return _json.DeserializeFromFile<ClientCapabilities>(path) ?? new ClientCapabilities();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return new ClientCapabilities();
|
||||
return _capabilitiesMap.TryGetValue(id, out ClientCapabilities result)
|
||||
? result
|
||||
: new ClientCapabilities();
|
||||
}
|
||||
|
||||
public DeviceInfo GetDevice(string id)
|
||||
{
|
||||
return GetDevice(id, true);
|
||||
}
|
||||
|
||||
private DeviceInfo GetDevice(string id, bool includeCapabilities)
|
||||
{
|
||||
var session = _authRepo.Get(new AuthenticationInfoQuery
|
||||
{
|
||||
@@ -154,16 +111,6 @@ namespace Emby.Server.Implementations.Devices
|
||||
};
|
||||
}
|
||||
|
||||
private string GetDevicesPath()
|
||||
{
|
||||
return Path.Combine(_config.ApplicationPaths.DataPath, "devices");
|
||||
}
|
||||
|
||||
private string GetDevicePath(string id)
|
||||
{
|
||||
return Path.Combine(GetDevicesPath(), id.GetMD5().ToString("N", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
public bool CanAccessDevice(User user, string deviceId)
|
||||
{
|
||||
if (user == null)
|
||||
|
||||
@@ -1503,7 +1503,7 @@ namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
if (query.AncestorIds.Length == 0 &&
|
||||
query.ParentId.Equals(Guid.Empty) &&
|
||||
query.ChannelIds.Length == 0 &&
|
||||
query.ChannelIds.Count == 0 &&
|
||||
query.TopParentIds.Length == 0 &&
|
||||
string.IsNullOrEmpty(query.AncestorWithPresentationUniqueKey) &&
|
||||
string.IsNullOrEmpty(query.SeriesPresentationUniqueKey) &&
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
private static IEnumerable<MediaStream> GetSortedStreams(IEnumerable<MediaStream> streams, MediaStreamType type, string[] languagePreferences)
|
||||
{
|
||||
// Give some preferance to external text subs for better performance
|
||||
// Give some preference to external text subs for better performance
|
||||
return streams.Where(i => i.Type == type)
|
||||
.OrderBy(i =>
|
||||
{
|
||||
|
||||
@@ -1635,7 +1635,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);
|
||||
return new EncodedRecorder(_logger, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, _config);
|
||||
}
|
||||
|
||||
return new DirectRecorder(_logger, _httpClientFactory, _streamHelper);
|
||||
|
||||
@@ -8,7 +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.Dto;
|
||||
@@ -25,6 +27,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
private readonly IServerApplicationPaths _appPaths;
|
||||
private readonly IJsonSerializer _json;
|
||||
private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>();
|
||||
private readonly IServerConfigurationManager _serverConfigurationManager;
|
||||
|
||||
private bool _hasExited;
|
||||
private Stream _logFileStream;
|
||||
@@ -35,12 +38,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
ILogger logger,
|
||||
IMediaEncoder mediaEncoder,
|
||||
IServerApplicationPaths appPaths,
|
||||
IJsonSerializer json)
|
||||
IJsonSerializer json,
|
||||
IServerConfigurationManager serverConfigurationManager)
|
||||
{
|
||||
_logger = logger;
|
||||
_mediaEncoder = mediaEncoder;
|
||||
_appPaths = appPaths;
|
||||
_json = json;
|
||||
_serverConfigurationManager = serverConfigurationManager;
|
||||
}
|
||||
|
||||
private static bool CopySubtitles => false;
|
||||
@@ -179,15 +184,17 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
|
||||
var outputParam = string.Empty;
|
||||
|
||||
var threads = EncodingHelper.GetNumberOfThreads(null, _serverConfigurationManager.GetEncodingOptions(), null);
|
||||
var commandLineArgs = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"-i \"{0}\" {2} -map_metadata -1 -threads 0 {3}{4}{5} -y \"{1}\"",
|
||||
"-i \"{0}\" {2} -map_metadata -1 -threads {6} {3}{4}{5} -y \"{1}\"",
|
||||
inputTempFile,
|
||||
targetFile,
|
||||
videoArgs,
|
||||
GetAudioArgs(mediaSource),
|
||||
subtitleArgs,
|
||||
outputParam);
|
||||
outputParam,
|
||||
threads);
|
||||
|
||||
return inputModifier + " " + commandLineArgs;
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||
Id = newID,
|
||||
StartDate = startAt,
|
||||
EndDate = endAt,
|
||||
Name = details.titles[0].title120 ?? "Unkown",
|
||||
Name = details.titles[0].title120 ?? "Unknown",
|
||||
OfficialRating = null,
|
||||
CommunityRating = null,
|
||||
EpisodeTitle = episodeTitle,
|
||||
|
||||
@@ -197,7 +197,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
if (string.IsNullOrWhiteSpace(numberString))
|
||||
{
|
||||
// Using this as a fallback now as this leads to Problems with channels like "5 USA"
|
||||
// where 5 isnt ment to be the channel number
|
||||
// where 5 isn't ment to be the channel number
|
||||
// Check for channel number with the format from SatIp
|
||||
// #EXTINF:0,84. VOX Schweiz
|
||||
// #EXTINF:0,84.0 - VOX Schweiz
|
||||
|
||||
@@ -113,5 +113,10 @@
|
||||
"TaskCleanTranscode": "Καθαρισμός Kαταλόγου Διακωδικοποιητή",
|
||||
"TaskUpdatePluginsDescription": "Κατεβάζει και εγκαθιστά ενημερώσεις για τις προσθήκες που έχουν ρυθμιστεί για αυτόματη ενημέρωση.",
|
||||
"TaskUpdatePlugins": "Ενημέρωση Προσθηκών",
|
||||
"TaskRefreshPeopleDescription": "Ενημερώνει μεταδεδομένα για ηθοποιούς και σκηνοθέτες στην βιβλιοθήκη των πολυμέσων σας."
|
||||
"TaskRefreshPeopleDescription": "Ενημερώνει μεταδεδομένα για ηθοποιούς και σκηνοθέτες στην βιβλιοθήκη των πολυμέσων σας.",
|
||||
"TaskCleanActivityLogDescription": "Διαγράφει καταχωρήσεις απο το αρχείο καταγραφής δραστηριοτήτων παλαιότερες από την ηλικία που έχει διαμορφωθεί.",
|
||||
"TaskCleanActivityLog": "Καθαρό Αρχείο Καταγραφής Δραστηριοτήτων",
|
||||
"Undefined": "Απροσδιόριστο",
|
||||
"Forced": "Εξαναγκασμένο",
|
||||
"Default": "Προεπιλογή"
|
||||
}
|
||||
|
||||
@@ -113,5 +113,10 @@
|
||||
"TaskRefreshChannels": "רענן ערוץ",
|
||||
"TaskCleanTranscodeDescription": "מחק קבצי transcode שנוצרו מלפני יותר מיום.",
|
||||
"TaskCleanTranscode": "נקה תקיית Transcode",
|
||||
"TaskUpdatePluginsDescription": "הורד והתקן עדכונים עבור תוספים שמוגדרים לעדכון אוטומטי."
|
||||
"TaskUpdatePluginsDescription": "הורד והתקן עדכונים עבור תוספים שמוגדרים לעדכון אוטומטי.",
|
||||
"TaskCleanActivityLogDescription": "מחק רשומת פעילות הישנה יותר מהגיל המוגדר.",
|
||||
"TaskCleanActivityLog": "נקה רשומת פעילות",
|
||||
"Undefined": "לא מוגדר",
|
||||
"Forced": "כפוי",
|
||||
"Default": "ברירת מחדל"
|
||||
}
|
||||
|
||||
@@ -115,5 +115,8 @@
|
||||
"TaskRefreshChannels": "Csatornák frissítése",
|
||||
"TaskCleanTranscodeDescription": "Törli az egy napnál régebbi átkódolási fájlokat.",
|
||||
"TaskCleanActivityLogDescription": "A beállítottnál korábbi bejegyzések törlése a tevékenységnaplóból.",
|
||||
"TaskCleanActivityLog": "Tevékenységnapló törlése"
|
||||
"TaskCleanActivityLog": "Tevékenységnapló törlése",
|
||||
"Undefined": "Meghatározatlan",
|
||||
"Forced": "Kényszerített",
|
||||
"Default": "Alapértelmezett"
|
||||
}
|
||||
|
||||
@@ -113,5 +113,10 @@
|
||||
"TasksChannelsCategory": "Kanały internetowe",
|
||||
"TasksApplicationCategory": "Aplikacja",
|
||||
"TasksLibraryCategory": "Biblioteka",
|
||||
"TasksMaintenanceCategory": "Konserwacja"
|
||||
"TasksMaintenanceCategory": "Konserwacja",
|
||||
"TaskCleanActivityLogDescription": "Usuwa wpisy dziennika aktywności starsze niż skonfigurowany wiek.",
|
||||
"TaskCleanActivityLog": "Czyść dziennik aktywności",
|
||||
"Undefined": "Nieustalony",
|
||||
"Forced": "Wymuszony",
|
||||
"Default": "Domyślne"
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||
await playlist.RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(_fileSystem)) { ForceSave = true }, CancellationToken.None)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (options.ItemIdList.Length > 0)
|
||||
if (options.ItemIdList.Count > 0)
|
||||
{
|
||||
await AddToPlaylistInternal(playlist.Id, options.ItemIdList, user, new DtoOptions(false)
|
||||
{
|
||||
@@ -184,7 +184,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||
return Playlist.GetPlaylistItems(playlistMediaType, items, user, options);
|
||||
}
|
||||
|
||||
public Task AddToPlaylistAsync(Guid playlistId, ICollection<Guid> itemIds, Guid userId)
|
||||
public Task AddToPlaylistAsync(Guid playlistId, IReadOnlyCollection<Guid> itemIds, Guid userId)
|
||||
{
|
||||
var user = userId.Equals(Guid.Empty) ? null : _userManager.GetUserById(userId);
|
||||
|
||||
@@ -194,7 +194,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||
});
|
||||
}
|
||||
|
||||
private async Task AddToPlaylistInternal(Guid playlistId, ICollection<Guid> newItemIds, User user, DtoOptions options)
|
||||
private async Task AddToPlaylistInternal(Guid playlistId, IReadOnlyCollection<Guid> newItemIds, User user, DtoOptions options)
|
||||
{
|
||||
// Retrieve the existing playlist
|
||||
var playlist = _libraryManager.GetItemById(playlistId) as Playlist
|
||||
|
||||
@@ -136,7 +136,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
{
|
||||
var type = scheduledTask.ScheduledTask.GetType();
|
||||
|
||||
_logger.LogInformation("Queueing task {0}", type.Name);
|
||||
_logger.LogInformation("Queuing task {0}", type.Name);
|
||||
|
||||
lock (_taskQueue)
|
||||
{
|
||||
@@ -176,7 +176,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
||||
{
|
||||
var type = task.ScheduledTask.GetType();
|
||||
|
||||
_logger.LogInformation("Queueing task {0}", type.Name);
|
||||
_logger.LogInformation("Queuing task {0}", type.Name);
|
||||
|
||||
lock (_taskQueue)
|
||||
{
|
||||
|
||||
@@ -58,8 +58,7 @@ namespace Emby.Server.Implementations.Session
|
||||
/// <summary>
|
||||
/// The active connections.
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<string, SessionInfo> _activeConnections =
|
||||
new ConcurrentDictionary<string, SessionInfo>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly ConcurrentDictionary<string, SessionInfo> _activeConnections = new (StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private Timer _idleTimer;
|
||||
|
||||
@@ -196,7 +195,7 @@ namespace Emby.Server.Implementations.Session
|
||||
{
|
||||
if (!string.IsNullOrEmpty(info.DeviceId))
|
||||
{
|
||||
var capabilities = GetSavedCapabilities(info.DeviceId);
|
||||
var capabilities = _deviceManager.GetCapabilities(info.DeviceId);
|
||||
|
||||
if (capabilities != null)
|
||||
{
|
||||
@@ -1677,27 +1676,10 @@ namespace Emby.Server.Implementations.Session
|
||||
SessionInfo = session
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
SaveCapabilities(session.DeviceId, capabilities);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Error saving device capabilities", ex);
|
||||
}
|
||||
_deviceManager.SaveCapabilities(session.DeviceId, capabilities);
|
||||
}
|
||||
}
|
||||
|
||||
private ClientCapabilities GetSavedCapabilities(string deviceId)
|
||||
{
|
||||
return _deviceManager.GetCapabilities(deviceId);
|
||||
}
|
||||
|
||||
private void SaveCapabilities(string deviceId, ClientCapabilities capabilities)
|
||||
{
|
||||
_deviceManager.SaveCapabilities(deviceId, capabilities);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a BaseItem to a BaseItemInfo.
|
||||
/// </summary>
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.SyncPlay
|
||||
new Dictionary<Guid, ISyncPlayController>();
|
||||
|
||||
/// <summary>
|
||||
/// Lock used for accesing any group.
|
||||
/// Lock used for accessing any group.
|
||||
/// </summary>
|
||||
private readonly object _groupsLock = new object();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user