Преглед на файлове

Merge branch 'master' into providermanager-cleanup

Claus Vium преди 2 години
родител
ревизия
81b04ddbb5
променени са 100 файла, в които са добавени 666 реда и са изтрити 5674 реда
  1. 2 0
      .ci/azure-pipelines-package.yml
  2. 4 4
      .github/workflows/codeql-analysis.yml
  3. 1 1
      .github/workflows/commands.yml
  4. 6 6
      .github/workflows/openapi.yml
  5. 1 1
      .github/workflows/repo-stale.yaml
  6. 4 0
      CONTRIBUTORS.md
  7. 3 3
      Dockerfile
  8. 1 4
      Dockerfile.arm
  9. 1 1
      Dockerfile.arm64
  10. 1 1
      Emby.Dlna/Configuration/DlnaOptions.cs
  11. 1 4
      Emby.Dlna/ContentDirectory/ContentDirectoryService.cs
  12. 2 8
      Emby.Dlna/ContentDirectory/ControlHandler.cs
  13. 3 1
      Emby.Dlna/Didl/DidlBuilder.cs
  14. 28 98
      Emby.Dlna/DlnaManager.cs
  15. 1 1
      Emby.Dlna/Emby.Dlna.csproj
  16. 2 2
      Emby.Dlna/IDlnaEventManager.cs
  17. 1 1
      Emby.Dlna/Main/DlnaEntryPoint.cs
  18. 20 28
      Emby.Dlna/PlayTo/Device.cs
  19. 108 0
      Emby.Dlna/PlayTo/DlnaHttpClient.cs
  20. 1 0
      Emby.Dlna/PlayTo/PlayToController.cs
  21. 0 141
      Emby.Dlna/PlayTo/SsdpHttpClient.cs
  22. 1 4
      Emby.Dlna/PlayTo/TransportCommands.cs
  23. 1 4
      Emby.Dlna/PlayTo/UpnpContainer.cs
  24. 1 4
      Emby.Dlna/PlayTo/uBaseObject.cs
  25. 0 14
      Emby.Dlna/Profiles/DefaultProfile.cs
  26. 0 34
      Emby.Dlna/Profiles/DenonAvrProfile.cs
  27. 0 129
      Emby.Dlna/Profiles/DirectTvProfile.cs
  28. 0 228
      Emby.Dlna/Profiles/DishHopperJoeyProfile.cs
  29. 0 78
      Emby.Dlna/Profiles/Foobar2000Profile.cs
  30. 0 211
      Emby.Dlna/Profiles/LgTvProfile.cs
  31. 0 55
      Emby.Dlna/Profiles/LinksysDMA2100Profile.cs
  32. 0 43
      Emby.Dlna/Profiles/MarantzProfile.cs
  33. 0 44
      Emby.Dlna/Profiles/MediaMonkeyProfile.cs
  34. 0 222
      Emby.Dlna/Profiles/PanasonicVieraProfile.cs
  35. 0 225
      Emby.Dlna/Profiles/PopcornHourProfile.cs
  36. 0 367
      Emby.Dlna/Profiles/SamsungSmartTvProfile.cs
  37. 0 121
      Emby.Dlna/Profiles/SharpSmartTvProfile.cs
  38. 0 59
      Emby.Dlna/Profiles/SonyBlurayPlayer2013.cs
  39. 0 59
      Emby.Dlna/Profiles/SonyBlurayPlayer2014.cs
  40. 0 47
      Emby.Dlna/Profiles/SonyBlurayPlayer2015.cs
  41. 0 47
      Emby.Dlna/Profiles/SonyBlurayPlayer2016.cs
  42. 0 42
      Emby.Dlna/Profiles/SonyBlurayPlayerProfile.cs
  43. 0 366
      Emby.Dlna/Profiles/SonyBravia2010Profile.cs
  44. 0 389
      Emby.Dlna/Profiles/SonyBravia2011Profile.cs
  45. 0 307
      Emby.Dlna/Profiles/SonyBravia2012Profile.cs
  46. 0 324
      Emby.Dlna/Profiles/SonyBravia2013Profile.cs
  47. 0 324
      Emby.Dlna/Profiles/SonyBravia2014Profile.cs
  48. 0 269
      Emby.Dlna/Profiles/SonyPs3Profile.cs
  49. 0 278
      Emby.Dlna/Profiles/SonyPs4Profile.cs
  50. 0 266
      Emby.Dlna/Profiles/WdtvLiveProfile.cs
  51. 0 372
      Emby.Dlna/Profiles/XboxOneProfile.cs
  52. 1 1
      Emby.Dlna/Service/BaseControlHandler.cs
  53. 1 1
      Emby.Drawing/Emby.Drawing.csproj
  54. 44 39
      Emby.Drawing/ImageProcessor.cs
  55. 1 1
      Emby.Naming/AudioBook/AudioBookFilePathParserResult.cs
  56. 1 2
      Emby.Naming/Common/NamingOptions.cs
  57. 2 2
      Emby.Naming/Emby.Naming.csproj
  58. 1 1
      Emby.Notifications/Emby.Notifications.csproj
  59. 2 2
      Emby.Photos/Emby.Photos.csproj
  60. 9 14
      Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs
  61. 55 9
      Emby.Server.Implementations/ApplicationHost.cs
  62. 1 4
      Emby.Server.Implementations/Channels/ChannelManager.cs
  63. 1 4
      Emby.Server.Implementations/Data/SqliteExtensions.cs
  64. 111 96
      Emby.Server.Implementations/Data/SqliteItemRepository.cs
  65. 3 12
      Emby.Server.Implementations/Data/SqliteUserDataRepository.cs
  66. 0 0
      Emby.Server.Implementations/Data/SynchronousMode.cs
  67. 7 3
      Emby.Server.Implementations/Dto/DtoService.cs
  68. 6 6
      Emby.Server.Implementations/Emby.Server.Implementations.csproj
  69. 0 60
      Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
  70. 32 2
      Emby.Server.Implementations/HttpServer/WebSocketConnection.cs
  71. 4 0
      Emby.Server.Implementations/IO/ManagedFileSystem.cs
  72. 1 0
      Emby.Server.Implementations/Images/DynamicImageProvider.cs
  73. 35 46
      Emby.Server.Implementations/Library/LibraryManager.cs
  74. 6 5
      Emby.Server.Implementations/Library/MediaSourceManager.cs
  75. 2 2
      Emby.Server.Implementations/Library/MediaStreamSelector.cs
  76. 5 3
      Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
  77. 1 4
      Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs
  78. 1 1
      Emby.Server.Implementations/Library/SearchEngine.cs
  79. 3 12
      Emby.Server.Implementations/Library/UserDataManager.cs
  80. 3 9
      Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
  81. 7 3
      Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
  82. 2 8
      Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
  83. 9 2
      Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
  84. 8 10
      Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
  85. 23 4
      Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
  86. 1 1
      Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
  87. 2 5
      Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
  88. 4 1
      Emby.Server.Implementations/Localization/Core/af.json
  89. 36 33
      Emby.Server.Implementations/Localization/Core/ar.json
  90. 5 2
      Emby.Server.Implementations/Localization/Core/bg-BG.json
  91. 2 2
      Emby.Server.Implementations/Localization/Core/ca.json
  92. 1 1
      Emby.Server.Implementations/Localization/Core/de.json
  93. 13 13
      Emby.Server.Implementations/Localization/Core/el.json
  94. 3 1
      Emby.Server.Implementations/Localization/Core/es-AR.json
  95. 2 1
      Emby.Server.Implementations/Localization/Core/es-MX.json
  96. 5 5
      Emby.Server.Implementations/Localization/Core/es.json
  97. 4 1
      Emby.Server.Implementations/Localization/Core/es_419.json
  98. 3 1
      Emby.Server.Implementations/Localization/Core/es_DO.json
  99. 2 1
      Emby.Server.Implementations/Localization/Core/et.json
  100. 1 1
      Emby.Server.Implementations/Localization/Core/fi.json

+ 2 - 0
.ci/azure-pipelines-package.yml

@@ -26,6 +26,8 @@ jobs:
         BuildConfiguration: linux.amd64-musl
         BuildConfiguration: linux.amd64-musl
       Linux.arm64:
       Linux.arm64:
         BuildConfiguration: linux.arm64
         BuildConfiguration: linux.arm64
+      Linux.musl-linux-arm64:
+        BuildConfiguration: linux.musl-linux-arm64
       Linux.armhf:
       Linux.armhf:
         BuildConfiguration: linux.armhf
         BuildConfiguration: linux.armhf
       Windows.amd64:
       Windows.amd64:

+ 4 - 4
.github/workflows/codeql-analysis.yml

@@ -22,16 +22,16 @@ jobs:
     - name: Checkout repository
     - name: Checkout repository
       uses: actions/checkout@v3
       uses: actions/checkout@v3
     - name: Setup .NET Core
     - name: Setup .NET Core
-      uses: actions/setup-dotnet@v2
+      uses: actions/setup-dotnet@v3
       with:
       with:
         dotnet-version: '6.0.x'
         dotnet-version: '6.0.x'
 
 
     - name: Initialize CodeQL
     - name: Initialize CodeQL
-      uses: github/codeql-action/init@v1
+      uses: github/codeql-action/init@v2
       with:
       with:
         languages: ${{ matrix.language }}
         languages: ${{ matrix.language }}
         queries: +security-extended
         queries: +security-extended
     - name: Autobuild
     - name: Autobuild
-      uses: github/codeql-action/autobuild@v1
+      uses: github/codeql-action/autobuild@v2
     - name: Perform CodeQL Analysis
     - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze@v1
+      uses: github/codeql-action/analyze@v2

+ 1 - 1
.github/workflows/commands.yml

@@ -29,7 +29,7 @@ jobs:
           fetch-depth: 0
           fetch-depth: 0
 
 
       - name: Automatic Rebase
       - name: Automatic Rebase
-        uses: cirrus-actions/rebase@1.5
+        uses: cirrus-actions/rebase@1.7
         env:
         env:
           GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }}
           GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }}
 
 

+ 6 - 6
.github/workflows/openapi.yml

@@ -17,13 +17,13 @@ jobs:
           ref: ${{ github.event.pull_request.head.sha }}
           ref: ${{ github.event.pull_request.head.sha }}
           repository: ${{ github.event.pull_request.head.repo.full_name }}
           repository: ${{ github.event.pull_request.head.repo.full_name }}
       - name: Setup .NET Core
       - name: Setup .NET Core
-        uses: actions/setup-dotnet@v2
+        uses: actions/setup-dotnet@v3
         with:
         with:
           dotnet-version: '6.0.x'
           dotnet-version: '6.0.x'
       - name: Generate openapi.json
       - name: Generate openapi.json
         run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
         run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
       - name: Upload openapi.json
       - name: Upload openapi.json
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: openapi-head
           name: openapi-head
           retention-days: 14
           retention-days: 14
@@ -41,13 +41,13 @@ jobs:
         with:
         with:
           ref: ${{ github.base_ref }}
           ref: ${{ github.base_ref }}
       - name: Setup .NET Core
       - name: Setup .NET Core
-        uses: actions/setup-dotnet@v2
+        uses: actions/setup-dotnet@v3
         with:
         with:
           dotnet-version: '6.0.x'
           dotnet-version: '6.0.x'
       - name: Generate openapi.json
       - name: Generate openapi.json
         run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
         run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
       - name: Upload openapi.json
       - name: Upload openapi.json
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: openapi-base
           name: openapi-base
           retention-days: 14
           retention-days: 14
@@ -63,12 +63,12 @@ jobs:
       - openapi-base
       - openapi-base
     steps:
     steps:
       - name: Download openapi-head
       - name: Download openapi-head
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
         with:
         with:
           name: openapi-head
           name: openapi-head
           path: openapi-head
           path: openapi-head
       - name: Download openapi-base
       - name: Download openapi-base
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
         with:
         with:
           name: openapi-base
           name: openapi-base
           path: openapi-base
           path: openapi-base

+ 1 - 1
.github/workflows/repo-stale.yaml

@@ -10,7 +10,7 @@ jobs:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     if: ${{ contains(github.repository, 'jellyfin/') }}
     if: ${{ contains(github.repository, 'jellyfin/') }}
     steps:
     steps:
-      - uses: actions/stale@v5
+      - uses: actions/stale@v6
         with:
         with:
           repo-token: ${{ secrets.JF_BOT_TOKEN }}
           repo-token: ${{ secrets.JF_BOT_TOKEN }}
           days-before-stale: 120
           days-before-stale: 120

+ 4 - 0
CONTRIBUTORS.md

