diff options
247 files changed, 1075 insertions, 7316 deletions
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 97ec4b30e..1dbd7fa36 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -22,7 +22,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - name: Setup .NET Core - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@v3 with: dotnet-version: '6.0.x' diff --git a/.github/workflows/openapi.yml b/.github/workflows/openapi.yml index 7739a5fa6..ceb4e8cdf 100644 --- a/.github/workflows/openapi.yml +++ b/.github/workflows/openapi.yml @@ -17,7 +17,7 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} repository: ${{ github.event.pull_request.head.repo.full_name }} - name: Setup .NET Core - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@v3 with: dotnet-version: '6.0.x' - name: Generate openapi.json @@ -41,7 +41,7 @@ jobs: with: ref: ${{ github.base_ref }} - name: Setup .NET Core - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@v3 with: dotnet-version: '6.0.x' - name: Generate openapi.json diff --git a/.github/workflows/repo-stale.yaml b/.github/workflows/repo-stale.yaml index 0504b1c50..2578f82cf 100644 --- a/.github/workflows/repo-stale.yaml +++ b/.github/workflows/repo-stale.yaml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest if: ${{ contains(github.repository, 'jellyfin/') }} steps: - - uses: actions/stale@v5 + - uses: actions/stale@v6 with: repo-token: ${{ secrets.JF_BOT_TOKEN }} days-before-stale: 120 diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 98acd4449..8daaae4d9 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -148,6 +148,7 @@ - [xosdy](https://github.com/xosdy) - [XVicarious](https://github.com/XVicarious) - [YouKnowBlom](https://github.com/YouKnowBlom) + - [ZachPhelan](https://github.com/ZachPhelan) - [KristupasSavickas](https://github.com/KristupasSavickas) - [Pusta](https://github.com/pusta) - [nielsvanvelzen](https://github.com/nielsvanvelzen) diff --git a/Dockerfile b/Dockerfile index 5ca233b8f..219b95893 100644 --- a/Dockerfile +++ b/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. # curl: healthcheck 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 - \ && 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 \ @@ -53,7 +53,7 @@ RUN apt-get update \ && dpkg -i *.deb \ && cd .. \ && 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 autoremove -y \ && rm -rf /var/lib/apt/lists/* \ diff --git a/Dockerfile.arm b/Dockerfile.arm index 8da17ee5f..8e0ba7af5 100644 --- a/Dockerfile.arm +++ b/Dockerfile.arm @@ -38,9 +38,6 @@ RUN apt-get update \ libssl-dev \ libfontconfig1 \ libfreetype6 \ - libomxil-bellagio0 \ - libomxil-bellagio-bin \ - libraspberrypi0 \ vainfo \ libva2 \ locales \ diff --git a/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs b/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs index 9020dea99..319a9f550 100644 --- a/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs +++ b/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs @@ -103,10 +103,7 @@ namespace Emby.Dlna.ContentDirectory /// <inheritdoc /> 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(); diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index 57170bb31..fc69960fd 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -114,15 +114,9 @@ namespace Emby.Dlna.ContentDirectory /// <inheritdoc /> 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"; diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 74624334b..2ea2c130f 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -1,4 +1,5 @@ #pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.Globalization; @@ -61,6 +62,7 @@ namespace Emby.Dlna try { await ExtractSystemProfilesAsync().ConfigureAwait(false); + Directory.CreateDirectory(UserProfilesPath); LoadProfiles(); } catch (Exception ex) @@ -100,10 +102,7 @@ namespace Emby.Dlna /// <inheritdoc /> public DeviceProfile? GetProfile(DeviceIdentification deviceInfo) { - if (deviceInfo == null) - { - throw new ArgumentNullException(nameof(deviceInfo)); - } + ArgumentNullException.ThrowIfNull(deviceInfo); var profile = GetProfiles() .FirstOrDefault(i => i.Identification != null && IsMatch(deviceInfo, i.Identification)); @@ -170,10 +169,7 @@ namespace Emby.Dlna /// <inheritdoc /> 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)); if (profile == null) @@ -328,32 +324,28 @@ namespace Emby.Dlna var path = Path.Join( 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 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 /> @@ -406,14 +398,20 @@ namespace Emby.Dlna } 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 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); @@ -496,72 +494,4 @@ namespace Emby.Dlna 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() - { - } - }*/ } diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 0b480f5ab..34981bd3f 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -931,10 +931,7 @@ namespace Emby.Dlna.PlayTo 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); @@ -958,10 +955,7 @@ namespace Emby.Dlna.PlayTo private static string[] GetProtocolInfo(XElement container) { - if (container == null) - { - throw new ArgumentNullException(nameof(container)); - } + ArgumentNullException.ThrowIfNull(container); var resElement = container.Element(UPnpNamespaces.Res); @@ -1183,10 +1177,7 @@ namespace Emby.Dlna.PlayTo #nullable enable 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 height = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("height")); diff --git a/Emby.Dlna/PlayTo/TransportCommands.cs b/Emby.Dlna/PlayTo/TransportCommands.cs index d373b57f5..9c3a9103b 100644 --- a/Emby.Dlna/PlayTo/TransportCommands.cs +++ b/Emby.Dlna/PlayTo/TransportCommands.cs @@ -61,10 +61,7 @@ namespace Emby.Dlna.PlayTo private static Argument ArgumentFromXml(XElement container) { - if (container == null) - { - throw new ArgumentNullException(nameof(container)); - } + ArgumentNullException.ThrowIfNull(container); return new Argument { diff --git a/Emby.Dlna/PlayTo/UpnpContainer.cs b/Emby.Dlna/PlayTo/UpnpContainer.cs index 05f27603f..017d51e60 100644 --- a/Emby.Dlna/PlayTo/UpnpContainer.cs +++ b/Emby.Dlna/PlayTo/UpnpContainer.cs @@ -10,10 +10,7 @@ namespace Emby.Dlna.PlayTo { public static UBaseObject Create(XElement container) { - if (container == null) - { - throw new ArgumentNullException(nameof(container)); - } + ArgumentNullException.ThrowIfNull(container); return new UBaseObject { diff --git a/Emby.Dlna/PlayTo/uBaseObject.cs b/Emby.Dlna/PlayTo/uBaseObject.cs index 02d2da58d..2e0f2063b 100644 --- a/Emby.Dlna/PlayTo/uBaseObject.cs +++ b/Emby.Dlna/PlayTo/uBaseObject.cs @@ -54,10 +54,7 @@ namespace Emby.Dlna.PlayTo public bool Equals(UBaseObject obj) { - if (obj == null) - { - throw new ArgumentNullException(nameof(obj)); - } + ArgumentNullException.ThrowIfNull(obj); return string.Equals(Id, obj.Id, StringComparison.Ordinal); } diff --git a/Emby.Dlna/Profiles/DefaultProfile.cs b/Emby.Dlna/Profiles/DefaultProfile.cs index 8f4f2bd38..23437f1bd 100644 --- a/Emby.Dlna/Profiles/DefaultProfile.cs +++ b/Emby.Dlna/Profiles/DefaultProfile.cs @@ -2,7 +2,6 @@ using System; using System.Globalization; -using System.Linq; using MediaBrowser.Model.Dlna; 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(); - } } } diff --git a/Emby.Dlna/Profiles/DenonAvrProfile.cs b/Emby.Dlna/Profiles/DenonAvrProfile.cs deleted file mode 100644 index a5ba0f36c..000000000 --- a/Emby.Dlna/Profiles/DenonAvrProfile.cs +++ /dev/null @@ -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>(); - } - } -} diff --git a/Emby.Dlna/Profiles/DirectTvProfile.cs b/Emby.Dlna/Profiles/DirectTvProfile.cs deleted file mode 100644 index f6f98b07d..000000000 --- a/Emby.Dlna/Profiles/DirectTvProfile.cs +++ /dev/null @@ -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>(); - } - } -} diff --git a/Emby.Dlna/Profiles/DishHopperJoeyProfile.cs b/Emby.Dlna/Profiles/DishHopperJoeyProfile.cs deleted file mode 100644 index 2a7524a6a..000000000 --- a/Emby.Dlna/Profiles/DishHopperJoeyProfile.cs +++ /dev/null @@ -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 - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/Foobar2000Profile.cs b/Emby.Dlna/Profiles/Foobar2000Profile.cs deleted file mode 100644 index 68e959770..000000000 --- a/Emby.Dlna/Profiles/Foobar2000Profile.cs +++ /dev/null @@ -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>(); - } - } -} diff --git a/Emby.Dlna/Profiles/LgTvProfile.cs b/Emby.Dlna/Profiles/LgTvProfile.cs deleted file mode 100644 index fbb368d3e..000000000 --- a/Emby.Dlna/Profiles/LgTvProfile.cs +++ /dev/null @@ -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" - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/LinksysDMA2100Profile.cs b/Emby.Dlna/Profiles/LinksysDMA2100Profile.cs deleted file mode 100644 index 1a510dfec..000000000 --- a/Emby.Dlna/Profiles/LinksysDMA2100Profile.cs +++ /dev/null @@ -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 - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/MarantzProfile.cs b/Emby.Dlna/Profiles/MarantzProfile.cs deleted file mode 100644 index 24078ab29..000000000 --- a/Emby.Dlna/Profiles/MarantzProfile.cs +++ /dev/null @@ -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>(); - } - } -} diff --git a/Emby.Dlna/Profiles/MediaMonkeyProfile.cs b/Emby.Dlna/Profiles/MediaMonkeyProfile.cs deleted file mode 100644 index 28d639b6d..000000000 --- a/Emby.Dlna/Profiles/MediaMonkeyProfile.cs +++ /dev/null @@ -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>(); - } - } -} diff --git a/Emby.Dlna/Profiles/PanasonicVieraProfile.cs b/Emby.Dlna/Profiles/PanasonicVieraProfile.cs deleted file mode 100644 index 0d536acf3..000000000 --- a/Emby.Dlna/Profiles/PanasonicVieraProfile.cs +++ /dev/null @@ -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" - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/PopcornHourProfile.cs b/Emby.Dlna/Profiles/PopcornHourProfile.cs deleted file mode 100644 index 7fbf8c164..000000000 --- a/Emby.Dlna/Profiles/PopcornHourProfile.cs +++ /dev/null @@ -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 - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/SamsungSmartTvProfile.cs b/Emby.Dlna/Profiles/SamsungSmartTvProfile.cs deleted file mode 100644 index ddbebba2a..000000000 --- a/Emby.Dlna/Profiles/SamsungSmartTvProfile.cs +++ /dev/null @@ -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" - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/SharpSmartTvProfile.cs b/Emby.Dlna/Profiles/SharpSmartTvProfile.cs deleted file mode 100644 index aa8d434e3..000000000 --- a/Emby.Dlna/Profiles/SharpSmartTvProfile.cs +++ /dev/null @@ -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" - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/SonyBlurayPlayer2013.cs b/Emby.Dlna/Profiles/SonyBlurayPlayer2013.cs deleted file mode 100644 index 765c12504..000000000 --- a/Emby.Dlna/Profiles/SonyBlurayPlayer2013.cs +++ /dev/null @@ -1,230 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using MediaBrowser.Model.Dlna; - -namespace Emby.Dlna.Profiles -{ - [System.Xml.Serialization.XmlRoot("Profile")] - public class SonyBlurayPlayer2013 : DefaultProfile - { - public SonyBlurayPlayer2013() - { - Name = "Sony Blu-ray Player 2013"; - - Identification = new DeviceIdentification - { - ModelNumber = "BDP-2013", - - Headers = new[] - { - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S1100", - Match = HeaderMatchType.Substring - }, - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S3100", - Match = HeaderMatchType.Substring - }, - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S5100", - Match = HeaderMatchType.Substring - }, - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S6100", - Match = HeaderMatchType.Substring - }, - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S7100", - Match = HeaderMatchType.Substring - } - } - }; - - AddXmlRootAttribute("xmlns:av", "urn:schemas-sony-com:av"); - - ModelName = "Windows Media Player Sharing"; - ModelNumber = "3.0"; - Manufacturer = "Microsoft Corporation"; - - ProtocolInfo = "http-get:*:video/divx:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/flac:DLNA.ORG_PN=FLAC;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/ogg:DLNA.ORG_PN=OGG;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:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/gif:DLNA.ORG_PN=GIF_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_JP_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-flv:DLNA.ORG_PN=FLV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-dvr:DLNA.ORG_PN=DVR_MS;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/wtv:DLNA.ORG_PN=WTV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/ogg:DLNA.ORG_PN=OGV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.rn-realvideo:DLNA.ORG_PN=REAL_VIDEO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_3GPP_P0_L10_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_MP4_P0_L10_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000"; - - TranscodingProfiles = new[] - { - new TranscodingProfile - { - Container = "mp3", - AudioCodec = "mp3", - Type = DlnaProfileType.Audio - }, - - new TranscodingProfile - { - Container = "mkv", - VideoCodec = "h264", - AudioCodec = "ac3,aac,mp3", - Type = DlnaProfileType.Video - }, - - new TranscodingProfile - { - Container = "jpeg", - Type = DlnaProfileType.Photo - } - }; - - DirectPlayProfiles = new[] - { - new DirectPlayProfile - { - Container = "ts,mpegts", - VideoCodec = "mpeg1video,mpeg2video,h264", - AudioCodec = "ac3,aac,mp3,pcm", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mpeg,mpg", - VideoCodec = "mpeg1video,mpeg2video", - AudioCodec = "ac3,mp3,mp2,pcm", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mp4,m4v", - VideoCodec = "mpeg4,h264", - AudioCodec = "ac3,aac,pcm,mp3", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "avi", - VideoCodec = "mpeg4,h264", - AudioCodec = "ac3,aac,mp3,pcm", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mkv", - VideoCodec = "mpeg4,h264", - AudioCodec = "ac3,dca,aac,mp3,pcm,dts", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "m2ts,mts", - VideoCodec = "h264,mpeg4,vc1", - AudioCodec = "aac,mp3,ac3,dca,dts", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "wmv,asf", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mp3,m4a,wma,wav", - Type = DlnaProfileType.Audio - }, - new DirectPlayProfile - { - Container = "jpeg,png,gif", - Type = DlnaProfileType.Photo - } - }; - - 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 CodecProfile - { - Type = CodecType.VideoAudio, - Codec = "ac3", - Conditions = new[] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.AudioChannels, - Value = "6", - IsRequired = false - } - } - } - }; - - 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" - } - } - } - }; - - SubtitleProfiles = new[] - { - new SubtitleProfile - { - Format = "srt", - Method = SubtitleDeliveryMethod.Embed - } - }; - - ResponseProfiles = Array.Empty<ResponseProfile>(); - } - } -} diff --git a/Emby.Dlna/Profiles/SonyBlurayPlayer2014.cs b/Emby.Dlna/Profiles/SonyBlurayPlayer2014.cs deleted file mode 100644 index 390c8a3e4..000000000 --- a/Emby.Dlna/Profiles/SonyBlurayPlayer2014.cs +++ /dev/null @@ -1,230 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using MediaBrowser.Model.Dlna; - -namespace Emby.Dlna.Profiles -{ - [System.Xml.Serialization.XmlRoot("Profile")] - public class SonyBlurayPlayer2014 : DefaultProfile - { - public SonyBlurayPlayer2014() - { - Name = "Sony Blu-ray Player 2014"; - - Identification = new DeviceIdentification - { - ModelNumber = "BDP-2014", - - Headers = new[] - { - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S1200", - Match = HeaderMatchType.Substring - }, - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S3200", - Match = HeaderMatchType.Substring - }, - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S5200", - Match = HeaderMatchType.Substring - }, - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S6200", - Match = HeaderMatchType.Substring - }, - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S7200", - Match = HeaderMatchType.Substring - } - } - }; - - AddXmlRootAttribute("xmlns:av", "urn:schemas-sony-com:av"); - - ModelName = "Windows Media Player Sharing"; - ModelNumber = "3.0"; - Manufacturer = "Microsoft Corporation"; - - ProtocolInfo = "http-get:*:video/divx:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/flac:DLNA.ORG_PN=FLAC;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/ogg:DLNA.ORG_PN=OGG;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:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/gif:DLNA.ORG_PN=GIF_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_JP_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-flv:DLNA.ORG_PN=FLV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-dvr:DLNA.ORG_PN=DVR_MS;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/wtv:DLNA.ORG_PN=WTV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/ogg:DLNA.ORG_PN=OGV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.rn-realvideo:DLNA.ORG_PN=REAL_VIDEO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_3GPP_P0_L10_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_MP4_P0_L10_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000"; - - TranscodingProfiles = new[] - { - new TranscodingProfile - { - Container = "mp3", - AudioCodec = "mp3", - Type = DlnaProfileType.Audio - }, - - new TranscodingProfile - { - Container = "mkv", - VideoCodec = "h264", - AudioCodec = "ac3,aac,mp3", - Type = DlnaProfileType.Video - }, - - new TranscodingProfile - { - Container = "jpeg", - Type = DlnaProfileType.Photo - } - }; - - DirectPlayProfiles = new[] - { - new DirectPlayProfile - { - Container = "ts,mpegts", - VideoCodec = "mpeg1video,mpeg2video,h264", - AudioCodec = "ac3,aac,mp3,pcm", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mpeg,mpg", - VideoCodec = "mpeg1video,mpeg2video", - AudioCodec = "ac3,mp3,mp2,pcm", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mp4,m4v", - VideoCodec = "mpeg4,h264", - AudioCodec = "ac3,aac,pcm,mp3", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "avi", - VideoCodec = "mpeg4,h264", - AudioCodec = "ac3,aac,mp3,pcm", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mkv", - VideoCodec = "mpeg4,h264", - AudioCodec = "ac3,dca,aac,mp3,pcm,dts", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "m2ts,mts", - VideoCodec = "h264,mpeg4,vc1", - AudioCodec = "aac,mp3,ac3,dca,dts", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "wmv,asf", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mp3,m4a,wma,wav", - Type = DlnaProfileType.Audio - }, - new DirectPlayProfile - { - Container = "jpeg,png,gif", - Type = DlnaProfileType.Photo - } - }; - - 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 CodecProfile - { - Type = CodecType.VideoAudio, - Codec = "ac3", - Conditions = new[] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.AudioChannels, - Value = "6", - IsRequired = false - } - } - } - }; - - 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" - } - } - } - }; - - SubtitleProfiles = new[] - { - new SubtitleProfile - { - Format = "srt", - Method = SubtitleDeliveryMethod.Embed - } - }; - - ResponseProfiles = Array.Empty<ResponseProfile>(); - } - } -} diff --git a/Emby.Dlna/Profiles/SonyBlurayPlayer2015.cs b/Emby.Dlna/Profiles/SonyBlurayPlayer2015.cs deleted file mode 100644 index 25adc4d02..000000000 --- a/Emby.Dlna/Profiles/SonyBlurayPlayer2015.cs +++ /dev/null @@ -1,218 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using MediaBrowser.Model.Dlna; - -namespace Emby.Dlna.Profiles -{ - [System.Xml.Serialization.XmlRoot("Profile")] - public class SonyBlurayPlayer2015 : DefaultProfile - { - public SonyBlurayPlayer2015() - { - Name = "Sony Blu-ray Player 2015"; - - Identification = new DeviceIdentification - { - ModelNumber = "BDP-2015", - - Headers = new[] - { - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S1500", - Match = HeaderMatchType.Substring - }, - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S3500", - Match = HeaderMatchType.Substring - }, - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S6500", - Match = HeaderMatchType.Substring - } - } - }; - - AddXmlRootAttribute("xmlns:av", "urn:schemas-sony-com:av"); - - ModelName = "Windows Media Player Sharing"; - ModelNumber = "3.0"; - Manufacturer = "Microsoft Corporation"; - - ProtocolInfo = "http-get:*:video/divx:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/flac:DLNA.ORG_PN=FLAC;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/ogg:DLNA.ORG_PN=OGG;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:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/gif:DLNA.ORG_PN=GIF_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_JP_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-flv:DLNA.ORG_PN=FLV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-dvr:DLNA.ORG_PN=DVR_MS;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/wtv:DLNA.ORG_PN=WTV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/ogg:DLNA.ORG_PN=OGV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.rn-realvideo:DLNA.ORG_PN=REAL_VIDEO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_3GPP_P0_L10_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_MP4_P0_L10_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000"; - - TranscodingProfiles = new[] - { - new TranscodingProfile - { - Container = "mp3", - AudioCodec = "mp3", - Type = DlnaProfileType.Audio - }, - - new TranscodingProfile - { - Container = "mkv", - VideoCodec = "h264", - AudioCodec = "ac3,aac,mp3", - Type = DlnaProfileType.Video - }, - - new TranscodingProfile - { - Container = "jpeg", - Type = DlnaProfileType.Photo - } - }; - - DirectPlayProfiles = new[] - { - new DirectPlayProfile - { - Container = "ts,mpegts", - VideoCodec = "mpeg1video,mpeg2video,h264", - AudioCodec = "ac3,aac,mp3,pcm", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mpeg,mpg", - VideoCodec = "mpeg1video,mpeg2video", - AudioCodec = "ac3,mp3,mp2,pcm", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mp4,m4v", - VideoCodec = "mpeg4,h264", - AudioCodec = "ac3,aac,pcm,mp3", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "avi", - VideoCodec = "mpeg4,h264", - AudioCodec = "ac3,aac,mp3,pcm", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mkv", - VideoCodec = "mpeg4,h264", - AudioCodec = "ac3,dca,aac,mp3,pcm,dts", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "m2ts,mts", - VideoCodec = "h264,mpeg4,vc1", - AudioCodec = "aac,mp3,ac3,dca,dts", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "wmv,asf", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mp3,m4a,wma,wav", - Type = DlnaProfileType.Audio - }, - new DirectPlayProfile - { - Container = "jpeg,png,gif", - Type = DlnaProfileType.Photo - } - }; - - 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 CodecProfile - { - Type = CodecType.VideoAudio, - Codec = "ac3", - Conditions = new[] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.AudioChannels, - Value = "6", - IsRequired = false - } - } - } - }; - - 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" - } - } - } - }; - - SubtitleProfiles = new[] - { - new SubtitleProfile - { - Format = "srt", - Method = SubtitleDeliveryMethod.Embed - } - }; - - ResponseProfiles = Array.Empty<ResponseProfile>(); - } - } -} diff --git a/Emby.Dlna/Profiles/SonyBlurayPlayer2016.cs b/Emby.Dlna/Profiles/SonyBlurayPlayer2016.cs deleted file mode 100644 index 0a39a5f40..000000000 --- a/Emby.Dlna/Profiles/SonyBlurayPlayer2016.cs +++ /dev/null @@ -1,218 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using MediaBrowser.Model.Dlna; - -namespace Emby.Dlna.Profiles -{ - [System.Xml.Serialization.XmlRoot("Profile")] - public class SonyBlurayPlayer2016 : DefaultProfile - { - public SonyBlurayPlayer2016() - { - Name = "Sony Blu-ray Player 2016"; - - Identification = new DeviceIdentification - { - ModelNumber = "BDP-2016", - - Headers = new[] - { - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S1700", - Match = HeaderMatchType.Substring - }, - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S3700", - Match = HeaderMatchType.Substring - }, - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = "BDP-S6700", - Match = HeaderMatchType.Substring - } - } - }; - - AddXmlRootAttribute("xmlns:av", "urn:schemas-sony-com:av"); - - ModelName = "Windows Media Player Sharing"; - ModelNumber = "3.0"; - Manufacturer = "Microsoft Corporation"; - - ProtocolInfo = "http-get:*:video/divx:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/flac:DLNA.ORG_PN=FLAC;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/ogg:DLNA.ORG_PN=OGG;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:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/gif:DLNA.ORG_PN=GIF_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_JP_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-flv:DLNA.ORG_PN=FLV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-dvr:DLNA.ORG_PN=DVR_MS;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/wtv:DLNA.ORG_PN=WTV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/ogg:DLNA.ORG_PN=OGV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.rn-realvideo:DLNA.ORG_PN=REAL_VIDEO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_3GPP_P0_L10_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_MP4_P0_L10_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000"; - - TranscodingProfiles = new[] - { - new TranscodingProfile - { - Container = "mp3", - AudioCodec = "mp3", - Type = DlnaProfileType.Audio - }, - - new TranscodingProfile - { - Container = "mkv", - VideoCodec = "h264", - AudioCodec = "ac3,aac,mp3", - Type = DlnaProfileType.Video - }, - - new TranscodingProfile - { - Container = "jpeg", - Type = DlnaProfileType.Photo - } - }; - - DirectPlayProfiles = new[] - { - new DirectPlayProfile - { - Container = "ts,mpegts", - VideoCodec = "mpeg1video,mpeg2video,h264", - AudioCodec = "ac3,aac,mp3,pcm", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mpeg,mpg", - VideoCodec = "mpeg1video,mpeg2video", - AudioCodec = "ac3,mp3,mp2,pcm", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mp4,m4v", - VideoCodec = "mpeg4,h264", - AudioCodec = "ac3,aac,pcm,mp3", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "avi", - VideoCodec = "mpeg4,h264", - AudioCodec = "ac3,aac,mp3,pcm", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mkv", - VideoCodec = "mpeg4,h264", - AudioCodec = "ac3,dca,aac,mp3,pcm,dts", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "m2ts,mts", - VideoCodec = "h264,mpeg4,vc1", - AudioCodec = "aac,mp3,ac3,dca,dts", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "wmv,asf", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mp3,m4a,wma,wav", - Type = DlnaProfileType.Audio - }, - new DirectPlayProfile - { - Container = "jpeg,png,gif", - Type = DlnaProfileType.Photo - } - }; - - 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 CodecProfile - { - Type = CodecType.VideoAudio, - Codec = "ac3", - Conditions = new[] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.AudioChannels, - Value = "6", - IsRequired = false - } - } - } - }; - - 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" - } - } - } - }; - - SubtitleProfiles = new[] - { - new SubtitleProfile - { - Format = "srt", - Method = SubtitleDeliveryMethod.Embed - } - }; - - ResponseProfiles = Array.Empty<ResponseProfile>(); - } - } -} diff --git a/Emby.Dlna/Profiles/SonyBlurayPlayerProfile.cs b/Emby.Dlna/Profiles/SonyBlurayPlayerProfile.cs deleted file mode 100644 index 05c8ab1c1..000000000 --- a/Emby.Dlna/Profiles/SonyBlurayPlayerProfile.cs +++ /dev/null @@ -1,284 +0,0 @@ -#pragma warning disable CS1591 - -using MediaBrowser.Model.Dlna; - -namespace Emby.Dlna.Profiles -{ - [System.Xml.Serialization.XmlRoot("Profile")] - public class SonyBlurayPlayerProfile : DefaultProfile - { - public SonyBlurayPlayerProfile() - { - Name = "Sony Blu-ray Player"; - - Identification = new DeviceIdentification - { - FriendlyName = @"Blu-ray Disc Player", - Manufacturer = "Sony", - - Headers = new[] - { - new HttpHeaderInfo - { - Name = "X-AV-Client-Info", - Value = @"(Blu-ray Disc Player|Home Theater System|Home Theatre System|Media Player)", - Match = HeaderMatchType.Regex - }, - - new HttpHeaderInfo - { - Name = "X-AV-Physical-Unit-Info", - Value = @"(Blu-ray Disc Player|Home Theater System|Home Theatre System|Media Player)", - Match = HeaderMatchType.Regex - } - } - }; - - AddXmlRootAttribute("xmlns:av", "urn:schemas-sony-com:av"); - - ModelName = "Windows Media Player Sharing"; - ModelNumber = "3.0"; - Manufacturer = "Microsoft Corporation"; - - ProtocolInfo = "http-get:*:video/divx:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/flac:DLNA.ORG_PN=FLAC;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/ogg:DLNA.ORG_PN=OGG;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:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/gif:DLNA.ORG_PN=GIF_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_JP_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-flv:DLNA.ORG_PN=FLV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-dvr:DLNA.ORG_PN=DVR_MS;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/wtv:DLNA.ORG_PN=WTV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/ogg:DLNA.ORG_PN=OGV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.rn-realvideo:DLNA.ORG_PN=REAL_VIDEO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_3GPP_P0_L10_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_MP4_P0_L10_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000"; - - TranscodingProfiles = new[] - { - new TranscodingProfile - { - Container = "mp3", - AudioCodec = "mp3", - Type = DlnaProfileType.Audio - }, - - new TranscodingProfile - { - Container = "ts", - VideoCodec = "mpeg2video", - AudioCodec = "ac3", - Type = DlnaProfileType.Video - }, - - new TranscodingProfile - { - Container = "jpeg", - Type = DlnaProfileType.Photo - } - }; - - DirectPlayProfiles = new[] - { - new DirectPlayProfile - { - Container = "ts,mpegts", - VideoCodec = "mpeg1video,mpeg2video,h264", - AudioCodec = "ac3,aac,mp3,pcm", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mpeg", - VideoCodec = "mpeg1video,mpeg2video", - AudioCodec = "ac3,mp3,pcm", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "avi,mp4,m4v", - VideoCodec = "mpeg4,h264", - AudioCodec = "ac3,aac,mp3,pcm", - 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 - } - }; - - 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.VideoLevel, - Value = "41", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoBitrate, - Value = "15360000", - IsRequired = false - } - } - }, - - new CodecProfile - { - Type = CodecType.VideoAudio, - Codec = "ac3", - 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 - } - } - } - }; - - 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,mpeg4,vc1", - AudioCodec = "ac3,aac,mp3", - 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 = "avi", - MimeType = "video/mpeg", - Type = DlnaProfileType.Video - }, - - new ResponseProfile - { - Container = "mkv", - MimeType = "video/vnd.dlna.mpeg-tts", - Type = DlnaProfileType.Video - }, - - new ResponseProfile - { - Container = "ts,mpegts", - MimeType = "video/vnd.dlna.mpeg-tts", - Type = DlnaProfileType.Video - }, - - new ResponseProfile - { - Container = "mp4", - MimeType = "video/mpeg", - Type = DlnaProfileType.Video - }, - - new ResponseProfile - { - Container = "m4v", - MimeType = "video/mpeg", - Type = DlnaProfileType.Video - }, - - new ResponseProfile - { - Container = "mpeg", - MimeType = "video/mpeg", - Type = DlnaProfileType.Video - }, - - new ResponseProfile - { - Container = "mp3", - MimeType = "audio/mpeg", - Type = DlnaProfileType.Audio - } - }; - - SubtitleProfiles = new[] - { - new SubtitleProfile - { - Format = "srt", - Method = SubtitleDeliveryMethod.Embed - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/SonyBravia2010Profile.cs b/Emby.Dlna/Profiles/SonyBravia2010Profile.cs deleted file mode 100644 index 9f0d82b8f..000000000 --- a/Emby.Dlna/Profiles/SonyBravia2010Profile.cs +++ /dev/null @@ -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 - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/SonyBravia2011Profile.cs b/Emby.Dlna/Profiles/SonyBravia2011Profile.cs deleted file mode 100644 index dfb91817a..000000000 --- a/Emby.Dlna/Profiles/SonyBravia2011Profile.cs +++ /dev/null @@ -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 - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/SonyBravia2012Profile.cs b/Emby.Dlna/Profiles/SonyBravia2012Profile.cs deleted file mode 100644 index d59ee38d7..000000000 --- a/Emby.Dlna/Profiles/SonyBravia2012Profile.cs +++ /dev/null @@ -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 - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/SonyBravia2013Profile.cs b/Emby.Dlna/Profiles/SonyBravia2013Profile.cs deleted file mode 100644 index 73b0fd67e..000000000 --- a/Emby.Dlna/Profiles/SonyBravia2013Profile.cs +++ /dev/null @@ -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 - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/SonyBravia2014Profile.cs b/Emby.Dlna/Profiles/SonyBravia2014Profile.cs deleted file mode 100644 index db8ee5750..000000000 --- a/Emby.Dlna/Profiles/SonyBravia2014Profile.cs +++ /dev/null @@ -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 - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/SonyPs3Profile.cs b/Emby.Dlna/Profiles/SonyPs3Profile.cs deleted file mode 100644 index e4a7a3a59..000000000 --- a/Emby.Dlna/Profiles/SonyPs3Profile.cs +++ /dev/null @@ -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 - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/SonyPs4Profile.cs b/Emby.Dlna/Profiles/SonyPs4Profile.cs deleted file mode 100644 index 985df0c9a..000000000 --- a/Emby.Dlna/Profiles/SonyPs4Profile.cs +++ /dev/null @@ -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 - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/WdtvLiveProfile.cs b/Emby.Dlna/Profiles/WdtvLiveProfile.cs deleted file mode 100644 index 937ca0f42..000000000 --- a/Emby.Dlna/Profiles/WdtvLiveProfile.cs +++ /dev/null @@ -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 - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/XboxOneProfile.cs b/Emby.Dlna/Profiles/XboxOneProfile.cs deleted file mode 100644 index 84d8184a2..000000000 --- a/Emby.Dlna/Profiles/XboxOneProfile.cs +++ /dev/null @@ -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 - } - }; - } - } -} diff --git a/Emby.Naming/AudioBook/AudioBookFilePathParserResult.cs b/Emby.Naming/AudioBook/AudioBookFilePathParserResult.cs index 48ab8b57d..ae8c8a39b 100644 --- a/Emby.Naming/AudioBook/AudioBookFilePathParserResult.cs +++ b/Emby.Naming/AudioBook/AudioBookFilePathParserResult.cs @@ -3,7 +3,7 @@ namespace Emby.Naming.AudioBook /// <summary> /// Data object for passing result of audiobook part/chapter extraction. /// </summary> - public struct AudioBookFilePathParserResult + public record struct AudioBookFilePathParserResult { /// <summary> /// Gets or sets optional number of path extracted from audiobook filename. diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index ddeec679d..a72e0ffc7 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -298,6 +298,13 @@ namespace Emby.Naming.Common "default" }; + MediaHearingImpairedFlags = new[] + { + "cc", + "hi", + "sdh" + }; + EpisodeExpressions = new[] { // *** Begin Kodi Standard Naming @@ -746,6 +753,11 @@ namespace Emby.Naming.Common public string[] MediaDefaultFlags { get; set; } /// <summary> + /// Gets or sets list of external media hearing impaired flags. + /// </summary> + public string[] MediaHearingImpairedFlags { get; set; } + + /// <summary> /// Gets or sets list of album stacking prefixes. /// </summary> public string[] AlbumStackingPrefixes { get; set; } diff --git a/Emby.Naming/ExternalFiles/ExternalPathParser.cs b/Emby.Naming/ExternalFiles/ExternalPathParser.cs index 3bde3a1cf..1fa4fa537 100644 --- a/Emby.Naming/ExternalFiles/ExternalPathParser.cs +++ b/Emby.Naming/ExternalFiles/ExternalPathParser.cs @@ -99,6 +99,18 @@ namespace Emby.Naming.ExternalFiles pathInfo.Language = culture.ThreeLetterISOLanguageName; extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase); } + else if (culture != null && pathInfo.Language == "hin") + { + // Hindi language code "hi" collides with a hearing impaired flag - use as Hindi only if no other language is set + pathInfo.IsHearingImpaired = true; + pathInfo.Language = culture.ThreeLetterISOLanguageName; + extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase); + } + else if (_namingOptions.MediaHearingImpairedFlags.Any(s => currentSliceWithoutSeparator.Contains(s, StringComparison.OrdinalIgnoreCase))) + { + pathInfo.IsHearingImpaired = true; + extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase); + } else { titleString = currentSlice + titleString; diff --git a/Emby.Naming/ExternalFiles/ExternalPathParserResult.cs b/Emby.Naming/ExternalFiles/ExternalPathParserResult.cs index 1cc773a2e..b0d9e7a9f 100644 --- a/Emby.Naming/ExternalFiles/ExternalPathParserResult.cs +++ b/Emby.Naming/ExternalFiles/ExternalPathParserResult.cs @@ -11,11 +11,13 @@ namespace Emby.Naming.ExternalFiles /// <param name="path">Path to file.</param> /// <param name="isDefault">Is default.</param> /// <param name="isForced">Is forced.</param> - public ExternalPathParserResult(string path, bool isDefault = false, bool isForced = false) + /// <param name="isHearingImpaired">For the hearing impaired.</param> + public ExternalPathParserResult(string path, bool isDefault = false, bool isForced = false, bool isHearingImpaired = false) { Path = path; IsDefault = isDefault; IsForced = isForced; + IsHearingImpaired = isHearingImpaired; } /// <summary> @@ -47,5 +49,11 @@ namespace Emby.Naming.ExternalFiles /// </summary> /// <value><c>true</c> if this instance is forced; otherwise, <c>false</c>.</value> public bool IsForced { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether this instance is for the hearing impaired. + /// </summary> + /// <value><c>true</c> if this instance is for the hearing impaired; otherwise, <c>false</c>.</value> + public bool IsHearingImpaired { get; set; } } } diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index c42cec593..26b4649dd 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/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> public virtual void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration) { - if (newConfiguration == null) - { - throw new ArgumentNullException(nameof(newConfiguration)); - } + ArgumentNullException.ThrowIfNull(newConfiguration); ValidateCachePath(newConfiguration); diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 91a16c199..9a9de1059 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -630,8 +630,6 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>(); - serviceCollection.AddScoped<ISessionContext, SessionContext>(); - serviceCollection.AddSingleton<IAuthService, AuthService>(); serviceCollection.AddSingleton<IQuickConnect, QuickConnectManager>(); diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 92a85e862..6837cce5c 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -1188,10 +1188,7 @@ namespace Emby.Server.Implementations.Channels internal IChannel GetChannelProvider(Channel channel) { - if (channel == null) - { - throw new ArgumentNullException(nameof(channel)); - } + ArgumentNullException.ThrowIfNull(channel); var result = GetAllChannels() .FirstOrDefault(i => GetInternalChannelId(i.Name).Equals(channel.ChannelId) || string.Equals(i.Name, channel.Name, StringComparison.OrdinalIgnoreCase)); diff --git a/Emby.Server.Implementations/Data/SqliteExtensions.cs b/Emby.Server.Implementations/Data/SqliteExtensions.cs index 381eb92a8..736b8125d 100644 --- a/Emby.Server.Implementations/Data/SqliteExtensions.cs +++ b/Emby.Server.Implementations/Data/SqliteExtensions.cs @@ -54,10 +54,7 @@ namespace Emby.Server.Implementations.Data public static void RunQueries(this SQLiteDatabaseConnection connection, string[] queries) { - if (queries == null) - { - throw new ArgumentNullException(nameof(queries)); - } + ArgumentNullException.ThrowIfNull(queries); connection.RunInTransaction(conn => { diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 1b176e60d..7622d2fe6 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -178,7 +178,8 @@ namespace Emby.Server.Implementations.Data "RpuPresentFlag", "ElPresentFlag", "BlPresentFlag", - "DvBlSignalCompatibilityId" + "DvBlSignalCompatibilityId", + "IsHearingImpaired" }; private static readonly string _mediaStreamSaveColumnsInsertQuery = @@ -349,7 +350,8 @@ namespace Emby.Server.Implementations.Data public void Initialize(SqliteUserDataRepository userDataRepo, IUserManager userManager) { 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, 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))"; + = "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, IsHearingImpaired BIT NULL, PRIMARY KEY (ItemId, StreamIndex))"; + 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))"; @@ -572,6 +574,8 @@ namespace Emby.Server.Implementations.Data AddColumn(db, "MediaStreams", "ElPresentFlag", "INT", existingColumnNames); AddColumn(db, "MediaStreams", "BlPresentFlag", "INT", existingColumnNames); AddColumn(db, "MediaStreams", "DvBlSignalCompatibilityId", "INT", existingColumnNames); + + AddColumn(db, "MediaStreams", "IsHearingImpaired", "BIT", existingColumnNames); }, TransactionMode); @@ -583,10 +587,7 @@ namespace Emby.Server.Implementations.Data public void SaveImages(BaseItem item) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); CheckDisposed(); @@ -617,10 +618,7 @@ namespace Emby.Server.Implementations.Data /// </exception> public void SaveItems(IEnumerable<BaseItem> items, CancellationToken cancellationToken) { - if (items == null) - { - throw new ArgumentNullException(nameof(items)); - } + ArgumentNullException.ThrowIfNull(items); cancellationToken.ThrowIfCancellationRequested(); @@ -2085,10 +2083,7 @@ namespace Emby.Server.Implementations.Data throw new ArgumentNullException(nameof(id)); } - if (chapters == null) - { - throw new ArgumentNullException(nameof(chapters)); - } + ArgumentNullException.ThrowIfNull(chapters); var idBlob = id.ToByteArray(); @@ -2557,10 +2552,7 @@ namespace Emby.Server.Implementations.Data public int GetCount(InternalItemsQuery query) { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); CheckDisposed(); @@ -2613,10 +2605,7 @@ namespace Emby.Server.Implementations.Data public List<BaseItem> GetItemList(InternalItemsQuery query) { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); CheckDisposed(); @@ -2794,10 +2783,7 @@ namespace Emby.Server.Implementations.Data public QueryResult<BaseItem> GetItems(InternalItemsQuery query) { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); CheckDisposed(); @@ -3174,10 +3160,7 @@ namespace Emby.Server.Implementations.Data public List<Guid> GetItemIdsList(InternalItemsQuery query) { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); CheckDisposed(); @@ -4837,10 +4820,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type public List<string> GetPeopleNames(InternalPeopleQuery query) { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); CheckDisposed(); @@ -4880,10 +4860,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type public List<PersonInfo> GetPeople(InternalPeopleQuery query) { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); CheckDisposed(); @@ -4999,10 +4976,7 @@ AND Type = @InternalPersonType)"); throw new ArgumentNullException(nameof(itemId)); } - if (ancestorIds == null) - { - throw new ArgumentNullException(nameof(ancestorIds)); - } + ArgumentNullException.ThrowIfNull(ancestorIds); CheckDisposed(); @@ -5175,10 +5149,7 @@ AND Type = @InternalPersonType)"); 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) { @@ -5531,10 +5502,7 @@ AND Type = @InternalPersonType)"); throw new ArgumentNullException(nameof(itemId)); } - if (values == null) - { - throw new ArgumentNullException(nameof(values)); - } + ArgumentNullException.ThrowIfNull(values); CheckDisposed(); @@ -5607,10 +5575,7 @@ AND Type = @InternalPersonType)"); throw new ArgumentNullException(nameof(itemId)); } - if (people == null) - { - throw new ArgumentNullException(nameof(people)); - } + ArgumentNullException.ThrowIfNull(people); CheckDisposed(); @@ -5710,10 +5675,7 @@ AND Type = @InternalPersonType)"); { CheckDisposed(); - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); var cmdText = _mediaStreamSaveColumnsSelectQuery; @@ -5766,10 +5728,7 @@ AND Type = @InternalPersonType)"); throw new ArgumentNullException(nameof(id)); } - if (streams == null) - { - throw new ArgumentNullException(nameof(streams)); - } + ArgumentNullException.ThrowIfNull(streams); cancellationToken.ThrowIfCancellationRequested(); @@ -5881,6 +5840,8 @@ AND Type = @InternalPersonType)"); statement.TryBind("@ElPresentFlag" + index, stream.ElPresentFlag); statement.TryBind("@BlPresentFlag" + index, stream.BlPresentFlag); statement.TryBind("@DvBlSignalCompatibilityId" + index, stream.DvBlSignalCompatibilityId); + + statement.TryBind("@IsHearingImpaired" + index, stream.IsHearingImpaired); } statement.Reset(); @@ -6092,12 +6053,15 @@ AND Type = @InternalPersonType)"); item.DvBlSignalCompatibilityId = dvBlSignalCompatibilityId; } + item.IsHearingImpaired = reader.GetBoolean(43); + if (item.Type == MediaStreamType.Subtitle) { item.LocalizedUndefined = _localization.GetLocalizedString("Undefined"); item.LocalizedDefault = _localization.GetLocalizedString("Default"); item.LocalizedForced = _localization.GetLocalizedString("Forced"); item.LocalizedExternal = _localization.GetLocalizedString("External"); + item.LocalizedHearingImpaired = _localization.GetLocalizedString("HearingImpaired"); } return item; @@ -6107,10 +6071,7 @@ AND Type = @InternalPersonType)"); { CheckDisposed(); - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); var cmdText = _mediaAttachmentSaveColumnsSelectQuery; @@ -6152,10 +6113,7 @@ AND Type = @InternalPersonType)"); throw new ArgumentException("Guid can't be empty.", nameof(id)); } - if (attachments == null) - { - throw new ArgumentNullException(nameof(attachments)); - } + ArgumentNullException.ThrowIfNull(attachments); cancellationToken.ThrowIfCancellationRequested(); diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index ba86dc156..8d78d644d 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -133,10 +133,7 @@ namespace Emby.Server.Implementations.Data /// <inheritdoc /> 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) { @@ -154,10 +151,7 @@ namespace Emby.Server.Implementations.Data /// <inheritdoc /> public void SaveAllUserData(long userId, UserItemData[] userData, CancellationToken cancellationToken) { - if (userData == null) - { - throw new ArgumentNullException(nameof(userData)); - } + ArgumentNullException.ThrowIfNull(userData); if (userId <= 0) { @@ -304,10 +298,7 @@ namespace Emby.Server.Implementations.Data public UserItemData GetUserData(long userId, List<string> keys) { - if (keys == null) - { - throw new ArgumentNullException(nameof(keys)); - } + ArgumentNullException.ThrowIfNull(keys); if (keys.Count == 0) { diff --git a/Emby.Server.Implementations/Data/SynchronouseMode.cs b/Emby.Server.Implementations/Data/SynchronousMode.cs index cde524e2e..cde524e2e 100644 --- a/Emby.Server.Implementations/Data/SynchronouseMode.cs +++ b/Emby.Server.Implementations/Data/SynchronousMode.cs diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 09ba36851..3d2b8f7f6 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -182,7 +182,7 @@ namespace Emby.Server.Implementations.Dto if (options.ContainsField(ItemFields.People)) { - AttachPeople(dto, item); + AttachPeople(dto, item, user); } if (options.ContainsField(ItemFields.PrimaryImageAspectRatio)) @@ -503,7 +503,8 @@ namespace Emby.Server.Implementations.Dto /// </summary> /// <param name="dto">The dto.</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. // This is taking advantage of the fact that they both begin with A @@ -560,6 +561,9 @@ namespace Emby.Server.Implementations.Dto return null; } }).Where(i => i != null) + .Where(i => user == null ? + true : + i.IsVisible(user)) .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase) .Select(x => x.First()) .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 24395a193..2792a4c7c 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -29,7 +29,7 @@ <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.8" /> + <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" /> diff --git a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs deleted file mode 100644 index 15ab363fe..000000000 --- a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs +++ /dev/null @@ -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); - } - } -} diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 818ccbb1b..d095248fa 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -11,7 +11,6 @@ using Jellyfin.Extensions.Json; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Net; using MediaBrowser.Model.Session; -using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.HttpServer diff --git a/Emby.Server.Implementations/Images/DynamicImageProvider.cs b/Emby.Server.Implementations/Images/DynamicImageProvider.cs index 9f9a4902a..0faa0f8fa 100644 --- a/Emby.Server.Implementations/Images/DynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/DynamicImageProvider.cs @@ -93,6 +93,7 @@ namespace Emby.Server.Implementations.Images returnItems.Shuffle(); return returnItems; } + returnItems = items .Where(i => i.HasImage(ImageType.Primary)) .ToList(); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 679684552..ee94670eb 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -46,7 +46,6 @@ using MediaBrowser.Model.Library; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Caching.Memory; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Episode = MediaBrowser.Controller.Entities.TV.Episode; using EpisodeInfo = Emby.Naming.TV.EpisodeInfo; @@ -282,10 +281,7 @@ namespace Emby.Server.Implementations.Library public void RegisterItem(BaseItem item) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); if (item is IItemByName) { @@ -312,10 +308,7 @@ namespace Emby.Server.Implementations.Library 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(); @@ -324,10 +317,7 @@ namespace Emby.Server.Implementations.Library 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) { @@ -510,10 +500,7 @@ namespace Emby.Server.Implementations.Library throw new ArgumentNullException(nameof(key)); } - if (type == null) - { - throw new ArgumentNullException(nameof(type)); - } + ArgumentNullException.ThrowIfNull(type); string programDataPath = _configurationManager.ApplicationPaths.ProgramDataPath; if (key.StartsWith(programDataPath, StringComparison.Ordinal)) @@ -545,10 +532,7 @@ namespace Emby.Server.Implementations.Library string collectionType = null, LibraryOptions libraryOptions = null) { - if (fileInfo == null) - { - throw new ArgumentNullException(nameof(fileInfo)); - } + ArgumentNullException.ThrowIfNull(fileInfo); var fullPath = fileInfo.FullName; @@ -1855,10 +1839,7 @@ namespace Emby.Server.Implementations.Library /// <inheritdoc /> 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() @@ -2297,10 +2278,7 @@ namespace Emby.Server.Implementations.Library string viewType, string sortName) { - if (parent == null) - { - throw new ArgumentNullException(nameof(parent)); - } + ArgumentNullException.ThrowIfNull(parent); var name = parent.Name; var parentId = parent.Id; @@ -2766,7 +2744,8 @@ namespace Emby.Server.Implementations.Library public List<Person> GetPeopleItems(InternalPeopleQuery query) { - return _itemRepository.GetPeopleNames(query).Select(i => + return _itemRepository.GetPeopleNames(query) + .Select(i => { try { @@ -2777,7 +2756,12 @@ namespace Emby.Server.Implementations.Library _logger.LogError(ex, "Error getting person"); 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) @@ -2978,10 +2962,7 @@ namespace Emby.Server.Implementations.Library private void AddMediaPathInternal(string virtualFolderName, MediaPathInfo pathInfo, bool saveLibraryOptions) { - if (pathInfo == null) - { - throw new ArgumentNullException(nameof(pathInfo)); - } + ArgumentNullException.ThrowIfNull(pathInfo); var path = pathInfo.Path; @@ -3028,10 +3009,7 @@ namespace Emby.Server.Implementations.Library public void UpdateMediaPath(string virtualFolderName, MediaPathInfo mediaPath) { - if (mediaPath == null) - { - throw new ArgumentNullException(nameof(mediaPath)); - } + ArgumentNullException.ThrowIfNull(mediaPath); var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath; var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index c0aef1899..bfccc7db7 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -322,10 +322,7 @@ namespace Emby.Server.Implementations.Library 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; diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs index bc2915db6..af4abfb80 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/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) { - if (path == null) - { - throw new ArgumentNullException(nameof(path)); - } + ArgumentNullException.ThrowIfNull(path); var filename = Path.GetFileNameWithoutExtension(path); diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs index 3810a76c4..aecab7d9c 100644 --- a/Emby.Server.Implementations/Library/UserDataManager.cs +++ b/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) { - if (userData == null) - { - throw new ArgumentNullException(nameof(userData)); - } + ArgumentNullException.ThrowIfNull(userData); - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); cancellationToken.ThrowIfCancellationRequested(); @@ -194,10 +188,7 @@ namespace Emby.Server.Implementations.Library /// <exception cref="ArgumentNullException"><paramref name="data"/> is <c>null</c>.</exception> private UserItemDataDto GetUserItemDataDto(UserItemData data) { - if (data == null) - { - throw new ArgumentNullException(nameof(data)); - } + ArgumentNullException.ThrowIfNull(data); return new UserItemDataDto { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 065309688..4da677636 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1223,10 +1223,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private async Task RecordStream(TimerInfo timer, DateTime recordingEndDate, ActiveRecordingInfo activeRecordingInfo) { - if (timer == null) - { - throw new ArgumentNullException(nameof(timer)); - } + ArgumentNullException.ThrowIfNull(timer); LiveTvProgram programInfo = null; @@ -2347,10 +2344,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private IEnumerable<TimerInfo> GetTimersForSeries(SeriesTimerInfo seriesTimer) { - if (seriesTimer == null) - { - throw new ArgumentNullException(nameof(seriesTimer)); - } + ArgumentNullException.ThrowIfNull(seriesTimer); var query = new InternalItemsQuery { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index 46979bfc5..58b798ce6 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -84,10 +84,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public virtual void Update(T item) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); lock (_fileDataLock) { @@ -107,10 +104,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public virtual void Add(T item) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); lock (_fileDataLock) { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs index 6ad9ccdf6..40dcca94f 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs @@ -2,8 +2,8 @@ using System; using System.Globalization; -using MediaBrowser.Controller.LiveTv; using System.Text; +using MediaBrowser.Controller.LiveTv; namespace Emby.Server.Implementations.LiveTv.EmbyTV { @@ -56,7 +56,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } tmpName += " " + info.EpisodeTitle; - // Since the filename will be used with file ext. (.mp4, .ts, etc) + // Since the filename will be used with file ext. (.mp4, .ts, etc) if (Encoding.UTF8.GetByteCount(tmpName) < 250) { name = tmpName; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index be06356a4..a423ec8f4 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/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) { - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } + ArgumentNullException.ThrowIfNull(info); if (!info.Url.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { diff --git a/Emby.Server.Implementations/Localization/Core/en-US.json b/Emby.Server.Implementations/Localization/Core/en-US.json index d8c33d51b..15088384c 100644 --- a/Emby.Server.Implementations/Localization/Core/en-US.json +++ b/Emby.Server.Implementations/Localization/Core/en-US.json @@ -28,6 +28,7 @@ "HeaderLiveTV": "Live TV", "HeaderNextUp": "Next Up", "HeaderRecordingGroups": "Recording Groups", + "HearingImpaired": "Hearing Impaired", "HomeVideos": "Home Videos", "Inherit": "Inherit", "ItemAddedWithName": "{0} was added to the library", diff --git a/Emby.Server.Implementations/Localization/Core/et.json b/Emby.Server.Implementations/Localization/Core/et.json index 8db6a0b38..da44e53d0 100644 --- a/Emby.Server.Implementations/Localization/Core/et.json +++ b/Emby.Server.Implementations/Localization/Core/et.json @@ -119,5 +119,6 @@ "SubtitleDownloadFailureFromForItem": "Subtiitrite allalaadimine {0} > {1} nurjus", "UserPolicyUpdatedWithName": "Kasutaja {0} õigusi värskendati", "UserStoppedPlayingItemWithValues": "{0} lõpetas {1} taasesituse seadmes {2}", - "UserOnlineFromDevice": "{0} on ühendatud seadmest {1}" + "UserOnlineFromDevice": "{0} on ühendatud seadmest {1}", + "External": "Väline" } diff --git a/Emby.Server.Implementations/Localization/Core/hr.json b/Emby.Server.Implementations/Localization/Core/hr.json index d2b5122b2..c63cd2b94 100644 --- a/Emby.Server.Implementations/Localization/Core/hr.json +++ b/Emby.Server.Implementations/Localization/Core/hr.json @@ -122,5 +122,6 @@ "TaskOptimizeDatabase": "Optimiziraj bazu podataka", "External": "Vanjski", "TaskKeyframeExtractorDescription": "Izvlačenje ključnih okvira iz videozapisa za stvaranje objektivnije HLS liste za reprodukciju. Pokretanje ovog zadatka može potrajati.", - "TaskKeyframeExtractor": "Izvoditelj ključnog okvira" + "TaskKeyframeExtractor": "Izvoditelj ključnog okvira", + "TaskOptimizeDatabaseDescription": "Sažima bazu podataka i uklanja prazan prostor. Pokretanje ovog zadatka, može poboljšati performanse nakon provođenja indeksiranja biblioteke ili provođenja drugih promjena koje utječu na bazu podataka." } diff --git a/Emby.Server.Implementations/Localization/Core/ko.json b/Emby.Server.Implementations/Localization/Core/ko.json index 186ec44d2..a4b2e75b3 100644 --- a/Emby.Server.Implementations/Localization/Core/ko.json +++ b/Emby.Server.Implementations/Localization/Core/ko.json @@ -3,14 +3,14 @@ "AppDeviceValues": "앱: {0}, 장치: {1}", "Application": "애플리케이션", "Artists": "아티스트", - "AuthenticationSucceededWithUserName": "{0}이 성공적으로 인증됨", + "AuthenticationSucceededWithUserName": "{0}이(가) 성공적으로 인증됨", "Books": "도서", "CameraImageUploadedFrom": "{0}에서 새로운 카메라 이미지가 업로드됨", "Channels": "채널", "ChapterNameValue": "챕터 {0}", "Collections": "컬렉션", "DeviceOfflineWithName": "{0}의 연결 끊김", - "DeviceOnlineWithName": "{0}이 연결됨", + "DeviceOnlineWithName": "{0}이(가) 연결됨", "FailedLoginAttemptWithUserName": "{0}에서 로그인 실패", "Favorites": "즐겨찾기", "Folders": "폴더", diff --git a/Emby.Server.Implementations/Localization/Core/lv.json b/Emby.Server.Implementations/Localization/Core/lv.json index 443a74a10..e460fd719 100644 --- a/Emby.Server.Implementations/Localization/Core/lv.json +++ b/Emby.Server.Implementations/Localization/Core/lv.json @@ -84,7 +84,7 @@ "CameraImageUploadedFrom": "Jauns kameras attēls ir ticis augšupielādēts no {0}", "Books": "Grāmatas", "Artists": "Izpildītāji", - "Albums": "Albumi", + "Albums": "Albūmi", "ProviderValue": "Provider: {0}", "HeaderFavoriteSongs": "Dziesmu Favorīti", "HeaderFavoriteShows": "Raidījumu Favorīti", @@ -117,7 +117,8 @@ "TaskCleanActivityLogDescription": "Nodzēš darbību žurnāla ierakstus, kuri ir vecāki par doto vecumu.", "TaskCleanActivityLog": "Notīrīt Darbību Žurnālu", "Undefined": "Nenoteikts", - "Default": "Noklusējums", + "Default": "Noklusējuma", "TaskOptimizeDatabaseDescription": "Saspiež datubāzi un atbrīvo atmiņu. Uzdevum palaišana pēc bibliotēku skenēšanas vai citām, ar datubāzi saistītām, izmaiņām iespējams uzlabos ātrdarbību.", - "TaskOptimizeDatabase": "Optimizēt datubāzi" + "TaskOptimizeDatabase": "Optimizēt datubāzi", + "External": "Ārējais" } diff --git a/Emby.Server.Implementations/Localization/Core/mk.json b/Emby.Server.Implementations/Localization/Core/mk.json index 3483a7f0c..cbccad87f 100644 --- a/Emby.Server.Implementations/Localization/Core/mk.json +++ b/Emby.Server.Implementations/Localization/Core/mk.json @@ -64,7 +64,7 @@ "CameraImageUploadedFrom": "Нова слика од камера беше поставена од {0}", "Books": "Книги", "AuthenticationSucceededWithUserName": "{0} успешно поврзан", - "Artists": "Изведувач", + "Artists": "Изведувачи", "Application": "Апликација", "AppDeviceValues": "Апликација: {0}, Уред: {1}", "Albums": "Албуми", diff --git a/Emby.Server.Implementations/Localization/Core/pt-PT.json b/Emby.Server.Implementations/Localization/Core/pt-PT.json index 44600374b..7047f1c28 100644 --- a/Emby.Server.Implementations/Localization/Core/pt-PT.json +++ b/Emby.Server.Implementations/Localization/Core/pt-PT.json @@ -8,15 +8,15 @@ "CameraImageUploadedFrom": "Uma nova imagem de câmara foi enviada a partir de {0}", "Channels": "Canais", "ChapterNameValue": "Capítulo {0}", - "Collections": "Coleções", + "Collections": "Colecções", "DeviceOfflineWithName": "{0} desligou-se", "DeviceOnlineWithName": "{0} ligou-se", "FailedLoginAttemptWithUserName": "Tentativa de login falhada a partir de {0}", "Favorites": "Favoritos", "Folders": "Pastas", "Genres": "Géneros", - "HeaderAlbumArtists": "Artistas do Álbum", - "HeaderContinueWatching": "Continuar a Ver", + "HeaderAlbumArtists": "Artistas do álbum", + "HeaderContinueWatching": "Continuar a ver", "HeaderFavoriteAlbums": "Álbuns Favoritos", "HeaderFavoriteArtists": "Artistas Favoritos", "HeaderFavoriteEpisodes": "Episódios Favoritos", diff --git a/Emby.Server.Implementations/Localization/Core/pt.json b/Emby.Server.Implementations/Localization/Core/pt.json index 69bc4c90f..c2c77ccab 100644 --- a/Emby.Server.Implementations/Localization/Core/pt.json +++ b/Emby.Server.Implementations/Localization/Core/pt.json @@ -1,5 +1,5 @@ { - "HeaderLiveTV": "TV Ao Vivo", + "HeaderLiveTV": "TV Em Direto", "Collections": "Coleções", "Books": "Livros", "Artists": "Artistas", @@ -10,9 +10,9 @@ "HeaderFavoriteAlbums": "Álbuns Favoritos", "HeaderFavoriteEpisodes": "Episódios Favoritos", "HeaderFavoriteShows": "Séries Favoritas", - "HeaderContinueWatching": "Continuar assistindo", + "HeaderContinueWatching": "Continuar a ver", "HeaderAlbumArtists": "Artistas do Álbum", - "Genres": "Gêneros", + "Genres": "Géneros", "Folders": "Diretórios", "Favorites": "Favoritos", "Channels": "Canais", @@ -74,7 +74,7 @@ "ItemRemovedWithName": "{0} foi removido da biblioteca", "ItemAddedWithName": "{0} foi adicionado à biblioteca", "Inherit": "Herdar", - "HomeVideos": "Vídeos principais", + "HomeVideos": "Vídeos Caseiros", "HeaderRecordingGroups": "Grupos de Gravação", "ValueSpecialEpisodeName": "Episódio Especial - {0}", "Sync": "Sincronização", @@ -83,14 +83,14 @@ "Playlists": "Listas de Reprodução", "Photos": "Fotografias", "Movies": "Filmes", - "FailedLoginAttemptWithUserName": "Tentativa falha de login a partir de {0}", - "DeviceOnlineWithName": "{0} está conectado", - "DeviceOfflineWithName": "{0} desconectou-se", + "FailedLoginAttemptWithUserName": "Tentativa de início de sessão falhada a partir de {0}", + "DeviceOnlineWithName": "{0} está ligado", + "DeviceOfflineWithName": "{0} desligou-se", "ChapterNameValue": "Capítulo {0}", "CameraImageUploadedFrom": "Uma nova imagem da câmara foi enviada a partir de {0}", "AuthenticationSucceededWithUserName": "{0} autenticado com sucesso", - "Application": "Aplicativo", - "AppDeviceValues": "Aplicativo {0}, Dispositivo: {1}", + "Application": "Aplicação", + "AppDeviceValues": "Aplicação: {0}, Dispositivo: {1}", "TaskCleanCache": "Limpar Diretório de Cache", "TasksApplicationCategory": "Aplicativo", "TasksLibraryCategory": "Biblioteca", diff --git a/Emby.Server.Implementations/Localization/Core/sl-SI.json b/Emby.Server.Implementations/Localization/Core/sl-SI.json index b2d7ce11d..d845accac 100644 --- a/Emby.Server.Implementations/Localization/Core/sl-SI.json +++ b/Emby.Server.Implementations/Localization/Core/sl-SI.json @@ -90,7 +90,7 @@ "UserStartedPlayingItemWithValues": "{0} predvaja {1} na {2}", "UserStoppedPlayingItemWithValues": "{0} je nehal predvajati {1} na {2}", "ValueHasBeenAddedToLibrary": "{0} je bil dodan vaši knjižnici", - "ValueSpecialEpisodeName": "Bonus - {0}", + "ValueSpecialEpisodeName": "Posebna epizoda - {0}", "VersionNumber": "Različica {0}", "TaskDownloadMissingSubtitles": "Prenesi manjkajoče podnapise", "TaskRefreshChannelsDescription": "Osveži podatke spletnih kanalov.", diff --git a/Emby.Server.Implementations/Localization/Core/ug.json b/Emby.Server.Implementations/Localization/Core/ug.json index aea93c7fa..0bcbffb41 100644 --- a/Emby.Server.Implementations/Localization/Core/ug.json +++ b/Emby.Server.Implementations/Localization/Core/ug.json @@ -3,7 +3,122 @@ "Channels": "قانال", "CameraImageUploadedFrom": "{0} ئورۇندىن يېڭى سۈرەت چىقىرىلدى", "Books": "كىتاب", - "AuthenticationSucceededWithUserName": "تىزىملىتىش مۇۋەپپەقىيەتلىك بول", + "AuthenticationSucceededWithUserName": "{0} تەستىقلاش مۇۋاپىقىيەتلىك بولدى", "Artists": "سەنئەتكار", - "Albums": "پىلاستىنكا" + "Albums": "پىلاستىنكا", + "DeviceOnlineWithName": "{0} ئۇلاندى", + "DeviceOfflineWithName": "{0} ئۈزۈلدى", + "Collections": "توپلام", + "Application": "ئەپ", + "AppDeviceValues": "ئەپ: {0}، ئۈسكۈنە: {1}", + "HeaderLiveTV": "تور تېلېۋىزىيەسى", + "Default": "سۈكۈتتىكى", + "Folders": "ھۆججەت خالتىسى", + "Favorites": "ساقلىغۇچ", + "LabelRunningTimeValue": "ئىجرا بولغان ۋاقتى:{0}", + "HeaderRecordingGroups": "خاتىرلەش گۇرۇپىسى", + "Forced": "ئەڭ", + "TaskKeyframeExtractor": "ھالقىلىق رامكا ئاجراتقۇچ", + "TaskKeyframeExtractorDescription": "سىن ھۆججەتلىرىدىن رامكا ئاجرىتىپ، تېخىمۇ ئېنىق بولغان HLS قويۇلۇش تىزىملىكىنى قۇرۇلىدۇ. بۇ ۋەزىپە ئۇزۇن داۋام قىلىشى مۇمكىن.", + "TaskOptimizeDatabase": "سانداننى ئەلالاشتۇرۇش", + "TaskDownloadMissingSubtitlesDescription": "ئامىللار تەڭشىكىگە ئاساسەن توردىن كەم بولغان فىلىم خېتىنى ئىزدەش.", + "TaskDownloadMissingSubtitles": "كەم بولغان فىلىم خەتلىرىنى چۈشۈرۈش", + "TasksChannelsCategory": "ئىنتېرنېت قاناللىرى", + "TaskRefreshChannelsDescription": "ئىنتېرنېت قانىلى ئۇچۇرىنى يېڭىلاش.", + "TaskRefreshChannels": "قانالنى يېڭىلاش", + "TaskCleanTranscodeDescription": "بىر كۈندىن ئاشقان ئالماشتۇرۇش ھۆججەتلىرىنى ئۆچۈرۈش.", + "TaskCleanTranscode": "ئايلاندۇرۇش ھۆججەت قىسقۇچىنى تازىلاش", + "TaskUpdatePluginsDescription": "ئاپتوماتىك يېڭىلاشقا بېكىتىلگەن قىستۇرمىلارنىڭ يېڭىلانمىسىنى چۈشۈرۈش ۋە قاچىلاش.", + "TaskUpdatePlugins": "قىستۇرمىلارنى يېڭىلاش", + "TaskRefreshPeopleDescription": "مېدىيا ئامبىرىدىكى ئارتىس ۋە رېژىسسورلارنىڭ ئۇچۇرىنى يېڭىلاش.", + "TaskRefreshPeople": "ئابونتلارنى يېڭىلاش", + "TaskCleanLogsDescription": "{0} كۈندىن ئاشقان Log ھۆججىتىنى ئۆچۈرۈش.", + "TaskCleanLogs": "Log ھۆججەت قسقۇچىنى تازىلاش", + "TaskRefreshLibraryDescription": "مېدىيا ئامبىرىغا قوشۇلغان يېڭى ھۆججەتلەرنى ئىزدەش ۋە مېدىيا ئۇچۇرلىرىنى يېڭىلاش.", + "TaskRefreshLibrary": "مېدىيا ئامبىرىنى سىكاننېرلاش", + "TaskRefreshChapterImagesDescription": "ۋېدىئو بۆلەكلىرى ئۈچۈن كىچىك سۈرەت ياساش.", + "TaskRefreshChapterImages": "بۆلەكلەر رەسىملىرىنى چىقىرىۋېلىش", + "TaskCleanCacheDescription": "سىستېما ئىھتىياجى يوق بولغان ۋاقىتلىق ھۆججەتلەرنى ئۆچۈرۈش.", + "TaskCleanCache": "ۋاقىتلىق ھۆججەت قىسقۇچنى تازىلاش", + "TaskCleanActivityLogDescription": "ۋاقىت تەڭشىكىدىن بۇرۇنقى پائالىيەت خاتىرىسى خاتىرىسىنى ئۆچۈرۈش.", + "TaskCleanActivityLog": "پروگرامما خاتىرىسىنى تازىلاش", + "TasksApplicationCategory": "پروگرامما", + "TasksLibraryCategory": "مېدىيا ئامبىرى", + "TasksMaintenanceCategory": "ئاسراش", + "VersionNumber": "نەشرى {0}", + "ValueSpecialEpisodeName": "خاسلىق - {0}", + "ValueHasBeenAddedToLibrary": "{0} مېدىيا ئامبىرىڭىزغا قوشۇلدى", + "UserStoppedPlayingItemWithValues": "{0}،{1} نى {2} دە قويۇنشتىن توختىدى", + "UserStartedPlayingItemWithValues": "{0}،{1} نى {2} دە قويۇۋاتىدۇ", + "UserPolicyUpdatedWithName": "ئابونتلار سىياسىتى {0} غا يېڭىلاندى", + "UserPasswordChangedWithName": "ئابونت{0} ئۈچۈن پارول ئۆزگەرتىلدى", + "UserOfflineFromDevice": "{0} بىلەن {1} نىڭ ئالاقىسى ئۈزۈلدى", + "UserLockedOutWithName": "ئابونت {0} قۇلۇپلاندى", + "UserDownloadingItemWithValues": "{0} چۈشۈرۈۋاتىدۇ {1}", + "UserDeletedWithName": "{0} ئابونت ئۆچۈرۈلدى", + "UserCreatedWithName": "{0} ئابونت يېڭىدىن قوشۇلدى", + "User": "ئابونت", + "Undefined": "بېكىتىلمىگەن", + "TvShows": "تىياتىرلار", + "System": "سىستېما", + "Sync": "ماس قەدەمدەش", + "SubtitleDownloadFailureFromForItem": "{0} دىن {0} نىڭ فىلىم خېتىنى چۈشۈرگىلى بولمىدى", + "StartupEmbyServerIsLoading": "Jellyfin مۇلازىمىتېرى يۈكلىنىۋاتىدۇ. سەل تۇرۇپ قايتا سىناڭ.", + "Songs": "ناخشىلار", + "Shows": "پروگراممىلار", + "ServerNameNeedsToBeRestarted": "{0} قايتا قوزغىتىلىشى كېرەك", + "ScheduledTaskStartedWithName": "{0} باشلاندى", + "ScheduledTaskFailedWithName": "{0} مەغلۇپ بولدى", + "ProviderValue": "تەمىنلىگۈچى: {0}", + "PluginUpdatedWithName": "{0} يېڭىلاندى", + "PluginUninstalledWithName": "{0} ئۆچۈرۈلدى", + "PluginInstalledWithName": "{0} قاچىلاندى", + "Plugin": "قىستۇرما", + "Playlists": "قويۇش تىزىملىكى", + "Photos": "رەسىملەر", + "NotificationOptionVideoPlaybackStopped": "سىن قويۇلۇش توختىدى", + "NotificationOptionVideoPlayback": "سىن قويۇلدى", + "NotificationOptionUserLockedOut": "ئابونت قۇلۇپلاندى", + "NotificationOptionTaskFailed": "بەلگىلەنگەن ۋەزىپە مەغلۇپ بولدى", + "NotificationOptionServerRestartRequired": "مۇلازىمىتېر قايتا قوزغىتىلىشى كېرەك", + "NotificationOptionPluginUpdateInstalled": "قىستۇرما يېڭىلانمىسى قاچىلاندى", + "NotificationOptionPluginInstalled": "قىستۇرما قاچىلاندى", + "NotificationOptionPluginUninstalled": "قىستۇرما ئۆچۈرۈلدى", + "NotificationOptionPluginError": "قىستۇرما خاتالىقى", + "NotificationOptionNewLibraryContent": "يېڭى مەزمۇن قوشۇلدى", + "NotificationOptionInstallationFailed": "قاچىلاش مەغلۇب بولدى", + "NotificationOptionCameraImageUploaded": "كامىكامېرا سۈرىتى يوللاندى", + "NotificationOptionAudioPlayback": "ئاۋاز قويۇش باشلاندى", + "NotificationOptionAudioPlaybackStopped": "ئاۋاز قويۇش توختىدى", + "NotificationOptionApplicationUpdateInstalled": "ئەپ يېڭىلانمىسى ئورنىتىلدى", + "NotificationOptionApplicationUpdateAvailable": "ئەپنىڭ نەشرىنى يېڭىلىغىلى بولۇدۇ", + "NewVersionIsAvailable": "Jellyfin Server نىڭ يېڭى نۇسخىسىنى چۈشۈرگىلى بولىدۇ.", + "NameSeasonUnknown": "نامەمۇم بۆلۈم", + "NameSeasonNumber": "{0}-بۆلۈم", + "NameInstallFailed": "{0} قاچىلاش مەغلۇپ بولدى", + "MusicVideos": "سىنلىق مۇزىكا", + "Music": "مۇزىكا", + "Movies": "فىلىملەر", + "MixedContent": "ئارىلاشما مەزمۇن", + "MessageNamedServerConfigurationUpdatedWithValue": "مۇلازىمىتېر تەڭشىكىنىڭ {0} قىسمى يېڭىلىنىپ بولدى", + "MessageServerConfigurationUpdated": "مۇلازىمىتېر يېڭىلىنىپ بولدى", + "MessageApplicationUpdated": "Jellyfin مۇلازىمىتېرى يېڭىلاندى", + "MessageApplicationUpdatedTo": "Jellyfin مۇلازىمىتېر نەشرى {0} گە يېڭىلاندى", + "Latest": "ئەڭ يېڭى", + "LabelIpAddressValue": "{0}: IP ئادرىسى", + "ItemRemovedWithName": "{0} ئامباردىن چىقىرىلدى", + "ItemAddedWithName": "{0} ئامبارغا قوشۇلدى", + "Inherit": "داۋاملاشتۇرۇش", + "HomeVideos": "ئائىلە سىنلىرى", + "HeaderNextUp": "كېيىنكىسى", + "HeaderFavoriteSongs": "ئەڭ ياقتۇرىدىغان ناخشىلار", + "HeaderFavoriteShows": "ئەڭ ياقتۇرىدىغان پروگراممىلار", + "HeaderFavoriteEpisodes": "ئەڭ ياقتۇرىدىغان تىياتېرلار", + "HeaderFavoriteArtists": "ئەڭ ياقتۇرىدىغان سەنئەتكارلار", + "HeaderFavoriteAlbums": "ياقتۇرىدىغان پىلاستىنكىلار", + "HeaderContinueWatching": "داۋاملىق كۆرۈش", + "HeaderAlbumArtists": "پىلاستىنكا سەنئەتكارلىرى", + "Genres": "ئۇسلۇبلار", + "FailedLoginAttemptWithUserName": "{0} كىرىش ئوڭۇشلۇق بولمىدى", + "External": "سىرتقى" } diff --git a/Emby.Server.Implementations/Localization/Core/zh-HK.json b/Emby.Server.Implementations/Localization/Core/zh-HK.json index ac74da67d..6c8bf7627 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-HK.json +++ b/Emby.Server.Implementations/Localization/Core/zh-HK.json @@ -120,5 +120,8 @@ "Default": "預設", "TaskOptimizeDatabaseDescription": "壓縮數據庫並截斷可用空間。在掃描媒體庫或執行其他數據庫的修改後運行此任務可能會提高性能。", "TaskOptimizeDatabase": "最佳化數據庫", - "TaskCleanActivityLogDescription": "刪除早於設定時間的日誌記錄。" + "TaskCleanActivityLogDescription": "刪除早於設定時間的日誌記錄。", + "TaskKeyframeExtractorDescription": "提取關鍵格以創建更準確的HLS播放列表。次指示可能用時很長。", + "TaskKeyframeExtractor": "關鍵幀提取器", + "External": "外部" } diff --git a/Emby.Server.Implementations/Localization/Ratings/fi.csv b/Emby.Server.Implementations/Localization/Ratings/fi.csv new file mode 100644 index 000000000..782785890 --- /dev/null +++ b/Emby.Server.Implementations/Localization/Ratings/fi.csv @@ -0,0 +1,10 @@ +FI-S,1 +FI-T,1 +FI-7,4 +FI-12,5 +FI-16,8 +FI-18,9 +FI-K7,4 +FI-K12,5 +FI-K16,8 +FI-K18,9 diff --git a/Emby.Server.Implementations/Localization/Ratings/no.csv b/Emby.Server.Implementations/Localization/Ratings/no.csv new file mode 100644 index 000000000..127407be8 --- /dev/null +++ b/Emby.Server.Implementations/Localization/Ratings/no.csv @@ -0,0 +1,6 @@ +NO-A,1 +NO-6,3 +NO-9,4 +NO-12,5 +NO-15,8 +NO-18,9 diff --git a/Emby.Server.Implementations/Localization/Ratings/se.csv b/Emby.Server.Implementations/Localization/Ratings/se.csv new file mode 100644 index 000000000..1443c07df --- /dev/null +++ b/Emby.Server.Implementations/Localization/Ratings/se.csv @@ -0,0 +1,5 @@ +SE-Btl,1 +SE-Barntillåten,1 +SE-7,3 +SE-11,5 +SE-15,8 diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs index 21795c8f8..303875df5 100644 --- a/Emby.Server.Implementations/Net/SocketFactory.cs +++ b/Emby.Server.Implementations/Net/SocketFactory.cs @@ -63,10 +63,7 @@ namespace Emby.Server.Implementations.Net /// <inheritdoc /> public ISocket CreateUdpMulticastSocket(IPAddress ipAddress, int multicastTimeToLive, int localPort) { - if (ipAddress == null) - { - throw new ArgumentNullException(nameof(ipAddress)); - } + ArgumentNullException.ThrowIfNull(ipAddress); if (multicastTimeToLive <= 0) { diff --git a/Emby.Server.Implementations/Net/UdpSocket.cs b/Emby.Server.Implementations/Net/UdpSocket.cs index 2c20daa57..c3994fc04 100644 --- a/Emby.Server.Implementations/Net/UdpSocket.cs +++ b/Emby.Server.Implementations/Net/UdpSocket.cs @@ -35,10 +35,7 @@ namespace Emby.Server.Implementations.Net public UdpSocket(Socket socket, int localPort, IPAddress ip) { - if (socket == null) - { - throw new ArgumentNullException(nameof(socket)); - } + ArgumentNullException.ThrowIfNull(socket); _socket = socket; _localPort = localPort; @@ -51,10 +48,7 @@ namespace Emby.Server.Implementations.Net public UdpSocket(Socket socket, IPEndPoint endPoint) { - if (socket == null) - { - throw new ArgumentNullException(nameof(socket)); - } + ArgumentNullException.ThrowIfNull(socket); _socket = socket; _socket.Connect(endPoint); diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index 45ef36441..ec4e0dbeb 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -234,10 +234,7 @@ namespace Emby.Server.Implementations.Plugins /// <returns>Outcome of the operation.</returns> public bool RemovePlugin(LocalPlugin plugin) { - if (plugin == null) - { - throw new ArgumentNullException(nameof(plugin)); - } + ArgumentNullException.ThrowIfNull(plugin); if (DeletePlugin(plugin)) { @@ -288,10 +285,7 @@ namespace Emby.Server.Implementations.Plugins /// <param name="plugin">The <see cref="LocalPlugin"/> of the plug to disable.</param> public void EnablePlugin(LocalPlugin plugin) { - if (plugin == null) - { - throw new ArgumentNullException(nameof(plugin)); - } + ArgumentNullException.ThrowIfNull(plugin); if (ChangePluginState(plugin, PluginStatus.Active)) { @@ -306,10 +300,7 @@ namespace Emby.Server.Implementations.Plugins /// <param name="plugin">The <see cref="LocalPlugin"/> of the plug to disable.</param> public void DisablePlugin(LocalPlugin plugin) { - if (plugin == null) - { - throw new ArgumentNullException(nameof(plugin)); - } + ArgumentNullException.ThrowIfNull(plugin); // Update the manifest on disk if (ChangePluginState(plugin, PluginStatus.Disabled)) @@ -326,10 +317,7 @@ namespace Emby.Server.Implementations.Plugins public void FailPlugin(Assembly assembly) { // Only save if disabled. - if (assembly == null) - { - throw new ArgumentNullException(nameof(assembly)); - } + ArgumentNullException.ThrowIfNull(assembly); var plugin = _plugins.FirstOrDefault(p => p.DllFiles.Contains(assembly.Location)); if (plugin == null) diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 2c4d6884d..b370e06ef 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -92,25 +92,13 @@ namespace Emby.Server.Implementations.ScheduledTasks /// </exception> public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, ILogger logger) { - if (scheduledTask == null) - { - throw new ArgumentNullException(nameof(scheduledTask)); - } + ArgumentNullException.ThrowIfNull(scheduledTask); - if (applicationPaths == null) - { - throw new ArgumentNullException(nameof(applicationPaths)); - } + ArgumentNullException.ThrowIfNull(applicationPaths); - if (taskManager == null) - { - throw new ArgumentNullException(nameof(taskManager)); - } + ArgumentNullException.ThrowIfNull(taskManager); - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } + ArgumentNullException.ThrowIfNull(logger); ScheduledTask = scheduledTask; _applicationPaths = applicationPaths; @@ -249,10 +237,7 @@ namespace Emby.Server.Implementations.ScheduledTasks get => _triggers; set { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } + ArgumentNullException.ThrowIfNull(value); // Cleanup current triggers if (_triggers != null) @@ -281,10 +266,7 @@ namespace Emby.Server.Implementations.ScheduledTasks set { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } + ArgumentNullException.ThrowIfNull(value); // This null check is not great, but is needed to handle bad user input, or user mucking with the config file incorrectly var triggerList = value.Where(i => i != null).ToArray(); diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 7f927e270..0d1029882 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -665,10 +665,7 @@ namespace Emby.Server.Implementations.Session { CheckDisposed(); - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } + ArgumentNullException.ThrowIfNull(info); var session = GetSession(info.SessionId); @@ -762,10 +759,7 @@ namespace Emby.Server.Implementations.Session { CheckDisposed(); - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } + ArgumentNullException.ThrowIfNull(info); var session = GetSession(info.SessionId); @@ -897,10 +891,7 @@ namespace Emby.Server.Implementations.Session { CheckDisposed(); - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } + ArgumentNullException.ThrowIfNull(info); if (info.PositionTicks.HasValue && info.PositionTicks.Value < 0) { @@ -1341,15 +1332,9 @@ namespace Emby.Server.Implementations.Session private static void AssertCanControl(SessionInfo session, SessionInfo controllingSession) { - if (session == null) - { - throw new ArgumentNullException(nameof(session)); - } + ArgumentNullException.ThrowIfNull(session); - if (controllingSession == null) - { - throw new ArgumentNullException(nameof(controllingSession)); - } + ArgumentNullException.ThrowIfNull(controllingSession); } /// <summary> @@ -1688,10 +1673,7 @@ namespace Emby.Server.Implementations.Session /// </summary> private BaseItemDto GetItemInfo(BaseItem item, MediaSourceInfo mediaSource) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); var dtoOptions = _itemInfoDtoOptions; @@ -1802,10 +1784,7 @@ namespace Emby.Server.Implementations.Session /// <inheritdoc /> public Task<SessionInfo> GetSessionByAuthenticationToken(Device info, string deviceId, string remoteEndpoint, string appVersion) { - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } + ArgumentNullException.ThrowIfNull(info); var user = info.UserId.Equals(default) ? null diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs index fccf50f60..c654828b1 100644 --- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Extensions; +using Jellyfin.Api.Extensions; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Net; @@ -54,7 +54,6 @@ namespace Emby.Server.Implementations.Session private readonly ISessionManager _sessionManager; private readonly ILogger<SessionWebSocketListener> _logger; private readonly ILoggerFactory _loggerFactory; - private readonly IAuthorizationContext _authorizationContext; /// <summary> /// The KeepAlive cancellation token. @@ -67,17 +66,14 @@ namespace Emby.Server.Implementations.Session /// <param name="logger">The logger.</param> /// <param name="sessionManager">The session manager.</param> /// <param name="loggerFactory">The logger factory.</param> - /// <param name="authorizationContext">The authorization context.</param> public SessionWebSocketListener( ILogger<SessionWebSocketListener> logger, ISessionManager sessionManager, - ILoggerFactory loggerFactory, - IAuthorizationContext authorizationContext) + ILoggerFactory loggerFactory) { _logger = logger; _sessionManager = sessionManager; _loggerFactory = loggerFactory; - _authorizationContext = authorizationContext; } /// <inheritdoc /> @@ -111,21 +107,18 @@ namespace Emby.Server.Implementations.Session private async Task<SessionInfo> GetSession(HttpContext httpContext, string remoteEndpoint) { - var authorizationInfo = await _authorizationContext.GetAuthorizationInfo(httpContext) - .ConfigureAwait(false); - - if (!authorizationInfo.IsAuthenticated) + if (!httpContext.User.Identity?.IsAuthenticated ?? false) { return null; } - var deviceId = authorizationInfo.DeviceId; + var deviceId = httpContext.User.GetDeviceId(); if (httpContext.Request.Query.TryGetValue("deviceId", out var queryDeviceId)) { deviceId = queryDeviceId; } - return await _sessionManager.GetSessionByAuthenticationToken(authorizationInfo.Token, deviceId, remoteEndpoint) + return await _sessionManager.GetSessionByAuthenticationToken(httpContext.User.GetToken(), deviceId, remoteEndpoint) .ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs index db8b68949..2d21bd9c2 100644 --- a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -24,15 +24,9 @@ namespace Emby.Server.Implementations.Sorting /// <returns>System.Int32.</returns> public int Compare(BaseItem? x, BaseItem? y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); var episode1 = x as Episode; var episode2 = y as Episode; diff --git a/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs b/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs index 5f142fa4b..5cb11ab46 100644 --- a/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs +++ b/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs @@ -23,15 +23,9 @@ namespace Emby.Server.Implementations.Sorting /// <returns>System.Int32.</returns> public int Compare(BaseItem? x, BaseItem? y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); return (x.CommunityRating ?? 0).CompareTo(y.CommunityRating ?? 0); } diff --git a/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs b/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs index 8b460166c..6133aaccc 100644 --- a/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs +++ b/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs @@ -24,15 +24,9 @@ namespace Emby.Server.Implementations.Sorting /// <returns>System.Int32.</returns> public int Compare(BaseItem? x, BaseItem? y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); return DateTime.Compare(x.DateCreated, y.DateCreated); } diff --git a/Emby.Server.Implementations/Sorting/IndexNumberComparer.cs b/Emby.Server.Implementations/Sorting/IndexNumberComparer.cs index c5b00afb1..1bcaccd8a 100644 --- a/Emby.Server.Implementations/Sorting/IndexNumberComparer.cs +++ b/Emby.Server.Implementations/Sorting/IndexNumberComparer.cs @@ -24,15 +24,9 @@ namespace Emby.Server.Implementations.Sorting /// <returns>System.Int32.</returns> public int Compare(BaseItem? x, BaseItem? y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); if (!x.IndexNumber.HasValue && !y.IndexNumber.HasValue) { diff --git a/Emby.Server.Implementations/Sorting/NameComparer.cs b/Emby.Server.Implementations/Sorting/NameComparer.cs index c2875eeb9..93bec4db9 100644 --- a/Emby.Server.Implementations/Sorting/NameComparer.cs +++ b/Emby.Server.Implementations/Sorting/NameComparer.cs @@ -24,15 +24,9 @@ namespace Emby.Server.Implementations.Sorting /// <returns>System.Int32.</returns> public int Compare(BaseItem? x, BaseItem? y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); return string.Compare(x.Name, y.Name, StringComparison.OrdinalIgnoreCase); } diff --git a/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs b/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs index a81f78ebf..ce44f99a6 100644 --- a/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs +++ b/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs @@ -31,15 +31,9 @@ namespace Emby.Server.Implementations.Sorting /// <returns>System.Int32.</returns> public int Compare(BaseItem? x, BaseItem? y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } - - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(x); + + ArgumentNullException.ThrowIfNull(y); var levelX = string.IsNullOrEmpty(x.OfficialRating) ? 0 : _localization.GetRatingLevel(x.OfficialRating) ?? 0; var levelY = string.IsNullOrEmpty(y.OfficialRating) ? 0 : _localization.GetRatingLevel(y.OfficialRating) ?? 0; diff --git a/Emby.Server.Implementations/Sorting/ParentIndexNumberComparer.cs b/Emby.Server.Implementations/Sorting/ParentIndexNumberComparer.cs index 8c408bb4d..c54750843 100644 --- a/Emby.Server.Implementations/Sorting/ParentIndexNumberComparer.cs +++ b/Emby.Server.Implementations/Sorting/ParentIndexNumberComparer.cs @@ -24,15 +24,9 @@ namespace Emby.Server.Implementations.Sorting /// <returns>System.Int32.</returns> public int Compare(BaseItem? x, BaseItem? y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); if (!x.ParentIndexNumber.HasValue && !y.ParentIndexNumber.HasValue) { diff --git a/Emby.Server.Implementations/Sorting/RuntimeComparer.cs b/Emby.Server.Implementations/Sorting/RuntimeComparer.cs index e32e5552e..646bafbb5 100644 --- a/Emby.Server.Implementations/Sorting/RuntimeComparer.cs +++ b/Emby.Server.Implementations/Sorting/RuntimeComparer.cs @@ -26,15 +26,9 @@ namespace Emby.Server.Implementations.Sorting /// <returns>System.Int32.</returns> public int Compare(BaseItem x, BaseItem y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); return (x.RunTimeTicks ?? 0).CompareTo(y.RunTimeTicks ?? 0); } diff --git a/Emby.Server.Implementations/Sorting/SortNameComparer.cs b/Emby.Server.Implementations/Sorting/SortNameComparer.cs index 79be9a89a..628b9b3dd 100644 --- a/Emby.Server.Implementations/Sorting/SortNameComparer.cs +++ b/Emby.Server.Implementations/Sorting/SortNameComparer.cs @@ -26,15 +26,9 @@ namespace Emby.Server.Implementations.Sorting /// <returns>System.Int32.</returns> public int Compare(BaseItem x, BaseItem y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); return string.Compare(x.SortName, y.SortName, StringComparison.OrdinalIgnoreCase); } diff --git a/Emby.Server.Implementations/Sorting/StudioComparer.cs b/Emby.Server.Implementations/Sorting/StudioComparer.cs index 4d89cfa8b..457c06271 100644 --- a/Emby.Server.Implementations/Sorting/StudioComparer.cs +++ b/Emby.Server.Implementations/Sorting/StudioComparer.cs @@ -3,7 +3,6 @@ #pragma warning disable CS1591 using System; -using System.Linq; using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; @@ -27,15 +26,9 @@ namespace Emby.Server.Implementations.Sorting /// <returns>System.Int32.</returns> public int Compare(BaseItem x, BaseItem y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); return AlphanumericComparator.CompareValues(x.Studios.FirstOrDefault(), y.Studios.FirstOrDefault()); } diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index d7ab9c021..6005896ad 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -135,20 +135,15 @@ namespace Emby.Server.Implementations.TV return GetResult(episodes, request); } - public IEnumerable<Episode> GetNextUpEpisodes(NextUpQuery request, User user, IReadOnlyList<string> seriesKeys, DtoOptions dtoOptions) + private IEnumerable<Episode> GetNextUpEpisodes(NextUpQuery request, User user, IReadOnlyList<string> seriesKeys, DtoOptions dtoOptions) { - // Avoid implicitly captured closure - var currentUser = user; - - var allNextUp = seriesKeys - .Select(i => GetNextUp(i, currentUser, dtoOptions, false)); + var allNextUp = seriesKeys.Select(i => GetNextUp(i, user, dtoOptions, false)); if (request.EnableRewatching) { allNextUp = allNextUp.Concat( - seriesKeys.Select(i => GetNextUp(i, currentUser, dtoOptions, true)) - ) - .OrderByDescending(i => i.Item1); + seriesKeys.Select(i => GetNextUp(i, user, dtoOptions, true))) + .OrderByDescending(i => i.LastWatchedDate); } // If viewing all next up for all series, remove first episodes @@ -161,23 +156,18 @@ namespace Emby.Server.Implementations.TV { if (request.DisableFirstEpisode) { - return i.Item1 != DateTime.MinValue; + return i.LastWatchedDate != DateTime.MinValue; } - if (alwaysEnableFirstEpisode || (i.Item1 != DateTime.MinValue && i.Item1.Date >= request.NextUpDateCutoff)) + if (alwaysEnableFirstEpisode || (i.LastWatchedDate != DateTime.MinValue && i.LastWatchedDate.Date >= request.NextUpDateCutoff)) { anyFound = true; return true; } - if (!anyFound && i.Item1 == DateTime.MinValue) - { - return true; - } - - return false; + return !anyFound && i.LastWatchedDate == DateTime.MinValue; }) - .Select(i => i.Item2()) + .Select(i => i.GetEpisodeFunction()) .Where(i => i != null); } @@ -195,14 +185,14 @@ namespace Emby.Server.Implementations.TV /// Gets the next up. /// </summary> /// <returns>Task{Episode}.</returns> - private Tuple<DateTime, Func<Episode>> GetNextUp(string seriesKey, User user, DtoOptions dtoOptions, bool rewatching) + private (DateTime LastWatchedDate, Func<Episode> GetEpisodeFunction) GetNextUp(string seriesKey, User user, DtoOptions dtoOptions, bool rewatching) { var lastQuery = new InternalItemsQuery(user) { AncestorWithPresentationUniqueKey = null, SeriesPresentationUniqueKey = seriesKey, IncludeItemTypes = new[] { BaseItemKind.Episode }, - OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Descending) }, + OrderBy = new[] { (ItemSortBy.ParentIndexNumber, SortOrder.Descending), (ItemSortBy.IndexNumber, SortOrder.Descending) }, IsPlayed = true, Limit = 1, ParentIndexNumberNotEquals = 0, @@ -216,24 +206,23 @@ namespace Emby.Server.Implementations.TV if (rewatching) { // find last watched by date played, not by newest episode watched - lastQuery.OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending) }; + lastQuery.OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending), (ItemSortBy.ParentIndexNumber, SortOrder.Descending), (ItemSortBy.IndexNumber, SortOrder.Descending) }; } var lastWatchedEpisode = _libraryManager.GetItemList(lastQuery).Cast<Episode>().FirstOrDefault(); - Func<Episode> getEpisode = () => + Episode GetEpisode() { var nextQuery = new InternalItemsQuery(user) { AncestorWithPresentationUniqueKey = null, SeriesPresentationUniqueKey = seriesKey, IncludeItemTypes = new[] { BaseItemKind.Episode }, - OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }, + OrderBy = new[] { (ItemSortBy.ParentIndexNumber, SortOrder.Ascending), (ItemSortBy.IndexNumber, SortOrder.Ascending) }, Limit = 1, IsPlayed = rewatching, IsVirtualItem = false, ParentIndexNumberNotEquals = 0, - MinSortName = lastWatchedEpisode?.SortName, DtoOptions = dtoOptions }; @@ -297,7 +286,7 @@ namespace Emby.Server.Implementations.TV } return nextEpisode; - }; + } if (lastWatchedEpisode != null) { @@ -305,11 +294,11 @@ namespace Emby.Server.Implementations.TV var lastWatchedDate = userData.LastPlayedDate ?? DateTime.MinValue.AddDays(1); - return new Tuple<DateTime, Func<Episode>>(lastWatchedDate, getEpisode); + return (lastWatchedDate, GetEpisode); } // Return the first episode - return new Tuple<DateTime, Func<Episode>>(DateTime.MinValue, getEpisode); + return (DateTime.MinValue, GetEpisode); } private static QueryResult<BaseItem> GetResult(IEnumerable<BaseItem> items, NextUpQuery query) diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 40c386e82..550f0e075 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -294,10 +294,7 @@ namespace Emby.Server.Implementations.Updates /// <inheritdoc /> public async Task InstallPackage(InstallationInfo package, CancellationToken cancellationToken) { - if (package == null) - { - throw new ArgumentNullException(nameof(package)); - } + ArgumentNullException.ThrowIfNull(package); var innerCancellationTokenSource = new CancellationTokenSource(); diff --git a/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs b/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs index 7ac089a34..4dcf5976a 100644 --- a/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs +++ b/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs @@ -25,6 +25,6 @@ namespace Jellyfin.Api.Attributes /// <param name="template">The route template. May not be null.</param> public HttpSubscribeAttribute(string template) : base(_supportedMethods, template) - => ArgumentNullException.ThrowIfNull(template, nameof(template)); + => ArgumentNullException.ThrowIfNull(template); } } diff --git a/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs b/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs index 16b3d0816..d0238424a 100644 --- a/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs +++ b/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs @@ -25,6 +25,6 @@ namespace Jellyfin.Api.Attributes /// <param name="template">The route template. May not be null.</param> public HttpUnsubscribeAttribute(string template) : base(_supportedMethods, template) - => ArgumentNullException.ThrowIfNull(template, nameof(template)); + => ArgumentNullException.ThrowIfNull(template); } } diff --git a/Jellyfin.Api/Auth/BaseAuthorizationHandler.cs b/Jellyfin.Api/Auth/BaseAuthorizationHandler.cs index 13d3257df..92ee1dd59 100644 --- a/Jellyfin.Api/Auth/BaseAuthorizationHandler.cs +++ b/Jellyfin.Api/Auth/BaseAuthorizationHandler.cs @@ -1,4 +1,5 @@ using System.Security.Claims; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Data.Enums; using MediaBrowser.Common.Extensions; @@ -51,21 +52,21 @@ namespace Jellyfin.Api.Auth bool requiredDownloadPermission = false) { // ApiKey is currently global admin, always allow. - var isApiKey = ClaimHelpers.GetIsApiKey(claimsPrincipal); + var isApiKey = claimsPrincipal.GetIsApiKey(); if (isApiKey) { return true; } // Ensure claim has userId. - var userId = ClaimHelpers.GetUserId(claimsPrincipal); - if (!userId.HasValue) + var userId = claimsPrincipal.GetUserId(); + if (userId.Equals(default)) { return false; } // Ensure userId links to a valid user. - var user = _userManager.GetUserById(userId.Value); + var user = _userManager.GetUserById(userId); if (user == null) { return false; diff --git a/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs index e6c04eb08..cdd7d8a52 100644 --- a/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs +++ b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Data.Enums; using MediaBrowser.Common.Net; @@ -44,14 +45,14 @@ namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy return Task.CompletedTask; } - var userId = ClaimHelpers.GetUserId(context.User); - var user = _userManager.GetUserById(userId!.Value); + var userId = context.User.GetUserId(); + var user = _userManager.GetUserById(userId); if (requirement.RequiredAccess == SyncPlayAccessRequirementType.HasAccess) { if (user.SyncPlayAccess == SyncPlayUserAccessType.CreateAndJoinGroups || user.SyncPlayAccess == SyncPlayUserAccessType.JoinGroups - || _syncPlayManager.IsUserActive(userId.Value)) + || _syncPlayManager.IsUserActive(userId)) { context.Succeed(requirement); } @@ -85,7 +86,7 @@ namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy } else if (requirement.RequiredAccess == SyncPlayAccessRequirementType.IsInGroup) { - if (_syncPlayManager.IsUserActive(userId.Value)) + if (_syncPlayManager.IsUserActive(userId)) { context.Succeed(requirement); } diff --git a/Jellyfin.Api/Controllers/ArtistsController.cs b/Jellyfin.Api/Controllers/ArtistsController.cs index 44796bcc4..c059cb198 100644 --- a/Jellyfin.Api/Controllers/ArtistsController.cs +++ b/Jellyfin.Api/Controllers/ArtistsController.cs @@ -120,7 +120,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableTotalRecordCount = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); User? user = null; @@ -323,7 +323,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableTotalRecordCount = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); User? user = null; @@ -463,7 +463,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult<BaseItemDto> GetArtistByName([FromRoute, Required] string name, [FromQuery] Guid? userId) { - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var item = _libraryManager.GetArtist(name, dtoOptions); diff --git a/Jellyfin.Api/Controllers/ClientLogController.cs b/Jellyfin.Api/Controllers/ClientLogController.cs index 98fd22430..ed073a687 100644 --- a/Jellyfin.Api/Controllers/ClientLogController.cs +++ b/Jellyfin.Api/Controllers/ClientLogController.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.ClientLogDtos; using MediaBrowser.Controller.ClientEvent; @@ -69,10 +70,10 @@ namespace Jellyfin.Api.Controllers private (string ClientName, string ClientVersion) GetRequestInformation() { - var clientName = ClaimHelpers.GetClient(HttpContext.User) ?? "unknown-client"; - var clientVersion = ClaimHelpers.GetIsApiKey(HttpContext.User) + var clientName = HttpContext.User.GetClient() ?? "unknown-client"; + var clientVersion = HttpContext.User.GetIsApiKey() ? "apikey" - : ClaimHelpers.GetVersion(HttpContext.User) ?? "unknown-version"; + : HttpContext.User.GetVersion() ?? "unknown-version"; return (clientName, clientVersion); } diff --git a/Jellyfin.Api/Controllers/CollectionController.cs b/Jellyfin.Api/Controllers/CollectionController.cs index 8a98d856c..effc9ed7a 100644 --- a/Jellyfin.Api/Controllers/CollectionController.cs +++ b/Jellyfin.Api/Controllers/CollectionController.cs @@ -6,7 +6,6 @@ using Jellyfin.Api.Extensions; using Jellyfin.Api.ModelBinders; using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.Collections; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -23,22 +22,18 @@ namespace Jellyfin.Api.Controllers { private readonly ICollectionManager _collectionManager; private readonly IDtoService _dtoService; - private readonly IAuthorizationContext _authContext; /// <summary> /// Initializes a new instance of the <see cref="CollectionController"/> class. /// </summary> /// <param name="collectionManager">Instance of <see cref="ICollectionManager"/> interface.</param> /// <param name="dtoService">Instance of <see cref="IDtoService"/> interface.</param> - /// <param name="authContext">Instance of <see cref="IAuthorizationContext"/> interface.</param> public CollectionController( ICollectionManager collectionManager, - IDtoService dtoService, - IAuthorizationContext authContext) + IDtoService dtoService) { _collectionManager = collectionManager; _dtoService = dtoService; - _authContext = authContext; } /// <summary> @@ -58,7 +53,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] Guid? parentId, [FromQuery] bool isLocked = false) { - var userId = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).UserId; + var userId = User.GetUserId(); var item = await _collectionManager.CreateCollectionAsync(new CollectionCreationOptions { @@ -69,7 +64,7 @@ namespace Jellyfin.Api.Controllers UserIds = new[] { userId } }).ConfigureAwait(false); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var dto = _dtoService.GetBaseItemDto(item, dtoOptions); diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 3ed80f662..0f4d3c1eb 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -20,7 +20,6 @@ using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.IO; @@ -46,7 +45,6 @@ namespace Jellyfin.Api.Controllers private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; private readonly IDlnaManager _dlnaManager; - private readonly IAuthorizationContext _authContext; private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; @@ -65,7 +63,6 @@ namespace Jellyfin.Api.Controllers /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> /// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param> - /// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> @@ -80,7 +77,6 @@ namespace Jellyfin.Api.Controllers ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, - IAuthorizationContext authContext, IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, @@ -95,7 +91,6 @@ namespace Jellyfin.Api.Controllers _libraryManager = libraryManager; _userManager = userManager; _dlnaManager = dlnaManager; - _authContext = authContext; _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; @@ -287,8 +282,7 @@ namespace Jellyfin.Api.Controllers var cancellationToken = cancellationTokenSource.Token; var state = await StreamingHelpers.GetStreamingState( streamingRequest, - Request, - _authContext, + HttpContext, _mediaSourceManager, _userManager, _libraryManager, @@ -1393,8 +1387,7 @@ namespace Jellyfin.Api.Controllers { using var state = await StreamingHelpers.GetStreamingState( streamingRequest, - Request, - _authContext, + HttpContext, _mediaSourceManager, _userManager, _libraryManager, @@ -1434,8 +1427,7 @@ namespace Jellyfin.Api.Controllers var state = await StreamingHelpers.GetStreamingState( streamingRequest, - Request, - _authContext, + HttpContext, _mediaSourceManager, _userManager, _libraryManager, diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs index e28a50750..611643bd8 100644 --- a/Jellyfin.Api/Controllers/GenresController.cs +++ b/Jellyfin.Api/Controllers/GenresController.cs @@ -92,7 +92,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableTotalRecordCount = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes); User? user = userId is null || userId.Value.Equals(default) @@ -157,7 +157,7 @@ namespace Jellyfin.Api.Controllers public ActionResult<BaseItemDto> GetGenre([FromRoute, Required] string genreName, [FromQuery] Guid? userId) { var dtoOptions = new DtoOptions() - .AddClientFields(Request); + .AddClientFields(User); Genre? item; if (genreName.Contains(BaseItem.SlugChar, StringComparison.OrdinalIgnoreCase)) diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 6c7842c7b..f092bd882 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -17,7 +17,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Branding; using MediaBrowser.Model.Drawing; @@ -44,11 +43,9 @@ namespace Jellyfin.Api.Controllers private readonly IProviderManager _providerManager; private readonly IImageProcessor _imageProcessor; private readonly IFileSystem _fileSystem; - private readonly IAuthorizationContext _authContext; private readonly ILogger<ImageController> _logger; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IApplicationPaths _appPaths; - private readonly IImageEncoder _imageEncoder; /// <summary> /// Initializes a new instance of the <see cref="ImageController"/> class. @@ -58,33 +55,27 @@ namespace Jellyfin.Api.Controllers /// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param> /// <param name="imageProcessor">Instance of the <see cref="IImageProcessor"/> interface.</param> /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> - /// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> /// <param name="logger">Instance of the <see cref="ILogger{ImageController}"/> interface.</param> /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="appPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param> - /// <param name="imageEncoder">Instance of the <see cref="IImageEncoder"/> interface.</param> public ImageController( IUserManager userManager, ILibraryManager libraryManager, IProviderManager providerManager, IImageProcessor imageProcessor, IFileSystem fileSystem, - IAuthorizationContext authContext, ILogger<ImageController> logger, IServerConfigurationManager serverConfigurationManager, - IApplicationPaths appPaths, - IImageEncoder imageEncoder) + IApplicationPaths appPaths) { _userManager = userManager; _libraryManager = libraryManager; _providerManager = providerManager; _imageProcessor = imageProcessor; _fileSystem = fileSystem; - _authContext = authContext; _logger = logger; _serverConfigurationManager = serverConfigurationManager; _appPaths = appPaths; - _imageEncoder = imageEncoder; } /// <summary> @@ -108,7 +99,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] ImageType imageType, [FromQuery] int? index = null) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, HttpContext.User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the image."); } @@ -155,7 +146,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] ImageType imageType, [FromRoute] int index) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, HttpContext.User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the image."); } @@ -201,7 +192,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] ImageType imageType, [FromQuery] int? index = null) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, HttpContext.User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to delete the image."); } @@ -245,7 +236,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] ImageType imageType, [FromRoute] int index) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, HttpContext.User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to delete the image."); } diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs index 9abea5938..2e0d3cb99 100644 --- a/Jellyfin.Api/Controllers/InstantMixController.cs +++ b/Jellyfin.Api/Controllers/InstantMixController.cs @@ -79,7 +79,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); @@ -115,7 +115,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(album, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); @@ -151,7 +151,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(playlist, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); @@ -186,7 +186,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromGenres(new[] { name }, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); @@ -222,7 +222,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); @@ -258,7 +258,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); @@ -331,7 +331,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 4d09070db..80ae5abcb 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -10,7 +10,6 @@ using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -34,7 +33,6 @@ namespace Jellyfin.Api.Controllers private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _localization; private readonly IDtoService _dtoService; - private readonly IAuthorizationContext _authContext; private readonly ILogger<ItemsController> _logger; private readonly ISessionManager _sessionManager; @@ -45,7 +43,6 @@ namespace Jellyfin.Api.Controllers /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param> /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param> - /// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param> /// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param> public ItemsController( @@ -53,7 +50,6 @@ namespace Jellyfin.Api.Controllers ILibraryManager libraryManager, ILocalizationManager localization, IDtoService dtoService, - IAuthorizationContext authContext, ILogger<ItemsController> logger, ISessionManager sessionManager) { @@ -61,7 +57,6 @@ namespace Jellyfin.Api.Controllers _libraryManager = libraryManager; _localization = localization; _dtoService = dtoService; - _authContext = authContext; _logger = logger; _sessionManager = sessionManager; } @@ -157,7 +152,7 @@ namespace Jellyfin.Api.Controllers /// <returns>A <see cref="QueryResult{BaseItemDto}"/> with the items.</returns> [HttpGet("Items")] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task<ActionResult<QueryResult<BaseItemDto>>> GetItems( + public ActionResult<QueryResult<BaseItemDto>> GetItems( [FromQuery] Guid? userId, [FromQuery] string? maxOfficialRating, [FromQuery] bool? hasThemeSong, @@ -244,21 +239,20 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableTotalRecordCount = true, [FromQuery] bool? enableImages = true) { - var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - + var isApiKey = User.GetIsApiKey(); // if api key is used (auth.IsApiKey == true), then `user` will be null throughout this method - var user = !auth.IsApiKey && userId.HasValue && !userId.Value.Equals(default) + var user = !isApiKey && userId.HasValue && !userId.Value.Equals(default) ? _userManager.GetUserById(userId.Value) : null; // beyond this point, we're either using an api key or we have a valid user - if (!auth.IsApiKey && user is null) + if (!isApiKey && user is null) { return BadRequest("userId is required"); } var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); if (includeItemTypes.Length == 1 @@ -288,12 +282,12 @@ namespace Jellyfin.Api.Controllers includeItemTypes = new[] { BaseItemKind.Playlist }; } - var enabledChannels = auth.IsApiKey + var enabledChannels = isApiKey ? Array.Empty<Guid>() : user!.GetPreferenceValues<Guid>(PreferenceKind.EnabledChannels); // api keys are always enabled for all folders - bool isInEnabledFolder = auth.IsApiKey + bool isInEnabledFolder = isApiKey || Array.IndexOf(user!.GetPreferenceValues<Guid>(PreferenceKind.EnabledFolders), item.Id) != -1 // Assume all folders inside an EnabledChannel are enabled || Array.IndexOf(enabledChannels, item.Id) != -1 @@ -633,7 +627,7 @@ namespace Jellyfin.Api.Controllers /// <returns>A <see cref="QueryResult{BaseItemDto}"/> with the items.</returns> [HttpGet("Users/{userId}/Items")] [ProducesResponseType(StatusCodes.Status200OK)] - public Task<ActionResult<QueryResult<BaseItemDto>>> GetItemsByUserId( + public ActionResult<QueryResult<BaseItemDto>> GetItemsByUserId( [FromRoute] Guid userId, [FromQuery] string? maxOfficialRating, [FromQuery] bool? hasThemeSong, @@ -850,7 +844,7 @@ namespace Jellyfin.Api.Controllers var user = _userManager.GetUserById(userId); var parentIdGuid = parentId ?? Guid.Empty; var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var ancestorIds = Array.Empty<Guid>(); diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index 4cc17dd0f..e9492a6a4 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -24,7 +24,6 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Activity; using MediaBrowser.Model.Configuration; @@ -50,7 +49,6 @@ namespace Jellyfin.Api.Controllers private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; private readonly IDtoService _dtoService; - private readonly IAuthorizationContext _authContext; private readonly IActivityManager _activityManager; private readonly ILocalizationManager _localization; private readonly ILibraryMonitor _libraryMonitor; @@ -64,7 +62,6 @@ namespace Jellyfin.Api.Controllers /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param> - /// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> /// <param name="activityManager">Instance of the <see cref="IActivityManager"/> interface.</param> /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param> /// <param name="libraryMonitor">Instance of the <see cref="ILibraryMonitor"/> interface.</param> @@ -75,7 +72,6 @@ namespace Jellyfin.Api.Controllers ILibraryManager libraryManager, IUserManager userManager, IDtoService dtoService, - IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILibraryMonitor libraryMonitor, @@ -86,7 +82,6 @@ namespace Jellyfin.Api.Controllers _libraryManager = libraryManager; _userManager = userManager; _dtoService = dtoService; - _authContext = authContext; _activityManager = activityManager; _localization = localization; _libraryMonitor = libraryMonitor; @@ -184,7 +179,7 @@ namespace Jellyfin.Api.Controllers item = parent; } - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var items = themeItems .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)) .ToArray(); @@ -250,7 +245,7 @@ namespace Jellyfin.Api.Controllers item = parent; } - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var items = themeItems .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)) .ToArray(); @@ -331,11 +326,10 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] - public async Task<ActionResult> DeleteItem(Guid itemId) + public ActionResult DeleteItem(Guid itemId) { var item = _libraryManager.GetItemById(itemId); - var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - var user = auth.User; + var user = _userManager.GetUserById(User.GetUserId()); if (!item.CanDelete(user)) { @@ -361,7 +355,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] - public async Task<ActionResult> DeleteItems([FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] ids) + public ActionResult DeleteItems([FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] ids) { if (ids.Length == 0) { @@ -371,8 +365,7 @@ namespace Jellyfin.Api.Controllers foreach (var i in ids) { var item = _libraryManager.GetItemById(i); - var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - var user = auth.User; + var user = _userManager.GetUserById(User.GetUserId()); if (!item.CanDelete(user)) { @@ -453,7 +446,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); BaseItem? parent = item.GetParent(); while (parent != null) @@ -505,7 +498,7 @@ namespace Jellyfin.Api.Controllers items = items.Where(i => i.IsHidden == val).ToList(); } - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var resultArray = _dtoService.GetBaseItemDtos(items, dtoOptions); return new QueryResult<BaseItemDto>(resultArray); } @@ -622,9 +615,7 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - - var user = auth.User; + var user = _userManager.GetUserById(User.GetUserId()); if (user != null) { @@ -643,7 +634,7 @@ namespace Jellyfin.Api.Controllers if (user != null) { - await LogDownloadAsync(item, user, auth).ConfigureAwait(false); + await LogDownloadAsync(item, user).ConfigureAwait(false); } var path = item.Path; @@ -704,7 +695,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request); + .AddClientFields(User); var program = item as IHasProgramAttributes; bool? isMovie = item is Movie || (program != null && program.IsMovie) || item is Trailer; @@ -892,16 +883,16 @@ namespace Jellyfin.Api.Controllers : item; } - private async Task LogDownloadAsync(BaseItem item, User user, AuthorizationInfo auth) + private async Task LogDownloadAsync(BaseItem item, User user) { try { await _activityManager.CreateAsync(new ActivityLog( string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Username, item.Name), "UserDownloadingContent", - auth.UserId) + User.GetUserId()) { - ShortOverview = string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("AppDeviceValues"), auth.Client, auth.Device), + ShortOverview = string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("AppDeviceValues"), User.GetClient(), User.GetDevice()), }).ConfigureAwait(false); } catch diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index 05340099b..394df0f58 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -17,6 +17,7 @@ using Jellyfin.Api.ModelBinders; using Jellyfin.Api.Models.LiveTvDtos; using Jellyfin.Data.Enums; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; @@ -24,6 +25,7 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Net; +using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.LiveTv; @@ -45,10 +47,10 @@ namespace Jellyfin.Api.Controllers private readonly IHttpClientFactory _httpClientFactory; private readonly ILibraryManager _libraryManager; private readonly IDtoService _dtoService; - private readonly ISessionContext _sessionContext; private readonly IMediaSourceManager _mediaSourceManager; private readonly IConfigurationManager _configurationManager; private readonly TranscodingJobHelper _transcodingJobHelper; + private readonly ISessionManager _sessionManager; /// <summary> /// Initializes a new instance of the <see cref="LiveTvController"/> class. @@ -58,30 +60,30 @@ namespace Jellyfin.Api.Controllers /// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param> - /// <param name="sessionContext">Instance of the <see cref="ISessionContext"/> interface.</param> /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="configurationManager">Instance of the <see cref="IConfigurationManager"/> interface.</param> /// <param name="transcodingJobHelper">Instance of the <see cref="TranscodingJobHelper"/> class.</param> + /// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param> public LiveTvController( ILiveTvManager liveTvManager, IUserManager userManager, IHttpClientFactory httpClientFactory, ILibraryManager libraryManager, IDtoService dtoService, - ISessionContext sessionContext, IMediaSourceManager mediaSourceManager, IConfigurationManager configurationManager, - TranscodingJobHelper transcodingJobHelper) + TranscodingJobHelper transcodingJobHelper, + ISessionManager sessionManager) { _liveTvManager = liveTvManager; _userManager = userManager; _httpClientFactory = httpClientFactory; _libraryManager = libraryManager; _dtoService = dtoService; - _sessionContext = sessionContext; _mediaSourceManager = mediaSourceManager; _configurationManager = configurationManager; _transcodingJobHelper = transcodingJobHelper; + _sessionManager = sessionManager; } /// <summary> @@ -154,7 +156,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool addCurrentProgram = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var channelResult = _liveTvManager.GetInternalChannels( @@ -219,7 +221,7 @@ namespace Jellyfin.Api.Controllers : _libraryManager.GetItemById(channelId); var dtoOptions = new DtoOptions() - .AddClientFields(Request); + .AddClientFields(User); return _dtoService.GetBaseItemDto(item, dtoOptions, user); } @@ -272,7 +274,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableTotalRecordCount = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); return _liveTvManager.GetRecordings( @@ -410,7 +412,7 @@ namespace Jellyfin.Api.Controllers var item = recordingId.Equals(default) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(recordingId); var dtoOptions = new DtoOptions() - .AddClientFields(Request); + .AddClientFields(User); return _dtoService.GetBaseItemDto(item, dtoOptions, user); } @@ -599,7 +601,7 @@ namespace Jellyfin.Api.Controllers } var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false); } @@ -653,7 +655,7 @@ namespace Jellyfin.Api.Controllers } var dtoOptions = new DtoOptions { Fields = body.Fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(body.EnableImages, body.EnableUserData, body.ImageTypeLimit, body.EnableImageTypes); return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false); } @@ -719,7 +721,7 @@ namespace Jellyfin.Api.Controllers }; var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); return await _liveTvManager.GetRecommendedProgramsAsync(query, dtoOptions, CancellationToken.None).ConfigureAwait(false); } @@ -1210,9 +1212,16 @@ namespace Jellyfin.Api.Controllers private async Task AssertUserCanManageLiveTv() { - var user = await _sessionContext.GetUser(Request).ConfigureAwait(false); - - if (user == null) + var user = _userManager.GetUserById(User.GetUserId()); + var session = await _sessionManager.LogSessionActivity( + User.GetClient(), + User.GetVersion(), + User.GetDeviceId(), + User.GetDevice(), + HttpContext.GetNormalizedRemoteIp().ToString(), + user).ConfigureAwait(false); + + if (session.UserId.Equals(default)) { throw new SecurityException("Anonymous live tv management is not allowed."); } diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs index d2852ed01..c111e9218 100644 --- a/Jellyfin.Api/Controllers/MediaInfoController.cs +++ b/Jellyfin.Api/Controllers/MediaInfoController.cs @@ -6,12 +6,12 @@ using System.Net.Mime; using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.MediaInfoDtos; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.MediaInfo; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -31,7 +31,6 @@ namespace Jellyfin.Api.Controllers private readonly IMediaSourceManager _mediaSourceManager; private readonly IDeviceManager _deviceManager; private readonly ILibraryManager _libraryManager; - private readonly IAuthorizationContext _authContext; private readonly ILogger<MediaInfoController> _logger; private readonly MediaInfoHelper _mediaInfoHelper; @@ -41,21 +40,18 @@ namespace Jellyfin.Api.Controllers /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> - /// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> /// <param name="logger">Instance of the <see cref="ILogger{MediaInfoController}"/> interface.</param> /// <param name="mediaInfoHelper">Instance of the <see cref="MediaInfoHelper"/>.</param> public MediaInfoController( IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager, - IAuthorizationContext authContext, ILogger<MediaInfoController> logger, MediaInfoHelper mediaInfoHelper) { _mediaSourceManager = mediaSourceManager; _deviceManager = deviceManager; _libraryManager = libraryManager; - _authContext = authContext; _logger = logger; _mediaInfoHelper = mediaInfoHelper; } @@ -122,14 +118,12 @@ namespace Jellyfin.Api.Controllers [FromQuery, ParameterObsolete] bool? allowAudioStreamCopy, [FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] PlaybackInfoDto? playbackInfoDto) { - var authInfo = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - var profile = playbackInfoDto?.DeviceProfile; _logger.LogDebug("GetPostedPlaybackInfo profile: {@Profile}", profile); if (profile == null) { - var caps = _deviceManager.GetCapabilities(authInfo.DeviceId); + var caps = _deviceManager.GetCapabilities(User.GetDeviceId()); if (caps != null) { profile = caps.DeviceProfile; @@ -176,7 +170,7 @@ namespace Jellyfin.Api.Controllers item, mediaSource, profile, - authInfo, + User, maxStreamingBitrate ?? profile.MaxStreamingBitrate, startTimeTicks ?? 0, mediaSourceId ?? string.Empty, @@ -203,7 +197,7 @@ namespace Jellyfin.Api.Controllers if (mediaSource != null && mediaSource.RequiresOpening && string.IsNullOrWhiteSpace(mediaSource.LiveStreamId)) { var openStreamResult = await _mediaInfoHelper.OpenMediaSource( - Request, + HttpContext, new LiveStreamRequest { AudioStreamIndex = audioStreamIndex, @@ -276,7 +270,7 @@ namespace Jellyfin.Api.Controllers EnableDirectStream = enableDirectStream ?? openLiveStreamDto?.EnableDirectStream ?? true, DirectPlayProtocols = openLiveStreamDto?.DirectPlayProtocols ?? new[] { MediaProtocol.Http } }; - return await _mediaInfoHelper.OpenMediaSource(Request, request).ConfigureAwait(false); + return await _mediaInfoHelper.OpenMediaSource(HttpContext, request).ConfigureAwait(false); } /// <summary> diff --git a/Jellyfin.Api/Controllers/MoviesController.cs b/Jellyfin.Api/Controllers/MoviesController.cs index 466944704..8195fc760 100644 --- a/Jellyfin.Api/Controllers/MoviesController.cs +++ b/Jellyfin.Api/Controllers/MoviesController.cs @@ -72,7 +72,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request); + .AddClientFields(User); var categories = new List<RecommendationDto>(); diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs index 0499b2985..f4fb5f44a 100644 --- a/Jellyfin.Api/Controllers/MusicGenresController.cs +++ b/Jellyfin.Api/Controllers/MusicGenresController.cs @@ -92,7 +92,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableTotalRecordCount = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes); User? user = userId is null || userId.Value.Equals(default) @@ -145,7 +145,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult<BaseItemDto> GetMusicGenre([FromRoute, Required] string genreName, [FromQuery] Guid? userId) { - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); MusicGenre? item; diff --git a/Jellyfin.Api/Controllers/PersonsController.cs b/Jellyfin.Api/Controllers/PersonsController.cs index be4b9eded..42be969b2 100644 --- a/Jellyfin.Api/Controllers/PersonsController.cs +++ b/Jellyfin.Api/Controllers/PersonsController.cs @@ -79,7 +79,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool? enableImages = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); User? user = userId is null || userId.Value.Equals(default) @@ -98,7 +98,10 @@ namespace Jellyfin.Api.Controllers Limit = limit ?? 0 }); - return new QueryResult<BaseItemDto>(peopleItems.Select(person => _dtoService.GetItemByNameDto(person, dtoOptions, null, user)).ToArray()); + return new QueryResult<BaseItemDto>( + peopleItems + .Select(person => _dtoService.GetItemByNameDto(person, dtoOptions, null, user)) + .ToArray()); } /// <summary> @@ -116,7 +119,7 @@ namespace Jellyfin.Api.Controllers public ActionResult<BaseItemDto> GetPerson([FromRoute, Required] string name, [FromQuery] Guid? userId) { var dtoOptions = new DtoOptions() - .AddClientFields(Request); + .AddClientFields(User); var item = _libraryManager.GetPerson(name); if (item == null) diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs index ad85f2fb2..fb045f891 100644 --- a/Jellyfin.Api/Controllers/PlaylistsController.cs +++ b/Jellyfin.Api/Controllers/PlaylistsController.cs @@ -200,7 +200,7 @@ namespace Jellyfin.Api.Controllers } var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var dtos = _dtoService.GetBaseItemDtos(items.Select(i => i.Item2).ToList(), dtoOptions, user); diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs index 6dee1c219..0dd4bf803 100644 --- a/Jellyfin.Api/Controllers/PlaystateController.cs +++ b/Jellyfin.Api/Controllers/PlaystateController.cs @@ -3,11 +3,11 @@ using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Session; @@ -29,7 +29,6 @@ namespace Jellyfin.Api.Controllers private readonly IUserDataManager _userDataRepository; private readonly ILibraryManager _libraryManager; private readonly ISessionManager _sessionManager; - private readonly IAuthorizationContext _authContext; private readonly ILogger<PlaystateController> _logger; private readonly TranscodingJobHelper _transcodingJobHelper; @@ -40,7 +39,6 @@ namespace Jellyfin.Api.Controllers /// <param name="userDataRepository">Instance of the <see cref="IUserDataManager"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param> - /// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param> /// <param name="transcodingJobHelper">Th <see cref="TranscodingJobHelper"/> singleton.</param> public PlaystateController( @@ -48,7 +46,6 @@ namespace Jellyfin.Api.Controllers IUserDataManager userDataRepository, ILibraryManager libraryManager, ISessionManager sessionManager, - IAuthorizationContext authContext, ILoggerFactory loggerFactory, TranscodingJobHelper transcodingJobHelper) { @@ -56,7 +53,6 @@ namespace Jellyfin.Api.Controllers _userDataRepository = userDataRepository; _libraryManager = libraryManager; _sessionManager = sessionManager; - _authContext = authContext; _logger = loggerFactory.CreateLogger<PlaystateController>(); _transcodingJobHelper = transcodingJobHelper; @@ -78,7 +74,7 @@ namespace Jellyfin.Api.Controllers [FromQuery, ModelBinder(typeof(LegacyDateTimeModelBinder))] DateTime? datePlayed) { var user = _userManager.GetUserById(userId); - var session = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false); + var session = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var dto = UpdatePlayedStatus(user, itemId, true, datePlayed); foreach (var additionalUserInfo in session.AdditionalUsers) { @@ -101,7 +97,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult<UserItemDataDto>> MarkUnplayedItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) { var user = _userManager.GetUserById(userId); - var session = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false); + var session = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var dto = UpdatePlayedStatus(user, itemId, false, null); foreach (var additionalUserInfo in session.AdditionalUsers) { @@ -123,7 +119,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> ReportPlaybackStart([FromBody] PlaybackStartInfo playbackStartInfo) { playbackStartInfo.PlayMethod = ValidatePlayMethod(playbackStartInfo.PlayMethod, playbackStartInfo.PlaySessionId); - playbackStartInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + playbackStartInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); await _sessionManager.OnPlaybackStart(playbackStartInfo).ConfigureAwait(false); return NoContent(); } @@ -139,7 +135,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> ReportPlaybackProgress([FromBody] PlaybackProgressInfo playbackProgressInfo) { playbackProgressInfo.PlayMethod = ValidatePlayMethod(playbackProgressInfo.PlayMethod, playbackProgressInfo.PlaySessionId); - playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); await _sessionManager.OnPlaybackProgress(playbackProgressInfo).ConfigureAwait(false); return NoContent(); } @@ -171,11 +167,10 @@ namespace Jellyfin.Api.Controllers _logger.LogDebug("ReportPlaybackStopped PlaySessionId: {0}", playbackStopInfo.PlaySessionId ?? string.Empty); if (!string.IsNullOrWhiteSpace(playbackStopInfo.PlaySessionId)) { - var authInfo = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - await _transcodingJobHelper.KillTranscodingJobs(authInfo.DeviceId, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); + await _transcodingJobHelper.KillTranscodingJobs(User.GetDeviceId()!, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); } - playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); await _sessionManager.OnPlaybackStopped(playbackStopInfo).ConfigureAwait(false); return NoContent(); } @@ -221,7 +216,7 @@ namespace Jellyfin.Api.Controllers }; playbackStartInfo.PlayMethod = ValidatePlayMethod(playbackStartInfo.PlayMethod, playbackStartInfo.PlaySessionId); - playbackStartInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + playbackStartInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); await _sessionManager.OnPlaybackStart(playbackStartInfo).ConfigureAwait(false); return NoContent(); } @@ -279,7 +274,7 @@ namespace Jellyfin.Api.Controllers }; playbackProgressInfo.PlayMethod = ValidatePlayMethod(playbackProgressInfo.PlayMethod, playbackProgressInfo.PlaySessionId); - playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);; await _sessionManager.OnPlaybackProgress(playbackProgressInfo).ConfigureAwait(false); return NoContent(); } @@ -321,11 +316,10 @@ namespace Jellyfin.Api.Controllers _logger.LogDebug("ReportPlaybackStopped PlaySessionId: {0}", playbackStopInfo.PlaySessionId ?? string.Empty); if (!string.IsNullOrWhiteSpace(playbackStopInfo.PlaySessionId)) { - var authInfo = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - await _transcodingJobHelper.KillTranscodingJobs(authInfo.DeviceId, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); + await _transcodingJobHelper.KillTranscodingJobs(User.GetDeviceId()!, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); } - playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);; await _sessionManager.OnPlaybackStopped(playbackStopInfo).ConfigureAwait(false); return NoContent(); } diff --git a/Jellyfin.Api/Controllers/QuickConnectController.cs b/Jellyfin.Api/Controllers/QuickConnectController.cs index 1df26355f..77d88475f 100644 --- a/Jellyfin.Api/Controllers/QuickConnectController.cs +++ b/Jellyfin.Api/Controllers/QuickConnectController.cs @@ -1,6 +1,7 @@ using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Authentication; @@ -104,15 +105,15 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task<ActionResult<bool>> AuthorizeQuickConnect([FromQuery, Required] string code) { - var userId = ClaimHelpers.GetUserId(Request.HttpContext.User); - if (!userId.HasValue) + var userId = User.GetUserId(); + if (userId.Equals(default)) { return StatusCode(StatusCodes.Status403Forbidden, "Unknown user id"); } try { - return await _quickConnect.AuthorizeRequest(userId.Value, code).ConfigureAwait(false); + return await _quickConnect.AuthorizeRequest(userId, code).ConfigureAwait(false); } catch (AuthenticationException) { diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs index 860bccb9b..28415555e 100644 --- a/Jellyfin.Api/Controllers/SessionController.cs +++ b/Jellyfin.Api/Controllers/SessionController.cs @@ -5,13 +5,13 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Api.Models.SessionDtos; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Session; @@ -29,7 +29,6 @@ namespace Jellyfin.Api.Controllers { private readonly ISessionManager _sessionManager; private readonly IUserManager _userManager; - private readonly IAuthorizationContext _authContext; private readonly IDeviceManager _deviceManager; /// <summary> @@ -37,17 +36,14 @@ namespace Jellyfin.Api.Controllers /// </summary> /// <param name="sessionManager">Instance of <see cref="ISessionManager"/> interface.</param> /// <param name="userManager">Instance of <see cref="IUserManager"/> interface.</param> - /// <param name="authContext">Instance of <see cref="IAuthorizationContext"/> interface.</param> /// <param name="deviceManager">Instance of <see cref="IDeviceManager"/> interface.</param> public SessionController( ISessionManager sessionManager, IUserManager userManager, - IAuthorizationContext authContext, IDeviceManager deviceManager) { _sessionManager = sessionManager; _userManager = userManager; - _authContext = authContext; _deviceManager = deviceManager; } @@ -139,7 +135,7 @@ namespace Jellyfin.Api.Controllers }; await _sessionManager.SendBrowseCommand( - await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false), + await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), sessionId, command, CancellationToken.None) @@ -186,7 +182,7 @@ namespace Jellyfin.Api.Controllers }; await _sessionManager.SendPlayCommand( - await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false), + await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), sessionId, playRequest, CancellationToken.None) @@ -214,7 +210,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? controllingUserId) { await _sessionManager.SendPlaystateCommand( - await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false), + await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), sessionId, new PlaystateRequest() { @@ -242,14 +238,14 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] string sessionId, [FromRoute, Required] GeneralCommandType command) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var generalCommand = new GeneralCommand { Name = command, ControllingUserId = currentSession.UserId }; - await _sessionManager.SendGeneralCommand(currentSession.Id, sessionId, generalCommand, CancellationToken.None); + await _sessionManager.SendGeneralCommand(currentSession.Id, sessionId, generalCommand, CancellationToken.None).ConfigureAwait(false); return NoContent(); } @@ -268,7 +264,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] string sessionId, [FromRoute, Required] GeneralCommandType command) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var generalCommand = new GeneralCommand { @@ -296,8 +292,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] string sessionId, [FromBody, Required] GeneralCommand command) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authContext, Request) - .ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); if (command == null) { @@ -336,7 +331,7 @@ namespace Jellyfin.Api.Controllers } await _sessionManager.SendMessageCommand( - await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false), + await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), sessionId, command, CancellationToken.None) @@ -405,7 +400,7 @@ namespace Jellyfin.Api.Controllers { if (string.IsNullOrWhiteSpace(id)) { - id = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + id = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); } _sessionManager.ReportCapabilities(id, new ClientCapabilities @@ -435,7 +430,7 @@ namespace Jellyfin.Api.Controllers { if (string.IsNullOrWhiteSpace(id)) { - id = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + id = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); } _sessionManager.ReportCapabilities(id, capabilities.ToClientCapabilities()); @@ -457,7 +452,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? sessionId, [FromQuery, Required] string? itemId) { - string session = sessionId ?? await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + string session = sessionId ?? await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); _sessionManager.ReportNowViewingItem(session, itemId); return NoContent(); @@ -473,9 +468,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task<ActionResult> ReportSessionEnded() { - AuthorizationInfo auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - - await _sessionManager.Logout(auth.Token).ConfigureAwait(false); + await _sessionManager.Logout(User.GetToken()).ConfigureAwait(false); return NoContent(); } diff --git a/Jellyfin.Api/Controllers/StudiosController.cs b/Jellyfin.Api/Controllers/StudiosController.cs index 053c7baaa..1288fb512 100644 --- a/Jellyfin.Api/Controllers/StudiosController.cs +++ b/Jellyfin.Api/Controllers/StudiosController.cs @@ -88,7 +88,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableTotalRecordCount = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); User? user = userId is null || userId.Value.Equals(default) @@ -140,7 +140,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult<BaseItemDto> GetStudio([FromRoute, Required] string name, [FromQuery] Guid? userId) { - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var item = _libraryManager.GetStudio(name); if (userId.HasValue && !userId.Equals(default)) diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index 16acedcf3..1258a9876 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -11,13 +11,13 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Models.SubtitleDtos; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Subtitles; using MediaBrowser.Model.Entities; @@ -45,7 +45,6 @@ namespace Jellyfin.Api.Controllers private readonly IMediaSourceManager _mediaSourceManager; private readonly IProviderManager _providerManager; private readonly IFileSystem _fileSystem; - private readonly IAuthorizationContext _authContext; private readonly ILogger<SubtitleController> _logger; /// <summary> @@ -58,7 +57,6 @@ namespace Jellyfin.Api.Controllers /// <param name="mediaSourceManager">Instance of <see cref="IMediaSourceManager"/> interface.</param> /// <param name="providerManager">Instance of <see cref="IProviderManager"/> interface.</param> /// <param name="fileSystem">Instance of <see cref="IFileSystem"/> interface.</param> - /// <param name="authContext">Instance of <see cref="IAuthorizationContext"/> interface.</param> /// <param name="logger">Instance of <see cref="ILogger{SubtitleController}"/> interface.</param> public SubtitleController( IServerConfigurationManager serverConfigurationManager, @@ -68,7 +66,6 @@ namespace Jellyfin.Api.Controllers IMediaSourceManager mediaSourceManager, IProviderManager providerManager, IFileSystem fileSystem, - IAuthorizationContext authContext, ILogger<SubtitleController> logger) { _serverConfigurationManager = serverConfigurationManager; @@ -78,7 +75,6 @@ namespace Jellyfin.Api.Controllers _mediaSourceManager = mediaSourceManager; _providerManager = providerManager; _fileSystem = fileSystem; - _authContext = authContext; _logger = logger; } @@ -361,7 +357,7 @@ namespace Jellyfin.Api.Controllers long positionTicks = 0; - var accessToken = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).Token; + var accessToken = User.GetToken(); while (positionTicks < runtime) { diff --git a/Jellyfin.Api/Controllers/SuggestionsController.cs b/Jellyfin.Api/Controllers/SuggestionsController.cs index e9c46dcf3..1cf528153 100644 --- a/Jellyfin.Api/Controllers/SuggestionsController.cs +++ b/Jellyfin.Api/Controllers/SuggestionsController.cs @@ -67,7 +67,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var result = _libraryManager.GetItemsResult(new InternalItemsQuery(user) { OrderBy = new[] { (ItemSortBy.Random, SortOrder.Descending) }, diff --git a/Jellyfin.Api/Controllers/SyncPlayController.cs b/Jellyfin.Api/Controllers/SyncPlayController.cs index c6b70f3d2..e194fc556 100644 --- a/Jellyfin.Api/Controllers/SyncPlayController.cs +++ b/Jellyfin.Api/Controllers/SyncPlayController.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.SyncPlayDtos; -using MediaBrowser.Controller.Net; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Session; using MediaBrowser.Controller.SyncPlay; using MediaBrowser.Controller.SyncPlay.PlaybackRequests; @@ -24,23 +24,23 @@ namespace Jellyfin.Api.Controllers public class SyncPlayController : BaseJellyfinApiController { private readonly ISessionManager _sessionManager; - private readonly IAuthorizationContext _authorizationContext; private readonly ISyncPlayManager _syncPlayManager; + private readonly IUserManager _userManager; /// <summary> /// Initializes a new instance of the <see cref="SyncPlayController"/> class. /// </summary> /// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param> - /// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> /// <param name="syncPlayManager">Instance of the <see cref="ISyncPlayManager"/> interface.</param> + /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> public SyncPlayController( ISessionManager sessionManager, - IAuthorizationContext authorizationContext, - ISyncPlayManager syncPlayManager) + ISyncPlayManager syncPlayManager, + IUserManager userManager) { _sessionManager = sessionManager; - _authorizationContext = authorizationContext; _syncPlayManager = syncPlayManager; + _userManager = userManager; } /// <summary> @@ -55,7 +55,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlayCreateGroup( [FromBody, Required] NewGroupRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new NewGroupRequest(requestData.GroupName); _syncPlayManager.NewGroup(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -73,7 +73,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlayJoinGroup( [FromBody, Required] JoinGroupRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new JoinGroupRequest(requestData.GroupId); _syncPlayManager.JoinGroup(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -89,7 +89,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.SyncPlayIsInGroup)] public async Task<ActionResult> SyncPlayLeaveGroup() { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new LeaveGroupRequest(); _syncPlayManager.LeaveGroup(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -105,7 +105,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.SyncPlayJoinGroup)] public async Task<ActionResult<IEnumerable<GroupInfoDto>>> SyncPlayGetGroups() { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new ListGroupsRequest(); return Ok(_syncPlayManager.ListGroups(currentSession, syncPlayRequest)); } @@ -122,7 +122,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlaySetNewQueue( [FromBody, Required] PlayRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new PlayGroupRequest( requestData.PlayingQueue, requestData.PlayingItemPosition, @@ -143,7 +143,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlaySetPlaylistItem( [FromBody, Required] SetPlaylistItemRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new SetPlaylistItemGroupRequest(requestData.PlaylistItemId); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -161,7 +161,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlayRemoveFromPlaylist( [FromBody, Required] RemoveFromPlaylistRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new RemoveFromPlaylistGroupRequest(requestData.PlaylistItemIds, requestData.ClearPlaylist, requestData.ClearPlayingItem); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -179,7 +179,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlayMovePlaylistItem( [FromBody, Required] MovePlaylistItemRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new MovePlaylistItemGroupRequest(requestData.PlaylistItemId, requestData.NewIndex); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -197,7 +197,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlayQueue( [FromBody, Required] QueueRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new QueueGroupRequest(requestData.ItemIds, requestData.Mode); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -213,7 +213,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.SyncPlayIsInGroup)] public async Task<ActionResult> SyncPlayUnpause() { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new UnpauseGroupRequest(); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -229,7 +229,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.SyncPlayIsInGroup)] public async Task<ActionResult> SyncPlayPause() { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new PauseGroupRequest(); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -245,7 +245,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.SyncPlayIsInGroup)] public async Task<ActionResult> SyncPlayStop() { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new StopGroupRequest(); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -263,7 +263,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlaySeek( [FromBody, Required] SeekRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new SeekGroupRequest(requestData.PositionTicks); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -281,7 +281,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlayBuffering( [FromBody, Required] BufferRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new BufferGroupRequest( requestData.When, requestData.PositionTicks, @@ -303,7 +303,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlayReady( [FromBody, Required] ReadyRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new ReadyGroupRequest( requestData.When, requestData.PositionTicks, @@ -325,7 +325,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlaySetIgnoreWait( [FromBody, Required] IgnoreWaitRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new IgnoreWaitGroupRequest(requestData.IgnoreWait); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -343,7 +343,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlayNextItem( [FromBody, Required] NextItemRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new NextItemGroupRequest(requestData.PlaylistItemId); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -361,7 +361,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlayPreviousItem( [FromBody, Required] PreviousItemRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new PreviousItemGroupRequest(requestData.PlaylistItemId); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -379,7 +379,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlaySetRepeatMode( [FromBody, Required] SetRepeatModeRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new SetRepeatModeGroupRequest(requestData.Mode); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -397,7 +397,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlaySetShuffleMode( [FromBody, Required] SetShuffleModeRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new SetShuffleModeGroupRequest(requestData.Mode); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -414,7 +414,7 @@ namespace Jellyfin.Api.Controllers public async Task<ActionResult> SyncPlayPing( [FromBody, Required] PingRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new PingGroupRequest(requestData.Ping); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); diff --git a/Jellyfin.Api/Controllers/TrailersController.cs b/Jellyfin.Api/Controllers/TrailersController.cs index cf812fa23..b296d1c96 100644 --- a/Jellyfin.Api/Controllers/TrailersController.cs +++ b/Jellyfin.Api/Controllers/TrailersController.cs @@ -119,7 +119,7 @@ namespace Jellyfin.Api.Controllers /// <returns>A <see cref="QueryResult{BaseItemDto}"/> with the trailers.</returns> [HttpGet] [ProducesResponseType(StatusCodes.Status200OK)] - public Task<ActionResult<QueryResult<BaseItemDto>>> GetTrailers( + public ActionResult<QueryResult<BaseItemDto>> GetTrailers( [FromQuery] Guid? userId, [FromQuery] string? maxOfficialRating, [FromQuery] bool? hasThemeSong, diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs index e39d05a6f..ea13ceb91 100644 --- a/Jellyfin.Api/Controllers/TvShowsController.cs +++ b/Jellyfin.Api/Controllers/TvShowsController.cs @@ -89,7 +89,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableRewatching = false) { var options = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var result = _tvSeriesManager.GetNextUp( @@ -154,7 +154,7 @@ namespace Jellyfin.Api.Controllers var parentIdGuid = parentId ?? Guid.Empty; var options = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user) @@ -223,7 +223,7 @@ namespace Jellyfin.Api.Controllers List<BaseItem> episodes; var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); if (seasonId.HasValue) // Season id was supplied. Get episodes by season id. @@ -349,7 +349,7 @@ namespace Jellyfin.Api.Controllers }); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var returnItems = _dtoService.GetBaseItemDtos(seasons, dtoOptions, user); diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index 43b8e2414..01e13b4fe 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -6,13 +6,13 @@ using System.Linq; using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Api.Models.StreamingDtos; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.MediaInfo; using Microsoft.AspNetCore.Authorization; @@ -28,7 +28,6 @@ namespace Jellyfin.Api.Controllers [Route("")] public class UniversalAudioController : BaseJellyfinApiController { - private readonly IAuthorizationContext _authorizationContext; private readonly ILibraryManager _libraryManager; private readonly ILogger<UniversalAudioController> _logger; private readonly MediaInfoHelper _mediaInfoHelper; @@ -38,21 +37,18 @@ namespace Jellyfin.Api.Controllers /// <summary> /// Initializes a new instance of the <see cref="UniversalAudioController"/> class. /// </summary> - /// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="logger">Instance of the <see cref="ILogger{UniversalAudioController}"/> interface.</param> /// <param name="mediaInfoHelper">Instance of <see cref="MediaInfoHelper"/>.</param> /// <param name="audioHelper">Instance of <see cref="AudioHelper"/>.</param> /// <param name="dynamicHlsHelper">Instance of <see cref="DynamicHlsHelper"/>.</param> public UniversalAudioController( - IAuthorizationContext authorizationContext, ILibraryManager libraryManager, ILogger<UniversalAudioController> logger, MediaInfoHelper mediaInfoHelper, AudioHelper audioHelper, DynamicHlsHelper dynamicHlsHelper) { - _authorizationContext = authorizationContext; _libraryManager = libraryManager; _logger = logger; _mediaInfoHelper = mediaInfoHelper; @@ -111,9 +107,11 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableRedirection = true) { var deviceProfile = GetDeviceProfile(container, transcodingContainer, audioCodec, transcodingProtocol, breakOnNonKeyFrames, transcodingAudioChannels, maxAudioSampleRate, maxAudioBitDepth, maxAudioChannels); - (await _authorizationContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).DeviceId = deviceId; - var authInfo = await _authorizationContext.GetAuthorizationInfo(Request).ConfigureAwait(false); + if (!userId.HasValue || userId.Value.Equals(Guid.Empty)) + { + userId = User.GetUserId(); + } _logger.LogInformation("GetPostedPlaybackInfo profile: {@Profile}", deviceProfile); @@ -132,7 +130,7 @@ namespace Jellyfin.Api.Controllers item, sourceInfo, deviceProfile, - authInfo, + User, maxStreamingBitrate ?? deviceProfile.MaxStreamingBitrate, startTimeTicks ?? 0, mediaSourceId ?? string.Empty, diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index d1109bebc..ff653fe6b 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -4,6 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.UserDtos; using Jellyfin.Data.Enums; @@ -82,11 +83,11 @@ namespace Jellyfin.Api.Controllers [HttpGet] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task<ActionResult<IEnumerable<UserDto>>> GetUsers( + public ActionResult<IEnumerable<UserDto>> GetUsers( [FromQuery] bool? isHidden, [FromQuery] bool? isDisabled) { - var users = await Get(isHidden, isDisabled, false, false).ConfigureAwait(false); + var users = Get(isHidden, isDisabled, false, false); return Ok(users); } @@ -97,15 +98,15 @@ namespace Jellyfin.Api.Controllers /// <returns>An <see cref="IEnumerable{UserDto}"/> containing the public users.</returns> [HttpGet("Public")] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task<ActionResult<IEnumerable<UserDto>>> GetPublicUsers() + public ActionResult<IEnumerable<UserDto>> GetPublicUsers() { // If the startup wizard hasn't been completed then just return all users if (!_config.Configuration.IsStartupWizardCompleted) { - return Ok(await Get(false, false, false, false).ConfigureAwait(false)); + return Ok(Get(false, false, false, false)); } - return Ok(await Get(false, false, true, true).ConfigureAwait(false)); + return Ok(Get(false, false, true, true)); } /// <summary> @@ -264,7 +265,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] Guid userId, [FromBody, Required] UpdateUserPassword request) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the password."); } @@ -282,7 +283,7 @@ namespace Jellyfin.Api.Controllers } else { - if (!HttpContext.User.IsInRole(UserRoles.Administrator)) + if (!User.IsInRole(UserRoles.Administrator)) { var success = await _userManager.AuthenticateUser( user.Username, @@ -299,7 +300,7 @@ namespace Jellyfin.Api.Controllers await _userManager.ChangePassword(user, request.NewPw).ConfigureAwait(false); - var currentToken = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).Token; + var currentToken = User.GetToken(); await _sessionManager.RevokeUserTokens(user.Id, currentToken).ConfigureAwait(false); } @@ -325,7 +326,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] Guid userId, [FromBody, Required] UpdateUserEasyPassword request) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the easy password."); } @@ -367,7 +368,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] Guid userId, [FromBody, Required] UserDto updateUser) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User update not allowed."); } @@ -427,7 +428,7 @@ namespace Jellyfin.Api.Controllers return StatusCode(StatusCodes.Status403Forbidden, "There must be at least one enabled user in the system."); } - var currentToken = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).Token; + var currentToken = User.GetToken(); await _sessionManager.RevokeUserTokens(user.Id, currentToken).ConfigureAwait(false); } @@ -452,7 +453,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] Guid userId, [FromBody, Required] UserConfiguration userConfig) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User configuration update not allowed"); } @@ -536,13 +537,13 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status400BadRequest)] public ActionResult<UserDto> GetCurrentUser() { - var userId = ClaimHelpers.GetUserId(Request.HttpContext.User); - if (userId is null) + var userId = User.GetUserId(); + if (userId.Equals(default)) { return BadRequest(); } - var user = _userManager.GetUserById(userId.Value); + var user = _userManager.GetUserById(userId); if (user == null) { return BadRequest(); @@ -551,7 +552,7 @@ namespace Jellyfin.Api.Controllers return _userManager.GetUserDto(user); } - private async Task<IEnumerable<UserDto>> Get(bool? isHidden, bool? isDisabled, bool filterByDevice, bool filterByNetwork) + private IEnumerable<UserDto> Get(bool? isHidden, bool? isDisabled, bool filterByDevice, bool filterByNetwork) { var users = _userManager.Users; @@ -567,7 +568,7 @@ namespace Jellyfin.Api.Controllers if (filterByDevice) { - var deviceId = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).DeviceId; + var deviceId = User.GetDeviceId(); if (!string.IsNullOrWhiteSpace(deviceId)) { diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index 1656a1e98..ee8a17b62 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -81,7 +81,7 @@ namespace Jellyfin.Api.Controllers await RefreshItemOnDemandIfNeeded(item).ConfigureAwait(false); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); return _dtoService.GetBaseItemDto(item, dtoOptions, user); } @@ -98,7 +98,7 @@ namespace Jellyfin.Api.Controllers { var user = _userManager.GetUserById(userId); var item = _libraryManager.GetUserRootFolder(); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); return _dtoService.GetBaseItemDto(item, dtoOptions, user); } @@ -120,7 +120,7 @@ namespace Jellyfin.Api.Controllers : _libraryManager.GetItemById(itemId); var items = await _libraryManager.GetIntros(item, user).ConfigureAwait(false); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var dtos = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray(); return new QueryResult<BaseItemDto>(dtos); @@ -200,7 +200,7 @@ namespace Jellyfin.Api.Controllers ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); if (item is IHasTrailers hasTrailers) { @@ -230,10 +230,11 @@ namespace Jellyfin.Api.Controllers ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); return Ok(item - .GetExtras(BaseItem.DisplayExtraTypes) + .GetExtras() + .Where(i => i.ExtraType.HasValue && BaseItem.DisplayExtraTypes.Contains(i.ExtraType.Value)) .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))); } @@ -279,7 +280,7 @@ namespace Jellyfin.Api.Controllers } var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var list = _userViewManager.GetLatestItems( diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs index 04732ccf2..85d154cac 100644 --- a/Jellyfin.Api/Controllers/UserViewsController.cs +++ b/Jellyfin.Api/Controllers/UserViewsController.cs @@ -85,7 +85,7 @@ namespace Jellyfin.Api.Controllers var folders = _userViewManager.GetUserViews(query); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var fields = dtoOptions.Fields.ToList(); fields.Add(ItemFields.PrimaryImageAspectRatio); diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 4e2895934..bf08ad376 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -43,7 +43,6 @@ namespace Jellyfin.Api.Controllers private readonly IUserManager _userManager; private readonly IDtoService _dtoService; private readonly IDlnaManager _dlnaManager; - private readonly IAuthorizationContext _authContext; private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; @@ -61,7 +60,6 @@ namespace Jellyfin.Api.Controllers /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param> /// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param> - /// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> @@ -74,7 +72,6 @@ namespace Jellyfin.Api.Controllers IUserManager userManager, IDtoService dtoService, IDlnaManager dlnaManager, - IAuthorizationContext authContext, IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, @@ -87,7 +84,6 @@ namespace Jellyfin.Api.Controllers _userManager = userManager; _dtoService = dtoService; _dlnaManager = dlnaManager; - _authContext = authContext; _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; @@ -120,7 +116,7 @@ namespace Jellyfin.Api.Controllers : _libraryManager.GetItemById(itemId); var dtoOptions = new DtoOptions(); - dtoOptions = dtoOptions.AddClientFields(Request); + dtoOptions = dtoOptions.AddClientFields(User); BaseItemDto[] items; if (item is Video video) @@ -429,8 +425,7 @@ namespace Jellyfin.Api.Controllers var state = await StreamingHelpers.GetStreamingState( streamingRequest, - Request, - _authContext, + HttpContext, _mediaSourceManager, _userManager, _libraryManager, diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs index 7c02e2550..b732bdff3 100644 --- a/Jellyfin.Api/Controllers/YearsController.cs +++ b/Jellyfin.Api/Controllers/YearsController.cs @@ -87,7 +87,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool? enableImages = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); User? user = userId is null || userId.Value.Equals(default) @@ -179,7 +179,7 @@ namespace Jellyfin.Api.Controllers } var dtoOptions = new DtoOptions() - .AddClientFields(Request); + .AddClientFields(User); if (userId.HasValue && !userId.Value.Equals(default)) { diff --git a/Jellyfin.Api/Extensions/ClaimsPrincipalExtensions.cs b/Jellyfin.Api/Extensions/ClaimsPrincipalExtensions.cs new file mode 100644 index 000000000..6b3e78d4d --- /dev/null +++ b/Jellyfin.Api/Extensions/ClaimsPrincipalExtensions.cs @@ -0,0 +1,81 @@ +using System; +using System.Linq; +using System.Security.Claims; +using Jellyfin.Api.Constants; + +namespace Jellyfin.Api.Extensions; + +/// <summary> +/// Extensions for <see cref="ClaimsPrincipal"/>. +/// </summary> +public static class ClaimsPrincipalExtensions +{ + /// <summary> + /// Get user id from claims. + /// </summary> + /// <param name="user">Current claims principal.</param> + /// <returns>User id.</returns> + public static Guid GetUserId(this ClaimsPrincipal user) + { + var value = GetClaimValue(user, InternalClaimTypes.UserId); + return string.IsNullOrEmpty(value) + ? default + : Guid.Parse(value); + } + + /// <summary> + /// Get device id from claims. + /// </summary> + /// <param name="user">Current claims principal.</param> + /// <returns>Device id.</returns> + public static string? GetDeviceId(this ClaimsPrincipal user) + => GetClaimValue(user, InternalClaimTypes.DeviceId); + + /// <summary> + /// Get device from claims. + /// </summary> + /// <param name="user">Current claims principal.</param> + /// <returns>Device.</returns> + public static string? GetDevice(this ClaimsPrincipal user) + => GetClaimValue(user, InternalClaimTypes.Device); + + /// <summary> + /// Get client from claims. + /// </summary> + /// <param name="user">Current claims principal.</param> + /// <returns>Client.</returns> + public static string? GetClient(this ClaimsPrincipal user) + => GetClaimValue(user, InternalClaimTypes.Client); + + /// <summary> + /// Get version from claims. + /// </summary> + /// <param name="user">Current claims principal.</param> + /// <returns>Version.</returns> + public static string? GetVersion(this ClaimsPrincipal user) + => GetClaimValue(user, InternalClaimTypes.Version); + + /// <summary> + /// Get token from claims. + /// </summary> + /// <param name="user">Current claims principal.</param> + /// <returns>Token.</returns> + public static string? GetToken(this ClaimsPrincipal user) + => GetClaimValue(user, InternalClaimTypes.Token); + + /// <summary> + /// Gets a flag specifying whether the request is using an api key. + /// </summary> + /// <param name="user">Current claims principal.</param> + /// <returns>The flag specifying whether the request is using an api key.</returns> + public static bool GetIsApiKey(this ClaimsPrincipal user) + { + var claimValue = GetClaimValue(user, InternalClaimTypes.IsApiKey); + return !string.IsNullOrEmpty(claimValue) + && bool.TryParse(claimValue, out var parsedClaimValue) + && parsedClaimValue; + } + + private static string? GetClaimValue(in ClaimsPrincipal user, string name) + => user.Claims.FirstOrDefault(claim => claim.Type.Equals(name, StringComparison.OrdinalIgnoreCase))?.Value; +} diff --git a/Jellyfin.Api/Extensions/DtoExtensions.cs b/Jellyfin.Api/Extensions/DtoExtensions.cs index 5e338b67d..9e784f7c4 100644 --- a/Jellyfin.Api/Extensions/DtoExtensions.cs +++ b/Jellyfin.Api/Extensions/DtoExtensions.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Jellyfin.Api.Helpers; +using System.Security.Claims; using Jellyfin.Extensions; using MediaBrowser.Controller.Dto; using MediaBrowser.Model.Entities; @@ -22,14 +22,14 @@ namespace Jellyfin.Api.Extensions /// Legacy order: 2. /// </remarks> /// <param name="dtoOptions">DtoOptions object.</param> - /// <param name="request">Current request.</param> + /// <param name="user">Current claims principal.</param> /// <returns>Modified DtoOptions object.</returns> internal static DtoOptions AddClientFields( - this DtoOptions dtoOptions, HttpRequest request) + this DtoOptions dtoOptions, ClaimsPrincipal user) { dtoOptions.Fields ??= Array.Empty<ItemFields>(); - string? client = ClaimHelpers.GetClient(request.HttpContext.User); + string? client = user.GetClient(); // No client in claim if (string.IsNullOrEmpty(client)) diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index 27497cd59..bc83ff48a 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -11,7 +11,6 @@ using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Net; using Microsoft.AspNetCore.Http; @@ -25,7 +24,6 @@ namespace Jellyfin.Api.Helpers public class AudioHelper { private readonly IDlnaManager _dlnaManager; - private readonly IAuthorizationContext _authContext; private readonly IUserManager _userManager; private readonly ILibraryManager _libraryManager; private readonly IMediaSourceManager _mediaSourceManager; @@ -41,7 +39,6 @@ namespace Jellyfin.Api.Helpers /// Initializes a new instance of the <see cref="AudioHelper"/> class. /// </summary> /// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param> - /// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> @@ -54,7 +51,6 @@ namespace Jellyfin.Api.Helpers /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param> public AudioHelper( IDlnaManager dlnaManager, - IAuthorizationContext authContext, IUserManager userManager, ILibraryManager libraryManager, IMediaSourceManager mediaSourceManager, @@ -67,7 +63,6 @@ namespace Jellyfin.Api.Helpers EncodingHelper encodingHelper) { _dlnaManager = dlnaManager; - _authContext = authContext; _userManager = userManager; _libraryManager = libraryManager; _mediaSourceManager = mediaSourceManager; @@ -102,8 +97,7 @@ namespace Jellyfin.Api.Helpers using var state = await StreamingHelpers.GetStreamingState( streamingRequest, - _httpContextAccessor.HttpContext.Request, - _authContext, + _httpContextAccessor.HttpContext, _mediaSourceManager, _userManager, _libraryManager, diff --git a/Jellyfin.Api/Helpers/ClaimHelpers.cs b/Jellyfin.Api/Helpers/ClaimHelpers.cs deleted file mode 100644 index c1c2f93b4..000000000 --- a/Jellyfin.Api/Helpers/ClaimHelpers.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.Linq; -using System.Security.Claims; -using Jellyfin.Api.Constants; - -namespace Jellyfin.Api.Helpers -{ - /// <summary> - /// Claim Helpers. - /// </summary> - public static class ClaimHelpers - { - /// <summary> - /// Get user id from claims. - /// </summary> - /// <param name="user">Current claims principal.</param> - /// <returns>User id.</returns> - public static Guid? GetUserId(in ClaimsPrincipal user) - { - var value = GetClaimValue(user, InternalClaimTypes.UserId); - return string.IsNullOrEmpty(value) - ? null - : Guid.Parse(value); - } - - /// <summary> - /// Get device id from claims. - /// </summary> - /// <param name="user">Current claims principal.</param> - /// <returns>Device id.</returns> - public static string? GetDeviceId(in ClaimsPrincipal user) - => GetClaimValue(user, InternalClaimTypes.DeviceId); - - /// <summary> - /// Get device from claims. - /// </summary> - /// <param name="user">Current claims principal.</param> - /// <returns>Device.</returns> - public static string? GetDevice(in ClaimsPrincipal user) - => GetClaimValue(user, InternalClaimTypes.Device); - - /// <summary> - /// Get client from claims. - /// </summary> - /// <param name="user">Current claims principal.</param> - /// <returns>Client.</returns> - public static string? GetClient(in ClaimsPrincipal user) - => GetClaimValue(user, InternalClaimTypes.Client); - - /// <summary> - /// Get version from claims. - /// </summary> - /// <param name="user">Current claims principal.</param> - /// <returns>Version.</returns> - public static string? GetVersion(in ClaimsPrincipal user) - => GetClaimValue(user, InternalClaimTypes.Version); - - /// <summary> - /// Get token from claims. - /// </summary> - /// <param name="user">Current claims principal.</param> - /// <returns>Token.</returns> - public static string? GetToken(in ClaimsPrincipal user) - => GetClaimValue(user, InternalClaimTypes.Token); - - /// <summary> - /// Gets a flag specifying whether the request is using an api key. - /// </summary> - /// <param name="user">Current claims principal.</param> - /// <returns>The flag specifying whether the request is using an api key.</returns> - public static bool GetIsApiKey(in ClaimsPrincipal user) - { - var claimValue = GetClaimValue(user, InternalClaimTypes.IsApiKey); - return !string.IsNullOrEmpty(claimValue) - && bool.TryParse(claimValue, out var parsedClaimValue) - && parsedClaimValue; - } - - private static string? GetClaimValue(in ClaimsPrincipal user, string name) - { - return user?.Identities - .SelectMany(c => c.Claims) - .Where(claim => claim.Type.Equals(name, StringComparison.OrdinalIgnoreCase)) - .Select(claim => claim.Value) - .FirstOrDefault(); - } - } -} diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index 83c9141a9..fa392e567 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -7,6 +7,7 @@ using System.Security.Claims; using System.Text; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Models.StreamingDtos; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; @@ -15,7 +16,6 @@ using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Net; @@ -34,7 +34,6 @@ namespace Jellyfin.Api.Helpers private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; private readonly IDlnaManager _dlnaManager; - private readonly IAuthorizationContext _authContext; private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; @@ -51,7 +50,6 @@ namespace Jellyfin.Api.Helpers /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> /// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param> - /// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> @@ -65,7 +63,6 @@ namespace Jellyfin.Api.Helpers ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, - IAuthorizationContext authContext, IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, @@ -79,7 +76,6 @@ namespace Jellyfin.Api.Helpers _libraryManager = libraryManager; _userManager = userManager; _dlnaManager = dlnaManager; - _authContext = authContext; _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; @@ -128,8 +124,7 @@ namespace Jellyfin.Api.Helpers using var state = await StreamingHelpers.GetStreamingState( streamingRequest, - _httpContextAccessor.HttpContext.Request, - _authContext, + _httpContextAccessor.HttpContext, _mediaSourceManager, _userManager, _libraryManager, @@ -483,7 +478,7 @@ namespace Jellyfin.Api.Helpers state.Request.MediaSourceId, stream.Index.ToString(CultureInfo.InvariantCulture), 30.ToString(CultureInfo.InvariantCulture), - ClaimHelpers.GetToken(user)); + user.GetToken()); var line = string.Format( CultureInfo.InvariantCulture, diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs index 5c05c57a6..4441ae023 100644 --- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs +++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs @@ -2,9 +2,11 @@ using System.Globalization; using System.Linq; using System.Net; +using System.Security.Claims; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Extensions; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using MediaBrowser.Common.Extensions; @@ -15,7 +17,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -39,7 +40,6 @@ namespace Jellyfin.Api.Helpers private readonly ILogger<MediaInfoHelper> _logger; private readonly INetworkManager _networkManager; private readonly IDeviceManager _deviceManager; - private readonly IAuthorizationContext _authContext; /// <summary> /// Initializes a new instance of the <see cref="MediaInfoHelper"/> class. @@ -52,7 +52,6 @@ namespace Jellyfin.Api.Helpers /// <param name="logger">Instance of the <see cref="ILogger{MediaInfoHelper}"/> interface.</param> /// <param name="networkManager">Instance of the <see cref="INetworkManager"/> interface.</param> /// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param> - /// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> public MediaInfoHelper( IUserManager userManager, ILibraryManager libraryManager, @@ -61,8 +60,7 @@ namespace Jellyfin.Api.Helpers IServerConfigurationManager serverConfigurationManager, ILogger<MediaInfoHelper> logger, INetworkManager networkManager, - IDeviceManager deviceManager, - IAuthorizationContext authContext) + IDeviceManager deviceManager) { _userManager = userManager; _libraryManager = libraryManager; @@ -72,7 +70,6 @@ namespace Jellyfin.Api.Helpers _logger = logger; _networkManager = networkManager; _deviceManager = deviceManager; - _authContext = authContext; } /// <summary> @@ -147,7 +144,7 @@ namespace Jellyfin.Api.Helpers /// <param name="item">Item to set data for.</param> /// <param name="mediaSource">Media source info.</param> /// <param name="profile">Device profile.</param> - /// <param name="auth">Authorization info.</param> + /// <param name="claimsPrincipal">Current claims principal.</param> /// <param name="maxBitrate">Max bitrate.</param> /// <param name="startTimeTicks">Start time ticks.</param> /// <param name="mediaSourceId">Media source id.</param> @@ -166,7 +163,7 @@ namespace Jellyfin.Api.Helpers BaseItem item, MediaSourceInfo mediaSource, DeviceProfile profile, - AuthorizationInfo auth, + ClaimsPrincipal claimsPrincipal, int? maxBitrate, long startTimeTicks, string mediaSourceId, @@ -188,7 +185,7 @@ namespace Jellyfin.Api.Helpers { MediaSources = new[] { mediaSource }, Context = EncodingContext.Streaming, - DeviceId = auth.DeviceId, + DeviceId = claimsPrincipal.GetDeviceId(), ItemId = item.Id, Profile = profile, MaxAudioChannels = maxAudioChannels, @@ -290,7 +287,7 @@ namespace Jellyfin.Api.Helpers mediaSource.SupportsDirectPlay = false; mediaSource.SupportsDirectStream = false; - mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-'); + mediaSource.TranscodingUrl = streamInfo.ToUrl("-", claimsPrincipal.GetToken()).TrimStart('-'); mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false"; mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false"; mediaSource.TranscodingContainer = streamInfo.Container; @@ -301,7 +298,7 @@ namespace Jellyfin.Api.Helpers if (!mediaSource.SupportsDirectPlay && (mediaSource.SupportsTranscoding || mediaSource.SupportsDirectStream)) { streamInfo.PlayMethod = PlayMethod.Transcode; - mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-'); + mediaSource.TranscodingUrl = streamInfo.ToUrl("-", claimsPrincipal.GetToken()).TrimStart('-'); if (!allowVideoStreamCopy) { @@ -316,7 +313,8 @@ namespace Jellyfin.Api.Helpers } // Do this after the above so that StartPositionTicks is set - SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token); + // The token must not be null + SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, claimsPrincipal.GetToken()!); mediaSource.DefaultAudioStreamIndex = streamInfo.AudioStreamIndex; } @@ -384,19 +382,17 @@ namespace Jellyfin.Api.Helpers /// <summary> /// Open media source. /// </summary> - /// <param name="httpRequest">Http Request.</param> + /// <param name="httpContext">Http Context.</param> /// <param name="request">Live stream request.</param> /// <returns>A <see cref="Task"/> containing the <see cref="LiveStreamResponse"/>.</returns> - public async Task<LiveStreamResponse> OpenMediaSource(HttpRequest httpRequest, LiveStreamRequest request) + public async Task<LiveStreamResponse> OpenMediaSource(HttpContext httpContext, LiveStreamRequest request) { - var authInfo = await _authContext.GetAuthorizationInfo(httpRequest).ConfigureAwait(false); - var result = await _mediaSourceManager.OpenLiveStream(request, CancellationToken.None).ConfigureAwait(false); var profile = request.DeviceProfile; if (profile == null) { - var clientCapabilities = _deviceManager.GetCapabilities(authInfo.DeviceId); + var clientCapabilities = _deviceManager.GetCapabilities(httpContext.User.GetDeviceId()); if (clientCapabilities != null) { profile = clientCapabilities.DeviceProfile; @@ -411,7 +407,7 @@ namespace Jellyfin.Api.Helpers item, result.MediaSource, profile, - authInfo, + httpContext.User, request.MaxStreamingBitrate, request.StartTimeTicks ?? 0, result.MediaSource.Id, @@ -425,7 +421,7 @@ namespace Jellyfin.Api.Helpers true, true, true, - httpRequest.HttpContext.GetNormalizedRemoteIp()); + httpContext.GetNormalizedRemoteIp()); } else { diff --git a/Jellyfin.Api/Helpers/RequestHelpers.cs b/Jellyfin.Api/Helpers/RequestHelpers.cs index 20427d7fa..8c5af013a 100644 --- a/Jellyfin.Api/Helpers/RequestHelpers.cs +++ b/Jellyfin.Api/Helpers/RequestHelpers.cs @@ -1,13 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Claims; using System.Threading.Tasks; +using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Net; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; @@ -55,37 +58,42 @@ namespace Jellyfin.Api.Helpers /// <summary> /// Checks if the user can update an entry. /// </summary> - /// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> - /// <param name="requestContext">The <see cref="HttpRequest"/>.</param> + /// <param name="userManager">An instance of the <see cref="IUserManager"/> interface.</param> + /// <param name="claimsPrincipal">The <see cref="ClaimsPrincipal"/> for the current request.</param> /// <param name="userId">The user id.</param> /// <param name="restrictUserPreferences">Whether to restrict the user preferences.</param> /// <returns>A <see cref="bool"/> whether the user can update the entry.</returns> - internal static async Task<bool> AssertCanUpdateUser(IAuthorizationContext authContext, HttpRequest requestContext, Guid userId, bool restrictUserPreferences) + internal static bool AssertCanUpdateUser(IUserManager userManager, ClaimsPrincipal claimsPrincipal, Guid userId, bool restrictUserPreferences) { - var auth = await authContext.GetAuthorizationInfo(requestContext).ConfigureAwait(false); - - var authenticatedUser = auth.User; + var authenticatedUserId = claimsPrincipal.GetUserId(); + var isAdministrator = claimsPrincipal.IsInRole(UserRoles.Administrator); // If they're going to update the record of another user, they must be an administrator - if ((!userId.Equals(auth.UserId) && !authenticatedUser.HasPermission(PermissionKind.IsAdministrator)) - || (restrictUserPreferences && !authenticatedUser.EnableUserPreferenceAccess)) + if (!userId.Equals(authenticatedUserId) && !isAdministrator) { return false; } - return true; + // TODO the EnableUserPreferenceAccess policy does not seem to be used elsewhere + if (!restrictUserPreferences || isAdministrator) + { + return true; + } + + var user = userManager.GetUserById(userId); + return user.EnableUserPreferenceAccess; } - internal static async Task<SessionInfo> GetSession(ISessionManager sessionManager, IAuthorizationContext authContext, HttpRequest request) + internal static async Task<SessionInfo> GetSession(ISessionManager sessionManager, IUserManager userManager, HttpContext httpContext) { - var authorization = await authContext.GetAuthorizationInfo(request).ConfigureAwait(false); - var user = authorization.User; + var userId = httpContext.User.GetUserId(); + var user = userManager.GetUserById(userId); var session = await sessionManager.LogSessionActivity( - authorization.Client, - authorization.Version, - authorization.DeviceId, - authorization.Device, - request.HttpContext.GetNormalizedRemoteIp().ToString(), + httpContext.User.GetClient(), + httpContext.User.GetVersion(), + httpContext.User.GetDeviceId(), + httpContext.User.GetDevice(), + httpContext.GetNormalizedRemoteIp().ToString(), user).ConfigureAwait(false); if (session == null) @@ -96,9 +104,9 @@ namespace Jellyfin.Api.Helpers return session; } - internal static async Task<string> GetSessionId(ISessionManager sessionManager, IAuthorizationContext authContext, HttpRequest request) + internal static async Task<string> GetSessionId(ISessionManager sessionManager, IUserManager userManager, HttpContext httpContext) { - var session = await GetSession(sessionManager, authContext, request).ConfigureAwait(false); + var session = await GetSession(sessionManager, userManager, httpContext).ConfigureAwait(false); return session.Id; } diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index b552df0a4..370573773 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Models.StreamingDtos; using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; @@ -14,7 +15,6 @@ using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -33,8 +33,7 @@ namespace Jellyfin.Api.Helpers /// Gets the current streaming state. /// </summary> /// <param name="streamingRequest">The <see cref="StreamingRequestDto"/>.</param> - /// <param name="httpRequest">The <see cref="HttpRequest"/>.</param> - /// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> + /// <param name="httpContext">The <see cref="HttpContext"/>.</param> /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> @@ -49,8 +48,7 @@ namespace Jellyfin.Api.Helpers /// <returns>A <see cref="Task"/> containing the current <see cref="StreamState"/>.</returns> public static async Task<StreamState> GetStreamingState( StreamingRequestDto streamingRequest, - HttpRequest httpRequest, - IAuthorizationContext authorizationContext, + HttpContext httpContext, IMediaSourceManager mediaSourceManager, IUserManager userManager, ILibraryManager libraryManager, @@ -63,6 +61,7 @@ namespace Jellyfin.Api.Helpers TranscodingJobType transcodingJobType, CancellationToken cancellationToken) { + var httpRequest = httpContext.Request; // Parse the DLNA time seek header if (!streamingRequest.StartTimeTicks.HasValue) { @@ -101,10 +100,10 @@ namespace Jellyfin.Api.Helpers EnableDlnaHeaders = enableDlnaHeaders }; - var auth = await authorizationContext.GetAuthorizationInfo(httpRequest).ConfigureAwait(false); - if (!auth.UserId.Equals(default)) + var userId = httpContext.User.GetUserId(); + if (!userId.Equals(default)) { - state.User = userManager.GetUserById(auth.UserId); + state.User = userManager.GetUserById(userId); } if (state.IsVideoRequest && !string.IsNullOrWhiteSpace(state.Request.VideoCodec)) diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 13dc878c1..c663c6e31 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -8,6 +8,7 @@ using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Models.PlaybackDtos; using Jellyfin.Api.Models.StreamingDtos; using Jellyfin.Data.Enums; @@ -17,7 +18,6 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Entities; @@ -46,7 +46,6 @@ namespace Jellyfin.Api.Helpers private readonly IAttachmentExtractor _attachmentExtractor; private readonly IApplicationPaths _appPaths; - private readonly IAuthorizationContext _authorizationContext; private readonly EncodingHelper _encodingHelper; private readonly IFileSystem _fileSystem; private readonly ILogger<TranscodingJobHelper> _logger; @@ -55,6 +54,7 @@ namespace Jellyfin.Api.Helpers private readonly IServerConfigurationManager _serverConfigurationManager; private readonly ISessionManager _sessionManager; private readonly ILoggerFactory _loggerFactory; + private readonly IUserManager _userManager; /// <summary> /// Initializes a new instance of the <see cref="TranscodingJobHelper"/> class. @@ -67,9 +67,9 @@ namespace Jellyfin.Api.Helpers /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param> - /// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param> /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param> + /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> public TranscodingJobHelper( IAttachmentExtractor attachmentExtractor, IApplicationPaths appPaths, @@ -79,9 +79,9 @@ namespace Jellyfin.Api.Helpers IMediaEncoder mediaEncoder, IServerConfigurationManager serverConfigurationManager, ISessionManager sessionManager, - IAuthorizationContext authorizationContext, EncodingHelper encodingHelper, - ILoggerFactory loggerFactory) + ILoggerFactory loggerFactory, + IUserManager userManager) { _attachmentExtractor = attachmentExtractor; _appPaths = appPaths; @@ -91,9 +91,9 @@ namespace Jellyfin.Api.Helpers _mediaEncoder = mediaEncoder; _serverConfigurationManager = serverConfigurationManager; _sessionManager = sessionManager; - _authorizationContext = authorizationContext; _encodingHelper = encodingHelper; _loggerFactory = loggerFactory; + _userManager = userManager; DeleteEncodedMediaCache(); @@ -512,8 +512,9 @@ namespace Jellyfin.Api.Helpers if (state.VideoRequest != null && !EncodingHelper.IsCopyCodec(state.OutputVideoCodec)) { - var auth = await _authorizationContext.GetAuthorizationInfo(request).ConfigureAwait(false); - if (auth.User != null && !auth.User.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding)) + var userId = request.HttpContext.User.GetUserId(); + var user = userId.Equals(default) ? null : _userManager.GetUserById(userId); + if (user != null && !user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding)) { this.OnTranscodeFailedToStart(outputPath, transcodingJobType, state); @@ -654,7 +655,7 @@ namespace Jellyfin.Api.Helpers { if (EnableThrottling(state)) { - transcodingJob.TranscodingThrottler = new TranscodingThrottler(transcodingJob, new Logger<TranscodingThrottler>(new LoggerFactory()), _serverConfigurationManager, _fileSystem); + transcodingJob.TranscodingThrottler = new TranscodingThrottler(transcodingJob, new Logger<TranscodingThrottler>(new LoggerFactory()), _serverConfigurationManager, _fileSystem, _mediaEncoder); transcodingJob.TranscodingThrottler.Start(); } } diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index ce01b415b..7e64cf645 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -17,7 +17,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.8" /> + <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.9" /> <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" /> <PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="6.4.0" /> diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs index 7a1ca252c..99376873c 100644 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs +++ b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs @@ -2,6 +2,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; @@ -17,6 +18,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos private readonly ILogger<TranscodingThrottler> _logger; private readonly IConfigurationManager _config; private readonly IFileSystem _fileSystem; + private readonly IMediaEncoder _mediaEncoder; private Timer? _timer; private bool _isPaused; @@ -27,12 +29,14 @@ namespace Jellyfin.Api.Models.PlaybackDtos /// <param name="logger">Instance of the <see cref="ILogger{TranscodingThrottler}"/> interface.</param> /// <param name="config">Instance of the <see cref="IConfigurationManager"/> interface.</param> /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> - public TranscodingThrottler(TranscodingJobDto job, ILogger<TranscodingThrottler> logger, IConfigurationManager config, IFileSystem fileSystem) + /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> + public TranscodingThrottler(TranscodingJobDto job, ILogger<TranscodingThrottler> logger, IConfigurationManager config, IFileSystem fileSystem, IMediaEncoder mediaEncoder) { _job = job; _logger = logger; _config = config; _fileSystem = fileSystem; + _mediaEncoder = mediaEncoder; } /// <summary> @@ -55,7 +59,8 @@ namespace Jellyfin.Api.Models.PlaybackDtos try { - await _job.Process!.StandardInput.WriteLineAsync().ConfigureAwait(false); + var resumeKey = _mediaEncoder.IsPkeyPauseSupported ? "u" : Environment.NewLine; + await _job.Process!.StandardInput.WriteAsync(resumeKey).ConfigureAwait(false); _isPaused = false; } catch (Exception ex) @@ -125,11 +130,13 @@ namespace Jellyfin.Api.Models.PlaybackDtos { if (!_isPaused) { - _logger.LogDebug("Sending pause command to ffmpeg"); + var pauseKey = _mediaEncoder.IsPkeyPauseSupported ? "p" : "c"; + + _logger.LogDebug("Sending pause command [{Key}] to ffmpeg", pauseKey); try { - await _job.Process!.StandardInput.WriteAsync("c").ConfigureAwait(false); + await _job.Process!.StandardInput.WriteAsync(pauseKey).ConfigureAwait(false); _isPaused = true; } catch (Exception ex) diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs index 13f155f35..84b261b54 100644 --- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -145,7 +145,7 @@ namespace Jellyfin.Drawing.Skia /// <exception cref="SkiaCodecException">The file at the specified path could not be used to generate a codec.</exception> public string GetImageBlurHash(int xComp, int yComp, string path) { - ArgumentNullException.ThrowIfNull(path, nameof(path)); + ArgumentNullException.ThrowIfNull(path); if (path.Length == 0) { diff --git a/Jellyfin.Drawing.Skia/StripCollageBuilder.cs b/Jellyfin.Drawing.Skia/StripCollageBuilder.cs index 6bece9db6..b55a99405 100644 --- a/Jellyfin.Drawing.Skia/StripCollageBuilder.cs +++ b/Jellyfin.Drawing.Skia/StripCollageBuilder.cs @@ -29,10 +29,7 @@ namespace Jellyfin.Drawing.Skia /// <returns>The image format.</returns> public static SKEncodedImageFormat GetEncodedFormat(string outputPath) { - if (outputPath == null) - { - throw new ArgumentNullException(nameof(outputPath)); - } + ArgumentNullException.ThrowIfNull(outputPath); var ext = Path.GetExtension(outputPath); diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index fd0665dbd..9e06cdfe7 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -353,10 +353,7 @@ namespace Jellyfin.Networking.Manager public string GetBindInterface(IPObject source, out int? port) { port = null; - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(source); // Do we have a source? bool haveSource = !source.Address.Equals(IPAddress.None); @@ -476,10 +473,7 @@ namespace Jellyfin.Networking.Manager /// <inheritdoc/> public bool IsInLocalNetwork(IPAddress address) { - if (address == null) - { - throw new ArgumentNullException(nameof(address)); - } + ArgumentNullException.ThrowIfNull(address); if (address.Equals(IPAddress.None)) { @@ -499,10 +493,7 @@ namespace Jellyfin.Networking.Manager /// <inheritdoc/> public bool IsPrivateAddressRange(IPObject address) { - if (address == null) - { - throw new ArgumentNullException(nameof(address)); - } + ArgumentNullException.ThrowIfNull(address); // See conversation at https://github.com/jellyfin/jellyfin/pull/3515. if (TrustAllIP6Interfaces && address.AddressFamily == AddressFamily.InterNetworkV6) diff --git a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs index 3203bed18..0728f1179 100644 --- a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs +++ b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs @@ -201,10 +201,7 @@ namespace Jellyfin.Server.Implementations.Devices /// <inheritdoc /> public bool CanAccessDevice(User user, string deviceId) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); if (string.IsNullOrEmpty(deviceId)) { diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 678f96083..83b226278 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -27,13 +27,13 @@ <ItemGroup> <PackageReference Include="System.Linq.Async" Version="6.0.1" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.8" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.8" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.8"> + <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.9" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.9" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.9"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> - <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.8"> + <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.9"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 6a2ef74dd..ed90e81c6 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -130,10 +130,7 @@ namespace Jellyfin.Server.Implementations.Users /// <inheritdoc/> public async Task RenameUser(User user, string newName) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); ThrowIfInvalidUsername(newName); @@ -267,10 +264,7 @@ namespace Jellyfin.Server.Implementations.Users /// <inheritdoc/> public async Task ChangePassword(User user, string newPassword) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); await GetAuthenticationProvider(user).ChangePassword(user, newPassword).ConfigureAwait(false); await UpdateUserAsync(user).ConfigureAwait(false); diff --git a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs index 28ed3894f..bb264d512 100644 --- a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs +++ b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs @@ -69,8 +69,8 @@ namespace Jellyfin.Server.Infrastructure /// <inheritdoc /> protected override Task WriteFileAsync(ActionContext context, PhysicalFileResult result, RangeItemHeaderValue? range, long rangeLength) { - ArgumentNullException.ThrowIfNull(context, nameof(context)); - ArgumentNullException.ThrowIfNull(result, nameof(result)); + ArgumentNullException.ThrowIfNull(context); + ArgumentNullException.ThrowIfNull(result); if (range != null && rangeLength == 0) { diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 4474a6d12..b2d79050b 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -37,18 +37,18 @@ <PackageReference Include="CommandLineParser" Version="2.9.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="6.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" /> - <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="6.0.8" /> - <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="6.0.8" /> + <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="6.0.9" /> + <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="6.0.9" /> <PackageReference Include="prometheus-net" Version="6.0.0" /> <PackageReference Include="prometheus-net.AspNetCore" Version="6.0.0" /> <PackageReference Include="Serilog.AspNetCore" Version="4.1.0" /> <PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" /> - <PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0" /> + <PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" /> <PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" /> - <PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" /> + <PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" /> <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" /> <PackageReference Include="Serilog.Sinks.Graylog" Version="2.3.0" /> - <PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.1" /> + <PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.2" /> </ItemGroup> <ItemGroup> diff --git a/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs b/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs index e0c112d60..9875df310 100644 --- a/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs +++ b/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs @@ -45,36 +45,32 @@ namespace Jellyfin.Server.Middleware var localPath = httpContext.Request.Path.ToString(); var baseUrlPrefix = serverConfigurationManager.GetNetworkConfiguration().BaseUrl; - if (!string.IsNullOrEmpty(baseUrlPrefix)) + if (string.IsNullOrEmpty(localPath) + || string.Equals(localPath, baseUrlPrefix, StringComparison.OrdinalIgnoreCase) + || string.Equals(localPath, baseUrlPrefix + "/", StringComparison.OrdinalIgnoreCase) + || string.Equals(localPath, baseUrlPrefix + "/web", StringComparison.OrdinalIgnoreCase) + || string.Equals(localPath, baseUrlPrefix + "/web/", StringComparison.OrdinalIgnoreCase) + || !localPath.StartsWith(baseUrlPrefix, StringComparison.OrdinalIgnoreCase) + ) { - var startsWithBaseUrl = localPath.StartsWith(baseUrlPrefix, StringComparison.OrdinalIgnoreCase); - - if (!startsWithBaseUrl - && (localPath.Equals("/health", StringComparison.OrdinalIgnoreCase) - || localPath.Equals("/health/", StringComparison.OrdinalIgnoreCase))) + // Redirect health endpoint + if (string.Equals(localPath, "/health", StringComparison.OrdinalIgnoreCase) + || string.Equals(localPath, "/health/", StringComparison.OrdinalIgnoreCase)) { _logger.LogDebug("Redirecting /health check"); httpContext.Response.Redirect(baseUrlPrefix + "/health"); return; } - if (!startsWithBaseUrl - || localPath.Length == baseUrlPrefix.Length - // Local path is /baseUrl/ - || (localPath.Length == baseUrlPrefix.Length + 1 && localPath[^1] == '/')) - { - // Always redirect back to the default path if the base prefix is invalid, missing, or is the full path. - _logger.LogDebug("Normalizing an URL at {LocalPath}", localPath); - httpContext.Response.Redirect(baseUrlPrefix + "/" + _configuration[DefaultRedirectKey]); - return; - } - } - else if (string.IsNullOrEmpty(localPath) - || localPath.Equals("/", StringComparison.Ordinal)) - { - // Always redirect back to the default path if root is requested. + // Always redirect back to the default path if the base prefix is invalid or missing _logger.LogDebug("Normalizing an URL at {LocalPath}", localPath); - httpContext.Response.Redirect("/" + _configuration[DefaultRedirectKey]); + + var uri = new Uri(localPath); + var redirectUri = new Uri(baseUrlPrefix + "/" + _configuration[DefaultRedirectKey]); + var target = uri.MakeRelativeUri(redirectUri).ToString(); + _logger.LogDebug("Redirecting to {Target}", target); + + httpContext.Response.Redirect(target); return; } diff --git a/MediaBrowser.Common/Net/IPNetAddress.cs b/MediaBrowser.Common/Net/IPNetAddress.cs index f1428d4be..98d1c2d97 100644 --- a/MediaBrowser.Common/Net/IPNetAddress.cs +++ b/MediaBrowser.Common/Net/IPNetAddress.cs @@ -160,10 +160,7 @@ namespace MediaBrowser.Common.Net /// <inheritdoc/> public override bool Contains(IPAddress address) { - if (address == null) - { - throw new ArgumentNullException(nameof(address)); - } + ArgumentNullException.ThrowIfNull(address); if (address.IsIPv4MappedToIPv6) { diff --git a/MediaBrowser.Common/Net/IPObject.cs b/MediaBrowser.Common/Net/IPObject.cs index 3a5187bc3..37385972f 100644 --- a/MediaBrowser.Common/Net/IPObject.cs +++ b/MediaBrowser.Common/Net/IPObject.cs @@ -55,10 +55,7 @@ namespace MediaBrowser.Common.Net /// <returns>IPAddress.</returns> public static (IPAddress Address, byte PrefixLength) NetworkAddressOf(IPAddress address, byte prefixLength) { - if (address == null) - { - throw new ArgumentNullException(nameof(address)); - } + ArgumentNullException.ThrowIfNull(address); if (address.IsIPv4MappedToIPv6) { @@ -109,10 +106,7 @@ namespace MediaBrowser.Common.Net /// <returns>True if it is.</returns> public static bool IsIP6(IPAddress address) { - if (address == null) - { - throw new ArgumentNullException(nameof(address)); - } + ArgumentNullException.ThrowIfNull(address); if (address.IsIPv4MappedToIPv6) { @@ -129,10 +123,7 @@ namespace MediaBrowser.Common.Net /// <returns>True if it contains a private address.</returns> public static bool IsPrivateAddressRange(IPAddress address) { - if (address == null) - { - throw new ArgumentNullException(nameof(address)); - } + ArgumentNullException.ThrowIfNull(address); if (!address.Equals(IPAddress.None)) { @@ -179,10 +170,7 @@ namespace MediaBrowser.Common.Net /// </remarks> public static bool IsIPv6LinkLocal(IPAddress address) { - if (address == null) - { - throw new ArgumentNullException(nameof(address)); - } + ArgumentNullException.ThrowIfNull(address); if (address.IsIPv4MappedToIPv6) { @@ -226,10 +214,7 @@ namespace MediaBrowser.Common.Net /// <returns>Byte CIDR representing the mask.</returns> public static byte MaskToCidr(IPAddress mask) { - if (mask == null) - { - throw new ArgumentNullException(nameof(mask)); - } + ArgumentNullException.ThrowIfNull(mask); byte cidrnet = 0; if (!mask.Equals(IPAddress.Any)) diff --git a/MediaBrowser.Common/Net/NetworkExtensions.cs b/MediaBrowser.Common/Net/NetworkExtensions.cs index 264bfacb4..7ad005854 100644 --- a/MediaBrowser.Common/Net/NetworkExtensions.cs +++ b/MediaBrowser.Common/Net/NetworkExtensions.cs @@ -61,10 +61,7 @@ namespace MediaBrowser.Common.Net return false; } - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); if (item.IsIPv4MappedToIPv6) { @@ -96,10 +93,7 @@ namespace MediaBrowser.Common.Net return false; } - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); foreach (var i in source) { @@ -153,10 +147,7 @@ namespace MediaBrowser.Common.Net /// <returns>Collection{IPObject} object containing the subnets.</returns> public static Collection<IPObject> AsNetworks(this Collection<IPObject> source) { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(source); Collection<IPObject> res = new Collection<IPObject>(); @@ -239,10 +230,7 @@ namespace MediaBrowser.Common.Net return new Collection<IPObject>(); } - if (target == null) - { - throw new ArgumentNullException(nameof(target)); - } + ArgumentNullException.ThrowIfNull(target); Collection<IPObject> nc = new Collection<IPObject>(); diff --git a/MediaBrowser.Common/Plugins/BasePluginOfT.cs b/MediaBrowser.Common/Plugins/BasePluginOfT.cs index afda83a7c..0da5592d3 100644 --- a/MediaBrowser.Common/Plugins/BasePluginOfT.cs +++ b/MediaBrowser.Common/Plugins/BasePluginOfT.cs @@ -164,10 +164,7 @@ namespace MediaBrowser.Common.Plugins /// <inheritdoc /> public virtual void UpdateConfiguration(BasePluginConfiguration configuration) { - if (configuration == null) - { - throw new ArgumentNullException(nameof(configuration)); - } + ArgumentNullException.ThrowIfNull(configuration); Configuration = (TConfigurationType)configuration; diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs index 77a857b78..e671e5c71 100644 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs @@ -171,10 +171,7 @@ namespace MediaBrowser.Controller.Entities /// <exception cref="ArgumentNullException">Throws if child is null.</exception> public void AddVirtualChild(BaseItem child) { - if (child == null) - { - throw new ArgumentNullException(nameof(child)); - } + ArgumentNullException.ThrowIfNull(child); _virtualChildren.Add(child); } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 5cee6ce40..41fce67fa 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1101,10 +1101,7 @@ namespace MediaBrowser.Controller.Entities private MediaSourceInfo GetVersionInfo(bool enablePathSubstitution, BaseItem item, MediaSourceType type) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); var protocol = item.PathProtocol; @@ -1544,10 +1541,7 @@ namespace MediaBrowser.Controller.Entities /// <exception cref="ArgumentNullException">If user is null.</exception> public bool IsParentalAllowed(User user) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); if (!IsVisibleViaTags(user)) { @@ -1667,10 +1661,7 @@ namespace MediaBrowser.Controller.Entities /// <exception cref="ArgumentNullException"><paramref name="user" /> is <c>null</c>.</exception> public virtual bool IsVisible(User user) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); return IsParentalAllowed(user); } @@ -1842,10 +1833,7 @@ namespace MediaBrowser.Controller.Entities DateTime? datePlayed, bool resetPosition) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); var data = UserDataManager.GetUserData(user, this); @@ -1876,10 +1864,7 @@ namespace MediaBrowser.Controller.Entities /// <exception cref="ArgumentNullException">Throws if user is null.</exception> public virtual void MarkUnplayed(User user) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); var data = UserDataManager.GetUserData(user, this); @@ -2110,10 +2095,7 @@ namespace MediaBrowser.Controller.Entities /// <returns>Image index.</returns> public int GetImageIndex(ItemImageInfo image) { - if (image == null) - { - throw new ArgumentNullException(nameof(image)); - } + ArgumentNullException.ThrowIfNull(image); if (image.Type == ImageType.Chapter) { @@ -2320,10 +2302,7 @@ namespace MediaBrowser.Controller.Entities public virtual bool IsUnplayed(User user) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); var userdata = UserDataManager.GetUserData(user, this); @@ -2616,7 +2595,8 @@ namespace MediaBrowser.Controller.Entities return ExtraIds .Select(LibraryManager.GetItemById) .Where(i => i != null) - .Where(i => i.ExtraType.HasValue && extraTypes.Contains(i.ExtraType.Value)); + .Where(i => i.ExtraType.HasValue && extraTypes.Contains(i.ExtraType.Value)) + .OrderBy(i => i.SortName); } public virtual long GetRunTimeTicksForPlayState() diff --git a/MediaBrowser.Controller/Entities/BaseItemExtensions.cs b/MediaBrowser.Controller/Entities/BaseItemExtensions.cs index e0583e630..948eb4375 100644 --- a/MediaBrowser.Controller/Entities/BaseItemExtensions.cs +++ b/MediaBrowser.Controller/Entities/BaseItemExtensions.cs @@ -71,15 +71,9 @@ namespace MediaBrowser.Controller.Entities where T : BaseItem where TU : BaseItem { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(source); - if (dest == null) - { - throw new ArgumentNullException(nameof(dest)); - } + ArgumentNullException.ThrowIfNull(dest); var destProps = typeof(TU).GetProperties().Where(x => x.CanWrite).ToList(); diff --git a/MediaBrowser.Controller/Entities/Extensions.cs b/MediaBrowser.Controller/Entities/Extensions.cs index 14534aa50..1acb92fdc 100644 --- a/MediaBrowser.Controller/Entities/Extensions.cs +++ b/MediaBrowser.Controller/Entities/Extensions.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Controller.Entities /// <param name="url">Trailer URL.</param> public static void AddTrailerUrl(this BaseItem item, string url) { - ArgumentNullException.ThrowIfNull(url, nameof(url)); + ArgumentNullException.ThrowIfNull(url); if (url.Length == 0) { diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 1860da4c7..808f91810 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -892,29 +892,7 @@ namespace MediaBrowser.Controller.Entities private static BaseItem[] SortItemsByRequest(InternalItemsQuery query, IReadOnlyList<BaseItem> items) { - var ids = query.ItemIds; - int size = items.Count; - - // ids can potentially contain non-unique guids, but query result cannot, - // so we include only first occurrence of each guid - var positions = new Dictionary<Guid, int>(size); - int index = 0; - for (int i = 0; i < ids.Length; i++) - { - if (positions.TryAdd(ids[i], index)) - { - index++; - } - } - - var newItems = new BaseItem[size]; - for (int i = 0; i < size; i++) - { - var item = items[i]; - newItems[positions[item.Id]] = item; - } - - return newItems; + return items.OrderBy(i => Array.IndexOf(query.ItemIds, i.Id)).ToArray(); } public QueryResult<BaseItem> GetItems(InternalItemsQuery query) @@ -1045,10 +1023,7 @@ namespace MediaBrowser.Controller.Entities IServerConfigurationManager configurationManager, ICollectionManager collectionManager) { - if (items == null) - { - throw new ArgumentNullException(nameof(items)); - } + ArgumentNullException.ThrowIfNull(items); if (CollapseBoxSetItems(query, queryParent, user, configurationManager)) { @@ -1295,20 +1270,14 @@ namespace MediaBrowser.Controller.Entities public List<BaseItem> GetChildren(User user, bool includeLinkedChildren) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); return GetChildren(user, includeLinkedChildren, null); } public virtual List<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); // the true root should return our users root folder children if (IsPhysicalRoot) @@ -1389,10 +1358,7 @@ namespace MediaBrowser.Controller.Entities public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); var result = new Dictionary<Guid, BaseItem>(); diff --git a/MediaBrowser.Controller/Entities/PeopleHelper.cs b/MediaBrowser.Controller/Entities/PeopleHelper.cs index 687ce1ec8..8571bfcea 100644 --- a/MediaBrowser.Controller/Entities/PeopleHelper.cs +++ b/MediaBrowser.Controller/Entities/PeopleHelper.cs @@ -11,10 +11,7 @@ namespace MediaBrowser.Controller.Entities { public static void AddPerson(List<PersonInfo> people, PersonInfo person) { - if (person == null) - { - throw new ArgumentNullException(nameof(person)); - } + ArgumentNullException.ThrowIfNull(person); if (string.IsNullOrEmpty(person.Name)) { diff --git a/MediaBrowser.Controller/IO/FileData.cs b/MediaBrowser.Controller/IO/FileData.cs index 2429ac42d..71feae536 100644 --- a/MediaBrowser.Controller/IO/FileData.cs +++ b/MediaBrowser.Controller/IO/FileData.cs @@ -40,10 +40,7 @@ namespace MediaBrowser.Controller.IO throw new ArgumentNullException(nameof(path)); } - if (args == null) - { - throw new ArgumentNullException(nameof(args)); - } + ArgumentNullException.ThrowIfNull(args); var entries = directoryService.GetFileSystemEntries(path); diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 17e410fe1..d0362b128 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -256,6 +256,21 @@ namespace MediaBrowser.Controller.MediaEncoding return string.Empty; } + /// <summary> + /// Gets the referer param. + /// </summary> + /// <param name="state">The state.</param> + /// <returns>System.String.</returns> + public string GetRefererParam(EncodingJobInfo state) + { + if (state.RemoteHttpHeaders.TryGetValue("Referer", out string referer)) + { + return "-referer \"" + referer + "\""; + } + + return string.Empty; + } + public static string GetInputFormat(string container) { if (string.IsNullOrEmpty(container)) @@ -4976,13 +4991,13 @@ namespace MediaBrowser.Controller.MediaEncoding // The default value of -probesize is more than enough, so leave it as is. var ffmpegAnalyzeDuration = _config.GetFFmpegAnalyzeDuration() ?? string.Empty; - if (!string.IsNullOrEmpty(ffmpegAnalyzeDuration)) + if (state.MediaSource.AnalyzeDurationMs > 0) { - analyzeDurationArgument = "-analyzeduration " + ffmpegAnalyzeDuration; + analyzeDurationArgument = "-analyzeduration " + (state.MediaSource.AnalyzeDurationMs.Value * 1000).ToString(CultureInfo.InvariantCulture); } - else if (state.MediaSource.AnalyzeDurationMs.HasValue) + else if (!string.IsNullOrEmpty(ffmpegAnalyzeDuration)) { - analyzeDurationArgument = "-analyzeduration " + (state.MediaSource.AnalyzeDurationMs.Value * 1000).ToString(CultureInfo.InvariantCulture); + analyzeDurationArgument = "-analyzeduration " + ffmpegAnalyzeDuration; } if (!string.IsNullOrEmpty(analyzeDurationArgument)) @@ -5001,6 +5016,15 @@ namespace MediaBrowser.Controller.MediaEncoding inputModifier = inputModifier.Trim(); + var refererParam = GetRefererParam(state); + + if (!string.IsNullOrEmpty(refererParam)) + { + inputModifier += " " + refererParam; + } + + inputModifier = inputModifier.Trim(); + inputModifier += " " + GetFastSeekCommandLineParameter(state, encodingOptions, segmentContainer); inputModifier = inputModifier.Trim(); @@ -5081,15 +5105,9 @@ namespace MediaBrowser.Controller.MediaEncoding MediaSourceInfo mediaSource, string requestedUrl) { - if (state == null) - { - throw new ArgumentNullException(nameof(state)); - } + ArgumentNullException.ThrowIfNull(state); - if (mediaSource == null) - { - throw new ArgumentNullException(nameof(mediaSource)); - } + ArgumentNullException.ThrowIfNull(mediaSource); var path = mediaSource.Path; var protocol = mediaSource.Protocol; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index 491662861..c9625cf1d 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Text.Json.Serialization; using Jellyfin.Data.Entities; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Drawing; diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index dae30cd8b..69d0bf45c 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -38,6 +38,12 @@ namespace MediaBrowser.Controller.MediaEncoding Version EncoderVersion { get; } /// <summary> + /// Whether p key pausing is supported. + /// </summary> + /// <value><c>true</c> if p key pausing is supported, <c>false</c> otherwise.</value> + bool IsPkeyPauseSupported { get; } + + /// <summary> /// Gets a value indicating whether the configured Vaapi device is from AMD(radeonsi/r600 Mesa driver). /// </summary> /// <value><c>true</c> if the Vaapi device is an AMD(radeonsi/r600 Mesa driver) GPU, <c>false</c> otherwise.</value> diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs index eadc09fd4..647de5003 100644 --- a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs +++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs @@ -38,10 +38,7 @@ namespace MediaBrowser.Controller.Net protected BasePeriodicWebSocketListener(ILogger<BasePeriodicWebSocketListener<TReturnDataType, TStateType>> logger) { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } + ArgumentNullException.ThrowIfNull(logger); Logger = logger; } @@ -77,10 +74,7 @@ namespace MediaBrowser.Controller.Net /// <returns>Task.</returns> public Task ProcessMessageAsync(WebSocketMessageInfo message) { - if (message == null) - { - throw new ArgumentNullException(nameof(message)); - } + ArgumentNullException.ThrowIfNull(message); if (message.MessageType == StartType) { diff --git a/MediaBrowser.Controller/Net/ISessionContext.cs b/MediaBrowser.Controller/Net/ISessionContext.cs deleted file mode 100644 index b48181b3f..000000000 --- a/MediaBrowser.Controller/Net/ISessionContext.cs +++ /dev/null @@ -1,20 +0,0 @@ -#pragma warning disable CS1591 - -using System.Threading.Tasks; -using Jellyfin.Data.Entities; -using MediaBrowser.Controller.Session; -using Microsoft.AspNetCore.Http; - -namespace MediaBrowser.Controller.Net -{ - public interface ISessionContext - { - Task<SessionInfo> GetSession(object requestContext); - - Task<User?> GetUser(object requestContext); - - Task<SessionInfo> GetSession(HttpContext requestContext); - - Task<User?> GetUser(HttpContext requestContext); - } -} diff --git a/MediaBrowser.Controller/Net/IWebSocketConnection.cs b/MediaBrowser.Controller/Net/IWebSocketConnection.cs index 43c7ce370..4f2492b89 100644 --- a/MediaBrowser.Controller/Net/IWebSocketConnection.cs +++ b/MediaBrowser.Controller/Net/IWebSocketConnection.cs @@ -6,7 +6,6 @@ using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.Net; -using Microsoft.AspNetCore.Http; namespace MediaBrowser.Controller.Net { diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index 828ecb2c5..7ae9ff746 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; using System.Text.Json.Serialization; diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 777fe6774..a9e1b4a51 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -53,10 +53,7 @@ namespace MediaBrowser.LocalMetadata.Parsers /// <exception cref="ArgumentNullException">Item is null.</exception> public void Fetch(MetadataResult<T> item, string metadataFile, CancellationToken cancellationToken) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); if (string.IsNullOrEmpty(metadataFile)) { diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 142571e8f..22abf93ac 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -52,10 +52,7 @@ namespace MediaBrowser.MediaEncoding.Attachments /// <inheritdoc /> public async Task<(MediaAttachment Attachment, Stream Stream)> GetAttachment(BaseItem item, string mediaSourceId, int attachmentStreamIndex, CancellationToken cancellationToken) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); if (string.IsNullOrWhiteSpace(mediaSourceId)) { diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index d378c6e13..9b4b1db94 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -153,7 +153,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string output; try { - output = GetProcessOutput(_encoderPath, "-version", false); + output = GetProcessOutput(_encoderPath, "-version", false, null); } catch (Exception ex) { @@ -234,7 +234,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string output; try { - output = GetProcessOutput(_encoderPath, "-version", false); + output = GetProcessOutput(_encoderPath, "-version", false, null); } catch (Exception ex) { @@ -341,7 +341,7 @@ namespace MediaBrowser.MediaEncoding.Encoder try { - var output = GetProcessOutput(_encoderPath, "-v verbose -hide_banner -init_hw_device vaapi=va:" + renderNodePath, true); + var output = GetProcessOutput(_encoderPath, "-v verbose -hide_banner -init_hw_device vaapi=va:" + renderNodePath, true, null); return output.Contains(driverName, StringComparison.Ordinal); } catch (Exception ex) @@ -356,7 +356,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string? output = null; try { - output = GetProcessOutput(_encoderPath, "-hwaccels", false); + output = GetProcessOutput(_encoderPath, "-hwaccels", false, null); } catch (Exception ex) { @@ -384,7 +384,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string output; try { - output = GetProcessOutput(_encoderPath, "-h filter=" + filter, false); + output = GetProcessOutput(_encoderPath, "-h filter=" + filter, false, null); } catch (Exception ex) { @@ -402,13 +402,34 @@ namespace MediaBrowser.MediaEncoding.Encoder return false; } + public bool CheckSupportedRuntimeKey(string keyDesc) + { + if (string.IsNullOrEmpty(keyDesc)) + { + return false; + } + + string output; + try + { + output = GetProcessOutput(_encoderPath, "-hide_banner -f lavfi -i nullsrc=s=1x1:d=500 -f null -", true, "?"); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error checking supported runtime key"); + return false; + } + + return output.Contains(keyDesc, StringComparison.Ordinal); + } + private IEnumerable<string> GetCodecs(Codec codec) { string codecstr = codec == Codec.Encoder ? "encoders" : "decoders"; string output; try { - output = GetProcessOutput(_encoderPath, "-" + codecstr, false); + output = GetProcessOutput(_encoderPath, "-" + codecstr, false, null); } catch (Exception ex) { @@ -439,7 +460,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string output; try { - output = GetProcessOutput(_encoderPath, "-filters", false); + output = GetProcessOutput(_encoderPath, "-filters", false, null); } catch (Exception ex) { @@ -477,7 +498,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return dict; } - private string GetProcessOutput(string path, string arguments, bool readStdErr) + private string GetProcessOutput(string path, string arguments, bool readStdErr, string? testKey) { using (var process = new Process() { @@ -487,6 +508,7 @@ namespace MediaBrowser.MediaEncoding.Encoder UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false, + RedirectStandardInput = !string.IsNullOrEmpty(testKey), RedirectStandardOutput = true, RedirectStandardError = true } @@ -496,6 +518,11 @@ namespace MediaBrowser.MediaEncoding.Encoder process.Start(); + if (!string.IsNullOrEmpty(testKey)) + { + process.StandardInput.Write(testKey); + } + return readStdErr ? process.StandardError.ReadToEnd() : process.StandardOutput.ReadToEnd(); } } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 7f301a9d8..757a01715 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -67,6 +67,8 @@ namespace MediaBrowser.MediaEncoding.Encoder private List<string> _filters = new List<string>(); private IDictionary<int, bool> _filtersWithOption = new Dictionary<int, bool>(); + private bool _isPkeyPauseSupported = false; + private bool _isVaapiDeviceAmd = false; private bool _isVaapiDeviceInteliHD = false; private bool _isVaapiDeviceInteli965 = false; @@ -100,6 +102,8 @@ namespace MediaBrowser.MediaEncoding.Encoder public Version EncoderVersion => _ffmpegVersion; + public bool IsPkeyPauseSupported => _isPkeyPauseSupported; + public bool IsVaapiDeviceAmd => _isVaapiDeviceAmd; public bool IsVaapiDeviceInteliHD => _isVaapiDeviceInteliHD; @@ -154,6 +158,8 @@ namespace MediaBrowser.MediaEncoding.Encoder _threads = EncodingHelper.GetNumberOfThreads(null, options, null); + _isPkeyPauseSupported = validator.CheckSupportedRuntimeKey("p pause transcoding"); + // Check the Vaapi device vendor if (OperatingSystem.IsLinux() && SupportsHwaccel("vaapi") @@ -376,15 +382,15 @@ namespace MediaBrowser.MediaEncoding.Encoder string analyzeDuration = string.Empty; string ffmpegAnalyzeDuration = _config.GetFFmpegAnalyzeDuration() ?? string.Empty; - if (!string.IsNullOrEmpty(ffmpegAnalyzeDuration)) - { - analyzeDuration = "-analyzeduration " + ffmpegAnalyzeDuration; - } - else if (request.MediaSource.AnalyzeDurationMs > 0) + if (request.MediaSource.AnalyzeDurationMs > 0) { analyzeDuration = "-analyzeduration " + (request.MediaSource.AnalyzeDurationMs * 1000).ToString(); } + else if (!string.IsNullOrEmpty(ffmpegAnalyzeDuration)) + { + analyzeDuration = "-analyzeduration " + ffmpegAnalyzeDuration; + } var forceEnableLogging = request.MediaSource.Protocol != MediaProtocol.File; diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index a9e753726..205e84153 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -15,10 +15,7 @@ namespace MediaBrowser.MediaEncoding.Probing /// <param name="result">The result.</param> public static void NormalizeFFProbeResult(InternalMediaInfoResult result) { - if (result == null) - { - throw new ArgumentNullException(nameof(result)); - } + ArgumentNullException.ThrowIfNull(result); if (result.Format?.Tags != null) { diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfoSideData.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfoSideData.cs index 095757bef..5dbc438e4 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfoSideData.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfoSideData.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.Text.Json.Serialization; namespace MediaBrowser.MediaEncoding.Probing diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 6cae7f558..417f1520f 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -730,6 +730,7 @@ namespace MediaBrowser.MediaEncoding.Probing stream.LocalizedDefault = _localization.GetLocalizedString("Default"); stream.LocalizedForced = _localization.GetLocalizedString("Forced"); stream.LocalizedExternal = _localization.GetLocalizedString("External"); + stream.LocalizedHearingImpaired = _localization.GetLocalizedString("HearingImpaired"); if (string.IsNullOrEmpty(stream.Title)) { @@ -875,8 +876,13 @@ namespace MediaBrowser.MediaEncoding.Probing } } } + else if (string.Equals(streamInfo.CodecType, "data", StringComparison.OrdinalIgnoreCase)) + { + stream.Type = MediaStreamType.Data; + } else { + _logger.LogError("Codec Type {CodecType} unknown. The stream (index: {Index}) will be ignored. Warning: Subsequential streams will have a wrong stream specifier!", streamInfo.CodecType, streamInfo.Index); return null; } @@ -950,6 +956,11 @@ namespace MediaBrowser.MediaEncoding.Probing { stream.IsForced = true; } + + if (disposition.GetValueOrDefault("hearing_impaired") == 1) + { + stream.IsHearingImpaired = true; + } } NormalizeStreamTitle(stream); diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs index eb8ff9624..0d4489517 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs @@ -3,12 +3,10 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; -using System.Reflection; using Jellyfin.Extensions; using MediaBrowser.Model.MediaInfo; using Microsoft.Extensions.Logging; using Nikse.SubtitleEdit.Core.Common; -using Nikse.SubtitleEdit.Core.SubtitleFormats; using SubtitleFormat = Nikse.SubtitleEdit.Core.SubtitleFormats.SubtitleFormat; namespace MediaBrowser.MediaEncoding.Subtitles diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 115f085ff..9185faf67 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -120,10 +120,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles async Task<Stream> ISubtitleEncoder.GetSubtitles(BaseItem item, string mediaSourceId, int subtitleStreamIndex, string outputFormat, long startTimeTicks, long endTimeTicks, bool preserveOriginalTimestamps, CancellationToken cancellationToken) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); if (string.IsNullOrWhiteSpace(mediaSourceId)) { diff --git a/MediaBrowser.Model/Branding/BrandingOptions.cs b/MediaBrowser.Model/Branding/BrandingOptions.cs index a0adb56ef..695267d46 100644 --- a/MediaBrowser.Model/Branding/BrandingOptions.cs +++ b/MediaBrowser.Model/Branding/BrandingOptions.cs @@ -1,5 +1,4 @@ using System.Text.Json.Serialization; -using System.Xml.Serialization; namespace MediaBrowser.Model.Branding; diff --git a/MediaBrowser.Model/Configuration/EmbeddedSubtitleOptions.cs b/MediaBrowser.Model/Configuration/EmbeddedSubtitleOptions.cs index 42f07dbff..98e0f84e3 100644 --- a/MediaBrowser.Model/Configuration/EmbeddedSubtitleOptions.cs +++ b/MediaBrowser.Model/Configuration/EmbeddedSubtitleOptions.cs @@ -5,7 +5,6 @@ namespace MediaBrowser.Model.Configuration /// </summary> public enum EmbeddedSubtitleOptions { - /// <summary> /// Allow all embedded subs. /// </summary> @@ -26,5 +25,4 @@ namespace MediaBrowser.Model.Configuration /// </summary> AllowNone = 3, } - } diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index 73ebfba70..f4cd2f006 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -1,5 +1,3 @@ -using System; - #nullable disable #pragma warning disable CS1591 diff --git a/MediaBrowser.Model/Cryptography/PasswordHash.cs b/MediaBrowser.Model/Cryptography/PasswordHash.cs index eec541041..32a34d23c 100644 --- a/MediaBrowser.Model/Cryptography/PasswordHash.cs +++ b/MediaBrowser.Model/Cryptography/PasswordHash.cs @@ -29,10 +29,7 @@ namespace MediaBrowser.Model.Cryptography public PasswordHash(string id, byte[] hash, byte[] salt, Dictionary<string, string> parameters) { - if (id == null) - { - throw new ArgumentNullException(nameof(id)); - } + ArgumentNullException.ThrowIfNull(id); if (id.Length == 0) { diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs index c32c1c108..1a9576361 100644 --- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs +++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs @@ -8,7 +8,7 @@ using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Model.Dlna { - public class ContentFeatureBuilder + public static class ContentFeatureBuilder { public static string BuildImageHeader( DeviceProfile profile, diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index fdb9fd5d5..b121a2905 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -565,10 +565,7 @@ namespace MediaBrowser.Model.Dlna private StreamInfo BuildVideoItem(MediaSourceInfo item, VideoOptions options) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); StreamInfo playlistItem = new StreamInfo { diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 0c66351c7..5cfa2e7e3 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Linq; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 90a60cf47..344ebaf80 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -221,6 +221,8 @@ namespace MediaBrowser.Model.Entities public string LocalizedExternal { get; set; } + public string LocalizedHearingImpaired { get; set; } + public string DisplayTitle { get @@ -345,6 +347,11 @@ namespace MediaBrowser.Model.Entities attributes.Add(string.IsNullOrEmpty(LocalizedUndefined) ? "Und" : LocalizedUndefined); } + if (IsHearingImpaired) + { + attributes.Add(string.IsNullOrEmpty(LocalizedHearingImpaired) ? "Hearing Impaired" : LocalizedHearingImpaired); + } + if (IsDefault) { attributes.Add(string.IsNullOrEmpty(LocalizedDefault) ? "Default" : LocalizedDefault); @@ -454,6 +461,12 @@ namespace MediaBrowser.Model.Entities public bool IsForced { get; set; } /// <summary> + /// Gets or sets a value indicating whether this instance is for the hearing impaired. + /// </summary> + /// <value><c>true</c> if this instance is for the hearing impaired; otherwise, <c>false</c>.</value> + public bool IsHearingImpaired { get; set; } + + /// <summary> /// Gets or sets the height. /// </summary> /// <value>The height.</value> diff --git a/MediaBrowser.Model/Entities/MediaStreamType.cs b/MediaBrowser.Model/Entities/MediaStreamType.cs index e09aaf6d0..83751a6a7 100644 --- a/MediaBrowser.Model/Entities/MediaStreamType.cs +++ b/MediaBrowser.Model/Entities/MediaStreamType.cs @@ -23,6 +23,11 @@ namespace MediaBrowser.Model.Entities /// <summary> /// The embedded image. /// </summary> - EmbeddedImage + EmbeddedImage, + + /// <summary> + /// The data. + /// </summary> + Data } } diff --git a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs index 62a2f3ce8..d3b8400f3 100644 --- a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs +++ b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs @@ -28,10 +28,7 @@ namespace MediaBrowser.Model.Entities /// <returns><c>true</c> if a provider id with the given name was found; otherwise <c>false</c>.</returns> public static bool HasProviderId(this IHasProviderIds instance, string name) { - if (instance == null) - { - throw new ArgumentNullException(nameof(instance)); - } + ArgumentNullException.ThrowIfNull(instance); return instance.TryGetProviderId(name, out _); } @@ -56,10 +53,7 @@ namespace MediaBrowser.Model.Entities /// <returns><c>true</c> if a provider id with the given name was found; otherwise <c>false</c>.</returns> public static bool TryGetProviderId(this IHasProviderIds instance, string name, [NotNullWhen(true)] out string? id) { - if (instance == null) - { - throw new ArgumentNullException(nameof(instance)); - } + ArgumentNullException.ThrowIfNull(instance); if (instance.ProviderIds == null) { @@ -121,10 +115,7 @@ namespace MediaBrowser.Model.Entities /// <param name="value">The value.</param> public static void SetProviderId(this IHasProviderIds instance, string name, string? value) { - if (instance == null) - { - throw new ArgumentNullException(nameof(instance)); - } + ArgumentNullException.ThrowIfNull(instance); // If it's null remove the key from the dictionary if (string.IsNullOrEmpty(value)) diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 4f511f996..ad2ff1ba2 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -34,13 +34,13 @@ <ItemGroup> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" /> - <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.1" /> + <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.2" /> <PackageReference Include="MimeTypes" Version="2.4.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> <PackageReference Include="System.Globalization" Version="4.3.0" /> - <PackageReference Include="System.Text.Json" Version="6.0.5" /> + <PackageReference Include="System.Text.Json" Version="6.0.6" /> </ItemGroup> <ItemGroup> diff --git a/MediaBrowser.Model/Search/SearchHint.cs b/MediaBrowser.Model/Search/SearchHint.cs index 4696c3797..3fa7f3d56 100644 --- a/MediaBrowser.Model/Search/SearchHint.cs +++ b/MediaBrowser.Model/Search/SearchHint.cs @@ -100,7 +100,7 @@ namespace MediaBrowser.Model.Search public BaseItemKind Type { get; set; } /// <summary> - /// Gets a value indicating whether this instance is folder. + /// Gets or sets a value indicating whether this instance is folder. /// </summary> /// <value><c>true</c> if this instance is folder; otherwise, <c>false</c>.</value> public bool? IsFolder { get; set; } diff --git a/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs b/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs index d55cc4491..1bc2edfd8 100644 --- a/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs +++ b/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs @@ -120,6 +120,7 @@ namespace MediaBrowser.Providers.MediaInfo mediaStream.Index = startIndex++; mediaStream.IsDefault = pathInfo.IsDefault || mediaStream.IsDefault; mediaStream.IsForced = pathInfo.IsForced || mediaStream.IsForced; + mediaStream.IsHearingImpaired = pathInfo.IsHearingImpaired || mediaStream.IsHearingImpaired; mediaStreams.Add(MergeMetadata(mediaStream, pathInfo)); } @@ -22,7 +22,7 @@ <a href="https://hub.docker.com/r/jellyfin/jellyfin"> <img alt="Docker Pull Count" src="https://img.shields.io/docker/pulls/jellyfin/jellyfin.svg"/> </a> -</br> +<br/> <a href="https://opencollective.com/jellyfin"> <img alt="Donate" src="https://img.shields.io/opencollective/all/jellyfin.svg?label=backers"/> </a> @@ -36,13 +36,10 @@ <img alt="Join our Subreddit" src="https://img.shields.io/badge/reddit-r%2Fjellyfin-%23FF5700.svg"/> </a> <a href="https://github.com/jellyfin/jellyfin/releases.atom"> -<img alt="Release RSS Feed"" src="https://img.shields.io/badge/rss-releases-ffa500?logo=rss" /> +<img alt="Release RSS Feed" src="https://img.shields.io/badge/rss-releases-ffa500?logo=rss" /> </a> <a href="https://github.com/jellyfin/jellyfin/commits/master.atom"> -<img alt="Master Commits RSS Feed"" src="https://img.shields.io/badge/rss-commits-ffa500?logo=rss" /> -</a> -<a href="https://lgtm.com/projects/g/jellyfin/jellyfin/alerts/"> -<img alt="Total LGTM alerts" src="https://img.shields.io/lgtm/alerts/g/jellyfin/jellyfin.svg?logo=lgtm&logoWidth=18"/> +<img alt="Master Commits RSS Feed" src="https://img.shields.io/badge/rss-commits-ffa500?logo=rss" /> </a> </p> diff --git a/debian/jellyfin.service b/debian/jellyfin.service index 2f97c4654..1150924a0 100644 --- a/debian/jellyfin.service +++ b/debian/jellyfin.service @@ -8,7 +8,7 @@ EnvironmentFile = /etc/default/jellyfin User = jellyfin Group = jellyfin WorkingDirectory = /var/lib/jellyfin -ExecStart = /usr/bin/jellyfin ${JELLYFIN_WEB_OPT} ${JELLYFIN_RESTART_OPT} ${JELLYFIN_FFMPEG_OPT} ${JELLYFIN_SERVICE_OPT} ${JELLYFIN_NOWEBAPP_OPT} ${JELLYFIN_ADDITIONAL_OPTS} +ExecStart = /usr/bin/jellyfin $JELLYFIN_WEB_OPT $JELLYFIN_RESTART_OPT $JELLYFIN_FFMPEG_OPT $JELLYFIN_SERVICE_OPT $JELLYFIN_NOWEBAPP_OPT $JELLYFIN_ADDITIONAL_OPTS Restart = on-failure TimeoutSec = 15 SuccessExitStatus=0 143 diff --git a/deployment/Dockerfile.centos.amd64 b/deployment/Dockerfile.centos.amd64 index 81d75c1aa..0bae42bc8 100644 --- a/deployment/Dockerfile.centos.amd64 +++ b/deployment/Dockerfile.centos.amd64 @@ -13,7 +13,7 @@ RUN yum update -yq \ && yum install -yq @buildsys-build rpmdevtools yum-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel git wget # Install DotNET SDK -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/cd0d0a4d-2a6a-4d0d-b42e-dfd3b880e222/008a93f83aba6d1acf75ded3d2cfba24/dotnet-sdk-6.0.400-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/8159607a-e686-4ead-ac99-b4c97290a5fd/ec6070b1b2cc0651ebe57cf1bd411315/dotnet-sdk-6.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.debian.amd64 b/deployment/Dockerfile.debian.amd64 index daba0eb7d..c7bb5f768 100644 --- a/deployment/Dockerfile.debian.amd64 +++ b/deployment/Dockerfile.debian.amd64 @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts build-essential mmv \ + debhelper gnupg devscripts build-essential mmv \ libcurl4-openssl-dev libfontconfig1-dev libfreetype6-dev libssl-dev \ libssl1.1 liblttng-ust0 diff --git a/deployment/Dockerfile.debian.arm64 b/deployment/Dockerfile.debian.arm64 index db4e7f817..a0ca9b3f3 100644 --- a/deployment/Dockerfile.debian.arm64 +++ b/deployment/Dockerfile.debian.arm64 @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts build-essential mmv + debhelper gnupg devscripts build-essential mmv # Prepare the cross-toolchain RUN dpkg --add-architecture arm64 \ diff --git a/deployment/Dockerfile.debian.armhf b/deployment/Dockerfile.debian.armhf index 9b008e7fb..42a55ebfe 100644 --- a/deployment/Dockerfile.debian.armhf +++ b/deployment/Dockerfile.debian.armhf @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts build-essential mmv + debhelper gnupg devscripts build-essential mmv # Prepare the cross-toolchain RUN dpkg --add-architecture armhf \ diff --git a/deployment/Dockerfile.fedora.amd64 b/deployment/Dockerfile.fedora.amd64 index 4139ed96d..20aa777b6 100644 --- a/deployment/Dockerfile.fedora.amd64 +++ b/deployment/Dockerfile.fedora.amd64 @@ -12,7 +12,7 @@ RUN dnf update -yq \ && dnf install -yq @buildsys-build rpmdevtools git dnf-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel systemd wget make # Install DotNET SDK -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/cd0d0a4d-2a6a-4d0d-b42e-dfd3b880e222/008a93f83aba6d1acf75ded3d2cfba24/dotnet-sdk-6.0.400-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/8159607a-e686-4ead-ac99-b4c97290a5fd/ec6070b1b2cc0651ebe57cf1bd411315/dotnet-sdk-6.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.linux.amd64 b/deployment/Dockerfile.linux.amd64 index 2c7e41cac..14b580d11 100644 --- a/deployment/Dockerfile.linux.amd64 +++ b/deployment/Dockerfile.linux.amd64 @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts unzip \ + debhelper gnupg devscripts unzip \ mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 diff --git a/deployment/Dockerfile.linux.amd64-musl b/deployment/Dockerfile.linux.amd64-musl index e903cf1d3..672c3f269 100644 --- a/deployment/Dockerfile.linux.amd64-musl +++ b/deployment/Dockerfile.linux.amd64-musl @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts unzip \ + debhelper gnupg devscripts unzip \ mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 diff --git a/deployment/Dockerfile.linux.arm64 b/deployment/Dockerfile.linux.arm64 index 0dd3c5e4e..f2a178be3 100644 --- a/deployment/Dockerfile.linux.arm64 +++ b/deployment/Dockerfile.linux.arm64 @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts unzip \ + debhelper gnupg devscripts unzip \ mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 diff --git a/deployment/Dockerfile.linux.armhf b/deployment/Dockerfile.linux.armhf index 16a8218e1..025716f45 100644 --- a/deployment/Dockerfile.linux.armhf +++ b/deployment/Dockerfile.linux.armhf @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts unzip \ + debhelper gnupg devscripts unzip \ mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 diff --git a/deployment/Dockerfile.macos b/deployment/Dockerfile.macos index 699ab2d40..f63dc2906 100644 --- a/deployment/Dockerfile.macos +++ b/deployment/Dockerfile.macos @@ -12,7 +12,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts \ + debhelper gnupg devscripts \ mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 diff --git a/deployment/Dockerfile.portable b/deployment/Dockerfile.portable index b567d7bce..e48e2d41a 100644 --- a/deployment/Dockerfile.portable +++ b/deployment/Dockerfile.portable @@ -11,7 +11,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts \ + debhelper gnupg devscripts \ mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 diff --git a/deployment/Dockerfile.ubuntu.amd64 b/deployment/Dockerfile.ubuntu.amd64 index 313a3e5cb..ccc0f76cd 100644 --- a/deployment/Dockerfile.ubuntu.amd64 +++ b/deployment/Dockerfile.ubuntu.amd64 @@ -12,12 +12,12 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg wget ca-certificates devscripts \ + debhelper gnupg wget ca-certificates devscripts \ mmv build-essential libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/cd0d0a4d-2a6a-4d0d-b42e-dfd3b880e222/008a93f83aba6d1acf75ded3d2cfba24/dotnet-sdk-6.0.400-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/8159607a-e686-4ead-ac99-b4c97290a5fd/ec6070b1b2cc0651ebe57cf1bd411315/dotnet-sdk-6.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.arm64 b/deployment/Dockerfile.ubuntu.arm64 index 693ee7c27..893180974 100644 --- a/deployment/Dockerfile.ubuntu.arm64 +++ b/deployment/Dockerfile.ubuntu.arm64 @@ -12,11 +12,11 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg wget ca-certificates devscripts \ + debhelper gnupg wget ca-certificates devscripts \ mmv build-essential lsb-release # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/cd0d0a4d-2a6a-4d0d-b42e-dfd3b880e222/008a93f83aba6d1acf75ded3d2cfba24/dotnet-sdk-6.0.400-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/8159607a-e686-4ead-ac99-b4c97290a5fd/ec6070b1b2cc0651ebe57cf1bd411315/dotnet-sdk-6.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.armhf b/deployment/Dockerfile.ubuntu.armhf index e7765a5b2..bf1edf777 100644 --- a/deployment/Dockerfile.ubuntu.armhf +++ b/deployment/Dockerfile.ubuntu.armhf @@ -12,11 +12,11 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg wget ca-certificates devscripts \ + debhelper gnupg wget ca-certificates devscripts \ mmv build-essential lsb-release # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/cd0d0a4d-2a6a-4d0d-b42e-dfd3b880e222/008a93f83aba6d1acf75ded3d2cfba24/dotnet-sdk-6.0.400-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/8159607a-e686-4ead-ac99-b4c97290a5fd/ec6070b1b2cc0651ebe57cf1bd411315/dotnet-sdk-6.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.windows.amd64 b/deployment/Dockerfile.windows.amd64 index b9543a7c9..655300d47 100644 --- a/deployment/Dockerfile.windows.amd64 +++ b/deployment/Dockerfile.windows.amd64 @@ -11,7 +11,7 @@ ENV IS_DOCKER=YES # Prepare Debian build environment RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ - apt-transport-https debhelper gnupg devscripts unzip \ + debhelper gnupg devscripts unzip \ mmv libcurl4-openssl-dev libfontconfig1-dev \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 zip diff --git a/fedora/jellyfin.service b/fedora/jellyfin.service index eb0d64087..2fb9f30e0 100644 --- a/fedora/jellyfin.service +++ b/fedora/jellyfin.service @@ -8,7 +8,7 @@ EnvironmentFile = /etc/sysconfig/jellyfin User = jellyfin Group = jellyfin WorkingDirectory = /var/lib/jellyfin -ExecStart = /usr/bin/jellyfin ${JELLYFIN_WEB_OPT} ${JELLYFIN_RESTART_OPT} ${JELLYFIN_FFMPEG_OPT} ${JELLYFIN_SERVICE_OPT} ${JELLYFIN_NOWEBAPP_OPT} ${JELLYFIN_ADDITIONAL_OPTS} +ExecStart = /usr/bin/jellyfin $JELLYFIN_WEB_OPT $JELLYFIN_RESTART_OPT $JELLYFIN_FFMPEG_OPT $JELLYFIN_SERVICE_OPT $JELLYFIN_NOWEBAPP_OPT $JELLYFIN_ADDITIONAL_OPTS Restart = on-failure TimeoutSec = 15 SuccessExitStatus=0 143 diff --git a/fuzz/Emby.Server.Implementations.Fuzz/Emby.Server.Implementations.Fuzz.csproj b/fuzz/Emby.Server.Implementations.Fuzz/Emby.Server.Implementations.Fuzz.csproj index 6abdb7734..7cd98c29a 100644 --- a/fuzz/Emby.Server.Implementations.Fuzz/Emby.Server.Implementations.Fuzz.csproj +++ b/fuzz/Emby.Server.Implementations.Fuzz/Emby.Server.Implementations.Fuzz.csproj @@ -2,7 +2,7 @@ <PropertyGroup> <OutputType>Exe</OutputType> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> </PropertyGroup> <ItemGroup> diff --git a/fuzz/Emby.Server.Implementations.Fuzz/fuzz.sh b/fuzz/Emby.Server.Implementations.Fuzz/fuzz.sh index 244f73402..37e6bdb76 100755 --- a/fuzz/Emby.Server.Implementations.Fuzz/fuzz.sh +++ b/fuzz/Emby.Server.Implementations.Fuzz/fuzz.sh @@ -8,4 +8,4 @@ cp bin/Emby.Server.Implementations.dll . dotnet build mkdir -p Findings -AFL_SKIP_BIN_CHECK=1 afl-fuzz -i "Testcases/$1" -o "Findings/$1" -t 5000 -m 10240 dotnet bin/Debug/net5.0/Emby.Server.Implementations.Fuzz.dll "$1" +AFL_SKIP_BIN_CHECK=1 afl-fuzz -i "Testcases/$1" -o "Findings/$1" -t 5000 -m 10240 dotnet bin/Debug/net6.0/Emby.Server.Implementations.Fuzz.dll "$1" diff --git a/fuzz/Jellyfin.Server.Fuzz/Jellyfin.Server.Fuzz.csproj b/fuzz/Jellyfin.Server.Fuzz/Jellyfin.Server.Fuzz.csproj index 6fcfbae0e..facd8b7bb 100644 --- a/fuzz/Jellyfin.Server.Fuzz/Jellyfin.Server.Fuzz.csproj +++ b/fuzz/Jellyfin.Server.Fuzz/Jellyfin.Server.Fuzz.csproj @@ -2,7 +2,7 @@ <PropertyGroup> <OutputType>Exe</OutputType> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> </PropertyGroup> <ItemGroup> diff --git a/fuzz/Jellyfin.Server.Fuzz/fuzz.sh b/fuzz/Jellyfin.Server.Fuzz/fuzz.sh index ad81e2c35..303eb2135 100755 --- a/fuzz/Jellyfin.Server.Fuzz/fuzz.sh +++ b/fuzz/Jellyfin.Server.Fuzz/fuzz.sh @@ -8,4 +8,4 @@ cp bin/jellyfin.dll . dotnet build mkdir -p Findings -AFL_SKIP_BIN_CHECK=1 afl-fuzz -i "Testcases/$1" -o "Findings/$1" -t 5000 -m 10240 dotnet bin/Debug/net5.0/Jellyfin.Server.Fuzz.dll "$1" +AFL_SKIP_BIN_CHECK=1 afl-fuzz -i "Testcases/$1" -o "Findings/$1" -t 5000 -m 10240 dotnet bin/Debug/net6.0/Jellyfin.Server.Fuzz.dll "$1" diff --git a/src/Jellyfin.Extensions/EnumerableExtensions.cs b/src/Jellyfin.Extensions/EnumerableExtensions.cs index b5fe93357..a31a57dc6 100644 --- a/src/Jellyfin.Extensions/EnumerableExtensions.cs +++ b/src/Jellyfin.Extensions/EnumerableExtensions.cs @@ -18,10 +18,7 @@ namespace Jellyfin.Extensions /// <exception cref="ArgumentNullException">The source is null.</exception> public static bool Contains(this IEnumerable<string> source, ReadOnlySpan<char> value, StringComparison stringComparison) { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(source); if (source is IList<string> list) { diff --git a/src/Jellyfin.Extensions/StringExtensions.cs b/src/Jellyfin.Extensions/StringExtensions.cs index 59fb038a7..b19be071b 100644 --- a/src/Jellyfin.Extensions/StringExtensions.cs +++ b/src/Jellyfin.Extensions/StringExtensions.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using System.Globalization; using System.Text; using System.Text.RegularExpressions; diff --git a/src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs index 497210f41..083e93de1 100644 --- a/src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs +++ b/src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics.CodeAnalysis; using Jellyfin.MediaEncoding.Keyframes; diff --git a/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj b/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj index 29cdf561f..9585cb60c 100644 --- a/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj +++ b/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj @@ -21,7 +21,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.1" /> + <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.2" /> </ItemGroup> <ItemGroup> diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 97a549943..a20c9690f 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -15,9 +15,9 @@ <PackageReference Include="AutoFixture" Version="4.17.0" /> <PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" /> <PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" /> - <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.8" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.9" /> <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" /> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <PrivateAssets>all</PrivateAssets> diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index 77cdcfada..95fc1d917 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -12,7 +12,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <PrivateAssets>all</PrivateAssets> diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index 1496bc80c..d95747206 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -12,7 +12,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="Moq" Version="4.18.2" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> diff --git a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj index f450936f2..1444d6faf 100644 --- a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj +++ b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj @@ -7,7 +7,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="Moq" Version="4.18.2" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> diff --git a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj index dfe765583..9e3bef881 100644 --- a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj +++ b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj @@ -7,7 +7,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> diff --git a/tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj b/tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj index dae7722c3..83ea1907c 100644 --- a/tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj @@ -7,7 +7,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> diff --git a/tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj index ea4788cb8..84a069424 100644 --- a/tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj @@ -8,7 +8,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index 5914eea47..4cff2143c 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -22,7 +22,7 @@ <PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" /> <PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" /> <PackageReference Include="coverlet.collector" Version="3.1.2" /> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="Moq" Version="4.18.2" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> diff --git a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs index 13cfe885f..bbe1246ca 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs @@ -65,6 +65,7 @@ namespace Jellyfin.MediaEncoding.Tests.Probing Assert.True(res.VideoStream.IsDefault); Assert.False(res.VideoStream.IsExternal); Assert.False(res.VideoStream.IsForced); + Assert.False(res.VideoStream.IsHearingImpaired); Assert.False(res.VideoStream.IsInterlaced); Assert.False(res.VideoStream.IsTextSubtitleStream); Assert.Equal(13d, res.VideoStream.Level); @@ -142,16 +143,19 @@ namespace Jellyfin.MediaEncoding.Tests.Probing Assert.Equal(MediaStreamType.Subtitle, res.MediaStreams[3].Type); Assert.Equal("DVDSUB", res.MediaStreams[3].Codec); Assert.Null(res.MediaStreams[3].Title); + Assert.False(res.MediaStreams[3].IsHearingImpaired); Assert.Equal("eng", res.MediaStreams[4].Language); Assert.Equal(MediaStreamType.Subtitle, res.MediaStreams[4].Type); Assert.Equal("mov_text", res.MediaStreams[4].Codec); Assert.Null(res.MediaStreams[4].Title); + Assert.True(res.MediaStreams[4].IsHearingImpaired); Assert.Equal("eng", res.MediaStreams[5].Language); Assert.Equal(MediaStreamType.Subtitle, res.MediaStreams[5].Type); Assert.Equal("mov_text", res.MediaStreams[5].Codec); Assert.Equal("Commentary", res.MediaStreams[5].Title); + Assert.False(res.MediaStreams[5].IsHearingImpaired); } [Fact] diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs index e14850eed..fe0d7fc90 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs @@ -1,7 +1,6 @@ using System; using System.Globalization; using System.IO; -using System.Threading; using MediaBrowser.MediaEncoding.Subtitles; using Microsoft.Extensions.Logging.Abstractions; using Xunit; diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs index 0038b1873..2aebee556 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs @@ -1,7 +1,6 @@ using System; using System.Globalization; using System.IO; -using System.Threading; using MediaBrowser.MediaEncoding.Subtitles; using Microsoft.Extensions.Logging.Abstractions; using Xunit; diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs index 3b9a71690..6abf2d26c 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text; -using System.Threading; using MediaBrowser.MediaEncoding.Subtitles; using MediaBrowser.Model.MediaInfo; using Microsoft.Extensions.Logging.Abstractions; diff --git a/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_mp4_metadata.json b/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_mp4_metadata.json index 77e3def76..9a7a4ba37 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_mp4_metadata.json +++ b/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_mp4_metadata.json @@ -206,7 +206,7 @@ "lyrics": 0, "karaoke": 0, "forced": 0, - "hearing_impaired": 0, + "hearing_impaired": 1, "visual_impaired": 0, "clean_effects": 0, "attached_pic": 0, diff --git a/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs b/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs index 80c38affe..d39a22e30 100644 --- a/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs +++ b/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs @@ -83,6 +83,19 @@ namespace Jellyfin.Model.Tests.Entities }); data.Add( + "Title - EN - Hearing Impaired - Default - Forced - SRT", + new MediaStream + { + Type = MediaStreamType.Subtitle, + Title = "Title", + Language = "EN", + IsForced = true, + IsDefault = true, + IsHearingImpaired = true, + Codec = "SRT" + }); + + data.Add( "Title - AAC - Default - External", new MediaStream { diff --git a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj index cef719cbd..fbcaa66f4 100644 --- a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj +++ b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj @@ -7,7 +7,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="Moq" Version="4.18.2" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> diff --git a/tests/Jellyfin.Naming.Tests/ExternalFiles/ExternalPathParserTests.cs b/tests/Jellyfin.Naming.Tests/ExternalFiles/ExternalPathParserTests.cs index b396b5440..97949adff 100644 --- a/tests/Jellyfin.Naming.Tests/ExternalFiles/ExternalPathParserTests.cs +++ b/tests/Jellyfin.Naming.Tests/ExternalFiles/ExternalPathParserTests.cs @@ -17,12 +17,15 @@ public class ExternalPathParserTests { var englishCultureDto = new CultureDto("English", "English", "en", new[] { "eng" }); var frenchCultureDto = new CultureDto("French", "French", "fr", new[] { "fre", "fra" }); + var hindiCultureDto = new CultureDto("Hindi", "Hindi", "hi", new[] { "hin" }); var localizationManager = new Mock<ILocalizationManager>(MockBehavior.Loose); localizationManager.Setup(lm => lm.FindLanguageInfo(It.IsRegex(@"en.*", RegexOptions.IgnoreCase))) .Returns(englishCultureDto); localizationManager.Setup(lm => lm.FindLanguageInfo(It.IsRegex(@"fr.*", RegexOptions.IgnoreCase))) .Returns(frenchCultureDto); + localizationManager.Setup(lm => lm.FindLanguageInfo(It.IsRegex(@"hi.*", RegexOptions.IgnoreCase))) + .Returns(hindiCultureDto); _audioPathParser = new ExternalPathParser(new NamingOptions(), localizationManager.Object, DlnaProfileType.Audio); _subtitlePathParser = new ExternalPathParser(new NamingOptions(), localizationManager.Object, DlnaProfileType.Subtitle); @@ -89,6 +92,7 @@ public class ExternalPathParserTests [InlineData(".DEFAULT.FORCED", null, null, true, true)] [InlineData(".en", null, "eng")] [InlineData(".EN", null, "eng")] + [InlineData(".hi", null, "hin")] [InlineData(".fr.en", "fr", "eng")] [InlineData(".en.fr", "en", "fre")] [InlineData(".title.en.fr", "title.en", "fre")] @@ -96,7 +100,11 @@ public class ExternalPathParserTests [InlineData(".Title.with.Separator", "Title.with.Separator", null)] [InlineData(".title.en.default.forced", "title", "eng", true, true)] [InlineData(".forced.default.en.title", "title", "eng", true, true)] - public void ParseFile_ExtraTokens_ParseToValues(string tokens, string? title, string? language, bool isDefault = false, bool isForced = false) + [InlineData(".sdh.en.title", "title", "eng", false, false, true)] + [InlineData(".en.cc.title", "title", "eng", false, false, true)] + [InlineData(".hi.en.title", "title", "eng", false, false, true)] + [InlineData(".en.hi.title", "title", "eng", false, false, true)] + public void ParseFile_ExtraTokens_ParseToValues(string tokens, string? title, string? language, bool isDefault = false, bool isForced = false, bool isHearingImpaired = false) { var path = "My.Video" + tokens + ".srt"; @@ -107,5 +115,6 @@ public class ExternalPathParserTests Assert.Equal(language, actual.Language); Assert.Equal(isDefault, actual.IsDefault); Assert.Equal(isForced, actual.IsForced); + Assert.Equal(isHearingImpaired, actual.IsHearingImpaired); } } diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index a630ace15..da0e9f5b1 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -12,7 +12,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="Moq" Version="4.18.2" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> diff --git a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs index 9a9a57be4..79f2366b8 100644 --- a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using Emby.Naming.Common; using Emby.Naming.Video; -using MediaBrowser.Model.IO; using Xunit; namespace Jellyfin.Naming.Tests.Video diff --git a/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs index b76187842..cc9cfdd7d 100644 --- a/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs @@ -3,7 +3,6 @@ using System.Linq; using Emby.Naming.Common; using Emby.Naming.Video; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; using Xunit; namespace Jellyfin.Naming.Tests.Video diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj index 75f0e688c..8ec0262bd 100644 --- a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj +++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj @@ -12,7 +12,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <PrivateAssets>all</PrivateAssets> diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs index 52b0e5a95..166bc0513 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs @@ -103,10 +103,7 @@ namespace Jellyfin.Networking.Tests "[192.158.0.0/16,192.0.0.0/8]")] public void TestCollections(string settings, string result1, string result2, string result3, string result4, string result5) { - if (settings == null) - { - throw new ArgumentNullException(nameof(settings)); - } + ArgumentNullException.ThrowIfNull(settings); var conf = new NetworkConfiguration() { @@ -155,20 +152,11 @@ namespace Jellyfin.Networking.Tests [InlineData("127.0.0.1", "127.0.0.1/8", "[127.0.0.1/32]")] public void UnionCheck(string settings, string compare, string result) { - if (settings == null) - { - throw new ArgumentNullException(nameof(settings)); - } + ArgumentNullException.ThrowIfNull(settings); - if (compare == null) - { - throw new ArgumentNullException(nameof(compare)); - } + ArgumentNullException.ThrowIfNull(compare); - if (result == null) - { - throw new ArgumentNullException(nameof(result)); - } + ArgumentNullException.ThrowIfNull(result); var conf = new NetworkConfiguration() { @@ -264,20 +252,11 @@ namespace Jellyfin.Networking.Tests public void TestCollectionEquality(string source, string dest, string result) { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(source); - if (dest == null) - { - throw new ArgumentNullException(nameof(dest)); - } + ArgumentNullException.ThrowIfNull(dest); - if (result == null) - { - throw new ArgumentNullException(nameof(result)); - } + ArgumentNullException.ThrowIfNull(result); var conf = new NetworkConfiguration() { @@ -331,20 +310,11 @@ namespace Jellyfin.Networking.Tests [InlineData("", "", false, "eth16")] public void TestBindInterfaces(string source, string bindAddresses, bool ipv6enabled, string result) { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(source); - if (bindAddresses == null) - { - throw new ArgumentNullException(nameof(bindAddresses)); - } + ArgumentNullException.ThrowIfNull(bindAddresses); - if (result == null) - { - throw new ArgumentNullException(nameof(result)); - } + ArgumentNullException.ThrowIfNull(result); var conf = new NetworkConfiguration() { @@ -403,15 +373,9 @@ namespace Jellyfin.Networking.Tests [InlineData("192.168.1.1", "192.168.1.0/24", "", false, "eth16=http://helloworld.com", "http://helloworld.com")] public void TestBindInterfaceOverrides(string source, string lan, string bindAddresses, bool ipv6enabled, string publishedServers, string result) { - if (lan == null) - { - throw new ArgumentNullException(nameof(lan)); - } + ArgumentNullException.ThrowIfNull(lan); - if (bindAddresses == null) - { - throw new ArgumentNullException(nameof(bindAddresses)); - } + ArgumentNullException.ThrowIfNull(bindAddresses); var conf = new NetworkConfiguration() { diff --git a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj index 465ea6b94..194229737 100644 --- a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj +++ b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj @@ -13,7 +13,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="Moq" Version="4.18.2" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/MediaInfoResolverTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/MediaInfoResolverTests.cs index 57674bb7f..6ee4b8ef2 100644 --- a/tests/Jellyfin.Providers.Tests/MediaInfo/MediaInfoResolverTests.cs +++ b/tests/Jellyfin.Providers.Tests/MediaInfo/MediaInfoResolverTests.cs @@ -227,7 +227,7 @@ public class MediaInfoResolverTests }); // filename has metadata - file = "My.Video.Title1.default.forced.en.srt"; + file = "My.Video.Title1.default.forced.sdh.en.srt"; data.Add( file, new[] @@ -236,7 +236,7 @@ public class MediaInfoResolverTests }, new[] { - CreateMediaStream(VideoDirectoryPath + "/" + file, "eng", "Title1", 0, true, true) + CreateMediaStream(VideoDirectoryPath + "/" + file, "eng", "Title1", 0, true, true, true) }); // single stream with metadata @@ -245,15 +245,15 @@ public class MediaInfoResolverTests file, new[] { - CreateMediaStream(VideoDirectoryPath + "/" + file, "eng", "Title", 0, true, true) + CreateMediaStream(VideoDirectoryPath + "/" + file, "eng", "Title", 0, true, true, true) }, new[] { - CreateMediaStream(VideoDirectoryPath + "/" + file, "eng", "Title", 0, true, true) + CreateMediaStream(VideoDirectoryPath + "/" + file, "eng", "Title", 0, true, true, true) }); // stream wins for title/language, filename wins for flags when conflicting - file = "My.Video.Title2.default.forced.en.srt"; + file = "My.Video.Title2.default.forced.sdh.en.srt"; data.Add( file, new[] @@ -262,7 +262,7 @@ public class MediaInfoResolverTests }, new[] { - CreateMediaStream(VideoDirectoryPath + "/" + file, "fra", "Metadata", 0, true, true) + CreateMediaStream(VideoDirectoryPath + "/" + file, "fra", "Metadata", 0, true, true, true) }); // multiple stream with metadata - filename flags ignored but other data filled in when missing from stream @@ -324,6 +324,7 @@ public class MediaInfoResolverTests Assert.Equal(expected.Path, actual.Path); Assert.Equal(expected.IsDefault, actual.IsDefault); Assert.Equal(expected.IsForced, actual.IsForced); + Assert.Equal(expected.IsHearingImpaired, actual.IsHearingImpaired); Assert.Equal(expected.Language, actual.Language); Assert.Equal(expected.Title, actual.Title); } @@ -396,7 +397,7 @@ public class MediaInfoResolverTests } } - private static MediaStream CreateMediaStream(string path, string? language, string? title, int index, bool isForced = false, bool isDefault = false) + private static MediaStream CreateMediaStream(string path, string? language, string? title, int index, bool isForced = false, bool isDefault = false, bool isHearingImpaired = false) { return new MediaStream { @@ -405,6 +406,7 @@ public class MediaInfoResolverTests Path = path, IsDefault = isDefault, IsForced = isForced, + IsHearingImpaired = isHearingImpaired, Language = language, Title = title }; diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index 27390c937..918802d77 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -21,7 +21,7 @@ <ItemGroup> <PackageReference Include="AutoFixture" Version="4.17.0" /> <PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" /> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="Moq" Version="4.18.2" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> diff --git a/tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs index 40f271d61..261092e01 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Emby.Server.Implementations.Sorting; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs index 5d7b0e874..a65f65bb2 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs @@ -34,8 +34,8 @@ namespace Jellyfin.Server.Integration.Tests.Controllers var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); - using var getResponse = await client.GetAsync("/Dlna/Profiles/" + NonExistentProfile).ConfigureAwait(false); - Assert.Equal(HttpStatusCode.NotFound, getResponse.StatusCode); + using var response = await client.GetAsync("/Dlna/Profiles/" + NonExistentProfile).ConfigureAwait(false); + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } [Fact] @@ -45,8 +45,8 @@ namespace Jellyfin.Server.Integration.Tests.Controllers var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); - using var getResponse = await client.DeleteAsync("/Dlna/Profiles/" + NonExistentProfile).ConfigureAwait(false); - Assert.Equal(HttpStatusCode.NotFound, getResponse.StatusCode); + using var response = await client.DeleteAsync("/Dlna/Profiles/" + NonExistentProfile).ConfigureAwait(false); + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } [Fact] @@ -61,8 +61,8 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Name = "ThisProfileDoesNotExist" }; - using var getResponse = await client.PostAsJsonAsync("/Dlna/Profiles/" + NonExistentProfile, deviceProfile, _jsonOptions).ConfigureAwait(false); - Assert.Equal(HttpStatusCode.NotFound, getResponse.StatusCode); + using var response = await client.PostAsJsonAsync("/Dlna/Profiles/" + NonExistentProfile, deviceProfile, _jsonOptions).ConfigureAwait(false); + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } [Fact] @@ -77,8 +77,8 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Name = "ThisProfileIsNew" }; - using var getResponse = await client.PostAsJsonAsync("/Dlna/Profiles", deviceProfile, _jsonOptions).ConfigureAwait(false); - Assert.Equal(HttpStatusCode.NoContent, getResponse.StatusCode); + using var response = await client.PostAsJsonAsync("/Dlna/Profiles", deviceProfile, _jsonOptions).ConfigureAwait(false); + Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); } [Fact] @@ -115,20 +115,46 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Id = _newDeviceProfileId }; - using var getResponse = await client.PostAsJsonAsync("/Dlna/Profiles", updatedProfile, _jsonOptions).ConfigureAwait(false); - Assert.Equal(HttpStatusCode.NoContent, getResponse.StatusCode); + using var postResponse = await client.PostAsJsonAsync("/Dlna/Profiles/" + _newDeviceProfileId, updatedProfile, _jsonOptions).ConfigureAwait(false); + Assert.Equal(HttpStatusCode.NoContent, postResponse.StatusCode); + + // Verify that the profile got updated + using var response = await client.GetAsync("/Dlna/ProfileInfos").ConfigureAwait(false); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); + Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); + + var profiles = await JsonSerializer.DeserializeAsync<DeviceProfileInfo[]>( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + _jsonOptions).ConfigureAwait(false); + + Assert.Null(profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsNew", StringComparison.Ordinal))); + var newProfile = profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsUpdated", StringComparison.Ordinal)); + Assert.NotNull(newProfile); + _newDeviceProfileId = newProfile!.Id; } [Fact] - [Priority(4)] + [Priority(5)] public async Task DeleteProfile_Valid_NoContent() { var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); - using var getResponse = await client.DeleteAsync("/Dlna/Profiles/" + _newDeviceProfileId).ConfigureAwait(false); - Console.WriteLine(await getResponse.Content.ReadAsStringAsync().ConfigureAwait(false)); - Assert.Equal(HttpStatusCode.NoContent, getResponse.StatusCode); + using var deleteResponse = await client.DeleteAsync("/Dlna/Profiles/" + _newDeviceProfileId).ConfigureAwait(false); + Assert.Equal(HttpStatusCode.NoContent, deleteResponse.StatusCode); + + // Verify that the profile got deleted + using var response = await client.GetAsync("/Dlna/ProfileInfos").ConfigureAwait(false); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); + Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); + + var profiles = await JsonSerializer.DeserializeAsync<DeviceProfileInfo[]>( + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + _jsonOptions).ConfigureAwait(false); + + Assert.Null(profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsUpdated", StringComparison.Ordinal))); } } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 2be523a80..659737392 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -9,9 +9,9 @@ <PackageReference Include="AutoFixture" Version="4.17.0" /> <PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" /> <PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" /> - <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.8" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.9" /> <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" /> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <PrivateAssets>all</PrivateAssets> diff --git a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs index adaf624a9..48c49bf84 100644 --- a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs +++ b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs @@ -11,7 +11,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Serilog; using Serilog.Extensions.Logging; -using static MediaBrowser.Controller.Extensions.ConfigurationExtensions; namespace Jellyfin.Server.Integration.Tests { diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index e69f1f0e0..b2653b28b 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -10,9 +10,9 @@ <PackageReference Include="AutoFixture" Version="4.17.0" /> <PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" /> <PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" /> - <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.8" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.9" /> <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" /> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <PrivateAssets>all</PrivateAssets> diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj index 53921cb6e..f03448eed 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj +++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj @@ -13,7 +13,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> <PackageReference Include="Moq" Version="4.18.2" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs index 7c9952030..988abce81 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading; using Jellyfin.Data.Entities; |
