Merged with latest master
This commit is contained in:
commit
fcd1b2f0e4
6
.vscode/launch.json
vendored
6
.vscode/launch.json
vendored
|
@ -11,7 +11,11 @@
|
|||
"cwd": "${workspaceFolder}/Jellyfin.Server",
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false,
|
||||
"internalConsoleOptions": "openOnSessionStart"
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"serverReadyAction": {
|
||||
"action": "openExternally",
|
||||
"pattern": "Overriding address\\(es\\) \\'(https?:\\S+)\\'",
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Launch (nowebclient)",
|
||||
|
|
|
@ -103,6 +103,7 @@
|
|||
- [sl1288](https://github.com/sl1288)
|
||||
- [sorinyo2004](https://github.com/sorinyo2004)
|
||||
- [sparky8251](https://github.com/sparky8251)
|
||||
- [spookbits](https://github.com/spookbits)
|
||||
- [stanionascu](https://github.com/stanionascu)
|
||||
- [stevehayles](https://github.com/stevehayles)
|
||||
- [SuperSandro2000](https://github.com/SuperSandro2000)
|
||||
|
|
|
@ -881,7 +881,10 @@ namespace Emby.Dlna.PlayTo
|
|||
return null;
|
||||
}
|
||||
|
||||
mediaSource = await _mediaSourceManager.GetMediaSource(Item, MediaSourceId, LiveStreamId, false, cancellationToken).ConfigureAwait(false);
|
||||
if (_mediaSourceManager != null)
|
||||
{
|
||||
mediaSource = await _mediaSourceManager.GetMediaSource(Item, MediaSourceId, LiveStreamId, false, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return mediaSource;
|
||||
}
|
||||
|
|
|
@ -235,13 +235,13 @@ namespace Emby.Dlna.Server
|
|||
.Append(SecurityElement.Escape(service.ServiceId ?? string.Empty))
|
||||
.Append("</serviceId>");
|
||||
builder.Append("<SCPDURL>")
|
||||
.Append(BuildUrl(service.ScpdUrl))
|
||||
.Append(BuildUrl(service.ScpdUrl, true))
|
||||
.Append("</SCPDURL>");
|
||||
builder.Append("<controlURL>")
|
||||
.Append(BuildUrl(service.ControlUrl))
|
||||
.Append(BuildUrl(service.ControlUrl, true))
|
||||
.Append("</controlURL>");
|
||||
builder.Append("<eventSubURL>")
|
||||
.Append(BuildUrl(service.EventSubUrl))
|
||||
.Append(BuildUrl(service.EventSubUrl, true))
|
||||
.Append("</eventSubURL>");
|
||||
|
||||
builder.Append("</service>");
|
||||
|
@ -250,7 +250,13 @@ namespace Emby.Dlna.Server
|
|||
builder.Append("</serviceList>");
|
||||
}
|
||||
|
||||
private string BuildUrl(string url)
|
||||
/// <summary>
|
||||
/// Builds a valid url for inclusion in the xml.
|
||||
/// </summary>
|
||||
/// <param name="url">Url to include.</param>
|
||||
/// <param name="absoluteUrl">Optional. When set to true, the absolute url is always used.</param>
|
||||
/// <returns>The url to use for the element.</returns>
|
||||
private string BuildUrl(string url, bool absoluteUrl = false)
|
||||
{
|
||||
if (string.IsNullOrEmpty(url))
|
||||
{
|
||||
|
@ -261,7 +267,7 @@ namespace Emby.Dlna.Server
|
|||
|
||||
url = "/dlna/" + _serverUdn + "/" + url;
|
||||
|
||||
if (EnableAbsoluteUrls)
|
||||
if (EnableAbsoluteUrls || absoluteUrl)
|
||||
{
|
||||
url = _serverAddress.TrimEnd('/') + url;
|
||||
}
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
using System;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Emby.Server.Implementations.Browser
|
||||
{
|
||||
/// <summary>
|
||||
/// Assists in opening application URLs in an external browser.
|
||||
/// </summary>
|
||||
public static class BrowserLauncher
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens the home page of the web client.
|
||||
/// </summary>
|
||||
/// <param name="appHost">The app host.</param>
|
||||
public static void OpenWebApp(IServerApplicationHost appHost)
|
||||
{
|
||||
TryOpenUrl(appHost, "/web/index.html");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the swagger API page.
|
||||
/// </summary>
|
||||
/// <param name="appHost">The app host.</param>
|
||||
public static void OpenSwaggerPage(IServerApplicationHost appHost)
|
||||
{
|
||||
TryOpenUrl(appHost, "/api-docs/swagger");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the specified URL in an external browser window. Any exceptions will be logged, but ignored.
|
||||
/// </summary>
|
||||
/// <param name="appHost">The application host.</param>
|
||||
/// <param name="relativeUrl">The URL to open, relative to the server base URL.</param>
|
||||
private static void TryOpenUrl(IServerApplicationHost appHost, string relativeUrl)
|
||||
{
|
||||
try
|
||||
{
|
||||
string baseUrl = appHost.GetLocalApiUrl("localhost");
|
||||
appHost.LaunchUrl(baseUrl + relativeUrl);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var logger = appHost.Resolve<ILogger<IServerApplicationHost>>();
|
||||
logger?.LogError(ex, "Failed to open browser window with URL {URL}", relativeUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2263,7 +2263,6 @@ namespace Emby.Server.Implementations.Data
|
|||
return query.IncludeItemTypes.Contains("Trailer", StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
|
||||
private static readonly HashSet<string> _artistExcludeParentTypes = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"Series",
|
||||
|
@ -3291,7 +3290,6 @@ namespace Emby.Server.Implementations.Data
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
var isReturningZeroItems = query.Limit.HasValue && query.Limit <= 0;
|
||||
|
||||
var statementTexts = new List<string>();
|
||||
|
@ -6006,7 +6004,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the chapter.
|
||||
/// </summary>
|
||||
|
|
|
@ -468,7 +468,6 @@ namespace Emby.Server.Implementations.Dto
|
|||
IncludeItemTypes = new[] { typeof(MusicAlbum).Name },
|
||||
Name = item.Album,
|
||||
Limit = 1
|
||||
|
||||
});
|
||||
|
||||
if (parentAlbumIds.Count > 0)
|
||||
|
@ -1139,6 +1138,7 @@ namespace Emby.Server.Implementations.Dto
|
|||
if (episodeSeries != null)
|
||||
{
|
||||
dto.SeriesPrimaryImageTag = GetTagAndFillBlurhash(dto, episodeSeries, ImageType.Primary);
|
||||
AttachPrimaryImageAspectRatio(dto, episodeSeries);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1185,6 +1185,7 @@ namespace Emby.Server.Implementations.Dto
|
|||
if (series != null)
|
||||
{
|
||||
dto.SeriesPrimaryImageTag = GetTagAndFillBlurhash(dto, series, ImageType.Primary);
|
||||
AttachPrimaryImageAspectRatio(dto, series);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1431,7 +1432,7 @@ namespace Emby.Server.Implementations.Dto
|
|||
return null;
|
||||
}
|
||||
|
||||
return width / height;
|
||||
return (double)width / height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
using System.Threading.Tasks;
|
||||
using Emby.Server.Implementations.Browser;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Extensions;
|
||||
using MediaBrowser.Controller.Plugins;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Emby.Server.Implementations.EntryPoints
|
||||
{
|
||||
/// <summary>
|
||||
/// Class StartupWizard.
|
||||
/// </summary>
|
||||
public sealed class StartupWizard : IServerEntryPoint
|
||||
{
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
private readonly IConfiguration _appConfig;
|
||||
private readonly IServerConfigurationManager _config;
|
||||
private readonly IStartupOptions _startupOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StartupWizard"/> class.
|
||||
/// </summary>
|
||||
/// <param name="appHost">The application host.</param>
|
||||
/// <param name="appConfig">The application configuration.</param>
|
||||
/// <param name="config">The configuration manager.</param>
|
||||
/// <param name="startupOptions">The application startup options.</param>
|
||||
public StartupWizard(
|
||||
IServerApplicationHost appHost,
|
||||
IConfiguration appConfig,
|
||||
IServerConfigurationManager config,
|
||||
IStartupOptions startupOptions)
|
||||
{
|
||||
_appHost = appHost;
|
||||
_appConfig = appConfig;
|
||||
_config = config;
|
||||
_startupOptions = startupOptions;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task RunAsync()
|
||||
{
|
||||
Run();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void Run()
|
||||
{
|
||||
if (!_appHost.CanLaunchWebBrowser)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Always launch the startup wizard if possible when it has not been completed
|
||||
if (!_config.Configuration.IsStartupWizardCompleted && _appConfig.HostWebClient())
|
||||
{
|
||||
BrowserLauncher.OpenWebApp(_appHost);
|
||||
return;
|
||||
}
|
||||
|
||||
// Do nothing if the web app is configured to not run automatically
|
||||
if (!_config.Configuration.AutoRunWebApp || _startupOptions.NoAutoRunWebApp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Launch the swagger page if the web client is not hosted, otherwise open the web client
|
||||
if (_appConfig.HostWebClient())
|
||||
{
|
||||
BrowserLauncher.OpenWebApp(_appHost);
|
||||
}
|
||||
else
|
||||
{
|
||||
BrowserLauncher.OpenSwaggerPage(_appHost);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,7 +28,6 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||
private readonly object _syncLock = new object();
|
||||
private Timer _updateTimer;
|
||||
|
||||
|
||||
public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, IUserManager userManager)
|
||||
{
|
||||
_userDataManager = userDataManager;
|
||||
|
|
|
@ -16,11 +16,6 @@ namespace Emby.Server.Implementations
|
|||
/// </summary>
|
||||
bool IsService { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the --noautorunwebapp command line option.
|
||||
/// </summary>
|
||||
bool NoAutoRunWebApp { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the --package-name command line option.
|
||||
/// </summary>
|
||||
|
|
|
@ -874,7 +874,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
public List<Lineup> lineups { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class Headends
|
||||
{
|
||||
public string headend { get; set; }
|
||||
|
@ -886,8 +885,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
public List<Lineup> lineups { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class Map
|
||||
{
|
||||
public string stationID { get; set; }
|
||||
|
@ -971,9 +968,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
public List<string> date { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public class Rating
|
||||
{
|
||||
public string body { get; set; }
|
||||
|
@ -1017,8 +1011,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
public string isPremiereOrFinale { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class MetadataSchedule
|
||||
{
|
||||
public string modified { get; set; }
|
||||
|
|
|
@ -2135,6 +2135,7 @@ namespace Emby.Server.Implementations.LiveTv
|
|||
}
|
||||
|
||||
private bool _disposed = false;
|
||||
|
||||
/// <summary>
|
||||
/// Releases unmanaged and - optionally - managed resources.
|
||||
/// </summary>
|
||||
|
|
|
@ -563,6 +563,19 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||
|
||||
protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo info, ChannelInfo channelInfo, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken)
|
||||
{
|
||||
var tunerCount = info.TunerCount;
|
||||
|
||||
if (tunerCount > 0)
|
||||
{
|
||||
var tunerHostId = info.Id;
|
||||
var liveStreams = currentLiveStreams.Where(i => string.Equals(i.TunerHostId, tunerHostId, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (liveStreams.Count() >= tunerCount)
|
||||
{
|
||||
throw new LiveTvConflictException("HDHomeRun simultaneous stream limit has been reached.");
|
||||
}
|
||||
}
|
||||
|
||||
var profile = streamId.Split('_')[0];
|
||||
|
||||
Logger.LogInformation("GetChannelStream: channel id: {0}. stream id: {1} profile: {2}", channelInfo.Id, streamId, profile);
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
{
|
||||
"Artists": "Kunstenare",
|
||||
"Channels": "Kanale",
|
||||
"Folders": "Fouers",
|
||||
"Favorites": "Gunstelinge",
|
||||
"Folders": "Lêergidse",
|
||||
"Favorites": "Gunstellinge",
|
||||
"HeaderFavoriteShows": "Gunsteling Vertonings",
|
||||
"ValueSpecialEpisodeName": "Spesiale - {0}",
|
||||
"HeaderAlbumArtists": "Album Kunstenaars",
|
||||
"Books": "Boeke",
|
||||
"HeaderNextUp": "Volgende",
|
||||
"Movies": "Rolprente",
|
||||
"Shows": "Program",
|
||||
"HeaderContinueWatching": "Hou Aan Kyk",
|
||||
"Movies": "Flieks",
|
||||
"Shows": "Televisie Reekse",
|
||||
"HeaderContinueWatching": "Kyk Verder",
|
||||
"HeaderFavoriteEpisodes": "Gunsteling Episodes",
|
||||
"Photos": "Fotos",
|
||||
"Playlists": "Speellysse",
|
||||
"Playlists": "Snitlyste",
|
||||
"HeaderFavoriteArtists": "Gunsteling Kunstenaars",
|
||||
"HeaderFavoriteAlbums": "Gunsteling Albums",
|
||||
"Sync": "Sinkroniseer",
|
||||
|
@ -23,7 +23,7 @@
|
|||
"DeviceOfflineWithName": "{0} is ontkoppel",
|
||||
"Collections": "Versamelings",
|
||||
"Inherit": "Ontvang",
|
||||
"HeaderLiveTV": "Live TV",
|
||||
"HeaderLiveTV": "Lewendige TV",
|
||||
"Application": "Program",
|
||||
"AppDeviceValues": "App: {0}, Toestel: {1}",
|
||||
"VersionNumber": "Weergawe {0}",
|
||||
|
@ -95,5 +95,23 @@
|
|||
"TasksChannelsCategory": "Internet kanale",
|
||||
"TasksApplicationCategory": "aansoek",
|
||||
"TasksLibraryCategory": "biblioteek",
|
||||
"TasksMaintenanceCategory": "onderhoud"
|
||||
"TasksMaintenanceCategory": "onderhoud",
|
||||
"TaskCleanCacheDescription": "Vee kasregister lêers uit wat nie meer deur die stelsel benodig word nie.",
|
||||
"TaskCleanCache": "Reinig Kasgeheue Lêergids",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Soek aanlyn vir vermiste onderskrifte gebasseer op metadata verstellings.",
|
||||
"TaskDownloadMissingSubtitles": "Laai vermiste onderskrifte af",
|
||||
"TaskRefreshChannelsDescription": "Vervris internet kanaal inligting.",
|
||||
"TaskRefreshChannels": "Vervris Kanale",
|
||||
"TaskCleanTranscodeDescription": "Vee transkodering lêers uit wat ouer is as een dag.",
|
||||
"TaskCleanTranscode": "Reinig Transkoderings Leêrbinder",
|
||||
"TaskUpdatePluginsDescription": "Laai opgedateerde inprop-sagteware af en installeer inprop-sagteware wat verstel is om outomaties op te dateer.",
|
||||
"TaskUpdatePlugins": "Dateer Inprop-Sagteware Op",
|
||||
"TaskRefreshPeopleDescription": "Vervris metadata oor akteurs en regisseurs in u media versameling.",
|
||||
"TaskRefreshPeople": "Vervris Mense",
|
||||
"TaskCleanLogsDescription": "Vee loglêers wat ouer as {0} dae is uit.",
|
||||
"TaskCleanLogs": "Reinig Loglêer Lêervouer",
|
||||
"TaskRefreshLibraryDescription": "Skandeer u media versameling vir nuwe lêers en verfris metadata.",
|
||||
"TaskRefreshLibrary": "Skandeer Media Versameling",
|
||||
"TaskRefreshChapterImagesDescription": "Maak kleinkiekeis (fotos) vir films wat hoofstukke het.",
|
||||
"TaskRefreshChapterImages": "Verkry Hoofstuk Beelde"
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
"NotificationOptionCameraImageUploaded": "อัปโหลดภาพถ่ายแล้ว",
|
||||
"NotificationOptionAudioPlaybackStopped": "หยุดเล่นเสียง",
|
||||
"NotificationOptionAudioPlayback": "เริ่มเล่นเสียง",
|
||||
"NotificationOptionApplicationUpdateInstalled": "ติดตั้งการอัปเดตแอพพลิเคชันแล้ว",
|
||||
"NotificationOptionApplicationUpdateAvailable": "มีการอัปเดตแอพพลิเคชัน",
|
||||
"NotificationOptionApplicationUpdateInstalled": "ติดตั้งการอัปเดตแอปพลิเคชันแล้ว",
|
||||
"NotificationOptionApplicationUpdateAvailable": "มีการอัปเดตแอปพลิเคชัน",
|
||||
"NewVersionIsAvailable": "เวอร์ชันใหม่ของเซิร์ฟเวอร์ Jellyfin พร้อมให้ดาวน์โหลดแล้ว",
|
||||
"NameSeasonUnknown": "ไม่ทราบซีซัน",
|
||||
"NameSeasonNumber": "ซีซัน {0}",
|
||||
|
@ -65,8 +65,8 @@
|
|||
"Books": "หนังสือ",
|
||||
"AuthenticationSucceededWithUserName": "{0} ยืนยันตัวสำเร็จแล้ว",
|
||||
"Artists": "ศิลปิน",
|
||||
"Application": "แอพพลิเคชัน",
|
||||
"AppDeviceValues": "แอพ: {0}, อุปกรณ์: {1}",
|
||||
"Application": "แอปพลิเคชัน",
|
||||
"AppDeviceValues": "แอป: {0}, อุปกรณ์: {1}",
|
||||
"Albums": "อัลบั้ม",
|
||||
"ScheduledTaskStartedWithName": "{0} เริ่มต้น",
|
||||
"ScheduledTaskFailedWithName": "{0} ล้มเหลว",
|
||||
|
@ -92,7 +92,7 @@
|
|||
"TaskCleanCacheDescription": "ลบไฟล์แคชที่ระบบไม่ต้องการ",
|
||||
"TaskCleanCache": "ล้างไดเรกทอรีแคช",
|
||||
"TasksChannelsCategory": "ช่องอินเทอร์เน็ต",
|
||||
"TasksApplicationCategory": "แอพพลิเคชัน",
|
||||
"TasksApplicationCategory": "แอปพลิเคชัน",
|
||||
"TasksLibraryCategory": "ไลบรารี",
|
||||
"TasksMaintenanceCategory": "ปิดซ่อมบำรุง",
|
||||
"VersionNumber": "เวอร์ชัน {0}",
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
"ValueSpecialEpisodeName": "Đặc Biệt - {0}",
|
||||
"Albums": "Albums",
|
||||
"Artists": "Các Nghệ Sĩ",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Tìm kiếm phụ đề bị thiếu trên Internet dựa trên cấu hình thông tin chi tiết.",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Tìm kiếm phụ đề bị thiếu trên Internet dựa trên cấu hình dữ liệu mô tả.",
|
||||
"TaskDownloadMissingSubtitles": "Tải xuống phụ đề bị thiếu",
|
||||
"TaskRefreshChannelsDescription": "Làm mới thông tin kênh internet.",
|
||||
"TaskRefreshChannels": "Làm Mới Kênh",
|
||||
|
|
|
@ -155,7 +155,12 @@ namespace Emby.Server.Implementations.Updates
|
|||
var result = new List<PackageInfo>();
|
||||
foreach (RepositoryInfo repository in _config.Configuration.PluginRepositories)
|
||||
{
|
||||
result.AddRange(await GetPackages(repository.Url, cancellationToken).ConfigureAwait(true));
|
||||
foreach (var package in await GetPackages(repository.Url, cancellationToken).ConfigureAwait(true))
|
||||
{
|
||||
package.repositoryName = repository.Name;
|
||||
package.repositoryUrl = repository.Url;
|
||||
result.Add(package);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -393,6 +398,7 @@ namespace Emby.Server.Implementations.Updates
|
|||
// Ignore any exceptions.
|
||||
}
|
||||
}
|
||||
|
||||
stream.Position = 0;
|
||||
_zipClient.ExtractAllFromZip(stream, targetDir, true);
|
||||
|
||||
|
|
|
@ -292,7 +292,7 @@ namespace Jellyfin.Api.Controllers
|
|||
/// A <see cref="Task" /> that represents the asynchronous operation to get the remote search results.
|
||||
/// The task result contains an <see cref="NoContentResult"/>.
|
||||
/// </returns>
|
||||
[HttpPost("Items/RemoteSearch/Apply/{id}")]
|
||||
[HttpPost("Items/RemoteSearch/Apply/{itemId}")]
|
||||
[Authorize(Policy = Policies.RequiresElevation)]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<ActionResult> ApplySearchCriteria(
|
||||
|
|
|
@ -77,6 +77,7 @@ namespace Jellyfin.Api.Controllers
|
|||
/// <param name="name">Package name.</param>
|
||||
/// <param name="assemblyGuid">GUID of the associated assembly.</param>
|
||||
/// <param name="version">Optional version. Defaults to latest version.</param>
|
||||
/// <param name="repositoryUrl">Optional. Specify the repository to install from.</param>
|
||||
/// <response code="204">Package found.</response>
|
||||
/// <response code="404">Package not found.</response>
|
||||
/// <returns>A <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the package could not be found.</returns>
|
||||
|
@ -87,9 +88,16 @@ namespace Jellyfin.Api.Controllers
|
|||
public async Task<ActionResult> InstallPackage(
|
||||
[FromRoute, Required] string name,
|
||||
[FromQuery] string? assemblyGuid,
|
||||
[FromQuery] string? version)
|
||||
[FromQuery] string? version,
|
||||
[FromQuery] string? repositoryUrl)
|
||||
{
|
||||
var packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false);
|
||||
if (!string.IsNullOrEmpty(repositoryUrl))
|
||||
{
|
||||
packages = packages.Where(p => p.repositoryUrl.Equals(repositoryUrl, StringComparison.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
var package = _installationManager.GetCompatibleVersions(
|
||||
packages,
|
||||
name,
|
||||
|
|
|
@ -505,17 +505,17 @@ namespace Jellyfin.Api.Controllers
|
|||
/// <summary>
|
||||
/// Initiates the forgot password process for a local user.
|
||||
/// </summary>
|
||||
/// <param name="enteredUsername">The entered username.</param>
|
||||
/// <param name="forgotPasswordRequest">The forgot password request containing the entered username.</param>
|
||||
/// <response code="200">Password reset process started.</response>
|
||||
/// <returns>A <see cref="Task"/> containing a <see cref="ForgotPasswordResult"/>.</returns>
|
||||
[HttpPost("ForgotPassword")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<ForgotPasswordResult>> ForgotPassword([FromBody] string? enteredUsername)
|
||||
public async Task<ActionResult<ForgotPasswordResult>> ForgotPassword([FromBody, Required] ForgotPasswordDto forgotPasswordRequest)
|
||||
{
|
||||
var isLocal = HttpContext.IsLocal()
|
||||
|| _networkManager.IsInLocalNetwork(HttpContext.GetNormalizedRemoteIp());
|
||||
|
||||
var result = await _userManager.StartForgotPasswordProcess(enteredUsername, isLocal).ConfigureAwait(false);
|
||||
var result = await _userManager.StartForgotPasswordProcess(forgotPasswordRequest.EnteredUsername, isLocal).ConfigureAwait(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="3.1.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.8" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.5.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="5.5.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="5.6.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
16
Jellyfin.Api/Models/UserDtos/ForgotPasswordDto.cs
Normal file
16
Jellyfin.Api/Models/UserDtos/ForgotPasswordDto.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Jellyfin.Api.Models.UserDtos
|
||||
{
|
||||
/// <summary>
|
||||
/// Forgot Password request body DTO.
|
||||
/// </summary>
|
||||
public class ForgotPasswordDto
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the entered username to have its password reset.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string? EnteredUsername { get; set; }
|
||||
}
|
||||
}
|
|
@ -18,8 +18,8 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BlurHashSharp" Version="1.1.0" />
|
||||
<PackageReference Include="BlurHashSharp.SkiaSharp" Version="1.1.0" />
|
||||
<PackageReference Include="BlurHashSharp" Version="1.1.1" />
|
||||
<PackageReference Include="BlurHashSharp.SkiaSharp" Version="1.1.1" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.80.2" />
|
||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="2.80.2" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<!-- ProjectGuid is only included as a requirement for SonarQube analysis -->
|
||||
<PropertyGroup>
|
||||
|
@ -13,6 +13,7 @@
|
|||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Nullable>enable</Nullable>
|
||||
<DisableImplicitAspNetCoreAnalyzers>true</DisableImplicitAspNetCoreAnalyzers>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -23,10 +24,6 @@
|
|||
<EmbeddedResource Include="Resources/Configuration/*" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Code Analyzers-->
|
||||
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" />
|
||||
|
@ -53,7 +50,7 @@
|
|||
<PackageReference Include="Serilog.Sinks.Async" Version="1.4.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Graylog" Version="2.1.3" />
|
||||
<PackageReference Include="Serilog.Sinks.Graylog" Version="2.2.1" />
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.0.4" />
|
||||
<PackageReference Include="SQLitePCLRaw.provider.sqlite3.netstandard11" Version="1.1.14" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
"profiles": {
|
||||
"Jellyfin.Server": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:8096",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
|
@ -12,6 +14,16 @@
|
|||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"commandLineArgs": "--nowebclient"
|
||||
},
|
||||
"Jellyfin.Server (API Docs)": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "api-docs/swagger",
|
||||
"applicationUrl": "http://localhost:8096",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"commandLineArgs": "--nowebclient"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,10 +63,6 @@ namespace Jellyfin.Server
|
|||
[Option("service", Required = false, HelpText = "Run as headless service.")]
|
||||
public bool IsService { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[Option("noautorunwebapp", Required = false, HelpText = "Run headless if startup wizard is complete.")]
|
||||
public bool NoAutoRunWebApp { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[Option("package-name", Required = false, HelpText = "Used when packaging Jellyfin (example, synology).")]
|
||||
public string? PackageName { get; set; }
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace MediaBrowser.Controller.Channels
|
|||
/// Indicates if a sort ascending/descending toggle is supported or not.
|
||||
/// </summary>
|
||||
public bool SupportsSortOrderToggle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the automatic refresh levels.
|
||||
/// </summary>
|
||||
|
@ -53,6 +54,7 @@ namespace MediaBrowser.Controller.Channels
|
|||
/// </summary>
|
||||
/// <value>The daily download limit.</value>
|
||||
public int? DailyDownloadLimit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [supports downloading].
|
||||
/// </summary>
|
||||
|
|
|
@ -90,7 +90,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
|
||||
var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty;
|
||||
|
||||
|
||||
if (ParentIndexNumber.HasValue)
|
||||
{
|
||||
songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey;
|
||||
|
|
|
@ -197,6 +197,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
public virtual bool SupportsRemoteImageDownloading => true;
|
||||
|
||||
private string _name;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
|
@ -661,6 +662,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
|
||||
private string _forcedSortName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the forced sort.
|
||||
/// </summary>
|
||||
|
|
|
@ -1386,7 +1386,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the linked children.
|
||||
/// </summary>
|
||||
|
|
|
@ -21,7 +21,5 @@ namespace MediaBrowser.Controller.Entities
|
|||
List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution);
|
||||
|
||||
List<MediaStream> GetMediaStreams();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
[JsonIgnore]
|
||||
public override Folder LatestItemsIndexContainer => AlbumEntity;
|
||||
|
||||
|
||||
[JsonIgnore]
|
||||
public PhotoAlbum AlbumEntity
|
||||
{
|
||||
|
|
|
@ -450,7 +450,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
protected override bool GetBlockUnratedValue(User user)
|
||||
{
|
||||
return user.GetPreference(PreferenceKind.BlockUnratedItems).Contains(UnratedItem.Series.ToString());
|
||||
|
|
|
@ -258,7 +258,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
IncludeItemTypes = new[] { typeof(Movie).Name },
|
||||
Recursive = true,
|
||||
EnableTotalRecordCount = false
|
||||
|
||||
}).Items
|
||||
.SelectMany(i => i.Genres)
|
||||
.DistinctNames()
|
||||
|
|
|
@ -111,5 +111,4 @@ namespace MediaBrowser.Controller.IO
|
|||
return returnResult;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ namespace MediaBrowser.Controller.Library
|
|||
MusicArtist GetArtist(string name);
|
||||
|
||||
MusicArtist GetArtist(string name, DtoOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a Studio.
|
||||
/// </summary>
|
||||
|
@ -234,6 +235,7 @@ namespace MediaBrowser.Controller.Library
|
|||
/// Occurs when [item updated].
|
||||
/// </summary>
|
||||
event EventHandler<ItemChangeEventArgs> ItemUpdated;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [item removed].
|
||||
/// </summary>
|
||||
|
|
|
@ -28,12 +28,14 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <param name="itemId">The item identifier.</param>
|
||||
/// <returns>IEnumerable<MediaStream>.</returns>
|
||||
List<MediaStream> GetMediaStreams(Guid itemId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media streams.
|
||||
/// </summary>
|
||||
/// <param name="mediaSourceId">The media source identifier.</param>
|
||||
/// <returns>IEnumerable<MediaStream>.</returns>
|
||||
List<MediaStream> GetMediaStreams(string mediaSourceId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media streams.
|
||||
/// </summary>
|
||||
|
|
|
@ -156,6 +156,7 @@ namespace MediaBrowser.Controller.Library
|
|||
}
|
||||
|
||||
// REVIEW: @bond
|
||||
|
||||
/// <summary>
|
||||
/// Gets the physical locations.
|
||||
/// </summary>
|
||||
|
|
|
@ -231,6 +231,7 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
/// Saves the tuner host.
|
||||
/// </summary>
|
||||
Task<TunerHostInfo> SaveTunerHost(TunerHostInfo info, bool dataSourceChanged = true);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the listing provider.
|
||||
/// </summary>
|
||||
|
|
|
@ -56,7 +56,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken);
|
||||
|
||||
Task<List<TunerHostInfo>> DiscoverDevices(int discoveryDurationMs, CancellationToken cancellationToken);
|
||||
|
||||
}
|
||||
|
||||
public interface IConfigurableTunerHost
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
/// </summary>
|
||||
/// <value>The tuners.</value>
|
||||
public List<LiveTvTunerInfo> Tuners { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is visible.
|
||||
/// </summary>
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
/// </summary>
|
||||
/// <value>The overview.</value>
|
||||
public string Overview { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the short overview.
|
||||
/// </summary>
|
||||
|
@ -169,31 +170,37 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
/// </summary>
|
||||
/// <value>The production year.</value>
|
||||
public int? ProductionYear { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the home page URL.
|
||||
/// </summary>
|
||||
/// <value>The home page URL.</value>
|
||||
public string HomePageUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the series identifier.
|
||||
/// </summary>
|
||||
/// <value>The series identifier.</value>
|
||||
public string SeriesId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the show identifier.
|
||||
/// </summary>
|
||||
/// <value>The show identifier.</value>
|
||||
public string ShowId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the season number.
|
||||
/// </summary>
|
||||
/// <value>The season number.</value>
|
||||
public int? SeasonNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the episode number.
|
||||
/// </summary>
|
||||
/// <value>The episode number.</value>
|
||||
public int? EpisodeNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the etag.
|
||||
/// </summary>
|
||||
|
|
|
@ -187,6 +187,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 the show identifier.
|
||||
/// </summary>
|
||||
|
|
|
@ -113,6 +113,7 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
|
||||
// Program properties
|
||||
public int? SeasonNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the episode number.
|
||||
/// </summary>
|
||||
|
|
|
@ -109,7 +109,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
}
|
||||
|
||||
return _mediaEncoder.SupportsHwaccel("vaapi");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -508,6 +507,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
arg.Append("-hwaccel qsv ");
|
||||
}
|
||||
}
|
||||
|
||||
// While using SW decoder
|
||||
else
|
||||
{
|
||||
|
@ -1441,7 +1441,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
|
||||
var codec = outputAudioCodec ?? string.Empty;
|
||||
|
||||
|
||||
int? transcoderChannelLimit;
|
||||
if (codec.IndexOf("wma", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
|
@ -2511,7 +2510,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
return inputModifier;
|
||||
}
|
||||
|
||||
|
||||
public void AttachMediaSourceInfo(
|
||||
EncodingJobInfo state,
|
||||
MediaSourceInfo mediaSource,
|
||||
|
|
|
@ -697,10 +697,12 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
/// The progressive.
|
||||
/// </summary>
|
||||
Progressive,
|
||||
|
||||
/// <summary>
|
||||
/// The HLS.
|
||||
/// </summary>
|
||||
Hls,
|
||||
|
||||
/// <summary>
|
||||
/// The dash.
|
||||
/// </summary>
|
||||
|
|
|
@ -100,6 +100,7 @@ namespace MediaBrowser.Controller.Persistence
|
|||
/// <param name="query">The query.</param>
|
||||
/// <returns>IEnumerable<Guid>.</returns>
|
||||
QueryResult<Guid> GetItemIds(InternalItemsQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the items.
|
||||
/// </summary>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Model.IO;
|
||||
|
@ -11,11 +12,11 @@ namespace MediaBrowser.Controller.Providers
|
|||
{
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
private readonly Dictionary<string, FileSystemMetadata[]> _cache = new Dictionary<string, FileSystemMetadata[]>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly ConcurrentDictionary<string, FileSystemMetadata[]> _cache = new ConcurrentDictionary<string, FileSystemMetadata[]>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private readonly Dictionary<string, FileSystemMetadata> _fileCache = new Dictionary<string, FileSystemMetadata>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly ConcurrentDictionary<string, FileSystemMetadata> _fileCache = new ConcurrentDictionary<string, FileSystemMetadata>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private readonly Dictionary<string, List<string>> _filePathCache = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly ConcurrentDictionary<string, List<string>> _filePathCache = new ConcurrentDictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public DirectoryService(IFileSystem fileSystem)
|
||||
{
|
||||
|
@ -24,14 +25,7 @@ namespace MediaBrowser.Controller.Providers
|
|||
|
||||
public FileSystemMetadata[] GetFileSystemEntries(string path)
|
||||
{
|
||||
if (!_cache.TryGetValue(path, out FileSystemMetadata[] entries))
|
||||
{
|
||||
entries = _fileSystem.GetFileSystemEntries(path).ToArray();
|
||||
|
||||
_cache[path] = entries;
|
||||
}
|
||||
|
||||
return entries;
|
||||
return _cache.GetOrAdd(path, p => _fileSystem.GetFileSystemEntries(p).ToArray());
|
||||
}
|
||||
|
||||
public List<FileSystemMetadata> GetFiles(string path)
|
||||
|
@ -51,21 +45,19 @@ namespace MediaBrowser.Controller.Providers
|
|||
|
||||
public FileSystemMetadata GetFile(string path)
|
||||
{
|
||||
if (!_fileCache.TryGetValue(path, out FileSystemMetadata file))
|
||||
var result = _fileCache.GetOrAdd(path, p =>
|
||||
{
|
||||
file = _fileSystem.GetFileInfo(path);
|
||||
var file = _fileSystem.GetFileInfo(p);
|
||||
return file != null && file.Exists ? file : null;
|
||||
});
|
||||
|
||||
if (file != null && file.Exists)
|
||||
{
|
||||
_fileCache[path] = file;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
// lets not store null results in the cache
|
||||
_fileCache.TryRemove(path, out _);
|
||||
}
|
||||
|
||||
return file;
|
||||
return result;
|
||||
}
|
||||
|
||||
public IReadOnlyList<string> GetFilePaths(string path)
|
||||
|
@ -73,14 +65,12 @@ namespace MediaBrowser.Controller.Providers
|
|||
|
||||
public IReadOnlyList<string> GetFilePaths(string path, bool clearCache)
|
||||
{
|
||||
if (clearCache || !_filePathCache.TryGetValue(path, out List<string> result))
|
||||
if (clearCache)
|
||||
{
|
||||
result = _fileSystem.GetFilePaths(path).ToList();
|
||||
|
||||
_filePathCache[path] = result;
|
||||
_filePathCache.TryRemove(path, out _);
|
||||
}
|
||||
|
||||
return result;
|
||||
return _filePathCache.GetOrAdd(path, p => _fileSystem.GetFilePaths(p).ToList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace MediaBrowser.Controller.Resolvers
|
|||
/// <param name="args">The args.</param>
|
||||
/// <returns>BaseItem.</returns>
|
||||
BaseItem ResolvePath(ItemResolveArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the priority.
|
||||
/// </summary>
|
||||
|
|
|
@ -22,7 +22,6 @@ namespace MediaBrowser.Controller.Session
|
|||
private readonly ISessionManager _sessionManager;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
|
||||
private readonly object _progressLock = new object();
|
||||
private Timer _progressTimer;
|
||||
private PlaybackProgressInfo _lastProgressInfo;
|
||||
|
|
|
@ -498,7 +498,6 @@ namespace MediaBrowser.Model.Dlna
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (playMethods.Count > 0)
|
||||
{
|
||||
transcodeReasons.Clear();
|
||||
|
@ -1431,6 +1430,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case ProfileConditionValue.AudioChannels:
|
||||
{
|
||||
if (string.IsNullOrEmpty(qualifier))
|
||||
|
@ -1466,6 +1466,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case ProfileConditionValue.IsAvc:
|
||||
{
|
||||
if (!enableNonQualifiedConditions)
|
||||
|
@ -1487,6 +1488,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case ProfileConditionValue.IsAnamorphic:
|
||||
{
|
||||
if (!enableNonQualifiedConditions)
|
||||
|
@ -1508,6 +1510,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case ProfileConditionValue.IsInterlaced:
|
||||
{
|
||||
if (string.IsNullOrEmpty(qualifier))
|
||||
|
@ -1539,6 +1542,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case ProfileConditionValue.AudioProfile:
|
||||
case ProfileConditionValue.Has64BitOffsets:
|
||||
case ProfileConditionValue.PacketLength:
|
||||
|
@ -1550,6 +1554,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
// Not supported yet
|
||||
break;
|
||||
}
|
||||
|
||||
case ProfileConditionValue.RefFrames:
|
||||
{
|
||||
if (string.IsNullOrEmpty(qualifier))
|
||||
|
@ -1585,6 +1590,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case ProfileConditionValue.VideoBitDepth:
|
||||
{
|
||||
if (string.IsNullOrEmpty(qualifier))
|
||||
|
@ -1620,6 +1626,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case ProfileConditionValue.VideoProfile:
|
||||
{
|
||||
if (string.IsNullOrEmpty(qualifier))
|
||||
|
@ -1643,6 +1650,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case ProfileConditionValue.Height:
|
||||
{
|
||||
if (!enableNonQualifiedConditions)
|
||||
|
@ -1668,6 +1676,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case ProfileConditionValue.VideoBitrate:
|
||||
{
|
||||
if (!enableNonQualifiedConditions)
|
||||
|
@ -1693,6 +1702,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case ProfileConditionValue.VideoFramerate:
|
||||
{
|
||||
if (!enableNonQualifiedConditions)
|
||||
|
@ -1718,6 +1728,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case ProfileConditionValue.VideoLevel:
|
||||
{
|
||||
if (string.IsNullOrEmpty(qualifier))
|
||||
|
@ -1743,6 +1754,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case ProfileConditionValue.Width:
|
||||
{
|
||||
if (!enableNonQualifiedConditions)
|
||||
|
|
|
@ -276,7 +276,6 @@ namespace MediaBrowser.Model.Dlna
|
|||
|
||||
list.Add(new NameValuePair("SubtitleMethod", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleDeliveryMethod.ToString() : string.Empty));
|
||||
|
||||
|
||||
if (!item.IsDirectStream)
|
||||
{
|
||||
if (item.RequireNonAnamorphic)
|
||||
|
|
|
@ -429,6 +429,7 @@ namespace MediaBrowser.Model.Dto
|
|||
/// </summary>
|
||||
/// <value>The album id.</value>
|
||||
public Guid AlbumId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the album image tag.
|
||||
/// </summary>
|
||||
|
@ -599,11 +600,13 @@ namespace MediaBrowser.Model.Dto
|
|||
/// </summary>
|
||||
/// <value>The trailer count.</value>
|
||||
public int? TrailerCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the movie count.
|
||||
/// </summary>
|
||||
/// <value>The movie count.</value>
|
||||
public int? MovieCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the series count.
|
||||
/// </summary>
|
||||
|
@ -611,16 +614,19 @@ namespace MediaBrowser.Model.Dto
|
|||
public int? SeriesCount { get; set; }
|
||||
|
||||
public int? ProgramCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the episode count.
|
||||
/// </summary>
|
||||
/// <value>The episode count.</value>
|
||||
public int? EpisodeCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the song count.
|
||||
/// </summary>
|
||||
/// <value>The song count.</value>
|
||||
public int? SongCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the album count.
|
||||
/// </summary>
|
||||
|
@ -628,6 +634,7 @@ namespace MediaBrowser.Model.Dto
|
|||
public int? AlbumCount { get; set; }
|
||||
|
||||
public int? ArtistCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the music video count.
|
||||
/// </summary>
|
||||
|
@ -768,6 +775,7 @@ namespace MediaBrowser.Model.Dto
|
|||
/// </summary>
|
||||
/// <value>The timer identifier.</value>
|
||||
public string TimerId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current program.
|
||||
/// </summary>
|
||||
|
|
|
@ -451,11 +451,13 @@ namespace MediaBrowser.Model.Entities
|
|||
/// </summary>
|
||||
/// <value>The method.</value>
|
||||
public SubtitleDeliveryMethod? DeliveryMethod { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the delivery URL.
|
||||
/// </summary>
|
||||
/// <value>The delivery URL.</value>
|
||||
public string DeliveryUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is external URL.
|
||||
/// </summary>
|
||||
|
|
|
@ -11,18 +11,22 @@ namespace MediaBrowser.Model.Entities
|
|||
/// The imdb.
|
||||
/// </summary>
|
||||
Imdb = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The TMDB.
|
||||
/// </summary>
|
||||
Tmdb = 3,
|
||||
|
||||
/// <summary>
|
||||
/// The TVDB.
|
||||
/// </summary>
|
||||
Tvdb = 4,
|
||||
|
||||
/// <summary>
|
||||
/// The tvcom.
|
||||
/// </summary>
|
||||
Tvcom = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Tmdb Collection Id.
|
||||
/// </summary>
|
||||
|
|
|
@ -84,6 +84,7 @@ namespace MediaBrowser.Model.LiveTv
|
|||
/// </summary>
|
||||
/// <value><c>null</c> if [is kids] contains no value, <c>true</c> if [is kids]; otherwise, <c>false</c>.</value>
|
||||
public bool? IsKids { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is sports.
|
||||
/// </summary>
|
||||
|
|
|
@ -68,5 +68,4 @@ namespace MediaBrowser.Model.Providers
|
|||
/// <value>The type of the rating.</value>
|
||||
public RatingType RatingType { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -50,6 +50,5 @@ namespace MediaBrowser.Model.Providers
|
|||
public RemoteSearchResult AlbumArtist { get; set; }
|
||||
|
||||
public RemoteSearchResult[] Artists { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,6 +168,7 @@ namespace MediaBrowser.Model.Querying
|
|||
Studios,
|
||||
|
||||
BasicSyncInfo,
|
||||
|
||||
/// <summary>
|
||||
/// The synchronize information.
|
||||
/// </summary>
|
||||
|
|
|
@ -37,16 +37,19 @@ namespace MediaBrowser.Model.Querying
|
|||
/// </summary>
|
||||
/// <value>The fields.</value>
|
||||
public ItemFields[] Fields { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [enable images].
|
||||
/// </summary>
|
||||
/// <value><c>null</c> if [enable images] contains no value, <c>true</c> if [enable images]; otherwise, <c>false</c>.</value>
|
||||
public bool? EnableImages { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the image type limit.
|
||||
/// </summary>
|
||||
/// <value>The image type limit.</value>
|
||||
public int? ImageTypeLimit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the enable image types.
|
||||
/// </summary>
|
||||
|
|
|
@ -88,16 +88,19 @@ namespace MediaBrowser.Model.Session
|
|||
/// </summary>
|
||||
/// <value>The play method.</value>
|
||||
public PlayMethod PlayMethod { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the live stream identifier.
|
||||
/// </summary>
|
||||
/// <value>The live stream identifier.</value>
|
||||
public string LiveStreamId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the play session identifier.
|
||||
/// </summary>
|
||||
/// <value>The play session identifier.</value>
|
||||
public string PlaySessionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the repeat mode.
|
||||
/// </summary>
|
||||
|
|
|
@ -8,10 +8,12 @@ namespace MediaBrowser.Model.Sync
|
|||
/// The latest.
|
||||
/// </summary>
|
||||
Latest = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The next up.
|
||||
/// </summary>
|
||||
NextUp = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The resume.
|
||||
/// </summary>
|
||||
|
|
|
@ -14,13 +14,16 @@ namespace MediaBrowser.Model.System
|
|||
{
|
||||
/// <summary>No path to FFmpeg found.</summary>
|
||||
NotFound,
|
||||
|
||||
/// <summary>Path supplied via command line using switch --ffmpeg.</summary>
|
||||
SetByArgument,
|
||||
|
||||
/// <summary>User has supplied path via Transcoding UI page.</summary>
|
||||
Custom,
|
||||
|
||||
/// <summary>FFmpeg tool found on system $PATH.</summary>
|
||||
System
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class SystemInfo.
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace MediaBrowser.Model.Tasks
|
|||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
|
||||
bool IsHidden { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is enabled.
|
||||
/// </summary>
|
||||
|
|
|
@ -52,6 +52,16 @@ namespace MediaBrowser.Model.Updates
|
|||
/// <value>The versions.</value>
|
||||
public IReadOnlyList<VersionInfo> versions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the repository name.
|
||||
/// </summary>
|
||||
public string repositoryName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the repository url.
|
||||
/// </summary>
|
||||
public string repositoryUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PackageInfo"/> class.
|
||||
/// </summary>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.8" />
|
||||
<PackageReference Include="OptimizedPriorityQueue" Version="4.2.0" />
|
||||
<PackageReference Include="PlaylistsNET" Version="1.1.2" />
|
||||
<PackageReference Include="TvDbSharper" Version="3.2.1" />
|
||||
<PackageReference Include="TvDbSharper" Version="3.2.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
|
|
@ -198,6 +198,7 @@ namespace MediaBrowser.Providers.Music
|
|||
result.Name = reader.ReadElementContentAsString();
|
||||
break;
|
||||
}
|
||||
|
||||
case "annotation":
|
||||
{
|
||||
result.Overview = reader.ReadElementContentAsString();
|
||||
|
|
|
@ -444,6 +444,7 @@ namespace MediaBrowser.Providers.Music
|
|||
result.Title = reader.ReadElementContentAsString();
|
||||
break;
|
||||
}
|
||||
|
||||
case "date":
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
|
@ -454,17 +455,20 @@ namespace MediaBrowser.Providers.Music
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case "annotation":
|
||||
{
|
||||
result.Overview = reader.ReadElementContentAsString();
|
||||
break;
|
||||
}
|
||||
|
||||
case "release-group":
|
||||
{
|
||||
result.ReleaseGroupId = reader.GetAttribute("id");
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
|
||||
case "artist-credit":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
|
|
|
@ -57,21 +57,28 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
|||
// Process images
|
||||
try
|
||||
{
|
||||
var episodeInfo = new EpisodeInfo
|
||||
string episodeTvdbId = null;
|
||||
|
||||
if (episode.IndexNumber.HasValue && episode.ParentIndexNumber.HasValue)
|
||||
{
|
||||
IndexNumber = episode.IndexNumber.Value,
|
||||
ParentIndexNumber = episode.ParentIndexNumber.Value,
|
||||
SeriesProviderIds = series.ProviderIds,
|
||||
SeriesDisplayOrder = series.DisplayOrder
|
||||
};
|
||||
string episodeTvdbId = await _tvdbClientManager
|
||||
.GetEpisodeTvdbId(episodeInfo, language, cancellationToken).ConfigureAwait(false);
|
||||
var episodeInfo = new EpisodeInfo
|
||||
{
|
||||
IndexNumber = episode.IndexNumber.Value,
|
||||
ParentIndexNumber = episode.ParentIndexNumber.Value,
|
||||
SeriesProviderIds = series.ProviderIds,
|
||||
SeriesDisplayOrder = series.DisplayOrder
|
||||
};
|
||||
|
||||
episodeTvdbId = await _tvdbClientManager
|
||||
.GetEpisodeTvdbId(episodeInfo, language, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(episodeTvdbId))
|
||||
{
|
||||
_logger.LogError(
|
||||
"Episode {SeasonNumber}x{EpisodeNumber} not found for series {SeriesTvdbId}",
|
||||
episodeInfo.ParentIndexNumber,
|
||||
episodeInfo.IndexNumber,
|
||||
episode.ParentIndexNumber,
|
||||
episode.IndexNumber,
|
||||
series.GetProviderId(MetadataProvider.Tvdb));
|
||||
return imageResult;
|
||||
}
|
||||
|
|
|
@ -302,7 +302,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
|||
{
|
||||
Url = string.Format(CultureInfo.InvariantCulture, "https://www.youtube.com/watch?v={0}", i.Source),
|
||||
Name = i.Name
|
||||
|
||||
}).ToArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -217,7 +217,6 @@ namespace MediaBrowser.Providers.TV
|
|||
new DeleteOptions
|
||||
{
|
||||
DeleteFileLocation = true
|
||||
|
||||
},
|
||||
false);
|
||||
|
||||
|
|
|
@ -53,18 +53,19 @@ Jellyfin is a Free Software Media System that puts you in control of managing an
|
|||
For further details, please see [our documentation page](https://docs.jellyfin.org/). To receive the latest updates, get help with Jellyfin, and join the community, please visit [one of our communication channels](https://docs.jellyfin.org/general/getting-help.html). For more information about the project, please see our [about page](https://docs.jellyfin.org/general/about.html).
|
||||
|
||||
<strong>Want to get started?</strong><br/>
|
||||
Choose from <a href="https://docs.jellyfin.org/general/administration/installing.html">Prebuilt Packages</a> or <a href="https://docs.jellyfin.org/general/administration/building.html">Build from Source</a>, then see our <a href="https://docs.jellyfin.org/general/quick-start.html">quick start guide</a>.<br/>
|
||||
Check out our <a href="https://jellyfin.org/downloads">downloads page</a> or our <a href="https://docs.jellyfin.org/general/administration/installing.html">installation guide</a>, then see our <a href="https://docs.jellyfin.org/general/quick-start.html">quick start guide</a>. You can also <a href="https://docs.jellyfin.org/general/administration/building.html">build from source</a>.<br/>
|
||||
|
||||
<strong>Something not working right?</strong><br/>
|
||||
Open an <a href="https://docs.jellyfin.org/general/contributing/issues.html">Issue</a> on GitHub.<br/>
|
||||
|
||||
<strong>Want to contribute?</strong><br/>
|
||||
Check out <a href="https://docs.jellyfin.org/general/contributing/index.html">our documentation for guidelines</a>.<br/>
|
||||
Check out our <a href="https://jellyfin.org/contribute">contributing choose-your-own-adventure</a> to see where you can help, then see our <a href="https://docs.jellyfin.org/general/contributing/index.html">contributing guide</a> and our <a href="https://jellyfin.org/docs/general/community-standards">community standards</a>.<br/>
|
||||
|
||||
<strong>New idea or improvement?</strong><br/>
|
||||
Check out our <a href="https://features.jellyfin.org/?view=most-wanted">feature request hub</a>.<br/>
|
||||
|
||||
Most of the translations can be found in the web client but we have several other clients that have missing strings. Translations can be improved very easily from our <a href="https://translate.jellyfin.org/projects/jellyfin/jellyfin-core">Weblate</a> instance. Look through the following graphic to see if your native language could use some work!
|
||||
<strong>Don't see Jellyfin in your language?</strong><br/>
|
||||
Check out our <a href="https://translate.jellyfin.org">Weblate instance</a> to help translate Jellyfin and its subprojects.<br/>
|
||||
|
||||
<a href="https://translate.jellyfin.org/engage/jellyfin/?utm_source=widget">
|
||||
<img src="https://translate.jellyfin.org/widgets/jellyfin/-/jellyfin-web/multi-auto.svg" alt="Detailed Translation Status"/>
|
||||
|
|
|
@ -45,8 +45,7 @@ namespace Jellyfin.Api.Tests
|
|||
// Specify the startup command line options
|
||||
var commandLineOpts = new StartupOptions
|
||||
{
|
||||
NoWebClient = true,
|
||||
NoAutoRunWebApp = true
|
||||
NoWebClient = true
|
||||
};
|
||||
|
||||
// Use a temporary directory for the application paths
|
||||
|
|
Loading…
Reference in New Issue
Block a user