@@ -36,6 +36,7 @@
  - [dmitrylyzo](https://github.com/dmitrylyzo)
  - [dmitrylyzo](https://github.com/dmitrylyzo)
  - [DMouse10462](https://github.com/DMouse10462)
  - [DMouse10462](https://github.com/DMouse10462)
  - [DrPandemic](https://github.com/DrPandemic)
  - [DrPandemic](https://github.com/DrPandemic)
+ - [eglia](https://github.com/eglia)
  - [EraYaN](https://github.com/EraYaN)
  - [EraYaN](https://github.com/EraYaN)
  - [escabe](https://github.com/escabe)
  - [escabe](https://github.com/escabe)
  - [excelite](https://github.com/excelite)
  - [excelite](https://github.com/excelite)
@@ -147,6 +148,7 @@
  - [xosdy](https://github.com/xosdy)
  - [xosdy](https://github.com/xosdy)
  - [XVicarious](https://github.com/XVicarious)
  - [XVicarious](https://github.com/XVicarious)
  - [YouKnowBlom](https://github.com/YouKnowBlom)
  - [YouKnowBlom](https://github.com/YouKnowBlom)
+ - [ZachPhelan](https://github.com/ZachPhelan)
  - [KristupasSavickas](https://github.com/KristupasSavickas)
  - [KristupasSavickas](https://github.com/KristupasSavickas)
  - [Pusta](https://github.com/pusta)
  - [Pusta](https://github.com/pusta)
  - [nielsvanvelzen](https://github.com/nielsvanvelzen)
  - [nielsvanvelzen](https://github.com/nielsvanvelzen)
@@ -157,6 +159,7 @@
  - [jonas-resch](https://github.com/jonas-resch)
  - [jonas-resch](https://github.com/jonas-resch)
  - [vgambier](https://github.com/vgambier)
  - [vgambier](https://github.com/vgambier)
  - [MinecraftPlaye](https://github.com/MinecraftPlaye)
  - [MinecraftPlaye](https://github.com/MinecraftPlaye)
+ - [RealGreenDragon](https://github.com/RealGreenDragon)
 
 
 # Emby Contributors
 # Emby Contributors
 
 
@@ -225,3 +228,4 @@
  - [gnuyent](https://github.com/gnuyent)
  - [gnuyent](https://github.com/gnuyent)
  - [Matthew Jones](https://github.com/matthew-jones-uk)
  - [Matthew Jones](https://github.com/matthew-jones-uk)
  - [Jakob Kukla](https://github.com/jakobkukla)
  - [Jakob Kukla](https://github.com/jakobkukla)
+ - [Utku Özdemir](https://github.com/utkuozdemir)

+ 3 - 3
Dockerfile

@@ -31,7 +31,7 @@ ARG LEVEL_ZERO_VERSION=1.3.22549
 # mesa-va-drivers: needed for AMD VAAPI. Mesa >= 20.1 is required for HEVC transcoding.
 # mesa-va-drivers: needed for AMD VAAPI. Mesa >= 20.1 is required for HEVC transcoding.
 # curl: healthcheck
 # curl: healthcheck
 RUN apt-get update \
 RUN apt-get update \
- && apt-get install --no-install-recommends --no-install-suggests -y ca-certificates gnupg wget apt-transport-https curl \
+ && apt-get install --no-install-recommends --no-install-suggests -y ca-certificates gnupg wget curl \
  && wget -O - https://repo.jellyfin.org/jellyfin_team.gpg.key | apt-key add - \
  && wget -O - https://repo.jellyfin.org/jellyfin_team.gpg.key | apt-key add - \
  && echo "deb [arch=$( dpkg --print-architecture )] https://repo.jellyfin.org/$( awk -F'=' '/^ID=/{ print $NF }' /etc/os-release ) $( awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release ) main" | tee /etc/apt/sources.list.d/jellyfin.list \
  && echo "deb [arch=$( dpkg --print-architecture )] https://repo.jellyfin.org/$( awk -F'=' '/^ID=/{ print $NF }' /etc/os-release ) $( awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release ) main" | tee /etc/apt/sources.list.d/jellyfin.list \
  && apt-get update \
  && apt-get update \
@@ -53,7 +53,7 @@ RUN apt-get update \
  && dpkg -i *.deb \
  && dpkg -i *.deb \
  && cd .. \
  && cd .. \
  && rm -rf intel-compute-runtime \
  && rm -rf intel-compute-runtime \
- && apt-get remove gnupg wget apt-transport-https -y \
+ && apt-get remove gnupg wget -y \
  && apt-get clean autoclean -y \
  && apt-get clean autoclean -y \
  && apt-get autoremove -y \
  && apt-get autoremove -y \
  && rm -rf /var/lib/apt/lists/* \
  && rm -rf /var/lib/apt/lists/* \
@@ -72,7 +72,7 @@ COPY . .
 ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
 ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
 # because of changes in docker and systemd we need to not build in parallel at the moment
 # 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
 # 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"
+RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="/jellyfin" --self-contained --runtime linux-x64 -p:DebugSymbols=false -p:DebugType=none
 
 
 FROM app
 FROM app
 
 

+ 1 - 4
Dockerfile.arm

@@ -38,9 +38,6 @@ RUN apt-get update \
  libssl-dev \
  libssl-dev \
  libfontconfig1 \
  libfontconfig1 \
  libfreetype6 \
  libfreetype6 \
- libomxil-bellagio0 \
- libomxil-bellagio-bin \
- libraspberrypi0 \
  vainfo \
  vainfo \
  libva2 \
  libva2 \
  locales \
  locales \
@@ -64,7 +61,7 @@ ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
 # Discard objs - may cause failures if exists
 # Discard objs - may cause failures if exists
 RUN find . -type d -name obj | xargs -r rm -r
 RUN find . -type d -name obj | xargs -r rm -r
 # Build
 # Build
-RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm "-p:DebugSymbols=false;DebugType=none"
+RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm -p:DebugSymbols=false -p:DebugType=none
 
 
 FROM app
 FROM app
 
 

+ 1 - 1
Dockerfile.arm64

@@ -55,7 +55,7 @@ ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
 # Discard objs - may cause failures if exists
 # Discard objs - may cause failures if exists
 RUN find . -type d -name obj | xargs -r rm -r
 RUN find . -type d -name obj | xargs -r rm -r
 # Build
 # Build
-RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm64 "-p:DebugSymbols=false;DebugType=none"
+RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm64 -p:DebugSymbols=false -p:DebugType=none
 
 
 FROM app
 FROM app
 
 

+ 1 - 1
Emby.Dlna/Configuration/DlnaOptions.cs

@@ -13,7 +13,7 @@ namespace Emby.Dlna.Configuration
         public DlnaOptions()
         public DlnaOptions()
         {
         {
             EnablePlayTo = true;
             EnablePlayTo = true;
-            EnableServer = true;
+            EnableServer = false;
             BlastAliveMessages = true;
             BlastAliveMessages = true;
             SendOnlyMatchedHost = true;
             SendOnlyMatchedHost = true;
             ClientDiscoveryIntervalSeconds = 60;
             ClientDiscoveryIntervalSeconds = 60;

+ 1 - 4
Emby.Dlna/ContentDirectory/ContentDirectoryService.cs

@@ -103,10 +103,7 @@ namespace Emby.Dlna.ContentDirectory
         /// <inheritdoc />
         /// <inheritdoc />
         public Task<ControlResponse> ProcessControlRequestAsync(ControlRequest request)
         public Task<ControlResponse> ProcessControlRequestAsync(ControlRequest request)
         {
         {
-            if (request == null)
-            {
-                throw new ArgumentNullException(nameof(request));
-            }
+            ArgumentNullException.ThrowIfNull(request);
 
 
             var profile = _dlna.GetProfile(request.Headers) ?? _dlna.GetDefaultProfile();
             var profile = _dlna.GetProfile(request.Headers) ?? _dlna.GetDefaultProfile();
 
 

+ 2 - 8
Emby.Dlna/ContentDirectory/ControlHandler.cs

@@ -114,15 +114,9 @@ namespace Emby.Dlna.ContentDirectory
         /// <inheritdoc />
         /// <inheritdoc />
         protected override void WriteResult(string methodName, IReadOnlyDictionary<string, string> methodParams, XmlWriter xmlWriter)
         protected override void WriteResult(string methodName, IReadOnlyDictionary<string, string> methodParams, XmlWriter xmlWriter)
         {
         {
-            if (xmlWriter == null)
-            {
-                throw new ArgumentNullException(nameof(xmlWriter));
-            }
+            ArgumentNullException.ThrowIfNull(xmlWriter);
 
 
-            if (methodParams == null)
-            {
-                throw new ArgumentNullException(nameof(methodParams));
-            }
+            ArgumentNullException.ThrowIfNull(methodParams);
 
 
             const string DeviceId = "test";
             const string DeviceId = "test";
 
 

+ 3 - 1
Emby.Dlna/Didl/DidlBuilder.cs

@@ -221,6 +221,7 @@ namespace Emby.Dlna.Didl
                 streamInfo.IsDirectStream,
                 streamInfo.IsDirectStream,
                 streamInfo.RunTimeTicks ?? 0,
                 streamInfo.RunTimeTicks ?? 0,
                 streamInfo.TargetVideoProfile,
                 streamInfo.TargetVideoProfile,
+                streamInfo.TargetVideoRangeType,
                 streamInfo.TargetVideoLevel,
                 streamInfo.TargetVideoLevel,
                 streamInfo.TargetFramerate ?? 0,
                 streamInfo.TargetFramerate ?? 0,
                 streamInfo.TargetPacketLength,
                 streamInfo.TargetPacketLength,
@@ -376,6 +377,7 @@ namespace Emby.Dlna.Didl
                 targetHeight,
                 targetHeight,
                 streamInfo.TargetVideoBitDepth,
                 streamInfo.TargetVideoBitDepth,
                 streamInfo.TargetVideoProfile,
                 streamInfo.TargetVideoProfile,
+                streamInfo.TargetVideoRangeType,
                 streamInfo.TargetVideoLevel,
                 streamInfo.TargetVideoLevel,
                 streamInfo.TargetFramerate ?? 0,
                 streamInfo.TargetFramerate ?? 0,
                 streamInfo.TargetPacketLength,
                 streamInfo.TargetPacketLength,
@@ -444,7 +446,7 @@ namespace Emby.Dlna.Didl
         /// </summary>
         /// </summary>
         /// <remarks>
         /// <remarks>
         /// If context is a season, this will return a string containing just episode number and name.
         /// If context is a season, this will return a string containing just episode number and name.
-        /// Otherwise the result will include series nams and season number.
+        /// Otherwise the result will include series names and season number.
         /// </remarks>
         /// </remarks>
         /// <param name="episode">The episode.</param>
         /// <param name="episode">The episode.</param>
         /// <param name="context">Current context.</param>
         /// <param name="context">Current context.</param>

+ 28 - 98
Emby.Dlna/DlnaManager.cs

@@ -1,4 +1,5 @@
 #pragma warning disable CS1591
 #pragma warning disable CS1591
+
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Globalization;
@@ -61,6 +62,7 @@ namespace Emby.Dlna
             try
             try
             {
             {
                 await ExtractSystemProfilesAsync().ConfigureAwait(false);
                 await ExtractSystemProfilesAsync().ConfigureAwait(false);
+                Directory.CreateDirectory(UserProfilesPath);
                 LoadProfiles();
                 LoadProfiles();
             }
             }
             catch (Exception ex)
             catch (Exception ex)
@@ -100,10 +102,7 @@ namespace Emby.Dlna
         /// <inheritdoc />
         /// <inheritdoc />
         public DeviceProfile? GetProfile(DeviceIdentification deviceInfo)
         public DeviceProfile? GetProfile(DeviceIdentification deviceInfo)
         {
         {
-            if (deviceInfo == null)
-            {
-                throw new ArgumentNullException(nameof(deviceInfo));
-            }
+            ArgumentNullException.ThrowIfNull(deviceInfo);
 
 
             var profile = GetProfiles()
             var profile = GetProfiles()
                 .FirstOrDefault(i => i.Identification != null && IsMatch(deviceInfo, i.Identification));
                 .FirstOrDefault(i => i.Identification != null && IsMatch(deviceInfo, i.Identification));
@@ -123,7 +122,7 @@ namespace Emby.Dlna
         /// <summary>
         /// <summary>
         /// Attempts to match a device with a profile.
         /// Attempts to match a device with a profile.
         /// Rules:
         /// Rules:
-        /// - If the profile field has no value, the field matches irregardless of its contents.
+        /// - If the profile field has no value, the field matches regardless of its contents.
         /// - the profile field can be an exact match, or a reg exp.
         /// - the profile field can be an exact match, or a reg exp.
         /// </summary>
         /// </summary>
         /// <param name="deviceInfo">The <see cref="DeviceIdentification"/> of the device.</param>
         /// <param name="deviceInfo">The <see cref="DeviceIdentification"/> of the device.</param>
@@ -170,10 +169,7 @@ namespace Emby.Dlna
         /// <inheritdoc />
         /// <inheritdoc />
         public DeviceProfile? GetProfile(IHeaderDictionary headers)
         public DeviceProfile? GetProfile(IHeaderDictionary headers)
         {
         {
-            if (headers == null)
-            {
-                throw new ArgumentNullException(nameof(headers));
-            }
+            ArgumentNullException.ThrowIfNull(headers);
 
 
             var profile = GetProfiles().FirstOrDefault(i => i.Identification != null && IsMatch(headers, i.Identification));
             var profile = GetProfiles().FirstOrDefault(i => i.Identification != null && IsMatch(headers, i.Identification));
             if (profile == null)
             if (profile == null)
@@ -328,32 +324,28 @@ namespace Emby.Dlna
 
 
                 var path = Path.Join(
                 var path = Path.Join(
                     systemProfilesPath,
                     systemProfilesPath,
-                    Path.GetFileName(name.AsSpan()).Slice(namespaceName.Length));
+                    Path.GetFileName(name.AsSpan())[namespaceName.Length..]);
+
+                if (File.Exists(path))
+                {
+                    continue;
+                }
 
 
                 // The stream should exist as we just got its name from GetManifestResourceNames
                 // The stream should exist as we just got its name from GetManifestResourceNames
                 using (var stream = _assembly.GetManifestResourceStream(name)!)
                 using (var stream = _assembly.GetManifestResourceStream(name)!)
                 {
                 {
-                    var length = stream.Length;
-                    var fileInfo = _fileSystem.GetFileInfo(path);
+                    Directory.CreateDirectory(systemProfilesPath);
 
 
-                    if (!fileInfo.Exists || fileInfo.Length != length)
+                    var fileOptions = AsyncFile.WriteOptions;
+                    fileOptions.Mode = FileMode.CreateNew;
+                    fileOptions.PreallocationSize = stream.Length;
+                    var fileStream = new FileStream(path, fileOptions);
+                    await using (fileStream.ConfigureAwait(false))
                     {
                     {
-                        Directory.CreateDirectory(systemProfilesPath);
-
-                        var fileOptions = AsyncFile.WriteOptions;
-                        fileOptions.Mode = FileMode.Create;
-                        fileOptions.PreallocationSize = length;
-                        var fileStream = new FileStream(path, fileOptions);
-                        await using (fileStream.ConfigureAwait(false))
-                        {
-                            await stream.CopyToAsync(fileStream).ConfigureAwait(false);
-                        }
+                        await stream.CopyToAsync(fileStream).ConfigureAwait(false);
                     }
                     }
                 }
                 }
             }
             }
-
-            // Not necessary, but just to make it easy to find
-            Directory.CreateDirectory(UserProfilesPath);
         }
         }
 
 
         /// <inheritdoc />
         /// <inheritdoc />
@@ -406,14 +398,20 @@ namespace Emby.Dlna
             }
             }
 
 
             var current = GetProfileInfosInternal().First(i => string.Equals(i.Info.Id, profileId, StringComparison.OrdinalIgnoreCase));
             var current = GetProfileInfosInternal().First(i => string.Equals(i.Info.Id, profileId, StringComparison.OrdinalIgnoreCase));
+            if (current.Info.Type == DeviceProfileType.System)
+            {
+                throw new ArgumentException("System profiles can't be edited");
+            }
 
 
             var newFilename = _fileSystem.GetValidFilename(profile.Name) + ".xml";
             var newFilename = _fileSystem.GetValidFilename(profile.Name) + ".xml";
-            var path = Path.Combine(UserProfilesPath, newFilename);
+            var path = Path.Join(UserProfilesPath, newFilename);
 
 
-            if (!string.Equals(path, current.Path, StringComparison.Ordinal) &&
-                current.Info.Type != DeviceProfileType.System)
+            if (!string.Equals(path, current.Path, StringComparison.Ordinal))
             {
             {
-                _fileSystem.DeleteFile(current.Path);
+                lock (_profiles)
+                {
+                    _profiles.Remove(current.Path);
+                }
             }
             }
 
 
             SaveProfile(profile, path, DeviceProfileType.User);
             SaveProfile(profile, path, DeviceProfileType.User);
@@ -496,72 +494,4 @@ namespace Emby.Dlna
             internal string Path { get; }
             internal string Path { get; }
         }
         }
     }
     }
-
-    /*
-    class DlnaProfileEntryPoint : IServerEntryPoint
-    {
-        private readonly IApplicationPaths _appPaths;
-        private readonly IFileSystem _fileSystem;
-        private readonly IXmlSerializer _xmlSerializer;
-
-        public DlnaProfileEntryPoint(IApplicationPaths appPaths, IFileSystem fileSystem, IXmlSerializer xmlSerializer)
-        {
-            _appPaths = appPaths;
-            _fileSystem = fileSystem;
-            _xmlSerializer = xmlSerializer;
-        }
-
-        public void Run()
-        {
-            DumpProfiles();
-        }
-
-        private void DumpProfiles()
-        {
-            DeviceProfile[] list = new[]
-            {
-                new SamsungSmartTvProfile(),
-                new XboxOneProfile(),
-                new SonyPs3Profile(),
-                new SonyPs4Profile(),
-                new SonyBravia2010Profile(),
-                new SonyBravia2011Profile(),
-                new SonyBravia2012Profile(),
-                new SonyBravia2013Profile(),
-                new SonyBravia2014Profile(),
-                new SonyBlurayPlayer2013(),
-                new SonyBlurayPlayer2014(),
-                new SonyBlurayPlayer2015(),
-                new SonyBlurayPlayer2016(),
-                new SonyBlurayPlayerProfile(),
-                new PanasonicVieraProfile(),
-                new WdtvLiveProfile(),
-                new DenonAvrProfile(),
-                new LinksysDMA2100Profile(),
-                new LgTvProfile(),
-                new Foobar2000Profile(),
-                new SharpSmartTvProfile(),
-                new MediaMonkeyProfile(),
-                // new Windows81Profile(),
-                // new WindowsMediaCenterProfile(),
-                // new WindowsPhoneProfile(),
-                new DirectTvProfile(),
-                new DishHopperJoeyProfile(),
-                new DefaultProfile(),
-                new PopcornHourProfile(),
-                new MarantzProfile()
-            };
-
-            foreach (var item in list)
-            {
-                var path = Path.Combine(_appPaths.ProgramDataPath, _fileSystem.GetValidFilename(item.Name) + ".xml");
-
-                _xmlSerializer.SerializeToFile(item, path);
-            }
-        }
-
-        public void Dispose()
-        {
-        }
-    }*/
 }
 }

+ 1 - 1
Emby.Dlna/Emby.Dlna.csproj

@@ -33,7 +33,7 @@
       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
     </PackageReference>
     </PackageReference>
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
-    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406" PrivateAssets="All" />
+    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
   </ItemGroup>
   </ItemGroup>
 
 

+ 2 - 2
Emby.Dlna/IDlnaEventManager.cs

@@ -16,7 +16,7 @@ namespace Emby.Dlna
         /// </summary>
         /// </summary>
         /// <param name="subscriptionId">The subscription identifier.</param>
         /// <param name="subscriptionId">The subscription identifier.</param>
         /// <param name="notificationType">The notification type.</param>
         /// <param name="notificationType">The notification type.</param>
-        /// <param name="requestedTimeoutString">The requested timeout as a sting.</param>
+        /// <param name="requestedTimeoutString">The requested timeout as a string.</param>
         /// <param name="callbackUrl">The callback url.</param>
         /// <param name="callbackUrl">The callback url.</param>
         /// <returns>The response.</returns>
         /// <returns>The response.</returns>
         EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string requestedTimeoutString, string callbackUrl);
         EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string requestedTimeoutString, string callbackUrl);
@@ -25,7 +25,7 @@ namespace Emby.Dlna
         /// Creates the event subscription.
         /// Creates the event subscription.
         /// </summary>
         /// </summary>
         /// <param name="notificationType">The notification type.</param>
         /// <param name="notificationType">The notification type.</param>
-        /// <param name="requestedTimeoutString">The requested timeout as a sting.</param>
+        /// <param name="requestedTimeoutString">The requested timeout as a string.</param>
         /// <param name="callbackUrl">The callback url.</param>
         /// <param name="callbackUrl">The callback url.</param>
         /// <returns>The response.</returns>
         /// <returns>The response.</returns>
         EventSubscriptionResponse CreateEventSubscription(string notificationType, string requestedTimeoutString, string callbackUrl);
         EventSubscriptionResponse CreateEventSubscription(string notificationType, string requestedTimeoutString, string callbackUrl);

+ 1 - 1
Emby.Dlna/Main/DlnaEntryPoint.cs

@@ -313,7 +313,7 @@ namespace Emby.Dlna.Main
 
 
                 _logger.LogInformation("Registering publisher for {ResourceName} on {DeviceAddress}", fullService, address);
                 _logger.LogInformation("Registering publisher for {ResourceName} on {DeviceAddress}", fullService, address);
 
 
-                var uri = new UriBuilder(_appHost.GetApiUrlForLocalAccess(false) + descriptorUri);
+                var uri = new UriBuilder(_appHost.GetApiUrlForLocalAccess(address, false) + descriptorUri);
 
 
                 var device = new SsdpRootDevice
                 var device = new SsdpRootDevice
                 {
                 {

+ 20 - 28
Emby.Dlna/PlayTo/Device.cs

@@ -235,7 +235,7 @@ namespace Emby.Dlna.PlayTo
             _logger.LogDebug("Setting mute");
             _logger.LogDebug("Setting mute");
             var value = mute ? 1 : 0;
             var value = mute ? 1 : 0;
 
 
-            await new SsdpHttpClient(_httpClientFactory)
+            await new DlnaHttpClient(_logger, _httpClientFactory)
                 .SendCommandAsync(
                 .SendCommandAsync(
                     Properties.BaseUrl,
                     Properties.BaseUrl,
                     service,
                     service,
@@ -276,7 +276,7 @@ namespace Emby.Dlna.PlayTo
             // Remote control will perform better
             // Remote control will perform better
             Volume = value;
             Volume = value;
 
 
-            await new SsdpHttpClient(_httpClientFactory)
+            await new DlnaHttpClient(_logger, _httpClientFactory)
                 .SendCommandAsync(
                 .SendCommandAsync(
                     Properties.BaseUrl,
                     Properties.BaseUrl,
                     service,
                     service,
@@ -303,7 +303,7 @@ namespace Emby.Dlna.PlayTo
                 throw new InvalidOperationException("Unable to find service");
                 throw new InvalidOperationException("Unable to find service");
             }
             }
 
 
-            await new SsdpHttpClient(_httpClientFactory)
+            await new DlnaHttpClient(_logger, _httpClientFactory)
                 .SendCommandAsync(
                 .SendCommandAsync(
                     Properties.BaseUrl,
                     Properties.BaseUrl,
                     service,
                     service,
@@ -343,7 +343,7 @@ namespace Emby.Dlna.PlayTo
             }
             }
 
 
             var post = avCommands.BuildPost(command, service.ServiceType, url, dictionary);
             var post = avCommands.BuildPost(command, service.ServiceType, url, dictionary);
-            await new SsdpHttpClient(_httpClientFactory)
+            await new DlnaHttpClient(_logger, _httpClientFactory)
                 .SendCommandAsync(
                 .SendCommandAsync(
                     Properties.BaseUrl,
                     Properties.BaseUrl,
                     service,
                     service,
@@ -400,7 +400,8 @@ namespace Emby.Dlna.PlayTo
             }
             }
 
 
             var post = avCommands.BuildPost(command, service.ServiceType, url, dictionary);
             var post = avCommands.BuildPost(command, service.ServiceType, url, dictionary);
-            await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header: header, cancellationToken)
+            await new DlnaHttpClient(_logger, _httpClientFactory)
+                .SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header, cancellationToken)
                 .ConfigureAwait(false);
                 .ConfigureAwait(false);
         }
         }
 
 
@@ -428,7 +429,7 @@ namespace Emby.Dlna.PlayTo
                 throw new InvalidOperationException("Unable to find service");
                 throw new InvalidOperationException("Unable to find service");
             }
             }
 
 
-            return new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
+            return new DlnaHttpClient(_logger, _httpClientFactory).SendCommandAsync(
                 Properties.BaseUrl,
                 Properties.BaseUrl,
                 service,
                 service,
                 command.Name,
                 command.Name,
@@ -461,7 +462,7 @@ namespace Emby.Dlna.PlayTo
 
 
             var service = GetAvTransportService();
             var service = GetAvTransportService();
 
 
-            await new SsdpHttpClient(_httpClientFactory)
+            await new DlnaHttpClient(_logger, _httpClientFactory)
                 .SendCommandAsync(
                 .SendCommandAsync(
                     Properties.BaseUrl,
                     Properties.BaseUrl,
                     service,
                     service,
@@ -485,7 +486,7 @@ namespace Emby.Dlna.PlayTo
 
 
             var service = GetAvTransportService();
             var service = GetAvTransportService();
 
 
-            await new SsdpHttpClient(_httpClientFactory)
+            await new DlnaHttpClient(_logger, _httpClientFactory)
                 .SendCommandAsync(
                 .SendCommandAsync(
                     Properties.BaseUrl,
                     Properties.BaseUrl,
                     service,
                     service,
@@ -618,7 +619,7 @@ namespace Emby.Dlna.PlayTo
                 return;
                 return;
             }
             }
 
 
-            var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
+            var result = await new DlnaHttpClient(_logger, _httpClientFactory).SendCommandAsync(
                 Properties.BaseUrl,
                 Properties.BaseUrl,
                 service,
                 service,
                 command.Name,
                 command.Name,
@@ -668,7 +669,7 @@ namespace Emby.Dlna.PlayTo
                 return;
                 return;
             }
             }
 
 
-            var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
+            var result = await new DlnaHttpClient(_logger, _httpClientFactory).SendCommandAsync(
                 Properties.BaseUrl,
                 Properties.BaseUrl,
                 service,
                 service,
                 command.Name,
                 command.Name,
@@ -701,7 +702,7 @@ namespace Emby.Dlna.PlayTo
                 return null;
                 return null;
             }
             }
 
 
-            var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
+            var result = await new DlnaHttpClient(_logger, _httpClientFactory).SendCommandAsync(
                 Properties.BaseUrl,
                 Properties.BaseUrl,
                 service,
                 service,
                 command.Name,
                 command.Name,
@@ -747,7 +748,7 @@ namespace Emby.Dlna.PlayTo
                 return null;
                 return null;
             }
             }
 
 
-            var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
+            var result = await new DlnaHttpClient(_logger, _httpClientFactory).SendCommandAsync(
                 Properties.BaseUrl,
                 Properties.BaseUrl,
                 service,
                 service,
                 command.Name,
                 command.Name,
@@ -819,7 +820,7 @@ namespace Emby.Dlna.PlayTo
                 return (false, null);
                 return (false, null);
             }
             }
 
 
-            var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
+            var result = await new DlnaHttpClient(_logger, _httpClientFactory).SendCommandAsync(
                 Properties.BaseUrl,
                 Properties.BaseUrl,
                 service,
                 service,
                 command.Name,
                 command.Name,
@@ -930,10 +931,7 @@ namespace Emby.Dlna.PlayTo
 
 
         private static UBaseObject CreateUBaseObject(XElement container, string trackUri)
         private static UBaseObject CreateUBaseObject(XElement container, string trackUri)
         {
         {
-            if (container == null)
-            {
-                throw new ArgumentNullException(nameof(container));
-            }
+            ArgumentNullException.ThrowIfNull(container);
 
 
             var url = container.GetValue(UPnpNamespaces.Res);
             var url = container.GetValue(UPnpNamespaces.Res);
 
 
@@ -957,10 +955,7 @@ namespace Emby.Dlna.PlayTo
 
 
         private static string[] GetProtocolInfo(XElement container)
         private static string[] GetProtocolInfo(XElement container)
         {
         {
-            if (container == null)
-            {
-                throw new ArgumentNullException(nameof(container));
-            }
+            ArgumentNullException.ThrowIfNull(container);
 
 
             var resElement = container.Element(UPnpNamespaces.Res);
             var resElement = container.Element(UPnpNamespaces.Res);
 
 
@@ -997,7 +992,7 @@ namespace Emby.Dlna.PlayTo
 
 
             string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
             string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
 
 
-            var httpClient = new SsdpHttpClient(_httpClientFactory);
+            var httpClient = new DlnaHttpClient(_logger, _httpClientFactory);
 
 
             var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
             var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
             if (document == null)
             if (document == null)
@@ -1029,7 +1024,7 @@ namespace Emby.Dlna.PlayTo
 
 
             string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
             string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
 
 
-            var httpClient = new SsdpHttpClient(_httpClientFactory);
+            var httpClient = new DlnaHttpClient(_logger, _httpClientFactory);
             _logger.LogDebug("Dlna Device.GetRenderingProtocolAsync");
             _logger.LogDebug("Dlna Device.GetRenderingProtocolAsync");
             var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
             var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
             if (document == null)
             if (document == null)
@@ -1064,7 +1059,7 @@ namespace Emby.Dlna.PlayTo
 
 
         public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClientFactory httpClientFactory, ILogger logger, CancellationToken cancellationToken)
         public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClientFactory httpClientFactory, ILogger logger, CancellationToken cancellationToken)
         {
         {
-            var ssdpHttpClient = new SsdpHttpClient(httpClientFactory);
+            var ssdpHttpClient = new DlnaHttpClient(logger, httpClientFactory);
 
 
             var document = await ssdpHttpClient.GetDataAsync(url.ToString(), cancellationToken).ConfigureAwait(false);
             var document = await ssdpHttpClient.GetDataAsync(url.ToString(), cancellationToken).ConfigureAwait(false);
             if (document == null)
             if (document == null)
@@ -1182,10 +1177,7 @@ namespace Emby.Dlna.PlayTo
 #nullable enable
 #nullable enable
         private static DeviceIcon CreateIcon(XElement element)
         private static DeviceIcon CreateIcon(XElement element)
         {
         {
-            if (element == null)
-            {
-                throw new ArgumentNullException(nameof(element));
-            }
+            ArgumentNullException.ThrowIfNull(element);
 
 
             var width = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("width"));
             var width = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("width"));
             var height = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("height"));
             var height = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("height"));

+ 108 - 0
Emby.Dlna/PlayTo/DlnaHttpClient.cs

@@ -0,0 +1,108 @@
+#pragma warning disable CS1591
+
+using System;
+using System.Globalization;
+using System.Net.Http;
+using System.Net.Mime;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Xml;
+using System.Xml.Linq;
+using Emby.Dlna.Common;
+using MediaBrowser.Common.Net;
+using Microsoft.Extensions.Logging;
+
+namespace Emby.Dlna.PlayTo
+{
+    public class DlnaHttpClient
+    {
+        private readonly ILogger _logger;
+        private readonly IHttpClientFactory _httpClientFactory;
+
+        public DlnaHttpClient(ILogger logger, IHttpClientFactory httpClientFactory)
+        {
+            _logger = logger;
+            _httpClientFactory = httpClientFactory;
+        }
+
+        private static string NormalizeServiceUrl(string baseUrl, string serviceUrl)
+        {
+            // If it's already a complete url, don't stick anything onto the front of it
+            if (serviceUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase))
+            {
+                return serviceUrl;
+            }
+
+            if (!serviceUrl.StartsWith('/'))
+            {
+                serviceUrl = "/" + serviceUrl;
+            }
+
+            return baseUrl + serviceUrl;
+        }
+
+        private async Task<XDocument?> SendRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+        {
+            using var response = await _httpClientFactory.CreateClient(NamedClient.Dlna).SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
+            response.EnsureSuccessStatusCode();
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
+            try
+            {
+                return await XDocument.LoadAsync(
+                    stream,
+                    LoadOptions.None,
+                    cancellationToken).ConfigureAwait(false);
+            }
+            catch (XmlException ex)
+            {
+                _logger.LogError(ex, "Failed to parse response");
+                if (_logger.IsEnabled(LogLevel.Debug))
+                {
+                    _logger.LogDebug("Malformed response: {Content}\n", await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false));
+                }
+
+                return null;
+            }
+        }
+
+        public async Task<XDocument?> GetDataAsync(string url, CancellationToken cancellationToken)
+        {
+            using var request = new HttpRequestMessage(HttpMethod.Get, url);
+
+            // Have to await here instead of returning the Task directly, otherwise request would be disposed too soon
+            return await SendRequestAsync(request, cancellationToken).ConfigureAwait(false);
+        }
+
+        public async Task<XDocument?> SendCommandAsync(
+            string baseUrl,
+            DeviceService service,
+            string command,
+            string postData,
+            string? header = null,
+            CancellationToken cancellationToken = default)
+        {
+            using var request = new HttpRequestMessage(HttpMethod.Post, NormalizeServiceUrl(baseUrl, service.ControlUrl))
+            {
+                Content = new StringContent(postData, Encoding.UTF8, MediaTypeNames.Text.Xml)
+            };
+
+            request.Headers.TryAddWithoutValidation(
+                "SOAPACTION",
+                string.Format(
+                    CultureInfo.InvariantCulture,
+                    "\"{0}#{1}\"",
+                    service.ServiceType,
+                    command));
+            request.Headers.Pragma.ParseAdd("no-cache");
+
+            if (!string.IsNullOrEmpty(header))
+            {
+                request.Headers.TryAddWithoutValidation("contentFeatures.dlna.org", header);
+            }
+
+            // Have to await here instead of returning the Task directly, otherwise request would be disposed too soon
+            return await SendRequestAsync(request, cancellationToken).ConfigureAwait(false);
+        }
+    }
+}

+ 1 - 0
Emby.Dlna/PlayTo/PlayToController.cs

@@ -561,6 +561,7 @@ namespace Emby.Dlna.PlayTo
                         streamInfo.IsDirectStream,
                         streamInfo.IsDirectStream,
                         streamInfo.RunTimeTicks ?? 0,
                         streamInfo.RunTimeTicks ?? 0,
                         streamInfo.TargetVideoProfile,
                         streamInfo.TargetVideoProfile,
+                        streamInfo.TargetVideoRangeType,
                         streamInfo.TargetVideoLevel,
                         streamInfo.TargetVideoLevel,
                         streamInfo.TargetFramerate ?? 0,
                         streamInfo.TargetFramerate ?? 0,
                         streamInfo.TargetPacketLength,
                         streamInfo.TargetPacketLength,

+ 0 - 141
Emby.Dlna/PlayTo/SsdpHttpClient.cs

@@ -1,141 +0,0 @@
-#nullable disable
-
-#pragma warning disable CS1591
-
-using System;
-using System.Globalization;
-using System.Net.Http;
-using System.Net.Mime;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Xml.Linq;
-using Emby.Dlna.Common;
-using MediaBrowser.Common.Net;
-
-namespace Emby.Dlna.PlayTo
-{
-    public class SsdpHttpClient
-    {
-        private const string USERAGENT = "Microsoft-Windows/6.2 UPnP/1.0 Microsoft-DLNA DLNADOC/1.50";
-        private const string FriendlyName = "Jellyfin";
-
-        private readonly IHttpClientFactory _httpClientFactory;
-
-        public SsdpHttpClient(IHttpClientFactory httpClientFactory)
-        {
-            _httpClientFactory = httpClientFactory;
-        }
-
-        public async Task<XDocument> SendCommandAsync(
-            string baseUrl,
-            DeviceService service,
-            string command,
-            string postData,
-            string header = null,
-            CancellationToken cancellationToken = default)
-        {
-            var url = NormalizeServiceUrl(baseUrl, service.ControlUrl);
-            using var response = await PostSoapDataAsync(
-                    url,
-                    $"\"{service.ServiceType}#{command}\"",
-                    postData,
-                    header,
-                    cancellationToken)
-                .ConfigureAwait(false);
-            response.EnsureSuccessStatusCode();
-
-            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
-            return await XDocument.LoadAsync(
-                stream,
-                LoadOptions.None,
-                cancellationToken).ConfigureAwait(false);
-        }
-
-        private static string NormalizeServiceUrl(string baseUrl, string serviceUrl)
-        {
-            // If it's already a complete url, don't stick anything onto the front of it
-            if (serviceUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase))
-            {
-                return serviceUrl;
-            }
-
-            if (!serviceUrl.StartsWith('/'))
-            {
-                serviceUrl = "/" + serviceUrl;
-            }
-
-            return baseUrl + serviceUrl;
-        }
-
-        public async Task SubscribeAsync(
-            string url,
-            string ip,
-            int port,
-            string localIp,
-            int eventport,
-            int timeOut = 3600)
-        {
-            using var options = new HttpRequestMessage(new HttpMethod("SUBSCRIBE"), url);
-            options.Headers.UserAgent.ParseAdd(USERAGENT);
-            options.Headers.TryAddWithoutValidation("HOST", ip + ":" + port.ToString(CultureInfo.InvariantCulture));
-            options.Headers.TryAddWithoutValidation("CALLBACK", "<" + localIp + ":" + eventport.ToString(CultureInfo.InvariantCulture) + ">");
-            options.Headers.TryAddWithoutValidation("NT", "upnp:event");
-            options.Headers.TryAddWithoutValidation("TIMEOUT", "Second-" + timeOut.ToString(CultureInfo.InvariantCulture));
-
-            using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
-                .SendAsync(options, HttpCompletionOption.ResponseHeadersRead)
-                .ConfigureAwait(false);
-            response.EnsureSuccessStatusCode();
-        }
-
-        public async Task<XDocument> GetDataAsync(string url, CancellationToken cancellationToken)
-        {
-            using var options = new HttpRequestMessage(HttpMethod.Get, url);
-            options.Headers.UserAgent.ParseAdd(USERAGENT);
-            options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName);
-            using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
-            response.EnsureSuccessStatusCode();
-            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
-            try
-            {
-                return await XDocument.LoadAsync(
-                    stream,
-                    LoadOptions.None,
-                    cancellationToken).ConfigureAwait(false);
-            }
-            catch
-            {
-                return null;
-            }
-        }
-
-        private async Task<HttpResponseMessage> PostSoapDataAsync(
-            string url,
-            string soapAction,
-            string postData,
-            string header,
-            CancellationToken cancellationToken)
-        {
-            if (soapAction[0] != '\"')
-            {
-                soapAction = $"\"{soapAction}\"";
-            }
-
-            using var options = new HttpRequestMessage(HttpMethod.Post, url);
-            options.Headers.UserAgent.ParseAdd(USERAGENT);
-            options.Headers.TryAddWithoutValidation("SOAPACTION", soapAction);
-            options.Headers.TryAddWithoutValidation("Pragma", "no-cache");
-            options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName);
-
-            if (!string.IsNullOrEmpty(header))
-            {
-                options.Headers.TryAddWithoutValidation("contentFeatures.dlna.org", header);
-            }
-
-            options.Content = new StringContent(postData, Encoding.UTF8, MediaTypeNames.Text.Xml);
-
-            return await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
-        }
-    }
-}

+ 1 - 4
Emby.Dlna/PlayTo/TransportCommands.cs

@@ -61,10 +61,7 @@ namespace Emby.Dlna.PlayTo
 
 
         private static Argument ArgumentFromXml(XElement container)
         private static Argument ArgumentFromXml(XElement container)
         {
         {
-            if (container == null)
-            {
-                throw new ArgumentNullException(nameof(container));
-            }
+            ArgumentNullException.ThrowIfNull(container);
 
 
             return new Argument
             return new Argument
             {
             {

+ 1 - 4
Emby.Dlna/PlayTo/UpnpContainer.cs

@@ -10,10 +10,7 @@ namespace Emby.Dlna.PlayTo
     {
     {
         public static UBaseObject Create(XElement container)
         public static UBaseObject Create(XElement container)
         {
         {
-            if (container == null)
-            {
-                throw new ArgumentNullException(nameof(container));
-            }
+            ArgumentNullException.ThrowIfNull(container);
 
 
             return new UBaseObject
             return new UBaseObject
             {
             {

+ 1 - 4
Emby.Dlna/PlayTo/uBaseObject.cs

@@ -54,10 +54,7 @@ namespace Emby.Dlna.PlayTo
 
 
         public bool Equals(UBaseObject obj)
         public bool Equals(UBaseObject obj)
         {
         {
-            if (obj == null)
-            {
-                throw new ArgumentNullException(nameof(obj));
-            }
+            ArgumentNullException.ThrowIfNull(obj);
 
 
             return string.Equals(Id, obj.Id, StringComparison.Ordinal);
             return string.Equals(Id, obj.Id, StringComparison.Ordinal);
         }
         }

+ 0 - 14
Emby.Dlna/Profiles/DefaultProfile.cs

@@ -2,7 +2,6 @@
 
 
 using System;
 using System;
 using System.Globalization;
 using System.Globalization;
-using System.Linq;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Dlna;
 
 
 namespace Emby.Dlna.Profiles
 namespace Emby.Dlna.Profiles
@@ -164,18 +163,5 @@ namespace Emby.Dlna.Profiles
                 }
                 }
             };
             };
         }
         }
-
-        public void AddXmlRootAttribute(string name, string value)
-        {
-            var list = XmlRootAttributes.ToList();
-
-            list.Add(new XmlAttribute
-            {
-                Name = name,
-                Value = value
-            });
-
-            XmlRootAttributes = list.ToArray();
-        }
     }
     }
 }
 }

+ 0 - 34
Emby.Dlna/Profiles/DenonAvrProfile.cs

@@ -1,34 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class DenonAvrProfile : DefaultProfile
-    {
-        public DenonAvrProfile()
-        {
-            Name = "Denon AVR";
-
-            SupportedMediaTypes = "Audio";
-
-            Identification = new DeviceIdentification
-            {
-                FriendlyName = @"Denon:\[AVR:.*",
-                Manufacturer = "Denon"
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "mp3,flac,m4a,wma",
-                    Type = DlnaProfileType.Audio
-                },
-            };
-
-            ResponseProfiles = System.Array.Empty<ResponseProfile>();
-        }
-    }
-}

+ 0 - 129
Emby.Dlna/Profiles/DirectTvProfile.cs

@@ -1,129 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class DirectTvProfile : DefaultProfile
-    {
-        public DirectTvProfile()
-        {
-            Name = "DirecTV HD-DVR";
-
-            TimelineOffsetSeconds = 10;
-            RequiresPlainFolders = true;
-            RequiresPlainVideoItems = true;
-
-            Identification = new DeviceIdentification
-            {
-                Headers = new[]
-                {
-                    new HttpHeaderInfo
-                    {
-                         Match = HeaderMatchType.Substring,
-                         Name = "User-Agent",
-                         Value = "DIRECTV"
-                    }
-                },
-
-                FriendlyName = "^DIRECTV.*$"
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "mpeg",
-                    VideoCodec = "mpeg2video",
-                    AudioCodec = "mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "jpeg,jpg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            TranscodingProfiles = new[]
-            {
-                new TranscodingProfile
-                {
-                    Container = "mpeg",
-                    VideoCodec = "mpeg2video",
-                    AudioCodec = "mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new TranscodingProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            CodecProfiles = new[]
-            {
-                new CodecProfile
-                {
-                    Codec = "mpeg2video",
-                    Type = CodecType.Video,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                             Condition = ProfileConditionType.LessThanEqual,
-                             Property = ProfileConditionValue.Width,
-                             Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                             Condition = ProfileConditionType.LessThanEqual,
-                             Property = ProfileConditionValue.Height,
-                             Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                             Condition = ProfileConditionType.LessThanEqual,
-                             Property = ProfileConditionValue.VideoFramerate,
-                             Value = "30"
-                        },
-                        new ProfileCondition
-                        {
-                             Condition = ProfileConditionType.LessThanEqual,
-                             Property = ProfileConditionValue.VideoBitrate,
-                             Value = "8192000"
-                        }
-                    }
-                },
-                new CodecProfile
-                {
-                    Codec = "mp2",
-                    Type = CodecType.Audio,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                             Condition = ProfileConditionType.LessThanEqual,
-                             Property = ProfileConditionValue.AudioChannels,
-                             Value = "2"
-                        }
-                    }
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                }
-            };
-
-            ResponseProfiles = System.Array.Empty<ResponseProfile>();
-        }
-    }
-}

+ 0 - 228
Emby.Dlna/Profiles/DishHopperJoeyProfile.cs

@@ -1,228 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class DishHopperJoeyProfile : DefaultProfile
-    {
-        public DishHopperJoeyProfile()
-        {
-            Name = "Dish Hopper-Joey";
-
-            ProtocolInfo = "http-get:*:video/mp2t:*,http-get:*:video/mpeg:*,http-get:*:video/MP1S:*,http-get:*:video/mpeg2:*,http-get:*:video/mp4:*,http-get:*:video/x-matroska:*,http-get:*:audio/mpeg:*,http-get:*:audio/mpeg3:*,http-get:*:audio/mp3:*,http-get:*:audio/mp4:*,http-get:*:audio/mp4a-latm:*,http-get:*:image/jpeg:*";
-
-            Identification = new DeviceIdentification
-            {
-                Manufacturer = "Echostar Technologies LLC",
-                ManufacturerUrl = "http://www.echostar.com",
-
-                Headers = new[]
-                {
-                    new HttpHeaderInfo
-                    {
-                         Match = HeaderMatchType.Substring,
-                         Name = "User-Agent",
-                         Value = "Zip_"
-                    }
-                }
-            };
-
-            TranscodingProfiles = new[]
-            {
-                new TranscodingProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-                new TranscodingProfile
-                {
-                    Container = "mp4",
-                    Type = DlnaProfileType.Video,
-                    AudioCodec = "aac",
-                    VideoCodec = "h264"
-                },
-
-                new TranscodingProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "mp4,mkv,mpeg,ts",
-                    VideoCodec = "h264,mpeg2video",
-                    AudioCodec = "mp3,ac3,aac,he-aac,pcm",
-                    Type = DlnaProfileType.Video
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "mp3,alac,flac",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            CodecProfiles = new[]
-            {
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Codec = "h264",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920",
-                            IsRequired = true
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080",
-                            IsRequired = true
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoFramerate,
-                            Value = "30",
-                            IsRequired = true
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoBitrate,
-                            Value = "20000000",
-                            IsRequired = true
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoLevel,
-                            Value = "41",
-                            IsRequired = true
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920",
-                            IsRequired = true
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080",
-                            IsRequired = true
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoFramerate,
-                            Value = "30",
-                            IsRequired = true
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoBitrate,
-                            Value = "20000000",
-                            IsRequired = true
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "ac3,he-aac",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "6",
-                            IsRequired = true
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "aac",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2",
-                            IsRequired = true
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Conditions = new[]
-                    {
-                        // The device does not have any audio switching capabilities
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.IsSecondaryAudio,
-                            Value = "false"
-                        }
-                    }
-                }
-            };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Container = "mkv,ts,mpegts",
-                    Type = DlnaProfileType.Video,
-                    MimeType = "video/mp4"
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                }
-            };
-        }
-    }
-}

+ 0 - 78
Emby.Dlna/Profiles/Foobar2000Profile.cs

@@ -1,78 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class Foobar2000Profile : DefaultProfile
-    {
-        public Foobar2000Profile()
-        {
-            Name = "foobar2000";
-
-            SupportedMediaTypes = "Audio";
-
-            Identification = new DeviceIdentification
-            {
-                FriendlyName = @"foobar",
-
-                Headers = new[]
-               {
-                   new HttpHeaderInfo
-                   {
-                       Name = "User-Agent",
-                       Value = "foobar",
-                       Match = HeaderMatchType.Substring
-                   }
-               }
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp2,mp3",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "mp4",
-                    AudioCodec = "mp4",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "aac,wav",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "flac",
-                    AudioCodec = "flac",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    AudioCodec = "wmav2,wmapro,wmavoice",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "ogg",
-                    AudioCodec = "vorbis",
-                    Type = DlnaProfileType.Audio
-                }
-            };
-
-            ResponseProfiles = System.Array.Empty<ResponseProfile>();
-        }
-    }
-}

+ 0 - 211
Emby.Dlna/Profiles/LgTvProfile.cs

@@ -1,211 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class LgTvProfile : DefaultProfile
-    {
-        public LgTvProfile()
-        {
-            Name = "LG Smart TV";
-
-            TimelineOffsetSeconds = 10;
-
-            Identification = new DeviceIdentification
-            {
-                FriendlyName = @"LG.*",
-
-                Headers = new[]
-               {
-                   new HttpHeaderInfo
-                   {
-                       Name = "User-Agent",
-                       Value = "LG",
-                       Match = HeaderMatchType.Substring
-                   }
-               }
-            };
-
-            TranscodingProfiles = new[]
-           {
-               new TranscodingProfile
-               {
-                   Container = "mp3",
-                   AudioCodec = "mp3",
-                   Type = DlnaProfileType.Audio
-               },
-               new TranscodingProfile
-               {
-                   Container = "ts",
-                   AudioCodec = "ac3,aac,mp3",
-                   VideoCodec = "h264",
-                   Type = DlnaProfileType.Video
-               },
-               new TranscodingProfile
-               {
-                   Container = "jpeg",
-                   Type = DlnaProfileType.Photo
-               }
-           };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts,avi,mkv,m2ts",
-                    VideoCodec = "h264",
-                    AudioCodec = "aac,ac3,eac3,mp3,dca,dts",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp4,m4v",
-                    VideoCodec = "h264,mpeg4",
-                    AudioCodec = "aac,ac3,eac3,mp3,dca,dts",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            ContainerProfiles = new[]
-            {
-                new ContainerProfile
-                {
-                    Type = DlnaProfileType.Photo,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        }
-                    }
-                }
-            };
-
-            CodecProfiles = new[]
-           {
-               new CodecProfile
-               {
-                   Type = CodecType.Video,
-                   Codec = "mpeg4",
-
-                   Conditions = new[]
-                   {
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.Width,
-                           Value = "1920"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.Height,
-                           Value = "1080"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.VideoFramerate,
-                           Value = "30"
-                       }
-                   }
-               },
-
-               new CodecProfile
-               {
-                   Type = CodecType.Video,
-                   Codec = "h264",
-
-                   Conditions = new[]
-                   {
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.Width,
-                           Value = "1920"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.Height,
-                           Value = "1080"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.VideoLevel,
-                           Value = "41"
-                       }
-                   }
-               },
-
-               new CodecProfile
-               {
-                   Type = CodecType.VideoAudio,
-                   Codec = "ac3,eac3,aac,mp3",
-
-                   Conditions = new[]
-                   {
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.AudioChannels,
-                           Value = "6"
-                       }
-                   }
-               }
-           };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                },
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.External
-                }
-            };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Container = "m4v",
-                    Type = DlnaProfileType.Video,
-                    MimeType = "video/mp4"
-                },
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    Type = DlnaProfileType.Video,
-                    MimeType = "video/mpeg"
-                }
-            };
-        }
-    }
-}

+ 0 - 55
Emby.Dlna/Profiles/LinksysDMA2100Profile.cs

@@ -1,55 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class LinksysDMA2100Profile : DefaultProfile
-    {
-        public LinksysDMA2100Profile()
-        {
-            // Linksys DMA2100us does not need any transcoding of the formats we support statically
-            Name = "Linksys DMA2100";
-
-            Identification = new DeviceIdentification
-            {
-                ModelName = "DMA2100us"
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "mp3,flac,m4a,wma",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "avi,mp4,mkv,ts,mpegts,m4v",
-                    Type = DlnaProfileType.Video
-                }
-            };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Container = "m4v",
-                    Type = DlnaProfileType.Video,
-                    MimeType = "video/mp4"
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                }
-            };
-        }
-    }
-}

+ 0 - 43
Emby.Dlna/Profiles/MarantzProfile.cs

@@ -1,43 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class MarantzProfile : DefaultProfile
-    {
-        public MarantzProfile()
-        {
-            Name = "Marantz";
-
-            SupportedMediaTypes = "Audio";
-
-            Identification = new DeviceIdentification
-            {
-                Manufacturer = @"Marantz",
-
-                Headers = new[]
-               {
-                   new HttpHeaderInfo
-                   {
-                       Name = "User-Agent",
-                       Value = "Marantz",
-                       Match = HeaderMatchType.Substring
-                   }
-               }
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "aac,mp3,wav,wma,flac",
-                    Type = DlnaProfileType.Audio
-                },
-            };
-
-            ResponseProfiles = System.Array.Empty<ResponseProfile>();
-        }
-    }
-}

+ 0 - 44
Emby.Dlna/Profiles/MediaMonkeyProfile.cs

@@ -1,44 +0,0 @@
-#pragma warning disable CS1591
-
-using System;
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class MediaMonkeyProfile : DefaultProfile
-    {
-        public MediaMonkeyProfile()
-        {
-            Name = "MediaMonkey";
-
-            SupportedMediaTypes = "Audio";
-
-            Identification = new DeviceIdentification
-            {
-                FriendlyName = @"MediaMonkey",
-
-                Headers = new[]
-               {
-                   new HttpHeaderInfo
-                   {
-                       Name = "User-Agent",
-                       Value = "MediaMonkey",
-                       Match = HeaderMatchType.Substring
-                   }
-               }
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "aac,mp3,mpa,wav,wma,mp2,ogg,oga,webma,ape,opus,flac,m4a",
-                    Type = DlnaProfileType.Audio
-                }
-            };
-
-            ResponseProfiles = Array.Empty<ResponseProfile>();
-        }
-    }
-}

+ 0 - 222
Emby.Dlna/Profiles/PanasonicVieraProfile.cs

@@ -1,222 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class PanasonicVieraProfile : DefaultProfile
-    {
-        public PanasonicVieraProfile()
-        {
-            Name = "Panasonic Viera";
-
-            Identification = new DeviceIdentification
-            {
-                FriendlyName = @"VIERA",
-                Manufacturer = "Panasonic",
-
-                Headers = new[]
-                {
-                    new HttpHeaderInfo
-                    {
-                        Name = "User-Agent",
-                        Value = "Panasonic MIL DLNA",
-                        Match = HeaderMatchType.Substring
-                    }
-                }
-            };
-
-            AddXmlRootAttribute("xmlns:pv", "http://www.pv.com/pvns/");
-
-            TimelineOffsetSeconds = 10;
-
-            TranscodingProfiles = new[]
-            {
-                new TranscodingProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-                new TranscodingProfile
-                {
-                    Container = "ts",
-                    AudioCodec = "ac3",
-                    VideoCodec = "h264",
-                    Type = DlnaProfileType.Video
-                },
-                new TranscodingProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "mpeg,mpg",
-                    VideoCodec = "mpeg2video,mpeg4",
-                    AudioCodec = "ac3,mp3,pcm_dvd",
-                    Type = DlnaProfileType.Video
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "mkv",
-                    VideoCodec = "h264,mpeg2video",
-                    AudioCodec = "aac,ac3,dca,mp3,mp2,pcm,dts",
-                    Type = DlnaProfileType.Video
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264,mpeg2video",
-                    AudioCodec = "aac,mp3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "mp4,m4v",
-                    VideoCodec = "h264",
-                    AudioCodec = "aac,ac3,mp3,pcm",
-                    Type = DlnaProfileType.Video
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "mov",
-                    VideoCodec = "h264",
-                    AudioCodec = "aac,pcm",
-                    Type = DlnaProfileType.Video
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "avi",
-                    VideoCodec = "mpeg4",
-                    AudioCodec = "pcm",
-                    Type = DlnaProfileType.Video
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "flv",
-                    VideoCodec = "h264",
-                    AudioCodec = "aac",
-                    Type = DlnaProfileType.Video
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "mp4",
-                    AudioCodec = "aac",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            ContainerProfiles = new[]
-            {
-                new ContainerProfile
-                {
-                    Type = DlnaProfileType.Photo,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        }
-                    }
-                }
-            };
-
-            CodecProfiles = new[]
-            {
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoBitDepth,
-                            Value = "8",
-                            IsRequired = false
-                        }
-                    }
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                },
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.External
-                }
-            };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Type = DlnaProfileType.Video,
-                    Container = "ts,mpegts",
-                    OrgPn = "MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
-                    MimeType = "video/vnd.dlna.mpeg-tts"
-                },
-                new ResponseProfile
-                {
-                    Container = "m4v",
-                    Type = DlnaProfileType.Video,
-                    MimeType = "video/mp4"
-                }
-            };
-        }
-    }
-}

