mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-11-03 19:17:24 -05:00 
			
		
		
		
	Merge branch 'jellyfin:master' into feature/EFUserData
This commit is contained in:
		
						commit
						fe1aab034e
					
				@ -1,28 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "Development Jellyfin Server - FFmpeg",
 | 
			
		||||
    "image":"mcr.microsoft.com/devcontainers/dotnet:9.0-jammy",
 | 
			
		||||
    // restores nuget packages, installs the dotnet workloads and installs the dev https certificate
 | 
			
		||||
    "postStartCommand": "dotnet restore; dotnet workload update; dotnet dev-certs https --trust; sudo bash \"./.devcontainer/Dev - Server Ffmpeg/install-ffmpeg.sh\"",
 | 
			
		||||
    // reads the extensions list and installs them
 | 
			
		||||
    "postAttachCommand": "cat .vscode/extensions.json | jq -r .recommendations[] | xargs -n 1 code --install-extension",
 | 
			
		||||
    "features": {
 | 
			
		||||
        "ghcr.io/devcontainers/features/dotnet:2": {
 | 
			
		||||
            "version": "none",
 | 
			
		||||
            "dotnetRuntimeVersions": "9.0",
 | 
			
		||||
            "aspNetCoreRuntimeVersions": "9.0"
 | 
			
		||||
        },
 | 
			
		||||
        "ghcr.io/devcontainers-contrib/features/apt-packages:1": {
 | 
			
		||||
            "preserve_apt_list": false,
 | 
			
		||||
            "packages": ["libfontconfig1"]
 | 
			
		||||
        },
 | 
			
		||||
        "ghcr.io/devcontainers/features/docker-in-docker:2": {
 | 
			
		||||
            "dockerDashComposeVersion": "v2"
 | 
			
		||||
        },
 | 
			
		||||
        "ghcr.io/devcontainers/features/github-cli:1": {},
 | 
			
		||||
        "ghcr.io/eitsupi/devcontainer-features/jq-likes:2": {}
 | 
			
		||||
    },
 | 
			
		||||
    "hostRequirements": {
 | 
			
		||||
        "memory": "8gb",
 | 
			
		||||
        "cpus": 4
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "Development Jellyfin Server",
 | 
			
		||||
    "image":"mcr.microsoft.com/devcontainers/dotnet:9.0-jammy",
 | 
			
		||||
    "image":"mcr.microsoft.com/devcontainers/dotnet:9.0-bookworm",
 | 
			
		||||
    // restores nuget packages, installs the dotnet workloads and installs the dev https certificate
 | 
			
		||||
    "postStartCommand": "dotnet restore; dotnet workload update; dotnet dev-certs https --trust",
 | 
			
		||||
    "postStartCommand": "sudo dotnet restore; sudo dotnet workload update; sudo dotnet dev-certs https --trust; sudo bash \"./.devcontainer/install-ffmpeg.sh\"",
 | 
			
		||||
    // reads the extensions list and installs them
 | 
			
		||||
    "postAttachCommand": "cat .vscode/extensions.json | jq -r .recommendations[] | xargs -n 1 code --install-extension",
 | 
			
		||||
    "features": {
 | 
			
		||||
 | 
			
		||||
@ -29,4 +29,4 @@ Signed-By: /etc/apt/keyrings/jellyfin.gpg
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
sudo apt update -y
 | 
			
		||||
sudo apt install jellyfin-ffmpeg6 -y
 | 
			
		||||
sudo apt install jellyfin-ffmpeg7 -y
 | 
			
		||||
							
								
								
									
										6
									
								
								.github/workflows/ci-codeql-analysis.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/ci-codeql-analysis.yml
									
									
									
									
										vendored
									
									
								
							@ -27,11 +27,11 @@ jobs:
 | 
			
		||||
        dotnet-version: '9.0.x'
 | 
			
		||||
 | 
			
		||||
    - name: Initialize CodeQL
 | 
			
		||||
      uses: github/codeql-action/init@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4
 | 
			
		||||
      uses: github/codeql-action/init@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6
 | 
			
		||||
      with:
 | 
			
		||||
        languages: ${{ matrix.language }}
 | 
			
		||||
        queries: +security-extended
 | 
			
		||||
    - name: Autobuild
 | 
			
		||||
      uses: github/codeql-action/autobuild@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4
 | 
			
		||||
      uses: github/codeql-action/autobuild@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6
 | 
			
		||||
    - name: Perform CodeQL Analysis
 | 
			
		||||
      uses: github/codeql-action/analyze@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4
 | 
			
		||||
      uses: github/codeql-action/analyze@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								.github/workflows/ci-openapi.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/ci-openapi.yml
									
									
									
									
										vendored
									
									
								
							@ -172,7 +172,7 @@ jobs:
 | 
			
		||||
          strip_components: 1
 | 
			
		||||
          target: "/srv/incoming/openapi/unstable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}"
 | 
			
		||||
      - name: Move openapi.json (unstable) into place
 | 
			
		||||
        uses: appleboy/ssh-action@25ce8cbbcb08177468c7ff7ec5cbfa236f9341e1 # v1.1.0
 | 
			
		||||
        uses: appleboy/ssh-action@7eaf76671a0d7eec5d98ee897acda4f968735a17 # v1.2.0
 | 
			
		||||
        with:
 | 
			
		||||
          host: "${{ secrets.REPO_HOST }}"
 | 
			
		||||
          username: "${{ secrets.REPO_USER }}"
 | 
			
		||||
@ -234,7 +234,7 @@ jobs:
 | 
			
		||||
          strip_components: 1
 | 
			
		||||
          target: "/srv/incoming/openapi/stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}"
 | 
			
		||||
      - name: Move openapi.json (stable) into place
 | 
			
		||||
        uses: appleboy/ssh-action@25ce8cbbcb08177468c7ff7ec5cbfa236f9341e1 # v1.1.0
 | 
			
		||||
        uses: appleboy/ssh-action@7eaf76671a0d7eec5d98ee897acda4f968735a17 # v1.2.0
 | 
			
		||||
        with:
 | 
			
		||||
          host: "${{ secrets.REPO_HOST }}"
 | 
			
		||||
          username: "${{ secrets.REPO_USER }}"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
								
							@ -4,7 +4,8 @@
 | 
			
		||||
        "editorconfig.editorconfig",
 | 
			
		||||
        "github.vscode-github-actions",
 | 
			
		||||
        "ms-dotnettools.vscode-dotnet-runtime",
 | 
			
		||||
        "ms-dotnettools.csdevkit"
 | 
			
		||||
        "ms-dotnettools.csdevkit",
 | 
			
		||||
        "alexcvzz.vscode-sqlite"
 | 
			
		||||
    ],
 | 
			
		||||
    "unwantedRecommendations": [
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -192,6 +192,7 @@
 | 
			
		||||
 - [jaina heartles](https://github.com/heartles)
 | 
			
		||||
 - [oxixes](https://github.com/oxixes)
 | 
			
		||||
 - [elfalem](https://github.com/elfalem)
 | 
			
		||||
 - [Kenneth Cochran](https://github.com/kennethcochran)
 | 
			
		||||
 - [benedikt257](https://github.com/benedikt257)
 | 
			
		||||
 - [revam](https://github.com/revam)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <!-- Run "dotnet list package (dash,dash)outdated" to see the latest versions of each package.-->
 | 
			
		||||
  <ItemGroup Label="Package Dependencies">
 | 
			
		||||
    <PackageVersion Include="AsyncKeyedLock" Version="7.1.3" />
 | 
			
		||||
    <PackageVersion Include="AsyncKeyedLock" Version="7.1.4" />
 | 
			
		||||
    <PackageVersion Include="AutoFixture.AutoMoq" Version="4.18.1" />
 | 
			
		||||
    <PackageVersion Include="AutoFixture.Xunit2" Version="4.18.1" />
 | 
			
		||||
    <PackageVersion Include="AutoFixture" Version="4.18.1" />
 | 
			
		||||
@ -47,8 +47,8 @@
 | 
			
		||||
    <PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" />
 | 
			
		||||
    <PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.0" />
 | 
			
		||||
    <PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.0" />
 | 
			
		||||
    <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
 | 
			
		||||
    <PackageVersion Include="MimeTypes" Version="2.4.0" />
 | 
			
		||||
    <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
 | 
			
		||||
    <PackageVersion Include="MimeTypes" Version="2.5.2" />
 | 
			
		||||
    <PackageVersion Include="Mono.Nat" Version="3.0.4" />
 | 
			
		||||
    <PackageVersion Include="Moq" Version="4.18.4" />
 | 
			
		||||
    <PackageVersion Include="NEbml" Version="0.11.0" />
 | 
			
		||||
@ -71,7 +71,7 @@
 | 
			
		||||
    <PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
 | 
			
		||||
    <PackageVersion Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" />
 | 
			
		||||
    <PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
 | 
			
		||||
    <PackageVersion Include="Svg.Skia" Version="2.0.0.2" />
 | 
			
		||||
    <PackageVersion Include="Svg.Skia" Version="2.0.0.4" />
 | 
			
		||||
    <PackageVersion Include="Swashbuckle.AspNetCore.ReDoc" Version="6.5.0" />
 | 
			
		||||
    <PackageVersion Include="Swashbuckle.AspNetCore" Version="6.2.3" />
 | 
			
		||||
    <PackageVersion Include="System.Globalization" Version="4.3.0" />
 | 
			
		||||
@ -80,12 +80,12 @@
 | 
			
		||||
    <PackageVersion Include="System.Text.Json" Version="9.0.0" />
 | 
			
		||||
    <PackageVersion Include="System.Threading.Tasks.Dataflow" Version="9.0.0" />
 | 
			
		||||
    <PackageVersion Include="TagLibSharp" Version="2.3.0" />
 | 
			
		||||
    <PackageVersion Include="z440.atl.core" Version="6.8.0" />
 | 
			
		||||
    <PackageVersion Include="z440.atl.core" Version="6.9.0" />
 | 
			
		||||
    <PackageVersion Include="TMDbLib" Version="2.2.0" />
 | 
			
		||||
    <PackageVersion Include="UTF.Unknown" Version="2.5.1" />
 | 
			
		||||
    <PackageVersion Include="Xunit.Priority" Version="1.1.6" />
 | 
			
		||||
    <PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
 | 
			
		||||
    <PackageVersion Include="Xunit.SkippableFact" Version="1.4.13" />
 | 
			
		||||
    <PackageVersion Include="Xunit.SkippableFact" Version="1.5.23" />
 | 
			
		||||
    <PackageVersion Include="xunit" Version="2.9.2" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
</Project>
 | 
			
		||||
@ -131,5 +131,6 @@
 | 
			
		||||
    "TaskRefreshTrickplayImages": "Генерирај слики за прегледување (Trickplay)",
 | 
			
		||||
    "TaskAudioNormalization": "Нормализација на звукот",
 | 
			
		||||
    "TaskRefreshTrickplayImagesDescription": "Креира трикплеј прегледи за видеа во овозможените библиотеки.",
 | 
			
		||||
    "TaskCleanCollectionsAndPlaylistsDescription": "Отстранува ставки од колекциите и плејлистите што веќе не постојат."
 | 
			
		||||
    "TaskCleanCollectionsAndPlaylistsDescription": "Отстранува ставки од колекциите и плејлистите што веќе не постојат.",
 | 
			
		||||
    "TaskExtractMediaSegments": "Скенирање на сегменти на содржина"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -77,7 +77,7 @@
 | 
			
		||||
    "HeaderAlbumArtists": "Artiști album",
 | 
			
		||||
    "Genres": "Genuri",
 | 
			
		||||
    "Folders": "Dosare",
 | 
			
		||||
    "Favorites": "Favorite",
 | 
			
		||||
    "Favorites": "Preferate",
 | 
			
		||||
    "FailedLoginAttemptWithUserName": "Încercare de conectare eșuată pentru {0}",
 | 
			
		||||
    "DeviceOnlineWithName": "{0} este conectat",
 | 
			
		||||
    "DeviceOfflineWithName": "{0} s-a deconectat",
 | 
			
		||||
 | 
			
		||||
@ -133,5 +133,6 @@
 | 
			
		||||
    "TaskDownloadMissingLyricsDescription": "下載歌詞",
 | 
			
		||||
    "TaskCleanCollectionsAndPlaylists": "整理媒體與播放清單",
 | 
			
		||||
    "TaskAudioNormalization": "音訊同等化",
 | 
			
		||||
    "TaskAudioNormalizationDescription": "掃描檔案裏的音訊同等化資料。"
 | 
			
		||||
    "TaskAudioNormalizationDescription": "掃描檔案裏的音訊同等化資料。",
 | 
			
		||||
    "TaskCleanCollectionsAndPlaylistsDescription": "從資料庫及播放清單中移除已不存在的項目。"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -5,23 +5,23 @@ TV-Y,0
 | 
			
		||||
TV-Y7,7
 | 
			
		||||
TV-Y7-FV,7
 | 
			
		||||
PG,10
 | 
			
		||||
TV-PG,10
 | 
			
		||||
TV-PG-D,10
 | 
			
		||||
TV-PG-L,10
 | 
			
		||||
TV-PG-S,10
 | 
			
		||||
TV-PG-V,10
 | 
			
		||||
TV-PG-DL,10
 | 
			
		||||
TV-PG-DS,10
 | 
			
		||||
TV-PG-DV,10
 | 
			
		||||
TV-PG-LS,10
 | 
			
		||||
TV-PG-LV,10
 | 
			
		||||
TV-PG-SV,10
 | 
			
		||||
TV-PG-DLS,10
 | 
			
		||||
TV-PG-DLV,10
 | 
			
		||||
TV-PG-DSV,10
 | 
			
		||||
TV-PG-LSV,10
 | 
			
		||||
TV-PG-DLSV,10
 | 
			
		||||
PG-13,13
 | 
			
		||||
TV-PG,13
 | 
			
		||||
TV-PG-D,13
 | 
			
		||||
TV-PG-L,13
 | 
			
		||||
TV-PG-S,13
 | 
			
		||||
TV-PG-V,13
 | 
			
		||||
TV-PG-DL,13
 | 
			
		||||
TV-PG-DS,13
 | 
			
		||||
TV-PG-DV,13
 | 
			
		||||
TV-PG-LS,13
 | 
			
		||||
TV-PG-LV,13
 | 
			
		||||
TV-PG-SV,13
 | 
			
		||||
TV-PG-DLS,13
 | 
			
		||||
TV-PG-DLV,13
 | 
			
		||||
TV-PG-DSV,13
 | 
			
		||||
TV-PG-LSV,13
 | 
			
		||||
TV-PG-DLSV,13
 | 
			
		||||
TV-14,14
 | 
			
		||||
TV-14-D,14
 | 
			
		||||
TV-14-L,14
 | 
			
		||||
 | 
			
		||||
		
		
			
  | 
@ -785,8 +785,6 @@ namespace Emby.Server.Implementations.Plugins
 | 
			
		||||
 | 
			
		||||
                var cleaned = false;
 | 
			
		||||
                var path = entry.Path;
 | 
			
		||||
                if (_config.RemoveOldPlugins)
 | 
			
		||||
                {
 | 
			
		||||
                // Attempt a cleanup of old folders.
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
@ -810,7 +808,6 @@ namespace Emby.Server.Implementations.Plugins
 | 
			
		||||
                    ChangePluginState(entry, PluginStatus.Deleted);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Only want plugin folders which have files.
 | 
			
		||||
            return versions.Where(p => p.DllFiles.Count != 0);
 | 
			
		||||
 | 
			
		||||
@ -471,7 +471,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
 | 
			
		||||
                    new()
 | 
			
		||||
                    {
 | 
			
		||||
                        IntervalTicks = TimeSpan.FromDays(1).Ticks,
 | 
			
		||||
                        Type = TaskTriggerInfo.TriggerInterval
 | 
			
		||||
                        Type = TaskTriggerInfoType.IntervalTrigger
 | 
			
		||||
                    }
 | 
			
		||||
                ];
 | 
			
		||||
            }
 | 
			
		||||
@ -616,7 +616,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
 | 
			
		||||
                MaxRuntimeTicks = info.MaxRuntimeTicks
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            if (info.Type.Equals(nameof(DailyTrigger), StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
            if (info.Type == TaskTriggerInfoType.DailyTrigger)
 | 
			
		||||
            {
 | 
			
		||||
                if (!info.TimeOfDayTicks.HasValue)
 | 
			
		||||
                {
 | 
			
		||||
@ -626,7 +626,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
 | 
			
		||||
                return new DailyTrigger(TimeSpan.FromTicks(info.TimeOfDayTicks.Value), options);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (info.Type.Equals(nameof(WeeklyTrigger), StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
            if (info.Type == TaskTriggerInfoType.WeeklyTrigger)
 | 
			
		||||
            {
 | 
			
		||||
                if (!info.TimeOfDayTicks.HasValue)
 | 
			
		||||
                {
 | 
			
		||||
@ -641,7 +641,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
 | 
			
		||||
                return new WeeklyTrigger(TimeSpan.FromTicks(info.TimeOfDayTicks.Value), info.DayOfWeek.Value, options);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (info.Type.Equals(nameof(IntervalTrigger), StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
            if (info.Type == TaskTriggerInfoType.IntervalTrigger)
 | 
			
		||||
            {
 | 
			
		||||
                if (!info.IntervalTicks.HasValue)
 | 
			
		||||
                {
 | 
			
		||||
@ -651,7 +651,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
 | 
			
		||||
                return new IntervalTrigger(TimeSpan.FromTicks(info.IntervalTicks.Value), options);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (info.Type.Equals(nameof(StartupTrigger), StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
            if (info.Type == TaskTriggerInfoType.StartupTrigger)
 | 
			
		||||
            {
 | 
			
		||||
                return new StartupTrigger(options);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -156,7 +156,7 @@ public partial class AudioNormalizationTask : IScheduledTask
 | 
			
		||||
        [
 | 
			
		||||
            new TaskTriggerInfo
 | 
			
		||||
            {
 | 
			
		||||
                Type = TaskTriggerInfo.TriggerInterval,
 | 
			
		||||
                Type = TaskTriggerInfoType.IntervalTrigger,
 | 
			
		||||
                IntervalTicks = TimeSpan.FromHours(24).Ticks
 | 
			
		||||
            }
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
@ -85,7 +85,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
 | 
			
		||||
            [
 | 
			
		||||
                new TaskTriggerInfo
 | 
			
		||||
                {
 | 
			
		||||
                    Type = TaskTriggerInfo.TriggerDaily,
 | 
			
		||||
                    Type = TaskTriggerInfoType.DailyTrigger,
 | 
			
		||||
                    TimeOfDayTicks = TimeSpan.FromHours(2).Ticks,
 | 
			
		||||
                    MaxRuntimeTicks = TimeSpan.FromHours(4).Ticks
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -135,6 +135,6 @@ public class CleanupCollectionAndPlaylistPathsTask : IScheduledTask
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
 | 
			
		||||
    {
 | 
			
		||||
        return [new TaskTriggerInfo() { Type = TaskTriggerInfo.TriggerStartup }];
 | 
			
		||||
        return [new TaskTriggerInfo() { Type = TaskTriggerInfoType.StartupTrigger }];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -73,7 +73,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
 | 
			
		||||
            return
 | 
			
		||||
            [
 | 
			
		||||
                // Every so often
 | 
			
		||||
                new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks }
 | 
			
		||||
                new TaskTriggerInfo { Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks }
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -62,7 +62,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
 | 
			
		||||
        {
 | 
			
		||||
            return
 | 
			
		||||
            [
 | 
			
		||||
                new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks }
 | 
			
		||||
                new TaskTriggerInfo { Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks }
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -69,11 +69,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
 | 
			
		||||
            [
 | 
			
		||||
                new TaskTriggerInfo
 | 
			
		||||
                {
 | 
			
		||||
                    Type = TaskTriggerInfo.TriggerStartup
 | 
			
		||||
                    Type = TaskTriggerInfoType.StartupTrigger
 | 
			
		||||
                },
 | 
			
		||||
                new TaskTriggerInfo
 | 
			
		||||
                {
 | 
			
		||||
                    Type = TaskTriggerInfo.TriggerInterval,
 | 
			
		||||
                    Type = TaskTriggerInfoType.IntervalTrigger,
 | 
			
		||||
                    IntervalTicks = TimeSpan.FromHours(24).Ticks
 | 
			
		||||
                }
 | 
			
		||||
            ];
 | 
			
		||||
 | 
			
		||||
@ -111,7 +111,7 @@ public class MediaSegmentExtractionTask : IScheduledTask
 | 
			
		||||
    {
 | 
			
		||||
        yield return new TaskTriggerInfo
 | 
			
		||||
        {
 | 
			
		||||
            Type = TaskTriggerInfo.TriggerInterval,
 | 
			
		||||
            Type = TaskTriggerInfoType.IntervalTrigger,
 | 
			
		||||
            IntervalTicks = TimeSpan.FromHours(12).Ticks
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -62,7 +62,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
 | 
			
		||||
            return
 | 
			
		||||
            [
 | 
			
		||||
                // Every so often
 | 
			
		||||
                new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks }
 | 
			
		||||
                new TaskTriggerInfo { Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks }
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -58,7 +58,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
 | 
			
		||||
            {
 | 
			
		||||
                new TaskTriggerInfo
 | 
			
		||||
                {
 | 
			
		||||
                    Type = TaskTriggerInfo.TriggerInterval,
 | 
			
		||||
                    Type = TaskTriggerInfoType.IntervalTrigger,
 | 
			
		||||
                    IntervalTicks = TimeSpan.FromDays(7).Ticks
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
@ -60,10 +60,10 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
 | 
			
		||||
        public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
 | 
			
		||||
        {
 | 
			
		||||
            // At startup
 | 
			
		||||
            yield return new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerStartup };
 | 
			
		||||
            yield return new TaskTriggerInfo { Type = TaskTriggerInfoType.StartupTrigger };
 | 
			
		||||
 | 
			
		||||
            // Every so often
 | 
			
		||||
            yield return new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks };
 | 
			
		||||
            yield return new TaskTriggerInfo { Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc />
 | 
			
		||||
 | 
			
		||||
@ -48,7 +48,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
 | 
			
		||||
        {
 | 
			
		||||
            yield return new TaskTriggerInfo
 | 
			
		||||
            {
 | 
			
		||||
                Type = TaskTriggerInfo.TriggerInterval,
 | 
			
		||||
                Type = TaskTriggerInfoType.IntervalTrigger,
 | 
			
		||||
                IntervalTicks = TimeSpan.FromHours(12).Ticks
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -1819,16 +1819,13 @@ public class DynamicHlsController : BaseJellyfinApiController
 | 
			
		||||
        if (isActualOutputVideoCodecHevc || isActualOutputVideoCodecAv1)
 | 
			
		||||
        {
 | 
			
		||||
            var requestedRange = state.GetRequestedRangeTypes(state.ActualOutputVideoCodec);
 | 
			
		||||
            var requestHasDOVI = requestedRange.Contains(VideoRangeType.DOVI.ToString(), StringComparison.OrdinalIgnoreCase);
 | 
			
		||||
            var requestHasDOVIWithHDR10 = requestedRange.Contains(VideoRangeType.DOVIWithHDR10.ToString(), StringComparison.OrdinalIgnoreCase);
 | 
			
		||||
            var requestHasDOVIWithHLG = requestedRange.Contains(VideoRangeType.DOVIWithHLG.ToString(), StringComparison.OrdinalIgnoreCase);
 | 
			
		||||
            var requestHasDOVIWithSDR = requestedRange.Contains(VideoRangeType.DOVIWithSDR.ToString(), StringComparison.OrdinalIgnoreCase);
 | 
			
		||||
            // Clients reporting Dolby Vision capabilities with fallbacks may only support the fallback layer.
 | 
			
		||||
            // Only enable Dolby Vision remuxing if the client explicitly declares support for profiles without fallbacks.
 | 
			
		||||
            var clientSupportsDoVi = requestedRange.Contains(VideoRangeType.DOVI.ToString(), StringComparison.OrdinalIgnoreCase);
 | 
			
		||||
            var videoIsDoVi = state.VideoStream.VideoRangeType is VideoRangeType.DOVI or VideoRangeType.DOVIWithHDR10 or VideoRangeType.DOVIWithHLG or VideoRangeType.DOVIWithSDR;
 | 
			
		||||
 | 
			
		||||
            if (EncodingHelper.IsCopyCodec(codec)
 | 
			
		||||
                && ((state.VideoStream.VideoRangeType == VideoRangeType.DOVI && requestHasDOVI)
 | 
			
		||||
                    || (state.VideoStream.VideoRangeType == VideoRangeType.DOVIWithHDR10 && requestHasDOVIWithHDR10)
 | 
			
		||||
                    || (state.VideoStream.VideoRangeType == VideoRangeType.DOVIWithHLG && requestHasDOVIWithHLG)
 | 
			
		||||
                    || (state.VideoStream.VideoRangeType == VideoRangeType.DOVIWithSDR && requestHasDOVIWithSDR)))
 | 
			
		||||
                && (videoIsDoVi && clientSupportsDoVi))
 | 
			
		||||
            {
 | 
			
		||||
                if (isActualOutputVideoCodecHevc)
 | 
			
		||||
                {
 | 
			
		||||
 | 
			
		||||
@ -962,9 +962,9 @@ public class LiveTvController : BaseJellyfinApiController
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Get guid info.
 | 
			
		||||
    /// Get guide info.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <response code="200">Guid info returned.</response>
 | 
			
		||||
    /// <response code="200">Guide info returned.</response>
 | 
			
		||||
    /// <returns>An <see cref="OkResult"/> containing the guide info.</returns>
 | 
			
		||||
    [HttpGet("GuideInfo")]
 | 
			
		||||
    [Authorize(Policy = Policies.LiveTvAccess)]
 | 
			
		||||
 | 
			
		||||
@ -61,7 +61,7 @@ public class MediaSegmentManager : IMediaSegmentManager
 | 
			
		||||
            .Where(e => !libraryOptions.DisabledMediaSegmentProviders.Contains(GetProviderId(e.Name)))
 | 
			
		||||
            .OrderBy(i =>
 | 
			
		||||
                {
 | 
			
		||||
                    var index = libraryOptions.MediaSegmentProvideOrder.IndexOf(i.Name);
 | 
			
		||||
                    var index = libraryOptions.MediaSegmentProviderOrder.IndexOf(i.Name);
 | 
			
		||||
                    return index == -1 ? int.MaxValue : index;
 | 
			
		||||
                })
 | 
			
		||||
            .ToList();
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,7 @@ namespace Jellyfin.Server.Migrations.Routines
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public Guid Id => Guid.Parse("{67445D54-B895-4B24-9F4C-35CE0690EA07}");
 | 
			
		||||
        public Guid Id => Guid.Parse("{73DAB92A-178B-48CD-B05B-FE18733ACDC8}");
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public string Name => "MigrateRatingLevels";
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@ namespace MediaBrowser.Model.Configuration
 | 
			
		||||
            TypeOptions = Array.Empty<TypeOptions>();
 | 
			
		||||
            DisabledSubtitleFetchers = Array.Empty<string>();
 | 
			
		||||
            DisabledMediaSegmentProviders = Array.Empty<string>();
 | 
			
		||||
            MediaSegmentProvideOrder = Array.Empty<string>();
 | 
			
		||||
            MediaSegmentProviderOrder = Array.Empty<string>();
 | 
			
		||||
            SubtitleFetcherOrder = Array.Empty<string>();
 | 
			
		||||
            DisabledLocalMetadataReaders = Array.Empty<string>();
 | 
			
		||||
            DisabledLyricFetchers = Array.Empty<string>();
 | 
			
		||||
@ -99,7 +99,7 @@ namespace MediaBrowser.Model.Configuration
 | 
			
		||||
 | 
			
		||||
        public string[] DisabledMediaSegmentProviders { get; set; }
 | 
			
		||||
 | 
			
		||||
        public string[] MediaSegmentProvideOrder { get; set; }
 | 
			
		||||
        public string[] MediaSegmentProviderOrder { get; set; }
 | 
			
		||||
 | 
			
		||||
        public bool SkipSubtitlesIfEmbeddedSubtitlesPresent { get; set; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -243,11 +243,6 @@ public class ServerConfiguration : BaseApplicationConfiguration
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public int LibraryMetadataRefreshConcurrency { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Gets or sets a value indicating whether older plugins should automatically be deleted from the plugin folder.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public bool RemoveOldPlugins { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Gets or sets a value indicating whether clients should be allowed to upload logs.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
 | 
			
		||||
@ -125,6 +125,7 @@ namespace MediaBrowser.Model.Net
 | 
			
		||||
            new("audio/vorbis", ".vorbis"),
 | 
			
		||||
            new("audio/x-ape", ".ape"),
 | 
			
		||||
            new("audio/xsp", ".xsp"),
 | 
			
		||||
            new("audio/x-aac", ".aac"),
 | 
			
		||||
            new("audio/x-wavpack", ".wv"),
 | 
			
		||||
 | 
			
		||||
            // Type image
 | 
			
		||||
 | 
			
		||||
@ -8,31 +8,11 @@ namespace MediaBrowser.Model.Tasks
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class TaskTriggerInfo
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The daily trigger.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public const string TriggerDaily = "DailyTrigger";
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The weekly trigger.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public const string TriggerWeekly = "WeeklyTrigger";
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The interval trigger.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public const string TriggerInterval = "IntervalTrigger";
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The startup trigger.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public const string TriggerStartup = "StartupTrigger";
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets or sets the type.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <value>The type.</value>
 | 
			
		||||
        public string Type { get; set; }
 | 
			
		||||
        public TaskTriggerInfoType Type { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets or sets the time of day.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										28
									
								
								MediaBrowser.Model/Tasks/TaskTriggerInfoType.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								MediaBrowser.Model/Tasks/TaskTriggerInfoType.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
namespace MediaBrowser.Model.Tasks
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Enum TaskTriggerInfoType.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public enum TaskTriggerInfoType
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The daily trigger.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        DailyTrigger,
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The weekly trigger.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        WeeklyTrigger,
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The interval trigger.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        IntervalTrigger,
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The startup trigger.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        StartupTrigger
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -162,7 +162,7 @@ public class LyricScheduledTask : IScheduledTask
 | 
			
		||||
        [
 | 
			
		||||
            new TaskTriggerInfo
 | 
			
		||||
            {
 | 
			
		||||
                Type = TaskTriggerInfo.TriggerInterval,
 | 
			
		||||
                Type = TaskTriggerInfoType.IntervalTrigger,
 | 
			
		||||
                IntervalTicks = TimeSpan.FromHours(24).Ticks
 | 
			
		||||
            }
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
@ -217,7 +217,7 @@ namespace MediaBrowser.Providers.MediaInfo
 | 
			
		||||
            return new[]
 | 
			
		||||
            {
 | 
			
		||||
                // Every so often
 | 
			
		||||
                new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks }
 | 
			
		||||
                new TaskTriggerInfo { Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks }
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -63,7 +63,7 @@ public class TrickplayImagesTask : IScheduledTask
 | 
			
		||||
        {
 | 
			
		||||
            new TaskTriggerInfo
 | 
			
		||||
            {
 | 
			
		||||
                Type = TaskTriggerInfo.TriggerDaily,
 | 
			
		||||
                Type = TaskTriggerInfoType.DailyTrigger,
 | 
			
		||||
                TimeOfDayTicks = TimeSpan.FromHours(3).Ticks
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
@ -79,7 +79,7 @@ namespace Jellyfin.LiveTv.Channels
 | 
			
		||||
                // Every so often
 | 
			
		||||
                new TaskTriggerInfo
 | 
			
		||||
                {
 | 
			
		||||
                    Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks
 | 
			
		||||
                    Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -66,7 +66,7 @@ public class RefreshGuideScheduledTask : IScheduledTask, IConfigurableScheduledT
 | 
			
		||||
        {
 | 
			
		||||
            new TaskTriggerInfo
 | 
			
		||||
            {
 | 
			
		||||
                Type = TaskTriggerInfo.TriggerInterval,
 | 
			
		||||
                Type = TaskTriggerInfoType.IntervalTrigger,
 | 
			
		||||
                IntervalTicks = TimeSpan.FromHours(24).Ticks
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										50
									
								
								tests/Jellyfin.LiveTv.Tests/Listings/ListingsManagerTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								tests/Jellyfin.LiveTv.Tests/Listings/ListingsManagerTests.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
			
		||||
using System;
 | 
			
		||||
using Jellyfin.LiveTv.Configuration;
 | 
			
		||||
using Jellyfin.LiveTv.Listings;
 | 
			
		||||
using MediaBrowser.Common.Configuration;
 | 
			
		||||
using MediaBrowser.Controller.LiveTv;
 | 
			
		||||
using MediaBrowser.Model.LiveTv;
 | 
			
		||||
using MediaBrowser.Model.Tasks;
 | 
			
		||||
using Microsoft.Extensions.Logging;
 | 
			
		||||
using Moq;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace Jellyfin.LiveTv.Tests.Listings;
 | 
			
		||||
 | 
			
		||||
public class ListingsManagerTests
 | 
			
		||||
{
 | 
			
		||||
    private readonly IConfigurationManager _config;
 | 
			
		||||
    private readonly IListingsProvider[] _listingsProviders;
 | 
			
		||||
    private readonly ILogger<ListingsManager> _logger;
 | 
			
		||||
    private readonly ITaskManager _taskManager;
 | 
			
		||||
    private readonly ITunerHostManager _tunerHostManager;
 | 
			
		||||
 | 
			
		||||
    public ListingsManagerTests()
 | 
			
		||||
    {
 | 
			
		||||
        _logger = Mock.Of<ILogger<ListingsManager>>();
 | 
			
		||||
        _config = Mock.Of<IConfigurationManager>();
 | 
			
		||||
        _taskManager = Mock.Of<ITaskManager>();
 | 
			
		||||
        _tunerHostManager = Mock.Of<ITunerHostManager>();
 | 
			
		||||
        _listingsProviders = new[] { Mock.Of<IListingsProvider>() };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void DeleteListingsProvider_DeletesProvider()
 | 
			
		||||
    {
 | 
			
		||||
        // Arrange
 | 
			
		||||
        var id = "MockId";
 | 
			
		||||
        var manager = new ListingsManager(_logger, _config, _taskManager, _tunerHostManager, _listingsProviders);
 | 
			
		||||
 | 
			
		||||
        Mock.Get(_config)
 | 
			
		||||
            .Setup(x => x.GetConfiguration(It.IsAny<string>()))
 | 
			
		||||
            .Returns(new LiveTvOptions { ListingProviders = [new ListingsProviderInfo { Id = id }] });
 | 
			
		||||
 | 
			
		||||
        // Act
 | 
			
		||||
        manager.DeleteListingsProvider(id);
 | 
			
		||||
 | 
			
		||||
        // Assert
 | 
			
		||||
        Assert.DoesNotContain(
 | 
			
		||||
            _config.GetLiveTvConfiguration().ListingProviders,
 | 
			
		||||
            p => p.Id.Equals(id, StringComparison.Ordinal));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user