diff --git a/.ci/azure-pipelines-abi.yml b/.ci/azure-pipelines-abi.yml
index 8d0737b66c..e58a2bdc7e 100644
--- a/.ci/azure-pipelines-abi.yml
+++ b/.ci/azure-pipelines-abi.yml
@@ -7,7 +7,7 @@ parameters:
default: "ubuntu-latest"
- name: DotNetSdkVersion
type: string
- default: 5.0.103
+ default: 5.0.302
jobs:
- job: CompatibilityCheck
diff --git a/.ci/azure-pipelines-main.yml b/.ci/azure-pipelines-main.yml
index 4bc72f9eb0..d2c087c14d 100644
--- a/.ci/azure-pipelines-main.yml
+++ b/.ci/azure-pipelines-main.yml
@@ -1,7 +1,7 @@
parameters:
LinuxImage: 'ubuntu-latest'
RestoreBuildProjects: 'Jellyfin.Server/Jellyfin.Server.csproj'
- DotNetSdkVersion: 5.0.103
+ DotNetSdkVersion: 5.0.302
jobs:
- job: Build
diff --git a/.ci/azure-pipelines-test.yml b/.ci/azure-pipelines-test.yml
index 7838b3b026..7ec4cdad1d 100644
--- a/.ci/azure-pipelines-test.yml
+++ b/.ci/azure-pipelines-test.yml
@@ -10,7 +10,7 @@ parameters:
default: "tests/**/*Tests.csproj"
- name: DotNetSdkVersion
type: string
- default: 5.0.103
+ default: 5.0.302
jobs:
- job: Test
diff --git a/.ci/azure-pipelines.yml b/.ci/azure-pipelines.yml
index c028b6e3e8..4e8b6557b9 100644
--- a/.ci/azure-pipelines.yml
+++ b/.ci/azure-pipelines.yml
@@ -6,7 +6,7 @@ variables:
- name: RestoreBuildProjects
value: 'Jellyfin.Server/Jellyfin.Server.csproj'
- name: DotNetSdkVersion
- value: 5.0.103
+ value: 5.0.302
pr:
autoCancel: true
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 12f1f5ed53..5a525267a9 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -17,6 +17,7 @@ assignees: ''
- Browser: [e.g. Firefox 72, Chrome 80, Safari 13]
- Jellyfin Version: [e.g. 10.4.3, nightly 20191231]
- Playback: [Direct Play, Remux, Direct Stream, Transcode]
+ - Hardware Acceleration: [e.g. none, VAAPI, NVENC, etc.]
- Installed Plugins: [e.g. none, Fanart, Anime, etc.]
- Reverse Proxy: [e.g. none, nginx, apache, etc.]
- Base URL: [e.g. none, yes: /example]
diff --git a/.github/stale.yml b/.github/stale.yml
index 05892c44dc..cba9c33b2a 100644
--- a/.github/stale.yml
+++ b/.github/stale.yml
@@ -17,9 +17,13 @@ staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has gone 120 days without comment. To avoid abandoned issues, it will be closed in 21 days if there are no new comments.
-
+
If you're the original submitter of this issue, please comment confirming if this issue still affects you in the latest release or nightlies, or close the issue if it has been fixed. If you're another user also affected by this bug, please comment confirming so. Either action will remove the stale label.
This bot exists to prevent issues from becoming stale and forgotten. Jellyfin is always moving forward, and bugs are often fixed as side effects of other changes. We therefore ask that bug report authors remain vigilant about their issues to ensure they are closed if fixed, or re-confirmed - perhaps with fresh logs or reproduction examples - regularly. If you have any questions you can reach us on [Matrix or Social Media](https://docs.jellyfin.org/general/getting-help.html).
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false
+
+# Disable automatic closing of pull requests
+pulls:
+ daysUntilClose: false
diff --git a/.github/workflows/automation.yml b/.github/workflows/automation.yml
index 38415f1c60..20294843d5 100644
--- a/.github/workflows/automation.yml
+++ b/.github/workflows/automation.yml
@@ -26,7 +26,7 @@ jobs:
if: ${{ github.repository == 'jellyfin/jellyfin' }}
steps:
- name: Remove from 'Current Release' project
- uses: alex-page/github-project-automation-plus@v0.7.1
+ uses: alex-page/github-project-automation-plus@v0.8.1
if: (github.event.pull_request || github.event.issue.pull_request) && !contains(github.event.*.labels.*.name, 'stable backport')
continue-on-error: true
with:
@@ -35,7 +35,7 @@ jobs:
repo-token: ${{ secrets.JF_BOT_TOKEN }}
- name: Add to 'Release Next' project
- uses: alex-page/github-project-automation-plus@v0.7.1
+ uses: alex-page/github-project-automation-plus@v0.8.1
if: (github.event.pull_request || github.event.issue.pull_request) && github.event.action == 'opened'
continue-on-error: true
with:
@@ -44,7 +44,7 @@ jobs:
repo-token: ${{ secrets.JF_BOT_TOKEN }}
- name: Add to 'Current Release' project
- uses: alex-page/github-project-automation-plus@v0.7.1
+ uses: alex-page/github-project-automation-plus@v0.8.1
if: (github.event.pull_request || github.event.issue.pull_request) && !contains(github.event.*.labels.*.name, 'stable backport')
continue-on-error: true
with:
@@ -58,7 +58,7 @@ jobs:
run: echo "::set-output name=number::$(curl -s ${{ github.event.issue.comments_url }} | jq '.[] | select(.author_association == "MEMBER") | .author_association' | wc -l)"
- name: Move issue to needs triage
- uses: alex-page/github-project-automation-plus@v0.7.1
+ uses: alex-page/github-project-automation-plus@v0.8.1
if: github.event.issue.pull_request == '' && github.event.comment.author_association == 'MEMBER' && steps.member_comments.outputs.number <= 1
continue-on-error: true
with:
@@ -67,7 +67,7 @@ jobs:
repo-token: ${{ secrets.JF_BOT_TOKEN }}
- name: Add issue to triage project
- uses: alex-page/github-project-automation-plus@v0.7.1
+ uses: alex-page/github-project-automation-plus@v0.8.1
if: github.event.issue.pull_request == '' && github.event.action == 'opened'
continue-on-error: true
with:
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index b44961bf8d..c2d2aff341 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -212,3 +212,4 @@
- [Tim Hobbs](https://github.com/timhobbs)
- [SvenVandenbrande](https://github.com/SvenVandenbrande)
- [olsh](https://github.com/olsh)
+ - [gnuyent](https://github.com/gnuyent)
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000000..b899999efb
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,14 @@
+
+
+
+
+ enable
+ true
+ $(MSBuildThisFileDirectory)/jellyfin.ruleset
+
+
+
+ AllEnabledByDefault
+
+
+
diff --git a/Dockerfile b/Dockerfile
index 4e2d06b82a..0859fdc4c8 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -8,15 +8,7 @@ RUN apk add curl git zlib zlib-dev autoconf g++ make libpng-dev gifsicle alpine-
&& npm ci --no-audit --unsafe-perm \
&& mv dist /dist
-FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION} as builder
-WORKDIR /repo
-COPY . .
-ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
-# because of changes in docker and systemd we need to not build in parallel at the moment
-# see https://success.docker.com/article/how-to-reserve-resource-temporarily-unavailable-errors-due-to-tasksmax-setting
-RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="/jellyfin" --self-contained --runtime linux-x64 "-p:DebugSymbols=false;DebugType=none"
-
-FROM debian:buster-slim
+FROM debian:buster-slim as app
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
ARG DEBIAN_FRONTEND="noninteractive"
@@ -25,9 +17,6 @@ ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
# https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(Native-GPU-Support)
ENV NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
-COPY --from=builder /jellyfin /jellyfin
-COPY --from=web-builder /dist /jellyfin/jellyfin-web
-
# https://github.com/intel/compute-runtime/releases
ARG GMMLIB_VERSION=20.3.2
ARG IGC_VERSION=1.0.5435
@@ -73,6 +62,19 @@ ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
+FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION} as builder
+WORKDIR /repo
+COPY . .
+ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
+# because of changes in docker and systemd we need to not build in parallel at the moment
+# see https://success.docker.com/article/how-to-reserve-resource-temporarily-unavailable-errors-due-to-tasksmax-setting
+RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="/jellyfin" --self-contained --runtime linux-x64 "-p:DebugSymbols=false;DebugType=none"
+
+FROM app
+
+COPY --from=builder /jellyfin /jellyfin
+COPY --from=web-builder /dist /jellyfin/jellyfin-web
+
EXPOSE 8096
VOLUME /cache /config /media
ENTRYPOINT ["./jellyfin/jellyfin", \
diff --git a/Dockerfile.arm b/Dockerfile.arm
index 25a0de7db6..cc0c79c94f 100644
--- a/Dockerfile.arm
+++ b/Dockerfile.arm
@@ -13,19 +13,8 @@ RUN apk add curl git zlib zlib-dev autoconf g++ make libpng-dev gifsicle alpine-
&& npm ci --no-audit --unsafe-perm \
&& mv dist /dist
-
-FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION} as builder
-WORKDIR /repo
-COPY . .
-ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
-# Discard objs - may cause failures if exists
-RUN find . -type d -name obj | xargs -r rm -r
-# Build
-RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm "-p:DebugSymbols=false;DebugType=none"
-
-
FROM multiarch/qemu-user-static:x86_64-arm as qemu
-FROM arm32v7/debian:buster-slim
+FROM arm32v7/debian:buster-slim as app
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
ARG DEBIAN_FRONTEND="noninteractive"
@@ -61,14 +50,25 @@ RUN apt-get update \
&& chmod 777 /cache /config /media \
&& sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen
-COPY --from=builder /jellyfin /jellyfin
-COPY --from=web-builder /dist /jellyfin/jellyfin-web
-
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
+FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION} as builder
+WORKDIR /repo
+COPY . .
+ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
+# Discard objs - may cause failures if exists
+RUN find . -type d -name obj | xargs -r rm -r
+# Build
+RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm "-p:DebugSymbols=false;DebugType=none"
+
+FROM app
+
+COPY --from=builder /jellyfin /jellyfin
+COPY --from=web-builder /dist /jellyfin/jellyfin-web
+
EXPOSE 8096
VOLUME /cache /config /media
ENTRYPOINT ["./jellyfin/jellyfin", \
diff --git a/Dockerfile.arm64 b/Dockerfile.arm64
index c9f19c5a39..64367a32da 100644
--- a/Dockerfile.arm64
+++ b/Dockerfile.arm64
@@ -13,18 +13,8 @@ RUN apk add curl git zlib zlib-dev autoconf g++ make libpng-dev gifsicle alpine-
&& npm ci --no-audit --unsafe-perm \
&& mv dist /dist
-
-FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION} as builder
-WORKDIR /repo
-COPY . .
-ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
-# Discard objs - may cause failures if exists
-RUN find . -type d -name obj | xargs -r rm -r
-# Build
-RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm64 "-p:DebugSymbols=false;DebugType=none"
-
FROM multiarch/qemu-user-static:x86_64-aarch64 as qemu
-FROM arm64v8/debian:buster-slim
+FROM arm64v8/debian:buster-slim as app
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
ARG DEBIAN_FRONTEND="noninteractive"
@@ -50,14 +40,25 @@ RUN apt-get update && apt-get install --no-install-recommends --no-install-sugge
&& chmod 777 /cache /config /media \
&& sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen
-COPY --from=builder /jellyfin /jellyfin
-COPY --from=web-builder /dist /jellyfin/jellyfin-web
-
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
+FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION} as builder
+WORKDIR /repo
+COPY . .
+ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
+# Discard objs - may cause failures if exists
+RUN find . -type d -name obj | xargs -r rm -r
+# Build
+RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm64 "-p:DebugSymbols=false;DebugType=none"
+
+FROM app
+
+COPY --from=builder /jellyfin /jellyfin
+COPY --from=web-builder /dist /jellyfin/jellyfin-web
+
EXPOSE 8096
VOLUME /cache /config /media
ENTRYPOINT ["./jellyfin/jellyfin", \
diff --git a/DvdLib/DvdLib.csproj b/DvdLib/DvdLib.csproj
index 7bbd9acf82..b8301e2f27 100644
--- a/DvdLib/DvdLib.csproj
+++ b/DvdLib/DvdLib.csproj
@@ -13,7 +13,8 @@
net5.0
false
true
- true
+ AllDisabledByDefault
+ disable
diff --git a/Emby.Dlna/Configuration/DlnaOptions.cs b/Emby.Dlna/Configuration/DlnaOptions.cs
index 5ceeb55300..91fac4bef5 100644
--- a/Emby.Dlna/Configuration/DlnaOptions.cs
+++ b/Emby.Dlna/Configuration/DlnaOptions.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
#pragma warning disable CS1591
namespace Emby.Dlna.Configuration
@@ -74,7 +72,7 @@ namespace Emby.Dlna.Configuration
///
/// Gets or sets the default user account that the dlna server uses.
///
- public string DefaultUserId { get; set; }
+ public string? DefaultUserId { get; set; }
///
/// Gets or sets a value indicating whether playTo device profiles should be created.
diff --git a/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs b/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs
index 7b8c504409..9020dea994 100644
--- a/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs
+++ b/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
#pragma warning disable CS1591
using System;
@@ -140,7 +138,7 @@ namespace Emby.Dlna.ContentDirectory
///
/// The .
/// The .
- private User GetUser(DeviceProfile profile)
+ private User? GetUser(DeviceProfile profile)
{
if (!string.IsNullOrEmpty(profile.UserId))
{
diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs
index 27c5b22680..ac336e5dcc 100644
--- a/Emby.Dlna/ContentDirectory/ControlHandler.cs
+++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs
@@ -288,21 +288,14 @@ namespace Emby.Dlna.ContentDirectory
/// The xml feature list.
private static string WriteFeatureListXml()
{
- // TODO: clean this up
- var builder = new StringBuilder();
-
- builder.Append("");
- builder.Append("");
-
- builder.Append("");
- builder.Append("");
- builder.Append("");
- builder.Append("");
- builder.Append("");
-
- builder.Append("");
-
- return builder.ToString();
+ return ""
+ + ""
+ + ""
+ + ""
+ + ""
+ + ""
+ + ""
+ + "";
}
///
diff --git a/Emby.Dlna/ControlResponse.cs b/Emby.Dlna/ControlResponse.cs
index a7f2d4a73b..8b09588424 100644
--- a/Emby.Dlna/ControlResponse.cs
+++ b/Emby.Dlna/ControlResponse.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
#pragma warning disable CS1591
using System.Collections.Generic;
@@ -8,9 +6,11 @@ namespace Emby.Dlna
{
public class ControlResponse
{
- public ControlResponse()
+ public ControlResponse(string xml, bool isSuccessful)
{
Headers = new Dictionary();
+ Xml = xml;
+ IsSuccessful = isSuccessful;
}
public IDictionary Headers { get; }
diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj
index a40578e403..970c16d2e6 100644
--- a/Emby.Dlna/Emby.Dlna.csproj
+++ b/Emby.Dlna/Emby.Dlna.csproj
@@ -20,8 +20,7 @@
net5.0
false
true
- true
- enable
+ AllDisabledByDefault
@@ -31,10 +30,6 @@
-
- ../jellyfin.ruleset
-
-
diff --git a/Emby.Dlna/EventSubscriptionResponse.cs b/Emby.Dlna/EventSubscriptionResponse.cs
index 8c82dcbf68..635d2c47a1 100644
--- a/Emby.Dlna/EventSubscriptionResponse.cs
+++ b/Emby.Dlna/EventSubscriptionResponse.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
#pragma warning disable CS1591
using System.Collections.Generic;
@@ -8,8 +6,10 @@ namespace Emby.Dlna
{
public class EventSubscriptionResponse
{
- public EventSubscriptionResponse()
+ public EventSubscriptionResponse(string content, string contentType)
{
+ Content = content;
+ ContentType = contentType;
Headers = new Dictionary();
}
diff --git a/Emby.Dlna/Eventing/DlnaEventManager.cs b/Emby.Dlna/Eventing/DlnaEventManager.cs
index 2e672b886b..3c91360904 100644
--- a/Emby.Dlna/Eventing/DlnaEventManager.cs
+++ b/Emby.Dlna/Eventing/DlnaEventManager.cs
@@ -51,11 +51,7 @@ namespace Emby.Dlna.Eventing
return GetEventSubscriptionResponse(subscriptionId, requestedTimeoutString, timeoutSeconds);
}
- return new EventSubscriptionResponse
- {
- Content = string.Empty,
- ContentType = "text/plain"
- };
+ return new EventSubscriptionResponse(string.Empty, "text/plain");
}
public EventSubscriptionResponse CreateEventSubscription(string notificationType, string requestedTimeoutString, string callbackUrl)
@@ -103,20 +99,12 @@ namespace Emby.Dlna.Eventing
_subscriptions.TryRemove(subscriptionId, out _);
- return new EventSubscriptionResponse
- {
- Content = string.Empty,
- ContentType = "text/plain"
- };
+ return new EventSubscriptionResponse(string.Empty, "text/plain");
}
private EventSubscriptionResponse GetEventSubscriptionResponse(string subscriptionId, string requestedTimeoutString, int timeoutSeconds)
{
- var response = new EventSubscriptionResponse
- {
- Content = string.Empty,
- ContentType = "text/plain"
- };
+ var response = new EventSubscriptionResponse(string.Empty, "text/plain");
response.Headers["SID"] = subscriptionId;
response.Headers["TIMEOUT"] = string.IsNullOrEmpty(requestedTimeoutString) ? ("SECOND-" + timeoutSeconds.ToString(_usCulture)) : requestedTimeoutString;
diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs
index 0309926abb..5d252d8dc4 100644
--- a/Emby.Dlna/Main/DlnaEntryPoint.cs
+++ b/Emby.Dlna/Main/DlnaEntryPoint.cs
@@ -27,11 +27,9 @@ using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Net;
-using MediaBrowser.Model.System;
using Microsoft.Extensions.Logging;
using Rssdp;
using Rssdp.Infrastructure;
-using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
namespace Emby.Dlna.Main
{
@@ -204,8 +202,8 @@ namespace Emby.Dlna.Main
{
if (_communicationsServer == null)
{
- var enableMultiSocketBinding = OperatingSystem.Id == OperatingSystemId.Windows ||
- OperatingSystem.Id == OperatingSystemId.Linux;
+ var enableMultiSocketBinding = OperatingSystem.IsWindows() ||
+ OperatingSystem.IsLinux();
_communicationsServer = new SsdpCommunicationsServer(_socketFactory, _networkManager, _logger, enableMultiSocketBinding)
{
@@ -268,7 +266,12 @@ namespace Emby.Dlna.Main
try
{
- _publisher = new SsdpDevicePublisher(_communicationsServer, _networkManager, OperatingSystem.Name, Environment.OSVersion.VersionString, _config.GetDlnaConfiguration().SendOnlyMatchedHost)
+ _publisher = new SsdpDevicePublisher(
+ _communicationsServer,
+ _networkManager,
+ MediaBrowser.Common.System.OperatingSystem.Name,
+ Environment.OSVersion.VersionString,
+ _config.GetDlnaConfiguration().SendOnlyMatchedHost)
{
LogFunction = LogMessage,
SupportPnpRootDevice = false
diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs
index 6c580d15bd..11fcd81cff 100644
--- a/Emby.Dlna/PlayTo/Device.cs
+++ b/Emby.Dlna/PlayTo/Device.cs
@@ -1260,10 +1260,7 @@ namespace Emby.Dlna.PlayTo
return;
}
- PlaybackStart?.Invoke(this, new PlaybackStartEventArgs
- {
- MediaInfo = mediaInfo
- });
+ PlaybackStart?.Invoke(this, new PlaybackStartEventArgs(mediaInfo));
}
private void OnPlaybackProgress(UBaseObject mediaInfo)
@@ -1273,27 +1270,17 @@ namespace Emby.Dlna.PlayTo
return;
}
- PlaybackProgress?.Invoke(this, new PlaybackProgressEventArgs
- {
- MediaInfo = mediaInfo
- });
+ PlaybackProgress?.Invoke(this, new PlaybackProgressEventArgs(mediaInfo));
}
private void OnPlaybackStop(UBaseObject mediaInfo)
{
- PlaybackStopped?.Invoke(this, new PlaybackStoppedEventArgs
- {
- MediaInfo = mediaInfo
- });
+ PlaybackStopped?.Invoke(this, new PlaybackStoppedEventArgs(mediaInfo));
}
private void OnMediaChanged(UBaseObject old, UBaseObject newMedia)
{
- MediaChanged?.Invoke(this, new MediaChangedEventArgs
- {
- OldMediaInfo = old,
- NewMediaInfo = newMedia
- });
+ MediaChanged?.Invoke(this, new MediaChangedEventArgs(old, newMedia));
}
///
diff --git a/Emby.Dlna/PlayTo/MediaChangedEventArgs.cs b/Emby.Dlna/PlayTo/MediaChangedEventArgs.cs
index 2bc4d8cc24..0f7a524d62 100644
--- a/Emby.Dlna/PlayTo/MediaChangedEventArgs.cs
+++ b/Emby.Dlna/PlayTo/MediaChangedEventArgs.cs
@@ -1,6 +1,4 @@
-#nullable disable
-
-#pragma warning disable CS1591
+#pragma warning disable CS1591
using System;
@@ -8,6 +6,12 @@ namespace Emby.Dlna.PlayTo
{
public class MediaChangedEventArgs : EventArgs
{
+ public MediaChangedEventArgs(UBaseObject oldMediaInfo, UBaseObject newMediaInfo)
+ {
+ OldMediaInfo = oldMediaInfo;
+ NewMediaInfo = newMediaInfo;
+ }
+
public UBaseObject OldMediaInfo { get; set; }
public UBaseObject NewMediaInfo { get; set; }
diff --git a/Emby.Dlna/PlayTo/PlaybackProgressEventArgs.cs b/Emby.Dlna/PlayTo/PlaybackProgressEventArgs.cs
index c7d2b28df8..c95d8b1e84 100644
--- a/Emby.Dlna/PlayTo/PlaybackProgressEventArgs.cs
+++ b/Emby.Dlna/PlayTo/PlaybackProgressEventArgs.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
#pragma warning disable CS1591
using System;
@@ -8,6 +6,11 @@ namespace Emby.Dlna.PlayTo
{
public class PlaybackProgressEventArgs : EventArgs
{
+ public PlaybackProgressEventArgs(UBaseObject mediaInfo)
+ {
+ MediaInfo = mediaInfo;
+ }
+
public UBaseObject MediaInfo { get; set; }
}
}
diff --git a/Emby.Dlna/PlayTo/PlaybackStartEventArgs.cs b/Emby.Dlna/PlayTo/PlaybackStartEventArgs.cs
index f8a14f411f..619c861ed9 100644
--- a/Emby.Dlna/PlayTo/PlaybackStartEventArgs.cs
+++ b/Emby.Dlna/PlayTo/PlaybackStartEventArgs.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
#pragma warning disable CS1591
using System;
@@ -8,6 +6,11 @@ namespace Emby.Dlna.PlayTo
{
public class PlaybackStartEventArgs : EventArgs
{
+ public PlaybackStartEventArgs(UBaseObject mediaInfo)
+ {
+ MediaInfo = mediaInfo;
+ }
+
public UBaseObject MediaInfo { get; set; }
}
}
diff --git a/Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs b/Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs
index 6661f92ac7..d0ec250591 100644
--- a/Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs
+++ b/Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
#pragma warning disable CS1591
using System;
@@ -8,6 +6,11 @@ namespace Emby.Dlna.PlayTo
{
public class PlaybackStoppedEventArgs : EventArgs
{
+ public PlaybackStoppedEventArgs(UBaseObject mediaInfo)
+ {
+ MediaInfo = mediaInfo;
+ }
+
public UBaseObject MediaInfo { get; set; }
}
}
diff --git a/Emby.Dlna/Service/BaseControlHandler.cs b/Emby.Dlna/Service/BaseControlHandler.cs
index b3ee860f4b..581e4a2861 100644
--- a/Emby.Dlna/Service/BaseControlHandler.cs
+++ b/Emby.Dlna/Service/BaseControlHandler.cs
@@ -95,11 +95,7 @@ namespace Emby.Dlna.Service
var xml = builder.ToString().Replace("xmlns:m=", "xmlns:u=", StringComparison.Ordinal);
- var controlResponse = new ControlResponse
- {
- Xml = xml,
- IsSuccessful = true
- };
+ var controlResponse = new ControlResponse(xml, true);
controlResponse.Headers.Add("EXT", string.Empty);
diff --git a/Emby.Dlna/Service/ControlErrorHandler.cs b/Emby.Dlna/Service/ControlErrorHandler.cs
index f2b5dd9ca8..3e2cd6d2e4 100644
--- a/Emby.Dlna/Service/ControlErrorHandler.cs
+++ b/Emby.Dlna/Service/ControlErrorHandler.cs
@@ -46,11 +46,7 @@ namespace Emby.Dlna.Service
writer.WriteEndDocument();
}
- return new ControlResponse
- {
- Xml = builder.ToString(),
- IsSuccessful = false
- };
+ return new ControlResponse(builder.ToString(), false);
}
}
}
diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj
index 5c5afe1c6e..baf350c6f1 100644
--- a/Emby.Drawing/Emby.Drawing.csproj
+++ b/Emby.Drawing/Emby.Drawing.csproj
@@ -9,8 +9,7 @@
net5.0
false
true
- true
- enable
+ AllDisabledByDefault
@@ -30,8 +29,4 @@
-
- ../jellyfin.ruleset
-
-
diff --git a/Emby.Naming/AudioBook/AudioBookInfo.cs b/Emby.Naming/AudioBook/AudioBookInfo.cs
index 15702ff2ca..acd8905af6 100644
--- a/Emby.Naming/AudioBook/AudioBookInfo.cs
+++ b/Emby.Naming/AudioBook/AudioBookInfo.cs
@@ -15,7 +15,7 @@ namespace Emby.Naming.AudioBook
/// List of files composing the actual audiobook.
/// List of extra files.
/// Alternative version of files.
- public AudioBookInfo(string name, int? year, List files, List extras, List alternateVersions)
+ public AudioBookInfo(string name, int? year, IReadOnlyList files, IReadOnlyList extras, IReadOnlyList alternateVersions)
{
Name = name;
Year = year;
@@ -39,18 +39,18 @@ namespace Emby.Naming.AudioBook
/// Gets or sets the files.
///
/// The files.
- public List Files { get; set; }
+ public IReadOnlyList Files { get; set; }
///
/// Gets or sets the extras.
///
/// The extras.
- public List Extras { get; set; }
+ public IReadOnlyList Extras { get; set; }
///
/// Gets or sets the alternate versions.
///
/// The alternate versions.
- public List AlternateVersions { get; set; }
+ public IReadOnlyList AlternateVersions { get; set; }
}
}
diff --git a/Emby.Naming/AudioBook/AudioBookListResolver.cs b/Emby.Naming/AudioBook/AudioBookListResolver.cs
index ca53228903..1e4a8d2edc 100644
--- a/Emby.Naming/AudioBook/AudioBookListResolver.cs
+++ b/Emby.Naming/AudioBook/AudioBookListResolver.cs
@@ -87,7 +87,7 @@ namespace Emby.Naming.AudioBook
foreach (var audioFile in group)
{
var name = Path.GetFileNameWithoutExtension(audioFile.Path);
- if (name.Equals("audiobook") ||
+ if (name.Equals("audiobook", StringComparison.OrdinalIgnoreCase) ||
name.Contains(nameParserResult.Name, StringComparison.OrdinalIgnoreCase) ||
name.Contains(nameWithReplacedDots, StringComparison.OrdinalIgnoreCase))
{
diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs
index 22a3e8bb49..915ce42cc9 100644
--- a/Emby.Naming/Common/NamingOptions.cs
+++ b/Emby.Naming/Common/NamingOptions.cs
@@ -137,7 +137,7 @@ namespace Emby.Naming.Common
CleanStrings = new[]
{
- @"[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|cd[1-9]|r3|r5|bd5|bd|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|2160p|hrhd|hrhdtv|hddvd|bluray|blu-ray|x264|x265|h264|xvid|xvidvd|xxx|www.www|AAC|DTS|\[.*\])([ _\,\.\(\)\[\]\-]|$)",
+ @"[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|cd[1-9]|r3|r5|bd5|bd|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|2160p|hrhd|hrhdtv|hddvd|bluray|blu-ray|x264|x265|h264|h265|xvid|xvidvd|xxx|www.www|AAC|DTS|\[.*\])([ _\,\.\(\)\[\]\-]|$)",
@"(\[.*\])"
};
@@ -277,14 +277,14 @@ namespace Emby.Naming.Common
IsNamed = true
},
- new EpisodeExpression("[\\\\/\\._ \\[\\(-]([0-9]+)x([0-9]+(?:(?:[a-i]|\\.[1-9])(?![0-9]))?)([^\\\\/]*)$")
+ new EpisodeExpression(@"[\\\/\._ \[\(-]([0-9]+)x([0-9]+(?:(?:[a-i]|\.[1-9])(?![0-9]))?)([^\\\/]*)$")
{
SupportsAbsoluteEpisodeNumbers = true
},
// Not a Kodi rule as well, but below rule also causes false positives for triple-digit episode names
// [bar] Foo - 1 [baz] special case of below expression to prevent false positives with digits in the series name
- new EpisodeExpression(@".*?(\[.*?\])+.*?(?[\w\s]+?)[\s_]*-[\s_]*(?[0-9]+).*$")
+ new EpisodeExpression(@".*[\\\/]?.*?(\[.*?\])+.*?(?[-\w\s]+?)[\s_]*-[\s_]*(?[0-9]+).*$")
{
IsNamed = true
},
@@ -305,6 +305,12 @@ namespace Emby.Naming.Common
// *** End Kodi Standard Naming
+ // "Episode 16", "Episode 16 - Title"
+ new EpisodeExpression(@"[Ee]pisode (?[0-9]+)(-(?[0-9]+))?[^\\\/]*$")
+ {
+ IsNamed = true
+ },
+
new EpisodeExpression(@".*(\\|\/)[sS]?(?[0-9]+)[xX](?[0-9]+)[^\\\/]*$")
{
IsNamed = true
@@ -362,12 +368,6 @@ namespace Emby.Naming.Common
IsOptimistic = true,
IsNamed = true
},
- // "Episode 16", "Episode 16 - Title"
- new EpisodeExpression(@".*[\\\/][^\\\/]* (?[0-9]{1,3})(-(?[0-9]{2,3}))*[^\\\/]*$")
- {
- IsOptimistic = true,
- IsNamed = true
- }
};
EpisodeWithoutSeasonExpressions = new[]
diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj
index 3224ff4129..07d879e96a 100644
--- a/Emby.Naming/Emby.Naming.csproj
+++ b/Emby.Naming/Emby.Naming.csproj
@@ -1,4 +1,4 @@
-
+
@@ -9,12 +9,11 @@
net5.0
false
true
- true
true
true
true
snupkg
- enable
+ AllDisabledByDefault
@@ -50,8 +49,4 @@
-
- ../jellyfin.ruleset
-
-
diff --git a/Emby.Naming/Video/ExtraResolver.cs b/Emby.Naming/Video/ExtraResolver.cs
index 1fade985be..a32af002cc 100644
--- a/Emby.Naming/Video/ExtraResolver.cs
+++ b/Emby.Naming/Video/ExtraResolver.cs
@@ -1,6 +1,5 @@
using System;
using System.IO;
-using System.Linq;
using System.Text.RegularExpressions;
using Emby.Naming.Audio;
using Emby.Naming.Common;
diff --git a/Emby.Naming/Video/VideoListResolver.cs b/Emby.Naming/Video/VideoListResolver.cs
index 7da2dcd7a5..ed7d511a39 100644
--- a/Emby.Naming/Video/VideoListResolver.cs
+++ b/Emby.Naming/Video/VideoListResolver.cs
@@ -21,7 +21,7 @@ namespace Emby.Naming.Video
/// The naming options.
/// Indication we should consider multi-versions of content.
/// Returns enumerable of which groups files together when related.
- public static IEnumerable Resolve(List files, NamingOptions namingOptions, bool supportMultiVersion = true)
+ public static IEnumerable Resolve(IEnumerable files, NamingOptions namingOptions, bool supportMultiVersion = true)
{
var videoInfos = files
.Select(i => VideoResolver.Resolve(i.FullName, i.IsDirectory, namingOptions))
diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj
index 5a2aea6423..5edcf2f295 100644
--- a/Emby.Notifications/Emby.Notifications.csproj
+++ b/Emby.Notifications/Emby.Notifications.csproj
@@ -9,10 +9,6 @@
net5.0
false
true
- true
- enable
- AllEnabledByDefault
- ../jellyfin.ruleset
diff --git a/Emby.Notifications/NotificationEntryPoint.cs b/Emby.Notifications/NotificationEntryPoint.cs
index 7433d3c8ae..e8ae14ff22 100644
--- a/Emby.Notifications/NotificationEntryPoint.cs
+++ b/Emby.Notifications/NotificationEntryPoint.cs
@@ -77,7 +77,6 @@ namespace Emby.Notifications
{
_libraryManager.ItemAdded += OnLibraryManagerItemAdded;
_appHost.HasPendingRestartChanged += OnAppHostHasPendingRestartChanged;
- _appHost.HasUpdateAvailableChanged += OnAppHostHasUpdateAvailableChanged;
_activityManager.EntryCreated += OnActivityManagerEntryCreated;
return Task.CompletedTask;
@@ -132,25 +131,6 @@ namespace Emby.Notifications
return _config.GetConfiguration("notifications");
}
- private async void OnAppHostHasUpdateAvailableChanged(object? sender, EventArgs e)
- {
- if (!_appHost.HasUpdateAvailable)
- {
- return;
- }
-
- var type = NotificationType.ApplicationUpdateAvailable.ToString();
-
- var notification = new NotificationRequest
- {
- Description = "Please see jellyfin.org for details.",
- NotificationType = type,
- Name = _localization.GetLocalizedString("NewVersionIsAvailable")
- };
-
- await SendNotification(notification, null).ConfigureAwait(false);
- }
-
private void OnLibraryManagerItemAdded(object? sender, ItemChangeEventArgs e)
{
if (!FilterItem(e.Item))
@@ -325,7 +305,6 @@ namespace Emby.Notifications
_libraryManager.ItemAdded -= OnLibraryManagerItemAdded;
_appHost.HasPendingRestartChanged -= OnAppHostHasPendingRestartChanged;
- _appHost.HasUpdateAvailableChanged -= OnAppHostHasUpdateAvailableChanged;
_activityManager.EntryCreated -= OnActivityManagerEntryCreated;
_disposed = true;
diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj
index 2b66181599..00b2f0f94c 100644
--- a/Emby.Photos/Emby.Photos.csproj
+++ b/Emby.Photos/Emby.Photos.csproj
@@ -22,10 +22,6 @@
net5.0
false
true
- true
- enable
- AllEnabledByDefault
- ../jellyfin.ruleset
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index baf5f88fce..19542c5ae2 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -100,7 +100,6 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Prometheus.DotNetRuntime;
-using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
using WebSocketManager = Emby.Server.Implementations.HttpServer.WebSocketManager;
namespace Emby.Server.Implementations
@@ -147,13 +146,7 @@ namespace Emby.Server.Implementations
return false;
}
- if (OperatingSystem.Id == OperatingSystemId.Windows
- || OperatingSystem.Id == OperatingSystemId.Darwin)
- {
- return true;
- }
-
- return false;
+ return OperatingSystem.IsWindows() || OperatingSystem.IsMacOS();
}
}
@@ -711,7 +704,7 @@ namespace Emby.Server.Implementations
logger.LogInformation("Environment Variables: {EnvVars}", relevantEnvVars);
logger.LogInformation("Arguments: {Args}", commandLineArgs);
- logger.LogInformation("Operating system: {OS}", OperatingSystem.Name);
+ logger.LogInformation("Operating system: {OS}", MediaBrowser.Common.System.OperatingSystem.Name);
logger.LogInformation("Architecture: {Architecture}", RuntimeInformation.OSArchitecture);
logger.LogInformation("64-Bit Process: {Is64Bit}", Environment.Is64BitProcess);
logger.LogInformation("User Interactive: {IsUserInteractive}", Environment.UserInteractive);
@@ -1088,11 +1081,10 @@ namespace Emby.Server.Implementations
ItemsByNamePath = ApplicationPaths.InternalMetadataPath,
InternalMetadataPath = ApplicationPaths.InternalMetadataPath,
CachePath = ApplicationPaths.CachePath,
- OperatingSystem = OperatingSystem.Id.ToString(),
- OperatingSystemDisplayName = OperatingSystem.Name,
+ OperatingSystem = MediaBrowser.Common.System.OperatingSystem.Id.ToString(),
+ OperatingSystemDisplayName = MediaBrowser.Common.System.OperatingSystem.Name,
CanSelfRestart = CanSelfRestart,
CanLaunchWebBrowser = CanLaunchWebBrowser,
- HasUpdateAvailable = HasUpdateAvailable,
TranscodingTempPath = ConfigurationManager.GetTranscodePath(),
ServerName = FriendlyName,
LocalAddress = GetSmartApiUrl(source),
@@ -1108,16 +1100,16 @@ namespace Emby.Server.Implementations
.Select(i => new WakeOnLanInfo(i))
.ToList();
- public PublicSystemInfo GetPublicSystemInfo(IPAddress source)
+ public PublicSystemInfo GetPublicSystemInfo(IPAddress address)
{
return new PublicSystemInfo
{
Version = ApplicationVersionString,
ProductName = ApplicationProductName,
Id = SystemId,
- OperatingSystem = OperatingSystem.Id.ToString(),
+ OperatingSystem = MediaBrowser.Common.System.OperatingSystem.Id.ToString(),
ServerName = FriendlyName,
- LocalAddress = GetSmartApiUrl(source),
+ LocalAddress = GetSmartApiUrl(address),
StartupWizardCompleted = ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted
};
}
@@ -1126,7 +1118,7 @@ namespace Emby.Server.Implementations
public bool ListenWithHttps => Certificate != null && ConfigurationManager.GetNetworkConfiguration().EnableHttps;
///
- public string GetSmartApiUrl(IPAddress ipAddress, int? port = null)
+ public string GetSmartApiUrl(IPAddress remoteAddr, int? port = null)
{
// Published server ends with a /
if (!string.IsNullOrEmpty(PublishedServerUrl))
@@ -1135,7 +1127,7 @@ namespace Emby.Server.Implementations
return PublishedServerUrl.Trim('/');
}
- string smart = NetManager.GetBindInterface(ipAddress, out port);
+ string smart = NetManager.GetBindInterface(remoteAddr, out port);
// If the smartAPI doesn't start with http then treat it as a host or ip.
if (smart.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
@@ -1198,14 +1190,14 @@ namespace Emby.Server.Implementations
}
///
- public string GetLocalApiUrl(string host, string scheme = null, int? port = null)
+ public string GetLocalApiUrl(string hostname, string scheme = null, int? port = null)
{
// NOTE: If no BaseUrl is set then UriBuilder appends a trailing slash, but if there is no BaseUrl it does
// not. For consistency, always trim the trailing slash.
return new UriBuilder
{
Scheme = scheme ?? (ListenWithHttps ? Uri.UriSchemeHttps : Uri.UriSchemeHttp),
- Host = host,
+ Host = hostname,
Port = port ?? (ListenWithHttps ? HttpsPort : HttpPort),
Path = ConfigurationManager.GetNetworkConfiguration().BaseUrl
}.ToString().TrimEnd('/');
@@ -1242,26 +1234,6 @@ namespace Emby.Server.Implementations
protected abstract void ShutdownInternal();
- public event EventHandler HasUpdateAvailableChanged;
-
- private bool _hasUpdateAvailable;
-
- public bool HasUpdateAvailable
- {
- get => _hasUpdateAvailable;
- set
- {
- var fireEvent = value && !_hasUpdateAvailable;
-
- _hasUpdateAvailable = value;
-
- if (fireEvent)
- {
- HasUpdateAvailableChanged?.Invoke(this, EventArgs.Empty);
- }
- }
- }
-
public IEnumerable GetApiPluginAssemblies()
{
var assemblies = _allConcreteTypes
diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs
index 82d80fc83c..08acd17672 100644
--- a/Emby.Server.Implementations/Collections/CollectionManager.cs
+++ b/Emby.Server.Implementations/Collections/CollectionManager.cs
@@ -82,12 +82,10 @@ namespace Emby.Server.Implementations.Collections
internal async Task EnsureLibraryFolder(string path, bool createIfNeeded)
{
- var existingFolders = FindFolders(path)
- .ToList();
-
- if (existingFolders.Count > 0)
+ var existingFolder = FindFolders(path).FirstOrDefault();
+ if (existingFolder != null)
{
- return existingFolders[0];
+ return existingFolder;
}
if (!createIfNeeded)
@@ -164,7 +162,7 @@ namespace Emby.Server.Implementations.Collections
DateCreated = DateTime.UtcNow
};
- parentFolder.AddChild(collection, CancellationToken.None);
+ parentFolder.AddChild(collection);
if (options.ItemIdList.Count > 0)
{
diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index 9c90de1eda..4c9e058212 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -24,11 +24,11 @@
-
+
-
+
@@ -44,12 +44,13 @@
net5.0
false
true
- true
- enable
AD0001
- AllEnabledByDefault
- ../jellyfin.ruleset
+ false
+
+
+
+ true
diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs
index ca028a3ca2..7c3c7da230 100644
--- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs
+++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs
@@ -11,7 +11,6 @@ using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.System;
using Microsoft.Extensions.Logging;
-using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
namespace Emby.Server.Implementations.IO
{
@@ -24,7 +23,7 @@ namespace Emby.Server.Implementations.IO
private readonly List _shortcutHandlers = new List();
private readonly string _tempPath;
- private static readonly bool _isEnvironmentCaseInsensitive = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+ private static readonly bool _isEnvironmentCaseInsensitive = OperatingSystem.IsWindows();
public ManagedFileSystem(
ILogger logger,
@@ -402,7 +401,7 @@ namespace Emby.Server.Implementations.IO
public virtual void SetHidden(string path, bool isHidden)
{
- if (OperatingSystem.Id != OperatingSystemId.Windows)
+ if (!OperatingSystem.IsWindows())
{
return;
}
@@ -426,7 +425,7 @@ namespace Emby.Server.Implementations.IO
public virtual void SetAttributes(string path, bool isHidden, bool isReadOnly)
{
- if (OperatingSystem.Id != OperatingSystemId.Windows)
+ if (!OperatingSystem.IsWindows())
{
return;
}
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index d806373329..13fb8b2fd5 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -2540,9 +2540,10 @@ namespace Emby.Server.Implementations.Library
{
episodeInfo = resolver.Resolve(episode.Path, isFolder, null, null, isAbsoluteNaming);
// Resolve from parent folder if it's not the Season folder
- if (episodeInfo == null && episode.Parent.GetType() == typeof(Folder))
+ var parent = episode.GetParent();
+ if (episodeInfo == null && parent.GetType() == typeof(Folder))
{
- episodeInfo = resolver.Resolve(episode.Parent.Path, true, null, null, isAbsoluteNaming);
+ episodeInfo = resolver.Resolve(parent.Path, true, null, null, isAbsoluteNaming);
if (episodeInfo != null)
{
// add the container
diff --git a/Emby.Server.Implementations/Localization/Core/ar.json b/Emby.Server.Implementations/Localization/Core/ar.json
index 3d6e159b13..be629c8a42 100644
--- a/Emby.Server.Implementations/Localization/Core/ar.json
+++ b/Emby.Server.Implementations/Localization/Core/ar.json
@@ -118,5 +118,7 @@
"TaskCleanActivityLog": "حذف سجل الأنشطة",
"Default": "الإعدادات الافتراضية",
"Undefined": "غير معرف",
- "Forced": "ملحقة"
+ "Forced": "ملحقة",
+ "TaskOptimizeDatabaseDescription": "يضغط قاعدة البيانات ويقتطع المساحة الحرة. تشغيل هذه المهمة بعد فحص المكتبة أو إجراء تغييرات أخرى تشير ضمنًا إلى أن تعديلات قاعدة البيانات قد تؤدي إلى تحسين الأداء.",
+ "TaskOptimizeDatabase": "تحسين قاعدة البيانات"
}
diff --git a/Emby.Server.Implementations/Localization/Core/bg-BG.json b/Emby.Server.Implementations/Localization/Core/bg-BG.json
index bc25531d30..f55287d15b 100644
--- a/Emby.Server.Implementations/Localization/Core/bg-BG.json
+++ b/Emby.Server.Implementations/Localization/Core/bg-BG.json
@@ -8,7 +8,7 @@
"CameraImageUploadedFrom": "Нова снимка от камера беше качена от {0}",
"Channels": "Канали",
"ChapterNameValue": "Глава {0}",
- "Collections": "Поредици",
+ "Collections": "Колекции",
"DeviceOfflineWithName": "{0} се разкачи",
"DeviceOnlineWithName": "{0} е свързан",
"FailedLoginAttemptWithUserName": "Неуспешен опит за влизане от {0}",
@@ -29,13 +29,13 @@
"Inherit": "Наследяване",
"ItemAddedWithName": "{0} е добавено към библиотеката",
"ItemRemovedWithName": "{0} е премахнато от библиотеката",
- "LabelIpAddressValue": "ИП адрес: {0}",
- "LabelRunningTimeValue": "Стартирано от: {0}",
+ "LabelIpAddressValue": "IP адрес: {0}",
+ "LabelRunningTimeValue": "Продължителност: {0}",
"Latest": "Последни",
- "MessageApplicationUpdated": "Сървърът е обновен",
- "MessageApplicationUpdatedTo": "Сървърът е обновен до {0}",
- "MessageNamedServerConfigurationUpdatedWithValue": "Секцията {0} от сървърната конфигурация се актуализира",
- "MessageServerConfigurationUpdated": "Конфигурацията на сървъра се актуализира",
+ "MessageApplicationUpdated": "Сървърът беше обновен",
+ "MessageApplicationUpdatedTo": "Сървърът беше обновен до {0}",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Секцията {0} от сървърната конфигурация беше актуализирана",
+ "MessageServerConfigurationUpdated": "Конфигурацията на сървъра беше актуализирана",
"MixedContent": "Смесено съдържание",
"Movies": "Филми",
"Music": "Музика",
@@ -118,5 +118,7 @@
"Forced": "Принудително",
"Default": "По подразбиране",
"TaskCleanActivityLogDescription": "Изтрива записите в дневника с активност по стари от конфигурираната възраст.",
- "TaskCleanActivityLog": "Изчисти дневника с активност"
+ "TaskCleanActivityLog": "Изчисти дневника с активност",
+ "TaskOptimizeDatabaseDescription": "Прави базата данни по-компактна и освобождава място. Пускането на тази задача след сканиране на библиотеката или правене на други промени, свързани с модификации на базата данни, може да подобри производителността.",
+ "TaskOptimizeDatabase": "Оптимизирай базата данни"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ca.json b/Emby.Server.Implementations/Localization/Core/ca.json
index fd8437b6d9..1b612dc716 100644
--- a/Emby.Server.Implementations/Localization/Core/ca.json
+++ b/Emby.Server.Implementations/Localization/Core/ca.json
@@ -118,5 +118,7 @@
"TaskCleanActivityLog": "Buidar Registre d'Activitat",
"Undefined": "Indefinit",
"Forced": "Forçat",
- "Default": "Defecto"
+ "Default": "Defecto",
+ "TaskOptimizeDatabaseDescription": "Compacta la base de dades i trunca l'espai lliure. Executar aquesta tasca després d’escanejar la biblioteca o fer altres canvis que impliquin modificacions a la base de dades pot millorar el rendiment.",
+ "TaskOptimizeDatabase": "Optimitzar la base de dades"
}
diff --git a/Emby.Server.Implementations/Localization/Core/cs.json b/Emby.Server.Implementations/Localization/Core/cs.json
index ff14c1929c..62b2b6328c 100644
--- a/Emby.Server.Implementations/Localization/Core/cs.json
+++ b/Emby.Server.Implementations/Localization/Core/cs.json
@@ -118,5 +118,7 @@
"TaskCleanActivityLog": "Smazat záznam aktivity",
"Undefined": "Nedefinované",
"Forced": "Vynucené",
- "Default": "Výchozí"
+ "Default": "Výchozí",
+ "TaskOptimizeDatabaseDescription": "Zmenší databázi a odstraní prázdné místo. Spuštění této úlohy po skenování knihovny či jiných změnách databáze může zlepšit výkon.",
+ "TaskOptimizeDatabase": "Optimalizovat databázi"
}
diff --git a/Emby.Server.Implementations/Localization/Core/da.json b/Emby.Server.Implementations/Localization/Core/da.json
index 3453507d9e..b2c484a31e 100644
--- a/Emby.Server.Implementations/Localization/Core/da.json
+++ b/Emby.Server.Implementations/Localization/Core/da.json
@@ -118,5 +118,7 @@
"TaskCleanActivityLog": "Ryd Aktivitetslog",
"Undefined": "Udefineret",
"Forced": "Tvunget",
- "Default": "Standard"
+ "Default": "Standard",
+ "TaskOptimizeDatabaseDescription": "Kompakter database og forkorter fri plads. Ved at køre denne proces efter at scanne biblioteket eller efter at ændre noget som kunne have indflydelse på databasen, kan forbedre ydeevne.",
+ "TaskOptimizeDatabase": "Optimér database"
}
diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json
index 9d82b58784..c924e5c150 100644
--- a/Emby.Server.Implementations/Localization/Core/de.json
+++ b/Emby.Server.Implementations/Localization/Core/de.json
@@ -3,7 +3,7 @@
"AppDeviceValues": "App: {0}, Gerät: {1}",
"Application": "Anwendung",
"Artists": "Interpreten",
- "AuthenticationSucceededWithUserName": "{0} wurde angemeldet",
+ "AuthenticationSucceededWithUserName": "{0} erfolgreich authentifiziert",
"Books": "Bücher",
"CameraImageUploadedFrom": "Ein neues Kamerafoto wurde von {0} hochgeladen",
"Channels": "Kanäle",
@@ -16,7 +16,7 @@
"Folders": "Verzeichnisse",
"Genres": "Genres",
"HeaderAlbumArtists": "Album-Interpreten",
- "HeaderContinueWatching": "Fortsetzen",
+ "HeaderContinueWatching": "Weiterschauen",
"HeaderFavoriteAlbums": "Lieblingsalben",
"HeaderFavoriteArtists": "Lieblings-Interpreten",
"HeaderFavoriteEpisodes": "Lieblingsepisoden",
@@ -118,5 +118,7 @@
"TaskCleanActivityLog": "Aktivitätsprotokoll aufräumen",
"Undefined": "Undefiniert",
"Forced": "Erzwungen",
- "Default": "Standard"
+ "Default": "Standard",
+ "TaskOptimizeDatabaseDescription": "Komprimiert die Datenbank und trimmt den freien Speicherplatz. Die Ausführung dieser Aufgabe nach dem Scannen der Bibliothek oder nach anderen Änderungen, die Datenbankänderungen implizieren, kann die Leistung verbessern.",
+ "TaskOptimizeDatabase": "Datenbank optimieren"
}
diff --git a/Emby.Server.Implementations/Localization/Core/en-GB.json b/Emby.Server.Implementations/Localization/Core/en-GB.json
index 7667612b90..8b2e8b6b1c 100644
--- a/Emby.Server.Implementations/Localization/Core/en-GB.json
+++ b/Emby.Server.Implementations/Localization/Core/en-GB.json
@@ -118,5 +118,7 @@
"TaskCleanActivityLog": "Clean Activity Log",
"Undefined": "Undefined",
"Forced": "Forced",
- "Default": "Default"
+ "Default": "Default",
+ "TaskOptimizeDatabaseDescription": "Compacts database and truncates free space. Running this task after scanning the library or doing other changes that imply database modifications might improve performance.",
+ "TaskOptimizeDatabase": "Optimise database"
}
diff --git a/Emby.Server.Implementations/Localization/Core/es-AR.json b/Emby.Server.Implementations/Localization/Core/es-AR.json
index 0d4a14be00..6321f695c4 100644
--- a/Emby.Server.Implementations/Localization/Core/es-AR.json
+++ b/Emby.Server.Implementations/Localization/Core/es-AR.json
@@ -118,5 +118,7 @@
"TaskCleanActivityLog": "Borrar log de actividades",
"Undefined": "Indefinido",
"Forced": "Forzado",
- "Default": "Por Defecto"
+ "Default": "Por Defecto",
+ "TaskOptimizeDatabaseDescription": "Compacta la base de datos y restaura el espacio libre. Ejecutar esta tarea después de actualizar las librerías o realizar otros cambios que impliquen modificar las bases de datos puede mejorar la performance.",
+ "TaskOptimizeDatabase": "Optimización de base de datos"
}
diff --git a/Emby.Server.Implementations/Localization/Core/es.json b/Emby.Server.Implementations/Localization/Core/es.json
index 91939843fa..7d42182b0c 100644
--- a/Emby.Server.Implementations/Localization/Core/es.json
+++ b/Emby.Server.Implementations/Localization/Core/es.json
@@ -70,7 +70,7 @@
"ScheduledTaskFailedWithName": "{0} falló",
"ScheduledTaskStartedWithName": "{0} iniciada",
"ServerNameNeedsToBeRestarted": "{0} necesita ser reiniciado",
- "Shows": "Series de Televisión",
+ "Shows": "Series",
"Songs": "Canciones",
"StartupEmbyServerIsLoading": "Jellyfin Server se está cargando. Vuelve a intentarlo en breve.",
"SubtitleDownloadFailureForItem": "Error al descargar subtítulos para {0}",
diff --git a/Emby.Server.Implementations/Localization/Core/es_419.json b/Emby.Server.Implementations/Localization/Core/es_419.json
index 6d2a5c7ac0..a968c6daba 100644
--- a/Emby.Server.Implementations/Localization/Core/es_419.json
+++ b/Emby.Server.Implementations/Localization/Core/es_419.json
@@ -117,5 +117,7 @@
"TaskCleanActivityLog": "Limpiar Registro de Actividades",
"Undefined": "Sin definir",
"Forced": "Forzado",
- "Default": "Por Defecto"
+ "Default": "Por Defecto",
+ "TaskOptimizeDatabaseDescription": "Compacta la base de datos y restaura el espacio libre. Ejecutar esta tarea después de actualizar las librerías o realizar otros cambios que impliquen modificar las bases de datos puede mejorar la performance.",
+ "TaskOptimizeDatabase": "Optimización de base de datos"
}
diff --git a/Emby.Server.Implementations/Localization/Core/fi.json b/Emby.Server.Implementations/Localization/Core/fi.json
index 633968d26d..4a1f4f1d52 100644
--- a/Emby.Server.Implementations/Localization/Core/fi.json
+++ b/Emby.Server.Implementations/Localization/Core/fi.json
@@ -117,5 +117,7 @@
"Default": "Oletus",
"TaskCleanActivityLogDescription": "Poistaa määritettyä ikää vanhemmat tapahtumat toimintahistoriasta.",
"TaskCleanActivityLog": "Tyhjennä toimintahistoria",
- "Undefined": "Määrittelemätön"
+ "Undefined": "Määrittelemätön",
+ "TaskOptimizeDatabaseDescription": "Tiivistää ja puhdistaa tietokannan. Tämän toiminnon suorittaminen kirjastojen skannauksen tai muiden tietokantaan liittyvien muutoksien jälkeen voi parantaa suorituskykyä.",
+ "TaskOptimizeDatabase": "Optimoi tietokanta"
}
diff --git a/Emby.Server.Implementations/Localization/Core/fr.json b/Emby.Server.Implementations/Localization/Core/fr.json
index ce1493be8a..0e4c38425c 100644
--- a/Emby.Server.Implementations/Localization/Core/fr.json
+++ b/Emby.Server.Implementations/Localization/Core/fr.json
@@ -118,5 +118,7 @@
"TaskCleanActivityLog": "Nettoyer le journal d'activité",
"Undefined": "Non défini",
"Forced": "Forcé",
- "Default": "Par défaut"
+ "Default": "Par défaut",
+ "TaskOptimizeDatabaseDescription": "Réduit les espaces vides/inutiles et compacte la base de données. Utiliser cette fonction après une mise à jour de la bibliothèque ou toute autre modification de la base de données peut améliorer les performances du serveur.",
+ "TaskOptimizeDatabase": "Optimiser la base de données"
}
diff --git a/Emby.Server.Implementations/Localization/Core/gl.json b/Emby.Server.Implementations/Localization/Core/gl.json
index 0398e1c9e5..afb22ab472 100644
--- a/Emby.Server.Implementations/Localization/Core/gl.json
+++ b/Emby.Server.Implementations/Localization/Core/gl.json
@@ -88,5 +88,34 @@
"NotificationOptionVideoPlaybackStopped": "Reproducción de vídeo parada",
"NotificationOptionVideoPlayback": "Reproducción de vídeo iniciada",
"NotificationOptionUserLockedOut": "Usuario bloqueado",
- "NotificationOptionTaskFailed": "Falla na tarefa axendada"
+ "NotificationOptionTaskFailed": "Falla na tarefa axendada",
+ "TaskCleanTranscodeDescription": "Borra os arquivos de transcode anteriores a un día.",
+ "TaskCleanTranscode": "Limpar Directorio de Transcode",
+ "UserStoppedPlayingItemWithValues": "{0} rematou de reproducir {1} en {2}",
+ "UserStartedPlayingItemWithValues": "{0} está reproducindo {1} en {2}",
+ "TaskDownloadMissingSubtitlesDescription": "Busca en internet por subtítulos que faltan baseado na configuración de metadatos.",
+ "TaskDownloadMissingSubtitles": "Descargar subtítulos que faltan",
+ "TaskRefreshChannelsDescription": "Refresca a información do canle de internet.",
+ "TaskRefreshChannels": "Refrescar Canles",
+ "TaskUpdatePluginsDescription": "Descarga e instala actualizacións para plugins que están configurados para actualizarse automáticamente.",
+ "TaskRefreshPeopleDescription": "Actualiza os metadatos dos actores e directores na túa libraría multimedia.",
+ "TaskRefreshPeople": "Refrescar Persoas",
+ "TaskCleanLogsDescription": "Borra arquivos de rexistro que son mais antigos que {0} días.",
+ "TaskRefreshLibraryDescription": "Escanea a tua libraría multimedia buscando novos arquivos e refrescando os metadatos.",
+ "TaskRefreshLibrary": "Escanear Libraría Multimedia",
+ "TaskRefreshChapterImagesDescription": "Crea previsualizacións para videos que teñen capítulos.",
+ "TaskRefreshChapterImages": "Extraer Imaxes dos Capítulos",
+ "TaskCleanCacheDescription": "Borra ficheiros da caché que xa non son necesarios para o sistema.",
+ "TaskCleanCache": "Limpa Directorio de Caché",
+ "TaskCleanActivityLogDescription": "Borra as entradas no rexistro de actividade anteriores á data configurada.",
+ "TasksApplicationCategory": "Aplicación",
+ "ValueSpecialEpisodeName": "Especial - {0}",
+ "ValueHasBeenAddedToLibrary": "{0} foi engadido a túa libraría multimedia",
+ "TasksLibraryCategory": "Libraría",
+ "TasksMaintenanceCategory": "Mantemento",
+ "VersionNumber": "Versión {0}",
+ "UserPolicyUpdatedWithName": "A política de usuario foi actualizada para {0}",
+ "UserPasswordChangedWithName": "Cambiouse o contrasinal para o usuario {0}",
+ "UserOnlineFromDevice": "{0} está en liña desde {1}",
+ "UserOfflineFromDevice": "{0} desconectouse desde {1}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/hu.json b/Emby.Server.Implementations/Localization/Core/hu.json
index 85848fed60..255d5427a6 100644
--- a/Emby.Server.Implementations/Localization/Core/hu.json
+++ b/Emby.Server.Implementations/Localization/Core/hu.json
@@ -118,5 +118,7 @@
"TaskCleanActivityLog": "Tevékenységnapló törlése",
"Undefined": "Meghatározatlan",
"Forced": "Kényszerített",
- "Default": "Alapértelmezett"
+ "Default": "Alapértelmezett",
+ "TaskOptimizeDatabaseDescription": "Tömöríti az adatbázist és csonkolja a szabad helyet. A feladat futtatása a könyvtár beolvasása után, vagy egyéb, adatbázis-módosítást igénylő változtatások végrehajtása javíthatja a teljesítményt.",
+ "TaskOptimizeDatabase": "Adatbázis optimalizálása"
}
diff --git a/Emby.Server.Implementations/Localization/Core/it.json b/Emby.Server.Implementations/Localization/Core/it.json
index bd06f0a258..0bde76e744 100644
--- a/Emby.Server.Implementations/Localization/Core/it.json
+++ b/Emby.Server.Implementations/Localization/Core/it.json
@@ -70,7 +70,7 @@
"ScheduledTaskFailedWithName": "{0} fallito",
"ScheduledTaskStartedWithName": "{0} avviati",
"ServerNameNeedsToBeRestarted": "{0} deve essere riavviato",
- "Shows": "Programmi",
+ "Shows": "Serie TV",
"Songs": "Canzoni",
"StartupEmbyServerIsLoading": "Jellyfin server si sta avviando. Per favore riprova più tardi.",
"SubtitleDownloadFailureForItem": "Impossibile scaricare i sottotitoli per {0}",
@@ -118,5 +118,7 @@
"TaskCleanActivityLogDescription": "Elimina gli inserimenti nel registro delle attività più vecchie dell’età configurata.",
"Undefined": "Non Definito",
"Forced": "Forzato",
- "Default": "Predefinito"
+ "Default": "Predefinito",
+ "TaskOptimizeDatabaseDescription": "Compatta Database e tronca spazi liberi. Eseguire questa azione dopo la scansione o dopo aver fatto altri cambiamenti inerenti il database potrebbe aumentarne la performance.",
+ "TaskOptimizeDatabase": "Ottimizza Database"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ja.json b/Emby.Server.Implementations/Localization/Core/ja.json
index fa0ab8b927..0d90ad31cc 100644
--- a/Emby.Server.Implementations/Localization/Core/ja.json
+++ b/Emby.Server.Implementations/Localization/Core/ja.json
@@ -117,5 +117,7 @@
"TaskCleanActivityLog": "アクティビティの履歴を消去",
"Undefined": "未定義",
"Forced": "強制",
- "Default": "デフォルト"
+ "Default": "デフォルト",
+ "TaskOptimizeDatabaseDescription": "データベースをコンパクトにして、空き領域を切り詰めます。メディアライブラリのスキャン後でこのタスクを実行するとパフォーマンスが向上する可能性があります。",
+ "TaskOptimizeDatabase": "データベースの最適化"
}
diff --git a/Emby.Server.Implementations/Localization/Core/kk.json b/Emby.Server.Implementations/Localization/Core/kk.json
index 4eee369892..1b4a18deb5 100644
--- a/Emby.Server.Implementations/Localization/Core/kk.json
+++ b/Emby.Server.Implementations/Localization/Core/kk.json
@@ -118,5 +118,7 @@
"TaskRefreshLibraryDescription": "Tasyğyşhanadağy jaña faildardy skanerleidі jäne metaderekterdı jañğyrtady.",
"TaskRefreshChapterImagesDescription": "Sahnalary bar beineler üşın nobailar jasaidy.",
"TaskCleanCacheDescription": "Jüiede qajet emes keştelgen faildardy joiady.",
- "TaskCleanActivityLogDescription": "Äreket jūrnalyndağy teñşelgen jasynan asqan jazbalary joiady."
+ "TaskCleanActivityLogDescription": "Äreket jūrnalyndağy teñşelgen jasynan asqan jazbalary joiady.",
+ "TaskOptimizeDatabaseDescription": "Derekqordy qysyp, bos oryndy qysqartady. Būl tapsyrmany tasyğyşhanany skanerlegennen keiın nemese derekqorğa meñzeitın basqa özgertuler ıstelgennen keiın oryndau önımdılıktı damytuy mümkın.",
+ "TaskOptimizeDatabase": "Derekqordy oñtailandyru"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ko.json b/Emby.Server.Implementations/Localization/Core/ko.json
index 9179bbc8de..409b4d26b3 100644
--- a/Emby.Server.Implementations/Localization/Core/ko.json
+++ b/Emby.Server.Implementations/Localization/Core/ko.json
@@ -118,5 +118,7 @@
"TaskCleanActivityLog": "활동내역청소",
"Undefined": "일치하지 않음",
"Forced": "강제하기",
- "Default": "기본 설정"
+ "Default": "기본 설정",
+ "TaskOptimizeDatabaseDescription": "데이터베이스를 압축하고 사용 가능한 공간을 늘립니다. 라이브러리를 검색한 후 이 작업을 실행하거나 데이터베이스 수정같은 비슷한 작업을 수행하면 성능이 향상될 수 있습니다.",
+ "TaskOptimizeDatabase": "데이터베이스 최적화"
}
diff --git a/Emby.Server.Implementations/Localization/Core/lv.json b/Emby.Server.Implementations/Localization/Core/lv.json
index a46bdc3ded..443a74a10f 100644
--- a/Emby.Server.Implementations/Localization/Core/lv.json
+++ b/Emby.Server.Implementations/Localization/Core/lv.json
@@ -117,5 +117,7 @@
"TaskCleanActivityLogDescription": "Nodzēš darbību žurnāla ierakstus, kuri ir vecāki par doto vecumu.",
"TaskCleanActivityLog": "Notīrīt Darbību Žurnālu",
"Undefined": "Nenoteikts",
- "Default": "Noklusējums"
+ "Default": "Noklusējums",
+ "TaskOptimizeDatabaseDescription": "Saspiež datubāzi un atbrīvo atmiņu. Uzdevum palaišana pēc bibliotēku skenēšanas vai citām, ar datubāzi saistītām, izmaiņām iespējams uzlabos ātrdarbību.",
+ "TaskOptimizeDatabase": "Optimizēt datubāzi"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ml.json b/Emby.Server.Implementations/Localization/Core/ml.json
index e764963cff..435f9b6305 100644
--- a/Emby.Server.Implementations/Localization/Core/ml.json
+++ b/Emby.Server.Implementations/Localization/Core/ml.json
@@ -117,5 +117,7 @@
"Favorites": "പ്രിയങ്കരങ്ങൾ",
"Books": "പുസ്തകങ്ങൾ",
"Genres": "വിഭാഗങ്ങൾ",
- "Channels": "ചാനലുകൾ"
+ "Channels": "ചാനലുകൾ",
+ "TaskOptimizeDatabaseDescription": "ഡാറ്റാബേസ് ചുരുക്കുകയും സ്വതന്ത്ര ഇടം വെട്ടിച്ചുരുക്കുകയും ചെയ്യുന്നു. ലൈബ്രറി സ്കാൻ ചെയ്തതിനുശേഷം അല്ലെങ്കിൽ ഡാറ്റാബേസ് പരിഷ്ക്കരണങ്ങളെ സൂചിപ്പിക്കുന്ന മറ്റ് മാറ്റങ്ങൾ ചെയ്തതിന് ശേഷം ഈ ടാസ്ക് പ്രവർത്തിപ്പിക്കുന്നത് പ്രകടനം മെച്ചപ്പെടുത്തും.",
+ "TaskOptimizeDatabase": "ഡാറ്റാബേസ് ഒപ്റ്റിമൈസ് ചെയ്യുക"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ms.json b/Emby.Server.Implementations/Localization/Core/ms.json
index 5b4c8ae107..b2dcf270c1 100644
--- a/Emby.Server.Implementations/Localization/Core/ms.json
+++ b/Emby.Server.Implementations/Localization/Core/ms.json
@@ -5,7 +5,7 @@
"Artists": "Artis",
"AuthenticationSucceededWithUserName": "{0} berjaya disahkan",
"Books": "Buku-buku",
- "CameraImageUploadedFrom": "Ada gambar dari kamera yang baru dimuat naik melalui {0}",
+ "CameraImageUploadedFrom": "Gambar baharu telah dimuat naik melalui {0}",
"Channels": "Saluran",
"ChapterNameValue": "Bab {0}",
"Collections": "Koleksi",
@@ -101,5 +101,13 @@
"Forced": "Paksa",
"Default": "Asal",
"TaskCleanCache": "Bersihkan Direktori Cache",
- "TaskCleanActivityLogDescription": "Padamkan entri log aktiviti yang lebih tua daripada usia yang dikonfigurasi."
+ "TaskCleanActivityLogDescription": "Padamkan entri log aktiviti yang lebih tua daripada usia yang dikonfigurasi.",
+ "TaskRefreshPeople": "Segarkan Orang",
+ "TaskCleanLogsDescription": "Padamkan fail log yang berumur lebih dari {0} hari.",
+ "TaskCleanLogs": "Bersihkan Direktotri Log",
+ "TaskRefreshLibraryDescription": "Imbas perpustakaan media untuk mencari fail-fail baru dan menyegarkan metadata.",
+ "TaskRefreshLibrary": "Imbas Perpustakaan Media",
+ "TaskRefreshChapterImagesDescription": "Membuat gambaran kecil untuk video yang mempunyai bab.",
+ "TaskRefreshChapterImages": "Ekstrak Gambar-gambar Bab",
+ "TaskCleanCacheDescription": "Menghapuskan fail cache yang tidak lagi diperlukan oleh sistem."
}
diff --git a/Emby.Server.Implementations/Localization/Core/nb.json b/Emby.Server.Implementations/Localization/Core/nb.json
index fbe1f7c4d5..81c1eefe74 100644
--- a/Emby.Server.Implementations/Localization/Core/nb.json
+++ b/Emby.Server.Implementations/Localization/Core/nb.json
@@ -118,5 +118,6 @@
"Undefined": "Udefinert",
"Forced": "Tvunget",
"Default": "Standard",
- "TaskCleanActivityLogDescription": "Sletter oppføringer i aktivitetsloggen som er eldre enn den konfigurerte alderen."
+ "TaskCleanActivityLogDescription": "Sletter oppføringer i aktivitetsloggen som er eldre enn den konfigurerte alderen.",
+ "TaskOptimizeDatabase": "Optimiser database"
}
diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json
index 2973c8c6ea..f79840c781 100644
--- a/Emby.Server.Implementations/Localization/Core/nl.json
+++ b/Emby.Server.Implementations/Localization/Core/nl.json
@@ -1,7 +1,7 @@
{
"Albums": "Albums",
"AppDeviceValues": "App: {0}, Apparaat: {1}",
- "Application": "Applicatie",
+ "Application": "Toepassing",
"Artists": "Artiesten",
"AuthenticationSucceededWithUserName": "{0} is succesvol geauthenticeerd",
"Books": "Boeken",
@@ -25,7 +25,7 @@
"HeaderLiveTV": "Live TV",
"HeaderNextUp": "Volgende",
"HeaderRecordingGroups": "Opnamegroepen",
- "HomeVideos": "Home video's",
+ "HomeVideos": "Thuis video's",
"Inherit": "Erven",
"ItemAddedWithName": "{0} is toegevoegd aan de bibliotheek",
"ItemRemovedWithName": "{0} is verwijderd uit de bibliotheek",
@@ -92,11 +92,11 @@
"ValueHasBeenAddedToLibrary": "{0} is toegevoegd aan je mediabibliotheek",
"ValueSpecialEpisodeName": "Speciaal - {0}",
"VersionNumber": "Versie {0}",
- "TaskDownloadMissingSubtitlesDescription": "Zoekt op het internet naar missende ondertitels gebaseerd op metadata configuratie.",
- "TaskDownloadMissingSubtitles": "Download missende ondertitels",
+ "TaskDownloadMissingSubtitlesDescription": "Zoekt op het internet naar missende ondertiteling gebaseerd op metadata configuratie.",
+ "TaskDownloadMissingSubtitles": "Download missende ondertiteling",
"TaskRefreshChannelsDescription": "Vernieuwt informatie van internet kanalen.",
"TaskRefreshChannels": "Vernieuw Kanalen",
- "TaskCleanTranscodeDescription": "Verwijder transcode bestanden ouder dan 1 dag.",
+ "TaskCleanTranscodeDescription": "Verwijdert transcode bestanden ouder dan 1 dag.",
"TaskCleanLogs": "Log Folder Opschonen",
"TaskCleanTranscode": "Transcode Folder Opschonen",
"TaskUpdatePluginsDescription": "Download en installeert updates voor plugins waar automatisch updaten aan staat.",
@@ -108,15 +108,17 @@
"TaskRefreshLibrary": "Scan Media Bibliotheek",
"TaskRefreshChapterImagesDescription": "Maakt thumbnails aan voor videos met hoofdstukken.",
"TaskRefreshChapterImages": "Hoofdstukafbeeldingen Uitpakken",
- "TaskCleanCacheDescription": "Verwijder gecachte bestanden die het systeem niet langer nodig heeft.",
+ "TaskCleanCacheDescription": "Verwijdert gecachte bestanden die het systeem niet langer nodig heeft.",
"TaskCleanCache": "Cache Folder Opschonen",
"TasksChannelsCategory": "Internet Kanalen",
"TasksApplicationCategory": "Applicatie",
"TasksLibraryCategory": "Bibliotheek",
"TasksMaintenanceCategory": "Onderhoud",
- "TaskCleanActivityLogDescription": "Verwijder activiteiten logs ouder dan de ingestelde tijd.",
+ "TaskCleanActivityLogDescription": "Verwijdert activiteiten logs ouder dan de ingestelde tijd.",
"TaskCleanActivityLog": "Leeg activiteiten logboek",
"Undefined": "Niet gedefinieerd",
"Forced": "Geforceerd",
- "Default": "Standaard"
+ "Default": "Standaard",
+ "TaskOptimizeDatabaseDescription": "Comprimeert de database en trimt vrije ruimte. Het uitvoeren van deze taak kan de prestaties verbeteren, na het scannen van de bibliotheek of andere aanpassingen die invloed hebben op de database.",
+ "TaskOptimizeDatabase": "Database optimaliseren"
}
diff --git a/Emby.Server.Implementations/Localization/Core/pl.json b/Emby.Server.Implementations/Localization/Core/pl.json
index e3da96a85a..275bdec6e6 100644
--- a/Emby.Server.Implementations/Localization/Core/pl.json
+++ b/Emby.Server.Implementations/Localization/Core/pl.json
@@ -118,5 +118,6 @@
"TaskCleanActivityLog": "Czyść dziennik aktywności",
"Undefined": "Nieustalony",
"Forced": "Wymuszony",
- "Default": "Domyślne"
+ "Default": "Domyślne",
+ "TaskOptimizeDatabase": "Optymalizuj bazę danych"
}
diff --git a/Emby.Server.Implementations/Localization/Core/pt.json b/Emby.Server.Implementations/Localization/Core/pt.json
index f1a78b2d32..b435672adf 100644
--- a/Emby.Server.Implementations/Localization/Core/pt.json
+++ b/Emby.Server.Implementations/Localization/Core/pt.json
@@ -61,7 +61,7 @@
"NameSeasonUnknown": "Temporada Desconhecida",
"NameSeasonNumber": "Temporada {0}",
"NameInstallFailed": "Falha na instalação de {0}",
- "MusicVideos": "Videoclips",
+ "MusicVideos": "Videoclipes",
"Music": "Música",
"MixedContent": "Conteúdo Misto",
"MessageServerConfigurationUpdated": "A configuração do servidor foi actualizada",
diff --git a/Emby.Server.Implementations/Localization/Core/ru.json b/Emby.Server.Implementations/Localization/Core/ru.json
index e58f8c39d0..248f06c4b2 100644
--- a/Emby.Server.Implementations/Localization/Core/ru.json
+++ b/Emby.Server.Implementations/Localization/Core/ru.json
@@ -118,5 +118,7 @@
"TaskCleanActivityLog": "Очистить журнал активности",
"Undefined": "Не определено",
"Forced": "Форсир-ые",
- "Default": "По умолчанию"
+ "Default": "По умолчанию",
+ "TaskOptimizeDatabaseDescription": "Сжимает базу данных и обрезает свободное место. Выполнение этой задачи после сканирования библиотеки или внесения других изменений, предполагающих модификации базы данных, может повысить производительность.",
+ "TaskOptimizeDatabase": "Оптимизировать базу данных"
}
diff --git a/Emby.Server.Implementations/Localization/Core/sk.json b/Emby.Server.Implementations/Localization/Core/sk.json
index 99fbd39540..37da7d5ab3 100644
--- a/Emby.Server.Implementations/Localization/Core/sk.json
+++ b/Emby.Server.Implementations/Localization/Core/sk.json
@@ -118,5 +118,7 @@
"TaskCleanActivityLog": "Vyčistiť log aktivít",
"Undefined": "Nedefinované",
"Forced": "Vynútené",
- "Default": "Predvolené"
+ "Default": "Predvolené",
+ "TaskOptimizeDatabaseDescription": "Zmenší databázu a odstráni prázdne miesto. Spustenie tejto úlohy po skenovaní knižnice alebo po iných zmenách zahŕňajúcich úpravy databáze môže zlepšiť výkon.",
+ "TaskOptimizeDatabase": "Optimalizovať databázu"
}
diff --git a/Emby.Server.Implementations/Localization/Core/sl-SI.json b/Emby.Server.Implementations/Localization/Core/sl-SI.json
index 343e067b79..a6fcbd3e29 100644
--- a/Emby.Server.Implementations/Localization/Core/sl-SI.json
+++ b/Emby.Server.Implementations/Localization/Core/sl-SI.json
@@ -16,7 +16,7 @@
"Folders": "Mape",
"Genres": "Zvrsti",
"HeaderAlbumArtists": "Izvajalci albuma",
- "HeaderContinueWatching": "Nadaljuj z ogledom",
+ "HeaderContinueWatching": "Nadaljuj ogled",
"HeaderFavoriteAlbums": "Priljubljeni albumi",
"HeaderFavoriteArtists": "Priljubljeni izvajalci",
"HeaderFavoriteEpisodes": "Priljubljene epizode",
@@ -90,7 +90,7 @@
"UserStartedPlayingItemWithValues": "{0} predvaja {1} na {2}",
"UserStoppedPlayingItemWithValues": "{0} je nehal predvajati {1} na {2}",
"ValueHasBeenAddedToLibrary": "{0} je bil dodan vaši knjižnici",
- "ValueSpecialEpisodeName": "Posebna - {0}",
+ "ValueSpecialEpisodeName": "Bonus - {0}",
"VersionNumber": "Različica {0}",
"TaskDownloadMissingSubtitles": "Prenesi manjkajoče podnapise",
"TaskRefreshChannelsDescription": "Osveži podatke spletnih kanalov.",
@@ -118,5 +118,7 @@
"TaskCleanActivityLog": "Počisti dnevnik aktivnosti",
"Undefined": "Nedoločen",
"Forced": "Prisilno",
- "Default": "Privzeto"
+ "Default": "Privzeto",
+ "TaskOptimizeDatabaseDescription": "Stisne bazo podatkov in uredi prazen prostor. Zagon tega opravila po iskanju predstavnosti ali drugih spremembah ki vplivajo na bazo podatkov lahko izboljša hitrost delovanja.",
+ "TaskOptimizeDatabase": "Optimiziraj bazo podatkov"
}
diff --git a/Emby.Server.Implementations/Localization/Core/sq.json b/Emby.Server.Implementations/Localization/Core/sq.json
index 0d909b06e9..e36fdc43db 100644
--- a/Emby.Server.Implementations/Localization/Core/sq.json
+++ b/Emby.Server.Implementations/Localization/Core/sq.json
@@ -42,8 +42,8 @@
"Sync": "Sinkronizo",
"SubtitleDownloadFailureFromForItem": "Titrat deshtuan të shkarkohen nga {0} për {1}",
"StartupEmbyServerIsLoading": "Serveri Jellyfin po ngarkohet. Ju lutemi provoni përseri pas pak.",
- "Songs": "Këngë",
- "Shows": "Seriale",
+ "Songs": "Këngët",
+ "Shows": "Serialet",
"ServerNameNeedsToBeRestarted": "{0} duhet të ristartoj",
"ScheduledTaskStartedWithName": "{0} filloi",
"ScheduledTaskFailedWithName": "{0} dështoi",
@@ -74,9 +74,9 @@
"NameSeasonUnknown": "Sezon i panjohur",
"NameSeasonNumber": "Sezoni {0}",
"NameInstallFailed": "Instalimi i {0} dështoi",
- "MusicVideos": "Video muzikore",
+ "MusicVideos": "Videot muzikore",
"Music": "Muzikë",
- "Movies": "Filma",
+ "Movies": "Filmat",
"MixedContent": "Përmbajtje e përzier",
"MessageServerConfigurationUpdated": "Konfigurimet e serverit u përditësuan",
"MessageNamedServerConfigurationUpdatedWithValue": "Seksioni i konfigurimit të serverit {0} u përditësua",
@@ -97,20 +97,27 @@
"HeaderFavoriteAlbums": "Albumet e preferuar",
"HeaderContinueWatching": "Vazhdo të shikosh",
"HeaderAlbumArtists": "Artistët e albumeve",
- "Genres": "Zhanre",
- "Folders": "Dosje",
- "Favorites": "Të preferuara",
+ "Genres": "Zhanret",
+ "Folders": "Skedarët",
+ "Favorites": "Të preferuarat",
"FailedLoginAttemptWithUserName": "Përpjekja për hyrje dështoi nga {0}",
"DeviceOnlineWithName": "{0} u lidh",
"DeviceOfflineWithName": "{0} u shkëput",
- "Collections": "Koleksione",
+ "Collections": "Koleksionet",
"ChapterNameValue": "Kapituj",
- "Channels": "Kanale",
+ "Channels": "Kanalet",
"CameraImageUploadedFrom": "Një foto e re nga kamera u ngarkua nga {0}",
- "Books": "Libra",
+ "Books": "Librat",
"AuthenticationSucceededWithUserName": "{0} u identifikua me sukses",
- "Artists": "Artistë",
+ "Artists": "Artistët",
"Application": "Aplikacioni",
"AppDeviceValues": "Aplikacioni: {0}, Pajisja: {1}",
- "Albums": "Albume"
+ "Albums": "Albumet",
+ "TaskCleanActivityLogDescription": "Pastro të dhënat mbi aktivitetin më të vjetra sesa koha e përcaktuar.",
+ "TaskCleanActivityLog": "Pastro të dhënat mbi aktivitetin",
+ "Undefined": "I papërcaktuar",
+ "Forced": "I detyruar",
+ "Default": "Parazgjedhur",
+ "TaskOptimizeDatabaseDescription": "Kompakton bazën e të dhënave dhe shkurton hapësirën e lirë. Drejtimi i kësaj detyre pasi skanoni bibliotekën ose bëni ndryshime të tjera që nënkuptojnë modifikime të bazës së të dhënave mund të përmirësojë performancën.",
+ "TaskOptimizeDatabase": "Optimizo databazën"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ta.json b/Emby.Server.Implementations/Localization/Core/ta.json
index 129986ed0e..d6e9aa8e5a 100644
--- a/Emby.Server.Implementations/Localization/Core/ta.json
+++ b/Emby.Server.Implementations/Localization/Core/ta.json
@@ -117,5 +117,7 @@
"TaskCleanActivityLog": "செயல்பாட்டு பதிவை அழி",
"Undefined": "வரையறுக்கப்படாத",
"Forced": "கட்டாயப்படுத்தப்பட்டது",
- "Default": "இயல்புநிலை"
+ "Default": "இயல்புநிலை",
+ "TaskOptimizeDatabaseDescription": "தரவுத்தளத்தை சுருக்கி, இலவச இடத்தை குறைக்கிறது. நூலகத்தை ஸ்கேன் செய்தபின் அல்லது தரவுத்தள மாற்றங்களைக் குறிக்கும் பிற மாற்றங்களைச் செய்தபின் இந்த பணியை இயக்குவது செயல்திறனை மேம்படுத்தக்கூடும்.",
+ "TaskOptimizeDatabase": "தரவுத்தளத்தை மேம்படுத்தவும்"
}
diff --git a/Emby.Server.Implementations/Localization/Core/tr.json b/Emby.Server.Implementations/Localization/Core/tr.json
index c6b904045b..771c91d59f 100644
--- a/Emby.Server.Implementations/Localization/Core/tr.json
+++ b/Emby.Server.Implementations/Localization/Core/tr.json
@@ -43,7 +43,7 @@
"NameInstallFailed": "{0} kurulumu başarısız",
"NameSeasonNumber": "Sezon {0}",
"NameSeasonUnknown": "Bilinmeyen Sezon",
- "NewVersionIsAvailable": "Jellyfin Sunucusunun yeni bir versiyonu indirmek için hazır.",
+ "NewVersionIsAvailable": "Jellyfin Sunucusunun yeni bir sürümü indirmek için hazır.",
"NotificationOptionApplicationUpdateAvailable": "Uygulama güncellemesi mevcut",
"NotificationOptionApplicationUpdateInstalled": "Uygulama güncellemesi yüklendi",
"NotificationOptionAudioPlayback": "Ses çalma başladı",
@@ -75,7 +75,7 @@
"StartupEmbyServerIsLoading": "Jellyfin Sunucusu yükleniyor. Lütfen kısa süre sonra tekrar deneyin.",
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
"SubtitleDownloadFailureFromForItem": "{1} için alt yazılar {0} 'dan indirilemedi",
- "Sync": "Eşitle",
+ "Sync": "Eşzamanlama",
"System": "Sistem",
"TvShows": "Diziler",
"User": "Kullanıcı",
@@ -89,34 +89,36 @@
"UserPolicyUpdatedWithName": "Kullanıcı politikası {0} için güncellendi",
"UserStartedPlayingItemWithValues": "{0}, {2} cihazında {1} izliyor",
"UserStoppedPlayingItemWithValues": "{0}, {2} cihazında {1} izlemeyi bitirdi",
- "ValueHasBeenAddedToLibrary": "Medya kitaplığınıza {0} eklendi",
+ "ValueHasBeenAddedToLibrary": "Medya kütüphanenize {0} eklendi",
"ValueSpecialEpisodeName": "Özel - {0}",
- "VersionNumber": "Versiyon {0}",
+ "VersionNumber": "Sürüm {0}",
"TaskCleanCache": "Geçici dosya klasörünü temizle",
"TasksChannelsCategory": "İnternet kanalları",
"TasksApplicationCategory": "Uygulama",
"TasksLibraryCategory": "Kütüphane",
- "TasksMaintenanceCategory": "Onarım",
+ "TasksMaintenanceCategory": "Bakım",
"TaskRefreshPeopleDescription": "Medya kütüphanenizdeki videoların oyuncu ve yönetmen bilgilerini günceller.",
"TaskDownloadMissingSubtitlesDescription": "Metadata ayarlarını baz alarak eksik altyazıları internette arar.",
"TaskDownloadMissingSubtitles": "Eksik altyazıları indir",
"TaskRefreshChannelsDescription": "Internet kanal bilgilerini yenile.",
"TaskRefreshChannels": "Kanalları Yenile",
- "TaskCleanTranscodeDescription": "Bir günü dolmuş dönüştürme bilgisi içeren dosyaları siler.",
+ "TaskCleanTranscodeDescription": "Bir günden daha eski dönüştürme dosyalarını siler.",
"TaskCleanTranscode": "Dönüşüm Dizinini Temizle",
"TaskUpdatePluginsDescription": "Otomatik güncellenmeye ayarlanmış eklentilerin güncellemelerini indirir ve kurar.",
"TaskUpdatePlugins": "Eklentileri Güncelle",
"TaskRefreshPeople": "Kullanıcıları Yenile",
- "TaskCleanLogsDescription": "{0} günden eski log dosyalarını siler.",
- "TaskCleanLogs": "Log Dizinini Temizle",
- "TaskRefreshLibraryDescription": "Medya kütüphanenize eklenen yeni dosyaları arar ve bilgileri yeniler.",
+ "TaskCleanLogsDescription": "{0} günden eski günlük dosyalarını siler.",
+ "TaskCleanLogs": "Günlük Dizinini Temizle",
+ "TaskRefreshLibraryDescription": "Medya kütüphanenize eklenen yeni dosyaları arar ve ortam bilgilerini yeniler.",
"TaskRefreshLibrary": "Medya Kütüphanesini Tara",
"TaskRefreshChapterImagesDescription": "Sahnelere ayrılmış videolar için küçük resimler oluştur.",
"TaskRefreshChapterImages": "Bölüm Resimlerini Çıkar",
"TaskCleanCacheDescription": "Sistem tarafından artık ihtiyaç duyulmayan önbellek dosyalarını siler.",
- "TaskCleanActivityLog": "İşlem Günlüğünü Temizle",
- "TaskCleanActivityLogDescription": "Belirtilen sureden daha eski etkinlik log kayıtları silindi.",
+ "TaskCleanActivityLog": "Etkinlik Günlüğünü Temizle",
+ "TaskCleanActivityLogDescription": "Yapılandırılan tarihten daha eski olan etkinlik günlüğü girişlerini siler.",
"Undefined": "Bilinmeyen",
"Default": "Varsayılan",
- "Forced": "Zorla"
+ "Forced": "Zorla",
+ "TaskOptimizeDatabaseDescription": "Veritabanını sıkıştırır ve boş alanı keser. Kitaplığı taradıktan sonra veya veritabanında değişiklik anlamına gelen diğer işlemleri yaptıktan sonra bu görevi çalıştırmak performansı artırabilir.",
+ "TaskOptimizeDatabase": "Veritabanını optimize et"
}
diff --git a/Emby.Server.Implementations/Localization/Core/vi.json b/Emby.Server.Implementations/Localization/Core/vi.json
index 58652c4693..20ab1dd7db 100644
--- a/Emby.Server.Implementations/Localization/Core/vi.json
+++ b/Emby.Server.Implementations/Localization/Core/vi.json
@@ -117,5 +117,7 @@
"TaskCleanActivityLog": "Xóa Nhật Ký Hoạt Động",
"Undefined": "Không Xác Định",
"Forced": "Bắt Buộc",
- "Default": "Mặc Định"
+ "Default": "Mặc Định",
+ "TaskOptimizeDatabaseDescription": "Thu gọn cơ sở dữ liệu và cắt bớt dung lượng trống. Chạy tác vụ này sau khi quét thư viện hoặc thực hiện các thay đổi khác ngụ ý sửa đổi cơ sở dữ liệu có thể cải thiện hiệu suất.",
+ "TaskOptimizeDatabase": "Tối ưu hóa cơ sở dữ liệu"
}
diff --git a/Emby.Server.Implementations/Localization/Core/zh-CN.json b/Emby.Server.Implementations/Localization/Core/zh-CN.json
index 12803456e3..faa9c40e27 100644
--- a/Emby.Server.Implementations/Localization/Core/zh-CN.json
+++ b/Emby.Server.Implementations/Localization/Core/zh-CN.json
@@ -118,5 +118,7 @@
"TaskCleanActivityLogDescription": "删除早于设置时间的活动日志条目。",
"Undefined": "未定义",
"Forced": "强制的",
- "Default": "默认"
+ "Default": "默认",
+ "TaskOptimizeDatabaseDescription": "压缩数据库并优化可用空间,在扫描库或执行其他数据库修改后运行此任务可能会提高性能。",
+ "TaskOptimizeDatabase": "优化数据库"
}
diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs
index a9e3bfdb0e..9808e47de2 100644
--- a/Emby.Server.Implementations/Localization/LocalizationManager.cs
+++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs
@@ -23,6 +23,9 @@ namespace Emby.Server.Implementations.Localization
public class LocalizationManager : ILocalizationManager
{
private const string DefaultCulture = "en-US";
+ private const string RatingsPath = "Emby.Server.Implementations.Localization.Ratings.";
+ private const string CulturesPath = "Emby.Server.Implementations.Localization.iso6392.txt";
+ private const string CountriesPath = "Emby.Server.Implementations.Localization.countries.json";
private static readonly Assembly _assembly = typeof(LocalizationManager).Assembly;
private static readonly string[] _unratedValues = { "n/a", "unrated", "not rated" };
@@ -58,43 +61,39 @@ namespace Emby.Server.Implementations.Localization
/// .
public async Task LoadAll()
{
- const string RatingsResource = "Emby.Server.Implementations.Localization.Ratings.";
-
// Extract from the assembly
foreach (var resource in _assembly.GetManifestResourceNames())
{
- if (!resource.StartsWith(RatingsResource, StringComparison.Ordinal))
+ if (!resource.StartsWith(RatingsPath, StringComparison.Ordinal))
{
continue;
}
- string countryCode = resource.Substring(RatingsResource.Length, 2);
+ string countryCode = resource.Substring(RatingsPath.Length, 2);
var dict = new Dictionary(StringComparer.OrdinalIgnoreCase);
- using (var str = _assembly.GetManifestResourceStream(resource))
- using (var reader = new StreamReader(str))
+ await using var str = _assembly.GetManifestResourceStream(resource);
+ using var reader = new StreamReader(str);
+ await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false))
{
- await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false))
+ if (string.IsNullOrWhiteSpace(line))
{
- if (string.IsNullOrWhiteSpace(line))
- {
- continue;
- }
-
- string[] parts = line.Split(',');
- if (parts.Length == 2
- && int.TryParse(parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var value))
- {
- var name = parts[0];
- dict.Add(name, new ParentalRating(name, value));
- }
-#if DEBUG
- else
- {
- _logger.LogWarning("Malformed line in ratings file for country {CountryCode}", countryCode);
- }
-#endif
+ continue;
}
+
+ string[] parts = line.Split(',');
+ if (parts.Length == 2
+ && int.TryParse(parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var value))
+ {
+ var name = parts[0];
+ dict.Add(name, new ParentalRating(name, value));
+ }
+#if DEBUG
+ else
+ {
+ _logger.LogWarning("Malformed line in ratings file for country {CountryCode}", countryCode);
+ }
+#endif
}
_allParentalRatings[countryCode] = dict;
@@ -114,52 +113,48 @@ namespace Emby.Server.Implementations.Localization
{
List list = new List();
- const string ResourcePath = "Emby.Server.Implementations.Localization.iso6392.txt";
-
- using (var stream = _assembly.GetManifestResourceStream(ResourcePath))
- using (var reader = new StreamReader(stream))
+ await using var stream = _assembly.GetManifestResourceStream(CulturesPath);
+ using var reader = new StreamReader(stream);
+ await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false))
{
- await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false))
+ if (string.IsNullOrWhiteSpace(line))
{
- if (string.IsNullOrWhiteSpace(line))
+ continue;
+ }
+
+ var parts = line.Split('|');
+
+ if (parts.Length == 5)
+ {
+ string name = parts[3];
+ if (string.IsNullOrWhiteSpace(name))
{
continue;
}
- var parts = line.Split('|');
-
- if (parts.Length == 5)
+ string twoCharName = parts[2];
+ if (string.IsNullOrWhiteSpace(twoCharName))
{
- string name = parts[3];
- if (string.IsNullOrWhiteSpace(name))
- {
- continue;
- }
-
- string twoCharName = parts[2];
- if (string.IsNullOrWhiteSpace(twoCharName))
- {
- continue;
- }
-
- string[] threeletterNames;
- if (string.IsNullOrWhiteSpace(parts[1]))
- {
- threeletterNames = new[] { parts[0] };
- }
- else
- {
- threeletterNames = new[] { parts[0], parts[1] };
- }
-
- list.Add(new CultureDto
- {
- DisplayName = name,
- Name = name,
- ThreeLetterISOLanguageNames = threeletterNames,
- TwoLetterISOLanguageName = twoCharName
- });
+ continue;
}
+
+ string[] threeletterNames;
+ if (string.IsNullOrWhiteSpace(parts[1]))
+ {
+ threeletterNames = new[] { parts[0] };
+ }
+ else
+ {
+ threeletterNames = new[] { parts[0], parts[1] };
+ }
+
+ list.Add(new CultureDto
+ {
+ DisplayName = name,
+ Name = name,
+ ThreeLetterISOLanguageNames = threeletterNames,
+ TwoLetterISOLanguageName = twoCharName
+ });
}
}
@@ -188,7 +183,7 @@ namespace Emby.Server.Implementations.Localization
///
public IEnumerable GetCountries()
{
- using StreamReader reader = new StreamReader(_assembly.GetManifestResourceStream("Emby.Server.Implementations.Localization.countries.json"));
+ using StreamReader reader = new StreamReader(_assembly.GetManifestResourceStream(CountriesPath));
return JsonSerializer.Deserialize>(reader.ReadToEnd(), _jsonOptions);
}
@@ -350,23 +345,21 @@ namespace Emby.Server.Implementations.Localization
private async Task CopyInto(IDictionary dictionary, string resourcePath)
{
- using (var stream = _assembly.GetManifestResourceStream(resourcePath))
+ await using var stream = _assembly.GetManifestResourceStream(resourcePath);
+ // If a Culture doesn't have a translation the stream will be null and it defaults to en-us further up the chain
+ if (stream != null)
{
- // If a Culture doesn't have a translation the stream will be null and it defaults to en-us further up the chain
- if (stream != null)
- {
- var dict = await JsonSerializer.DeserializeAsync>(stream, _jsonOptions).ConfigureAwait(false);
+ var dict = await JsonSerializer.DeserializeAsync>(stream, _jsonOptions).ConfigureAwait(false);
- foreach (var key in dict.Keys)
- {
- dictionary[key] = dict[key];
- }
- }
- else
+ foreach (var key in dict.Keys)
{
- _logger.LogError("Missing translation/culture resource: {ResourcePath}", resourcePath);
+ dictionary[key] = dict[key];
}
}
+ else
+ {
+ _logger.LogError("Missing translation/culture resource: {ResourcePath}", resourcePath);
+ }
}
private static string GetResourceFilename(string culture)
diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs
index 9a1ca99467..8cafde38ee 100644
--- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs
+++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs
@@ -147,7 +147,7 @@ namespace Emby.Server.Implementations.Playlists
playlist.SetMediaType(options.MediaType);
- parentFolder.AddChild(playlist, CancellationToken.None);
+ parentFolder.AddChild(playlist);
await playlist.RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(_fileSystem)) { ForceSave = true }, CancellationToken.None)
.ConfigureAwait(false);
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
index baeb86a221..b764a139cb 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
@@ -55,9 +55,19 @@ namespace Emby.Server.Implementations.ScheduledTasks
_localization = localization;
}
- ///
- /// Creates the triggers that define when the task will run.
- ///
+ ///
+ public string Name => _localization.GetLocalizedString("TaskRefreshChapterImages");
+
+ ///
+ public string Description => _localization.GetLocalizedString("TaskRefreshChapterImagesDescription");
+
+ ///
+ public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
+
+ ///
+ public string Key => "RefreshChapterImages";
+
+ ///
public IEnumerable GetDefaultTriggers()
{
return new[]
@@ -162,26 +172,5 @@ namespace Emby.Server.Implementations.ScheduledTasks
}
}
}
-
- ///
- public string Name => _localization.GetLocalizedString("TaskRefreshChapterImages");
-
- ///
- public string Description => _localization.GetLocalizedString("TaskRefreshChapterImagesDescription");
-
- ///
- public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
-
- ///
- public string Key => "RefreshChapterImages";
-
- ///
- public bool IsHidden => false;
-
- ///
- public bool IsEnabled => true;
-
- ///
- public bool IsLogged => true;
}
}
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs
index 50ba9bc899..19600b1e64 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs
@@ -65,7 +65,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
throw new Exception($"Activity Log Retention days must be at least 0. Currently: {retentionDays}");
}
- var startDate = DateTime.UtcNow.AddDays(retentionDays.Value * -1);
+ var startDate = DateTime.UtcNow.AddDays(-retentionDays.Value);
return _activityManager.CleanAsync(startDate);
}
diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs
index 62283d038d..35435b0071 100644
--- a/Jellyfin.Api/Controllers/DynamicHlsController.cs
+++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs
@@ -1380,7 +1380,7 @@ namespace Jellyfin.Api.Controllers
}
else if (string.Equals(segmentFormat, "mp4", StringComparison.OrdinalIgnoreCase))
{
- var outputFmp4HeaderArg = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) switch
+ var outputFmp4HeaderArg = OperatingSystem.IsWindows() switch
{
// on Windows, the path of fmp4 header file needs to be configured
true => " -hls_fmp4_init_filename \"" + outputPrefix + "-1" + outputExtension + "\"",
@@ -1496,7 +1496,7 @@ namespace Jellyfin.Api.Controllers
args += " -ar " + state.OutputAudioSampleRate.Value.ToString(CultureInfo.InvariantCulture);
}
- args += _encodingHelper.GetAudioFilterParam(state, _encodingOptions, true);
+ args += _encodingHelper.GetAudioFilterParam(state, _encodingOptions);
return args;
}
diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs
index f232dffaa5..4774ed4efa 100644
--- a/Jellyfin.Api/Controllers/InstantMixController.cs
+++ b/Jellyfin.Api/Controllers/InstantMixController.cs
@@ -228,42 +228,6 @@ namespace Jellyfin.Api.Controllers
return GetResult(items, user, limit, dtoOptions);
}
- ///
- /// Creates an instant playlist based on a given genre.
- ///
- /// The item id.
- /// Optional. Filter by user id, and attach user data.
- /// Optional. The maximum number of records to return.
- /// Optional. Specify additional fields of information to return in the output.
- /// Optional. Include image information in output.
- /// Optional. Include user data.
- /// Optional. The max number of images to return, per image type.
- /// Optional. The image types to include in the output.
- /// Instant playlist returned.
- /// A with the playlist items.
- [HttpGet("MusicGenres/{id}/InstantMix")]
- [ProducesResponseType(StatusCodes.Status200OK)]
- public ActionResult> GetInstantMixFromMusicGenreById(
- [FromRoute, Required] Guid id,
- [FromQuery] Guid? userId,
- [FromQuery] int? limit,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
- [FromQuery] bool? enableImages,
- [FromQuery] bool? enableUserData,
- [FromQuery] int? imageTypeLimit,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes)
- {
- var item = _libraryManager.GetItemById(id);
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
- var dtoOptions = new DtoOptions { Fields = fields }
- .AddClientFields(Request)
- .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!);
- var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
- return GetResult(items, user, limit, dtoOptions);
- }
-
///
/// Creates an instant playlist based on a given item.
///
@@ -352,8 +316,7 @@ namespace Jellyfin.Api.Controllers
/// A with the playlist items.
[HttpGet("MusicGenres/InstantMix")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [Obsolete("Use GetInstantMixFromMusicGenres instead")]
- public ActionResult> GetInstantMixFromMusicGenreById2(
+ public ActionResult> GetInstantMixFromMusicGenreById(
[FromQuery, Required] Guid id,
[FromQuery] Guid? userId,
[FromQuery] int? limit,
@@ -363,15 +326,15 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? imageTypeLimit,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes)
{
- return GetInstantMixFromMusicGenreById(
- id,
- userId,
- limit,
- fields,
- enableImages,
- enableUserData,
- imageTypeLimit,
- enableImageTypes);
+ var item = _libraryManager.GetItemById(id);
+ var user = userId.HasValue && !userId.Equals(Guid.Empty)
+ ? _userManager.GetUserById(userId.Value)
+ : null;
+ var dtoOptions = new DtoOptions { Fields = fields }
+ .AddClientFields(Request)
+ .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!);
+ var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
+ return GetResult(items, user, limit, dtoOptions);
}
private QueryResult GetResult(List items, User? user, int? limit, DtoOptions dtoOptions)
diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs
index 6c29e6bb84..7c78928f72 100644
--- a/Jellyfin.Api/Controllers/MediaInfoController.cs
+++ b/Jellyfin.Api/Controllers/MediaInfoController.cs
@@ -161,6 +161,11 @@ namespace Jellyfin.Api.Controllers
liveStreamId)
.ConfigureAwait(false);
+ if (info.ErrorCode != null)
+ {
+ return info;
+ }
+
if (profile != null)
{
// set device specific data
@@ -302,27 +307,12 @@ namespace Jellyfin.Api.Controllers
///
/// The bitrate. Defaults to 102400.
/// Test buffer returned.
- /// Size has to be a numer between 0 and 10,000,000.
/// A with specified bitrate.
[HttpGet("Playback/BitrateTest")]
[ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status400BadRequest)]
- [Produces(MediaTypeNames.Application.Octet)]
[ProducesFile(MediaTypeNames.Application.Octet)]
- public ActionResult GetBitrateTestBytes([FromQuery] int size = 102400)
+ public ActionResult GetBitrateTestBytes([FromQuery][Range(1, 100_000_000, ErrorMessage = "The requested size must be greater than or equal to {1} and less than or equal to {2}")] int size = 102400)
{
- const int MaxSize = 10_000_000;
-
- if (size <= 0)
- {
- return BadRequest($"The requested size ({size}) is equal to or smaller than 0.");
- }
-
- if (size > MaxSize)
- {
- return BadRequest($"The requested size ({size}) is larger than the max allowed value ({MaxSize}).");
- }
-
byte[] buffer = ArrayPool.Shared.Rent(size);
try
{
diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs
index 6a720b1a45..5c941b2767 100644
--- a/Jellyfin.Api/Controllers/VideoHlsController.cs
+++ b/Jellyfin.Api/Controllers/VideoHlsController.cs
@@ -366,8 +366,7 @@ namespace Jellyfin.Api.Controllers
else if (string.Equals(segmentFormat, "mp4", StringComparison.OrdinalIgnoreCase))
{
var outputFmp4HeaderArg = string.Empty;
- var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
- if (isWindows)
+ if (OperatingSystem.IsWindows())
{
// on Windows, the path of fmp4 header file needs to be configured
outputFmp4HeaderArg = " -hls_fmp4_init_filename \"" + outputPrefix + "-1" + outputExtension + "\"";
@@ -485,7 +484,7 @@ namespace Jellyfin.Api.Controllers
args += " -ar " + state.OutputAudioSampleRate.Value.ToString(CultureInfo.InvariantCulture);
}
- args += _encodingHelper.GetAudioFilterParam(state, _encodingOptions, true);
+ args += _encodingHelper.GetAudioFilterParam(state, _encodingOptions);
return args;
}
diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs
index dc64a0f1bc..29a25fa6aa 100644
--- a/Jellyfin.Api/Controllers/VideosController.cs
+++ b/Jellyfin.Api/Controllers/VideosController.cs
@@ -296,6 +296,8 @@ namespace Jellyfin.Api.Controllers
/// Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms.
/// Optional. The fixed horizontal resolution of the encoded video.
/// Optional. The fixed vertical resolution of the encoded video.
+ /// Optional. The maximum horizontal resolution of the encoded video.
+ /// Optional. The maximum vertical resolution of the encoded video.
/// Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults.
/// Optional. The index of the subtitle stream to use. If omitted no subtitles will be used.
/// Optional. Specify the subtitle delivery method.
@@ -352,6 +354,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery] long? startTimeTicks,
[FromQuery] int? width,
[FromQuery] int? height,
+ [FromQuery] int? maxWidth,
+ [FromQuery] int? maxHeight,
[FromQuery] int? videoBitRate,
[FromQuery] int? subtitleStreamIndex,
[FromQuery] SubtitleDeliveryMethod? subtitleMethod,
@@ -407,6 +411,8 @@ namespace Jellyfin.Api.Controllers
StartTimeTicks = startTimeTicks,
Width = width,
Height = height,
+ MaxWidth = maxWidth,
+ MaxHeight = maxHeight,
VideoBitRate = videoBitRate,
SubtitleStreamIndex = subtitleStreamIndex,
SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode,
@@ -550,6 +556,8 @@ namespace Jellyfin.Api.Controllers
/// Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms.
/// Optional. The fixed horizontal resolution of the encoded video.
/// Optional. The fixed vertical resolution of the encoded video.
+ /// Optional. The maximum horizontal resolution of the encoded video.
+ /// Optional. The maximum vertical resolution of the encoded video.
/// Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults.
/// Optional. The index of the subtitle stream to use. If omitted no subtitles will be used.
/// Optional. Specify the subtitle delivery method.
@@ -606,6 +614,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery] long? startTimeTicks,
[FromQuery] int? width,
[FromQuery] int? height,
+ [FromQuery] int? maxWidth,
+ [FromQuery] int? maxHeight,
[FromQuery] int? videoBitRate,
[FromQuery] int? subtitleStreamIndex,
[FromQuery] SubtitleDeliveryMethod? subtitleMethod,
@@ -657,6 +667,8 @@ namespace Jellyfin.Api.Controllers
startTimeTicks,
width,
height,
+ maxWidth,
+ maxHeight,
videoBitRate,
subtitleStreamIndex,
subtitleMethod,
diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs
index d0666034e9..d1cdaf867e 100644
--- a/Jellyfin.Api/Helpers/HlsHelpers.cs
+++ b/Jellyfin.Api/Helpers/HlsHelpers.cs
@@ -99,8 +99,7 @@ namespace Jellyfin.Api.Helpers
return fmp4InitFileName;
}
- var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
- if (isWindows)
+ if (OperatingSystem.IsWindows())
{
// on Windows
// #EXT-X-MAP:URI="X:\transcodes\prefix-1.mp4"
diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs
index e9db07d5ab..5d3724c11f 100644
--- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs
+++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs
@@ -380,7 +380,7 @@ namespace Jellyfin.Api.Helpers
private void DeleteHlsPartialStreamFiles(string outputFilePath)
{
var directory = Path.GetDirectoryName(outputFilePath)
- ?? throw new ArgumentException("Path can't be a root directory.", nameof(outputFilePath));
+ ?? throw new ArgumentException("Path can't be a root directory.", nameof(outputFilePath));
var name = Path.GetFileNameWithoutExtension(outputFilePath);
@@ -444,6 +444,10 @@ namespace Jellyfin.Api.Helpers
{
var audioCodec = state.ActualOutputAudioCodec;
var videoCodec = state.ActualOutputVideoCodec;
+ var hardwareAccelerationTypeString = _serverConfigurationManager.GetEncodingOptions().HardwareAccelerationType;
+ HardwareEncodingType? hardwareAccelerationType = string.IsNullOrEmpty(hardwareAccelerationTypeString)
+ ? null
+ : (HardwareEncodingType)Enum.Parse(typeof(HardwareEncodingType), hardwareAccelerationTypeString, true);
_sessionManager.ReportTranscodingInfo(deviceId, new TranscodingInfo
{
@@ -458,6 +462,7 @@ namespace Jellyfin.Api.Helpers
AudioChannels = state.OutputAudioChannels,
IsAudioDirect = EncodingHelper.IsCopyCodec(state.OutputAudioCodec),
IsVideoDirect = EncodingHelper.IsCopyCodec(state.OutputVideoCodec),
+ HardwareAccelerationType = hardwareAccelerationType,
TranscodeReasons = state.TranscodeReasons
});
}
@@ -759,8 +764,8 @@ namespace Jellyfin.Api.Helpers
if (state.MediaSource.RequiresOpening && string.IsNullOrWhiteSpace(state.Request.LiveStreamId))
{
var liveStreamResponse = await _mediaSourceManager.OpenLiveStream(
- new LiveStreamRequest { OpenToken = state.MediaSource.OpenToken },
- cancellationTokenSource.Token)
+ new LiveStreamRequest { OpenToken = state.MediaSource.OpenToken },
+ cancellationTokenSource.Token)
.ConfigureAwait(false);
var encodingOptions = _serverConfigurationManager.GetEncodingOptions();
diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj
index bd7da9b067..a527282d15 100644
--- a/Jellyfin.Api/Jellyfin.Api.csproj
+++ b/Jellyfin.Api/Jellyfin.Api.csproj
@@ -8,17 +8,16 @@
net5.0
true
- true
- enable
AD0001
+ AllDisabledByDefault
-
+
-
-
+
+
@@ -33,10 +32,6 @@
-
- ../jellyfin.ruleset
-
-
<_Parameter1>Jellyfin.Api.Tests
diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj
index 3b14d33125..65bbd49da2 100644
--- a/Jellyfin.Data/Jellyfin.Data.csproj
+++ b/Jellyfin.Data/Jellyfin.Data.csproj
@@ -4,10 +4,6 @@
net5.0
false
true
- true
- AllEnabledByDefault
- ../jellyfin.ruleset
- enable
true
true
true
diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj
index ee43c2159a..8cee5dcaee 100644
--- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj
+++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj
@@ -9,10 +9,6 @@
net5.0
false
true
- true
- enable
- AllEnabledByDefault
- ../jellyfin.ruleset
@@ -22,8 +18,8 @@
-
-
+
+
diff --git a/Jellyfin.Networking/Jellyfin.Networking.csproj b/Jellyfin.Networking/Jellyfin.Networking.csproj
index 63557e91f0..227a41ce44 100644
--- a/Jellyfin.Networking/Jellyfin.Networking.csproj
+++ b/Jellyfin.Networking/Jellyfin.Networking.csproj
@@ -3,10 +3,6 @@
net5.0
false
true
- true
- enable
- AllEnabledByDefault
- ../jellyfin.ruleset
diff --git a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs
index 976bb4570c..ba2c8b54f9 100644
--- a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs
+++ b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs
@@ -86,15 +86,12 @@ namespace Jellyfin.Server.Implementations.Activity
private static ActivityLogEntry ConvertToOldModel(ActivityLog entry)
{
- return new ActivityLogEntry
+ return new ActivityLogEntry(entry.Name, entry.Type, entry.UserId)
{
Id = entry.Id,
- Name = entry.Name,
Overview = entry.Overview,
ShortOverview = entry.ShortOverview,
- Type = entry.Type,
ItemId = entry.ItemId,
- UserId = entry.UserId,
Date = entry.DateCreated,
Severity = entry.LogSeverity
};
diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj
index eeeb1d19bf..728f9021dc 100644
--- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj
+++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj
@@ -4,14 +4,6 @@
net5.0
false
true
- true
- enable
- AllEnabledByDefault
- ../jellyfin.ruleset
-
-
-
- ../jellyfin.ruleset
@@ -27,13 +19,13 @@
-
-
-
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
index 15dc438561..f19e87aba5 100644
--- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
+++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
@@ -303,7 +303,7 @@ namespace Jellyfin.Server.Extensions
{
description.TryGetMethodInfo(out MethodInfo methodInfo);
// Attribute name, method name, none.
- return description?.ActionDescriptor?.AttributeRouteInfo?.Name
+ return description?.ActionDescriptor.AttributeRouteInfo?.Name
?? methodInfo?.Name
?? null;
});
@@ -341,7 +341,7 @@ namespace Jellyfin.Server.Extensions
{
foreach (var address in host.GetAddresses())
{
- AddIpAddress(config, options, addr.Address, addr.PrefixLength);
+ AddIpAddress(config, options, address, address.AddressFamily == AddressFamily.InterNetwork ? 32 : 128);
}
}
}
@@ -397,7 +397,7 @@ namespace Jellyfin.Server.Extensions
Type = "object",
Properties = typeof(ImageType).GetEnumNames().ToDictionary(
name => name,
- name => new OpenApiSchema
+ _ => new OpenApiSchema
{
Type = "object",
AdditionalProperties = new OpenApiSchema
diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj
index ea782cb66b..49529b7944 100644
--- a/Jellyfin.Server/Jellyfin.Server.csproj
+++ b/Jellyfin.Server/Jellyfin.Server.csproj
@@ -12,11 +12,6 @@
false
false
true
- true
- enable
- AllEnabledByDefault
- ../jellyfin.ruleset
-
@@ -38,16 +33,16 @@
-
-
-
-
+
+
+
+
-
-
-
+
+
+
diff --git a/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs b/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs
index 2eef223e52..3e5982eedf 100644
--- a/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs
+++ b/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs
@@ -58,9 +58,12 @@ namespace Jellyfin.Server.Middleware
return;
}
- if (!startsWithBaseUrl)
+ if (!startsWithBaseUrl
+ || localPath.Length == baseUrlPrefix.Length
+ // Local path is /baseUrl/
+ || (localPath.Length == baseUrlPrefix.Length + 1 && localPath[^1] == '/'))
{
- // Always redirect back to the default path if the base prefix is invalid or missing
+ // Always redirect back to the default path if the base prefix is invalid, missing, or is the full path.
_logger.LogDebug("Normalizing an URL at {LocalPath}", localPath);
httpContext.Response.Redirect(baseUrlPrefix + "/" + _configuration[ConfigurationExtensions.DefaultRedirectKey]);
return;
diff --git a/Jellyfin.Server/Middleware/ExceptionMiddleware.cs b/Jellyfin.Server/Middleware/ExceptionMiddleware.cs
index f6c76e4d9e..db7877c31e 100644
--- a/Jellyfin.Server/Middleware/ExceptionMiddleware.cs
+++ b/Jellyfin.Server/Middleware/ExceptionMiddleware.cs
@@ -137,11 +137,6 @@ namespace Jellyfin.Server.Middleware
private string NormalizeExceptionMessage(string msg)
{
- if (msg == null)
- {
- return string.Empty;
- }
-
// Strip any information we don't want to reveal
return msg.Replace(
_configuration.ApplicationPaths.ProgramSystemPath,
diff --git a/Jellyfin.Server/Migrations/MigrationRunner.cs b/Jellyfin.Server/Migrations/MigrationRunner.cs
index 2710f94af3..7365c8dbc1 100644
--- a/Jellyfin.Server/Migrations/MigrationRunner.cs
+++ b/Jellyfin.Server/Migrations/MigrationRunner.cs
@@ -41,7 +41,7 @@ namespace Jellyfin.Server.Migrations
.Select(m => ActivatorUtilities.CreateInstance(host.ServiceProvider, m))
.OfType()
.ToArray();
- var migrationOptions = ((IConfigurationManager)host.ConfigurationManager).GetConfiguration(MigrationsListStore.StoreKey);
+ var migrationOptions = host.ConfigurationManager.GetConfiguration(MigrationsListStore.StoreKey);
if (!host.ConfigurationManager.Configuration.IsStartupWizardCompleted && migrationOptions.Applied.Count == 0)
{
diff --git a/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs
index 6048160c63..9e22978aee 100644
--- a/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs
+++ b/Jellyfin.Server/Migrations/Routines/MigrateActivityLogDb.cs
@@ -92,7 +92,7 @@ namespace Jellyfin.Server.Migrations.Routines
if (entry[6].SQLiteType != SQLiteType.Null && !Guid.TryParse(entry[6].ToString(), out guid))
{
// This is not a valid Guid, see if it is an internal ID from an old Emby schema
- _logger.LogWarning("Invalid Guid in UserId column: ", entry[6].ToString());
+ _logger.LogWarning("Invalid Guid in UserId column: {Guid}", entry[6].ToString());
using var statement = userDbConnection.PrepareStatement("SELECT guid FROM LocalUsersv2 WHERE Id=@Id");
statement.TryBind("@Id", entry[6].ToString());
diff --git a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs
index e25d291226..6ff59626de 100644
--- a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs
+++ b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.Json;
diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs
index 3a3d7415bf..7018d537fd 100644
--- a/Jellyfin.Server/Program.cs
+++ b/Jellyfin.Server/Program.cs
@@ -5,7 +5,6 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
-using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -121,11 +120,11 @@ namespace Jellyfin.Server
// Log uncaught exceptions to the logging instead of std error
AppDomain.CurrentDomain.UnhandledException -= UnhandledExceptionToConsole;
- AppDomain.CurrentDomain.UnhandledException += (sender, e)
+ AppDomain.CurrentDomain.UnhandledException += (_, e)
=> _logger.LogCritical((Exception)e.ExceptionObject, "Unhandled Exception");
// Intercept Ctrl+C and Ctrl+Break
- Console.CancelKeyPress += (sender, e) =>
+ Console.CancelKeyPress += (_, e) =>
{
if (_tokenSource.IsCancellationRequested)
{
@@ -139,7 +138,7 @@ namespace Jellyfin.Server
};
// Register a SIGTERM handler
- AppDomain.CurrentDomain.ProcessExit += (sender, e) =>
+ AppDomain.CurrentDomain.ProcessExit += (_, _) =>
{
if (_tokenSource.IsCancellationRequested)
{
@@ -180,7 +179,7 @@ namespace Jellyfin.Server
"The server is expected to host the web client, but the provided content directory is either " +
$"invalid or empty: {webContentPath}. If you do not want to host the web client with the " +
"server, you may set the '--nowebclient' command line flag, or set" +
- $"'{MediaBrowser.Controller.Extensions.ConfigurationExtensions.HostWebClientKey}=false' in your config settings.");
+ $"'{ConfigurationExtensions.HostWebClientKey}=false' in your config settings.");
}
}
@@ -318,8 +317,8 @@ namespace Jellyfin.Server
}
}
- // Bind to unix socket (only on macOS and Linux)
- if (startupConfig.UseUnixSocket() && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ // Bind to unix socket (only on unix systems)
+ if (startupConfig.UseUnixSocket() && Environment.OSVersion.Platform == PlatformID.Unix)
{
var socketPath = startupConfig.GetUnixSocketPath();
if (string.IsNullOrEmpty(socketPath))
@@ -404,7 +403,7 @@ namespace Jellyfin.Server
{
if (options.DataDir != null
|| Directory.Exists(Path.Combine(dataDir, "config"))
- || RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ || OperatingSystem.IsWindows())
{
// Hang config folder off already set dataDir
configDir = Path.Combine(dataDir, "config");
@@ -442,7 +441,7 @@ namespace Jellyfin.Server
if (string.IsNullOrEmpty(cacheDir))
{
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ if (OperatingSystem.IsWindows())
{
// Hang cache folder off already set dataDir
cacheDir = Path.Combine(dataDir, "cache");
@@ -543,7 +542,7 @@ namespace Jellyfin.Server
// Get a stream of the resource contents
// NOTE: The .csproj name is used instead of the assembly name in the resource path
const string ResourcePath = "Jellyfin.Server.Resources.Configuration.logging.json";
- await using Stream? resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath)
+ await using Stream resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath)
?? throw new InvalidOperationException($"Invalid resource path: '{ResourcePath}'");
// Copy the resource contents to the expected file path for the config file
diff --git a/MediaBrowser.Common/Extensions/ProcessExtensions.cs b/MediaBrowser.Common/Extensions/ProcessExtensions.cs
index c747871222..08e01bfd65 100644
--- a/MediaBrowser.Common/Extensions/ProcessExtensions.cs
+++ b/MediaBrowser.Common/Extensions/ProcessExtensions.cs
@@ -40,7 +40,7 @@ namespace MediaBrowser.Common.Extensions
// Add an event handler for the process exit event
var tcs = new TaskCompletionSource();
- process.Exited += (sender, args) => tcs.TrySetResult(true);
+ process.Exited += (_, _) => tcs.TrySetResult(true);
// Return immediately if the process has already exited
if (process.HasExitedSafe())
diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj
index 0299a84563..12cfaf9789 100644
--- a/MediaBrowser.Common/MediaBrowser.Common.csproj
+++ b/MediaBrowser.Common/MediaBrowser.Common.csproj
@@ -32,10 +32,6 @@
net5.0
false
true
- true
- enable
- AllEnabledByDefault
- ../jellyfin.ruleset
true
true
true
diff --git a/MediaBrowser.Common/Net/IPHost.cs b/MediaBrowser.Common/Net/IPHost.cs
index 5db8817ee6..d78d7def2b 100644
--- a/MediaBrowser.Common/Net/IPHost.cs
+++ b/MediaBrowser.Common/Net/IPHost.cs
@@ -79,16 +79,11 @@ namespace MediaBrowser.Common.Net
///
public override byte PrefixLength
{
- get
- {
- return (byte)(ResolveHost() ? 128 : 32);
- }
+ get => (byte)(ResolveHost() ? 128 : 32);
- set
- {
- // Not implemented, as a host object can only have a prefix length of 128 (IPv6) or 32 (IPv4) prefix length,
- // which is automatically determined by it's IP type. Anything else is meaningless.
- }
+ // Not implemented, as a host object can only have a prefix length of 128 (IPv6) or 32 (IPv4) prefix length,
+ // which is automatically determined by it's IP type. Anything else is meaningless.
+ set => throw new NotImplementedException();
}
///
diff --git a/MediaBrowser.Common/Providers/ProviderIdParsers.cs b/MediaBrowser.Common/Providers/ProviderIdParsers.cs
index 33d09ed385..487b5a6d29 100644
--- a/MediaBrowser.Common/Providers/ProviderIdParsers.cs
+++ b/MediaBrowser.Common/Providers/ProviderIdParsers.cs
@@ -18,7 +18,7 @@ namespace MediaBrowser.Common.Providers
/// The text to parse.
/// The parsed IMDb id.
/// True if parsing was successful, false otherwise.
- public static bool TryFindImdbId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan imdbId)
+ public static bool TryFindImdbId(ReadOnlySpan text, out ReadOnlySpan imdbId)
{
// imdb id is at least 9 chars (tt + 7 numbers)
while (text.Length >= 2 + ImdbMinNumbers)
@@ -62,7 +62,7 @@ namespace MediaBrowser.Common.Providers
/// The text with the url to parse.
/// The parsed TMDb id.
/// True if parsing was successful, false otherwise.
- public static bool TryFindTmdbMovieId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan tmdbId)
+ public static bool TryFindTmdbMovieId(ReadOnlySpan text, out ReadOnlySpan tmdbId)
=> TryFindProviderId(text, "themoviedb.org/movie/", out tmdbId);
///
@@ -71,7 +71,7 @@ namespace MediaBrowser.Common.Providers
/// The text with the url to parse.
/// The parsed TMDb id.
/// True if parsing was successful, false otherwise.
- public static bool TryFindTmdbSeriesId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan tmdbId)
+ public static bool TryFindTmdbSeriesId(ReadOnlySpan text, out ReadOnlySpan tmdbId)
=> TryFindProviderId(text, "themoviedb.org/tv/", out tmdbId);
///
@@ -80,7 +80,7 @@ namespace MediaBrowser.Common.Providers
/// The text with the url to parse.
/// The parsed TVDb id.
/// True if parsing was successful, false otherwise.
- public static bool TryFindTvdbId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan tvdbId)
+ public static bool TryFindTvdbId(ReadOnlySpan text, out ReadOnlySpan tvdbId)
=> TryFindProviderId(text, "thetvdb.com/?tab=series&id=", out tvdbId);
private static bool TryFindProviderId(ReadOnlySpan text, ReadOnlySpan searchString, [NotNullWhen(true)] out ReadOnlySpan providerId)
diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs
index 26a936be0c..e6923b55ca 100644
--- a/MediaBrowser.Controller/Channels/Channel.cs
+++ b/MediaBrowser.Controller/Channels/Channel.cs
@@ -17,6 +17,12 @@ namespace MediaBrowser.Controller.Channels
{
public class Channel : Folder
{
+ [JsonIgnore]
+ public override bool SupportsInheritedParentImages => false;
+
+ [JsonIgnore]
+ public override SourceType SourceType => SourceType.Channel;
+
public override bool IsVisible(User user)
{
var blockedChannelsPreference = user.GetPreferenceValues(PreferenceKind.BlockedChannels);
@@ -39,12 +45,6 @@ namespace MediaBrowser.Controller.Channels
return base.IsVisible(user);
}
- [JsonIgnore]
- public override bool SupportsInheritedParentImages => false;
-
- [JsonIgnore]
- public override SourceType SourceType => SourceType.Channel;
-
protected override QueryResult GetItemsInternal(InternalItemsQuery query)
{
try
diff --git a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs
index 4d1e35f9ea..55f80b240f 100644
--- a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs
+++ b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CA2227, CS1591
using System;
using System.Collections.Generic;
diff --git a/MediaBrowser.Controller/Channels/ChannelItemResult.cs b/MediaBrowser.Controller/Channels/ChannelItemResult.cs
index 6b20776629..7a0addd9f9 100644
--- a/MediaBrowser.Controller/Channels/ChannelItemResult.cs
+++ b/MediaBrowser.Controller/Channels/ChannelItemResult.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CA2227, CS1591
using System.Collections.Generic;
diff --git a/MediaBrowser.Controller/Channels/IHasFolderAttributes.cs b/MediaBrowser.Controller/Channels/IHasFolderAttributes.cs
index 47277a8cc8..64af8496c7 100644
--- a/MediaBrowser.Controller/Channels/IHasFolderAttributes.cs
+++ b/MediaBrowser.Controller/Channels/IHasFolderAttributes.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1819, CS1591
namespace MediaBrowser.Controller.Channels
{
diff --git a/MediaBrowser.Controller/Channels/InternalChannelFeatures.cs b/MediaBrowser.Controller/Channels/InternalChannelFeatures.cs
index 45cd08173a..394996868e 100644
--- a/MediaBrowser.Controller/Channels/InternalChannelFeatures.cs
+++ b/MediaBrowser.Controller/Channels/InternalChannelFeatures.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CA2227, CS1591
using System.Collections.Generic;
using MediaBrowser.Model.Channels;
diff --git a/MediaBrowser.Controller/Chapters/IChapterManager.cs b/MediaBrowser.Controller/Chapters/IChapterManager.cs
index f82e5b41a2..c049bb97e7 100644
--- a/MediaBrowser.Controller/Chapters/IChapterManager.cs
+++ b/MediaBrowser.Controller/Chapters/IChapterManager.cs
@@ -12,6 +12,8 @@ namespace MediaBrowser.Controller.Chapters
///
/// Saves the chapters.
///
+ /// The item.
+ /// The set of chapters.
void SaveChapters(Guid itemId, IReadOnlyList chapters);
}
}
diff --git a/MediaBrowser.Controller/Collections/CollectionCreationOptions.cs b/MediaBrowser.Controller/Collections/CollectionCreationOptions.cs
index 30f5f4efa2..76ad335c59 100644
--- a/MediaBrowser.Controller/Collections/CollectionCreationOptions.cs
+++ b/MediaBrowser.Controller/Collections/CollectionCreationOptions.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA2227, CS1591
using System;
using System.Collections.Generic;
diff --git a/MediaBrowser.Controller/Collections/ICollectionManager.cs b/MediaBrowser.Controller/Collections/ICollectionManager.cs
index 46bc37e7f6..49cc39f047 100644
--- a/MediaBrowser.Controller/Collections/ICollectionManager.cs
+++ b/MediaBrowser.Controller/Collections/ICollectionManager.cs
@@ -32,6 +32,7 @@ namespace MediaBrowser.Controller.Collections
/// Creates the collection.
///
/// The options.
+ /// BoxSet wrapped in an awaitable task.
Task CreateCollectionAsync(CollectionCreationOptions options);
///
diff --git a/MediaBrowser.Controller/Drawing/IImageEncoder.cs b/MediaBrowser.Controller/Drawing/IImageEncoder.cs
index 4e640d4215..4e67cfee4f 100644
--- a/MediaBrowser.Controller/Drawing/IImageEncoder.cs
+++ b/MediaBrowser.Controller/Drawing/IImageEncoder.cs
@@ -57,6 +57,15 @@ namespace MediaBrowser.Controller.Drawing
///
/// Encode an image.
///
+ /// Input path of image.
+ /// Date modified.
+ /// Output path of image.
+ /// Auto-orient image.
+ /// Desired orientation of image.
+ /// Quality of encoded image.
+ /// Image processing options.
+ /// Image format of output.
+ /// Path of encoded image.
string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat outputFormat);
///
diff --git a/MediaBrowser.Controller/Drawing/ImageStream.cs b/MediaBrowser.Controller/Drawing/ImageStream.cs
index 5ee781ffa9..5d552170f9 100644
--- a/MediaBrowser.Controller/Drawing/ImageStream.cs
+++ b/MediaBrowser.Controller/Drawing/ImageStream.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1711, CS1591
using System;
using System.IO;
diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs
index 61d7962357..89aafc84fb 100644
--- a/MediaBrowser.Controller/Dto/IDtoService.cs
+++ b/MediaBrowser.Controller/Dto/IDtoService.cs
@@ -1,4 +1,5 @@
#nullable disable
+#pragma warning disable CA1002
using System.Collections.Generic;
using Jellyfin.Data.Entities;
diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs
index fe1bc62aba..9589f52452 100644
--- a/MediaBrowser.Controller/Entities/AggregateFolder.cs
+++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1819, CS1591
using System;
using System.Collections.Concurrent;
@@ -18,32 +18,23 @@ namespace MediaBrowser.Controller.Entities
{
///
/// Specialized folder that can have items added to it's children by external entities.
- /// Used for our RootFolder so plug-ins can add items.
+ /// Used for our RootFolder so plugins can add items.
///
public class AggregateFolder : Folder
{
- private bool _requiresRefresh;
-
- public AggregateFolder()
- {
- PhysicalLocationsList = Array.Empty();
- }
-
- [JsonIgnore]
- public override bool IsPhysicalRoot => true;
-
- public override bool CanDelete()
- {
- return false;
- }
-
- [JsonIgnore]
- public override bool SupportsPlayedStatus => false;
+ private readonly object _childIdsLock = new object();
///
/// The _virtual children.
///
private readonly ConcurrentBag _virtualChildren = new ConcurrentBag();
+ private bool _requiresRefresh;
+ private Guid[] _childrenIds = null;
+
+ public AggregateFolder()
+ {
+ PhysicalLocationsList = Array.Empty();
+ }
///
/// Gets the virtual children.
@@ -51,19 +42,27 @@ namespace MediaBrowser.Controller.Entities
/// The virtual children.
public ConcurrentBag VirtualChildren => _virtualChildren;
+ [JsonIgnore]
+ public override bool IsPhysicalRoot => true;
+
+ [JsonIgnore]
+ public override bool SupportsPlayedStatus => false;
+
[JsonIgnore]
public override string[] PhysicalLocations => PhysicalLocationsList;
public string[] PhysicalLocationsList { get; set; }
+ public override bool CanDelete()
+ {
+ return false;
+ }
+
protected override FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService)
{
return CreateResolveArgs(directoryService, true).FileSystemChildren;
}
- private Guid[] _childrenIds = null;
- private readonly object _childIdsLock = new object();
-
protected override List LoadChildren()
{
lock (_childIdsLock)
@@ -169,7 +168,7 @@ namespace MediaBrowser.Controller.Entities
/// Adds the virtual child.
///
/// The child.
- ///
+ /// Throws if child is null.
public void AddVirtualChild(BaseItem child)
{
if (child == null)
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs
index 576ab67a22..7bf1219ec2 100644
--- a/MediaBrowser.Controller/Entities/Audio/Audio.cs
+++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CA1724, CA1826, CS1591
using System;
using System.Collections.Generic;
@@ -25,6 +25,12 @@ namespace MediaBrowser.Controller.Entities.Audio
IHasLookupInfo,
IHasMediaSources
{
+ public Audio()
+ {
+ Artists = Array.Empty();
+ AlbumArtists = Array.Empty();
+ }
+
///
[JsonIgnore]
public IReadOnlyList Artists { get; set; }
@@ -33,17 +39,6 @@ namespace MediaBrowser.Controller.Entities.Audio
[JsonIgnore]
public IReadOnlyList AlbumArtists { get; set; }
- public Audio()
- {
- Artists = Array.Empty();
- AlbumArtists = Array.Empty();
- }
-
- public override double GetDefaultPrimaryImageAspectRatio()
- {
- return 1;
- }
-
[JsonIgnore]
public override bool SupportsPlayedStatus => true;
@@ -62,11 +57,6 @@ namespace MediaBrowser.Controller.Entities.Audio
[JsonIgnore]
public override Folder LatestItemsIndexContainer => AlbumEntity;
- public override bool CanDownload()
- {
- return IsFileProtocol;
- }
-
[JsonIgnore]
public MusicAlbum AlbumEntity => FindParent();
@@ -77,6 +67,16 @@ namespace MediaBrowser.Controller.Entities.Audio
[JsonIgnore]
public override string MediaType => Model.Entities.MediaType.Audio;
+ public override double GetDefaultPrimaryImageAspectRatio()
+ {
+ return 1;
+ }
+
+ public override bool CanDownload()
+ {
+ return IsFileProtocol;
+ }
+
///
/// Creates the name of the sort.
///
diff --git a/MediaBrowser.Controller/Entities/Audio/IHasMusicGenres.cs b/MediaBrowser.Controller/Entities/Audio/IHasMusicGenres.cs
index db60c3071d..c2dae5a2dc 100644
--- a/MediaBrowser.Controller/Entities/Audio/IHasMusicGenres.cs
+++ b/MediaBrowser.Controller/Entities/Audio/IHasMusicGenres.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1819, CS1591
namespace MediaBrowser.Controller.Entities.Audio
{
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index 610bce4f5f..03d1f33043 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1721, CA1826, CS1591
using System;
using System.Collections.Generic;
@@ -23,18 +23,18 @@ namespace MediaBrowser.Controller.Entities.Audio
///
public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo, IMetadataContainer
{
- ///
- public IReadOnlyList AlbumArtists { get; set; }
-
- ///
- public IReadOnlyList Artists { get; set; }
-
public MusicAlbum()
{
Artists = Array.Empty();
AlbumArtists = Array.Empty();
}
+ ///
+ public IReadOnlyList AlbumArtists { get; set; }
+
+ ///
+ public IReadOnlyList Artists { get; set; }
+
[JsonIgnore]
public override bool SupportsAddingToPlaylist => true;
@@ -44,6 +44,25 @@ namespace MediaBrowser.Controller.Entities.Audio
[JsonIgnore]
public MusicArtist MusicArtist => GetMusicArtist(new DtoOptions(true));
+ [JsonIgnore]
+ public override bool SupportsPlayedStatus => false;
+
+ [JsonIgnore]
+ public override bool SupportsCumulativeRunTimeTicks => true;
+
+ [JsonIgnore]
+ public string AlbumArtist => AlbumArtists.FirstOrDefault();
+
+ [JsonIgnore]
+ public override bool SupportsPeople => false;
+
+ ///
+ /// Gets the tracks.
+ ///
+ /// The tracks.
+ [JsonIgnore]
+ public IEnumerable
public class MusicGenre : BaseItem, IItemByName
{
- public override List GetUserDataKeys()
- {
- var list = base.GetUserDataKeys();
-
- list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
- return list;
- }
-
- public override string CreatePresentationUniqueKey()
- {
- return GetUserDataKeys()[0];
- }
-
[JsonIgnore]
public override bool SupportsAddingToPlaylist => true;
@@ -45,6 +32,22 @@ namespace MediaBrowser.Controller.Entities.Audio
[JsonIgnore]
public override string ContainingFolderPath => Path;
+ [JsonIgnore]
+ public override bool SupportsPeople => false;
+
+ public override List GetUserDataKeys()
+ {
+ var list = base.GetUserDataKeys();
+
+ list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
+ return list;
+ }
+
+ public override string CreatePresentationUniqueKey()
+ {
+ return GetUserDataKeys()[0];
+ }
+
public override double GetDefaultPrimaryImageAspectRatio()
{
return 1;
@@ -60,9 +63,6 @@ namespace MediaBrowser.Controller.Entities.Audio
return true;
}
- [JsonIgnore]
- public override bool SupportsPeople => false;
-
public IList GetTaggedItems(InternalItemsQuery query)
{
query.GenreIds = new[] { Id };
@@ -106,6 +106,8 @@ namespace MediaBrowser.Controller.Entities.Audio
///
/// This is called before any metadata refresh and returns true or false indicating if changes were made.
///
+ /// Option to replace metadata.
+ /// True if metadata changed.
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
{
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
diff --git a/MediaBrowser.Controller/Entities/AudioBook.cs b/MediaBrowser.Controller/Entities/AudioBook.cs
index 4052846228..782481fbcd 100644
--- a/MediaBrowser.Controller/Entities/AudioBook.cs
+++ b/MediaBrowser.Controller/Entities/AudioBook.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1724, CS1591
using System;
using System.Text.Json.Serialization;
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index e5be5421a2..23b97f70c6 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -771,19 +771,6 @@ namespace MediaBrowser.Controller.Entities
[JsonIgnore]
public Guid ParentId { get; set; }
- ///
- /// Gets or sets the parent.
- ///
- /// The parent.
- [JsonIgnore]
- public Folder Parent
- {
- get => GetParent() as Folder;
- set
- {
- }
- }
-
public void SetParent(Folder parent)
{
ParentId = parent == null ? Guid.Empty : parent.Id;
@@ -822,8 +809,7 @@ namespace MediaBrowser.Controller.Entities
{
foreach (var parent in GetParents())
{
- var item = parent as T;
- if (item != null)
+ if (parent is T item)
{
return item;
}
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 5417474221..34ad5bbbb6 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CA1721, CA1819, CS1591
using System;
using System.Collections.Generic;
@@ -165,6 +165,8 @@ namespace MediaBrowser.Controller.Entities
}
}
+ public static ICollectionManager CollectionManager { get; set; }
+
public override bool CanDelete()
{
if (IsRoot)
@@ -206,9 +208,8 @@ namespace MediaBrowser.Controller.Entities
/// Adds the child.
///
/// The item.
- /// The cancellation token.
/// Unable to add + item.Name.
- public void AddChild(BaseItem item, CancellationToken cancellationToken)
+ public void AddChild(BaseItem item)
{
item.SetParent(this);
@@ -259,6 +260,7 @@ namespace MediaBrowser.Controller.Entities
/// Loads our children. Validation will occur externally.
/// We want this synchronous.
///
+ /// Returns children.
protected virtual List LoadChildren()
{
// logger.LogDebug("Loading children from {0} {1} {2}", GetType().Name, Id, Path);
@@ -643,6 +645,8 @@ namespace MediaBrowser.Controller.Entities
/// Get the children of this folder from the actual file system.
///
/// IEnumerable{BaseItem}.
+ /// The directory service to use for operation.
+ /// Returns set of base items.
protected virtual IEnumerable GetNonCachedChildren(IDirectoryService directoryService)
{
var collectionType = LibraryManager.GetContentType(this);
@@ -999,8 +1003,6 @@ namespace MediaBrowser.Controller.Entities
return PostFilterAndSort(items, query, true);
}
- public static ICollectionManager CollectionManager { get; set; }
-
protected QueryResult PostFilterAndSort(IEnumerable items, InternalItemsQuery query, bool enableSorting)
{
var user = query.User;
@@ -1385,18 +1387,6 @@ namespace MediaBrowser.Controller.Entities
}
}
- ///
- /// Gets allowed recursive children of an item.
- ///
- /// The user.
- /// if set to true [include linked children].
- /// IEnumerable{BaseItem}.
- ///
- public IEnumerable GetRecursiveChildren(User user, bool includeLinkedChildren = true)
- {
- return GetRecursiveChildren(user, null);
- }
-
public virtual IEnumerable GetRecursiveChildren(User user, InternalItemsQuery query)
{
if (user == null)
diff --git a/MediaBrowser.Controller/Entities/ICollectionFolder.cs b/MediaBrowser.Controller/Entities/ICollectionFolder.cs
index 2304570fd7..89e494ebc3 100644
--- a/MediaBrowser.Controller/Entities/ICollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/ICollectionFolder.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1819, CS1591
using System;
diff --git a/MediaBrowser.Controller/Entities/IHasShares.cs b/MediaBrowser.Controller/Entities/IHasShares.cs
index bdde744a37..dca5af873f 100644
--- a/MediaBrowser.Controller/Entities/IHasShares.cs
+++ b/MediaBrowser.Controller/Entities/IHasShares.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1819, CS1591
namespace MediaBrowser.Controller.Entities
{
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
index ebaf5506d6..0baa7725e1 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1044, CA1819, CA2227, CS1591
using System;
using System.Collections.Generic;
@@ -12,6 +12,55 @@ namespace MediaBrowser.Controller.Entities
{
public class InternalItemsQuery
{
+ public InternalItemsQuery()
+ {
+ AlbumArtistIds = Array.Empty();
+ AlbumIds = Array.Empty();
+ AncestorIds = Array.Empty();
+ ArtistIds = Array.Empty();
+ BlockUnratedItems = Array.Empty();
+ BoxSetLibraryFolders = Array.Empty();
+ ChannelIds = Array.Empty();
+ ContributingArtistIds = Array.Empty();
+ DtoOptions = new DtoOptions();
+ EnableTotalRecordCount = true;
+ ExcludeArtistIds = Array.Empty();
+ ExcludeInheritedTags = Array.Empty();
+ ExcludeItemIds = Array.Empty();
+ ExcludeItemTypes = Array.Empty();
+ ExcludeTags = Array.Empty();
+ GenreIds = Array.Empty();
+ Genres = Array.Empty();
+ GroupByPresentationUniqueKey = true;
+ ImageTypes = Array.Empty();
+ IncludeItemTypes = Array.Empty();
+ ItemIds = Array.Empty();
+ MediaTypes = Array.Empty();
+ MinSimilarityScore = 20;
+ OfficialRatings = Array.Empty();
+ OrderBy = Array.Empty>();
+ PersonIds = Array.Empty();
+ PersonTypes = Array.Empty();
+ PresetViews = Array.Empty();
+ SeriesStatuses = Array.Empty();
+ SourceTypes = Array.Empty();
+ StudioIds = Array.Empty();
+ Tags = Array.Empty();
+ TopParentIds = Array.Empty();
+ TrailerTypes = Array.Empty();
+ VideoTypes = Array.Empty();
+ Years = Array.Empty();
+ }
+
+ public InternalItemsQuery(User? user)
+ : this()
+ {
+ if (user != null)
+ {
+ SetUser(user);
+ }
+ }
+
public bool Recursive { get; set; }
public int? StartIndex { get; set; }
@@ -186,23 +235,6 @@ namespace MediaBrowser.Controller.Entities
public Guid[] TopParentIds { get; set; }
- public BaseItem? Parent
- {
- set
- {
- if (value == null)
- {
- ParentId = Guid.Empty;
- ParentType = null;
- }
- else
- {
- ParentId = value.Id;
- ParentType = value.GetType().Name;
- }
- }
- }
-
public string[] PresetViews { get; set; }
public TrailerType[] TrailerTypes { get; set; }
@@ -270,72 +302,23 @@ namespace MediaBrowser.Controller.Entities
///
public bool? DisplayAlbumFolders { get; set; }
- public InternalItemsQuery()
+ public BaseItem? Parent
{
- AlbumArtistIds = Array.Empty();
- AlbumIds = Array.Empty();
- AncestorIds = Array.Empty();
- ArtistIds = Array.Empty();
- BlockUnratedItems = Array.Empty();
- BoxSetLibraryFolders = Array.Empty();
- ChannelIds = Array.Empty();
- ContributingArtistIds = Array.Empty();
- DtoOptions = new DtoOptions();
- EnableTotalRecordCount = true;
- ExcludeArtistIds = Array.Empty();
- ExcludeInheritedTags = Array.Empty();
- ExcludeItemIds = Array.Empty();
- ExcludeItemTypes = Array.Empty();
- ExcludeTags = Array.Empty();
- GenreIds = Array.Empty();
- Genres = Array.Empty();
- GroupByPresentationUniqueKey = true;
- ImageTypes = Array.Empty();
- IncludeItemTypes = Array.Empty();
- ItemIds = Array.Empty();
- MediaTypes = Array.Empty();
- MinSimilarityScore = 20;
- OfficialRatings = Array.Empty();
- OrderBy = Array.Empty>();
- PersonIds = Array.Empty();
- PersonTypes = Array.Empty();
- PresetViews = Array.Empty();
- SeriesStatuses = Array.Empty();
- SourceTypes = Array.Empty();
- StudioIds = Array.Empty();
- Tags = Array.Empty();
- TopParentIds = Array.Empty();
- TrailerTypes = Array.Empty();
- VideoTypes = Array.Empty();
- Years = Array.Empty();
- }
-
- public InternalItemsQuery(User? user)
- : this()
- {
- if (user != null)
+ set
{
- SetUser(user);
+ if (value == null)
+ {
+ ParentId = Guid.Empty;
+ ParentType = null;
+ }
+ else
+ {
+ ParentId = value.Id;
+ ParentType = value.GetType().Name;
+ }
}
}
- public void SetUser(User user)
- {
- MaxParentalRating = user.MaxParentalAgeRating;
-
- if (MaxParentalRating.HasValue)
- {
- string other = UnratedItem.Other.ToString();
- BlockUnratedItems = user.GetPreference(PreferenceKind.BlockUnratedItems)
- .Where(i => i != other)
- .Select(e => Enum.Parse(e, true)).ToArray();
- }
-
- ExcludeInheritedTags = user.GetPreference(PreferenceKind.BlockedTags);
-
- User = user;
- }
-
public Dictionary? HasAnyProviderId { get; set; }
public Guid[] AlbumArtistIds { get; set; }
@@ -361,5 +344,22 @@ namespace MediaBrowser.Controller.Entities
public string? SearchTerm { get; set; }
public string? SeriesTimerId { get; set; }
+
+ public void SetUser(User user)
+ {
+ MaxParentalRating = user.MaxParentalAgeRating;
+
+ if (MaxParentalRating.HasValue)
+ {
+ string other = UnratedItem.Other.ToString();
+ BlockUnratedItems = user.GetPreference(PreferenceKind.BlockUnratedItems)
+ .Where(i => i != other)
+ .Select(e => Enum.Parse(e, true)).ToArray();
+ }
+
+ ExcludeInheritedTags = user.GetPreference(PreferenceKind.BlockedTags);
+
+ User = user;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
index 74e84288d1..e46f99cd57 100644
--- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
+++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1721, CA1819, CS1591
using System;
using System.Collections.Generic;
@@ -49,6 +49,30 @@ namespace MediaBrowser.Controller.Entities.Movies
/// The display order.
public string DisplayOrder { get; set; }
+ [JsonIgnore]
+ private bool IsLegacyBoxSet
+ {
+ get
+ {
+ if (string.IsNullOrEmpty(Path))
+ {
+ return false;
+ }
+
+ if (LinkedChildren.Length > 0)
+ {
+ return false;
+ }
+
+ return !FileSystem.ContainsSubPath(ConfigurationManager.ApplicationPaths.DataPath, Path);
+ }
+ }
+
+ [JsonIgnore]
+ public override bool IsPreSorted => true;
+
+ public Guid[] LibraryFolderIds { get; set; }
+
protected override bool GetBlockUnratedValue(User user)
{
return user.GetPreferenceValues(PreferenceKind.BlockUnratedItems).Contains(UnratedItem.Movie);
@@ -83,28 +107,6 @@ namespace MediaBrowser.Controller.Entities.Movies
return new List();
}
- [JsonIgnore]
- private bool IsLegacyBoxSet
- {
- get
- {
- if (string.IsNullOrEmpty(Path))
- {
- return false;
- }
-
- if (LinkedChildren.Length > 0)
- {
- return false;
- }
-
- return !FileSystem.ContainsSubPath(ConfigurationManager.ApplicationPaths.DataPath, Path);
- }
- }
-
- [JsonIgnore]
- public override bool IsPreSorted => true;
-
public override bool IsAuthorizedToDelete(User user, List allCollectionFolders)
{
return true;
@@ -191,8 +193,6 @@ namespace MediaBrowser.Controller.Entities.Movies
return IsVisible(user);
}
- public Guid[] LibraryFolderIds { get; set; }
-
private Guid[] GetLibraryFolderIds(User user)
{
return LibraryManager.GetUserRootFolder().GetChildren(user, true)
diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs
index b0ab280af4..b9e37269e4 100644
--- a/MediaBrowser.Controller/Entities/Person.cs
+++ b/MediaBrowser.Controller/Entities/Person.cs
@@ -16,6 +16,26 @@ namespace MediaBrowser.Controller.Entities
///
public class Person : BaseItem, IItemByName, IHasLookupInfo
{
+ ///
+ /// Gets the folder containing the item.
+ /// If the item is a folder, it returns the folder itself.
+ ///
+ /// The containing folder path.
+ [JsonIgnore]
+ public override string ContainingFolderPath => Path;
+
+ ///
+ /// Gets a value indicating whether to enable alpha numeric sorting.
+ ///
+ [JsonIgnore]
+ public override bool EnableAlphaNumericSorting => false;
+
+ [JsonIgnore]
+ public override bool SupportsPeople => false;
+
+ [JsonIgnore]
+ public override bool SupportsAncestors => false;
+
public override List GetUserDataKeys()
{
var list = base.GetUserDataKeys();
@@ -49,14 +69,6 @@ namespace MediaBrowser.Controller.Entities
return LibraryManager.GetItemList(query);
}
- ///
- /// Gets the folder containing the item.
- /// If the item is a folder, it returns the folder itself.
- ///
- /// The containing folder path.
- [JsonIgnore]
- public override string ContainingFolderPath => Path;
-
public override bool CanDelete()
{
return false;
@@ -67,18 +79,6 @@ namespace MediaBrowser.Controller.Entities
return true;
}
- ///
- /// Gets a value indicating whether to enable alpha numeric sorting.
- ///
- [JsonIgnore]
- public override bool EnableAlphaNumericSorting => false;
-
- [JsonIgnore]
- public override bool SupportsPeople => false;
-
- [JsonIgnore]
- public override bool SupportsAncestors => false;
-
public static string GetPath(string name)
{
return GetPath(name, true);
diff --git a/MediaBrowser.Controller/Entities/PersonInfo.cs b/MediaBrowser.Controller/Entities/PersonInfo.cs
index fb79323f8f..2b689ae7e2 100644
--- a/MediaBrowser.Controller/Entities/PersonInfo.cs
+++ b/MediaBrowser.Controller/Entities/PersonInfo.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA2227, CS1591
using System;
using System.Collections.Generic;
diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs
index 3312a0e3e2..ba6ce189ac 100644
--- a/MediaBrowser.Controller/Entities/Photo.cs
+++ b/MediaBrowser.Controller/Entities/Photo.cs
@@ -36,6 +36,30 @@ namespace MediaBrowser.Controller.Entities
}
}
+ public string CameraMake { get; set; }
+
+ public string CameraModel { get; set; }
+
+ public string Software { get; set; }
+
+ public double? ExposureTime { get; set; }
+
+ public double? FocalLength { get; set; }
+
+ public ImageOrientation? Orientation { get; set; }
+
+ public double? Aperture { get; set; }
+
+ public double? ShutterSpeed { get; set; }
+
+ public double? Latitude { get; set; }
+
+ public double? Longitude { get; set; }
+
+ public double? Altitude { get; set; }
+
+ public int? IsoSpeedRating { get; set; }
+
public override bool CanDownload()
{
return true;
@@ -69,29 +93,5 @@ namespace MediaBrowser.Controller.Entities
return base.GetDefaultPrimaryImageAspectRatio();
}
-
- public string CameraMake { get; set; }
-
- public string CameraModel { get; set; }
-
- public string Software { get; set; }
-
- public double? ExposureTime { get; set; }
-
- public double? FocalLength { get; set; }
-
- public ImageOrientation? Orientation { get; set; }
-
- public double? Aperture { get; set; }
-
- public double? ShutterSpeed { get; set; }
-
- public double? Latitude { get; set; }
-
- public double? Longitude { get; set; }
-
- public double? Altitude { get; set; }
-
- public int? IsoSpeedRating { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs
index 888b300012..556624e14e 100644
--- a/MediaBrowser.Controller/Entities/Studio.cs
+++ b/MediaBrowser.Controller/Entities/Studio.cs
@@ -15,19 +15,6 @@ namespace MediaBrowser.Controller.Entities
///
public class Studio : BaseItem, IItemByName
{
- public override List GetUserDataKeys()
- {
- var list = base.GetUserDataKeys();
-
- list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
- return list;
- }
-
- public override string CreatePresentationUniqueKey()
- {
- return GetUserDataKeys()[0];
- }
-
///
/// Gets the folder containing the item.
/// If the item is a folder, it returns the folder itself.
@@ -42,6 +29,22 @@ namespace MediaBrowser.Controller.Entities
[JsonIgnore]
public override bool SupportsAncestors => false;
+ [JsonIgnore]
+ public override bool SupportsPeople => false;
+
+ public override List GetUserDataKeys()
+ {
+ var list = base.GetUserDataKeys();
+
+ list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
+ return list;
+ }
+
+ public override string CreatePresentationUniqueKey()
+ {
+ return GetUserDataKeys()[0];
+ }
+
public override double GetDefaultPrimaryImageAspectRatio()
{
double value = 16;
@@ -67,9 +70,6 @@ namespace MediaBrowser.Controller.Entities
return LibraryManager.GetItemList(query);
}
- [JsonIgnore]
- public override bool SupportsPeople => false;
-
public static string GetPath(string name)
{
return GetPath(name, true);
diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs
index 732b45521b..1c558d4196 100644
--- a/MediaBrowser.Controller/Entities/Trailer.cs
+++ b/MediaBrowser.Controller/Entities/Trailer.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1819, CS1591
using System;
using System.Collections.Generic;
@@ -23,6 +23,9 @@ namespace MediaBrowser.Controller.Entities
TrailerTypes = Array.Empty();
}
+ [JsonIgnore]
+ public override bool StopRefreshIfLocalMetadataFound => false;
+
public TrailerType[] TrailerTypes { get; set; }
public override double GetDefaultPrimaryImageAspectRatio()
@@ -97,8 +100,5 @@ namespace MediaBrowser.Controller.Entities
return list;
}
-
- [JsonIgnore]
- public override bool StopRefreshIfLocalMetadataFound => false;
}
}
diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs
index 57dc9b59ba..62f3c4b557 100644
--- a/MediaBrowser.Controller/Entities/UserView.cs
+++ b/MediaBrowser.Controller/Entities/UserView.cs
@@ -15,6 +15,25 @@ namespace MediaBrowser.Controller.Entities
{
public class UserView : Folder, IHasCollectionType
{
+ private static readonly string[] _viewTypesEligibleForGrouping = new string[]
+ {
+ Model.Entities.CollectionType.Movies,
+ Model.Entities.CollectionType.TvShows,
+ string.Empty
+ };
+
+ private static readonly string[] _originalFolderViewTypes = new string[]
+ {
+ Model.Entities.CollectionType.Books,
+ Model.Entities.CollectionType.MusicVideos,
+ Model.Entities.CollectionType.HomeVideos,
+ Model.Entities.CollectionType.Photos,
+ Model.Entities.CollectionType.Music,
+ Model.Entities.CollectionType.BoxSets
+ };
+
+ public static ITVSeriesManager TVSeriesManager { get; set; }
+
///
/// Gets or sets the view type.
///
@@ -30,12 +49,22 @@ namespace MediaBrowser.Controller.Entities
///
public Guid? UserId { get; set; }
- public static ITVSeriesManager TVSeriesManager;
-
///
[JsonIgnore]
public string CollectionType => ViewType;
+ ///
+ [JsonIgnore]
+ public override bool SupportsInheritedParentImages => false;
+
+ ///
+ [JsonIgnore]
+ public override bool SupportsPlayedStatus => false;
+
+ ///
+ [JsonIgnore]
+ public override bool SupportsPeople => false;
+
///
public override IEnumerable GetIdsForAncestorQuery()
{
@@ -53,17 +82,13 @@ namespace MediaBrowser.Controller.Entities
}
}
- [JsonIgnore]
- public override bool SupportsInheritedParentImages => false;
-
- [JsonIgnore]
- public override bool SupportsPlayedStatus => false;
-
+ ///
public override int GetChildCount(User user)
{
return GetChildren(user, true).Count;
}
+ ///
protected override QueryResult GetItemsInternal(InternalItemsQuery query)
{
var parent = this as Folder;
@@ -81,6 +106,7 @@ namespace MediaBrowser.Controller.Entities
.GetUserItems(parent, this, CollectionType, query);
}
+ ///
public override List GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query)
{
query ??= new InternalItemsQuery(user);
@@ -91,16 +117,19 @@ namespace MediaBrowser.Controller.Entities
return result.ToList();
}
+ ///
public override bool CanDelete()
{
return false;
}
+ ///
public override bool IsSaveLocalMetadataEnabled()
{
return true;
}
+ ///
public override IEnumerable GetRecursiveChildren(User user, InternalItemsQuery query)
{
query.SetUser(user);
@@ -111,32 +140,26 @@ namespace MediaBrowser.Controller.Entities
return GetItemList(query);
}
+ ///
protected override IEnumerable GetEligibleChildrenForRecursiveChildren(User user)
{
return GetChildren(user, false);
}
- private static readonly string[] UserSpecificViewTypes = new string[]
- {
- Model.Entities.CollectionType.Playlists
- };
-
public static bool IsUserSpecific(Folder folder)
{
- var collectionFolder = folder as ICollectionFolder;
-
- if (collectionFolder == null)
+ if (folder is not ICollectionFolder collectionFolder)
{
return false;
}
- var supportsUserSpecific = folder as ISupportsUserSpecificView;
- if (supportsUserSpecific != null && supportsUserSpecific.EnableUserSpecificView)
+ if (folder is ISupportsUserSpecificView supportsUserSpecific
+ && supportsUserSpecific.EnableUserSpecificView)
{
return true;
}
- return UserSpecificViewTypes.Contains(collectionFolder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
+ return string.Equals(Model.Entities.CollectionType.Playlists, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase);
}
public static bool IsEligibleForGrouping(Folder folder)
@@ -145,39 +168,19 @@ namespace MediaBrowser.Controller.Entities
&& IsEligibleForGrouping(collectionFolder.CollectionType);
}
- private static string[] ViewTypesEligibleForGrouping = new string[]
- {
- Model.Entities.CollectionType.Movies,
- Model.Entities.CollectionType.TvShows,
- string.Empty
- };
-
public static bool IsEligibleForGrouping(string viewType)
{
- return ViewTypesEligibleForGrouping.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
+ return _viewTypesEligibleForGrouping.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
}
- private static string[] OriginalFolderViewTypes = new string[]
- {
- Model.Entities.CollectionType.Books,
- Model.Entities.CollectionType.MusicVideos,
- Model.Entities.CollectionType.HomeVideos,
- Model.Entities.CollectionType.Photos,
- Model.Entities.CollectionType.Music,
- Model.Entities.CollectionType.BoxSets
- };
-
public static bool EnableOriginalFolder(string viewType)
{
- return OriginalFolderViewTypes.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
+ return _originalFolderViewTypes.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
}
protected override Task ValidateChildrenInternal(IProgress progress, bool recursive, bool refreshChildMetadata, Providers.MetadataRefreshOptions refreshOptions, Providers.IDirectoryService directoryService, System.Threading.CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
-
- [JsonIgnore]
- public override bool SupportsPeople => false;
}
}
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index add734f626..266fda767d 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -65,7 +65,7 @@ namespace MediaBrowser.Controller.Entities
switch (viewType)
{
case CollectionType.Folders:
- return GetResult(_libraryManager.GetUserRootFolder().GetChildren(user, true), queryParent, query);
+ return GetResult(_libraryManager.GetUserRootFolder().GetChildren(user, true), query);
case CollectionType.TvShows:
return GetTvView(queryParent, user, query);
@@ -110,7 +110,7 @@ namespace MediaBrowser.Controller.Entities
return GetMovieMovies(queryParent, user, query);
case SpecialFolder.MovieCollections:
- return GetMovieCollections(queryParent, user, query);
+ return GetMovieCollections(user, query);
case SpecialFolder.TvFavoriteEpisodes:
return GetFavoriteEpisodes(queryParent, user, query);
@@ -122,7 +122,7 @@ namespace MediaBrowser.Controller.Entities
{
if (queryParent is UserView)
{
- return GetResult(GetMediaFolders(user).OfType().SelectMany(i => i.GetChildren(user, true)), queryParent, query);
+ return GetResult(GetMediaFolders(user).OfType().SelectMany(i => i.GetChildren(user, true)), query);
}
return queryParent.GetItems(query);
@@ -160,7 +160,7 @@ namespace MediaBrowser.Controller.Entities
GetUserView(SpecialFolder.MovieGenres, "Genres", "5", parent)
};
- return GetResult(list, parent, query);
+ return GetResult(list, query);
}
private QueryResult GetFavoriteMovies(Folder parent, User user, InternalItemsQuery query)
@@ -207,7 +207,7 @@ namespace MediaBrowser.Controller.Entities
return _libraryManager.GetItemsResult(query);
}
- private QueryResult GetMovieCollections(Folder parent, User user, InternalItemsQuery query)
+ private QueryResult GetMovieCollections(User user, InternalItemsQuery query)
{
query.Parent = null;
query.IncludeItemTypes = new[] { nameof(BoxSet) };
@@ -275,9 +275,9 @@ namespace MediaBrowser.Controller.Entities
}
})
.Where(i => i != null)
- .Select(i => GetUserViewWithName(i.Name, SpecialFolder.MovieGenre, i.SortName, parent));
+ .Select(i => GetUserViewWithName(SpecialFolder.MovieGenre, i.SortName, parent));
- return GetResult(genres, parent, query);
+ return GetResult(genres, query);
}
private QueryResult GetMovieGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
@@ -323,7 +323,7 @@ namespace MediaBrowser.Controller.Entities
GetUserView(SpecialFolder.TvGenres, "Genres", "6", parent)
};
- return GetResult(list, parent, query);
+ return GetResult(list, query);
}
private QueryResult GetTvLatest(Folder parent, User user, InternalItemsQuery query)
@@ -403,9 +403,9 @@ namespace MediaBrowser.Controller.Entities
}
})
.Where(i => i != null)
- .Select(i => GetUserViewWithName(i.Name, SpecialFolder.TvGenre, i.SortName, parent));
+ .Select(i => GetUserViewWithName(SpecialFolder.TvGenre, i.SortName, parent));
- return GetResult(genres, parent, query);
+ return GetResult(genres, query);
}
private QueryResult GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
@@ -432,13 +432,12 @@ namespace MediaBrowser.Controller.Entities
private QueryResult GetResult(
IEnumerable items,
- BaseItem queryParent,
InternalItemsQuery query)
where T : BaseItem
{
items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager));
- return PostFilterAndSort(items, queryParent, null, query, _libraryManager, _config);
+ return PostFilterAndSort(items, null, query, _libraryManager);
}
public static bool FilterItem(BaseItem item, InternalItemsQuery query)
@@ -448,11 +447,9 @@ namespace MediaBrowser.Controller.Entities
public static QueryResult PostFilterAndSort(
IEnumerable items,
- BaseItem queryParent,
int? totalRecordLimit,
InternalItemsQuery query,
- ILibraryManager libraryManager,
- IServerConfigurationManager configurationManager)
+ ILibraryManager libraryManager)
{
var user = query.User;
@@ -1001,7 +998,7 @@ namespace MediaBrowser.Controller.Entities
return new BaseItem[] { parent };
}
- private UserView GetUserViewWithName(string name, string type, string sortName, BaseItem parent)
+ private UserView GetUserViewWithName(string type, string sortName, BaseItem parent)
{
return _userViewManager.GetUserSubView(parent.Id, parent.Id.ToString("N", CultureInfo.InvariantCulture), type, sortName);
}
diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs
index f268bc939e..0853200dd1 100644
--- a/MediaBrowser.Controller/Entities/Year.cs
+++ b/MediaBrowser.Controller/Entities/Year.cs
@@ -15,13 +15,11 @@ namespace MediaBrowser.Controller.Entities
///
public class Year : BaseItem, IItemByName
{
- public override List GetUserDataKeys()
- {
- var list = base.GetUserDataKeys();
+ [JsonIgnore]
+ public override bool SupportsAncestors => false;
- list.Insert(0, "Year-" + Name);
- return list;
- }
+ [JsonIgnore]
+ public override bool SupportsPeople => false;
///
/// Gets the folder containing the item.
@@ -31,6 +29,19 @@ namespace MediaBrowser.Controller.Entities
[JsonIgnore]
public override string ContainingFolderPath => Path;
+ public override bool CanDelete()
+ {
+ return false;
+ }
+
+ public override List GetUserDataKeys()
+ {
+ var list = base.GetUserDataKeys();
+
+ list.Insert(0, "Year-" + Name);
+ return list;
+ }
+
public override double GetDefaultPrimaryImageAspectRatio()
{
double value = 2;
@@ -39,14 +50,6 @@ namespace MediaBrowser.Controller.Entities
return value;
}
- [JsonIgnore]
- public override bool SupportsAncestors => false;
-
- public override bool CanDelete()
- {
- return false;
- }
-
public override bool IsSaveLocalMetadataEnabled()
{
return true;
@@ -76,9 +79,6 @@ namespace MediaBrowser.Controller.Entities
return null;
}
- [JsonIgnore]
- public override bool SupportsPeople => false;
-
public static string GetPath(string name)
{
return GetPath(name, true);
diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs
index 0949238426..753c18bc7e 100644
--- a/MediaBrowser.Controller/IServerApplicationHost.cs
+++ b/MediaBrowser.Controller/IServerApplicationHost.cs
@@ -16,8 +16,6 @@ namespace MediaBrowser.Controller
///
public interface IServerApplicationHost : IApplicationHost
{
- event EventHandler HasUpdateAvailableChanged;
-
bool CoreStartupHasCompleted { get; }
bool CanLaunchWebBrowser { get; }
@@ -39,12 +37,6 @@ namespace MediaBrowser.Controller
///
bool ListenWithHttps { get; }
- ///
- /// Gets a value indicating whether this instance has update available.
- ///
- /// true if this instance has update available; otherwise, false.
- bool HasUpdateAvailable { get; }
-
///
/// Gets the name of the friendly.
///
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index 7a4ba6a24a..604960d8bc 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CS1591
using System;
using System.Collections.Generic;
@@ -31,6 +31,29 @@ namespace MediaBrowser.Controller.Library
///
public interface ILibraryManager
{
+ ///
+ /// Occurs when [item added].
+ ///
+ event EventHandler ItemAdded;
+
+ ///
+ /// Occurs when [item updated].
+ ///
+ event EventHandler ItemUpdated;
+
+ ///
+ /// Occurs when [item removed].
+ ///
+ event EventHandler ItemRemoved;
+
+ ///
+ /// Gets the root folder.
+ ///
+ /// The root folder.
+ AggregateFolder RootFolder { get; }
+
+ bool IsScanRunning { get; }
+
///
/// Resolves the path.
///
@@ -57,16 +80,10 @@ namespace MediaBrowser.Controller.Library
LibraryOptions libraryOptions,
string collectionType = null);
- ///
- /// Gets the root folder.
- ///
- /// The root folder.
- AggregateFolder RootFolder { get; }
-
///
/// Gets a Person.
///
- /// The name.
+ /// The name of the person.
/// Task{Person}.
Person GetPerson(string name);
@@ -81,7 +98,7 @@ namespace MediaBrowser.Controller.Library
///
/// Gets the artist.
///
- /// The name.
+ /// The name of the artist.
/// Task{Artist}.
MusicArtist GetArtist(string name);
@@ -90,21 +107,21 @@ namespace MediaBrowser.Controller.Library
///
/// Gets a Studio.
///
- /// The name.
+ /// The name of the studio.
/// Task{Studio}.
Studio GetStudio(string name);
///
/// Gets a Genre.
///
- /// The name.
+ /// The name of the genre.
/// Task{Genre}.
Genre GetGenre(string name);
///
/// Gets the genre.
///
- /// The name.
+ /// The name of the music genre.
/// Task{MusicGenre}.
MusicGenre GetMusicGenre(string name);
@@ -113,7 +130,7 @@ namespace MediaBrowser.Controller.Library
///
/// The value.
/// Task{Year}.
- ///
+ /// Throws if year is invalid.
Year GetYear(int value);
///
@@ -205,16 +222,26 @@ namespace MediaBrowser.Controller.Library
///
/// Creates the item.
///
+ /// Item to create.
+ /// Parent of new item.
void CreateItem(BaseItem item, BaseItem parent);
///
/// Creates the items.
///
+ /// Items to create.
+ /// Parent of new items.
+ /// CancellationToken to use for operation.
void CreateItems(IReadOnlyList items, BaseItem parent, CancellationToken cancellationToken);
///
/// Updates the item.
///
+ /// Items to update.
+ /// Parent of updated items.
+ /// Reason for update.
+ /// CancellationToken to use for operation.
+ /// Returns a Task that can be awaited.
Task UpdateItemsAsync(IReadOnlyList items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken);
///
@@ -224,6 +251,7 @@ namespace MediaBrowser.Controller.Library
/// The parent item.
/// The update reason.
/// The cancellation token.
+ /// Returns a Task that can be awaited.
Task UpdateItemAsync(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken);
///
@@ -233,23 +261,6 @@ namespace MediaBrowser.Controller.Library
/// BaseItem.
BaseItem RetrieveItem(Guid id);
- bool IsScanRunning { get; }
-
- ///
- /// Occurs when [item added].
- ///
- event EventHandler ItemAdded;
-
- ///
- /// Occurs when [item updated].
- ///
- event EventHandler ItemUpdated;
-
- ///
- /// Occurs when [item removed].
- ///
- event EventHandler ItemRemoved;
-
///
/// Finds the type of the collection.
///
@@ -294,16 +305,25 @@ namespace MediaBrowser.Controller.Library
///
/// Deletes the item.
///
+ /// Item to delete.
+ /// Options to use for deletion.
void DeleteItem(BaseItem item, DeleteOptions options);
///
/// Deletes the item.
///
+ /// Item to delete.
+ /// Options to use for deletion.
+ /// Notify parent of deletion.
void DeleteItem(BaseItem item, DeleteOptions options, bool notifyParentItem);
///
/// Deletes the item.
///
+ /// Item to delete.
+ /// Options to use for deletion.
+ /// Parent of item.
+ /// Notify parent of deletion.
void DeleteItem(BaseItem item, DeleteOptions options, BaseItem parent, bool notifyParentItem);
///
@@ -314,6 +334,7 @@ namespace MediaBrowser.Controller.Library
/// The parent identifier.
/// Type of the view.
/// Name of the sort.
+ /// The named view.
UserView GetNamedView(
User user,
string name,
@@ -328,6 +349,7 @@ namespace MediaBrowser.Controller.Library
/// The name.
/// Type of the view.
/// Name of the sort.
+ /// The named view.
UserView GetNamedView(
User user,
string name,
@@ -340,6 +362,7 @@ namespace MediaBrowser.Controller.Library
/// The name.
/// Type of the view.
/// Name of the sort.
+ /// The named view.
UserView GetNamedView(
string name,
string viewType,
@@ -397,6 +420,9 @@ namespace MediaBrowser.Controller.Library
///
/// Fills the missing episode numbers from path.
///
+ /// Episode to use.
+ /// Option to force refresh of episode numbers.
+ /// True if successful.
bool FillMissingEpisodeNumbersFromPath(Episode episode, bool forceRefresh);
///
@@ -539,6 +565,9 @@ namespace MediaBrowser.Controller.Library
///
/// Gets the items.
///
+ /// The query to use.
+ /// Items to use for query.
+ /// List of items.
List GetItemList(InternalItemsQuery query, List parents);
///
diff --git a/MediaBrowser.Controller/Library/ILiveStream.cs b/MediaBrowser.Controller/Library/ILiveStream.cs
index 85d866de5c..323aa48768 100644
--- a/MediaBrowser.Controller/Library/ILiveStream.cs
+++ b/MediaBrowser.Controller/Library/ILiveStream.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1711, CS1591
using System.Threading;
using System.Threading.Tasks;
diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs
index d3d85a0563..fd3631da9c 100644
--- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs
+++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CS1591
using System;
using System.Collections.Generic;
@@ -62,16 +62,32 @@ namespace MediaBrowser.Controller.Library
///
/// Gets the playack media sources.
///
+ /// Item to use.
+ /// User to use for operation.
+ /// Option to allow media probe.
+ /// Option to enable path substitution.
+ /// CancellationToken to use for operation.
+ /// List of media sources wrapped in an awaitable task.
Task> GetPlaybackMediaSources(BaseItem item, User user, bool allowMediaProbe, bool enablePathSubstitution, CancellationToken cancellationToken);
///
/// Gets the static media sources.
///
+ /// Item to use.
+ /// Option to enable path substitution.
+ /// User to use for operation.
+ /// List of media sources.
List GetStaticMediaSources(BaseItem item, bool enablePathSubstitution, User user = null);
///
/// Gets the static media source.
///
+ /// Item to use.
+ /// Media source to get.
+ /// Live stream to use.
+ /// Option to enable path substitution.
+ /// CancellationToken to use for operation.
+ /// The static media source wrapped in an awaitable task.
Task GetMediaSource(BaseItem item, string mediaSourceId, string liveStreamId, bool enablePathSubstitution, CancellationToken cancellationToken);
///
diff --git a/MediaBrowser.Controller/Library/IMediaSourceProvider.cs b/MediaBrowser.Controller/Library/IMediaSourceProvider.cs
index 5bf4acebb4..ca4b53fbee 100644
--- a/MediaBrowser.Controller/Library/IMediaSourceProvider.cs
+++ b/MediaBrowser.Controller/Library/IMediaSourceProvider.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CS1591
using System.Collections.Generic;
using System.Threading;
@@ -21,6 +21,10 @@ namespace MediaBrowser.Controller.Library
///
/// Opens the media source.
///
+ /// Token to use.
+ /// List of live streams.
+ /// CancellationToken to use for operation.
+ /// The media source wrapped as an awaitable task.
Task OpenMediaSource(string openToken, List currentLiveStreams, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/Library/IMetadataSaver.cs b/MediaBrowser.Controller/Library/IMetadataSaver.cs
index 5fbfad8814..d963fd2491 100644
--- a/MediaBrowser.Controller/Library/IMetadataSaver.cs
+++ b/MediaBrowser.Controller/Library/IMetadataSaver.cs
@@ -29,7 +29,6 @@ namespace MediaBrowser.Controller.Library
///
/// The item.
/// The cancellation token.
- /// Task.
void Save(BaseItem item, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/Library/IMusicManager.cs b/MediaBrowser.Controller/Library/IMusicManager.cs
index 5329841bf5..ec34a868b3 100644
--- a/MediaBrowser.Controller/Library/IMusicManager.cs
+++ b/MediaBrowser.Controller/Library/IMusicManager.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CS1591
using System.Collections.Generic;
using Jellyfin.Data.Entities;
@@ -15,16 +15,28 @@ namespace MediaBrowser.Controller.Library
///
/// Gets the instant mix from song.
///
+ /// The item to use.
+ /// The user to use.
+ /// The options to use.
+ /// List of items.
List GetInstantMixFromItem(BaseItem item, User user, DtoOptions dtoOptions);
///
/// Gets the instant mix from artist.
///
+ /// The artist to use.
+ /// The user to use.
+ /// The options to use.
+ /// List of items.
List GetInstantMixFromArtist(MusicArtist artist, User user, DtoOptions dtoOptions);
///
/// Gets the instant mix from genre.
///
+ /// The genres to use.
+ /// The user to use.
+ /// The options to use.
+ /// List of items.
List GetInstantMixFromGenres(IEnumerable genres, User user, DtoOptions dtoOptions);
}
}
diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs
index e5dcfcff04..cf35b48dba 100644
--- a/MediaBrowser.Controller/Library/IUserDataManager.cs
+++ b/MediaBrowser.Controller/Library/IUserDataManager.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CA1707, CS1591
using System;
using System.Collections.Generic;
@@ -42,6 +42,9 @@ namespace MediaBrowser.Controller.Library
///
/// Gets the user data dto.
///
+ /// Item to use.
+ /// User to use.
+ /// User data dto.
UserItemDataDto GetUserDataDto(BaseItem item, User user);
UserItemDataDto GetUserDataDto(BaseItem item, BaseItemDto itemDto, User user, DtoOptions dto_options);
@@ -64,6 +67,10 @@ namespace MediaBrowser.Controller.Library
///
/// Updates playstate for an item and returns true or false indicating if it was played to completion.
///
+ /// Item to update.
+ /// Data to update.
+ /// New playstate.
+ /// True if playstate was updated.
bool UpdatePlayState(BaseItem item, UserItemData data, long? positionTicks);
}
}
diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs
index 51118e39cd..993e3e18f9 100644
--- a/MediaBrowser.Controller/Library/IUserManager.cs
+++ b/MediaBrowser.Controller/Library/IUserManager.cs
@@ -38,6 +38,7 @@ namespace MediaBrowser.Controller.Library
///
/// Initializes the user manager and ensures that a user exists.
///
+ /// Awaitable task.
Task InitializeAsync();
///
@@ -107,11 +108,18 @@ namespace MediaBrowser.Controller.Library
///
/// Changes the password.
///
+ /// The user.
+ /// New password to use.
+ /// Awaitable task.
Task ChangePassword(User user, string newPassword);
///
/// Changes the easy password.
///
+ /// The user.
+ /// New password to use.
+ /// Hash of new password.
+ /// Task.
Task ChangeEasyPassword(User user, string newPassword, string newPasswordSha1);
///
@@ -125,6 +133,12 @@ namespace MediaBrowser.Controller.Library
///
/// Authenticates the user.
///
+ /// The user.
+ /// The password to use.
+ /// Hash of password.
+ /// Remove endpoint to use.
+ /// Specifies if a user session.
+ /// User wrapped in awaitable task.
Task AuthenticateUser(string username, string password, string passwordSha1, string remoteEndPoint, bool isUserSession);
///
diff --git a/MediaBrowser.Controller/Library/IUserViewManager.cs b/MediaBrowser.Controller/Library/IUserViewManager.cs
index 46004e42f7..055627d3e3 100644
--- a/MediaBrowser.Controller/Library/IUserViewManager.cs
+++ b/MediaBrowser.Controller/Library/IUserViewManager.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CS1591
using System;
using System.Collections.Generic;
@@ -13,10 +13,29 @@ namespace MediaBrowser.Controller.Library
{
public interface IUserViewManager
{
+ ///
+ /// Gets user views.
+ ///
+ /// Query to use.
+ /// Set of folders.
Folder[] GetUserViews(UserViewQuery query);
+ ///
+ /// Gets user sub views.
+ ///
+ /// Parent to use.
+ /// Type to use.
+ /// Localization key to use.
+ /// Sort to use.
+ /// User view.
UserView GetUserSubView(Guid parentId, string type, string localizationKey, string sortName);
+ ///
+ /// Gets latest items.
+ ///
+ /// Query to use.
+ /// Options to use.
+ /// Set of items.
List>> GetLatestItems(LatestItemsQuery request, DtoOptions options);
}
}
diff --git a/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs b/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs
index a37dc7af11..3586dc69d6 100644
--- a/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs
+++ b/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1711, CS1591
using MediaBrowser.Controller.Entities;
diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs
index 521e372742..bfc1e4857f 100644
--- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs
+++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1721, CA1819, CS1591
using System;
using System.Collections.Generic;
@@ -109,6 +109,21 @@ namespace MediaBrowser.Controller.Library
/// The additional locations.
private List AdditionalLocations { get; set; }
+ ///
+ /// Gets the physical locations.
+ ///
+ /// The physical locations.
+ public string[] PhysicalLocations
+ {
+ get
+ {
+ var paths = string.IsNullOrEmpty(Path) ? Array.Empty() : new[] { Path };
+ return AdditionalLocations == null ? paths : paths.Concat(AdditionalLocations).ToArray();
+ }
+ }
+
+ public string CollectionType { get; set; }
+
public bool HasParent()
where T : Folder
{
@@ -138,6 +153,16 @@ namespace MediaBrowser.Controller.Library
return false;
}
+ ///
+ /// Determines whether the specified is equal to this instance.
+ ///
+ /// The object to compare with the current object.
+ /// true if the specified is equal to this instance; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return Equals(obj as ItemResolveArgs);
+ }
+
///
/// Adds the additional location.
///
@@ -156,19 +181,6 @@ namespace MediaBrowser.Controller.Library
// REVIEW: @bond
- ///
- /// Gets the physical locations.
- ///
- /// The physical locations.
- public string[] PhysicalLocations
- {
- get
- {
- var paths = string.IsNullOrEmpty(Path) ? Array.Empty() : new[] { Path };
- return AdditionalLocations == null ? paths : paths.Concat(AdditionalLocations).ToArray();
- }
- }
-
///
/// Gets the name of the file system entry by.
///
@@ -190,7 +202,7 @@ namespace MediaBrowser.Controller.Library
///
/// The path.
/// FileSystemInfo.
- ///
+ /// Throws if path is invalid.
public FileSystemMetadata GetFileSystemEntryByPath(string path)
{
if (string.IsNullOrEmpty(path))
@@ -224,18 +236,6 @@ namespace MediaBrowser.Controller.Library
return CollectionType;
}
- public string CollectionType { get; set; }
-
- ///
- /// Determines whether the specified is equal to this instance.
- ///
- /// The object to compare with the current object.
- /// true if the specified is equal to this instance; otherwise, false.
- public override bool Equals(object obj)
- {
- return Equals(obj as ItemResolveArgs);
- }
-
///
/// Returns a hash code for this instance.
///
diff --git a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
index 609336ec4d..76e9eb1f54 100644
--- a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
+++ b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CA2227, CS1591
using System;
using System.Collections.Generic;
diff --git a/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs b/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs
index bfe433c971..4d90346f29 100644
--- a/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs
+++ b/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CA2227, CS1591
using System;
using System.Collections.Generic;
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
index f4dc18e11c..bd097c90ac 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
@@ -22,12 +22,22 @@ namespace MediaBrowser.Controller.LiveTv
///
public interface ILiveTvManager
{
+ event EventHandler> SeriesTimerCancelled;
+
+ event EventHandler> TimerCancelled;
+
+ event EventHandler> TimerCreated;
+
+ event EventHandler> SeriesTimerCreated;
+
///
/// Gets the services.
///
/// The services.
IReadOnlyList Services { get; }
+ IListingsProvider[] ListingProviders { get; }
+
///
/// Gets the new timer defaults asynchronous.
///
@@ -86,6 +96,7 @@ namespace MediaBrowser.Controller.LiveTv
///
/// The query.
/// The options.
+ /// A recording.
QueryResult GetRecordings(RecordingQuery query, DtoOptions options);
///
@@ -176,11 +187,16 @@ namespace MediaBrowser.Controller.LiveTv
/// The query.
/// The options.
/// The cancellation token.
+ /// Recommended programs.
QueryResult GetRecommendedPrograms(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken);
///
/// Gets the recommended programs internal.
///
+ /// The query.
+ /// The options.
+ /// The cancellation token.
+ /// Recommended programs.
QueryResult GetRecommendedProgramsInternal(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken);
///
@@ -202,6 +218,7 @@ namespace MediaBrowser.Controller.LiveTv
/// Gets the live tv folder.
///
/// The cancellation token.
+ /// Live TV folder.
Folder GetInternalLiveTvFolder(CancellationToken cancellationToken);
///
@@ -213,11 +230,18 @@ namespace MediaBrowser.Controller.LiveTv
///
/// Gets the internal channels.
///
+ /// The query.
+ /// The options.
+ /// The cancellation token.
+ /// Internal channels.
QueryResult GetInternalChannels(LiveTvChannelQuery query, DtoOptions dtoOptions, CancellationToken cancellationToken);
///
/// Gets the channel media sources.
///
+ /// Item to search for.
+ /// CancellationToken to use for operation.
+ /// Channel media sources wrapped in a task.
Task> GetChannelMediaSources(BaseItem item, CancellationToken cancellationToken);
///
@@ -232,6 +256,9 @@ namespace MediaBrowser.Controller.LiveTv
///
/// Saves the tuner host.
///
+ /// Turner host to save.
+ /// Option to specify that data source has changed.
+ /// Tuner host information wrapped in a task.
Task SaveTunerHost(TunerHostInfo info, bool dataSourceChanged = true);
///
@@ -271,20 +298,10 @@ namespace MediaBrowser.Controller.LiveTv
Task> GetChannelsFromListingsProviderData(string id, CancellationToken cancellationToken);
- IListingsProvider[] ListingProviders { get; }
-
List GetTunerHostTypes();
Task> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken);
- event EventHandler> SeriesTimerCancelled;
-
- event EventHandler> TimerCancelled;
-
- event EventHandler> TimerCreated;
-
- event EventHandler> SeriesTimerCreated;
-
string GetEmbyTvActiveRecordingPath(string id);
ActiveRecordingInfo GetActiveRecordingInfo(string path);
diff --git a/MediaBrowser.Controller/LiveTv/ITunerHost.cs b/MediaBrowser.Controller/LiveTv/ITunerHost.cs
index 7dced9f5ef..24820abb90 100644
--- a/MediaBrowser.Controller/LiveTv/ITunerHost.cs
+++ b/MediaBrowser.Controller/LiveTv/ITunerHost.cs
@@ -30,6 +30,8 @@ namespace MediaBrowser.Controller.LiveTv
///
/// Gets the channels.
///
+ /// Option to enable using cache.
+ /// The CancellationToken for this operation.
/// Task<IEnumerable<ChannelInfo>>.
Task> GetChannels(bool enableCache, CancellationToken cancellationToken);
@@ -47,6 +49,7 @@ namespace MediaBrowser.Controller.LiveTv
/// The stream identifier.
/// The current live streams.
/// The cancellation token to cancel operation.
+ /// Live stream wrapped in a task.
Task GetChannelStream(string channelId, string streamId, List currentLiveStreams, CancellationToken cancellationToken);
///
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
index 1a893fc2d0..074e023e8d 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
@@ -18,23 +18,6 @@ namespace MediaBrowser.Controller.LiveTv
{
public class LiveTvChannel : BaseItem, IHasMediaSources, IHasProgramAttributes
{
- public override List GetUserDataKeys()
- {
- var list = base.GetUserDataKeys();
-
- if (!ConfigurationManager.Configuration.DisableLiveTvChannelUserDataName)
- {
- list.Insert(0, GetClientTypeName() + "-" + Name);
- }
-
- return list;
- }
-
- public override UnratedItem GetBlockUnratedType()
- {
- return UnratedItem.LiveTvChannel;
- }
-
[JsonIgnore]
public override bool SupportsPositionTicksResume => false;
@@ -59,70 +42,9 @@ namespace MediaBrowser.Controller.LiveTv
[JsonIgnore]
public override LocationType LocationType => LocationType.Remote;
- protected override string CreateSortName()
- {
- if (!string.IsNullOrEmpty(Number))
- {
- double number = 0;
-
- if (double.TryParse(Number, NumberStyles.Any, CultureInfo.InvariantCulture, out number))
- {
- return string.Format(CultureInfo.InvariantCulture, "{0:00000.0}", number) + "-" + (Name ?? string.Empty);
- }
- }
-
- return (Number ?? string.Empty) + "-" + (Name ?? string.Empty);
- }
-
[JsonIgnore]
public override string MediaType => ChannelType == ChannelType.Radio ? Model.Entities.MediaType.Audio : Model.Entities.MediaType.Video;
- public override string GetClientTypeName()
- {
- return "TvChannel";
- }
-
- public IEnumerable GetTaggedItems(IEnumerable inputItems)
- {
- return new List();
- }
-
- public override List GetMediaSources(bool enablePathSubstitution)
- {
- var list = new List();
-
- var info = new MediaSourceInfo
- {
- Id = Id.ToString("N", CultureInfo.InvariantCulture),
- Protocol = PathProtocol ?? MediaProtocol.File,
- MediaStreams = new List(),
- Name = Name,
- Path = Path,
- RunTimeTicks = RunTimeTicks,
- Type = MediaSourceType.Placeholder,
- IsInfiniteStream = RunTimeTicks == null
- };
-
- list.Add(info);
-
- return list;
- }
-
- public override List GetMediaStreams()
- {
- return new List();
- }
-
- protected override string GetInternalMetadataPath(string basePath)
- {
- return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N", CultureInfo.InvariantCulture), "metadata");
- }
-
- public override bool CanDelete()
- {
- return false;
- }
-
[JsonIgnore]
public bool IsMovie { get; set; }
@@ -163,5 +85,83 @@ namespace MediaBrowser.Controller.LiveTv
/// The episode title.
[JsonIgnore]
public string EpisodeTitle { get; set; }
+
+ public override List GetUserDataKeys()
+ {
+ var list = base.GetUserDataKeys();
+
+ if (!ConfigurationManager.Configuration.DisableLiveTvChannelUserDataName)
+ {
+ list.Insert(0, GetClientTypeName() + "-" + Name);
+ }
+
+ return list;
+ }
+
+ public override UnratedItem GetBlockUnratedType()
+ {
+ return UnratedItem.LiveTvChannel;
+ }
+
+ protected override string CreateSortName()
+ {
+ if (!string.IsNullOrEmpty(Number))
+ {
+ double number = 0;
+
+ if (double.TryParse(Number, NumberStyles.Any, CultureInfo.InvariantCulture, out number))
+ {
+ return string.Format(CultureInfo.InvariantCulture, "{0:00000.0}", number) + "-" + (Name ?? string.Empty);
+ }
+ }
+
+ return (Number ?? string.Empty) + "-" + (Name ?? string.Empty);
+ }
+
+ public override string GetClientTypeName()
+ {
+ return "TvChannel";
+ }
+
+ public IEnumerable GetTaggedItems()
+ {
+ return new List();
+ }
+
+ public override List GetMediaSources(bool enablePathSubstitution)
+ {
+ var list = new List();
+
+ var info = new MediaSourceInfo
+ {
+ Id = Id.ToString("N", CultureInfo.InvariantCulture),
+ Protocol = PathProtocol ?? MediaProtocol.File,
+ MediaStreams = new List(),
+ Name = Name,
+ Path = Path,
+ RunTimeTicks = RunTimeTicks,
+ Type = MediaSourceType.Placeholder,
+ IsInfiniteStream = RunTimeTicks == null
+ };
+
+ list.Add(info);
+
+ return list;
+ }
+
+ public override List GetMediaStreams()
+ {
+ return new List();
+ }
+
+ protected override string GetInternalMetadataPath(string basePath)
+ {
+ return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N", CultureInfo.InvariantCulture), "metadata");
+ }
+
+ public override bool CanDelete()
+ {
+ return false;
+ }
}
}
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
index 9d638a0bf6..111dc0d275 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CS1591, SA1306
using System;
using System.Collections.Generic;
@@ -19,54 +19,14 @@ namespace MediaBrowser.Controller.LiveTv
{
public class LiveTvProgram : BaseItem, IHasLookupInfo, IHasStartDate, IHasProgramAttributes
{
+ private static string EmbyServiceName = "Emby";
+
public LiveTvProgram()
{
IsVirtualItem = true;
}
- public override List GetUserDataKeys()
- {
- var list = base.GetUserDataKeys();
-
- if (!IsSeries)
- {
- var key = this.GetProviderId(MetadataProvider.Imdb);
- if (!string.IsNullOrEmpty(key))
- {
- list.Insert(0, key);
- }
-
- key = this.GetProviderId(MetadataProvider.Tmdb);
- if (!string.IsNullOrEmpty(key))
- {
- list.Insert(0, key);
- }
- }
- else if (!string.IsNullOrEmpty(EpisodeTitle))
- {
- var name = GetClientTypeName();
-
- list.Insert(0, name + "-" + Name + (EpisodeTitle ?? string.Empty));
- }
-
- return list;
- }
-
- private static string EmbyServiceName = "Emby";
-
- public override double GetDefaultPrimaryImageAspectRatio()
- {
- var serviceName = ServiceName;
-
- if (string.Equals(serviceName, EmbyServiceName, StringComparison.OrdinalIgnoreCase) || string.Equals(serviceName, "Next Pvr", StringComparison.OrdinalIgnoreCase))
- {
- return 2.0 / 3;
- }
- else
- {
- return 16.0 / 9;
- }
- }
+ public string SeriesName { get; set; }
[JsonIgnore]
public override SourceType SourceType => SourceType.LiveTV;
@@ -182,6 +142,66 @@ namespace MediaBrowser.Controller.LiveTv
}
}
+ [JsonIgnore]
+ public override bool SupportsPeople
+ {
+ get
+ {
+ // Optimization
+ if (IsNews || IsSports)
+ {
+ return false;
+ }
+
+ return base.SupportsPeople;
+ }
+ }
+
+ [JsonIgnore]
+ public override bool SupportsAncestors => false;
+
+ public override List GetUserDataKeys()
+ {
+ var list = base.GetUserDataKeys();
+
+ if (!IsSeries)
+ {
+ var key = this.GetProviderId(MetadataProvider.Imdb);
+ if (!string.IsNullOrEmpty(key))
+ {
+ list.Insert(0, key);
+ }
+
+ key = this.GetProviderId(MetadataProvider.Tmdb);
+ if (!string.IsNullOrEmpty(key))
+ {
+ list.Insert(0, key);
+ }
+ }
+ else if (!string.IsNullOrEmpty(EpisodeTitle))
+ {
+ var name = GetClientTypeName();
+
+ list.Insert(0, name + "-" + Name + (EpisodeTitle ?? string.Empty));
+ }
+
+ return list;
+ }
+
+ public override double GetDefaultPrimaryImageAspectRatio()
+ {
+ var serviceName = ServiceName;
+
+ if (string.Equals(serviceName, EmbyServiceName, StringComparison.OrdinalIgnoreCase) || string.Equals(serviceName, "Next Pvr", StringComparison.OrdinalIgnoreCase))
+ {
+ return 2.0 / 3;
+ }
+ else
+ {
+ return 16.0 / 9;
+ }
+ }
+
public override string GetClientTypeName()
{
return "Program";
@@ -202,24 +222,6 @@ namespace MediaBrowser.Controller.LiveTv
return false;
}
- [JsonIgnore]
- public override bool SupportsPeople
- {
- get
- {
- // Optimization
- if (IsNews || IsSports)
- {
- return false;
- }
-
- return base.SupportsPeople;
- }
- }
-
- [JsonIgnore]
- public override bool SupportsAncestors => false;
-
private LiveTvOptions GetConfiguration()
{
return ConfigurationManager.GetConfiguration("livetv");
@@ -273,7 +275,5 @@ namespace MediaBrowser.Controller.LiveTv
return list;
}
-
- public string SeriesName { get; set; }
}
}
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 4bed112e43..0f697bcccd 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -35,14 +35,15 @@
net5.0
false
true
- true
- enable
- AllEnabledByDefault
- ../jellyfin.ruleset
true
true
true
snupkg
+ false
+
+
+
+ true
diff --git a/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs
index 745ee6bdb5..dd6f468dab 100644
--- a/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs
+++ b/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs
@@ -10,6 +10,15 @@ namespace MediaBrowser.Controller.MediaEncoding
{
public class BaseEncodingJobOptions
{
+ public BaseEncodingJobOptions()
+ {
+ EnableAutoStreamCopy = true;
+ AllowVideoStreamCopy = true;
+ AllowAudioStreamCopy = true;
+ Context = EncodingContext.Streaming;
+ StreamOptions = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ }
+
///
/// Gets or sets the id.
///
@@ -191,14 +200,5 @@ namespace MediaBrowser.Controller.MediaEncoding
return null;
}
-
- public BaseEncodingJobOptions()
- {
- EnableAutoStreamCopy = true;
- AllowVideoStreamCopy = true;
- AllowAudioStreamCopy = true;
- Context = EncodingContext.Streaming;
- StreamOptions = new Dictionary(StringComparer.OrdinalIgnoreCase);
- }
}
}
\ No newline at end of file
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index 26b0bc3def..9bae95a272 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -143,8 +143,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// Hybrid VPP tonemapping for QSV with VAAPI
- var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
- if (isLinux && string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
+ if (OperatingSystem.IsLinux() && string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
{
// Limited to HEVC for now since the filter doesn't accept master data from VP9.
return IsColorDepth10(state)
@@ -162,6 +161,9 @@ namespace MediaBrowser.Controller.MediaEncoding
///
/// Gets the name of the output video codec.
///
+ /// Encording state.
+ /// Encoding options.
+ /// Encoder string.
public string GetVideoEncoder(EncodingJobInfo state, EncodingOptions encodingOptions)
{
var codec = state.OutputVideoCodec;
@@ -316,6 +318,11 @@ namespace MediaBrowser.Controller.MediaEncoding
return container;
}
+ ///
+ /// Gets decoder from a codec.
+ ///
+ /// Codec to use.
+ /// Decoder string.
public string GetDecoderFromCodec(string codec)
{
// For these need to find out the ffmpeg names
@@ -345,6 +352,8 @@ namespace MediaBrowser.Controller.MediaEncoding
///
/// Infers the audio codec based on the url.
///
+ /// Container to use.
+ /// Codec string.
public string InferAudioCodec(string container)
{
var ext = "." + (container ?? string.Empty);
@@ -490,6 +499,9 @@ namespace MediaBrowser.Controller.MediaEncoding
///
/// Gets the input argument.
///
+ /// Encoding state.
+ /// Encoding options.
+ /// Input arguments.
public string GetInputArgument(EncodingJobInfo state, EncodingOptions encodingOptions)
{
var arg = new StringBuilder();
@@ -503,9 +515,9 @@ namespace MediaBrowser.Controller.MediaEncoding
var isQsvEncoder = outputVideoCodec.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1;
var isNvdecDecoder = videoDecoder.Contains("cuda", StringComparison.OrdinalIgnoreCase);
var isCuvidHevcDecoder = videoDecoder.Contains("hevc_cuvid", StringComparison.OrdinalIgnoreCase);
- var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
- var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
- var isMacOS = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
+ var isWindows = OperatingSystem.IsWindows();
+ var isLinux = OperatingSystem.IsLinux();
+ var isMacOS = OperatingSystem.IsMacOS();
var isTonemappingSupported = IsTonemappingSupported(state, encodingOptions);
var isVppTonemappingSupported = IsVppTonemappingSupported(state, encodingOptions);
@@ -966,6 +978,11 @@ namespace MediaBrowser.Controller.MediaEncoding
///
/// Gets the video bitrate to specify on the command line.
///
+ /// Encoding state.
+ /// Video encoder to use.
+ /// Encoding options.
+ /// Default present to use for encoding.
+ /// Video bitrate.
public string GetVideoQualityParam(EncodingJobInfo state, string videoEncoder, EncodingOptions encodingOptions, string defaultPreset)
{
var param = string.Empty;
@@ -1692,7 +1709,7 @@ namespace MediaBrowser.Controller.MediaEncoding
return 128000;
}
- public string GetAudioFilterParam(EncodingJobInfo state, EncodingOptions encodingOptions, bool isHls)
+ public string GetAudioFilterParam(EncodingJobInfo state, EncodingOptions encodingOptions)
{
var channels = state.OutputAudioChannels;
@@ -1967,8 +1984,12 @@ namespace MediaBrowser.Controller.MediaEncoding
}
///
- /// Gets the graphical subtitle param.
+ /// Gets the graphical subtitle parameter.
///
+ /// Encoding state.
+ /// Encoding options.
+ /// Video codec to use.
+ /// Graphical subtitle parameter.
public string GetGraphicalSubtitleParam(
EncodingJobInfo state,
EncodingOptions options,
@@ -1983,7 +2004,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var videoSizeParam = string.Empty;
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options) ?? string.Empty;
- var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
+ var isLinux = OperatingSystem.IsLinux();
var isVaapiDecoder = videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1;
var isVaapiH264Encoder = outputVideoCodec.IndexOf("h264_vaapi", StringComparison.OrdinalIgnoreCase) != -1;
@@ -2486,6 +2507,13 @@ namespace MediaBrowser.Controller.MediaEncoding
return string.Format(CultureInfo.InvariantCulture, filter, widthParam, heightParam);
}
+ ///
+ /// Gets the output size parameter.
+ ///
+ /// Encoding state.
+ /// Encoding options.
+ /// Video codec to use.
+ /// The output size parameter.
public string GetOutputSizeParam(
EncodingJobInfo state,
EncodingOptions options,
@@ -2496,8 +2524,13 @@ namespace MediaBrowser.Controller.MediaEncoding
}
///
+ /// Gets the output size parameter.
/// If we're going to put a fixed size on the command line, this will calculate it.
///
+ /// Encoding state.
+ /// Encoding options.
+ /// Video codec to use.
+ /// The output size parameter.
public string GetOutputSizeParamInternal(
EncodingJobInfo state,
EncodingOptions options,
@@ -2528,7 +2561,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var isCuvidHevcDecoder = videoDecoder.Contains("hevc_cuvid", StringComparison.OrdinalIgnoreCase);
var isLibX264Encoder = outputVideoCodec.IndexOf("libx264", StringComparison.OrdinalIgnoreCase) != -1;
var isLibX265Encoder = outputVideoCodec.IndexOf("libx265", StringComparison.OrdinalIgnoreCase) != -1;
- var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
+ var isLinux = OperatingSystem.IsLinux();
var isColorDepth10 = IsColorDepth10(state);
var isTonemappingSupported = IsTonemappingSupported(state, options);
var isVppTonemappingSupported = IsVppTonemappingSupported(state, options);
@@ -2909,6 +2942,10 @@ namespace MediaBrowser.Controller.MediaEncoding
///
/// Gets the number of threads.
///
+ /// Encoding state.
+ /// Encoding options.
+ /// Video codec to use.
+ /// Number of threads.
#nullable enable
public static int GetNumberOfThreads(EncodingJobInfo? state, EncodingOptions encodingOptions, string? outputVideoCodec)
{
@@ -3552,6 +3589,11 @@ namespace MediaBrowser.Controller.MediaEncoding
///
/// Gets a hw decoder name.
///
+ /// Encoding options.
+ /// Decoder to use.
+ /// Video codec to use.
+ /// Specifies if color depth 10.
+ /// Hardware decoder name.
public string GetHwDecoderName(EncodingOptions options, string decoder, string videoCodec, bool isColorDepth10)
{
var isCodecAvailable = _mediaEncoder.SupportsDecoder(decoder) && options.HardwareDecodingCodecs.Contains(videoCodec, StringComparer.OrdinalIgnoreCase);
@@ -3570,10 +3612,15 @@ namespace MediaBrowser.Controller.MediaEncoding
///
/// Gets a hwaccel type to use as a hardware decoder(dxva/vaapi) depending on the system.
///
+ /// Encoding state.
+ /// Encoding options.
+ /// Video codec to use.
+ /// Specifies if color depth 10.
+ /// Hardware accelerator type.
public string GetHwaccelType(EncodingJobInfo state, EncodingOptions options, string videoCodec, bool isColorDepth10)
{
- var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
- var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
+ var isWindows = OperatingSystem.IsWindows();
+ var isLinux = OperatingSystem.IsLinux();
var isWindows8orLater = Environment.OSVersion.Version.Major > 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor > 1);
var isDxvaSupported = _mediaEncoder.SupportsHwaccel("dxva2") || _mediaEncoder.SupportsHwaccel("d3d11va");
var isCodecAvailable = options.HardwareDecodingCodecs.Contains(videoCodec, StringComparer.OrdinalIgnoreCase);
@@ -3836,7 +3883,7 @@ namespace MediaBrowser.Controller.MediaEncoding
args += " -ar " + state.OutputAudioSampleRate.Value.ToString(_usCulture);
}
- args += GetAudioFilterParam(state, encodingOptions, false);
+ args += GetAudioFilterParam(state, encodingOptions);
return args;
}
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
index bc0318ad7c..fa9f40d60d 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CS1591, SA1401
using System;
using System.Collections.Generic;
@@ -20,6 +20,44 @@ namespace MediaBrowser.Controller.MediaEncoding
// For now, a common base class until the API and MediaEncoding classes are unified
public class EncodingJobInfo
{
+ public int? OutputAudioBitrate;
+ public int? OutputAudioChannels;
+
+ private TranscodeReason[] _transcodeReasons = null;
+
+ public EncodingJobInfo(TranscodingJobType jobType)
+ {
+ TranscodingType = jobType;
+ RemoteHttpHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ SupportedAudioCodecs = Array.Empty();
+ SupportedVideoCodecs = Array.Empty();
+ SupportedSubtitleCodecs = Array.Empty();
+ }
+
+ public TranscodeReason[] TranscodeReasons
+ {
+ get
+ {
+ if (_transcodeReasons == null)
+ {
+ if (BaseRequest.TranscodeReasons == null)
+ {
+ return Array.Empty();
+ }
+
+ _transcodeReasons = BaseRequest.TranscodeReasons
+ .Split(',')
+ .Where(i => !string.IsNullOrEmpty(i))
+ .Select(v => (TranscodeReason)Enum.Parse(typeof(TranscodeReason), v, true))
+ .ToArray();
+ }
+
+ return _transcodeReasons;
+ }
+ }
+
+ public IProgress Progress { get; set; }
+
public MediaStream VideoStream { get; set; }
public VideoType VideoType { get; set; }
@@ -58,40 +96,6 @@ namespace MediaBrowser.Controller.MediaEncoding
public string MimeType { get; set; }
- public string GetMimeType(string outputPath, bool enableStreamDefault = true)
- {
- if (!string.IsNullOrEmpty(MimeType))
- {
- return MimeType;
- }
-
- return MimeTypes.GetMimeType(outputPath, enableStreamDefault);
- }
-
- private TranscodeReason[] _transcodeReasons = null;
-
- public TranscodeReason[] TranscodeReasons
- {
- get
- {
- if (_transcodeReasons == null)
- {
- if (BaseRequest.TranscodeReasons == null)
- {
- return Array.Empty();
- }
-
- _transcodeReasons = BaseRequest.TranscodeReasons
- .Split(',')
- .Where(i => !string.IsNullOrEmpty(i))
- .Select(v => (TranscodeReason)Enum.Parse(typeof(TranscodeReason), v, true))
- .ToArray();
- }
-
- return _transcodeReasons;
- }
- }
-
public bool IgnoreInputDts => MediaSource.IgnoreDts;
public bool IgnoreInputIndex => MediaSource.IgnoreIndex;
@@ -144,196 +148,17 @@ namespace MediaBrowser.Controller.MediaEncoding
public BaseEncodingJobOptions BaseRequest { get; set; }
- public long? StartTimeTicks => BaseRequest.StartTimeTicks;
-
- public bool CopyTimestamps => BaseRequest.CopyTimestamps;
-
- public int? OutputAudioBitrate;
- public int? OutputAudioChannels;
-
- public bool DeInterlace(string videoCodec, bool forceDeinterlaceIfSourceIsInterlaced)
- {
- var videoStream = VideoStream;
- var isInputInterlaced = videoStream != null && videoStream.IsInterlaced;
-
- if (!isInputInterlaced)
- {
- return false;
- }
-
- // Support general param
- if (BaseRequest.DeInterlace)
- {
- return true;
- }
-
- if (!string.IsNullOrEmpty(videoCodec))
- {
- if (string.Equals(BaseRequest.GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
- }
-
- return forceDeinterlaceIfSourceIsInterlaced && isInputInterlaced;
- }
-
- public string[] GetRequestedProfiles(string codec)
- {
- if (!string.IsNullOrEmpty(BaseRequest.Profile))
- {
- return BaseRequest.Profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries);
- }
-
- if (!string.IsNullOrEmpty(codec))
- {
- var profile = BaseRequest.GetOption(codec, "profile");
-
- if (!string.IsNullOrEmpty(profile))
- {
- return profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries);
- }
- }
-
- return Array.Empty();
- }
-
- public string GetRequestedLevel(string codec)
- {
- if (!string.IsNullOrEmpty(BaseRequest.Level))
- {
- return BaseRequest.Level;
- }
-
- if (!string.IsNullOrEmpty(codec))
- {
- return BaseRequest.GetOption(codec, "level");
- }
-
- return null;
- }
-
- public int? GetRequestedMaxRefFrames(string codec)
- {
- if (BaseRequest.MaxRefFrames.HasValue)
- {
- return BaseRequest.MaxRefFrames;
- }
-
- if (!string.IsNullOrEmpty(codec))
- {
- var value = BaseRequest.GetOption(codec, "maxrefframes");
- if (!string.IsNullOrEmpty(value)
- && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
- {
- return result;
- }
- }
-
- return null;
- }
-
- public int? GetRequestedVideoBitDepth(string codec)
- {
- if (BaseRequest.MaxVideoBitDepth.HasValue)
- {
- return BaseRequest.MaxVideoBitDepth;
- }
-
- if (!string.IsNullOrEmpty(codec))
- {
- var value = BaseRequest.GetOption(codec, "videobitdepth");
- if (!string.IsNullOrEmpty(value)
- && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
- {
- return result;
- }
- }
-
- return null;
- }
-
- public int? GetRequestedAudioBitDepth(string codec)
- {
- if (BaseRequest.MaxAudioBitDepth.HasValue)
- {
- return BaseRequest.MaxAudioBitDepth;
- }
-
- if (!string.IsNullOrEmpty(codec))
- {
- var value = BaseRequest.GetOption(codec, "audiobitdepth");
- if (!string.IsNullOrEmpty(value)
- && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
- {
- return result;
- }
- }
-
- return null;
- }
-
- public int? GetRequestedAudioChannels(string codec)
- {
- if (!string.IsNullOrEmpty(codec))
- {
- var value = BaseRequest.GetOption(codec, "audiochannels");
- if (!string.IsNullOrEmpty(value)
- && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
- {
- return result;
- }
- }
-
- if (BaseRequest.MaxAudioChannels.HasValue)
- {
- return BaseRequest.MaxAudioChannels;
- }
-
- if (BaseRequest.AudioChannels.HasValue)
- {
- return BaseRequest.AudioChannels;
- }
-
- if (BaseRequest.TranscodingMaxAudioChannels.HasValue)
- {
- return BaseRequest.TranscodingMaxAudioChannels;
- }
-
- return null;
- }
-
public bool IsVideoRequest { get; set; }
public TranscodingJobType TranscodingType { get; set; }
- public EncodingJobInfo(TranscodingJobType jobType)
- {
- TranscodingType = jobType;
- RemoteHttpHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase);
- SupportedAudioCodecs = Array.Empty();
- SupportedVideoCodecs = Array.Empty();
- SupportedSubtitleCodecs = Array.Empty();
- }
+ public long? StartTimeTicks => BaseRequest.StartTimeTicks;
+
+ public bool CopyTimestamps => BaseRequest.CopyTimestamps;
public bool IsSegmentedLiveStream
=> TranscodingType != TranscodingJobType.Progressive && !RunTimeTicks.HasValue;
- public bool EnableBreakOnNonKeyFrames(string videoCodec)
- {
- if (TranscodingType != TranscodingJobType.Progressive)
- {
- if (IsSegmentedLiveStream)
- {
- return false;
- }
-
- return BaseRequest.BreakOnNonKeyFrames && EncodingHelper.IsCopyCodec(videoCodec);
- }
-
- return false;
- }
-
public int? TotalOutputBitrate => (OutputAudioBitrate ?? 0) + (OutputVideoBitrate ?? 0);
public int? OutputWidth
@@ -682,6 +507,21 @@ namespace MediaBrowser.Controller.MediaEncoding
public int HlsListSize => 0;
+ public bool EnableBreakOnNonKeyFrames(string videoCodec)
+ {
+ if (TranscodingType != TranscodingJobType.Progressive)
+ {
+ if (IsSegmentedLiveStream)
+ {
+ return false;
+ }
+
+ return BaseRequest.BreakOnNonKeyFrames && EncodingHelper.IsCopyCodec(videoCodec);
+ }
+
+ return false;
+ }
+
private int? GetMediaStreamCount(MediaStreamType type, int limit)
{
var count = MediaSource.GetStreamCount(type);
@@ -694,7 +534,167 @@ namespace MediaBrowser.Controller.MediaEncoding
return count;
}
- public IProgress Progress { get; set; }
+ public string GetMimeType(string outputPath, bool enableStreamDefault = true)
+ {
+ if (!string.IsNullOrEmpty(MimeType))
+ {
+ return MimeType;
+ }
+
+ return MimeTypes.GetMimeType(outputPath, enableStreamDefault);
+ }
+
+ public bool DeInterlace(string videoCodec, bool forceDeinterlaceIfSourceIsInterlaced)
+ {
+ var videoStream = VideoStream;
+ var isInputInterlaced = videoStream != null && videoStream.IsInterlaced;
+
+ if (!isInputInterlaced)
+ {
+ return false;
+ }
+
+ // Support general param
+ if (BaseRequest.DeInterlace)
+ {
+ return true;
+ }
+
+ if (!string.IsNullOrEmpty(videoCodec))
+ {
+ if (string.Equals(BaseRequest.GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ }
+
+ return forceDeinterlaceIfSourceIsInterlaced && isInputInterlaced;
+ }
+
+ public string[] GetRequestedProfiles(string codec)
+ {
+ if (!string.IsNullOrEmpty(BaseRequest.Profile))
+ {
+ return BaseRequest.Profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ if (!string.IsNullOrEmpty(codec))
+ {
+ var profile = BaseRequest.GetOption(codec, "profile");
+
+ if (!string.IsNullOrEmpty(profile))
+ {
+ return profile.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries);
+ }
+ }
+
+ return Array.Empty();
+ }
+
+ public string GetRequestedLevel(string codec)
+ {
+ if (!string.IsNullOrEmpty(BaseRequest.Level))
+ {
+ return BaseRequest.Level;
+ }
+
+ if (!string.IsNullOrEmpty(codec))
+ {
+ return BaseRequest.GetOption(codec, "level");
+ }
+
+ return null;
+ }
+
+ public int? GetRequestedMaxRefFrames(string codec)
+ {
+ if (BaseRequest.MaxRefFrames.HasValue)
+ {
+ return BaseRequest.MaxRefFrames;
+ }
+
+ if (!string.IsNullOrEmpty(codec))
+ {
+ var value = BaseRequest.GetOption(codec, "maxrefframes");
+ if (!string.IsNullOrEmpty(value)
+ && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
+ {
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+ public int? GetRequestedVideoBitDepth(string codec)
+ {
+ if (BaseRequest.MaxVideoBitDepth.HasValue)
+ {
+ return BaseRequest.MaxVideoBitDepth;
+ }
+
+ if (!string.IsNullOrEmpty(codec))
+ {
+ var value = BaseRequest.GetOption(codec, "videobitdepth");
+ if (!string.IsNullOrEmpty(value)
+ && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
+ {
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+ public int? GetRequestedAudioBitDepth(string codec)
+ {
+ if (BaseRequest.MaxAudioBitDepth.HasValue)
+ {
+ return BaseRequest.MaxAudioBitDepth;
+ }
+
+ if (!string.IsNullOrEmpty(codec))
+ {
+ var value = BaseRequest.GetOption(codec, "audiobitdepth");
+ if (!string.IsNullOrEmpty(value)
+ && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
+ {
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+ public int? GetRequestedAudioChannels(string codec)
+ {
+ if (!string.IsNullOrEmpty(codec))
+ {
+ var value = BaseRequest.GetOption(codec, "audiochannels");
+ if (!string.IsNullOrEmpty(value)
+ && int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
+ {
+ return result;
+ }
+ }
+
+ if (BaseRequest.MaxAudioChannels.HasValue)
+ {
+ return BaseRequest.MaxAudioChannels;
+ }
+
+ if (BaseRequest.AudioChannels.HasValue)
+ {
+ return BaseRequest.AudioChannels;
+ }
+
+ if (BaseRequest.TranscodingMaxAudioChannels.HasValue)
+ {
+ return BaseRequest.TranscodingMaxAudioChannels;
+ }
+
+ return null;
+ }
public virtual void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate)
{
diff --git a/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs b/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs
index 773547872c..8ce40a58d1 100644
--- a/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs
@@ -16,6 +16,13 @@ namespace MediaBrowser.Controller.MediaEncoding
///
/// Refreshes the chapter images.
///
+ /// Video to use.
+ /// Directory service to use.
+ /// Set of chapters to refresh.
+ /// Option to extract images.
+ /// Option to save chapters.
+ /// CancellationToken to use for operation.
+ /// true if successful, false if not.
Task RefreshChapterImages(Video video, IDirectoryService directoryService, IReadOnlyList chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
index 76a9fd7c74..ff24560703 100644
--- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
@@ -71,13 +71,42 @@ namespace MediaBrowser.Controller.MediaEncoding
///
/// Extracts the video image.
///
+ /// Input file.
+ /// Video container type.
+ /// Media source information.
+ /// Media stream information.
+ /// Video 3D format.
+ /// Time offset.
+ /// CancellationToken to use for operation.
+ /// Location of video image.
Task ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
+ ///
+ /// Extracts the video image.
+ ///
+ /// Input file.
+ /// Video container type.
+ /// Media source information.
+ /// Media stream information.
+ /// Index of the stream to extract from.
+ /// CancellationToken to use for operation.
+ /// Location of video image.
Task ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken);
///
/// Extracts the video images on interval.
///
+ /// Input file.
+ /// Video container type.
+ /// Media stream information.
+ /// Media source information.
+ /// Video 3D format.
+ /// Time interval.
+ /// Directory to write images.
+ /// Filename prefix to use.
+ /// Maximum width of image.
+ /// CancellationToken to use for operation.
+ /// A task.
Task ExtractVideoImagesOnInterval(
string inputFile,
string container,
@@ -122,10 +151,24 @@ namespace MediaBrowser.Controller.MediaEncoding
/// System.String.
string EscapeSubtitleFilterPath(string path);
+ ///
+ /// Sets the path to find FFmpeg.
+ ///
void SetFFmpegPath();
+ ///
+ /// Updates the encoder path.
+ ///
+ /// The path.
+ /// The type of path.
void UpdateEncoderPath(string path, string pathType);
+ ///
+ /// Gets the primary playlist of .vob files.
+ ///
+ /// The to the .vob files.
+ /// The title number to start with.
+ /// A playlist.
IEnumerable GetPrimaryPlaylistVobFiles(string path, uint? titleNumber);
}
}
diff --git a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs
index 3fb2c47e13..4483cf708a 100644
--- a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs
@@ -15,6 +15,14 @@ namespace MediaBrowser.Controller.MediaEncoding
///
/// Gets the subtitles.
///
+ /// Item to use.
+ /// Media source.
+ /// Subtitle stream to use.
+ /// Output format to use.
+ /// Start time.
+ /// End time.
+ /// Option to preserve original timestamps.
+ /// The cancellation token for the operation.
/// Task{Stream}.
Task GetSubtitles(
BaseItem item,
diff --git a/MediaBrowser.Controller/Providers/AlbumInfo.cs b/MediaBrowser.Controller/Providers/AlbumInfo.cs
index c7fad5974a..aefa520e72 100644
--- a/MediaBrowser.Controller/Providers/AlbumInfo.cs
+++ b/MediaBrowser.Controller/Providers/AlbumInfo.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CA2227, CS1591
using System;
using System.Collections.Generic;
diff --git a/MediaBrowser.Controller/Providers/ArtistInfo.cs b/MediaBrowser.Controller/Providers/ArtistInfo.cs
index e9181f4765..4854d1a5fa 100644
--- a/MediaBrowser.Controller/Providers/ArtistInfo.cs
+++ b/MediaBrowser.Controller/Providers/ArtistInfo.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CA2227, CS1591
using System.Collections.Generic;
diff --git a/MediaBrowser.Controller/Providers/EpisodeInfo.cs b/MediaBrowser.Controller/Providers/EpisodeInfo.cs
index 0c932fa877..b59a037384 100644
--- a/MediaBrowser.Controller/Providers/EpisodeInfo.cs
+++ b/MediaBrowser.Controller/Providers/EpisodeInfo.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA2227, CS1591
using System;
using System.Collections.Generic;
diff --git a/MediaBrowser.Controller/Providers/IDirectoryService.cs b/MediaBrowser.Controller/Providers/IDirectoryService.cs
index b1a36e1024..48d6276918 100644
--- a/MediaBrowser.Controller/Providers/IDirectoryService.cs
+++ b/MediaBrowser.Controller/Providers/IDirectoryService.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CA1819, CS1591
using System.Collections.Generic;
using MediaBrowser.Model.IO;
diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs
index 684bd9e681..9f7a76be64 100644
--- a/MediaBrowser.Controller/Providers/IProviderManager.cs
+++ b/MediaBrowser.Controller/Providers/IProviderManager.cs
@@ -31,6 +31,9 @@ namespace MediaBrowser.Controller.Providers
///
/// Queues the refresh.
///
+ /// Item ID.
+ /// MetadataRefreshOptions for operation.
+ /// RefreshPriority for operation.
void QueueRefresh(Guid itemId, MetadataRefreshOptions options, RefreshPriority priority);
///
@@ -85,6 +88,13 @@ namespace MediaBrowser.Controller.Providers
///
/// Saves the image.
///
+ /// Image to save.
+ /// Source of image.
+ /// Mime type image.
+ /// Type of image.
+ /// Index of image.
+ /// Option to save locally.
+ /// CancellationToken to use with operation.
/// Task.
Task SaveImage(BaseItem item, string source, string mimeType, ImageType type, int? imageIndex, bool? saveLocallyWithMedia, CancellationToken cancellationToken);
@@ -93,6 +103,11 @@ namespace MediaBrowser.Controller.Providers
///
/// Adds the metadata providers.
///
+ /// Image providers to use.
+ /// Metadata services to use.
+ /// Metadata providers to use.
+ /// Metadata savers to use.
+ /// External IDs to use.
void AddParts(
IEnumerable imageProviders,
IEnumerable metadataServices,
diff --git a/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs b/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs
index 81a22affb0..2ac4c728ba 100644
--- a/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs
+++ b/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1819, CS1591
using System;
using System.Linq;
@@ -10,6 +10,15 @@ namespace MediaBrowser.Controller.Providers
{
public class ImageRefreshOptions
{
+ public ImageRefreshOptions(IDirectoryService directoryService)
+ {
+ ImageRefreshMode = MetadataRefreshMode.Default;
+ DirectoryService = directoryService;
+
+ ReplaceImages = Array.Empty();
+ IsAutomated = true;
+ }
+
public MetadataRefreshMode ImageRefreshMode { get; set; }
public IDirectoryService DirectoryService { get; private set; }
@@ -20,15 +29,6 @@ namespace MediaBrowser.Controller.Providers
public bool IsAutomated { get; set; }
- public ImageRefreshOptions(IDirectoryService directoryService)
- {
- ImageRefreshMode = MetadataRefreshMode.Default;
- DirectoryService = directoryService;
-
- ReplaceImages = Array.Empty();
- IsAutomated = true;
- }
-
public bool IsReplacingImage(ImageType type)
{
return ImageRefreshMode == MetadataRefreshMode.FullRefresh &&
diff --git a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs
index 2fd89e3bb4..460f4e500f 100644
--- a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs
+++ b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA2227, CS1591
using System;
using System.Collections.Generic;
@@ -23,7 +23,7 @@ namespace MediaBrowser.Controller.Providers
public string Name { get; set; }
///
- /// Gets or sets the original title
+ /// Gets or sets the original title.
///
/// The original title of the item.
public string OriginalTitle { get; set; }
diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
index 2cf5367793..a42c7f8b5e 100644
--- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
+++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1819, CS1591
using System;
using System.Linq;
diff --git a/MediaBrowser.Controller/Providers/MetadataResult.cs b/MediaBrowser.Controller/Providers/MetadataResult.cs
index 7ec1eefcd6..2085ae4adf 100644
--- a/MediaBrowser.Controller/Providers/MetadataResult.cs
+++ b/MediaBrowser.Controller/Providers/MetadataResult.cs
@@ -1,6 +1,6 @@
#nullable disable
-#pragma warning disable CS1591
+#pragma warning disable CA1002, CA2227, CS1591
using System;
using System.Collections.Generic;
diff --git a/MediaBrowser.Controller/Providers/SeasonInfo.cs b/MediaBrowser.Controller/Providers/SeasonInfo.cs
index 7e39bc37a6..1edceb0e4a 100644
--- a/MediaBrowser.Controller/Providers/SeasonInfo.cs
+++ b/MediaBrowser.Controller/Providers/SeasonInfo.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CA2227, CS1591
using System;
using System.Collections.Generic;
diff --git a/MediaBrowser.Controller/Providers/SongInfo.cs b/MediaBrowser.Controller/Providers/SongInfo.cs
index c90717a2e1..4b64a8a982 100644
--- a/MediaBrowser.Controller/Providers/SongInfo.cs
+++ b/MediaBrowser.Controller/Providers/SongInfo.cs
@@ -9,16 +9,16 @@ namespace MediaBrowser.Controller.Providers
{
public class SongInfo : ItemLookupInfo
{
- public IReadOnlyList AlbumArtists { get; set; }
-
- public string Album { get; set; }
-
- public IReadOnlyList Artists { get; set; }
-
public SongInfo()
{
Artists = Array.Empty();
AlbumArtists = Array.Empty();
}
+
+ public IReadOnlyList AlbumArtists { get; set; }
+
+ public string Album { get; set; }
+
+ public IReadOnlyList Artists { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Session/ISessionController.cs b/MediaBrowser.Controller/Session/ISessionController.cs
index 6bc39d6f4e..b38ee11462 100644
--- a/MediaBrowser.Controller/Session/ISessionController.cs
+++ b/MediaBrowser.Controller/Session/ISessionController.cs
@@ -26,6 +26,12 @@ namespace MediaBrowser.Controller.Session
///