+ 0 - 225
Emby.Dlna/Profiles/PopcornHourProfile.cs

@@ -1,225 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class PopcornHourProfile : DefaultProfile
-    {
-        public PopcornHourProfile()
-        {
-            Name = "Popcorn Hour";
-
-            TranscodingProfiles = new[]
-            {
-                new TranscodingProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new TranscodingProfile
-                {
-                    Container = "mp4",
-                    Type = DlnaProfileType.Video,
-                    AudioCodec = "aac",
-                    VideoCodec = "h264"
-                },
-
-                new TranscodingProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "mp4,mov,m4v",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "h264,mpeg4",
-                    AudioCodec = "aac"
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "h264",
-                    AudioCodec = "aac,ac3,eac3,mp3,mp2,pcm"
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "asf,wmv",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "wmv3,vc1",
-                    AudioCodec = "wmav2,wmapro"
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "avi",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "mpeg4,msmpeg4",
-                    AudioCodec = "mp3,ac3,eac3,mp2,pcm"
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "mkv",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "h264",
-                    AudioCodec = "aac,mp3,ac3,eac3,mp2,pcm"
-                },
-                new DirectPlayProfile
-                {
-                    Container = "aac,mp3,flac,ogg,wma,wav",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "jpeg,gif,bmp,png",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            CodecProfiles = new[]
-            {
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Codec = "h264",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition(ProfileConditionType.EqualsAny, ProfileConditionValue.VideoProfile, "baseline|constrained baseline"),
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.NotEquals,
-                            Property = ProfileConditionValue.IsAnamorphic,
-                            Value = "true",
-                            IsRequired = false
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.NotEquals,
-                            Property = ProfileConditionValue.IsAnamorphic,
-                            Value = "true",
-                            IsRequired = false
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "aac",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2",
-                            IsRequired = false
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.Audio,
-                    Codec = "aac",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2",
-                            IsRequired = false
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.Audio,
-                    Codec = "mp3",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2",
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioBitrate,
-                            Value = "320000",
-                            IsRequired = false
-                        }
-                    }
-                }
-            };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Container = "m4v",
-                    Type = DlnaProfileType.Video,
-                    MimeType = "video/mp4"
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                }
-            };
-        }
-    }
-}

+ 0 - 367
Emby.Dlna/Profiles/SamsungSmartTvProfile.cs

@@ -1,367 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class SamsungSmartTvProfile : DefaultProfile
-    {
-        public SamsungSmartTvProfile()
-        {
-            Name = "Samsung Smart TV";
-
-            EnableAlbumArtInDidl = true;
-
-            // Without this, older samsungs fail to browse
-            EnableSingleAlbumArtLimit = true;
-
-            Identification = new DeviceIdentification
-            {
-                ModelUrl = "samsung.com",
-
-                Headers = new[]
-                {
-                    new HttpHeaderInfo
-                    {
-                        Name = "User-Agent",
-                        Value = @"SEC_",
-                        Match = HeaderMatchType.Substring
-                    }
-                }
-            };
-
-            AddXmlRootAttribute("xmlns:sec", "http://www.sec.co.kr/");
-
-            TranscodingProfiles = new[]
-           {
-               new TranscodingProfile
-               {
-                   Container = "mp3",
-                   AudioCodec = "mp3",
-                   Type = DlnaProfileType.Audio
-               },
-               new TranscodingProfile
-               {
-                   Container = "ts",
-                   AudioCodec = "ac3",
-                   VideoCodec = "h264",
-                   Type = DlnaProfileType.Video,
-                   EstimateContentLength = false
-               },
-               new TranscodingProfile
-               {
-                   Container = "jpeg",
-                   Type = DlnaProfileType.Photo
-               }
-           };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    VideoCodec = "h264,mpeg4,mjpeg",
-                    AudioCodec = "mp3,ac3,wmav2,wmapro,wmavoice",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "avi",
-                    VideoCodec = "h264,mpeg4,mjpeg",
-                    AudioCodec = "mp3,ac3,dca,dts",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mkv",
-                    VideoCodec = "h264,mpeg4,mjpeg4",
-                    AudioCodec = "mp3,ac3,dca,aac,dts",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp4,m4v",
-                    VideoCodec = "h264,mpeg4",
-                    AudioCodec = "mp3,aac",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "3gp",
-                    VideoCodec = "h264,mpeg4",
-                    AudioCodec = "aac,he-aac",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mpg,mpeg",
-                    VideoCodec = "mpeg1video,mpeg2video,h264",
-                    AudioCodec = "ac3,mp2,mp3,aac",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "vro,vob",
-                    VideoCodec = "mpeg1video,mpeg2video",
-                    AudioCodec = "ac3,mp2,mp3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "ts",
-                    VideoCodec = "mpeg2video,h264,vc1",
-                    AudioCodec = "ac3,aac,mp3,eac3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    VideoCodec = "wmv2,wmv3",
-                    AudioCodec = "wmav2,wmavoice",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp3,flac",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            ContainerProfiles = new[]
-            {
-                new ContainerProfile
-                {
-                    Type = DlnaProfileType.Photo,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        }
-                    }
-                }
-            };
-
-            CodecProfiles = new[]
-           {
-               new CodecProfile
-               {
-                   Type = CodecType.Video,
-                   Codec = "mpeg2video",
-
-                   Conditions = new[]
-                   {
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.Width,
-                           Value = "1920"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.Height,
-                           Value = "1080"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.VideoFramerate,
-                           Value = "30"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.VideoBitrate,
-                           Value = "30720000"
-                       }
-                   }
-               },
-
-               new CodecProfile
-               {
-                   Type = CodecType.Video,
-                   Codec = "mpeg4",
-
-                   Conditions = new[]
-                   {
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.Width,
-                           Value = "1920"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.Height,
-                           Value = "1080"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.VideoFramerate,
-                           Value = "30"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.VideoBitrate,
-                           Value = "8192000"
-                       }
-                   }
-               },
-
-               new CodecProfile
-               {
-                   Type = CodecType.Video,
-                   Codec = "h264",
-
-                   Conditions = new[]
-                   {
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.Width,
-                           Value = "1920"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.Height,
-                           Value = "1080"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.VideoFramerate,
-                           Value = "30"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.VideoBitrate,
-                           Value = "37500000"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.VideoLevel,
-                           Value = "41"
-                       }
-                   }
-               },
-
-               new CodecProfile
-               {
-                   Type = CodecType.Video,
-                   Codec = "wmv2,wmv3,vc1",
-
-                   Conditions = new[]
-                   {
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.Width,
-                           Value = "1920"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.Height,
-                           Value = "1080"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.VideoFramerate,
-                           Value = "30"
-                       },
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.VideoBitrate,
-                           Value = "25600000"
-                       }
-                   }
-               },
-
-               new CodecProfile
-               {
-                   Type = CodecType.VideoAudio,
-                   Codec = "wmav2,dca,aac,mp3,dts",
-
-                   Conditions = new[]
-                   {
-                       new ProfileCondition
-                       {
-                           Condition = ProfileConditionType.LessThanEqual,
-                           Property = ProfileConditionValue.AudioChannels,
-                           Value = "6"
-                       }
-                   }
-               }
-           };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Container = "avi",
-                    MimeType = "video/x-msvideo",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "mkv",
-                    MimeType = "video/x-mkv",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "flac",
-                    MimeType = "audio/x-flac",
-                    Type = DlnaProfileType.Audio
-                },
-                new ResponseProfile
-                {
-                    Container = "m4v",
-                    Type = DlnaProfileType.Video,
-                    MimeType = "video/mp4"
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                },
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.External,
-                    DidlMode = "CaptionInfoEx"
-                }
-            };
-        }
-    }
-}

+ 0 - 121
Emby.Dlna/Profiles/SharpSmartTvProfile.cs

@@ -1,121 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class SharpSmartTvProfile : DefaultProfile
-    {
-        public SharpSmartTvProfile()
-        {
-            Name = "Sharp Smart TV";
-
-            RequiresPlainFolders = true;
-            RequiresPlainVideoItems = true;
-
-            Identification = new DeviceIdentification
-            {
-                Manufacturer = "Sharp",
-
-                Headers = new[]
-               {
-                   new HttpHeaderInfo
-                   {
-                       Name = "User-Agent",
-                       Value = "Sharp",
-                       Match = HeaderMatchType.Substring
-                   }
-               }
-            };
-
-            TranscodingProfiles = new[]
-            {
-                new TranscodingProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new TranscodingProfile
-                {
-                    Container = "ts",
-                    Type = DlnaProfileType.Video,
-                    AudioCodec = "ac3,aac,mp3,dts,dca",
-                    VideoCodec = "h264",
-                    EnableMpegtsM2TsMode = true
-                },
-
-                new TranscodingProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "m4v,mkv,avi,mov,mp4",
-                    VideoCodec = "h264,mpeg4",
-                    AudioCodec = "aac,mp3,ac3,dts,dca",
-                    Type = DlnaProfileType.Video
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "asf,wmv",
-                    Type = DlnaProfileType.Video
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "mpg,mpeg",
-                    VideoCodec = "mpeg2video",
-                    AudioCodec = "mp3,aac",
-                    Type = DlnaProfileType.Video
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "flv",
-                    VideoCodec = "h264",
-                    AudioCodec = "mp3,aac",
-                    Type = DlnaProfileType.Video
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "mp3,wav",
-                    Type = DlnaProfileType.Audio
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                },
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.External
-                }
-            };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Container = "m4v",
-                    Type = DlnaProfileType.Video,
-                    MimeType = "video/mp4"
-                }
-            };
-        }
-    }
-}

Файловите разлики са ограничени, защото са твърде много
+ 0 - 59
Emby.Dlna/Profiles/SonyBlurayPlayer2013.cs


Файловите разлики са ограничени, защото са твърде много
+ 0 - 59
Emby.Dlna/Profiles/SonyBlurayPlayer2014.cs


Файловите разлики са ограничени, защото са твърде много
+ 0 - 47
Emby.Dlna/Profiles/SonyBlurayPlayer2015.cs


Файловите разлики са ограничени, защото са твърде много
+ 0 - 47
Emby.Dlna/Profiles/SonyBlurayPlayer2016.cs


Файловите разлики са ограничени, защото са твърде много
+ 0 - 42
Emby.Dlna/Profiles/SonyBlurayPlayerProfile.cs


+ 0 - 366
Emby.Dlna/Profiles/SonyBravia2010Profile.cs

@@ -1,366 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class SonyBravia2010Profile : DefaultProfile
-    {
-        public SonyBravia2010Profile()
-        {
-            Name = "Sony Bravia (2010)";
-
-            Identification = new DeviceIdentification
-            {
-                FriendlyName = @"KDL-[0-9]{2}[EHLNPB]X[0-9][01][0-9].*",
-                Manufacturer = "Sony",
-
-                Headers = new[]
-                {
-                    new HttpHeaderInfo
-                    {
-                        Name = "X-AV-Client-Info",
-                        Value = @".*KDL-[0-9]{2}[EHLNPB]X[0-9][01][0-9].*",
-                        Match = HeaderMatchType.Regex
-                    }
-                }
-            };
-
-            AddXmlRootAttribute("xmlns:av", "urn:schemas-sony-com:av");
-
-            AlbumArtPn = "JPEG_TN";
-
-            ModelName = "Windows Media Player Sharing";
-            ModelNumber = "3.0";
-            ModelUrl = "http://www.microsoft.com/";
-            Manufacturer = "Microsoft Corporation";
-            ManufacturerUrl = "http://www.microsoft.com/";
-            SonyAggregationFlags = "10";
-            ProtocolInfo =
-                "http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000";
-
-            EnableSingleAlbumArtLimit = true;
-            EnableAlbumArtInDidl = true;
-
-            TranscodingProfiles = new[]
-            {
-                new TranscodingProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-                new TranscodingProfile
-                {
-                    Container = "ts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3",
-                    Type = DlnaProfileType.Video,
-                    EnableMpegtsM2TsMode = true
-                },
-                new TranscodingProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "mpeg1video,mpeg2video",
-                    AudioCodec = "mp3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mpeg",
-                    VideoCodec = "mpeg2video,mpeg1video",
-                    AudioCodec = "mp3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                }
-            };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    MimeType = "video/vnd.dlna.mpeg-tts",
-                    OrgPn = "AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.PacketLength,
-                            Value = "192"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.VideoTimestamp,
-                            Value = "Valid"
-                        }
-                    }
-                },
-
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    MimeType = "video/mpeg",
-                    OrgPn = "AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.PacketLength,
-                            Value = "188"
-                        }
-                    }
-                },
-
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    MimeType = "video/vnd.dlna.mpeg-tts",
-                    OrgPn = "AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "mpeg2video",
-                    MimeType = "video/vnd.dlna.mpeg-tts",
-                    OrgPn = "MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "mpeg",
-                    VideoCodec = "mpeg1video,mpeg2video",
-                    MimeType = "video/mpeg",
-                    OrgPn = "MPEG_PS_NTSC,MPEG_PS_PAL",
-                    Type = DlnaProfileType.Video
-                }
-            };
-
-            ContainerProfiles = new[]
-            {
-                new ContainerProfile
-                {
-                    Type = DlnaProfileType.Photo,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        }
-                    }
-                }
-            };
-
-            CodecProfiles = new[]
-            {
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Codec = "h264",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoFramerate,
-                            Value = "30"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoBitrate,
-                            Value = "20000000"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoLevel,
-                            Value = "41"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Codec = "mpeg2video",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoFramerate,
-                            Value = "30"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoBitrate,
-                            Value = "20000000"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoFramerate,
-                            Value = "30"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "ac3",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "6"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "aac",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.NotEquals,
-                            Property = ProfileConditionValue.AudioProfile,
-                            Value = "he-aac"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "mp3,mp2",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2"
-                        }
-                    }
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                }
-            };
-        }
-    }
-}

+ 0 - 389
Emby.Dlna/Profiles/SonyBravia2011Profile.cs

@@ -1,389 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class SonyBravia2011Profile : DefaultProfile
-    {
-        public SonyBravia2011Profile()
-        {
-            Name = "Sony Bravia (2011)";
-
-            Identification = new DeviceIdentification
-            {
-                FriendlyName = @"KDL-[0-9]{2}([A-Z]X[0-9]2[0-9]|CX400).*",
-                Manufacturer = "Sony",
-
-                Headers = new[]
-                {
-                    new HttpHeaderInfo
-                    {
-                        Name = "X-AV-Client-Info",
-                        Value = @".*KDL-[0-9]{2}([A-Z]X[0-9]2[0-9]|CX400).*",
-                        Match = HeaderMatchType.Regex
-                    }
-                }
-            };
-
-            AddXmlRootAttribute("xmlns:av", "urn:schemas-sony-com:av");
-
-            AlbumArtPn = "JPEG_TN";
-
-            ModelName = "Windows Media Player Sharing";
-            ModelNumber = "3.0";
-            ModelUrl = "http://www.microsoft.com/";
-            Manufacturer = "Microsoft Corporation";
-            ManufacturerUrl = "http://www.microsoft.com/";
-            SonyAggregationFlags = "10";
-            EnableSingleAlbumArtLimit = true;
-            EnableAlbumArtInDidl = true;
-
-            TranscodingProfiles = new[]
-            {
-                new TranscodingProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-                new TranscodingProfile
-                {
-                    Container = "ts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3",
-                    Type = DlnaProfileType.Video,
-                    EnableMpegtsM2TsMode = true
-                },
-                new TranscodingProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "mpeg2video",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp4,m4v",
-                    VideoCodec = "h264,mpeg4",
-                    AudioCodec = "ac3,aac,mp3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mpeg",
-                    VideoCodec = "mpeg2video,mpeg1video",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    VideoCodec = "wmv2,wmv3,vc1",
-                    AudioCodec = "wmav2,wmapro,wmavoice",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    AudioCodec = "wmav2,wmapro,wmavoice",
-                    Type = DlnaProfileType.Audio
-                }
-            };
-
-            ContainerProfiles = new[]
-            {
-                new ContainerProfile
-                {
-                    Type = DlnaProfileType.Photo,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        }
-                    }
-                }
-            };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    MimeType = "video/vnd.dlna.mpeg-tts",
-                    OrgPn = "AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.PacketLength,
-                            Value = "192"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.VideoTimestamp,
-                            Value = "Valid"
-                        }
-                    }
-                },
-
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    MimeType = "video/mpeg",
-                    OrgPn = "AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.PacketLength,
-                            Value = "188"
-                        }
-                    }
-                },
-
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    MimeType = "video/vnd.dlna.mpeg-tts",
-                    OrgPn = "AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "mpeg2video",
-                    MimeType = "video/vnd.dlna.mpeg-tts",
-                    OrgPn = "MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "mpeg",
-                    VideoCodec = "mpeg1video,mpeg2video",
-                    MimeType = "video/mpeg",
-                    OrgPn = "MPEG_PS_NTSC,MPEG_PS_PAL",
-                    Type = DlnaProfileType.Video
-                },
-                new ResponseProfile
-                {
-                    Container = "m4v",
-                    Type = DlnaProfileType.Video,
-                    MimeType = "video/mp4"
-                }
-            };
-
-            CodecProfiles = new[]
-            {
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Codec = "h264",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoFramerate,
-                            Value = "30"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoBitrate,
-                            Value = "20000000"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoLevel,
-                            Value = "41"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Codec = "mpeg2video",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoFramerate,
-                            Value = "30"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoBitrate,
-                            Value = "20000000"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoFramerate,
-                            Value = "30"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "ac3",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "6"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "aac",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.NotEquals,
-                            Property = ProfileConditionValue.AudioProfile,
-                            Value = "he-aac"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "mp3,mp2",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2"
-                        }
-                    }
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                }
-            };
-        }
-    }
-}

+ 0 - 307
Emby.Dlna/Profiles/SonyBravia2012Profile.cs

@@ -1,307 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class SonyBravia2012Profile : DefaultProfile
-    {
-        public SonyBravia2012Profile()
-        {
-            Name = "Sony Bravia (2012)";
-
-            Identification = new DeviceIdentification
-            {
-                FriendlyName = @"KDL-[0-9]{2}[A-Z]X[0-9]5([0-9]|G).*",
-                Manufacturer = "Sony",
-
-                Headers = new[]
-                {
-                    new HttpHeaderInfo
-                    {
-                        Name = "X-AV-Client-Info",
-                        Value = @".*KDL-[0-9]{2}[A-Z]X[0-9]5([0-9]|G).*",
-                        Match = HeaderMatchType.Regex
-                    }
-                }
-            };
-
-            AddXmlRootAttribute("xmlns:av", "urn:schemas-sony-com:av");
-
-            AlbumArtPn = "JPEG_TN";
-
-            ModelName = "Windows Media Player Sharing";
-            ModelNumber = "3.0";
-            ModelUrl = "http://www.microsoft.com/";
-            Manufacturer = "Microsoft Corporation";
-            ManufacturerUrl = "http://www.microsoft.com/";
-            SonyAggregationFlags = "10";
-            EnableSingleAlbumArtLimit = true;
-            EnableAlbumArtInDidl = true;
-
-            TranscodingProfiles = new[]
-            {
-                new TranscodingProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-                new TranscodingProfile
-                {
-                    Container = "ts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3",
-                    Type = DlnaProfileType.Video,
-                    EnableMpegtsM2TsMode = true
-                },
-                new TranscodingProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "mpeg2video",
-                    AudioCodec = "mp3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp4,m4v",
-                    VideoCodec = "h264,mpeg4",
-                    AudioCodec = "ac3,aac,mp3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "avi",
-                    VideoCodec = "mpeg4",
-                    AudioCodec = "ac3,mp3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mpeg",
-                    VideoCodec = "mpeg2video,mpeg1video",
-                    AudioCodec = "mp3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    VideoCodec = "wmv2,wmv3,vc1",
-                    AudioCodec = "wmav2,wmapro,wmavoice",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    AudioCodec = "wmav2,wmapro,wmavoice",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    MimeType = "video/vnd.dlna.mpeg-tts",
-                    OrgPn = "AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.PacketLength,
-                            Value = "192"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.VideoTimestamp,
-                            Value = "Valid"
-                        }
-                    }
-                },
-
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    MimeType = "video/mpeg",
-                    OrgPn = "AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.PacketLength,
-                            Value = "188"
-                        }
-                    }
-                },
-
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    MimeType = "video/vnd.dlna.mpeg-tts",
-                    OrgPn = "AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "mpeg2video",
-                    MimeType = "video/vnd.dlna.mpeg-tts",
-                    OrgPn = "MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "mpeg",
-                    VideoCodec = "mpeg1video,mpeg2video",
-                    MimeType = "video/mpeg",
-                    OrgPn = "MPEG_PS_NTSC,MPEG_PS_PAL",
-                    Type = DlnaProfileType.Video
-                },
-                new ResponseProfile
-                {
-                    Container = "m4v",
-                    Type = DlnaProfileType.Video,
-                    MimeType = "video/mp4"
-                }
-            };
-
-            ContainerProfiles = new[]
-            {
-                new ContainerProfile
-                {
-                    Type = DlnaProfileType.Photo,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        }
-                    }
-                }
-            };
-
-            CodecProfiles = new[]
-            {
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoFramerate,
-                            Value = "30"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "ac3",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "6"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "mp3,mp2",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2"
-                        }
-                    }
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                }
-            };
-        }
-    }
-}

+ 0 - 324
Emby.Dlna/Profiles/SonyBravia2013Profile.cs

@@ -1,324 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class SonyBravia2013Profile : DefaultProfile
-    {
-        public SonyBravia2013Profile()
-        {
-            Name = "Sony Bravia (2013)";
-
-            Identification = new DeviceIdentification
-            {
-                FriendlyName = @"KDL-[0-9]{2}[WR][5689][0-9]{2}A.*",
-                Manufacturer = "Sony",
-
-                Headers = new[]
-                {
-                    new HttpHeaderInfo
-                    {
-                        Name = "X-AV-Client-Info",
-                        Value = @".*KDL-[0-9]{2}[WR][5689][0-9]{2}A.*",
-                        Match = HeaderMatchType.Regex
-                    }
-                }
-            };
-
-            AddXmlRootAttribute("xmlns:av", "urn:schemas-sony-com:av");
-
-            AlbumArtPn = "JPEG_TN";
-
-            ModelName = "Windows Media Player Sharing";
-            ModelNumber = "3.0";
-            ModelUrl = "http://www.microsoft.com/";
-            Manufacturer = "Microsoft Corporation";
-            ManufacturerUrl = "http://www.microsoft.com/";
-            SonyAggregationFlags = "10";
-            EnableSingleAlbumArtLimit = true;
-            EnableAlbumArtInDidl = true;
-
-            TranscodingProfiles = new[]
-            {
-                new TranscodingProfile
-                {
-                    Container = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-                new TranscodingProfile
-                {
-                    Container = "ts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3",
-                    Type = DlnaProfileType.Video,
-                    EnableMpegtsM2TsMode = true
-                },
-                new TranscodingProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,eac3,aac,mp3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "mpeg2video",
-                    AudioCodec = "mp3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp4,m4v",
-                    VideoCodec = "h264,mpeg4",
-                    AudioCodec = "ac3,eac3,aac,mp3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mov",
-                    VideoCodec = "h264,mpeg4,mjpeg",
-                    AudioCodec = "ac3,eac3,aac,mp3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mkv",
-                    VideoCodec = "h264,mpeg4,vp8",
-                    AudioCodec = "ac3,eac3,aac,mp3,mp2,pcm,vorbis",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "avi",
-                    VideoCodec = "mpeg4",
-                    AudioCodec = "ac3,eac3,mp3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "avi",
-                    VideoCodec = "mjpeg",
-                    AudioCodec = "pcm",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mpeg",
-                    VideoCodec = "mpeg2video,mpeg1video",
-                    AudioCodec = "mp3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    VideoCodec = "wmv2,wmv3,vc1",
-                    AudioCodec = "wmav2,wmapro,wmavoice",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp4",
-                    AudioCodec = "aac",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "wav",
-                    AudioCodec = "pcm",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    AudioCodec = "wmav2,wmapro,wmavoice",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            ContainerProfiles = new[]
-            {
-                new ContainerProfile
-                {
-                    Type = DlnaProfileType.Photo,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        }
-                    }
-                }
-            };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    MimeType = "video/vnd.dlna.mpeg-tts",
-                    OrgPn = "AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.PacketLength,
-                            Value = "192"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.VideoTimestamp,
-                            Value = "Valid"
-                        }
-                    }
-                },
-
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    MimeType = "video/mpeg",
-                    OrgPn = "AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.PacketLength,
-                            Value = "188"
-                        }
-                    }
-                },
-
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    MimeType = "video/vnd.dlna.mpeg-tts",
-                    OrgPn = "AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "mpeg2video",
-                    MimeType = "video/vnd.dlna.mpeg-tts",
-                    OrgPn = "MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "mpeg",
-                    VideoCodec = "mpeg1video,mpeg2video",
-                    MimeType = "video/mpeg",
-                    OrgPn = "MPEG_PS_NTSC,MPEG_PS_PAL",
-                    Type = DlnaProfileType.Video
-                },
-                new ResponseProfile
-                {
-                    Container = "m4v",
-                    Type = DlnaProfileType.Video,
-                    MimeType = "video/mp4"
-                }
-            };
-
-            CodecProfiles = new[]
-            {
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoFramerate,
-                            Value = "30"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "mp3,mp2",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2"
-                        }
-                    }
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                }
-            };
-        }
-    }
-}

+ 0 - 324
Emby.Dlna/Profiles/SonyBravia2014Profile.cs

@@ -1,324 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class SonyBravia2014Profile : DefaultProfile
-    {
-        public SonyBravia2014Profile()
-        {
-            Name = "Sony Bravia (2014)";
-
-            Identification = new DeviceIdentification
-            {
-                FriendlyName = @"(KDL-[0-9]{2}W[5-9][0-9]{2}B|KDL-[0-9]{2}R480|XBR-[0-9]{2}X[89][0-9]{2}B|KD-[0-9]{2}[SX][89][0-9]{3}B).*",
-                Manufacturer = "Sony",
-
-                Headers = new[]
-                {
-                    new HttpHeaderInfo
-                    {
-                        Name = "X-AV-Client-Info",
-                        Value = @".*(KDL-[0-9]{2}W[5-9][0-9]{2}B|KDL-[0-9]{2}R480|XBR-[0-9]{2}X[89][0-9]{2}B|KD-[0-9]{2}[SX][89][0-9]{3}B).*",
-                        Match = HeaderMatchType.Regex
-                    }
-                }
-            };
-
-            AddXmlRootAttribute("xmlns:av", "urn:schemas-sony-com:av");
-
-            AlbumArtPn = "JPEG_TN";
-
-            ModelName = "Windows Media Player Sharing";
-            ModelNumber = "3.0";
-            ModelUrl = "http://www.microsoft.com/";
-            Manufacturer = "Microsoft Corporation";
-            ManufacturerUrl = "http://www.microsoft.com/";
-            SonyAggregationFlags = "10";
-            EnableSingleAlbumArtLimit = true;
-            EnableAlbumArtInDidl = true;
-
-            TranscodingProfiles = new[]
-            {
-                new TranscodingProfile
-                {
-                    Container = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-                new TranscodingProfile
-                {
-                    Container = "ts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3",
-                    Type = DlnaProfileType.Video,
-                    EnableMpegtsM2TsMode = true
-                },
-                new TranscodingProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,eac3,aac,mp3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "mpeg2video",
-                    AudioCodec = "mp3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp4,m4v",
-                    VideoCodec = "h264,mpeg4",
-                    AudioCodec = "ac3,eac3,aac,mp3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mov",
-                    VideoCodec = "h264,mpeg4,mjpeg",
-                    AudioCodec = "ac3,eac3,aac,mp3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mkv",
-                    VideoCodec = "h264,mpeg4,vp8",
-                    AudioCodec = "ac3,eac3,aac,mp3,mp2,pcm,vorbis",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "avi",
-                    VideoCodec = "mpeg4",
-                    AudioCodec = "ac3,eac3,mp3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "avi",
-                    VideoCodec = "mjpeg",
-                    AudioCodec = "pcm",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mpeg",
-                    VideoCodec = "mpeg2video,mpeg1video",
-                    AudioCodec = "mp3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    VideoCodec = "wmv2,wmv3,vc1",
-                    AudioCodec = "wmav2,wmapro,wmavoice",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp4",
-                    AudioCodec = "aac",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "wav",
-                    AudioCodec = "pcm",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    AudioCodec = "wmav2,wmapro,wmavoice",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            ContainerProfiles = new[]
-            {
-                new ContainerProfile
-                {
-                    Type = DlnaProfileType.Photo,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        }
-                    }
-                }
-            };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    MimeType = "video/vnd.dlna.mpeg-tts",
-                    OrgPn = "AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.PacketLength,
-                            Value = "192"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.VideoTimestamp,
-                            Value = "Valid"
-                        }
-                    }
-                },
-
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    MimeType = "video/mpeg",
-                    OrgPn = "AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
-                    Type = DlnaProfileType.Video,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.PacketLength,
-                            Value = "188"
-                        }
-                    }
-                },
-
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264",
-                    AudioCodec = "ac3,aac,mp3",
-                    MimeType = "video/vnd.dlna.mpeg-tts",
-                    OrgPn = "AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "mpeg2video",
-                    MimeType = "video/vnd.dlna.mpeg-tts",
-                    OrgPn = "MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "mpeg",
-                    VideoCodec = "mpeg1video,mpeg2video",
-                    MimeType = "video/mpeg",
-                    OrgPn = "MPEG_PS_NTSC,MPEG_PS_PAL",
-                    Type = DlnaProfileType.Video
-                },
-                new ResponseProfile
-                {
-                    Container = "m4v",
-                    Type = DlnaProfileType.Video,
-                    MimeType = "video/mp4"
-                }
-            };
-
-            CodecProfiles = new[]
-            {
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoFramerate,
-                            Value = "30"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "mp3,mp2",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2"
-                        }
-                    }
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                }
-            };
-        }
-    }
-}

+ 0 - 269
Emby.Dlna/Profiles/SonyPs3Profile.cs

@@ -1,269 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class SonyPs3Profile : DefaultProfile
-    {
-        public SonyPs3Profile()
-        {
-            Name = "Sony PlayStation 3";
-
-            Identification = new DeviceIdentification
-            {
-                FriendlyName = "PLAYSTATION 3",
-
-                Headers = new[]
-                {
-                    new HttpHeaderInfo
-                    {
-                        Name = "User-Agent",
-                        Value = @"PLAYSTATION 3",
-                        Match = HeaderMatchType.Substring
-                    },
-
-                    new HttpHeaderInfo
-                    {
-                        Name = "X-AV-Client-Info",
-                        Value = @"PLAYSTATION 3",
-                        Match = HeaderMatchType.Substring
-                    }
-                }
-            };
-
-            AlbumArtPn = "JPEG_TN";
-
-            SonyAggregationFlags = "10";
-            EnableSingleAlbumArtLimit = true;
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "avi",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "mpeg4",
-                    AudioCodec = "mp2,mp3"
-                },
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "mpeg1video,mpeg2video,h264",
-                    AudioCodec = "aac,ac3,mp2"
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mpeg",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "mpeg1video,mpeg2video",
-                    AudioCodec = "mp2"
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp4",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "h264,mpeg4",
-                    AudioCodec = "aac,ac3"
-                },
-                new DirectPlayProfile
-                {
-                    Container = "aac,mp3,wav",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "jpeg,png,gif,bmp,tiff",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            TranscodingProfiles = new[]
-            {
-                new TranscodingProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-                new TranscodingProfile
-                {
-                    Container = "ts",
-                    VideoCodec = "h264",
-                    AudioCodec = "aac,ac3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new TranscodingProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            ContainerProfiles = new[]
-            {
-                new ContainerProfile
-                {
-                    Type = DlnaProfileType.Photo,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        }
-                    }
-                }
-            };
-
-            CodecProfiles = new[]
-            {
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Codec = "h264",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoFramerate,
-                            Value = "30",
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoBitrate,
-                            Value = "15360000",
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoLevel,
-                            Value = "41",
-                            IsRequired = false
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "ac3",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "6",
-                            IsRequired = false
-                        },
-
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioBitrate,
-                            Value = "640000",
-                            IsRequired = false
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "wmapro",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "aac",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.NotEquals,
-                            Property = ProfileConditionValue.AudioProfile,
-                            Value = "he-aac",
-                            IsRequired = false
-                        }
-                    }
-                }
-            };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Container = "mp4,mov",
-                    AudioCodec = "aac",
-                    MimeType = "video/mp4",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "avi",
-                    MimeType = "video/divx",
-                    OrgPn = "AVI",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "wav",
-                    MimeType = "audio/wav",
-                    Type = DlnaProfileType.Audio
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                }
-            };
-        }
-    }
-}

+ 0 - 278
Emby.Dlna/Profiles/SonyPs4Profile.cs

@@ -1,278 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class SonyPs4Profile : DefaultProfile
-    {
-        public SonyPs4Profile()
-        {
-            Name = "Sony PlayStation 4";
-
-            Identification = new DeviceIdentification
-            {
-                FriendlyName = "PLAYSTATION 4",
-
-                Headers = new[]
-                {
-                    new HttpHeaderInfo
-                    {
-                        Name = "User-Agent",
-                        Value = @"PLAYSTATION 4",
-                        Match = HeaderMatchType.Substring
-                    },
-
-                    new HttpHeaderInfo
-                    {
-                        Name = "X-AV-Client-Info",
-                        Value = @"PLAYSTATION 4",
-                        Match = HeaderMatchType.Substring
-                    }
-                }
-            };
-
-            AlbumArtPn = "JPEG_TN";
-
-            SonyAggregationFlags = "10";
-            EnableSingleAlbumArtLimit = true;
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "avi",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "mpeg4",
-                    AudioCodec = "mp2,mp3"
-                },
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "mpeg1video,mpeg2video,h264",
-                    AudioCodec = "aac,ac3,mp2"
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mpeg",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "mpeg1video,mpeg2video",
-                    AudioCodec = "mp2"
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp4,mkv,m4v",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "h264,mpeg4",
-                    AudioCodec = "aac,ac3"
-                },
-                new DirectPlayProfile
-                {
-                    Container = "aac,mp3,wav",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "jpeg,png,gif,bmp,tiff",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            TranscodingProfiles = new[]
-            {
-                new TranscodingProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio,
-                    // Transcoded audio won't be playable at all without this
-                    TranscodeSeekInfo = TranscodeSeekInfo.Bytes
-                },
-                new TranscodingProfile
-                {
-                    Container = "ts",
-                    VideoCodec = "h264",
-                    AudioCodec = "aac,ac3,mp2",
-                    Type = DlnaProfileType.Video
-                },
-                new TranscodingProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            ContainerProfiles = new[]
-            {
-                new ContainerProfile
-                {
-                    Type = DlnaProfileType.Photo,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        }
-                    }
-                }
-            };
-
-            CodecProfiles = new[]
-            {
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Codec = "h264",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoFramerate,
-                            Value = "30",
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoBitrate,
-                            Value = "15360000",
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoLevel,
-                            Value = "41",
-                            IsRequired = false
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "ac3",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "6",
-                            IsRequired = false
-                        },
-
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioBitrate,
-                            Value = "640000",
-                            IsRequired = false
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "wmapro",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "aac",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.NotEquals,
-                            Property = ProfileConditionValue.AudioProfile,
-                            Value = "he-aac",
-                            IsRequired = false
-                        }
-                    }
-                }
-            };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Container = "mp4,mov",
-                    AudioCodec = "aac",
-                    MimeType = "video/mp4",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "avi",
-                    MimeType = "video/divx",
-                    OrgPn = "AVI",
-                    Type = DlnaProfileType.Video
-                },
-
-                new ResponseProfile
-                {
-                    Container = "wav",
-                    MimeType = "audio/wav",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new ResponseProfile
-                {
-                    Container = "m4v",
-                    Type = DlnaProfileType.Video,
-                    MimeType = "video/mp4"
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                }
-            };
-        }
-    }
-}

+ 0 - 266
Emby.Dlna/Profiles/WdtvLiveProfile.cs

@@ -1,266 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class WdtvLiveProfile : DefaultProfile
-    {
-        public WdtvLiveProfile()
-        {
-            Name = "WDTV Live";
-
-            TimelineOffsetSeconds = 5;
-            IgnoreTranscodeByteRangeRequests = true;
-
-            Identification = new DeviceIdentification
-            {
-                ModelName = "WD TV",
-
-                Headers = new[]
-                {
-                    new HttpHeaderInfo { Name = "User-Agent", Value = "alphanetworks", Match = HeaderMatchType.Substring },
-                    new HttpHeaderInfo
-                    {
-                        Name = "User-Agent",
-                        Value = "ALPHA Networks",
-                        Match = HeaderMatchType.Substring
-                    }
-                }
-            };
-
-            TranscodingProfiles = new[]
-            {
-                new TranscodingProfile
-                {
-                    Container = "mp3",
-                    Type = DlnaProfileType.Audio,
-                    AudioCodec = "mp3"
-                },
-                new TranscodingProfile
-                {
-                    Container = "ts",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "h264",
-                    AudioCodec = "aac"
-                },
-                new TranscodingProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "avi",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "mpeg1video,mpeg2video,mpeg4,h264,vc1",
-                    AudioCodec = "ac3,eac3,dca,mp2,mp3,pcm,dts"
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "mpeg",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "mpeg1video,mpeg2video",
-                    AudioCodec = "ac3,eac3,dca,mp2,mp3,pcm,dts"
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "mkv",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "mpeg1video,mpeg2video,mpeg4,h264,vc1",
-                    AudioCodec = "ac3,eac3,dca,aac,mp2,mp3,pcm,dts"
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "ts,m2ts,mpegts",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "mpeg1video,mpeg2video,h264,vc1",
-                    AudioCodec = "ac3,eac3,dca,mp2,mp3,aac,dts"
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "mp4,mov,m4v",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "h264,mpeg4",
-                    AudioCodec = "ac3,eac3,aac,mp2,mp3,dca,dts"
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "vc1",
-                    AudioCodec = "wmav2,wmapro"
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    Type = DlnaProfileType.Video,
-                    VideoCodec = "mpeg2video",
-                    AudioCodec = "mp2,ac3"
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp2,mp3",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "mp4",
-                    AudioCodec = "mp4",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "flac",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    AudioCodec = "wmav2,wmapro,wmavoice",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new DirectPlayProfile
-                {
-                    Container = "ogg",
-                    AudioCodec = "vorbis",
-                    Type = DlnaProfileType.Audio
-                },
-
-                new DirectPlayProfile
-                {
-                    Type = DlnaProfileType.Photo,
-
-                    Container = "jpeg,png,gif,bmp,tiff"
-                }
-            };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Container = "ts,mpegts",
-                    OrgPn = "MPEG_TS_SD_NA",
-                    Type = DlnaProfileType.Video
-                }
-            };
-
-            ContainerProfiles = new[]
-            {
-                new ContainerProfile
-                {
-                    Type = DlnaProfileType.Photo,
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        }
-                    }
-                }
-            };
-
-            CodecProfiles = new[]
-            {
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Codec = "h264",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoLevel,
-                            Value = "41"
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "aac",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2"
-                        }
-                    }
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.External
-                },
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                },
-                new SubtitleProfile
-                {
-                    Format = "sub",
-                    Method = SubtitleDeliveryMethod.Embed
-                },
-                new SubtitleProfile
-                {
-                    Format = "subrip",
-                    Method = SubtitleDeliveryMethod.Embed
-                },
-                new SubtitleProfile
-                {
-                    Format = "idx",
-                    Method = SubtitleDeliveryMethod.Embed
-                }
-            };
-        }
-    }
-}

+ 0 - 372
Emby.Dlna/Profiles/XboxOneProfile.cs

@@ -1,372 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Model.Dlna;
-
-namespace Emby.Dlna.Profiles
-{
-    [System.Xml.Serialization.XmlRoot("Profile")]
-    public class XboxOneProfile : DefaultProfile
-    {
-        public XboxOneProfile()
-        {
-            Name = "Xbox One";
-
-            TimelineOffsetSeconds = 40;
-
-            Identification = new DeviceIdentification
-            {
-                ModelName = "Xbox One",
-
-                Headers = new[]
-                {
-                    new HttpHeaderInfo
-                    {
-                        Name = "FriendlyName.DLNA.ORG", Value = "XboxOne", Match = HeaderMatchType.Substring
-                    },
-                    new HttpHeaderInfo
-                    {
-                        Name = "User-Agent", Value = "NSPlayer/12", Match = HeaderMatchType.Substring
-                    }
-                }
-            };
-
-            var videoProfile = "high|main|baseline|constrained baseline";
-            var videoLevel = "41";
-
-            TranscodingProfiles = new[]
-            {
-                new TranscodingProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-                new TranscodingProfile
-                {
-                    Container = "jpeg",
-                    VideoCodec = "jpeg",
-                    Type = DlnaProfileType.Photo
-                },
-                new TranscodingProfile
-                {
-                    Container = "ts",
-                    VideoCodec = "h264",
-                    AudioCodec = "aac",
-                    Type = DlnaProfileType.Video
-                }
-            };
-
-            DirectPlayProfiles = new[]
-            {
-                new DirectPlayProfile
-                {
-                    Container = "ts,mpegts",
-                    VideoCodec = "h264,mpeg2video,hevc",
-                    AudioCodec = "ac3,aac,mp3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "avi",
-                    VideoCodec = "mpeg4",
-                    AudioCodec = "ac3,mp3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "avi",
-                    VideoCodec = "h264",
-                    AudioCodec = "aac",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp4,mov,mkv,m4v",
-                    VideoCodec = "h264,mpeg4,mpeg2video,hevc",
-                    AudioCodec = "aac,ac3",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    VideoCodec = "wmv2,wmv3,vc1",
-                    AudioCodec = "wmav2,wmapro",
-                    Type = DlnaProfileType.Video
-                },
-                new DirectPlayProfile
-                {
-                    Container = "asf",
-                    AudioCodec = "wmav2,wmapro,wmavoice",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "mp3",
-                    AudioCodec = "mp3",
-                    Type = DlnaProfileType.Audio
-                },
-                new DirectPlayProfile
-                {
-                    Container = "jpeg",
-                    Type = DlnaProfileType.Photo
-                }
-            };
-
-            ContainerProfiles = new[]
-            {
-                new ContainerProfile
-                {
-                    Type = DlnaProfileType.Video,
-                    Container = "mp4,mov",
-
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.Has64BitOffsets,
-                            Value = "false",
-                            IsRequired = false
-                        }
-                    }
-                }
-            };
-
-            CodecProfiles = new[]
-            {
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Codec = "mpeg4",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.NotEquals,
-                            Property = ProfileConditionValue.IsAnamorphic,
-                            Value = "true",
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoBitDepth,
-                            Value = "8",
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoFramerate,
-                            Value = "30",
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoBitrate,
-                            Value = "5120000",
-                            IsRequired = false
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Codec = "h264",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.NotEquals,
-                            Property = ProfileConditionValue.IsAnamorphic,
-                            Value = "true",
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoBitDepth,
-                            Value = "8",
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoLevel,
-                            Value = videoLevel,
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.EqualsAny,
-                            Property = ProfileConditionValue.VideoProfile,
-                            Value = videoProfile,
-                            IsRequired = false
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Codec = "wmv2,wmv3,vc1",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.NotEquals,
-                            Property = ProfileConditionValue.IsAnamorphic,
-                            Value = "true",
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoBitDepth,
-                            Value = "8",
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Width,
-                            Value = "1920"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.Height,
-                            Value = "1080"
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoFramerate,
-                            Value = "30",
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoBitrate,
-                            Value = "15360000",
-                            IsRequired = false
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.Video,
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.NotEquals,
-                            Property = ProfileConditionValue.IsAnamorphic,
-                            Value = "true",
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.VideoBitDepth,
-                            Value = "8",
-                            IsRequired = false
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "ac3,wmav2,wmapro",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "6",
-                            IsRequired = false
-                        }
-                    }
-                },
-
-                new CodecProfile
-                {
-                    Type = CodecType.VideoAudio,
-                    Codec = "aac",
-                    Conditions = new[]
-                    {
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.LessThanEqual,
-                            Property = ProfileConditionValue.AudioChannels,
-                            Value = "2",
-                            IsRequired = false
-                        },
-                        new ProfileCondition
-                        {
-                            Condition = ProfileConditionType.Equals,
-                            Property = ProfileConditionValue.AudioProfile,
-                            Value = "lc",
-                            IsRequired = false
-                        }
-                    }
-                }
-            };
-
-            ResponseProfiles = new[]
-            {
-                new ResponseProfile
-                {
-                    Container = "avi",
-                    MimeType = "video/avi",
-                    Type = DlnaProfileType.Video
-                },
-                new ResponseProfile
-                {
-                    Container = "m4v",
-                    Type = DlnaProfileType.Video,
-                    MimeType = "video/mp4"
-                }
-            };
-
-            SubtitleProfiles = new[]
-            {
-                new SubtitleProfile
-                {
-                    Format = "srt",
-                    Method = SubtitleDeliveryMethod.Embed
-                }
-            };
-        }
-    }
-}

+ 1 - 1
Emby.Dlna/Service/BaseControlHandler.cs

@@ -6,8 +6,8 @@ using System.IO;
 using System.Text;
 using System.Text;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using System.Xml;
 using System.Xml;
-using Diacritics.Extensions;
 using Emby.Dlna.Didl;
 using Emby.Dlna.Didl;
+using Jellyfin.Extensions;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Logging;
 
 

+ 1 - 1
Emby.Drawing/Emby.Drawing.csproj

@@ -32,7 +32,7 @@
       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
     </PackageReference>
     </PackageReference>
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
-    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406" PrivateAssets="All" />
+    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
   </ItemGroup>
   </ItemGroup>
 
 

+ 44 - 39
Emby.Drawing/ImageProcessor.cs

@@ -395,7 +395,13 @@ namespace Emby.Drawing
         public string GetImageBlurHash(string path)
         public string GetImageBlurHash(string path)
         {
         {
             var size = GetImageDimensions(path);
             var size = GetImageDimensions(path);
-            if (size.Width <= 0 || size.Height <= 0)
+            return GetImageBlurHash(path, size);
+        }
+
+        /// <inheritdoc />
+        public string GetImageBlurHash(string path, ImageDimensions imageDimensions)
+        {
+            if (imageDimensions.Width <= 0 || imageDimensions.Height <= 0)
             {
             {
                 return string.Empty;
                 return string.Empty;
             }
             }
@@ -403,8 +409,8 @@ namespace Emby.Drawing
             // We want tiles to be as close to square as possible, and to *mostly* keep under 16 tiles for performance.
             // We want tiles to be as close to square as possible, and to *mostly* keep under 16 tiles for performance.
             // One tile is (width / xComp) x (height / yComp) pixels, which means that ideally yComp = xComp * height / width.
             // One tile is (width / xComp) x (height / yComp) pixels, which means that ideally yComp = xComp * height / width.
             // See more at https://github.com/woltapp/blurhash/#how-do-i-pick-the-number-of-x-and-y-components
             // See more at https://github.com/woltapp/blurhash/#how-do-i-pick-the-number-of-x-and-y-components
-            float xCompF = MathF.Sqrt(16.0f * size.Width / size.Height);
-            float yCompF = xCompF * size.Height / size.Width;
+            float xCompF = MathF.Sqrt(16.0f * imageDimensions.Width / imageDimensions.Height);
+            float yCompF = xCompF * imageDimensions.Height / imageDimensions.Width;
 
 
             int xComp = Math.Min((int)xCompF + 1, 9);
             int xComp = Math.Min((int)xCompF + 1, 9);
             int yComp = Math.Min((int)yCompF + 1, 9);
             int yComp = Math.Min((int)yCompF + 1, 9);
@@ -439,47 +445,46 @@ namespace Emby.Drawing
                 .ToString("N", CultureInfo.InvariantCulture);
                 .ToString("N", CultureInfo.InvariantCulture);
         }
         }
 
 
-        private async Task<(string Path, DateTime DateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified)
+        private Task<(string Path, DateTime DateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified)
         {
         {
-            var inputFormat = Path.GetExtension(originalImagePath)
-                .TrimStart('.')
-                .Replace("jpeg", "jpg", StringComparison.OrdinalIgnoreCase);
+            var inputFormat = Path.GetExtension(originalImagePath.AsSpan()).TrimStart('.').ToString();
 
 
             // These are just jpg files renamed as tbn
             // These are just jpg files renamed as tbn
             if (string.Equals(inputFormat, "tbn", StringComparison.OrdinalIgnoreCase))
             if (string.Equals(inputFormat, "tbn", StringComparison.OrdinalIgnoreCase))
             {
             {
-                return (originalImagePath, dateModified);
-            }
-
-            if (!_imageEncoder.SupportedInputFormats.Contains(inputFormat))
-            {
-                try
-                {
-                    string filename = (originalImagePath + dateModified.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("N", CultureInfo.InvariantCulture);
-
-                    string cacheExtension = _mediaEncoder.SupportsEncoder("libwebp") ? ".webp" : ".png";
-                    var outputPath = Path.Combine(_appPaths.ImageCachePath, "converted-images", filename + cacheExtension);
-
-                    var file = _fileSystem.GetFileInfo(outputPath);
-                    if (!file.Exists)
-                    {
-                        await _mediaEncoder.ConvertImage(originalImagePath, outputPath).ConfigureAwait(false);
-                        dateModified = _fileSystem.GetLastWriteTimeUtc(outputPath);
-                    }
-                    else
-                    {
-                        dateModified = file.LastWriteTimeUtc;
-                    }
-
-                    originalImagePath = outputPath;
-                }
-                catch (Exception ex)
-                {
-                    _logger.LogError(ex, "Image conversion failed for {Path}", originalImagePath);
-                }
-            }
-
-            return (originalImagePath, dateModified);
+                return Task.FromResult((originalImagePath, dateModified));
+            }
+
+            // TODO _mediaEncoder.ConvertImage is not implemented
+            // if (!_imageEncoder.SupportedInputFormats.Contains(inputFormat))
+            // {
+            //     try
+            //     {
+            //         string filename = (originalImagePath + dateModified.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("N", CultureInfo.InvariantCulture);
+            //
+            //         string cacheExtension = _mediaEncoder.SupportsEncoder("libwebp") ? ".webp" : ".png";
+            //         var outputPath = Path.Combine(_appPaths.ImageCachePath, "converted-images", filename + cacheExtension);
+            //
+            //         var file = _fileSystem.GetFileInfo(outputPath);
+            //         if (!file.Exists)
+            //         {
+            //             await _mediaEncoder.ConvertImage(originalImagePath, outputPath).ConfigureAwait(false);
+            //             dateModified = _fileSystem.GetLastWriteTimeUtc(outputPath);
+            //         }
+            //         else
+            //         {
+            //             dateModified = file.LastWriteTimeUtc;
+            //         }
+            //
+            //         originalImagePath = outputPath;
+            //     }
+            //     catch (Exception ex)
+            //     {
+            //         _logger.LogError(ex, "Image conversion failed for {Path}", originalImagePath);
+            //     }
+            // }
+
+            return Task.FromResult((originalImagePath, dateModified));
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 1 - 1
Emby.Naming/AudioBook/AudioBookFilePathParserResult.cs

@@ -3,7 +3,7 @@ namespace Emby.Naming.AudioBook
     /// <summary>
     /// <summary>
     /// Data object for passing result of audiobook part/chapter extraction.
     /// Data object for passing result of audiobook part/chapter extraction.
     /// </summary>
     /// </summary>
-    public struct AudioBookFilePathParserResult
+    public record struct AudioBookFilePathParserResult
     {
     {
         /// <summary>
         /// <summary>
         /// Gets or sets optional number of path extracted from audiobook filename.
         /// Gets or sets optional number of path extracted from audiobook filename.

+ 1 - 2
Emby.Naming/Common/NamingOptions.cs

@@ -48,7 +48,6 @@ namespace Emby.Naming.Common
                 ".mkv",
                 ".mkv",
                 ".mk3d",
                 ".mk3d",
                 ".mov",
                 ".mov",
-                ".mp2",
                 ".mp4",
                 ".mp4",
                 ".mpe",
                 ".mpe",
                 ".mpeg",
                 ".mpeg",
@@ -315,7 +314,7 @@ namespace Emby.Naming.Common
                 // This isn't a Kodi naming rule, but the expression below causes false positives,
                 // This isn't a Kodi naming rule, but the expression below causes false positives,
                 // so we make sure this one gets tested first.
                 // so we make sure this one gets tested first.
                 // "Foo Bar 889"
                 // "Foo Bar 889"
-                new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?<seriesname>[\w\s]+?)\s(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*[^\\\/x]*$")
+                new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?<seriesname>[\w\s]+?)\s(?<epnumber>[0-9]{1,4})(-(?<endingepnumber>[0-9]{2,4}))*[^\\\/x]*$")
                 {
                 {
                     IsNamed = true
                     IsNamed = true
                 },
                 },

+ 2 - 2
Emby.Naming/Emby.Naming.csproj

@@ -36,7 +36,7 @@
   <PropertyGroup>
   <PropertyGroup>
     <Authors>Jellyfin Contributors</Authors>
     <Authors>Jellyfin Contributors</Authors>
     <PackageId>Jellyfin.Naming</PackageId>
     <PackageId>Jellyfin.Naming</PackageId>
-    <VersionPrefix>10.8.0</VersionPrefix>
+    <VersionPrefix>10.9.0</VersionPrefix>
     <RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
     <RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
     <PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
     <PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
   </PropertyGroup>
   </PropertyGroup>
@@ -52,7 +52,7 @@
       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
     </PackageReference>
     </PackageReference>
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
-    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406" PrivateAssets="All" />
+    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
   </ItemGroup>
   </ItemGroup>
 
 

+ 1 - 1
Emby.Notifications/Emby.Notifications.csproj

@@ -28,7 +28,7 @@
       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
     </PackageReference>
     </PackageReference>
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
-    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406" PrivateAssets="All" />
+    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
   </ItemGroup>
   </ItemGroup>
 
 

+ 2 - 2
Emby.Photos/Emby.Photos.csproj

@@ -15,7 +15,7 @@
   </ItemGroup>
   </ItemGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Include="TagLibSharp" Version="2.2.0" />
+    <PackageReference Include="TagLibSharp" Version="2.3.0" />
   </ItemGroup>
   </ItemGroup>
 
 
   <PropertyGroup>
   <PropertyGroup>
@@ -30,7 +30,7 @@
       <PrivateAssets>all</PrivateAssets>
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
     </PackageReference>
     </PackageReference>
-    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406" PrivateAssets="All" />
+    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
   </ItemGroup>
   </ItemGroup>

+ 9 - 14
Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs

@@ -210,10 +210,7 @@ namespace Emby.Server.Implementations.AppBase
         /// <exception cref="ArgumentNullException"><c>newConfiguration</c> is <c>null</c>.</exception>
         /// <exception cref="ArgumentNullException"><c>newConfiguration</c> is <c>null</c>.</exception>
         public virtual void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration)
         public virtual void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration)
         {
         {
-            if (newConfiguration == null)
-            {
-                throw new ArgumentNullException(nameof(newConfiguration));
-            }
+            ArgumentNullException.ThrowIfNull(newConfiguration);
 
 
             ValidateCachePath(newConfiguration);
             ValidateCachePath(newConfiguration);
 
 
@@ -365,11 +362,7 @@ namespace Emby.Server.Implementations.AppBase
                 validatingStore.Validate(currentConfiguration, configuration);
                 validatingStore.Validate(currentConfiguration, configuration);
             }
             }
 
 
-            NamedConfigurationUpdating?.Invoke(this, new ConfigurationUpdateEventArgs
-            {
-                Key = key,
-                NewConfiguration = configuration
-            });
+            NamedConfigurationUpdating?.Invoke(this, new ConfigurationUpdateEventArgs(key, configuration));
 
 
             _configurations.AddOrUpdate(key, configuration, (_, _) => configuration);
             _configurations.AddOrUpdate(key, configuration, (_, _) => configuration);
 
 
@@ -391,11 +384,13 @@ namespace Emby.Server.Implementations.AppBase
         /// <param name="configuration">The old configuration.</param>
         /// <param name="configuration">The old configuration.</param>
         protected virtual void OnNamedConfigurationUpdated(string key, object configuration)
         protected virtual void OnNamedConfigurationUpdated(string key, object configuration)
         {
         {
-            NamedConfigurationUpdated?.Invoke(this, new ConfigurationUpdateEventArgs
-            {
-                Key = key,
-                NewConfiguration = configuration
-            });
+            NamedConfigurationUpdated?.Invoke(this, new ConfigurationUpdateEventArgs(key, configuration));
+        }
+
+        /// <inheritdoc />
+        public ConfigurationStore[] GetConfigurationStores()
+        {
+            return _configurationStores;
         }
         }
 
 
         /// <inheritdoc />
         /// <inheritdoc />

+ 55 - 9
Emby.Server.Implementations/ApplicationHost.cs

@@ -83,6 +83,7 @@ using MediaBrowser.Controller.SyncPlay;
 using MediaBrowser.Controller.TV;
 using MediaBrowser.Controller.TV;
 using MediaBrowser.LocalMetadata.Savers;
 using MediaBrowser.LocalMetadata.Savers;
 using MediaBrowser.MediaEncoding.BdInfo;
 using MediaBrowser.MediaEncoding.BdInfo;
+using MediaBrowser.MediaEncoding.Subtitles;
 using MediaBrowser.Model.Cryptography;
 using MediaBrowser.Model.Cryptography;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Globalization;
 using MediaBrowser.Model.Globalization;
@@ -111,7 +112,7 @@ namespace Emby.Server.Implementations
     /// <summary>
     /// <summary>
     /// Class CompositionRoot.
     /// Class CompositionRoot.
     /// </summary>
     /// </summary>
-    public abstract class ApplicationHost : IServerApplicationHost, IDisposable
+    public abstract class ApplicationHost : IServerApplicationHost, IAsyncDisposable, IDisposable
     {
     {
         /// <summary>
         /// <summary>
         /// The environment variable prefixes to log at server startup.
         /// The environment variable prefixes to log at server startup.
@@ -629,12 +630,11 @@ namespace Emby.Server.Implementations
 
 
             serviceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>();
             serviceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>();
 
 
-            serviceCollection.AddScoped<ISessionContext, SessionContext>();
-
             serviceCollection.AddSingleton<IAuthService, AuthService>();
             serviceCollection.AddSingleton<IAuthService, AuthService>();
             serviceCollection.AddSingleton<IQuickConnect, QuickConnectManager>();
             serviceCollection.AddSingleton<IQuickConnect, QuickConnectManager>();
 
 
-            serviceCollection.AddSingleton<ISubtitleEncoder, MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder>();
+            serviceCollection.AddSingleton<ISubtitleParser, SubtitleEditParser>();
+            serviceCollection.AddSingleton<ISubtitleEncoder, SubtitleEncoder>();
 
 
             serviceCollection.AddSingleton<IAttachmentExtractor, MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor>();
             serviceCollection.AddSingleton<IAttachmentExtractor, MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor>();
 
 
@@ -1114,13 +1114,13 @@ namespace Emby.Server.Implementations
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        public string GetApiUrlForLocalAccess(bool allowHttps = true)
+        public string GetApiUrlForLocalAccess(IPObject hostname = null, bool allowHttps = true)
         {
         {
             // With an empty source, the port will be null
             // With an empty source, the port will be null
-            string smart = NetManager.GetBindInterface(string.Empty, out _);
+            var smart = NetManager.GetBindInterface(hostname ?? IPHost.None, out _);
             var scheme = !allowHttps ? Uri.UriSchemeHttp : null;
             var scheme = !allowHttps ? Uri.UriSchemeHttp : null;
             int? port = !allowHttps ? HttpPort : null;
             int? port = !allowHttps ? HttpPort : null;
-            return GetLocalApiUrl(smart.Trim('/'), scheme, port);
+            return GetLocalApiUrl(smart, scheme, port);
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
@@ -1134,11 +1134,13 @@ namespace Emby.Server.Implementations
 
 
             // NOTE: If no BaseUrl is set then UriBuilder appends a trailing slash, but if there is no BaseUrl it does
             // 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.
             // not. For consistency, always trim the trailing slash.
+            scheme ??= ListenWithHttps ? Uri.UriSchemeHttps : Uri.UriSchemeHttp;
+            var isHttps = string.Equals(scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase);
             return new UriBuilder
             return new UriBuilder
             {
             {
-                Scheme = scheme ?? (ListenWithHttps ? Uri.UriSchemeHttps : Uri.UriSchemeHttp),
+                Scheme = scheme,
                 Host = hostname,
                 Host = hostname,
-                Port = port ?? (ListenWithHttps ? HttpsPort : HttpPort),
+                Port = port ?? (isHttps ? HttpsPort : HttpPort),
                 Path = ConfigurationManager.GetNetworkConfiguration().BaseUrl
                 Path = ConfigurationManager.GetNetworkConfiguration().BaseUrl
             }.ToString().TrimEnd('/');
             }.ToString().TrimEnd('/');
         }
         }
@@ -1230,5 +1232,49 @@ namespace Emby.Server.Implementations
 
 
             _disposed = true;
             _disposed = true;
         }
         }
+
+        public async ValueTask DisposeAsync()
+        {
+            await DisposeAsyncCore().ConfigureAwait(false);
+            Dispose(false);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Used to perform asynchronous cleanup of managed resources or for cascading calls to <see cref="DisposeAsync"/>.
+        /// </summary>
+        /// <returns>A ValueTask.</returns>
+        protected virtual async ValueTask DisposeAsyncCore()
+        {
+            var type = GetType();
+
+            Logger.LogInformation("Disposing {Type}", type.Name);
+
+            foreach (var (part, _) in _disposableParts)
+            {
+                var partType = part.GetType();
+                if (partType == type)
+                {
+                    continue;
+                }
+
+                Logger.LogInformation("Disposing {Type}", partType.Name);
+
+                try
+                {
+                    part.Dispose();
+                }
+                catch (Exception ex)
+                {
+                    Logger.LogError(ex, "Error disposing {Type}", partType.Name);
+                }
+            }
+
+            // used for closing websockets
+            foreach (var session in _sessionManager.Sessions)
+            {
+                await session.DisposeAsync().ConfigureAwait(false);
+            }
+        }
     }
     }
 }
 }

+ 1 - 4
Emby.Server.Implementations/Channels/ChannelManager.cs

@@ -1188,10 +1188,7 @@ namespace Emby.Server.Implementations.Channels
 
 
         internal IChannel GetChannelProvider(Channel channel)
         internal IChannel GetChannelProvider(Channel channel)
         {
         {
-            if (channel == null)
-            {
-                throw new ArgumentNullException(nameof(channel));
-            }
+            ArgumentNullException.ThrowIfNull(channel);
 
 
             var result = GetAllChannels()
             var result = GetAllChannels()
                 .FirstOrDefault(i => GetInternalChannelId(i.Name).Equals(channel.ChannelId) || string.Equals(i.Name, channel.Name, StringComparison.OrdinalIgnoreCase));
                 .FirstOrDefault(i => GetInternalChannelId(i.Name).Equals(channel.ChannelId) || string.Equals(i.Name, channel.Name, StringComparison.OrdinalIgnoreCase));

+ 1 - 4
Emby.Server.Implementations/Data/SqliteExtensions.cs

@@ -54,10 +54,7 @@ namespace Emby.Server.Implementations.Data
 
 
         public static void RunQueries(this SQLiteDatabaseConnection connection, string[] queries)
         public static void RunQueries(this SQLiteDatabaseConnection connection, string[] queries)
         {
         {
-            if (queries == null)
-            {
-                throw new ArgumentNullException(nameof(queries));
-            }
+            ArgumentNullException.ThrowIfNull(queries);
 
 
             connection.RunInTransaction(conn =>
             connection.RunInTransaction(conn =>
             {
             {

+ 111 - 96
Emby.Server.Implementations/Data/SqliteItemRepository.cs

@@ -11,7 +11,6 @@ using System.Linq;
 using System.Text;
 using System.Text;
 using System.Text.Json;
 using System.Text.Json;
 using System.Threading;
 using System.Threading;
-using Diacritics.Extensions;
 using Emby.Server.Implementations.Playlists;
 using Emby.Server.Implementations.Playlists;
 using Jellyfin.Data.Enums;
 using Jellyfin.Data.Enums;
 using Jellyfin.Extensions;
 using Jellyfin.Extensions;
@@ -171,7 +170,15 @@ namespace Emby.Server.Implementations.Data
             "CodecTimeBase",
             "CodecTimeBase",
             "ColorPrimaries",
             "ColorPrimaries",
             "ColorSpace",
             "ColorSpace",
-            "ColorTransfer"
+            "ColorTransfer",
+            "DvVersionMajor",
+            "DvVersionMinor",
+            "DvProfile",
+            "DvLevel",
+            "RpuPresentFlag",
+            "ElPresentFlag",
+            "BlPresentFlag",
+            "DvBlSignalCompatibilityId"
         };
         };
 
 
         private static readonly string _mediaStreamSaveColumnsInsertQuery =
         private static readonly string _mediaStreamSaveColumnsInsertQuery =
@@ -342,7 +349,7 @@ namespace Emby.Server.Implementations.Data
         public void Initialize(SqliteUserDataRepository userDataRepo, IUserManager userManager)
         public void Initialize(SqliteUserDataRepository userDataRepo, IUserManager userManager)
         {
         {
             const string CreateMediaStreamsTableCommand
             const string CreateMediaStreamsTableCommand
-                    = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, IsAvc BIT NULL, Title TEXT NULL, TimeBase TEXT NULL, CodecTimeBase TEXT NULL, ColorPrimaries TEXT NULL, ColorSpace TEXT NULL, ColorTransfer TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))";
+                    = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, IsAvc BIT NULL, Title TEXT NULL, TimeBase TEXT NULL, CodecTimeBase TEXT NULL, ColorPrimaries TEXT NULL, ColorSpace TEXT NULL, ColorTransfer TEXT NULL, DvVersionMajor INT NULL, DvVersionMinor INT NULL, DvProfile INT NULL, DvLevel INT NULL, RpuPresentFlag INT NULL, ElPresentFlag INT NULL, BlPresentFlag INT NULL, DvBlSignalCompatibilityId INT NULL, PRIMARY KEY (ItemId, StreamIndex))";
             const string CreateMediaAttachmentsTableCommand
             const string CreateMediaAttachmentsTableCommand
                     = "create table if not exists mediaattachments (ItemId GUID, AttachmentIndex INT, Codec TEXT, CodecTag TEXT NULL, Comment TEXT NULL, Filename TEXT NULL, MIMEType TEXT NULL, PRIMARY KEY (ItemId, AttachmentIndex))";
                     = "create table if not exists mediaattachments (ItemId GUID, AttachmentIndex INT, Codec TEXT, CodecTag TEXT NULL, Comment TEXT NULL, Filename TEXT NULL, MIMEType TEXT NULL, PRIMARY KEY (ItemId, AttachmentIndex))";
 
 
@@ -556,6 +563,15 @@ namespace Emby.Server.Implementations.Data
                         AddColumn(db, "MediaStreams", "ColorPrimaries", "TEXT", existingColumnNames);
                         AddColumn(db, "MediaStreams", "ColorPrimaries", "TEXT", existingColumnNames);
                         AddColumn(db, "MediaStreams", "ColorSpace", "TEXT", existingColumnNames);
                         AddColumn(db, "MediaStreams", "ColorSpace", "TEXT", existingColumnNames);
                         AddColumn(db, "MediaStreams", "ColorTransfer", "TEXT", existingColumnNames);
                         AddColumn(db, "MediaStreams", "ColorTransfer", "TEXT", existingColumnNames);
+
+                        AddColumn(db, "MediaStreams", "DvVersionMajor", "INT", existingColumnNames);
+                        AddColumn(db, "MediaStreams", "DvVersionMinor", "INT", existingColumnNames);
+                        AddColumn(db, "MediaStreams", "DvProfile", "INT", existingColumnNames);
+                        AddColumn(db, "MediaStreams", "DvLevel", "INT", existingColumnNames);
+                        AddColumn(db, "MediaStreams", "RpuPresentFlag", "INT", existingColumnNames);
+                        AddColumn(db, "MediaStreams", "ElPresentFlag", "INT", existingColumnNames);
+                        AddColumn(db, "MediaStreams", "BlPresentFlag", "INT", existingColumnNames);
+                        AddColumn(db, "MediaStreams", "DvBlSignalCompatibilityId", "INT", existingColumnNames);
                     },
                     },
                     TransactionMode);
                     TransactionMode);
 
 
@@ -567,10 +583,7 @@ namespace Emby.Server.Implementations.Data
 
 
         public void SaveImages(BaseItem item)
         public void SaveImages(BaseItem item)
         {
         {
-            if (item == null)
-            {
-                throw new ArgumentNullException(nameof(item));
-            }
+            ArgumentNullException.ThrowIfNull(item);
 
 
             CheckDisposed();
             CheckDisposed();
 
 
@@ -601,10 +614,7 @@ namespace Emby.Server.Implementations.Data
         /// </exception>
         /// </exception>
         public void SaveItems(IEnumerable<BaseItem> items, CancellationToken cancellationToken)
         public void SaveItems(IEnumerable<BaseItem> items, CancellationToken cancellationToken)
         {
         {
-            if (items == null)
-            {
-                throw new ArgumentNullException(nameof(items));
-            }
+            ArgumentNullException.ThrowIfNull(items);
 
 
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 
@@ -2069,10 +2079,7 @@ namespace Emby.Server.Implementations.Data
                 throw new ArgumentNullException(nameof(id));
                 throw new ArgumentNullException(nameof(id));
             }
             }
 
 
-            if (chapters == null)
-            {
-                throw new ArgumentNullException(nameof(chapters));
-            }
+            ArgumentNullException.ThrowIfNull(chapters);
 
 
             var idBlob = id.ToByteArray();
             var idBlob = id.ToByteArray();
 
 
@@ -2404,7 +2411,7 @@ namespace Emby.Server.Implementations.Data
                 }
                 }
 
 
                 // genres, tags, studios, person, year?
                 // genres, tags, studios, person, year?
-                builder.Append("+ (Select count(1) * 10 from ItemValues where ItemId=Guid and CleanValue in (select CleanValue from itemvalues where ItemId=@SimilarItemId))");
+                builder.Append("+ (Select count(1) * 10 from ItemValues where ItemId=Guid and CleanValue in (select CleanValue from ItemValues where ItemId=@SimilarItemId))");
 
 
                 if (item is MusicArtist)
                 if (item is MusicArtist)
                 {
                 {
@@ -2541,10 +2548,7 @@ namespace Emby.Server.Implementations.Data
 
 
         public int GetCount(InternalItemsQuery query)
         public int GetCount(InternalItemsQuery query)
         {
         {
-            if (query == null)
-            {
-                throw new ArgumentNullException(nameof(query));
-            }
+            ArgumentNullException.ThrowIfNull(query);
 
 
             CheckDisposed();
             CheckDisposed();
 
 
@@ -2597,10 +2601,7 @@ namespace Emby.Server.Implementations.Data
 
 
         public List<BaseItem> GetItemList(InternalItemsQuery query)
         public List<BaseItem> GetItemList(InternalItemsQuery query)
         {
         {
-            if (query == null)
-            {
-                throw new ArgumentNullException(nameof(query));
-            }
+            ArgumentNullException.ThrowIfNull(query);
 
 
             CheckDisposed();
             CheckDisposed();
 
 
@@ -2778,10 +2779,7 @@ namespace Emby.Server.Implementations.Data
 
 
         public QueryResult<BaseItem> GetItems(InternalItemsQuery query)
         public QueryResult<BaseItem> GetItems(InternalItemsQuery query)
         {
         {
-            if (query == null)
-            {
-                throw new ArgumentNullException(nameof(query));
-            }
+            ArgumentNullException.ThrowIfNull(query);
 
 
             CheckDisposed();
             CheckDisposed();
 
 
@@ -3059,12 +3057,12 @@ namespace Emby.Server.Implementations.Data
 
 
             if (string.Equals(name, ItemSortBy.Artist, StringComparison.OrdinalIgnoreCase))
             if (string.Equals(name, ItemSortBy.Artist, StringComparison.OrdinalIgnoreCase))
             {
             {
-                return "(select CleanValue from itemvalues where ItemId=Guid and Type=0 LIMIT 1)";
+                return "(select CleanValue from ItemValues where ItemId=Guid and Type=0 LIMIT 1)";
             }
             }
 
 
             if (string.Equals(name, ItemSortBy.AlbumArtist, StringComparison.OrdinalIgnoreCase))
             if (string.Equals(name, ItemSortBy.AlbumArtist, StringComparison.OrdinalIgnoreCase))
             {
             {
-                return "(select CleanValue from itemvalues where ItemId=Guid and Type=1 LIMIT 1)";
+                return "(select CleanValue from ItemValues where ItemId=Guid and Type=1 LIMIT 1)";
             }
             }
 
 
             if (string.Equals(name, ItemSortBy.OfficialRating, StringComparison.OrdinalIgnoreCase))
             if (string.Equals(name, ItemSortBy.OfficialRating, StringComparison.OrdinalIgnoreCase))
@@ -3074,7 +3072,7 @@ namespace Emby.Server.Implementations.Data
 
 
             if (string.Equals(name, ItemSortBy.Studio, StringComparison.OrdinalIgnoreCase))
             if (string.Equals(name, ItemSortBy.Studio, StringComparison.OrdinalIgnoreCase))
             {
             {
-                return "(select CleanValue from itemvalues where ItemId=Guid and Type=3 LIMIT 1)";
+                return "(select CleanValue from ItemValues where ItemId=Guid and Type=3 LIMIT 1)";
             }
             }
 
 
             if (string.Equals(name, ItemSortBy.SeriesDatePlayed, StringComparison.OrdinalIgnoreCase))
             if (string.Equals(name, ItemSortBy.SeriesDatePlayed, StringComparison.OrdinalIgnoreCase))
@@ -3147,16 +3145,18 @@ namespace Emby.Server.Implementations.Data
                 return ItemSortBy.IndexNumber;
                 return ItemSortBy.IndexNumber;
             }
             }
 
 
+            if (string.Equals(name, ItemSortBy.SimilarityScore, StringComparison.OrdinalIgnoreCase))
+            {
+                return ItemSortBy.SimilarityScore;
+            }
+
             // Unknown SortBy, just sort by the SortName.
             // Unknown SortBy, just sort by the SortName.
             return ItemSortBy.SortName;
             return ItemSortBy.SortName;
         }
         }
 
 
         public List<Guid> GetItemIdsList(InternalItemsQuery query)
         public List<Guid> GetItemIdsList(InternalItemsQuery query)
         {
         {
-            if (query == null)
-            {
-                throw new ArgumentNullException(nameof(query));
-            }
+            ArgumentNullException.ThrowIfNull(query);
 
 
             CheckDisposed();
             CheckDisposed();
 
 
@@ -3847,7 +3847,7 @@ namespace Emby.Server.Implementations.Data
                 {
                 {
                     var paramName = "@ArtistIds" + index;
                     var paramName = "@ArtistIds" + index;
 
 
-                    clauses.Add("(guid in (select itemid from itemvalues where CleanValue = (select CleanName from TypedBaseItems where guid=" + paramName + ") and Type<=1))");
+                    clauses.Add("(guid in (select itemid from ItemValues where CleanValue = (select CleanName from TypedBaseItems where guid=" + paramName + ") and Type<=1))");
                     if (statement != null)
                     if (statement != null)
                     {
                     {
                         statement.TryBind(paramName, artistId);
                         statement.TryBind(paramName, artistId);
@@ -3868,7 +3868,7 @@ namespace Emby.Server.Implementations.Data
                 {
                 {
                     var paramName = "@ArtistIds" + index;
                     var paramName = "@ArtistIds" + index;
 
 
-                    clauses.Add("(guid in (select itemid from itemvalues where CleanValue = (select CleanName from TypedBaseItems where guid=" + paramName + ") and Type=1))");
+                    clauses.Add("(guid in (select itemid from ItemValues where CleanValue = (select CleanName from TypedBaseItems where guid=" + paramName + ") and Type=1))");
                     if (statement != null)
                     if (statement != null)
                     {
                     {
                         statement.TryBind(paramName, artistId);
                         statement.TryBind(paramName, artistId);
@@ -3889,7 +3889,7 @@ namespace Emby.Server.Implementations.Data
                 {
                 {
                     var paramName = "@ArtistIds" + index;
                     var paramName = "@ArtistIds" + index;
 
 
-                    clauses.Add("((select CleanName from TypedBaseItems where guid=" + paramName + ") in (select CleanValue from itemvalues where ItemId=Guid and Type=0) AND (select CleanName from TypedBaseItems where guid=" + paramName + ") not in (select CleanValue from itemvalues where ItemId=Guid and Type=1))");
+                    clauses.Add("((select CleanName from TypedBaseItems where guid=" + paramName + ") in (select CleanValue from ItemValues where ItemId=Guid and Type=0) AND (select CleanName from TypedBaseItems where guid=" + paramName + ") not in (select CleanValue from ItemValues where ItemId=Guid and Type=1))");
                     if (statement != null)
                     if (statement != null)
                     {
                     {
                         statement.TryBind(paramName, artistId);
                         statement.TryBind(paramName, artistId);
@@ -3931,7 +3931,7 @@ namespace Emby.Server.Implementations.Data
                 {
                 {
                     var paramName = "@ExcludeArtistId" + index;
                     var paramName = "@ExcludeArtistId" + index;
 
 
-                    clauses.Add("(guid not in (select itemid from itemvalues where CleanValue = (select CleanName from TypedBaseItems where guid=" + paramName + ") and Type<=1))");
+                    clauses.Add("(guid not in (select itemid from ItemValues where CleanValue = (select CleanName from TypedBaseItems where guid=" + paramName + ") and Type<=1))");
                     if (statement != null)
                     if (statement != null)
                     {
                     {
                         statement.TryBind(paramName, artistId);
                         statement.TryBind(paramName, artistId);
@@ -3952,7 +3952,7 @@ namespace Emby.Server.Implementations.Data
                 {
                 {
                     var paramName = "@GenreId" + index;
                     var paramName = "@GenreId" + index;
 
 
-                    clauses.Add("(guid in (select itemid from itemvalues where CleanValue = (select CleanName from TypedBaseItems where guid=" + paramName + ") and Type=2))");
+                    clauses.Add("(guid in (select itemid from ItemValues where CleanValue = (select CleanName from TypedBaseItems where guid=" + paramName + ") and Type=2))");
                     if (statement != null)
                     if (statement != null)
                     {
                     {
                         statement.TryBind(paramName, genreId);
                         statement.TryBind(paramName, genreId);
@@ -3971,7 +3971,7 @@ namespace Emby.Server.Implementations.Data
                 var index = 0;
                 var index = 0;
                 foreach (var item in query.Genres)
                 foreach (var item in query.Genres)
                 {
                 {
-                    clauses.Add("@Genre" + index + " in (select CleanValue from itemvalues where ItemId=Guid and Type=2)");
+                    clauses.Add("@Genre" + index + " in (select CleanValue from ItemValues where ItemId=Guid and Type=2)");
                     if (statement != null)
                     if (statement != null)
                     {
                     {
                         statement.TryBind("@Genre" + index, GetCleanValue(item));
                         statement.TryBind("@Genre" + index, GetCleanValue(item));
@@ -3990,7 +3990,7 @@ namespace Emby.Server.Implementations.Data
                 var index = 0;
                 var index = 0;
                 foreach (var item in tags)
                 foreach (var item in tags)
                 {
                 {
-                    clauses.Add("@Tag" + index + " in (select CleanValue from itemvalues where ItemId=Guid and Type=4)");
+                    clauses.Add("@Tag" + index + " in (select CleanValue from ItemValues where ItemId=Guid and Type=4)");
                     if (statement != null)
                     if (statement != null)
                     {
                     {
                         statement.TryBind("@Tag" + index, GetCleanValue(item));
                         statement.TryBind("@Tag" + index, GetCleanValue(item));
@@ -4009,7 +4009,7 @@ namespace Emby.Server.Implementations.Data
                 var index = 0;
                 var index = 0;
                 foreach (var item in excludeTags)
                 foreach (var item in excludeTags)
                 {
                 {
-                    clauses.Add("@ExcludeTag" + index + " not in (select CleanValue from itemvalues where ItemId=Guid and Type=4)");
+                    clauses.Add("@ExcludeTag" + index + " not in (select CleanValue from ItemValues where ItemId=Guid and Type=4)");
                     if (statement != null)
                     if (statement != null)
                     {
                     {
                         statement.TryBind("@ExcludeTag" + index, GetCleanValue(item));
                         statement.TryBind("@ExcludeTag" + index, GetCleanValue(item));
@@ -4030,7 +4030,7 @@ namespace Emby.Server.Implementations.Data
                 {
                 {
                     var paramName = "@StudioId" + index;
                     var paramName = "@StudioId" + index;
 
 
-                    clauses.Add("(guid in (select itemid from itemvalues where CleanValue = (select CleanName from TypedBaseItems where guid=" + paramName + ") and Type=3))");
+                    clauses.Add("(guid in (select itemid from ItemValues where CleanValue = (select CleanName from TypedBaseItems where guid=" + paramName + ") and Type=3))");
 
 
                     if (statement != null)
                     if (statement != null)
                     {
                     {
@@ -4509,7 +4509,7 @@ namespace Emby.Server.Implementations.Data
                 {
                 {
                     int index = 0;
                     int index = 0;
                     string excludedTags = string.Join(',', query.ExcludeInheritedTags.Select(_ => paramName + index++));
                     string excludedTags = string.Join(',', query.ExcludeInheritedTags.Select(_ => paramName + index++));
-                    whereClauses.Add("((select CleanValue from itemvalues where ItemId=Guid and Type=6 and cleanvalue in (" + excludedTags + ")) is null)");
+                    whereClauses.Add("((select CleanValue from ItemValues where ItemId=Guid and Type=6 and cleanvalue in (" + excludedTags + ")) is null)");
                 }
                 }
                 else
                 else
                 {
                 {
@@ -4744,11 +4744,11 @@ namespace Emby.Server.Implementations.Data
                 ';',
                 ';',
                 new string[]
                 new string[]
                 {
                 {
-                    "delete from itemvalues where type = 6",
+                    "delete from ItemValues where type = 6",
 
 
-                    "insert into itemvalues (ItemId, Type, Value, CleanValue)  select ItemId, 6, Value, CleanValue from ItemValues where Type=4",
+                    "insert into ItemValues (ItemId, Type, Value, CleanValue)  select ItemId, 6, Value, CleanValue from ItemValues where Type=4",
 
 
-                    @"insert into itemvalues (ItemId, Type, Value, CleanValue) select AncestorIds.itemid, 6, ItemValues.Value, ItemValues.CleanValue
+                    @"insert into ItemValues (ItemId, Type, Value, CleanValue) select AncestorIds.itemid, 6, ItemValues.Value, ItemValues.CleanValue
 FROM AncestorIds
 FROM AncestorIds
 LEFT JOIN ItemValues ON (AncestorIds.AncestorId = ItemValues.ItemId)
 LEFT JOIN ItemValues ON (AncestorIds.AncestorId = ItemValues.ItemId)
 where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type = 4 "
 where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type = 4 "
@@ -4816,10 +4816,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
 
 
         public List<string> GetPeopleNames(InternalPeopleQuery query)
         public List<string> GetPeopleNames(InternalPeopleQuery query)
         {
         {
-            if (query == null)
-            {
-                throw new ArgumentNullException(nameof(query));
-            }
+            ArgumentNullException.ThrowIfNull(query);
 
 
             CheckDisposed();
             CheckDisposed();
 
 
@@ -4859,10 +4856,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
 
 
         public List<PersonInfo> GetPeople(InternalPeopleQuery query)
         public List<PersonInfo> GetPeople(InternalPeopleQuery query)
         {
         {
-            if (query == null)
-            {
-                throw new ArgumentNullException(nameof(query));
-            }
+            ArgumentNullException.ThrowIfNull(query);
 
 
             CheckDisposed();
             CheckDisposed();
 
 
@@ -4913,6 +4907,7 @@ SELECT key FROM UserDatas WHERE isFavorite=@IsFavorite AND userId=@UserId)
 AND Type = @InternalPersonType)");
 AND Type = @InternalPersonType)");
                 statement?.TryBind("@IsFavorite", query.IsFavorite.Value);
                 statement?.TryBind("@IsFavorite", query.IsFavorite.Value);
                 statement?.TryBind("@InternalPersonType", typeof(Person).FullName);
                 statement?.TryBind("@InternalPersonType", typeof(Person).FullName);
+                statement?.TryBind("@UserId", query.User.InternalId);
             }
             }
 
 
             if (!query.ItemId.Equals(default))
             if (!query.ItemId.Equals(default))
@@ -4967,11 +4962,6 @@ AND Type = @InternalPersonType)");
                 statement?.TryBind("@NameContains", "%" + query.NameContains + "%");
                 statement?.TryBind("@NameContains", "%" + query.NameContains + "%");
             }
             }
 
 
-            if (query.User != null)
-            {
-                statement?.TryBind("@UserId", query.User.InternalId);
-            }
-
             return whereClauses;
             return whereClauses;
         }
         }
 
 
@@ -4982,10 +4972,7 @@ AND Type = @InternalPersonType)");
                 throw new ArgumentNullException(nameof(itemId));
                 throw new ArgumentNullException(nameof(itemId));
             }
             }
 
 
-            if (ancestorIds == null)
-            {
-                throw new ArgumentNullException(nameof(ancestorIds));
-            }
+            ArgumentNullException.ThrowIfNull(ancestorIds);
 
 
             CheckDisposed();
             CheckDisposed();
 
 
@@ -5158,10 +5145,7 @@ AND Type = @InternalPersonType)");
 
 
         private QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetItemValues(InternalItemsQuery query, int[] itemValueTypes, string returnType)
         private QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetItemValues(InternalItemsQuery query, int[] itemValueTypes, string returnType)
         {
         {
-            if (query == null)
-            {
-                throw new ArgumentNullException(nameof(query));
-            }
+            ArgumentNullException.ThrowIfNull(query);
 
 
             if (!query.Limit.HasValue)
             if (!query.Limit.HasValue)
             {
             {
@@ -5514,10 +5498,7 @@ AND Type = @InternalPersonType)");
                 throw new ArgumentNullException(nameof(itemId));
                 throw new ArgumentNullException(nameof(itemId));
             }
             }
 
 
-            if (values == null)
-            {
-                throw new ArgumentNullException(nameof(values));
-            }
+            ArgumentNullException.ThrowIfNull(values);
 
 
             CheckDisposed();
             CheckDisposed();
 
 
@@ -5590,10 +5571,7 @@ AND Type = @InternalPersonType)");
                 throw new ArgumentNullException(nameof(itemId));
                 throw new ArgumentNullException(nameof(itemId));
             }
             }
 
 
-            if (people == null)
-            {
-                throw new ArgumentNullException(nameof(people));
-            }
+            ArgumentNullException.ThrowIfNull(people);
 
 
             CheckDisposed();
             CheckDisposed();
 
 
@@ -5693,10 +5671,7 @@ AND Type = @InternalPersonType)");
         {
         {
             CheckDisposed();
             CheckDisposed();
 
 
-            if (query == null)
-            {
-                throw new ArgumentNullException(nameof(query));
-            }
+            ArgumentNullException.ThrowIfNull(query);
 
 
             var cmdText = _mediaStreamSaveColumnsSelectQuery;
             var cmdText = _mediaStreamSaveColumnsSelectQuery;
 
 
@@ -5749,10 +5724,7 @@ AND Type = @InternalPersonType)");
                 throw new ArgumentNullException(nameof(id));
                 throw new ArgumentNullException(nameof(id));
             }
             }
 
 
-            if (streams == null)
-            {
-                throw new ArgumentNullException(nameof(streams));
-            }
+            ArgumentNullException.ThrowIfNull(streams);
 
 
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 
@@ -5763,7 +5735,7 @@ AND Type = @InternalPersonType)");
                 {
                 {
                     var itemIdBlob = id.ToByteArray();
                     var itemIdBlob = id.ToByteArray();
 
 
-                    // First delete chapters
+                    // Delete existing mediastreams
                     db.Execute("delete from mediastreams where ItemId=@ItemId", itemIdBlob);
                     db.Execute("delete from mediastreams where ItemId=@ItemId", itemIdBlob);
 
 
                     InsertMediaStreams(itemIdBlob, streams, db);
                     InsertMediaStreams(itemIdBlob, streams, db);
@@ -5855,6 +5827,15 @@ AND Type = @InternalPersonType)");
                         statement.TryBind("@ColorPrimaries" + index, stream.ColorPrimaries);
                         statement.TryBind("@ColorPrimaries" + index, stream.ColorPrimaries);
                         statement.TryBind("@ColorSpace" + index, stream.ColorSpace);
                         statement.TryBind("@ColorSpace" + index, stream.ColorSpace);
                         statement.TryBind("@ColorTransfer" + index, stream.ColorTransfer);
                         statement.TryBind("@ColorTransfer" + index, stream.ColorTransfer);
+
+                        statement.TryBind("@DvVersionMajor" + index, stream.DvVersionMajor);
+                        statement.TryBind("@DvVersionMinor" + index, stream.DvVersionMinor);
+                        statement.TryBind("@DvProfile" + index, stream.DvProfile);
+                        statement.TryBind("@DvLevel" + index, stream.DvLevel);
+                        statement.TryBind("@RpuPresentFlag" + index, stream.RpuPresentFlag);
+                        statement.TryBind("@ElPresentFlag" + index, stream.ElPresentFlag);
+                        statement.TryBind("@BlPresentFlag" + index, stream.BlPresentFlag);
+                        statement.TryBind("@DvBlSignalCompatibilityId" + index, stream.DvBlSignalCompatibilityId);
                     }
                     }
 
 
                     statement.Reset();
                     statement.Reset();
@@ -5867,10 +5848,10 @@ AND Type = @InternalPersonType)");
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Gets the chapter.
+        /// Gets the media stream.
         /// </summary>
         /// </summary>
         /// <param name="reader">The reader.</param>
         /// <param name="reader">The reader.</param>
-        /// <returns>ChapterInfo.</returns>
+        /// <returns>MediaStream.</returns>
         private MediaStream GetMediaStream(IReadOnlyList<ResultSetValue> reader)
         private MediaStream GetMediaStream(IReadOnlyList<ResultSetValue> reader)
         {
         {
             var item = new MediaStream
             var item = new MediaStream
@@ -6026,6 +6007,46 @@ AND Type = @InternalPersonType)");
                 item.ColorTransfer = colorTransfer;
                 item.ColorTransfer = colorTransfer;
             }
             }
 
 
+            if (reader.TryGetInt32(35, out var dvVersionMajor))
+            {
+                item.DvVersionMajor = dvVersionMajor;
+            }
+
+            if (reader.TryGetInt32(36, out var dvVersionMinor))
+            {
+                item.DvVersionMinor = dvVersionMinor;
+            }
+
+            if (reader.TryGetInt32(37, out var dvProfile))
+            {
+                item.DvProfile = dvProfile;
+            }
+
+            if (reader.TryGetInt32(38, out var dvLevel))
+            {
+                item.DvLevel = dvLevel;
+            }
+
+            if (reader.TryGetInt32(39, out var rpuPresentFlag))
+            {
+                item.RpuPresentFlag = rpuPresentFlag;
+            }
+
+            if (reader.TryGetInt32(40, out var elPresentFlag))
+            {
+                item.ElPresentFlag = elPresentFlag;
+            }
+
+            if (reader.TryGetInt32(41, out var blPresentFlag))
+            {
+                item.BlPresentFlag = blPresentFlag;
+            }
+
+            if (reader.TryGetInt32(42, out var dvBlSignalCompatibilityId))
+            {
+                item.DvBlSignalCompatibilityId = dvBlSignalCompatibilityId;
+            }
+
             if (item.Type == MediaStreamType.Subtitle)
             if (item.Type == MediaStreamType.Subtitle)
             {
             {
                 item.LocalizedUndefined = _localization.GetLocalizedString("Undefined");
                 item.LocalizedUndefined = _localization.GetLocalizedString("Undefined");
@@ -6041,10 +6062,7 @@ AND Type = @InternalPersonType)");
         {
         {
             CheckDisposed();
             CheckDisposed();
 
 
-            if (query == null)
-            {
-                throw new ArgumentNullException(nameof(query));
-            }
+            ArgumentNullException.ThrowIfNull(query);
 
 
             var cmdText = _mediaAttachmentSaveColumnsSelectQuery;
             var cmdText = _mediaAttachmentSaveColumnsSelectQuery;
 
 
@@ -6086,10 +6104,7 @@ AND Type = @InternalPersonType)");
                 throw new ArgumentException("Guid can't be empty.", nameof(id));
                 throw new ArgumentException("Guid can't be empty.", nameof(id));
             }
             }
 
 
-            if (attachments == null)
-            {
-                throw new ArgumentNullException(nameof(attachments));
-            }
+            ArgumentNullException.ThrowIfNull(attachments);
 
 
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 

+ 3 - 12
Emby.Server.Implementations/Data/SqliteUserDataRepository.cs

@@ -133,10 +133,7 @@ namespace Emby.Server.Implementations.Data
         /// <inheritdoc />
         /// <inheritdoc />
         public void SaveUserData(long userId, string key, UserItemData userData, CancellationToken cancellationToken)
         public void SaveUserData(long userId, string key, UserItemData userData, CancellationToken cancellationToken)
         {
         {
-            if (userData == null)
-            {
-                throw new ArgumentNullException(nameof(userData));
-            }
+            ArgumentNullException.ThrowIfNull(userData);
 
 
             if (userId <= 0)
             if (userId <= 0)
             {
             {
@@ -154,10 +151,7 @@ namespace Emby.Server.Implementations.Data
         /// <inheritdoc />
         /// <inheritdoc />
         public void SaveAllUserData(long userId, UserItemData[] userData, CancellationToken cancellationToken)
         public void SaveAllUserData(long userId, UserItemData[] userData, CancellationToken cancellationToken)
         {
         {
-            if (userData == null)
-            {
-                throw new ArgumentNullException(nameof(userData));
-            }
+            ArgumentNullException.ThrowIfNull(userData);
 
 
             if (userId <= 0)
             if (userId <= 0)
             {
             {
@@ -304,10 +298,7 @@ namespace Emby.Server.Implementations.Data
 
 
         public UserItemData GetUserData(long userId, List<string> keys)
         public UserItemData GetUserData(long userId, List<string> keys)
         {
         {
-            if (keys == null)
-            {
-                throw new ArgumentNullException(nameof(keys));
-            }
+            ArgumentNullException.ThrowIfNull(keys);
 
 
             if (keys.Count == 0)
             if (keys.Count == 0)
             {
             {

+ 0 - 0
Emby.Server.Implementations/Data/SynchronouseMode.cs → Emby.Server.Implementations/Data/SynchronousMode.cs


+ 7 - 3
Emby.Server.Implementations/Dto/DtoService.cs

@@ -182,7 +182,7 @@ namespace Emby.Server.Implementations.Dto
 
 
             if (options.ContainsField(ItemFields.People))
             if (options.ContainsField(ItemFields.People))
             {
             {
-                AttachPeople(dto, item);
+                AttachPeople(dto, item, user);
             }
             }
 
 
             if (options.ContainsField(ItemFields.PrimaryImageAspectRatio))
             if (options.ContainsField(ItemFields.PrimaryImageAspectRatio))
@@ -503,7 +503,8 @@ namespace Emby.Server.Implementations.Dto
         /// </summary>
         /// </summary>
         /// <param name="dto">The dto.</param>
         /// <param name="dto">The dto.</param>
         /// <param name="item">The item.</param>
         /// <param name="item">The item.</param>
-        private void AttachPeople(BaseItemDto dto, BaseItem item)
+        /// <param name="user">The requesting user.</param>
+        private void AttachPeople(BaseItemDto dto, BaseItem item, User user = null)
         {
         {
             // Ordering by person type to ensure actors and artists are at the front.
             // Ordering by person type to ensure actors and artists are at the front.
             // This is taking advantage of the fact that they both begin with A
             // This is taking advantage of the fact that they both begin with A
@@ -560,6 +561,9 @@ namespace Emby.Server.Implementations.Dto
                         return null;
                         return null;
                     }
                     }
                 }).Where(i => i != null)
                 }).Where(i => i != null)
+                .Where(i => user == null ?
+                    true :
+                    i.IsVisible(user))
                 .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
                 .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
                 .Select(x => x.First())
                 .Select(x => x.First())
                 .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
                 .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
@@ -1094,7 +1098,7 @@ namespace Emby.Server.Implementations.Dto
             {
             {
                 if (item is IHasTrailers hasTrailers)
                 if (item is IHasTrailers hasTrailers)
                 {
                 {
-                    dto.LocalTrailerCount = hasTrailers.GetTrailerCount();
+                    dto.LocalTrailerCount = hasTrailers.LocalTrailers.Count;
                 }
                 }
                 else
                 else
                 {
                 {

+ 6 - 6
Emby.Server.Implementations/Emby.Server.Implementations.csproj

@@ -24,15 +24,15 @@
 
 
   <ItemGroup>
   <ItemGroup>
     <PackageReference Include="DiscUtils.Udf" Version="0.16.13" />
     <PackageReference Include="DiscUtils.Udf" Version="0.16.13" />
-    <PackageReference Include="Jellyfin.XmlTv" Version="10.6.2" />
+    <PackageReference Include="Jellyfin.XmlTv" Version="10.8.0" />
     <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
     <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
     <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
     <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
     <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
     <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
     <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />
     <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />
-    <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.3" />
-    <PackageReference Include="Mono.Nat" Version="3.0.2" />
-    <PackageReference Include="prometheus-net.DotNetRuntime" Version="4.2.3" />
-    <PackageReference Include="sharpcompress" Version="0.30.1" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.9" />
+    <PackageReference Include="Mono.Nat" Version="3.0.3" />
+    <PackageReference Include="prometheus-net.DotNetRuntime" Version="4.2.4" />
+    <PackageReference Include="sharpcompress" Version="0.32.2" />
     <PackageReference Include="SQLitePCL.pretty.netstandard" Version="3.1.0" />
     <PackageReference Include="SQLitePCL.pretty.netstandard" Version="3.1.0" />
     <PackageReference Include="DotNet.Glob" Version="3.1.3" />
     <PackageReference Include="DotNet.Glob" Version="3.1.3" />
   </ItemGroup>
   </ItemGroup>
@@ -60,7 +60,7 @@
       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
     </PackageReference>
     </PackageReference>
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
-    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406" PrivateAssets="All" />
+    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
   </ItemGroup>
   </ItemGroup>
 
 

+ 0 - 60
Emby.Server.Implementations/HttpServer/Security/SessionContext.cs

@@ -1,60 +0,0 @@
-#pragma warning disable CS1591
-
-using System;
-using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Session;
-using Microsoft.AspNetCore.Http;
-
-namespace Emby.Server.Implementations.HttpServer.Security
-{
-    public class SessionContext : ISessionContext
-    {
-        private readonly IUserManager _userManager;
-        private readonly ISessionManager _sessionManager;
-        private readonly IAuthorizationContext _authContext;
-
-        public SessionContext(IUserManager userManager, IAuthorizationContext authContext, ISessionManager sessionManager)
-        {
-            _userManager = userManager;
-            _authContext = authContext;
-            _sessionManager = sessionManager;
-        }
-
-        public async Task<SessionInfo> GetSession(HttpContext requestContext)
-        {
-            var authorization = await _authContext.GetAuthorizationInfo(requestContext).ConfigureAwait(false);
-
-            var user = authorization.User;
-            return await _sessionManager.LogSessionActivity(
-                authorization.Client,
-                authorization.Version,
-                authorization.DeviceId,
-                authorization.Device,
-                requestContext.GetNormalizedRemoteIp().ToString(),
-                user).ConfigureAwait(false);
-        }
-
-        public Task<SessionInfo> GetSession(object requestContext)
-        {
-            return GetSession((HttpContext)requestContext);
-        }
-
-        public async Task<User?> GetUser(HttpContext requestContext)
-        {
-            var session = await GetSession(requestContext).ConfigureAwait(false);
-
-            return session.UserId.Equals(default)
-                ? null
-                : _userManager.GetUserById(session.UserId);
-        }
-
-        public Task<User?> GetUser(object requestContext)
-        {
-            return GetUser(((HttpRequest)requestContext).HttpContext);
-        }
-    }
-}

+ 32 - 2
Emby.Server.Implementations/HttpServer/WebSocketConnection.cs

@@ -11,7 +11,6 @@ using Jellyfin.Extensions.Json;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.Net;
 using MediaBrowser.Model.Net;
 using MediaBrowser.Model.Session;
 using MediaBrowser.Model.Session;
-using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Logging;
 
 
 namespace Emby.Server.Implementations.HttpServer
 namespace Emby.Server.Implementations.HttpServer
@@ -19,7 +18,7 @@ namespace Emby.Server.Implementations.HttpServer
     /// <summary>
     /// <summary>
     /// Class WebSocketConnection.
     /// Class WebSocketConnection.
     /// </summary>
     /// </summary>
-    public class WebSocketConnection : IWebSocketConnection, IDisposable
+    public class WebSocketConnection : IWebSocketConnection
     {
     {
         /// <summary>
         /// <summary>
         /// The logger.
         /// The logger.
@@ -36,6 +35,8 @@ namespace Emby.Server.Implementations.HttpServer
         /// </summary>
         /// </summary>
         private readonly WebSocket _socket;
         private readonly WebSocket _socket;
 
 
+        private bool _disposed = false;
+
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
         /// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
         /// </summary>
         /// </summary>
@@ -244,10 +245,39 @@ namespace Emby.Server.Implementations.HttpServer
         /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
         /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
         protected virtual void Dispose(bool dispose)
         protected virtual void Dispose(bool dispose)
         {
         {
+            if (_disposed)
+            {
+                return;
+            }
+
             if (dispose)
             if (dispose)
             {
             {
                 _socket.Dispose();
                 _socket.Dispose();
             }
             }
+
+            _disposed = true;
+        }
+
+        /// <inheritdoc />
+        public async ValueTask DisposeAsync()
+        {
+            await DisposeAsyncCore().ConfigureAwait(false);
+            Dispose(false);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Used to perform asynchronous cleanup of managed resources or for cascading calls to <see cref="DisposeAsync"/>.
+        /// </summary>
+        /// <returns>A ValueTask.</returns>
+        protected virtual async ValueTask DisposeAsyncCore()
+        {
+            if (_socket.State == WebSocketState.Open)
+            {
+                await _socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "System Shutdown", CancellationToken.None).ConfigureAwait(false);
+            }
+
+            _socket.Dispose();
         }
         }
     }
     }
 }
 }

+ 4 - 0
Emby.Server.Implementations/IO/ManagedFileSystem.cs

@@ -262,6 +262,10 @@ namespace Emby.Server.Implementations.IO
                             _logger.LogError(ex, "Reading the file size of the symlink at {Path} failed. Marking the file as not existing.", fileInfo.FullName);
                             _logger.LogError(ex, "Reading the file size of the symlink at {Path} failed. Marking the file as not existing.", fileInfo.FullName);
                             result.Exists = false;
                             result.Exists = false;
                         }
                         }
+                        catch (UnauthorizedAccessException ex)
+                        {
+                            _logger.LogError(ex, "Reading the file at {Path} failed due to a permissions exception.", fileInfo.FullName);
+                        }
                     }
                     }
                 }
                 }
 
 

+ 1 - 0
Emby.Server.Implementations/Images/DynamicImageProvider.cs

@@ -93,6 +93,7 @@ namespace Emby.Server.Implementations.Images
                 returnItems.Shuffle();
                 returnItems.Shuffle();
                 return returnItems;
                 return returnItems;
             }
             }
+
             returnItems = items
             returnItems = items
                 .Where(i => i.HasImage(ImageType.Primary))
                 .Where(i => i.HasImage(ImageType.Primary))
                 .ToList();
                 .ToList();

+ 35 - 46
Emby.Server.Implementations/Library/LibraryManager.cs

@@ -46,7 +46,6 @@ using MediaBrowser.Model.Library;
 using MediaBrowser.Model.Querying;
 using MediaBrowser.Model.Querying;
 using MediaBrowser.Model.Tasks;
 using MediaBrowser.Model.Tasks;
 using Microsoft.Extensions.Caching.Memory;
 using Microsoft.Extensions.Caching.Memory;
-using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Logging;
 using Episode = MediaBrowser.Controller.Entities.TV.Episode;
 using Episode = MediaBrowser.Controller.Entities.TV.Episode;
 using EpisodeInfo = Emby.Naming.TV.EpisodeInfo;
 using EpisodeInfo = Emby.Naming.TV.EpisodeInfo;
@@ -282,10 +281,7 @@ namespace Emby.Server.Implementations.Library
 
 
         public void RegisterItem(BaseItem item)
         public void RegisterItem(BaseItem item)
         {
         {
-            if (item == null)
-            {
-                throw new ArgumentNullException(nameof(item));
-            }
+            ArgumentNullException.ThrowIfNull(item);
 
 
             if (item is IItemByName)
             if (item is IItemByName)
             {
             {
@@ -312,10 +308,7 @@ namespace Emby.Server.Implementations.Library
 
 
         public void DeleteItem(BaseItem item, DeleteOptions options, bool notifyParentItem)
         public void DeleteItem(BaseItem item, DeleteOptions options, bool notifyParentItem)
         {
         {
-            if (item == null)
-            {
-                throw new ArgumentNullException(nameof(item));
-            }
+            ArgumentNullException.ThrowIfNull(item);
 
 
             var parent = item.GetOwner() ?? item.GetParent();
             var parent = item.GetOwner() ?? item.GetParent();
 
 
@@ -324,10 +317,7 @@ namespace Emby.Server.Implementations.Library
 
 
         public void DeleteItem(BaseItem item, DeleteOptions options, BaseItem parent, bool notifyParentItem)
         public void DeleteItem(BaseItem item, DeleteOptions options, BaseItem parent, bool notifyParentItem)
         {
         {
-            if (item == null)
-            {
-                throw new ArgumentNullException(nameof(item));
-            }
+            ArgumentNullException.ThrowIfNull(item);
 
 
             if (item.SourceType == SourceType.Channel)
             if (item.SourceType == SourceType.Channel)
             {
             {
@@ -510,10 +500,7 @@ namespace Emby.Server.Implementations.Library
                 throw new ArgumentNullException(nameof(key));
                 throw new ArgumentNullException(nameof(key));
             }
             }
 
 
-            if (type == null)
-            {
-                throw new ArgumentNullException(nameof(type));
-            }
+            ArgumentNullException.ThrowIfNull(type);
 
 
             string programDataPath = _configurationManager.ApplicationPaths.ProgramDataPath;
             string programDataPath = _configurationManager.ApplicationPaths.ProgramDataPath;
             if (key.StartsWith(programDataPath, StringComparison.Ordinal))
             if (key.StartsWith(programDataPath, StringComparison.Ordinal))
@@ -545,10 +532,7 @@ namespace Emby.Server.Implementations.Library
             string collectionType = null,
             string collectionType = null,
             LibraryOptions libraryOptions = null)
             LibraryOptions libraryOptions = null)
         {
         {
-            if (fileInfo == null)
-            {
-                throw new ArgumentNullException(nameof(fileInfo));
-            }
+            ArgumentNullException.ThrowIfNull(fileInfo);
 
 
             var fullPath = fileInfo.FullName;
             var fullPath = fileInfo.FullName;
 
 
@@ -1855,12 +1839,11 @@ namespace Emby.Server.Implementations.Library
         /// <inheritdoc />
         /// <inheritdoc />
         public async Task UpdateImagesAsync(BaseItem item, bool forceUpdate = false)
         public async Task UpdateImagesAsync(BaseItem item, bool forceUpdate = false)
         {
         {
-            if (item == null)
-            {
-                throw new ArgumentNullException(nameof(item));
-            }
+            ArgumentNullException.ThrowIfNull(item);
 
 
-            var outdated = forceUpdate ? item.ImageInfos.Where(i => i.Path != null).ToArray() : item.ImageInfos.Where(ImageNeedsRefresh).ToArray();
+            var outdated = forceUpdate
+                ? item.ImageInfos.Where(i => i.Path != null).ToArray()
+                : item.ImageInfos.Where(ImageNeedsRefresh).ToArray();
             // Skip image processing if current or live tv source
             // Skip image processing if current or live tv source
             if (outdated.Length == 0 || item.SourceType != SourceType.Library)
             if (outdated.Length == 0 || item.SourceType != SourceType.Library)
             {
             {
@@ -1883,7 +1866,7 @@ namespace Emby.Server.Implementations.Library
                         _logger.LogWarning("Cannot get image index for {ImagePath}", img.Path);
                         _logger.LogWarning("Cannot get image index for {ImagePath}", img.Path);
                         continue;
                         continue;
                     }
                     }
-                    catch (Exception ex) when (ex is InvalidOperationException || ex is IOException)
+                    catch (Exception ex) when (ex is InvalidOperationException or IOException)
                     {
                     {
                         _logger.LogWarning(ex, "Cannot fetch image from {ImagePath}", img.Path);
                         _logger.LogWarning(ex, "Cannot fetch image from {ImagePath}", img.Path);
                         continue;
                         continue;
@@ -1895,23 +1878,24 @@ namespace Emby.Server.Implementations.Library
                     }
                     }
                 }
                 }
 
 
+                ImageDimensions size;
                 try
                 try
                 {
                 {
-                    ImageDimensions size = _imageProcessor.GetImageDimensions(item, image);
+                    size = _imageProcessor.GetImageDimensions(item, image);
                     image.Width = size.Width;
                     image.Width = size.Width;
                     image.Height = size.Height;
                     image.Height = size.Height;
                 }
                 }
                 catch (Exception ex)
                 catch (Exception ex)
                 {
                 {
                     _logger.LogError(ex, "Cannot get image dimensions for {ImagePath}", image.Path);
                     _logger.LogError(ex, "Cannot get image dimensions for {ImagePath}", image.Path);
+                    size = new ImageDimensions(0, 0);
                     image.Width = 0;
                     image.Width = 0;
                     image.Height = 0;
                     image.Height = 0;
-                    continue;
                 }
                 }
 
 
                 try
                 try
                 {
                 {
-                    image.BlurHash = _imageProcessor.GetImageBlurHash(image.Path);
+                    image.BlurHash = _imageProcessor.GetImageBlurHash(image.Path, size);
                 }
                 }
                 catch (Exception ex)
                 catch (Exception ex)
                 {
                 {
@@ -2294,10 +2278,7 @@ namespace Emby.Server.Implementations.Library
             string viewType,
             string viewType,
             string sortName)
             string sortName)
         {
         {
-            if (parent == null)
-            {
-                throw new ArgumentNullException(nameof(parent));
-            }
+            ArgumentNullException.ThrowIfNull(parent);
 
 
             var name = parent.Name;
             var name = parent.Name;
             var parentId = parent.Id;
             var parentId = parent.Id;
@@ -2450,6 +2431,12 @@ namespace Emby.Server.Implementations.Library
             return RootFolder;
             return RootFolder;
         }
         }
 
 
+        /// <inheritdoc />
+        public void QueueLibraryScan()
+        {
+            _taskManager.QueueScheduledTask<RefreshMediaLibraryTask>();
+        }
+
         /// <inheritdoc />
         /// <inheritdoc />
         public int? GetSeasonNumberFromPath(string path)
         public int? GetSeasonNumberFromPath(string path)
             => SeasonPathParser.Parse(path, true, true).SeasonNumber;
             => SeasonPathParser.Parse(path, true, true).SeasonNumber;
@@ -2520,7 +2507,7 @@ namespace Emby.Server.Implementations.Library
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
-                _logger.LogError(ex, "Error reading the episode informations with ffprobe. Episode: {EpisodeInfo}", episodeInfo.Path);
+                _logger.LogError(ex, "Error reading the episode information with ffprobe. Episode: {EpisodeInfo}", episodeInfo.Path);
             }
             }
 
 
             var changed = false;
             var changed = false;
@@ -2757,7 +2744,8 @@ namespace Emby.Server.Implementations.Library
 
 
         public List<Person> GetPeopleItems(InternalPeopleQuery query)
         public List<Person> GetPeopleItems(InternalPeopleQuery query)
         {
         {
-            return _itemRepository.GetPeopleNames(query).Select(i =>
+            return _itemRepository.GetPeopleNames(query)
+            .Select(i =>
             {
             {
                 try
                 try
                 {
                 {
@@ -2768,7 +2756,12 @@ namespace Emby.Server.Implementations.Library
                     _logger.LogError(ex, "Error getting person");
                     _logger.LogError(ex, "Error getting person");
                     return null;
                     return null;
                 }
                 }
-            }).Where(i => i != null).ToList();
+            })
+            .Where(i => i != null)
+            .Where(i => query.User == null ?
+                true :
+                i.IsVisible(query.User))
+            .ToList();
         }
         }
 
 
         public List<string> GetPeopleNames(InternalPeopleQuery query)
         public List<string> GetPeopleNames(InternalPeopleQuery query)
@@ -2840,10 +2833,12 @@ namespace Emby.Server.Implementations.Library
 
 
             var existingNameCount = 1; // first numbered name will be 2
             var existingNameCount = 1; // first numbered name will be 2
             var virtualFolderPath = Path.Combine(rootFolderPath, name);
             var virtualFolderPath = Path.Combine(rootFolderPath, name);
+            var originalName = name;
             while (Directory.Exists(virtualFolderPath))
             while (Directory.Exists(virtualFolderPath))
             {
             {
                 existingNameCount++;
                 existingNameCount++;
-                virtualFolderPath = Path.Combine(rootFolderPath, name + " " + existingNameCount);
+                name = originalName + existingNameCount;
+                virtualFolderPath = Path.Combine(rootFolderPath, name);
             }
             }
 
 
             var mediaPathInfos = options.PathInfos;
             var mediaPathInfos = options.PathInfos;
@@ -2967,10 +2962,7 @@ namespace Emby.Server.Implementations.Library
 
 
         private void AddMediaPathInternal(string virtualFolderName, MediaPathInfo pathInfo, bool saveLibraryOptions)
         private void AddMediaPathInternal(string virtualFolderName, MediaPathInfo pathInfo, bool saveLibraryOptions)
         {
         {
-            if (pathInfo == null)
-            {
-                throw new ArgumentNullException(nameof(pathInfo));
-            }
+            ArgumentNullException.ThrowIfNull(pathInfo);
 
 
             var path = pathInfo.Path;
             var path = pathInfo.Path;
 
 
@@ -3017,10 +3009,7 @@ namespace Emby.Server.Implementations.Library
 
 
         public void UpdateMediaPath(string virtualFolderName, MediaPathInfo mediaPath)
         public void UpdateMediaPath(string virtualFolderName, MediaPathInfo mediaPath)
         {
         {
-            if (mediaPath == null)
-            {
-                throw new ArgumentNullException(nameof(mediaPath));
-            }
+            ArgumentNullException.ThrowIfNull(mediaPath);
 
 
             var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath;
             var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath;
             var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName);
             var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName);

+ 6 - 5
Emby.Server.Implementations/Library/MediaSourceManager.cs

@@ -151,7 +151,11 @@ namespace Emby.Server.Implementations.Library
         {
         {
             var mediaSources = GetStaticMediaSources(item, enablePathSubstitution, user);
             var mediaSources = GetStaticMediaSources(item, enablePathSubstitution, user);
 
 
-            if (allowMediaProbe && mediaSources[0].Type != MediaSourceType.Placeholder && !mediaSources[0].MediaStreams.Any(i => i.Type == MediaStreamType.Audio || i.Type == MediaStreamType.Video))
+            // If file is strm or main media stream is missing, force a metadata refresh with remote probing
+            if (allowMediaProbe && mediaSources[0].Type != MediaSourceType.Placeholder
+                && (item.Path.EndsWith(".strm", StringComparison.OrdinalIgnoreCase)
+                    || (item.MediaType == MediaType.Video && !mediaSources[0].MediaStreams.Any(i => i.Type == MediaStreamType.Video))
+                    || (item.MediaType == MediaType.Audio && !mediaSources[0].MediaStreams.Any(i => i.Type == MediaStreamType.Audio))))
             {
             {
                 await item.RefreshMetadata(
                 await item.RefreshMetadata(
                     new MetadataRefreshOptions(_directoryService)
                     new MetadataRefreshOptions(_directoryService)
@@ -318,10 +322,7 @@ namespace Emby.Server.Implementations.Library
 
 
         public List<MediaSourceInfo> GetStaticMediaSources(BaseItem item, bool enablePathSubstitution, User user = null)
         public List<MediaSourceInfo> GetStaticMediaSources(BaseItem item, bool enablePathSubstitution, User user = null)
         {
         {
-            if (item == null)
-            {
-                throw new ArgumentNullException(nameof(item));
-            }
+            ArgumentNullException.ThrowIfNull(item);
 
 
             var hasMediaSources = (IHasMediaSources)item;
             var hasMediaSources = (IHasMediaSources)item;
 
 

+ 2 - 2
Emby.Server.Implementations/Library/MediaStreamSelector.cs

@@ -13,11 +13,11 @@ namespace Emby.Server.Implementations.Library
     {
     {
         public static int? GetDefaultAudioStreamIndex(IReadOnlyList<MediaStream> streams, IReadOnlyList<string> preferredLanguages, bool preferDefaultTrack)
         public static int? GetDefaultAudioStreamIndex(IReadOnlyList<MediaStream> streams, IReadOnlyList<string> preferredLanguages, bool preferDefaultTrack)
         {
         {
-            var sortedStreams = GetSortedStreams(streams, MediaStreamType.Audio, preferredLanguages);
+            var sortedStreams = GetSortedStreams(streams, MediaStreamType.Audio, preferredLanguages).ToList();
 
 
             if (preferDefaultTrack)
             if (preferDefaultTrack)
             {
             {
-                var defaultStream = streams.FirstOrDefault(i => i.IsDefault);
+                var defaultStream = sortedStreams.FirstOrDefault(i => i.IsDefault);
 
 
                 if (defaultStream != null)
                 if (defaultStream != null)
                 {
                 {

+ 5 - 3
Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs

@@ -225,7 +225,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
 
 
             if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
             if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
             {
             {
-                return ResolveVideos<Episode>(parent, files, true, collectionType, true);
+                return ResolveVideos<Episode>(parent, files, false, collectionType, true);
             }
             }
 
 
             return null;
             return null;
@@ -387,7 +387,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
 
 
                 if (!string.IsNullOrEmpty(item.Path))
                 if (!string.IsNullOrEmpty(item.Path))
                 {
                 {
-                    // check for imdb id - we use full media path, as we can assume, that this will match in any use case (wither id in parent dir or in file name)
+                    // check for imdb id - we use full media path, as we can assume, that this will match in any use case (either id in parent dir or in file name)
                     var imdbid = item.Path.AsSpan().GetAttributeValue("imdbid");
                     var imdbid = item.Path.AsSpan().GetAttributeValue("imdbid");
 
 
                     if (!string.IsNullOrWhiteSpace(imdbid))
                     if (!string.IsNullOrWhiteSpace(imdbid))
@@ -464,7 +464,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
             var result = ResolveVideos<T>(parent, fileSystemEntries, SupportsMultiVersion, collectionType, parseName) ??
             var result = ResolveVideos<T>(parent, fileSystemEntries, SupportsMultiVersion, collectionType, parseName) ??
                 new MultiItemResolverResult();
                 new MultiItemResolverResult();
 
 
-            if (result.Items.Count == 1)
+            var isPhotosCollection = string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase)
+                                         || string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase);
+            if (!isPhotosCollection && result.Items.Count == 1)
             {
             {
                 var videoPath = result.Items[0].Path;
                 var videoPath = result.Items[0].Path;
                 var hasPhotos = photos.Any(i => !PhotoResolver.IsOwnedByResolvedMedia(videoPath, i.Name));
                 var hasPhotos = photos.Any(i => !PhotoResolver.IsOwnedByResolvedMedia(videoPath, i.Name));

+ 1 - 4
Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs

@@ -91,10 +91,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
 
 
         internal static bool IsImageFile(string path, IImageProcessor imageProcessor)
         internal static bool IsImageFile(string path, IImageProcessor imageProcessor)
         {
         {
-            if (path == null)
-            {
-                throw new ArgumentNullException(nameof(path));
-            }
+            ArgumentNullException.ThrowIfNull(path);
 
 
             var filename = Path.GetFileNameWithoutExtension(path);
             var filename = Path.GetFileNameWithoutExtension(path);
 
 

+ 1 - 1
Emby.Server.Implementations/Library/SearchEngine.cs

@@ -5,9 +5,9 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
-using Diacritics.Extensions;
 using Jellyfin.Data.Entities;
 using Jellyfin.Data.Entities;
 using Jellyfin.Data.Enums;
 using Jellyfin.Data.Enums;
+using Jellyfin.Extensions;
 using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Library;

+ 3 - 12
Emby.Server.Implementations/Library/UserDataManager.cs

@@ -53,15 +53,9 @@ namespace Emby.Server.Implementations.Library
 
 
         public void SaveUserData(User user, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken)
         public void SaveUserData(User user, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken)
         {
         {
-            if (userData == null)
-            {
-                throw new ArgumentNullException(nameof(userData));
-            }
+            ArgumentNullException.ThrowIfNull(userData);
 
 
-            if (item == null)
-            {
-                throw new ArgumentNullException(nameof(item));
-            }
+            ArgumentNullException.ThrowIfNull(item);
 
 
             cancellationToken.ThrowIfCancellationRequested();
             cancellationToken.ThrowIfCancellationRequested();
 
 
@@ -194,10 +188,7 @@ namespace Emby.Server.Implementations.Library
         /// <exception cref="ArgumentNullException"><paramref name="data"/> is <c>null</c>.</exception>
         /// <exception cref="ArgumentNullException"><paramref name="data"/> is <c>null</c>.</exception>
         private UserItemDataDto GetUserItemDataDto(UserItemData data)
         private UserItemDataDto GetUserItemDataDto(UserItemData data)
         {
         {
-            if (data == null)
-            {
-                throw new ArgumentNullException(nameof(data));
-            }
+            ArgumentNullException.ThrowIfNull(data);
 
 
             return new UserItemDataDto
             return new UserItemDataDto
             {
             {

+ 3 - 9
Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs

@@ -995,7 +995,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
                 }
                 }
             }
             }
 
 
-            throw new Exception("Tuner not found.");
+            throw new ResourceNotFoundException("Tuner not found.");
         }
         }
 
 
         public async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken)
         public async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken)
@@ -1223,10 +1223,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
 
 
         private async Task RecordStream(TimerInfo timer, DateTime recordingEndDate, ActiveRecordingInfo activeRecordingInfo)
         private async Task RecordStream(TimerInfo timer, DateTime recordingEndDate, ActiveRecordingInfo activeRecordingInfo)
         {
         {
-            if (timer == null)
-            {
-                throw new ArgumentNullException(nameof(timer));
-            }
+            ArgumentNullException.ThrowIfNull(timer);
 
 
             LiveTvProgram programInfo = null;
             LiveTvProgram programInfo = null;
 
 
@@ -2347,10 +2344,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
 
 
         private IEnumerable<TimerInfo> GetTimersForSeries(SeriesTimerInfo seriesTimer)
         private IEnumerable<TimerInfo> GetTimersForSeries(SeriesTimerInfo seriesTimer)
         {
         {
-            if (seriesTimer == null)
-            {
-                throw new ArgumentNullException(nameof(seriesTimer));
-            }
+            ArgumentNullException.ThrowIfNull(seriesTimer);
 
 
             var query = new InternalItemsQuery
             var query = new InternalItemsQuery
             {
             {

+ 7 - 3
Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs

@@ -13,6 +13,7 @@ using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using Jellyfin.Extensions;
 using Jellyfin.Extensions;
 using Jellyfin.Extensions.Json;
 using Jellyfin.Extensions.Json;
+using MediaBrowser.Common;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
@@ -65,7 +66,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
 
 
             await RecordFromFile(mediaSource, mediaSource.Path, targetFile, onStarted, cancellationTokenSource.Token).ConfigureAwait(false);
             await RecordFromFile(mediaSource, mediaSource.Path, targetFile, onStarted, cancellationTokenSource.Token).ConfigureAwait(false);
 
 
-            _logger.LogInformation("Recording completed to file {0}", targetFile);
+            _logger.LogInformation("Recording completed to file {Path}", targetFile);
         }
         }
 
 
         private async Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, Action onStarted, CancellationToken cancellationToken)
         private async Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, Action onStarted, CancellationToken cancellationToken)
@@ -115,7 +116,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
             // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback
             // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback
             _ = StartStreamingLog(_process.StandardError.BaseStream, _logFileStream);
             _ = StartStreamingLog(_process.StandardError.BaseStream, _logFileStream);
 
 
-            _logger.LogInformation("ffmpeg recording process started for {0}", _targetPath);
+            _logger.LogInformation("ffmpeg recording process started for {Path}", _targetPath);
+
+            // Block until ffmpeg exits
+            await _taskCompletionSource.Task.ConfigureAwait(false);
         }
         }
 
 
         private string GetCommandLineArgs(MediaSourceInfo mediaSource, string inputTempFile, string targetFile)
         private string GetCommandLineArgs(MediaSourceInfo mediaSource, string inputTempFile, string targetFile)
@@ -294,7 +298,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
                 else
                 else
                 {
                 {
                     _taskCompletionSource.TrySetException(
                     _taskCompletionSource.TrySetException(
-                        new Exception(
+                        new FfmpegException(
                             string.Format(
                             string.Format(
                                 CultureInfo.InvariantCulture,
                                 CultureInfo.InvariantCulture,
                                 "Recording for {0} failed. Exit code {1}",
                                 "Recording for {0} failed. Exit code {1}",

+ 2 - 8
Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs

@@ -84,10 +84,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
 
 
         public virtual void Update(T item)
         public virtual void Update(T item)
         {
         {
-            if (item == null)
-            {
-                throw new ArgumentNullException(nameof(item));
-            }
+            ArgumentNullException.ThrowIfNull(item);
 
 
             lock (_fileDataLock)
             lock (_fileDataLock)
             {
             {
@@ -107,10 +104,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
 
 
         public virtual void Add(T item)
         public virtual void Add(T item)
         {
         {
-            if (item == null)
-            {
-                throw new ArgumentNullException(nameof(item));
-            }
+            ArgumentNullException.ThrowIfNull(item);
 
 
             lock (_fileDataLock)
             lock (_fileDataLock)
             {
             {

+ 9 - 2
Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs

@@ -2,6 +2,7 @@
 
 
 using System;
 using System;
 using System.Globalization;
 using System.Globalization;
+using System.Text;
 using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Controller.LiveTv;
 
 
 namespace Emby.Server.Implementations.LiveTv.EmbyTV
 namespace Emby.Server.Implementations.LiveTv.EmbyTV
@@ -48,12 +49,18 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
 
 
                 if (!string.IsNullOrWhiteSpace(info.EpisodeTitle))
                 if (!string.IsNullOrWhiteSpace(info.EpisodeTitle))
                 {
                 {
+                    var tmpName = name;
                     if (addHyphen)
                     if (addHyphen)
                     {
                     {
-                        name += " -";
+                        tmpName += " -";
                     }
                     }
 
 
-                    name += " " + info.EpisodeTitle;
+                    tmpName += " " + info.EpisodeTitle;
+                    // Since the filename will be used with file ext. (.mp4, .ts, etc)
+                    if (Encoding.UTF8.GetByteCount(tmpName) < 250)
+                    {
+                        name = tmpName;
+                    }
                 }
                 }
             }
             }
             else if (info.IsMovie && info.ProductionYear != null)
             else if (info.IsMovie && info.ProductionYear != null)

+ 8 - 10
Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs

@@ -20,6 +20,7 @@ using Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos;
 using Jellyfin.Extensions;
 using Jellyfin.Extensions;
 using Jellyfin.Extensions.Json;
 using Jellyfin.Extensions.Json;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Authentication;
 using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
@@ -591,13 +592,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             }
             }
             catch (HttpRequestException ex)
             catch (HttpRequestException ex)
             {
             {
-                if (ex.StatusCode.HasValue)
+                if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.BadRequest)
                 {
                 {
-                    if ((int)ex.StatusCode.Value == 400)
-                    {
-                        _tokens.Clear();
-                        _lastErrorResponse = DateTime.UtcNow;
-                    }
+                    _tokens.Clear();
+                    _lastErrorResponse = DateTime.UtcNow;
                 }
                 }
 
 
                 throw;
                 throw;
@@ -662,7 +660,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
                 return root.Token;
                 return root.Token;
             }
             }
 
 
-            throw new Exception("Could not authenticate with Schedules Direct Error: " + root.Message);
+            throw new AuthenticationException("Could not authenticate with Schedules Direct Error: " + root.Message);
         }
         }
 
 
         private async Task AddLineupToAccount(ListingsProviderInfo info, CancellationToken cancellationToken)
         private async Task AddLineupToAccount(ListingsProviderInfo info, CancellationToken cancellationToken)
@@ -697,7 +695,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
 
 
             if (string.IsNullOrEmpty(token))
             if (string.IsNullOrEmpty(token))
             {
             {
-                throw new Exception("token required");
+                throw new ArgumentException("token required");
             }
             }
 
 
             _logger.LogInformation("Headends on account ");
             _logger.LogInformation("Headends on account ");
@@ -768,14 +766,14 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             var listingsId = info.ListingsId;
             var listingsId = info.ListingsId;
             if (string.IsNullOrEmpty(listingsId))
             if (string.IsNullOrEmpty(listingsId))
             {
             {
-                throw new Exception("ListingsId required");
+                throw new ArgumentException("ListingsId required");
             }
             }
 
 
             var token = await GetToken(info, cancellationToken).ConfigureAwait(false);
             var token = await GetToken(info, cancellationToken).ConfigureAwait(false);
 
 
             if (string.IsNullOrEmpty(token))
             if (string.IsNullOrEmpty(token))
             {
             {
-                throw new Exception("token required");
+                throw new ArgumentException("token required");
             }
             }
 
 
             using var options = new HttpRequestMessage(HttpMethod.Get, ApiUrl + "/lineups/" + listingsId);
             using var options = new HttpRequestMessage(HttpMethod.Get, ApiUrl + "/lineups/" + listingsId);

+ 23 - 4
Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs

@@ -8,6 +8,7 @@ using System.Globalization;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
 using System.Net.Http;
 using System.Net.Http;
+using System.Security.Cryptography;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using Jellyfin.Extensions;
 using Jellyfin.Extensions;
@@ -26,6 +27,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings
 {
 {
     public class XmlTvListingsProvider : IListingsProvider
     public class XmlTvListingsProvider : IListingsProvider
     {
     {
+        private static readonly TimeSpan _maxCacheAge = TimeSpan.FromHours(1);
+
         private readonly IServerConfigurationManager _config;
         private readonly IServerConfigurationManager _config;
         private readonly IHttpClientFactory _httpClientFactory;
         private readonly IHttpClientFactory _httpClientFactory;
         private readonly ILogger<XmlTvListingsProvider> _logger;
         private readonly ILogger<XmlTvListingsProvider> _logger;
@@ -69,13 +72,19 @@ namespace Emby.Server.Implementations.LiveTv.Listings
                 return UnzipIfNeeded(info.Path, info.Path);
                 return UnzipIfNeeded(info.Path, info.Path);
             }
             }
 
 
-            string cacheFilename = DateTime.UtcNow.DayOfYear.ToString(CultureInfo.InvariantCulture) + "-" + DateTime.UtcNow.Hour.ToString(CultureInfo.InvariantCulture) + "-" + info.Id + ".xml";
+            string cacheFilename = info.Id + ".xml";
             string cacheFile = Path.Combine(_config.ApplicationPaths.CachePath, "xmltv", cacheFilename);
             string cacheFile = Path.Combine(_config.ApplicationPaths.CachePath, "xmltv", cacheFilename);
-            if (File.Exists(cacheFile))
+            if (File.Exists(cacheFile) && File.GetLastWriteTimeUtc(cacheFile) >= DateTime.UtcNow.Subtract(_maxCacheAge))
             {
             {
                 return UnzipIfNeeded(info.Path, cacheFile);
                 return UnzipIfNeeded(info.Path, cacheFile);
             }
             }
 
 
+            // Must check if file exists as parent directory may not exist.
+            if (File.Exists(cacheFile))
+            {
+                File.Delete(cacheFile);
+            }
+
             _logger.LogInformation("Downloading xmltv listings from {Path}", info.Path);
             _logger.LogInformation("Downloading xmltv listings from {Path}", info.Path);
 
 
             Directory.CreateDirectory(Path.GetDirectoryName(cacheFile));
             Directory.CreateDirectory(Path.GetDirectoryName(cacheFile));
@@ -124,7 +133,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
         {
         {
             using (var stream = File.OpenRead(file))
             using (var stream = File.OpenRead(file))
             {
             {
-                string tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString());
+                string tempFolder = GetTempFolderPath(stream);
                 Directory.CreateDirectory(tempFolder);
                 Directory.CreateDirectory(tempFolder);
 
 
                 _zipClient.ExtractFirstFileFromGz(stream, tempFolder, "data.xml");
                 _zipClient.ExtractFirstFileFromGz(stream, tempFolder, "data.xml");
@@ -137,7 +146,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
         {
         {
             using (var stream = File.OpenRead(file))
             using (var stream = File.OpenRead(file))
             {
             {
-                string tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString());
+                string tempFolder = GetTempFolderPath(stream);
                 Directory.CreateDirectory(tempFolder);
                 Directory.CreateDirectory(tempFolder);
 
 
                 _zipClient.ExtractAllFromGz(stream, tempFolder, true);
                 _zipClient.ExtractAllFromGz(stream, tempFolder, true);
@@ -146,6 +155,16 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             }
             }
         }
         }
 
 
+        private string GetTempFolderPath(Stream stream)
+        {
+#pragma warning disable CA5351
+            using var md5 = MD5.Create();
+#pragma warning restore CA5351
+            var checksum = Convert.ToHexString(md5.ComputeHash(stream));
+            stream.Position = 0;
+            return Path.Combine(_config.ApplicationPaths.TempDirectory, checksum);
+        }
+
         private string FindXmlFile(string directory)
         private string FindXmlFile(string directory)
         {
         {
             return _fileSystem.GetFiles(directory, true)
             return _fileSystem.GetFiles(directory, true)

+ 1 - 1
Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs

@@ -196,7 +196,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
                 IsInfiniteStream = true,
                 IsInfiniteStream = true,
                 IsRemote = isRemote,
                 IsRemote = isRemote,
 
 
-                IgnoreDts = true,
+                IgnoreDts = info.IgnoreDts,
                 SupportsDirectPlay = supportsDirectPlay,
                 SupportsDirectPlay = supportsDirectPlay,
                 SupportsDirectStream = supportsDirectStream,
                 SupportsDirectStream = supportsDirectStream,
 
 

+ 2 - 5
Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs

@@ -44,10 +44,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
 
 
         public async Task<Stream> GetListingsStream(TunerHostInfo info, CancellationToken cancellationToken)
         public async Task<Stream> GetListingsStream(TunerHostInfo info, CancellationToken cancellationToken)
         {
         {
-            if (info == null)
-            {
-                throw new ArgumentNullException(nameof(info));
-            }
+            ArgumentNullException.ThrowIfNull(info);
 
 
             if (!info.Url.StartsWith("http", StringComparison.OrdinalIgnoreCase))
             if (!info.Url.StartsWith("http", StringComparison.OrdinalIgnoreCase))
             {
             {
@@ -199,7 +196,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
                 if (string.IsNullOrWhiteSpace(numberString))
                 if (string.IsNullOrWhiteSpace(numberString))
                 {
                 {
                     // Using this as a fallback now as this leads to Problems with channels like "5 USA"
                     // Using this as a fallback now as this leads to Problems with channels like "5 USA"
-                    // where 5 isn't ment to be the channel number
+                    // where 5 isn't meant to be the channel number
                     // Check for channel number with the format from SatIp
                     // Check for channel number with the format from SatIp
                     // #EXTINF:0,84. VOX Schweiz
                     // #EXTINF:0,84. VOX Schweiz
                     // #EXTINF:0,84.0 - VOX Schweiz
                     // #EXTINF:0,84.0 - VOX Schweiz

+ 4 - 1
Emby.Server.Implementations/Localization/Core/af.json

@@ -119,5 +119,8 @@
     "TaskCleanActivityLogDescription": "Verwyder aktiwiteitsaantekeninge ouer as die opgestelde ouderdom.",
     "TaskCleanActivityLogDescription": "Verwyder aktiwiteitsaantekeninge ouer as die opgestelde ouderdom.",
     "TaskCleanActivityLog": "Maak Aktiwiteitsaantekeninge Skoon",
     "TaskCleanActivityLog": "Maak Aktiwiteitsaantekeninge Skoon",
     "TaskOptimizeDatabaseDescription": "Komprimeer databasis en verkort vrye ruimte. As hierdie taak uitgevoer word nadat die media versameling geskandeer is of ander veranderings aangebring is wat databasisaanpassings impliseer, kan dit die prestasie verbeter.",
     "TaskOptimizeDatabaseDescription": "Komprimeer databasis en verkort vrye ruimte. As hierdie taak uitgevoer word nadat die media versameling geskandeer is of ander veranderings aangebring is wat databasisaanpassings impliseer, kan dit die prestasie verbeter.",
-    "TaskOptimizeDatabase": "Optimaliseer databasis"
+    "TaskOptimizeDatabase": "Optimaliseer databasis",
+    "TaskKeyframeExtractorDescription": "Haal keyframes vanuit video lêers om meer presiese HLS afspeellyste te maak. Dit kan lank duur.",
+    "TaskKeyframeExtractor": "Keyframe Ekstraktor",
+    "External": "Ekstern"
 }
 }

+ 36 - 33
Emby.Server.Implementations/Localization/Core/ar.json

@@ -1,9 +1,9 @@
 {
 {
-    "Albums": "ألبومات",
+    "Albums": "البومات",
     "AppDeviceValues": "تطبيق: {0}, جهاز: {1}",
     "AppDeviceValues": "تطبيق: {0}, جهاز: {1}",
     "Application": "تطبيق",
     "Application": "تطبيق",
     "Artists": "الفنانين",
     "Artists": "الفنانين",
-    "AuthenticationSucceededWithUserName": "{0} سجل الدخول بنجاح",
+    "AuthenticationSucceededWithUserName": "تمت مصادقة {0} بنجاح",
     "Books": "الكتب",
     "Books": "الكتب",
     "CameraImageUploadedFrom": "صورة كاميرا جديدة تم رفعها من {0}",
     "CameraImageUploadedFrom": "صورة كاميرا جديدة تم رفعها من {0}",
     "Channels": "القنوات",
     "Channels": "القنوات",
@@ -14,7 +14,7 @@
     "FailedLoginAttemptWithUserName": "محاولة تسجيل الدخول فشلت من {0}",
     "FailedLoginAttemptWithUserName": "محاولة تسجيل الدخول فشلت من {0}",
     "Favorites": "مفضلات",
     "Favorites": "مفضلات",
     "Folders": "المجلدات",
     "Folders": "المجلدات",
-    "Genres": "التضنيفات",
+    "Genres": "التصنيفات",
     "HeaderAlbumArtists": "فناني الألبوم",
     "HeaderAlbumArtists": "فناني الألبوم",
     "HeaderContinueWatching": "استمر بالمشاهدة",
     "HeaderContinueWatching": "استمر بالمشاهدة",
     "HeaderFavoriteAlbums": "الألبومات المفضلة",
     "HeaderFavoriteAlbums": "الألبومات المفضلة",
@@ -30,8 +30,8 @@
     "ItemAddedWithName": "تم إضافة {0} للمكتبة",
     "ItemAddedWithName": "تم إضافة {0} للمكتبة",
     "ItemRemovedWithName": "تم إزالة {0} من المكتبة",
     "ItemRemovedWithName": "تم إزالة {0} من المكتبة",
     "LabelIpAddressValue": "عنوان الآي بي: {0}",
     "LabelIpAddressValue": "عنوان الآي بي: {0}",
-    "LabelRunningTimeValue": "المدة: {0}",
-    "Latest": "الأحدث",
+    "LabelRunningTimeValue": "مدة التشغيل: {0}",
+    "Latest": "أحدث",
     "MessageApplicationUpdated": "لقد تم تحديث خادم Jellyfin",
     "MessageApplicationUpdated": "لقد تم تحديث خادم Jellyfin",
     "MessageApplicationUpdatedTo": "تم تحديث خادم Jellyfin الى {0}",
     "MessageApplicationUpdatedTo": "تم تحديث خادم Jellyfin الى {0}",
     "MessageNamedServerConfigurationUpdatedWithValue": "تم تحديث إعدادات الخادم في قسم {0}",
     "MessageNamedServerConfigurationUpdatedWithValue": "تم تحديث إعدادات الخادم في قسم {0}",
@@ -40,7 +40,7 @@
     "Movies": "الأفلام",
     "Movies": "الأفلام",
     "Music": "الموسيقى",
     "Music": "الموسيقى",
     "MusicVideos": "الفيديوهات الموسيقية",
     "MusicVideos": "الفيديوهات الموسيقية",
-    "NameInstallFailed": "فشل التثبيت {0}",
+    "NameInstallFailed": "فشل تثبيت {0}",
     "NameSeasonNumber": "الموسم {0}",
     "NameSeasonNumber": "الموسم {0}",
     "NameSeasonUnknown": "الموسم غير معروف",
     "NameSeasonUnknown": "الموسم غير معروف",
     "NewVersionIsAvailable": "نسخة جديدة من خادم Jellyfin متوفرة للتحميل.",
     "NewVersionIsAvailable": "نسخة جديدة من خادم Jellyfin متوفرة للتحميل.",
@@ -49,9 +49,9 @@
     "NotificationOptionAudioPlayback": "بدأ تشغيل المقطع الصوتي",
     "NotificationOptionAudioPlayback": "بدأ تشغيل المقطع الصوتي",
     "NotificationOptionAudioPlaybackStopped": "تم إيقاف تشغيل المقطع الصوتي",
     "NotificationOptionAudioPlaybackStopped": "تم إيقاف تشغيل المقطع الصوتي",
     "NotificationOptionCameraImageUploaded": "تم رفع صورة الكاميرا",
     "NotificationOptionCameraImageUploaded": "تم رفع صورة الكاميرا",
-    "NotificationOptionInstallationFailed": "فشل التثبيت",
+    "NotificationOptionInstallationFailed": "فشل في التثبيت",
     "NotificationOptionNewLibraryContent": "تم إضافة محتوى جديد",
     "NotificationOptionNewLibraryContent": "تم إضافة محتوى جديد",
-    "NotificationOptionPluginError": "فشل في البرنامج المضاف",
+    "NotificationOptionPluginError": "فشل في الملحق",
     "NotificationOptionPluginInstalled": "تم تثبيت الملحق",
     "NotificationOptionPluginInstalled": "تم تثبيت الملحق",
     "NotificationOptionPluginUninstalled": "تمت إزالة الملحق",
     "NotificationOptionPluginUninstalled": "تمت إزالة الملحق",
     "NotificationOptionPluginUpdateInstalled": "تم تثبيت تحديثات الملحق",
     "NotificationOptionPluginUpdateInstalled": "تم تثبيت تحديثات الملحق",
@@ -67,22 +67,22 @@
     "PluginUninstalledWithName": "تمت إزالة {0}",
     "PluginUninstalledWithName": "تمت إزالة {0}",
     "PluginUpdatedWithName": "تم تحديث {0}",
     "PluginUpdatedWithName": "تم تحديث {0}",
     "ProviderValue": "المزود: {0}",
     "ProviderValue": "المزود: {0}",
-    "ScheduledTaskFailedWithName": "العملية {0} فشلت",
-    "ScheduledTaskStartedWithName": "تم بدء {0}",
-    "ServerNameNeedsToBeRestarted": "يحتاج لإعادة تشغيله {0}",
-    "Shows": "الحلقات",
+    "ScheduledTaskFailedWithName": "فشلت العملية {0}",
+    "ScheduledTaskStartedWithName": "تم بدء العملية {0}",
+    "ServerNameNeedsToBeRestarted": "يحتاج {0} لإعادة التشغيل",
+    "Shows": "العروض",
     "Songs": "الأغاني",
     "Songs": "الأغاني",
-    "StartupEmbyServerIsLoading": "خادم Jellyfin قيد التشغيل . الرجاء المحاولة بعد قليل.",
+    "StartupEmbyServerIsLoading": "يتم تحميل خادم Jellyfin . الرجاء المحاولة بعد قليل.",
     "SubtitleDownloadFailureForItem": "عملية إنزال الترجمة فشلت لـ{0}",
     "SubtitleDownloadFailureForItem": "عملية إنزال الترجمة فشلت لـ{0}",
-    "SubtitleDownloadFailureFromForItem": "الترجمات فشلت في التحميل من {0} الى {1}",
+    "SubtitleDownloadFailureFromForItem": "فشل تحميل الترجمات من {0} ل {1}",
     "Sync": "مزامنة",
     "Sync": "مزامنة",
     "System": "النظام",
     "System": "النظام",
     "TvShows": "البرامج التلفزيونية",
     "TvShows": "البرامج التلفزيونية",
     "User": "المستخدم",
     "User": "المستخدم",
     "UserCreatedWithName": "تم إنشاء المستخدم {0}",
     "UserCreatedWithName": "تم إنشاء المستخدم {0}",
     "UserDeletedWithName": "تم حذف المستخدم {0}",
     "UserDeletedWithName": "تم حذف المستخدم {0}",
-    "UserDownloadingItemWithValues": "{0} يقوم بإنزال {1}",
-    "UserLockedOutWithName": "المستخدم {0} تم منعه من الدخول",
+    "UserDownloadingItemWithValues": "يقوم {0} بتنزيل {1}",
+    "UserLockedOutWithName": "تم منع المستخدم {0} من الدخول",
     "UserOfflineFromDevice": "تم قطع اتصال {0} من {1}",
     "UserOfflineFromDevice": "تم قطع اتصال {0} من {1}",
     "UserOnlineFromDevice": "{0} متصل عبر {1}",
     "UserOnlineFromDevice": "{0} متصل عبر {1}",
     "UserPasswordChangedWithName": "تم تغيير كلمة السر للمستخدم {0}",
     "UserPasswordChangedWithName": "تم تغيير كلمة السر للمستخدم {0}",
@@ -90,35 +90,38 @@
     "UserStartedPlayingItemWithValues": "قام {0} ببدء تشغيل {1} على {2}",
     "UserStartedPlayingItemWithValues": "قام {0} ببدء تشغيل {1} على {2}",
     "UserStoppedPlayingItemWithValues": "قام {0} بإيقاف تشغيل {1} على {2}",
     "UserStoppedPlayingItemWithValues": "قام {0} بإيقاف تشغيل {1} على {2}",
     "ValueHasBeenAddedToLibrary": "تمت اضافت {0} إلى مكتبة الوسائط",
     "ValueHasBeenAddedToLibrary": "تمت اضافت {0} إلى مكتبة الوسائط",
-    "ValueSpecialEpisodeName": "خاص - {0}",
+    "ValueSpecialEpisodeName": "حلقه خاصه - {0}",
     "VersionNumber": "النسخة {0}",
     "VersionNumber": "النسخة {0}",
-    "TaskCleanCacheDescription": "يحذف ملفات ذاكرة التخزين المؤقت التي لم يعد النظام بحاجة إليها.",
-    "TaskCleanCache": "احذف مجلد ذاكرة التخزين المؤقت",
+    "TaskCleanCacheDescription": "يحذف الملفات المؤقتة التي لم يعد النظام بحاجة إليها.",
+    "TaskCleanCache": "احذف ما بمجلد الملفات المؤقتة",
     "TasksChannelsCategory": "قنوات الإنترنت",
     "TasksChannelsCategory": "قنوات الإنترنت",
     "TasksLibraryCategory": "مكتبة",
     "TasksLibraryCategory": "مكتبة",
     "TasksMaintenanceCategory": "صيانة",
     "TasksMaintenanceCategory": "صيانة",
-    "TaskRefreshLibraryDescription": "يقوم بفصح مكتبة الوسائط الخاصة بك بحثًا عن ملفات جديدة وتحديث البيانات الوصفية.",
+    "TaskRefreshLibraryDescription": "يفصح مكتبة الوسائط الخاصة بك بحثًا عن ملفات جديدة، ومن ثم يتحدث البيانات الوصفية.",
     "TaskRefreshLibrary": "افحص مكتبة الوسائط",
     "TaskRefreshLibrary": "افحص مكتبة الوسائط",
-    "TaskRefreshChapterImagesDescription": "إنشاء صور مصغرة لمقاطع الفيديو ذات فصول.",
+    "TaskRefreshChapterImagesDescription": "يُنشئ صور مصغرة لمقاطع الفيديو التي تحتوي على فصول.",
     "TaskRefreshChapterImages": "استخراج صور الفصل",
     "TaskRefreshChapterImages": "استخراج صور الفصل",
     "TasksApplicationCategory": "تطبيق",
     "TasksApplicationCategory": "تطبيق",
-    "TaskDownloadMissingSubtitlesDescription": "ابحث في الإنترنت على الترجمات المفقودة إستنادا على الميتاداتا.",
-    "TaskDownloadMissingSubtitles": "تحميل الترجمات المفقودة",
-    "TaskRefreshChannelsDescription": "تحديث معلومات قنوات الإنترنت.",
+    "TaskDownloadMissingSubtitlesDescription": "يبحث في الإنترنت على الترجمات الناقصة استنادا على البيانات الوصفية.",
+    "TaskDownloadMissingSubtitles": "تحميل الترجمات الناقصة",
+    "TaskRefreshChannelsDescription": "يحدث معلومات قنوات الإنترنت.",
     "TaskRefreshChannels": "إعادة تحديث القنوات",
     "TaskRefreshChannels": "إعادة تحديث القنوات",
-    "TaskCleanTranscodeDescription": "حذف ملفات الترميز الأقدم من يوم واحد.",
-    "TaskCleanTranscode": "حذف سجلات الترميز",
+    "TaskCleanTranscodeDescription": "يحذف ملفات الترميز الأقدم من يوم واحد.",
+    "TaskCleanTranscode": "حذف ما بمجلد الترميز",
     "TaskUpdatePluginsDescription": "تحميل وتثبيت الإضافات التي تم تفعيل التحديث التلقائي لها.",
     "TaskUpdatePluginsDescription": "تحميل وتثبيت الإضافات التي تم تفعيل التحديث التلقائي لها.",
     "TaskUpdatePlugins": "تحديث الإضافات",
     "TaskUpdatePlugins": "تحديث الإضافات",
-    "TaskRefreshPeopleDescription": "تحديث البيانات الوصفية للممثلين والمخرجين في مكتبة الوسائط الخاصة بك.",
+    "TaskRefreshPeopleDescription": "يقوم بتحديث البيانات الوصفية للممثلين والمخرجين في مكتبة الوسائط الخاصة بك.",
     "TaskRefreshPeople": "إعادة تحميل الأشخاص",
     "TaskRefreshPeople": "إعادة تحميل الأشخاص",
-    "TaskCleanLogsDescription": "حذف السجلات الأقدم من {0} يوم.",
-    "TaskCleanLogs": "حذف دليل السجل",
-    "TaskCleanActivityLogDescription": "يحذف سجل الأنشطة الأقدم من الوقت الموضوع.",
+    "TaskCleanLogsDescription": "يحذف السجلات الأقدم من {0} يوم.",
+    "TaskCleanLogs": "حذف مسار السجل",
+    "TaskCleanActivityLogDescription": "يحذف سجل الأنشطة الأقدم من الوقت الذي تم تحديده.",
     "TaskCleanActivityLog": "حذف سجل الأنشطة",
     "TaskCleanActivityLog": "حذف سجل الأنشطة",
-    "Default": "الإعدادات الافتراضية",
+    "Default": "افتراضي",
     "Undefined": "غير معرف",
     "Undefined": "غير معرف",
     "Forced": "ملحقة",
     "Forced": "ملحقة",
-    "TaskOptimizeDatabaseDescription": "يضغط قاعدة البيانات ويقتطع المساحة الحرة. تشغيل هذه المهمة بعد فحص المكتبة أو إجراء تغييرات أخرى تشير ضمنًا إلى أن تعديلات قاعدة البيانات قد تؤدي إلى تحسين الأداء.",
-    "TaskOptimizeDatabase": "تحسين قاعدة البيانات"
+    "TaskOptimizeDatabaseDescription": "يضغط قاعدة البيانات ويقتطع المساحة الحرة. تشغيل هذه المهمة بعد فحص المكتبة أو إجراء تغييرات أخرى تتضمن تعديلات في قاعدة البيانات قد تؤدي إلى تحسين الأداء.",
+    "TaskOptimizeDatabase": "تحسين قاعدة البيانات",
+    "TaskKeyframeExtractorDescription": "يستخرج الإطارات الرئيسية من ملفات الفيديو لكي ينشئ قوائم تشغيل بث HTTP المباشر. قد تستمر هذه العملية لوقت طويل.",
+    "TaskKeyframeExtractor": "مستخرج الإطار الرئيسي",
+    "External": "خارجي"
 }
 }

+ 5 - 2
Emby.Server.Implementations/Localization/Core/bg-BG.json

@@ -43,7 +43,7 @@
     "NameInstallFailed": "{0} не можа да се инсталира",
     "NameInstallFailed": "{0} не можа да се инсталира",
     "NameSeasonNumber": "Сезон {0}",
     "NameSeasonNumber": "Сезон {0}",
     "NameSeasonUnknown": "Неразпознат сезон",
     "NameSeasonUnknown": "Неразпознат сезон",
-    "NewVersionIsAvailable": "Нова версия на Jellyfin сървъра е достъпна за сваляне.",
+    "NewVersionIsAvailable": "Нова версия на Джелифин сървъра е достъпна за сваляне.",
     "NotificationOptionApplicationUpdateAvailable": "Налично е обновление на програмата",
     "NotificationOptionApplicationUpdateAvailable": "Налично е обновление на програмата",
     "NotificationOptionApplicationUpdateInstalled": "Обновлението на програмата е инсталирано",
     "NotificationOptionApplicationUpdateInstalled": "Обновлението на програмата е инсталирано",
     "NotificationOptionAudioPlayback": "Възпроизвеждането на звук започна",
     "NotificationOptionAudioPlayback": "Възпроизвеждането на звук започна",
@@ -120,5 +120,8 @@
     "TaskCleanActivityLogDescription": "Изтрива записите в дневника с активност по стари от конфигурираната възраст.",
     "TaskCleanActivityLogDescription": "Изтрива записите в дневника с активност по стари от конфигурираната възраст.",
     "TaskCleanActivityLog": "Изчисти дневника с активност",
     "TaskCleanActivityLog": "Изчисти дневника с активност",
     "TaskOptimizeDatabaseDescription": "Прави базата данни по-компактна и освобождава място. Пускането на тази задача след сканиране на библиотеката или правене на други промени, свързани с модификации на базата данни, може да подобри производителността.",
     "TaskOptimizeDatabaseDescription": "Прави базата данни по-компактна и освобождава място. Пускането на тази задача след сканиране на библиотеката или правене на други промени, свързани с модификации на базата данни, може да подобри производителността.",
-    "TaskOptimizeDatabase": "Оптимизирай базата данни"
+    "TaskOptimizeDatabase": "Оптимизирай базата данни",
+    "TaskKeyframeExtractorDescription": "Извличат се ключови кадри от видеофайловете ,за да се създаде по точен ХЛС списък . Задачата може да отнеме много време.",
+    "TaskKeyframeExtractor": "Извличане на ключови кадри",
+    "External": "Външен"
 }
 }

+ 2 - 2
Emby.Server.Implementations/Localization/Core/ca.json

@@ -20,7 +20,7 @@
     "HeaderFavoriteAlbums": "Àlbums Preferits",
     "HeaderFavoriteAlbums": "Àlbums Preferits",
     "HeaderFavoriteArtists": "Artistes Predilectes",
     "HeaderFavoriteArtists": "Artistes Predilectes",
     "HeaderFavoriteEpisodes": "Episodis Predilectes",
     "HeaderFavoriteEpisodes": "Episodis Predilectes",
-    "HeaderFavoriteShows": "Programes Predilectes",
+    "HeaderFavoriteShows": "Sèries Predilectes",
     "HeaderFavoriteSongs": "Cançons Predilectes",
     "HeaderFavoriteSongs": "Cançons Predilectes",
     "HeaderLiveTV": "TV en Directe",
     "HeaderLiveTV": "TV en Directe",
     "HeaderNextUp": "A continuació",
     "HeaderNextUp": "A continuació",
@@ -70,7 +70,7 @@
     "ScheduledTaskFailedWithName": "{0} ha fallat",
     "ScheduledTaskFailedWithName": "{0} ha fallat",
     "ScheduledTaskStartedWithName": "{0} iniciat",
     "ScheduledTaskStartedWithName": "{0} iniciat",
     "ServerNameNeedsToBeRestarted": "{0} necessita ser reiniciat",
     "ServerNameNeedsToBeRestarted": "{0} necessita ser reiniciat",
-    "Shows": "Programes",
+    "Shows": "Sèries",
     "Songs": "Cançons",
     "Songs": "Cançons",
     "StartupEmbyServerIsLoading": "El Servidor d'Jellyfin est&agrave; carregant. Si et plau, prova de nou en breus.",
     "StartupEmbyServerIsLoading": "El Servidor d'Jellyfin est&agrave; carregant. Si et plau, prova de nou en breus.",
     "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
     "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",

+ 1 - 1
Emby.Server.Implementations/Localization/Core/de.json

@@ -121,7 +121,7 @@
     "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.",
     "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",
     "TaskOptimizeDatabase": "Datenbank optimieren",
-    "TaskKeyframeExtractorDescription": "Extrahiere Keyframes aus Videodateien, um präzisere HLS-Playlisten zu erzeugen. Diese Aufgabe kann sehr lange dauern.",
+    "TaskKeyframeExtractorDescription": "Extrahiere Keyframes aus Videodateien, um präzisere HLS-Playlisten zu erzeugen. Dieser Vorgang kann sehr lange dauern.",
     "TaskKeyframeExtractor": "Keyframe Extraktor",
     "TaskKeyframeExtractor": "Keyframe Extraktor",
     "External": "Extern"
     "External": "Extern"
 }
 }

+ 13 - 13
Emby.Server.Implementations/Localization/Core/el.json

@@ -5,17 +5,17 @@
     "Artists": "Καλλιτέχνες",
     "Artists": "Καλλιτέχνες",
     "AuthenticationSucceededWithUserName": "Ο χρήστης {0} επαληθεύτηκε επιτυχώς",
     "AuthenticationSucceededWithUserName": "Ο χρήστης {0} επαληθεύτηκε επιτυχώς",
     "Books": "Βιβλία",
     "Books": "Βιβλία",
-    "CameraImageUploadedFrom": "Μια νέα εικόνα κάμερας έχει αποσταλεί από {0}",
+    "CameraImageUploadedFrom": "Μια νέα φωτογραφία φορτώθηκε από {0}",
     "Channels": "Κανάλια",
     "Channels": "Κανάλια",
     "ChapterNameValue": "Κεφάλαιο {0}",
     "ChapterNameValue": "Κεφάλαιο {0}",
     "Collections": "Συλλογές",
     "Collections": "Συλλογές",
-    "DeviceOfflineWithName": "{0} αποσυνδέθηκε",
-    "DeviceOnlineWithName": "{0} συνδέθηκε",
+    "DeviceOfflineWithName": "Ο/Η {0} αποσυνδέθηκε",
+    "DeviceOnlineWithName": "Ο/Η {0} συνδέθηκε",
     "FailedLoginAttemptWithUserName": "Αποτυχημένη προσπάθεια σύνδεσης από {0}",
     "FailedLoginAttemptWithUserName": "Αποτυχημένη προσπάθεια σύνδεσης από {0}",
     "Favorites": "Αγαπημένα",
     "Favorites": "Αγαπημένα",
     "Folders": "Φάκελοι",
     "Folders": "Φάκελοι",
     "Genres": "Είδη",
     "Genres": "Είδη",
-    "HeaderAlbumArtists": "Καλλιτέχνες άλμπουμ",
+    "HeaderAlbumArtists": "Δισκογραφικοί καλλιτέχνες",
     "HeaderContinueWatching": "Συνεχίστε την παρακολούθηση",
     "HeaderContinueWatching": "Συνεχίστε την παρακολούθηση",
     "HeaderFavoriteAlbums": "Αγαπημένα Άλμπουμ",
     "HeaderFavoriteAlbums": "Αγαπημένα Άλμπουμ",
     "HeaderFavoriteArtists": "Αγαπημένοι Καλλιτέχνες",
     "HeaderFavoriteArtists": "Αγαπημένοι Καλλιτέχνες",
@@ -24,7 +24,7 @@
     "HeaderFavoriteSongs": "Αγαπημένα Τραγούδια",
     "HeaderFavoriteSongs": "Αγαπημένα Τραγούδια",
     "HeaderLiveTV": "Ζωντανή Τηλεόραση",
     "HeaderLiveTV": "Ζωντανή Τηλεόραση",
     "HeaderNextUp": "Επόμενο",
     "HeaderNextUp": "Επόμενο",
-    "HeaderRecordingGroups": "Γκρουπ Εγγραφών",
+    "HeaderRecordingGroups": "Μουσικά Συγκροτήματα",
     "HomeVideos": "Προσωπικά βίντεο",
     "HomeVideos": "Προσωπικά βίντεο",
     "Inherit": "Κληρονόμηση",
     "Inherit": "Κληρονόμηση",
     "ItemAddedWithName": "{0} προστέθηκε στη βιβλιοθήκη",
     "ItemAddedWithName": "{0} προστέθηκε στη βιβλιοθήκη",
@@ -32,10 +32,10 @@
     "LabelIpAddressValue": "Διεύθυνση IP: {0}",
     "LabelIpAddressValue": "Διεύθυνση IP: {0}",
     "LabelRunningTimeValue": "Διάρκεια: {0}",
     "LabelRunningTimeValue": "Διάρκεια: {0}",
     "Latest": "Πρόσφατα",
     "Latest": "Πρόσφατα",
-    "MessageApplicationUpdated": "Ο Jellyfin Server έχει ενημερωθεί",
-    "MessageApplicationUpdatedTo": "Ο server Jellyfin αναβαθμίστηκε σε έκδοση {0}",
-    "MessageNamedServerConfigurationUpdatedWithValue": "Η ενότητα {0} ρύθμισης παραμέτρων του server έχει ενημερωθεί",
-    "MessageServerConfigurationUpdated": "Η ρύθμιση παραμέτρων του server έχει ενημερωθεί",
+    "MessageApplicationUpdated": "Ο διακομιστής Jellyfin έχει ενημερωθεί",
+    "MessageApplicationUpdatedTo": "Ο διακομιστής Jellyfin αναβαθμίστηκε στην έκδοση {0}",
+    "MessageNamedServerConfigurationUpdatedWithValue": "Η ενότητα {0} ρύθμισης παραμέτρων του διακομιστή έχει ενημερωθεί",
+    "MessageServerConfigurationUpdated": "Η ρύθμιση παραμέτρων του διακομιστή έχει ενημερωθεί",
     "MixedContent": "Ανάμεικτο Περιεχόμενο",
     "MixedContent": "Ανάμεικτο Περιεχόμενο",
     "Movies": "Ταινίες",
     "Movies": "Ταινίες",
     "Music": "Μουσική",
     "Music": "Μουσική",
@@ -43,7 +43,7 @@
     "NameInstallFailed": "{0} η εγκατάσταση απέτυχε",
     "NameInstallFailed": "{0} η εγκατάσταση απέτυχε",
     "NameSeasonNumber": "Κύκλος {0}",
     "NameSeasonNumber": "Κύκλος {0}",
     "NameSeasonUnknown": "Άγνωστος Κύκλος",
     "NameSeasonUnknown": "Άγνωστος Κύκλος",
-    "NewVersionIsAvailable": "Μια νέα έκδοση του Jellyfin Server είναι διαθέσιμη για λήψη.",
+    "NewVersionIsAvailable": "Μια νέα έκδοση του διακομιστή Jellyfin είναι διαθέσιμη για λήψη.",
     "NotificationOptionApplicationUpdateAvailable": "Διαθέσιμη ενημερωμένη έκδοση εφαρμογής",
     "NotificationOptionApplicationUpdateAvailable": "Διαθέσιμη ενημερωμένη έκδοση εφαρμογής",
     "NotificationOptionApplicationUpdateInstalled": "Η ενημέρωση εφαρμογής εγκαταστάθηκε",
     "NotificationOptionApplicationUpdateInstalled": "Η ενημέρωση εφαρμογής εγκαταστάθηκε",
     "NotificationOptionAudioPlayback": "Η αναπαραγωγή ήχου ξεκίνησε",
     "NotificationOptionAudioPlayback": "Η αναπαραγωγή ήχου ξεκίνησε",
@@ -55,7 +55,7 @@
     "NotificationOptionPluginInstalled": "Το plugin εγκαταστάθηκε",
     "NotificationOptionPluginInstalled": "Το plugin εγκαταστάθηκε",
     "NotificationOptionPluginUninstalled": "Το plugin απεγκαταστάθηκε",
     "NotificationOptionPluginUninstalled": "Το plugin απεγκαταστάθηκε",
     "NotificationOptionPluginUpdateInstalled": "Η αναβάθμιση του plugin εγκαταστάθηκε",
     "NotificationOptionPluginUpdateInstalled": "Η αναβάθμιση του plugin εγκαταστάθηκε",
-    "NotificationOptionServerRestartRequired": "Απαιτείται επανεκκίνηση του server",
+    "NotificationOptionServerRestartRequired": "Ο διακομιστής χρειάζεται επανεκκίνηση",
     "NotificationOptionTaskFailed": "Αποτυχία προγραμματισμένης εργασίας",
     "NotificationOptionTaskFailed": "Αποτυχία προγραμματισμένης εργασίας",
     "NotificationOptionUserLockedOut": "Ο χρήστης αποκλείστηκε",
     "NotificationOptionUserLockedOut": "Ο χρήστης αποκλείστηκε",
     "NotificationOptionVideoPlayback": "Η αναπαραγωγή βίντεο ξεκίνησε",
     "NotificationOptionVideoPlayback": "Η αναπαραγωγή βίντεο ξεκίνησε",
@@ -72,7 +72,7 @@
     "ServerNameNeedsToBeRestarted": "{0} χρειάζεται επανεκκίνηση",
     "ServerNameNeedsToBeRestarted": "{0} χρειάζεται επανεκκίνηση",
     "Shows": "Σειρές",
     "Shows": "Σειρές",
     "Songs": "Τραγούδια",
     "Songs": "Τραγούδια",
-    "StartupEmbyServerIsLoading": "Ο Jellyfin Server φορτώνει. Παρακαλώ δοκιμάστε σε λίγο.",
+    "StartupEmbyServerIsLoading": "Ο διακομιστής Jellyfin φορτώνει. Περιμένετε λίγο και δοκιμάστε ξανά.",
     "SubtitleDownloadFailureForItem": "Οι υπότιτλοι απέτυχαν να κατέβουν για {0}",
     "SubtitleDownloadFailureForItem": "Οι υπότιτλοι απέτυχαν να κατέβουν για {0}",
     "SubtitleDownloadFailureFromForItem": "Αποτυχίες μεταφόρτωσης υποτίτλων από {0} για {1}",
     "SubtitleDownloadFailureFromForItem": "Αποτυχίες μεταφόρτωσης υποτίτλων από {0} για {1}",
     "Sync": "Συγχρονισμός",
     "Sync": "Συγχρονισμός",
@@ -121,7 +121,7 @@
     "Default": "Προεπιλογή",
     "Default": "Προεπιλογή",
     "TaskOptimizeDatabaseDescription": "Συμπιέζει τη βάση δεδομένων και δημιουργεί ελεύθερο χώρο. Η εκτέλεση αυτής της εργασίας μετά τη σάρωση της βιβλιοθήκης ή την πραγματοποίηση άλλων αλλαγών που συνεπάγονται τροποποιήσεις της βάσης δεδομένων μπορεί να βελτιώσει την απόδοση.",
     "TaskOptimizeDatabaseDescription": "Συμπιέζει τη βάση δεδομένων και δημιουργεί ελεύθερο χώρο. Η εκτέλεση αυτής της εργασίας μετά τη σάρωση της βιβλιοθήκης ή την πραγματοποίηση άλλων αλλαγών που συνεπάγονται τροποποιήσεις της βάσης δεδομένων μπορεί να βελτιώσει την απόδοση.",
     "TaskOptimizeDatabase": "Βελτιστοποίηση βάσης δεδομένων",
     "TaskOptimizeDatabase": "Βελτιστοποίηση βάσης δεδομένων",
-    "TaskKeyframeExtractorDescription": "Εξάγει τα βασικά καρέ από αρχεία βίντεο για να δημιουργήσει πιο ακριβείς HLS λίστες αναπαραγωγής. Αυτή η εργασία μπορεί να διαρκέσει πολλή ώρα.",
+    "TaskKeyframeExtractorDescription": "Εξάγει καρέ από αρχεία βίντεο για να δημιουργήσει πιο ακριβείς λίστες αναπαραγωγής HLS. Αυτή η διεργασία μπορεί να πάρει χρόνο.",
     "TaskKeyframeExtractor": "Εξαγωγέας βασικών καρέ βίντεο",
     "TaskKeyframeExtractor": "Εξαγωγέας βασικών καρέ βίντεο",
     "External": "Εξωτερικό"
     "External": "Εξωτερικό"
 }
 }

+ 3 - 1
Emby.Server.Implementations/Localization/Core/es-AR.json

@@ -121,5 +121,7 @@
     "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.",
     "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",
     "TaskOptimizeDatabase": "Optimización de base de datos",
-    "External": "Externo"
+    "External": "Externo",
+    "TaskKeyframeExtractorDescription": "Extrae Fotogramas Clave de los archivos de vídeo para crear Listas de Reprodución HLS más precisas. Esta tarea puede durar mucho tiempo.",
+    "TaskKeyframeExtractor": "Extractor de Fotogramas Clave"
 }
 }

+ 2 - 1
Emby.Server.Implementations/Localization/Core/es-MX.json

@@ -122,5 +122,6 @@
     "TaskOptimizeDatabase": "Optimizar base de datos",
     "TaskOptimizeDatabase": "Optimizar base de datos",
     "TaskOptimizeDatabaseDescription": "Compacta la base de datos y trunca el espacio libre. Puede mejorar el rendimiento si se realiza esta tarea después de escanear la biblioteca o después de realizar otros cambios que impliquen modificar la base de datos.",
     "TaskOptimizeDatabaseDescription": "Compacta la base de datos y trunca el espacio libre. Puede mejorar el rendimiento si se realiza esta tarea después de escanear la biblioteca o después de realizar otros cambios que impliquen modificar la base de datos.",
     "TaskKeyframeExtractorDescription": "Extrae los cuadros clave de los archivos de vídeo para crear listas HLS más precisas. Esta tarea puede tardar un buen rato.",
     "TaskKeyframeExtractorDescription": "Extrae los cuadros clave de los archivos de vídeo para crear listas HLS más precisas. Esta tarea puede tardar un buen rato.",
-    "TaskKeyframeExtractor": "Extractor de Cuadros Clave"
+    "TaskKeyframeExtractor": "Extractor de Cuadros Clave",
+    "External": "Externo"
 }
 }

+ 5 - 5
Emby.Server.Implementations/Localization/Core/es.json

@@ -74,7 +74,7 @@
     "Songs": "Canciones",
     "Songs": "Canciones",
     "StartupEmbyServerIsLoading": "Jellyfin Server se está cargando. Vuelve a intentarlo en breve.",
     "StartupEmbyServerIsLoading": "Jellyfin Server se está cargando. Vuelve a intentarlo en breve.",
     "SubtitleDownloadFailureForItem": "Error al descargar subtítulos para {0}",
     "SubtitleDownloadFailureForItem": "Error al descargar subtítulos para {0}",
-    "SubtitleDownloadFailureFromForItem": "Fallo de descarga de subtítulos desde {0} para {1}",
+    "SubtitleDownloadFailureFromForItem": "Fallo en la descarga de subtítulos desde {0} para {1}",
     "Sync": "Sincronizar",
     "Sync": "Sincronizar",
     "System": "Sistema",
     "System": "Sistema",
     "TvShows": "Series",
     "TvShows": "Series",
@@ -93,19 +93,19 @@
     "ValueSpecialEpisodeName": "Especial - {0}",
     "ValueSpecialEpisodeName": "Especial - {0}",
     "VersionNumber": "Versión {0}",
     "VersionNumber": "Versión {0}",
     "TasksMaintenanceCategory": "Mantenimiento",
     "TasksMaintenanceCategory": "Mantenimiento",
-    "TasksLibraryCategory": "Librería",
+    "TasksLibraryCategory": "Biblioteca",
     "TasksApplicationCategory": "Aplicación",
     "TasksApplicationCategory": "Aplicación",
     "TasksChannelsCategory": "Canales de internet",
     "TasksChannelsCategory": "Canales de internet",
     "TaskCleanCache": "Eliminar archivos temporales",
     "TaskCleanCache": "Eliminar archivos temporales",
     "TaskCleanCacheDescription": "Elimina los archivos temporales que ya no son necesarios para el servidor.",
     "TaskCleanCacheDescription": "Elimina los archivos temporales que ya no son necesarios para el servidor.",
     "TaskRefreshChapterImages": "Extraer imágenes de los capítulos",
     "TaskRefreshChapterImages": "Extraer imágenes de los capítulos",
-    "TaskRefreshChapterImagesDescription": "Crea las miniaturas de los vídeos que tengan capítulos.",
+    "TaskRefreshChapterImagesDescription": "Crear miniaturas de los vídeos que tengan capítulos.",
     "TaskRefreshLibrary": "Escanear la biblioteca",
     "TaskRefreshLibrary": "Escanear la biblioteca",
     "TaskRefreshLibraryDescription": "Añade los archivos que se hayan añadido a la biblioteca y actualiza las etiquetas de los ya presentes.",
     "TaskRefreshLibraryDescription": "Añade los archivos que se hayan añadido a la biblioteca y actualiza las etiquetas de los ya presentes.",
     "TaskCleanLogs": "Limpiar registros",
     "TaskCleanLogs": "Limpiar registros",
     "TaskCleanLogsDescription": "Elimina los archivos de registro que tengan más de {0} días.",
     "TaskCleanLogsDescription": "Elimina los archivos de registro que tengan más de {0} días.",
     "TaskRefreshPeople": "Actualizar personas",
     "TaskRefreshPeople": "Actualizar personas",
-    "TaskRefreshPeopleDescription": "Actualiza las etiquetas de los intérpretes y directores presentes en tus bibliotecas.",
+    "TaskRefreshPeopleDescription": "Actualiza las etiquetas de los actores y directores presentes en tus bibliotecas.",
     "TaskUpdatePlugins": "Actualizar extensiones",
     "TaskUpdatePlugins": "Actualizar extensiones",
     "TaskUpdatePluginsDescription": "Actualiza las extensiones que están configuradas para actualizarse automáticamente.",
     "TaskUpdatePluginsDescription": "Actualiza las extensiones que están configuradas para actualizarse automáticamente.",
     "TaskCleanTranscode": "Limpiar las transcodificaciones",
     "TaskCleanTranscode": "Limpiar las transcodificaciones",
@@ -120,7 +120,7 @@
     "Forced": "Forzado",
     "Forced": "Forzado",
     "Default": "Predeterminado",
     "Default": "Predeterminado",
     "TaskOptimizeDatabase": "Optimizar la base de datos",
     "TaskOptimizeDatabase": "Optimizar la base de datos",
-    "TaskOptimizeDatabaseDescription": "Compacta y libera el espacio libre en la base de datos. Ejecutar esta tarea tras escanear la biblioteca o hacer cambios que impliquen modificaciones en la base de datos puede mejorar el rendimiento.",
+    "TaskOptimizeDatabaseDescription": "Optimiza y libera el espacio libre en la base de datos. Ejecutar esta tarea tras escanear la biblioteca o hacer cambios que impliquen modificaciones en la base de datos puede mejorar el rendimiento.",
     "TaskKeyframeExtractorDescription": "Extrae los fotogramas clave de los archivos de vídeo para crear listas HLS más precisas. Esta tarea puede tardar mucho tiempo.",
     "TaskKeyframeExtractorDescription": "Extrae los fotogramas clave de los archivos de vídeo para crear listas HLS más precisas. Esta tarea puede tardar mucho tiempo.",
     "TaskKeyframeExtractor": "Extractor de Fotogramas Clave",
     "TaskKeyframeExtractor": "Extractor de Fotogramas Clave",
     "External": "Externo"
     "External": "Externo"

+ 4 - 1
Emby.Server.Implementations/Localization/Core/es_419.json

@@ -119,5 +119,8 @@
     "Forced": "Forzado",
     "Forced": "Forzado",
     "Default": "Por defecto",
     "Default": "Por defecto",
     "TaskOptimizeDatabaseDescription": "Compacta la base de datos y libera espacio. Ejecutar esta tarea después de escanear la biblioteca o hacer otros cambios que impliquen modificaciones en la base de datos puede mejorar el rendimiento.",
     "TaskOptimizeDatabaseDescription": "Compacta la base de datos y libera espacio. Ejecutar esta tarea después de escanear la biblioteca o hacer otros cambios que impliquen modificaciones en la base de datos puede mejorar el rendimiento.",
-    "TaskOptimizeDatabase": "Optimizar base de datos"
+    "TaskOptimizeDatabase": "Optimizar base de datos",
+    "External": "Externo",
+    "TaskKeyframeExtractorDescription": "Extrae Fotogramas Clave de los archivos de vídeo para crear Listas de Reproducción HLS más precisas. Esta tarea puede durar mucho tiempo.",
+    "TaskKeyframeExtractor": "Extractor de Fotogramas Clave"
 }
 }

+ 3 - 1
Emby.Server.Implementations/Localization/Core/es_DO.json

@@ -19,5 +19,7 @@
     "FailedLoginAttemptWithUserName": "Intento de inicio de sesión fallido de {0}",
     "FailedLoginAttemptWithUserName": "Intento de inicio de sesión fallido de {0}",
     "HeaderFavoriteSongs": "Canciones Favoritas",
     "HeaderFavoriteSongs": "Canciones Favoritas",
     "HeaderFavoriteEpisodes": "Episodios Favoritos",
     "HeaderFavoriteEpisodes": "Episodios Favoritos",
-    "HeaderFavoriteArtists": "Artistas Favoritos"
+    "HeaderFavoriteArtists": "Artistas Favoritos",
+    "External": "Externo",
+    "Default": "Predeterminado"
 }
 }

+ 2 - 1
Emby.Server.Implementations/Localization/Core/et.json

@@ -119,5 +119,6 @@
     "SubtitleDownloadFailureFromForItem": "Subtiitrite allalaadimine {0} > {1} nurjus",
     "SubtitleDownloadFailureFromForItem": "Subtiitrite allalaadimine {0} > {1} nurjus",
     "UserPolicyUpdatedWithName": "Kasutaja {0} õigusi värskendati",
     "UserPolicyUpdatedWithName": "Kasutaja {0} õigusi värskendati",
     "UserStoppedPlayingItemWithValues": "{0} lõpetas {1} taasesituse seadmes {2}",
     "UserStoppedPlayingItemWithValues": "{0} lõpetas {1} taasesituse seadmes {2}",
-    "UserOnlineFromDevice": "{0} on ühendatud seadmest {1}"
+    "UserOnlineFromDevice": "{0} on ühendatud seadmest {1}",
+    "External": "Väline"
 }
 }

+ 1 - 1
Emby.Server.Implementations/Localization/Core/fi.json

@@ -1,5 +1,5 @@
 {
 {
-    "HeaderLiveTV": "Suora TV",
+    "HeaderLiveTV": "Televisio",
     "NewVersionIsAvailable": "Uusi versio Jellyfin-palvelimesta on ladattavissa.",
     "NewVersionIsAvailable": "Uusi versio Jellyfin-palvelimesta on ladattavissa.",
     "NameSeasonUnknown": "Tuntematon kausi",
     "NameSeasonUnknown": "Tuntematon kausi",
     "NameSeasonNumber": "Kausi {0}",
     "NameSeasonNumber": "Kausi {0}",

Някои файлове не бяха показани, защото твърде много файлове са промени