From 3a9fcb6abd249759bd44b2fbcf437beee8f611c2 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 12 Feb 2021 17:34:51 +0100 Subject: Rewrite packet writing code for HdHomerun --- .../TunerHosts/HdHomerun/HdHomerunManager.cs | 241 +++++---------------- 1 file changed, 59 insertions(+), 182 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index f09338330..188eca158 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -2,6 +2,7 @@ using System; using System.Buffers; +using System.Buffers.Binary; using System.Collections.Generic; using System.Globalization; using System.Net; @@ -10,6 +11,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common; using MediaBrowser.Controller.LiveTv; namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun @@ -120,13 +122,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private static async Task CheckTunerAvailability(NetworkStream stream, int tuner, CancellationToken cancellationToken) { - var lockkeyMsg = CreateGetMessage(tuner, "lockkey"); - await stream.WriteAsync(lockkeyMsg, 0, lockkeyMsg.Length, cancellationToken).ConfigureAwait(false); - byte[] buffer = ArrayPool.Shared.Rent(8192); try { - int receivedBytes = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); + var msgLen = WriteGetMessage(buffer, tuner, "lockkey"); + await stream.WriteAsync(buffer.AsMemory(0, msgLen), cancellationToken).ConfigureAwait(false); + + int receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); ParseReturnMessage(buffer, receivedBytes, out string returnVal); @@ -166,9 +168,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun _activeTuner = i; var lockKeyString = string.Format(CultureInfo.InvariantCulture, "{0:d}", lockKeyValue); - var lockkeyMsg = CreateSetMessage(i, "lockkey", lockKeyString, null); - await stream.WriteAsync(lockkeyMsg, 0, lockkeyMsg.Length, cancellationToken).ConfigureAwait(false); - int receivedBytes = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); + var lockkeyMsgLen = WriteSetMessage(buffer, i, "lockkey", lockKeyString, null); + await stream.WriteAsync(buffer.AsMemory(0, lockkeyMsgLen), cancellationToken).ConfigureAwait(false); + int receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); // parse response to make sure it worked if (!ParseReturnMessage(buffer, receivedBytes, out _)) @@ -178,9 +180,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun foreach (var command in commands.GetCommands()) { - var channelMsg = CreateSetMessage(i, command.Item1, command.Item2, lockKeyValue); - await stream.WriteAsync(channelMsg, 0, channelMsg.Length, cancellationToken).ConfigureAwait(false); - receivedBytes = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); + var channelMsgLen = WriteSetMessage(buffer, i, command.Item1, command.Item2, lockKeyValue); + await stream.WriteAsync(buffer.AsMemory(0, channelMsgLen), cancellationToken).ConfigureAwait(false); + receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); // parse response to make sure it worked if (!ParseReturnMessage(buffer, receivedBytes, out _)) @@ -191,10 +193,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } var targetValue = string.Format(CultureInfo.InvariantCulture, "rtp://{0}:{1}", localIp, localPort); - var targetMsg = CreateSetMessage(i, "target", targetValue, lockKeyValue); + var targetMsgLen = WriteSetMessage(buffer, i, "target", targetValue, lockKeyValue); - await stream.WriteAsync(targetMsg, 0, targetMsg.Length, cancellationToken).ConfigureAwait(false); - receivedBytes = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); + await stream.WriteAsync(buffer.AsMemory(0, targetMsgLen), cancellationToken).ConfigureAwait(false); + receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); // parse response to make sure it worked if (!ParseReturnMessage(buffer, receivedBytes, out _)) @@ -232,9 +234,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { foreach (var command in commandList) { - var channelMsg = CreateSetMessage(_activeTuner, command.Item1, command.Item2, _lockkey); - await stream.WriteAsync(channelMsg, 0, channelMsg.Length, cancellationToken).ConfigureAwait(false); - int receivedBytes = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); + var channelMsgLen = WriteSetMessage(buffer, _activeTuner, command.Item1, command.Item2, _lockkey); + await stream.WriteAsync(buffer.AsMemory(0, channelMsgLen), cancellationToken).ConfigureAwait(false); + int receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); // parse response to make sure it worked if (!ParseReturnMessage(buffer, receivedBytes, out _)) @@ -265,17 +267,17 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { var stream = client.GetStream(); - var releaseTarget = CreateSetMessage(_activeTuner, "target", "none", lockKeyValue); - await stream.WriteAsync(releaseTarget, 0, releaseTarget.Length).ConfigureAwait(false); - var buffer = ArrayPool.Shared.Rent(8192); try { - await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); - var releaseKeyMsg = CreateSetMessage(_activeTuner, "lockkey", "none", lockKeyValue); + var releaseTargetLen = WriteSetMessage(buffer, _activeTuner, "target", "none", lockKeyValue); + await stream.WriteAsync(buffer.AsMemory(0, releaseTargetLen)).ConfigureAwait(false); + + await stream.ReadAsync(buffer).ConfigureAwait(false); + var releaseKeyMsgLen = WriteSetMessage(buffer, _activeTuner, "lockkey", "none", lockKeyValue); _lockkey = null; - await stream.WriteAsync(releaseKeyMsg, 0, releaseKeyMsg.Length).ConfigureAwait(false); - await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); + await stream.WriteAsync(buffer.AsMemory(0, releaseKeyMsgLen)).ConfigureAwait(false); + await stream.ReadAsync(buffer).ConfigureAwait(false); } finally { @@ -283,105 +285,65 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } - private static byte[] CreateGetMessage(int tuner, string name) + internal static int WriteGetMessage(Span buffer, int tuner, string name) { - var byteName = Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "/tuner{0}/{1}\0", tuner, name)); - int messageLength = byteName.Length + 10; // 4 bytes for header + 4 bytes for crc + 2 bytes for tag name and length - - var message = new byte[messageLength]; - - int offset = InsertHeaderAndName(byteName, messageLength, message); - - bool flipEndian = BitConverter.IsLittleEndian; + var byteName = string.Format(CultureInfo.InvariantCulture, "/tuner{0}/{1}", tuner, name); + int offset = WriteHeaderAndName(buffer, byteName); // calculate crc and insert at the end of the message - var crcBytes = BitConverter.GetBytes(HdHomerunCrc.GetCrc32(message, messageLength - 4)); - if (flipEndian) - { - Array.Reverse(crcBytes); - } - - Buffer.BlockCopy(crcBytes, 0, message, offset, 4); + var crc = Crc32.Compute(buffer.Slice(0, offset)); + BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), crc); - return message; + return offset + 4; } - private static byte[] CreateSetMessage(int tuner, string name, string value, uint? lockkey) + private static int WriteSetMessage(Span buffer, int tuner, string name, string value, uint? lockkey) { - var byteName = Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "/tuner{0}/{1}\0", tuner, name)); - var byteValue = Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}\0", value)); + var byteName = string.Format(CultureInfo.InvariantCulture, "/tuner{0}/{1}", tuner, name); + int offset = WriteHeaderAndName(buffer, byteName); - int messageLength = byteName.Length + byteValue.Length + 12; - if (lockkey.HasValue) - { - messageLength += 6; - } - - var message = new byte[messageLength]; - - int offset = InsertHeaderAndName(byteName, messageLength, message); + buffer[offset++] = GetSetValue; + offset += WriteNullTerminatedString(buffer.Slice(offset), value); - bool flipEndian = BitConverter.IsLittleEndian; - - message[offset++] = GetSetValue; - message[offset++] = Convert.ToByte(byteValue.Length); - Buffer.BlockCopy(byteValue, 0, message, offset, byteValue.Length); - offset += byteValue.Length; if (lockkey.HasValue) { - message[offset++] = GetSetLockkey; - message[offset++] = 4; - var lockKeyBytes = BitConverter.GetBytes(lockkey.Value); - if (flipEndian) - { - Array.Reverse(lockKeyBytes); - } - - Buffer.BlockCopy(lockKeyBytes, 0, message, offset, 4); + buffer[offset++] = GetSetLockkey; + buffer[offset++] = 4; + BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset), lockkey.Value); offset += 4; } // calculate crc and insert at the end of the message - var crcBytes = BitConverter.GetBytes(HdHomerunCrc.GetCrc32(message, messageLength - 4)); - if (flipEndian) - { - Array.Reverse(crcBytes); - } - - Buffer.BlockCopy(crcBytes, 0, message, offset, 4); + var crc = Crc32.Compute(buffer.Slice(0, offset)); + BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), crc); - return message; + return offset + 4; } - private static int InsertHeaderAndName(byte[] byteName, int messageLength, byte[] message) + internal static int WriteNullTerminatedString(Span buffer, ReadOnlySpan value) { - // check to see if we need to flip endiannes - bool flipEndian = BitConverter.IsLittleEndian; - int offset = 0; + int len = Encoding.UTF8.GetBytes(value, buffer.Slice(1)) + 1; - // create header bytes - var getSetBytes = BitConverter.GetBytes(GetSetRequest); - var msgLenBytes = BitConverter.GetBytes((ushort)(messageLength - 8)); // Subtrace 4 bytes for header and 4 bytes for crc + // Write length in front of value + buffer[0] = Convert.ToByte(len); - if (flipEndian) - { - Array.Reverse(getSetBytes); - Array.Reverse(msgLenBytes); - } + // null-terminate + buffer[len++] = 0; + + return len; + } + private static int WriteHeaderAndName(Span buffer, ReadOnlySpan payload) + { // insert header bytes into message - Buffer.BlockCopy(getSetBytes, 0, message, offset, 2); - offset += 2; - Buffer.BlockCopy(msgLenBytes, 0, message, offset, 2); - offset += 2; + BinaryPrimitives.WriteUInt16BigEndian(buffer, GetSetRequest); + int offset = 2; + // Subtract 4 bytes for header and 4 bytes for crc + BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(offset), (ushort)(payload.Length + 2)); // insert tag name and length - message[offset++] = GetSetName; - message[offset++] = Convert.ToByte(byteName.Length); - - // insert name string - Buffer.BlockCopy(byteName, 0, message, offset, byteName.Length); - offset += byteName.Length; + buffer[offset++] = GetSetName; + offset += WriteNullTerminatedString(buffer.Slice(offset), payload); return offset; } @@ -442,90 +404,5 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun returnVal = Encoding.UTF8.GetString(buf, offset, valueLength - 1); // remove null terminator return true; } - - private static class HdHomerunCrc - { - private static uint[] crc_table = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, - 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, - 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, - 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, - 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, - 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, - 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, - 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, - 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, - 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, - 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, - 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, - 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, - 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, - 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, - 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, - 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, - 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, - 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, - 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, - 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, - 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, - 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, - 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, - 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, - 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, - 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, - 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, - 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, - 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, - 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, - 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, - 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; - - public static uint GetCrc32(byte[] bytes, int numBytes) - { - var hash = 0xffffffff; - for (var i = 0; i < numBytes; i++) - { - hash = (hash >> 8) ^ crc_table[(hash ^ bytes[i]) & 0xff]; - } - - var tmp = ~hash & 0xffffffff; - var b0 = tmp & 0xff; - var b1 = (tmp >> 8) & 0xff; - var b2 = (tmp >> 16) & 0xff; - var b3 = (tmp >> 24) & 0xff; - return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3; - } - } } } -- cgit v1.2.3 From e1bc322b709756529759fbb74cb003e133f30ab6 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 12 Feb 2021 18:35:54 +0100 Subject: Add test for WriteGetMessage --- .../TunerHosts/HdHomerun/HdHomerunManager.cs | 51 ++++++++++++---------- .../LiveTv/HdHomerunManagerTests.cs | 19 ++++++++ 2 files changed, 48 insertions(+), 22 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index 188eca158..20a4d87fb 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -288,19 +288,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun internal static int WriteGetMessage(Span buffer, int tuner, string name) { var byteName = string.Format(CultureInfo.InvariantCulture, "/tuner{0}/{1}", tuner, name); - int offset = WriteHeaderAndName(buffer, byteName); - - // calculate crc and insert at the end of the message - var crc = Crc32.Compute(buffer.Slice(0, offset)); - BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), crc); - - return offset + 4; + int offset = WriteHeaderAndPayload(buffer, byteName); + return FinishPacket(buffer, offset); } private static int WriteSetMessage(Span buffer, int tuner, string name, string value, uint? lockkey) { var byteName = string.Format(CultureInfo.InvariantCulture, "/tuner{0}/{1}", tuner, name); - int offset = WriteHeaderAndName(buffer, byteName); + int offset = WriteHeaderAndPayload(buffer, byteName); buffer[offset++] = GetSetValue; offset += WriteNullTerminatedString(buffer.Slice(offset), value); @@ -313,17 +308,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun offset += 4; } - // calculate crc and insert at the end of the message - var crc = Crc32.Compute(buffer.Slice(0, offset)); - BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), crc); - - return offset + 4; + return FinishPacket(buffer, offset); } - internal static int WriteNullTerminatedString(Span buffer, ReadOnlySpan value) + internal static int WriteNullTerminatedString(Span buffer, ReadOnlySpan payload) { - int len = Encoding.UTF8.GetBytes(value, buffer.Slice(1)) + 1; + int len = Encoding.UTF8.GetBytes(payload, buffer.Slice(1)) + 1; + // TODO: variable length: this can be 2 bytes if len > 127 // Write length in front of value buffer[0] = Convert.ToByte(len); @@ -333,21 +325,36 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return len; } - private static int WriteHeaderAndName(Span buffer, ReadOnlySpan payload) + private static int WriteHeaderAndPayload(Span buffer, ReadOnlySpan payload) { - // insert header bytes into message + // Packet type BinaryPrimitives.WriteUInt16BigEndian(buffer, GetSetRequest); - int offset = 2; - // Subtract 4 bytes for header and 4 bytes for crc - BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(offset), (ushort)(payload.Length + 2)); - // insert tag name and length + // We write the payload length at the end + int offset = 4; + + // Tag buffer[offset++] = GetSetName; - offset += WriteNullTerminatedString(buffer.Slice(offset), payload); + + // Payload length + data + int strLen = WriteNullTerminatedString(buffer.Slice(offset), payload); + offset += strLen; return offset; } + private static int FinishPacket(Span buffer, int offset) + { + // Payload length + BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(2), (ushort)(offset - 4)); + + // calculate crc and insert at the end of the message + var crc = Crc32.Compute(buffer.Slice(0, offset)); + BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), crc); + + return offset + 4; + } + private static bool ParseReturnMessage(byte[] buf, int numBytes, out string returnVal) { returnVal = string.Empty; diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs index 15cc12d64..7e04a1ec1 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs @@ -35,5 +35,24 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv Assert.Equal(expected.Length, len); Assert.True(expected.SequenceEqual(buffer.Slice(0, len))); } + + [Fact] + public void WriteGetMessage_Valid_Success() + { + ReadOnlySpan expected = stackalloc byte[] + { + 0, 4, + 0, 12, + 3, + 10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0, + 0xc0, 0xc9, 0x87, 0x33 + }; + + Span buffer = stackalloc byte[128]; + int len = HdHomerunManager.WriteGetMessage(buffer, 0, "N"); + + Assert.Equal(expected.Length, len); + Assert.True(expected.SequenceEqual(buffer.Slice(0, len))); + } } } -- cgit v1.2.3 From acac21d8dc3eb9383136ff692606dc2f65adf405 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 23 Feb 2021 16:45:10 +0100 Subject: Improve tests --- .../EntryPoints/UdpServerEntryPoint.cs | 11 + Emby.Server.Implementations/Udp/UdpServer.cs | 2 +- .../Converters/JsonCommaDelimitedArrayConverter.cs | 2 +- .../Converters/JsonPipeDelimitedArrayConverter.cs | 2 +- .../Json/Converters/JsonVersionConverter.cs | 20 - MediaBrowser.Common/Json/JsonDefaults.cs | 1 - .../Test Data/Updates/manifest-stable.json | 684 +++++++++++++++++++++ .../Updates/InstallationManagerTests.cs | 57 ++ 8 files changed, 755 insertions(+), 24 deletions(-) delete mode 100644 MediaBrowser.Common/Json/Converters/JsonVersionConverter.cs create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest-stable.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs index a12a6b26c..3624e079f 100644 --- a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs +++ b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs @@ -1,5 +1,6 @@ #nullable enable +using System; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; @@ -51,6 +52,8 @@ namespace Emby.Server.Implementations.EntryPoints /// public Task RunAsync() { + CheckDisposed(); + try { _udpServer = new UdpServer(_logger, _appHost, _config); @@ -64,6 +67,14 @@ namespace Emby.Server.Implementations.EntryPoints return Task.CompletedTask; } + private void CheckDisposed() + { + if (_disposed) + { + throw new ObjectDisposedException(this.GetType().Name); + } + } + /// public void Dispose() { diff --git a/Emby.Server.Implementations/Udp/UdpServer.cs b/Emby.Server.Implementations/Udp/UdpServer.cs index 4fd7ac0c1..d01184e0b 100644 --- a/Emby.Server.Implementations/Udp/UdpServer.cs +++ b/Emby.Server.Implementations/Udp/UdpServer.cs @@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.Udp /// Starts the specified port. /// /// The port. - /// + /// The cancellation token to cancel operation. public void Start(int port, CancellationToken cancellationToken) { _endpoint = new IPEndPoint(IPAddress.Any, port); diff --git a/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs b/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs index 38a7e1d20..d9f6519e9 100644 --- a/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs +++ b/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.Common.Json.Converters /// public override void Write(Utf8JsonWriter writer, T[] value, JsonSerializerOptions options) { - JsonSerializer.Serialize(writer, value, options); + throw new NotImplementedException(); } } } diff --git a/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs b/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs index 377db1a44..c408a3be1 100644 --- a/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs +++ b/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.Common.Json.Converters /// public override void Write(Utf8JsonWriter writer, T[] value, JsonSerializerOptions options) { - JsonSerializer.Serialize(writer, value, options); + throw new NotImplementedException(); } } } diff --git a/MediaBrowser.Common/Json/Converters/JsonVersionConverter.cs b/MediaBrowser.Common/Json/Converters/JsonVersionConverter.cs deleted file mode 100644 index 37e6f64e3..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonVersionConverter.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// - /// Converts a Version object or value to/from JSON. - /// - public class JsonVersionConverter : JsonConverter - { - /// - public override Version Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - => new Version(reader.GetString()); - - /// - public override void Write(Utf8JsonWriter writer, Version value, JsonSerializerOptions options) - => writer.WriteStringValue(value.ToString()); - } -} diff --git a/MediaBrowser.Common/Json/JsonDefaults.cs b/MediaBrowser.Common/Json/JsonDefaults.cs index 2ef24a884..a3999e7e2 100644 --- a/MediaBrowser.Common/Json/JsonDefaults.cs +++ b/MediaBrowser.Common/Json/JsonDefaults.cs @@ -35,7 +35,6 @@ namespace MediaBrowser.Common.Json { new JsonGuidConverter(), new JsonNullableGuidConverter(), - new JsonVersionConverter(), new JsonStringEnumConverter(), new JsonNullableStructConverterFactory(), new JsonBoolNumberConverter(), diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest-stable.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest-stable.json new file mode 100644 index 000000000..b766e668e --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest-stable.json @@ -0,0 +1,684 @@ +[ + { + "guid": "a4df60c5-6ab4-412a-8f79-2cab93fb2bc5", + "name": "Anime", + "description": "Manage your anime in Jellyfin. This plugin supports several different metadata providers and options for organizing your collection.\n", + "overview": "Manage your anime from Jellyfin", + "owner": "jellyfin", + "category": "Metadata", + "versions": [ + { + "version": "10.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/anime/anime_10.0.0.0.zip", + "checksum": "93e969adeba1050423fc8817ed3c36f8", + "timestamp": "2020-08-17T01:41:13Z" + }, + { + "version": "9.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/anime/anime_9.0.0.0.zip", + "checksum": "9b1cebff835813e15f414f44b40c41c8", + "timestamp": "2020-07-20T01:30:16Z" + } + ] + }, + { + "guid": "70b7b43b-471b-4159-b4be-56750c795499", + "name": "Auto Organize", + "description": "Automatically organize your media", + "overview": "Automatically organize your media", + "owner": "jellyfin", + "category": "General", + "versions": [ + { + "version": "9.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/auto-organize/auto-organize_9.0.0.0.zip", + "checksum": "ff29ac3cbe05d208b6af94cd6d9dea39", + "timestamp": "2020-12-05T22:31:12Z" + }, + { + "version": "8.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/auto-organize/auto-organize_8.0.0.0.zip", + "checksum": "460bbb45e556464a8476b18e41c097f5", + "timestamp": "2020-07-20T01:30:25Z" + } + ] + }, + { + "guid": "9c4e63f1-031b-4f25-988b-4f7d78a8b53e", + "name": "Bookshelf", + "description": "Supports several different metadata providers and options for organizing your collection.\n", + "overview": "Manage your books", + "owner": "jellyfin", + "category": "Metadata", + "versions": [ + { + "version": "5.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/bookshelf/bookshelf_5.0.0.0.zip", + "checksum": "2063fb8ab317b8d77b200fde41eb5e1e", + "timestamp": "2020-12-05T22:03:13Z" + }, + { + "version": "4.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/bookshelf/bookshelf_4.0.0.0.zip", + "checksum": "fc9f76c0815d766491e5b0f30ede55ed", + "timestamp": "2020-07-20T01:30:33Z" + } + ] + }, + { + "guid": "cfa0f7f4-4155-4d71-849b-d6598dc4c5bb", + "name": "Email", + "description": "Send SMTP email notifications", + "overview": "Send SMTP email notifications", + "owner": "jellyfin", + "category": "Notifications", + "versions": [ + { + "version": "9.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/email/email_9.0.0.0.zip", + "checksum": "cfe7afc00f3fbd6d6ab8244d7ff968ce", + "timestamp": "2020-12-05T22:20:32Z" + }, + { + "version": "7.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/email/email_7.0.0.0.zip", + "checksum": "680ca511d8ad84923cb04f024fd8eb19", + "timestamp": "2020-07-20T01:30:40Z" + } + ] + }, + { + "guid": "170a157f-ac6c-437a-abdd-ca9c25cebd39", + "name": "Fanart", + "description": "Scrape poster images for movies, shows, and artists in your library.", + "overview": "Scrape poster images from Fanart", + "owner": "jellyfin", + "category": "Metadata", + "versions": [ + { + "version": "6.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/fanart/fanart_6.0.0.0.zip", + "checksum": "ee4360bfcc8722d5a3a54cfe7eef640f", + "timestamp": "2020-12-05T22:25:43Z" + }, + { + "version": "5.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/fanart/fanart_5.0.0.0.zip", + "checksum": "f842f7d65d23f377761c907d40b89647", + "timestamp": "2020-07-20T01:30:48Z" + } + ] + }, + { + "guid": "e29621a5-fa9e-4330-982e-ef6e54c0cad2", + "name": "Gotify Notification", + "description": "You must have a Gotify server to use this plugin!\n", + "overview": "Sends notifications to your Gotify server", + "owner": "crobibero", + "category": "Notifications", + "versions": [ + { + "version": "7.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/gotify-notification/gotify-notification_7.0.0.0.zip", + "checksum": "7c5ff9e8792c8cdee7e8a2aaeb6cc093", + "timestamp": "2020-07-20T01:30:56Z" + } + ] + }, + { + "guid": "a59b5c4b-05a8-488f-bfa8-7a63fffc7639", + "name": "IPTV", + "description": "Enable IPTV support in Jellyfin", + "overview": "Enable IPTV support in Jellyfin", + "owner": "jellyfin", + "category": "Channel", + "versions": [ + { + "version": "6.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/iptv/iptv_6.0.0.0.zip", + "checksum": "9cf103bf67a4eda7c3a42d9b235f6447", + "timestamp": "2020-07-20T01:31:05Z" + } + ] + }, + { + "guid": "4682DD4C-A675-4F1B-8E7C-79ADF137A8F8", + "name": "ISO Mounter", + "description": "Mount your ISO files for Jellyfin.\n", + "overview": "Mount your ISO files for Jellyfin", + "owner": "jellyfin", + "category": "Metadata", + "versions": [ + { + "version": "1.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/iso-mounter/iso-mounter_1.0.0.0.zip", + "checksum": "847e5bc7ac34c1bf4dc5b28173170fae", + "timestamp": "2020-07-20T01:31:13Z" + } + ] + }, + { + "guid": "771e19d6-5385-4caf-b35c-28a0e865cf63", + "name": "Kodi Sync Queue", + "description": "This plugin will track all media changes while Kodi clients are offline to decrease sync times.", + "overview": "Sync all media changes with Kodi clients", + "owner": "jellyfin", + "category": "General", + "versions": [ + { + "version": "6.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/kodi-sync-queue/kodi-sync-queue_6.0.0.0.zip", + "checksum": "787c856c0d2ad2224cdd8b3094cf0329", + "timestamp": "2020-12-05T22:10:37Z" + }, + { + "version": "5.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/kodi-sync-queue/kodi-sync-queue_5.0.0.0.zip", + "checksum": "08285397aecd93ea64a4f15d38b1bd7b", + "timestamp": "2020-07-20T01:31:22Z" + } + ] + }, + { + "guid": "958aad66-3784-4d2a-b89a-a7b6fab6e25c", + "name": "LDAP Authentication", + "description": "Authenticate your Jellyfin users against an LDAP database, and optionally create users who do not yet exist automatically.\nAllows the administrator to customize most aspects of the LDAP authentication process, including customizable search attributes, username attribute, and a search filter for administrative users (set on user creation). The user, via the \"Manual Login\" process, can enter any valid attribute value, which will be mapped back to the specified username attribute automatically as well.\n", + "overview": "Authenticate users against an LDAP database", + "owner": "jellyfin", + "category": "Authentication", + "versions": [ + { + "version": "10.0.0.0", + "changelog": "Update for 10.7 support\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/ldap-authentication/ldap-authentication_10.0.0.0.zip", + "checksum": "62e7e1cd3ffae0944c14750a3c90df4f", + "timestamp": "2020-12-05T19:48:10Z" + }, + { + "version": "9.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/ldap-authentication/ldap-authentication_9.0.0.0.zip", + "checksum": "7f2f83587a65a43ebf168e4058421463", + "timestamp": "2020-07-22T15:42:57Z" + }, + { + "version": "8.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/ldap-authentication/ldap-authentication_8.0.0.0.zip", + "checksum": "8af8cee62717d63577f8b1e710839415", + "timestamp": "2020-07-20T01:31:30Z" + } + ] + }, + { + "guid": "9574ac10-bf23-49bc-949f-924f23cfa48f", + "name": "NextPVR", + "description": "Provides access to live TV, program guide, and recordings from NextPVR.\n", + "overview": "Live TV plugin for NextPVR", + "owner": "jellyfin", + "category": "LiveTV", + "versions": [ + { + "version": "5.0.0.0", + "changelog": "Updated to use NextPVR API v5, no longer compatable with API v4.\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/nextpvr/nextpvr_5.0.0.0.zip", + "checksum": "d70f694d14bf9462ba2b2ebe110068d3", + "timestamp": "2020-12-05T22:24:03Z" + }, + { + "version": "4.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/nextpvr/nextpvr_4.0.0.0.zip", + "checksum": "b15949d895ac5a8c89496581db350478", + "timestamp": "2020-07-20T01:31:38Z" + } + ] + }, + { + "guid": "4b9ed42f-5185-48b5-9803-6ff2989014c4", + "name": "Open Subtitles", + "description": "Download subtitles from the internet to use with your media files.", + "overview": "Download subtitles for your media", + "owner": "jellyfin", + "category": "Metadata", + "versions": [ + { + "version": "10.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/open-subtitles/open-subtitles_10.0.0.0.zip", + "checksum": "ed99d03ec463bf15fca1256a113f57b4", + "timestamp": "2020-12-05T21:56:19Z" + }, + { + "version": "9.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/open-subtitles/open-subtitles_9.0.0.0.zip", + "checksum": "16789b26497cea0509daf6b18c579340", + "timestamp": "2020-07-20T01:32:00Z" + } + ] + }, + { + "guid": "5c534381-91a3-43cb-907a-35aa02eb9d2c", + "name": "Playback Reporting", + "description": "Collect and show user play statistics", + "overview": "Collect and show user play statistics", + "owner": "jellyfin", + "category": "General", + "versions": [ + { + "version": "9.0.0.0", + "changelog": "Add authentication to plugin endpoints\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/playback-reporting/playback-reporting_9.0.0.0.zip", + "checksum": "ca323b3dcb2cb86cc2e72a7a0f1eee22", + "timestamp": "2020-12-05T22:15:48Z" + }, + { + "version": "8.0.0.0", + "changelog": "Add authentication to plugin endpoints\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/playback-reporting/playback-reporting_8.0.0.0.zip", + "checksum": "58644c505586542ef0b8b65e2f704bd1", + "timestamp": "2020-11-18T03:01:51Z" + }, + { + "version": "7.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/playback-reporting/playback-reporting_7.0.0.0.zip", + "checksum": "6a361ef33bca97f9155856d02ff47380", + "timestamp": "2020-07-20T01:32:09Z" + } + ] + }, + { + "guid": "de228f12-e43e-4bd9-9fc0-2830819c3b92", + "name": "Pushbullet", + "description": "Get notifications via Pushbullet.\n", + "overview": "Pushbullet notification plugin", + "owner": "jellyfin", + "category": "Notifications", + "versions": [ + { + "version": "6.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/pushbullet/pushbullet_6.0.0.0.zip", + "checksum": "248cf3d56644f1d909e75aaddbdfb3a6", + "timestamp": "2020-12-06T02:47:53Z" + }, + { + "version": "5.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/pushbullet/pushbullet_5.0.0.0.zip", + "checksum": "dabbdd86328b2922a69dfa0c9e1c8343", + "timestamp": "2020-07-20T01:32:17Z" + } + ] + }, + { + "guid": "F240D6BE-5743-441B-87F1-A70ECAC42642", + "name": "Pushover", + "description": "Send messages to a wide range of devices through Pushover.", + "overview": "Send notifications via Pushover", + "owner": "crobibero", + "category": "Notifications", + "versions": [ + { + "version": "4.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/pushover/pushover_4.0.0.0.zip", + "checksum": "56a0da16c7e48cc184987737b7e155dd", + "timestamp": "2020-07-20T01:32:25Z" + } + ] + }, + { + "guid": "d4312cd9-5c90-4f38-82e8-51da566790e8", + "name": "Reports", + "description": "Generate reports of your media library", + "overview": "Generate reports of your media library", + "owner": "jellyfin", + "category": "General", + "versions": [ + { + "version": "11.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/reports/reports_11.0.0.0.zip", + "checksum": "d71bc6a4c008e58ee70ad44c83bfd310", + "timestamp": "2020-12-05T22:00:46Z" + }, + { + "version": "10.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/reports/reports_10.0.0.0.zip", + "checksum": "3917e75839337475b42daf2ba0b5bd7b", + "timestamp": "2020-10-19T19:30:41Z" + }, + { + "version": "9.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/reports/reports_9.0.0.0.zip", + "checksum": "5b5ad8d885616a21e8d1e8eecf5ea979", + "timestamp": "2020-10-16T23:52:37Z" + } + ] + }, + { + "guid": "1fc322a1-af2e-49a5-b2eb-a89b4240f700", + "name": "ServerWMC", + "description": "Provides access to Live TV, Program Guide and Recordings from your Windows MediaCenter Server running ServerWMC. Requires ServerWMC to be installed and running on your Windows MediaCenter machine.\n", + "overview": "Jellyfin Live TV plugin for Windows MediaCenter with ServerWMC", + "owner": "jellyfin", + "category": "LiveTV", + "versions": [ + { + "version": "6.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/serverwmc/serverwmc_6.0.0.0.zip", + "checksum": "3120af0cea2c1cb8b7cf578d9b4b862c", + "timestamp": "2020-12-05T22:28:15Z" + }, + { + "version": "5.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/serverwmc/serverwmc_5.0.0.0.zip", + "checksum": "dc44b039aa1b66eaf40a44fbf02d37e2", + "timestamp": "2020-07-20T01:32:42Z" + } + ] + }, + { + "guid": "94fb77c3-55ad-4c50-bf4e-4e5497467b79", + "name": "Slack Notifications", + "description": "Get notifications via Slack.\n", + "overview": "Get notifications via Slack", + "owner": "jellyfin", + "category": "Notifications", + "versions": [ + { + "version": "7.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/slack-notifications/slack-notifications_7.0.0.0.zip", + "checksum": "1d5330a77ce7b2a9ac8e5d58088a012c", + "timestamp": "2020-12-05T22:40:02Z" + }, + { + "version": "6.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/slack-notifications/slack-notifications_6.0.0.0.zip", + "checksum": "ede4cbe064542d1ecccc5823921bee4b", + "timestamp": "2020-07-20T01:32:50Z" + } + ] + }, + { + "guid": "bc4aad2e-d3d0-4725-a5e2-fd07949e5b42", + "name": "TMDb Box Sets", + "description": "Automatically create movie box sets based on TMDb collections", + "overview": "Automatically create movie box sets based on TMDb collections", + "owner": "jellyfin", + "category": "Metadata", + "versions": [ + { + "version": "7.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/tmdb-box-sets/tmdb-box-sets_7.0.0.0.zip", + "checksum": "1551792e6af4d36f2cead01153c73cf0", + "timestamp": "2020-12-05T22:07:21Z" + }, + { + "version": "6.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/tmdb-box-sets/tmdb-box-sets_6.0.0.0.zip", + "checksum": "b92b68a922c5fcbb8f4d47b8601b01b6", + "timestamp": "2020-07-20T01:32:58Z" + } + ] + }, + { + "guid": "4fe3201e-d6ae-4f2e-8917-e12bda571281", + "name": "Trakt", + "description": "Record your watched media with Trakt.\n", + "overview": "Record your watched media with Trakt", + "owner": "jellyfin", + "category": "General", + "versions": [ + { + "version": "11.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/trakt/trakt_11.0.0.0.zip", + "checksum": "2257ccde1e39114644a27e0966a0bf2d", + "timestamp": "2020-12-05T19:56:12Z" + }, + { + "version": "10.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/trakt/trakt_10.0.0.0.zip", + "checksum": "ab67e6b59ea2e7860a6a3ff7b8452759", + "timestamp": "2020-07-20T01:33:06Z" + } + ] + }, + { + "guid": "3fd018e5-5e78-4e58-b280-a0c068febee0", + "name": "TVHeadend", + "description": "Manage TVHeadend from Jellyfin", + "overview": "Manage TVHeadend from Jellyfin", + "owner": "jellyfin", + "category": "LiveTV", + "versions": [ + { + "version": "7.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/tvheadend/tvheadend_7.0.0.0.zip", + "checksum": "1abbfce737b6962f4b1b2255dc63e932", + "timestamp": "2021-01-05T16:20:33Z" + }, + { + "version": "6.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/tvheadend/tvheadend_6.0.0.0.zip", + "checksum": "143c34fd70d7173b8912cc03ce4b517d", + "timestamp": "2020-07-20T01:33:15Z" + } + ] + }, + { + "guid": "022a3003-993f-45f1-8565-87d12af2e12a", + "name": "InfuseSync", + "description": "This plugin will track all media changes while any Infuse clients are offline to decrease sync times when logging back in to your server.", + "overview": "Blazing fast indexing for Infuse", + "owner": "Firecore LLC", + "category": "General", + "versions": [ + { + "version": "1.2.4.0", + "changelog": "New Playlist support.\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://github.com/firecore/InfuseSync/releases/download/v1.2.4/InfuseSync-jellyfin-1.2.4.zip", + "checksum": "7adde11b8c8404fd2923f59d98fb1a30", + "timestamp": "2020-10-12T08:00:00Z" + }, + { + "version": "1.2.1.3", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://github.com/firecore/InfuseSync/releases/download/v1.2.3/InfuseSync-jellyfin-1.2.3.zip", + "checksum": "d8e2c5fe736a302097bb3bac3d04b1c4", + "timestamp": "2020-09-18T12:19:00Z" + }, + { + "version": "1.2.1.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://github.com/firecore/InfuseSync/releases/download/v1.2.1/InfuseSync-jellyfin-1.2.1.zip", + "checksum": "1a853e926cc422f5d79d398d9ae18ee8", + "timestamp": "2020-08-21T10:48:00Z" + }, + { + "version": "1.2.0.0", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://github.com/firecore/InfuseSync/releases/download/v1.2.0/InfuseSync-jellyfin-1.2.0.zip", + "checksum": "2d3c7859852695a7f05adc6d3fcbc783", + "timestamp": "2020-07-20T11:51:00Z" + } + ] + }, + { + "guid": "8119f3c6-cfc2-4d9c-a0ba-028f1d93e526", + "name": "Cover Art Archive", + "description": "This plugin provides images from the Cover Art Archive https://musicbrainz.org/doc/Cover_Art_Archive and depends on the MusicBrainz metadata provider to know what images belong where\n", + "overview": "MusicBrainz Cover Art Archive", + "owner": "jellyfin", + "category": "Metadata", + "versions": [ + { + "version": "2.0.0.0", + "changelog": "changelog\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/cover-art-archive/cover-art-archive_2.0.0.0.zip", + "checksum": "bea8fa4a37b3e7ed74e22266e7597a68", + "timestamp": "2020-12-06T02:51:03Z" + }, + { + "version": "1.0.0.3", + "changelog": "changelog\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/cover-art-archive/cover-art-archive_1.0.0.3.zip", + "checksum": "c502a5c54b168810614c1c40709b9598", + "timestamp": "2020-08-06T21:21:22Z" + } + ] + }, + { + "guid": "A4A488D0-17A3-4919-8D82-7F3DE4F6B209", + "name": "TV Maze", + "description": "Get TV metadata from TV Maze\n", + "overview": "Get TV metadata from TV Maze", + "owner": "jellyfin", + "category": "Metadata", + "versions": [ + { + "version": "5.0.0.0", + "changelog": "Get additional image types\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/tv-maze/tv-maze_5.0.0.0.zip", + "checksum": "509a85e40b1d1ac36eef45673deaf606", + "timestamp": "2020-12-06T02:51:56Z" + }, + { + "version": "4.0.0.0", + "changelog": "Get additional image types\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/tv-maze/tv-maze_4.0.0.0.zip", + "checksum": "58ee9ab3f129151bdfff033ad889ad87", + "timestamp": "2020-11-24T14:44:37Z" + }, + { + "version": "3.0.0.0", + "changelog": "Remove unused dependencies \n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/tv-maze/tv-maze_3.0.0.0.zip", + "checksum": "f3b2c70b3e136fb15c917e4420f4fdec", + "timestamp": "2020-11-09T14:32:56Z" + }, + { + "version": "2.0.0.0", + "changelog": "Remove unused dependencies \n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/tv-maze/tv-maze_2.0.0.0.zip", + "checksum": "c7662ae8ae52ce8a4e8d685d55f36e80", + "timestamp": "2020-11-09T02:33:11Z" + }, + { + "version": "1.0.0.0", + "changelog": "Initial release.\n", + "targetAbi": "10.6.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/tv-maze/tv-maze_1.0.0.0.zip", + "checksum": "c90eee48c12f2c07880b4b28e507fd14", + "timestamp": "2020-11-08T19:05:32Z" + } + ] + }, + { + "guid": "a677c0da-fac5-4cde-941a-7134223f14c8", + "name": "TheTVDB", + "description": "Get TV metadata from TheTvdb\n", + "overview": "Get TV metadata from TheTvdb", + "owner": "jellyfin", + "category": "Metadata", + "versions": [ + { + "version": "2.0.0.0", + "changelog": "Remove from Jellyfin core.\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/thetvdb/thetvdb_2.0.0.0.zip", + "checksum": "e46cee334476a1b475e5c553171c4cb6", + "timestamp": "2020-12-16T20:03:28Z" + }, + { + "version": "1.0.0.0", + "changelog": "Remove from Jellyfin core.\n", + "targetAbi": "10.7.0.0", + "sourceUrl": "https://repo.jellyfin.org/releases/plugin/thetvdb/thetvdb_1.0.0.0.zip", + "checksum": "5a3dca5c0db4824d83bfd4e7e2b7bf11", + "timestamp": "2020-12-06T02:56:40Z" + } + ] + } +] \ No newline at end of file diff --git a/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs new file mode 100644 index 000000000..4fa64d8a2 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using System.IO; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using AutoFixture; +using AutoFixture.AutoMoq; +using Emby.Server.Implementations.Updates; +using MediaBrowser.Model.Updates; +using Moq; +using Moq.Protected; +using Xunit; + +namespace Jellyfin.Server.Implementations.Tests.Updates +{ + public class InstallationManagerTests + { + private readonly Fixture _fixture; + private readonly InstallationManager _installationManager; + + public InstallationManagerTests() + { + var messageHandler = new Mock(); + messageHandler.Protected() + .Setup>("SendAsync", ItExpr.IsAny(), ItExpr.IsAny()) + .Returns( + (m, _) => + { + return Task.FromResult(new HttpResponseMessage() + { + Content = new StreamContent(File.OpenRead("Test Data/Updates/" + m.RequestUri?.Segments[^1])) + }); + }); + + var http = new Mock(); + http.Setup(x => x.CreateClient(It.IsAny())) + .Returns(new HttpClient(messageHandler.Object)); + _fixture = new Fixture(); + _fixture.Customize(new AutoMoqCustomization + { + ConfigureMembers = true + }).Inject(http); + _installationManager = _fixture.Create(); + } + + [Fact] + public async Task GetPackages_Valid_Success() + { + IList packages = await _installationManager.GetPackages( + "Jellyfin Stable", + "https://repo.jellyfin.org/releases/plugin/manifest-stable.json", + false); + + Assert.Equal(25, packages.Count); + } + } +} -- cgit v1.2.3 From 032d72a8a7a1c3884d07b0f3b7bd93790988d414 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 23 Feb 2021 17:30:24 +0100 Subject: Pls fix race condition --- Emby.Server.Implementations/ApplicationHost.cs | 10 ++++++---- Jellyfin.Server/Program.cs | 2 +- tests/Jellyfin.Api.Tests/JellyfinApplicationFactory.cs | 5 +++-- 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 0a7c5c1fb..d7ac8bc3b 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -126,7 +126,6 @@ namespace Emby.Server.Implementations private IMediaEncoder _mediaEncoder; private ISessionManager _sessionManager; private string[] _urlPrefixes; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); /// /// Gets a value indicating whether this instance can self restart. @@ -484,8 +483,9 @@ namespace Emby.Server.Implementations /// Runs the startup tasks. /// /// . - public async Task RunStartupTasksAsync() + public async Task RunStartupTasksAsync(CancellationToken cancellationToken) { + cancellationToken.ThrowIfCancellationRequested(); Logger.LogInformation("Running startup tasks"); Resolve().AddTasks(GetExports(false)); @@ -501,13 +501,15 @@ namespace Emby.Server.Implementations var stopWatch = new Stopwatch(); stopWatch.Start(); - await Task.WhenAll(StartEntryPoints(entryPoints, true)).ConfigureAwait(false); + cancellationToken.ThrowIfCancellationRequested(); + await Task.WhenAny(Task.WhenAll(StartEntryPoints(entryPoints, true)), Task.Delay(-1, cancellationToken)).ConfigureAwait(false); Logger.LogInformation("Executed all pre-startup entry points in {Elapsed:g}", stopWatch.Elapsed); Logger.LogInformation("Core startup complete"); CoreStartupHasCompleted = true; stopWatch.Restart(); - await Task.WhenAll(StartEntryPoints(entryPoints, false)).ConfigureAwait(false); + cancellationToken.ThrowIfCancellationRequested(); + await Task.WhenAny(Task.WhenAll(StartEntryPoints(entryPoints, false)), Task.Delay(-1, cancellationToken)).ConfigureAwait(false); Logger.LogInformation("Executed all post-startup entry points in {Elapsed:g}", stopWatch.Elapsed); stopWatch.Stop(); } diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index f05cdfe9b..81199c775 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -202,7 +202,7 @@ namespace Jellyfin.Server throw; } - await appHost.RunStartupTasksAsync().ConfigureAwait(false); + await appHost.RunStartupTasksAsync(_tokenSource.Token).ConfigureAwait(false); stopWatch.Stop(); diff --git a/tests/Jellyfin.Api.Tests/JellyfinApplicationFactory.cs b/tests/Jellyfin.Api.Tests/JellyfinApplicationFactory.cs index dbbd5ac28..ab7e0b6e7 100644 --- a/tests/Jellyfin.Api.Tests/JellyfinApplicationFactory.cs +++ b/tests/Jellyfin.Api.Tests/JellyfinApplicationFactory.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Concurrent; using System.IO; +using System.Threading; using Emby.Server.Implementations; using Emby.Server.Implementations.IO; using Jellyfin.Server; @@ -21,7 +22,7 @@ namespace Jellyfin.Api.Tests public class JellyfinApplicationFactory : WebApplicationFactory { private static readonly string _testPathRoot = Path.Combine(Path.GetTempPath(), "jellyfin-test-data"); - private static readonly ConcurrentBag _disposableComponents = new ConcurrentBag(); + private readonly ConcurrentBag _disposableComponents = new ConcurrentBag(); /// /// Initializes a new instance of the class. @@ -96,7 +97,7 @@ namespace Jellyfin.Api.Tests var appHost = (TestAppHost)testServer.Services.GetRequiredService(); appHost.ServiceProvider = testServer.Services; appHost.InitializeServices().GetAwaiter().GetResult(); - appHost.RunStartupTasksAsync().GetAwaiter().GetResult(); + appHost.RunStartupTasksAsync(CancellationToken.None).GetAwaiter().GetResult(); return testServer; } -- cgit v1.2.3 From 2bc1eef4ddb23385f90c8bfc6af2ecf9888d7879 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 24 Feb 2021 22:18:59 +0100 Subject: Clean up code --- Emby.Server.Implementations/ApplicationHost.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index d7ac8bc3b..b1c20815e 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -499,17 +499,22 @@ namespace Emby.Server.Implementations var entryPoints = GetExports(); + cancellationToken.ThrowIfCancellationRequested(); + var stopWatch = new Stopwatch(); stopWatch.Start(); - cancellationToken.ThrowIfCancellationRequested(); - await Task.WhenAny(Task.WhenAll(StartEntryPoints(entryPoints, true)), Task.Delay(-1, cancellationToken)).ConfigureAwait(false); + + await Task.WhenAll(StartEntryPoints(entryPoints, true)).ConfigureAwait(false); Logger.LogInformation("Executed all pre-startup entry points in {Elapsed:g}", stopWatch.Elapsed); Logger.LogInformation("Core startup complete"); CoreStartupHasCompleted = true; - stopWatch.Restart(); + cancellationToken.ThrowIfCancellationRequested(); - await Task.WhenAny(Task.WhenAll(StartEntryPoints(entryPoints, false)), Task.Delay(-1, cancellationToken)).ConfigureAwait(false); + + stopWatch.Restart(); + + await Task.WhenAll(StartEntryPoints(entryPoints, false)).ConfigureAwait(false); Logger.LogInformation("Executed all post-startup entry points in {Elapsed:g}", stopWatch.Elapsed); stopWatch.Stop(); } -- cgit v1.2.3 From 0a1b91f084ec9eb7db5a341b9699c41c340d644a Mon Sep 17 00:00:00 2001 From: Eben van Deventer Date: Fri, 26 Feb 2021 15:53:55 +0000 Subject: Translated using Weblate (Afrikaans) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/af/ --- Emby.Server.Implementations/Localization/Core/af.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/af.json b/Emby.Server.Implementations/Localization/Core/af.json index 977a1c2d7..b029b7042 100644 --- a/Emby.Server.Implementations/Localization/Core/af.json +++ b/Emby.Server.Implementations/Localization/Core/af.json @@ -112,5 +112,8 @@ "TaskRefreshLibraryDescription": "Skandeer u media versameling vir nuwe lêers en verfris metadata.", "TaskRefreshLibrary": "Skandeer Media Versameling", "TaskRefreshChapterImagesDescription": "Maak kleinkiekeis (fotos) vir films wat hoofstukke het.", - "TaskRefreshChapterImages": "Verkry Hoofstuk Beelde" + "TaskRefreshChapterImages": "Verkry Hoofstuk Beelde", + "Undefined": "Ongedefineerd", + "Forced": "Geforseer", + "Default": "Oorspronklik" } -- cgit v1.2.3 From a25e3c02568b5632278e23d6168efa927b29eda9 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sat, 27 Feb 2021 13:56:21 +0000 Subject: fix for override ports contained in PublishedServerUrl --- Emby.Dlna/Main/DlnaEntryPoint.cs | 9 ++++++--- Emby.Server.Implementations/ApplicationHost.cs | 10 ++++++++++ MediaBrowser.Controller/IServerApplicationHost.cs | 5 +++++ 3 files changed, 21 insertions(+), 3 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 82490ec31..2652e6245 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -313,9 +313,12 @@ namespace Emby.Dlna.Main _logger.LogInformation("Registering publisher for {0} on {1}", fullService, address); var uri = new UriBuilder(_appHost.GetSmartApiUrl(address.Address) + descriptorUri); - // DLNA will only work over http, so we must reset to http:// : {port} - uri.Scheme = "http://"; - uri.Port = _netConfig.HttpServerPortNumber; + if (string.IsNullOrEmpty(_appHost.PublishedServerUrl)) + { + // DLNA will only work over http, so we must reset to http:// : {port}. + uri.Scheme = "http"; + uri.Port = _netConfig.HttpServerPortNumber; + } var device = new SsdpRootDevice { diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 1b9bb86bb..604f69986 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -135,6 +135,11 @@ namespace Emby.Server.Implementations public bool CoreStartupHasCompleted { get; private set; } + /// + /// Gets a value indicating whether this instance has a custom published url. + /// + public Uri PublishedServerUrl => _startupOptions.PublishedServerUrl; + public virtual bool CanLaunchWebBrowser { get @@ -1141,6 +1146,11 @@ namespace Emby.Server.Implementations /// public bool ListenWithHttps => Certificate != null && ServerConfigurationManager.GetNetworkConfiguration().EnableHttps; + public string GetStartupOption(string propName) + { + return _startupOptions.GetType().GetProperty(propName).GetValue(src, null); + } + /// public string GetSmartApiUrl(IPAddress ipAddress, int? port = null) { diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 92b2d43ce..b6f049391 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -52,6 +52,11 @@ namespace MediaBrowser.Controller /// The name of the friendly. string FriendlyName { get; } + /// + /// Gets a value indicating whether this instance has a custom published url. + /// + Uri PublishedServerUrl { get; } + /// /// Gets the system info. /// -- cgit v1.2.3 From d95ca20fc731cf51e060c7ba6802821b6dd8c48f Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sat, 27 Feb 2021 14:05:13 +0000 Subject: removed bad merge code --- Emby.Dlna/Main/DlnaEntryPoint.cs | 2 +- Emby.Server.Implementations/ApplicationHost.cs | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 2652e6245..797045857 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -313,7 +313,7 @@ namespace Emby.Dlna.Main _logger.LogInformation("Registering publisher for {0} on {1}", fullService, address); var uri = new UriBuilder(_appHost.GetSmartApiUrl(address.Address) + descriptorUri); - if (string.IsNullOrEmpty(_appHost.PublishedServerUrl)) + if (_appHost.PublishedServerUrl == null) { // DLNA will only work over http, so we must reset to http:// : {port}. uri.Scheme = "http"; diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 604f69986..56aa5a007 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1146,11 +1146,6 @@ namespace Emby.Server.Implementations /// public bool ListenWithHttps => Certificate != null && ServerConfigurationManager.GetNetworkConfiguration().EnableHttps; - public string GetStartupOption(string propName) - { - return _startupOptions.GetType().GetProperty(propName).GetValue(src, null); - } - /// public string GetSmartApiUrl(IPAddress ipAddress, int? port = null) { -- cgit v1.2.3 From 73ca367bf9419b47e6be9487971bce90aec6b82d Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sat, 27 Feb 2021 17:34:48 +0000 Subject: Update Emby.Server.Implementations/ApplicationHost.cs Co-authored-by: Cody Robibero --- Emby.Server.Implementations/ApplicationHost.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 56aa5a007..cddd60079 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -135,9 +135,7 @@ namespace Emby.Server.Implementations public bool CoreStartupHasCompleted { get; private set; } - /// - /// Gets a value indicating whether this instance has a custom published url. - /// + /// public Uri PublishedServerUrl => _startupOptions.PublishedServerUrl; public virtual bool CanLaunchWebBrowser -- cgit v1.2.3 From f666b7e10268a5c19228d8fdb1bd313a642b0915 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sat, 27 Feb 2021 20:12:55 +0000 Subject: fix --- Emby.Server.Implementations/ApplicationHost.cs | 22 ++++++++++++++++------ Emby.Server.Implementations/IStartupOptions.cs | 12 ++++++------ Jellyfin.Server/CoreAppHost.cs | 4 ++++ Jellyfin.Server/Program.cs | 1 + Jellyfin.Server/StartupOptions.cs | 4 ++-- .../JellyfinApplicationFactory.cs | 2 ++ 6 files changed, 31 insertions(+), 14 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 1b9bb86bb..785a3e89c 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -99,6 +99,7 @@ using MediaBrowser.Providers.Subtitles; using MediaBrowser.XbmcMetadata.Providers; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Prometheus.DotNetRuntime; @@ -118,6 +119,7 @@ namespace Emby.Server.Implementations private static readonly string[] _relevantEnvVarPrefixes = { "JELLYFIN_", "DOTNET_", "ASPNETCORE_" }; private readonly IFileSystem _fileSystemManager; + private readonly IConfiguration _startupConfig; private readonly IXmlSerializer _xmlSerializer; private readonly IStartupOptions _startupOptions; private readonly IPluginManager _pluginManager; @@ -228,6 +230,11 @@ namespace Emby.Server.Implementations /// public int HttpsPort { get; private set; } + /// + /// Gets the PublishedServerUrl setting. + /// + public string PublishedServerUrl => _startupOptions.PublishedServerUrl ?? _startupConfig["PublishedServerUrl"]; + /// /// Gets the server configuration manager. /// @@ -240,12 +247,14 @@ namespace Emby.Server.Implementations /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// The interface. /// Instance of the interface. /// Instance of the interface. public ApplicationHost( IServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, IStartupOptions options, + IConfiguration startupConfig, IFileSystem fileSystem, IServiceCollection serviceCollection) { @@ -268,6 +277,7 @@ namespace Emby.Server.Implementations Logger = LoggerFactory.CreateLogger(); _startupOptions = options; + _startupConfig = startupConfig; // Initialize runtime stat collection if (ServerConfigurationManager.Configuration.EnableMetrics) @@ -1145,10 +1155,10 @@ namespace Emby.Server.Implementations public string GetSmartApiUrl(IPAddress ipAddress, int? port = null) { // Published server ends with a / - if (_startupOptions.PublishedServerUrl != null) + if (!string.IsNullOrEmpty(PublishedServerUrl)) { // Published server ends with a '/', so we need to remove it. - return _startupOptions.PublishedServerUrl.ToString().Trim('/'); + return PublishedServerUrl.Trim('/'); } string smart = NetManager.GetBindInterface(ipAddress, out port); @@ -1165,10 +1175,10 @@ namespace Emby.Server.Implementations public string GetSmartApiUrl(HttpRequest request, int? port = null) { // Published server ends with a / - if (_startupOptions.PublishedServerUrl != null) + if (!string.IsNullOrEmpty(PublishedServerUrl)) { // Published server ends with a '/', so we need to remove it. - return _startupOptions.PublishedServerUrl.ToString().Trim('/'); + return PublishedServerUrl.Trim('/'); } string smart = NetManager.GetBindInterface(request, out port); @@ -1185,10 +1195,10 @@ namespace Emby.Server.Implementations public string GetSmartApiUrl(string hostname, int? port = null) { // Published server ends with a / - if (_startupOptions.PublishedServerUrl != null) + if (!string.IsNullOrEmpty(PublishedServerUrl)) { // Published server ends with a '/', so we need to remove it. - return _startupOptions.PublishedServerUrl.ToString().Trim('/'); + return PublishedServerUrl.Trim('/'); } string smart = NetManager.GetBindInterface(hostname, out port); diff --git a/Emby.Server.Implementations/IStartupOptions.cs b/Emby.Server.Implementations/IStartupOptions.cs index 4bef59543..0b823ff06 100644 --- a/Emby.Server.Implementations/IStartupOptions.cs +++ b/Emby.Server.Implementations/IStartupOptions.cs @@ -1,5 +1,5 @@ #pragma warning disable CS1591 - +#nullable enable using System; namespace Emby.Server.Implementations @@ -9,7 +9,7 @@ namespace Emby.Server.Implementations /// /// Gets the value of the --ffmpeg command line option. /// - string FFmpegPath { get; } + string? FFmpegPath { get; } /// /// Gets the value of the --service command line option. @@ -19,21 +19,21 @@ namespace Emby.Server.Implementations /// /// Gets the value of the --package-name command line option. /// - string PackageName { get; } + string? PackageName { get; } /// /// Gets the value of the --restartpath command line option. /// - string RestartPath { get; } + string? RestartPath { get; } /// /// Gets the value of the --restartargs command line option. /// - string RestartArgs { get; } + string? RestartArgs { get; } /// /// Gets the value of the --published-server-url command line option. /// - Uri PublishedServerUrl { get; } + string? PublishedServerUrl { get; } } } diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index b76aa5e14..1daa32dee 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -21,6 +21,7 @@ using MediaBrowser.Controller.Net; using MediaBrowser.Model.Activity; using MediaBrowser.Model.IO; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -37,18 +38,21 @@ namespace Jellyfin.Server /// The to be used by the . /// The to be used by the . /// The to be used by the . + /// The to be used by the . /// The to be used by the . /// The to be used by the . public CoreAppHost( IServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, IStartupOptions options, + IConfiguration startupConfig, IFileSystem fileSystem, IServiceCollection collection) : base( applicationPaths, loggerFactory, options, + startupConfig, fileSystem, collection) { diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index f05cdfe9b..18aa91ee1 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -164,6 +164,7 @@ namespace Jellyfin.Server appPaths, _loggerFactory, options, + startupConfig, new ManagedFileSystem(_loggerFactory.CreateLogger(), appPaths), serviceCollection); diff --git a/Jellyfin.Server/StartupOptions.cs b/Jellyfin.Server/StartupOptions.cs index b63434092..6d8210527 100644 --- a/Jellyfin.Server/StartupOptions.cs +++ b/Jellyfin.Server/StartupOptions.cs @@ -77,7 +77,7 @@ namespace Jellyfin.Server /// [Option("published-server-url", Required = false, HelpText = "Jellyfin Server URL to publish via auto discover process")] - public Uri? PublishedServerUrl { get; set; } + public string? PublishedServerUrl { get; set; } /// /// Gets the command line options as a dictionary that can be used in the .NET configuration system. @@ -94,7 +94,7 @@ namespace Jellyfin.Server if (PublishedServerUrl != null) { - config.Add(UdpServer.AddressOverrideConfigKey, PublishedServerUrl.ToString()); + config.Add(UdpServer.AddressOverrideConfigKey, PublishedServerUrl); } if (FFmpegPath != null) diff --git a/tests/Jellyfin.Api.Tests/JellyfinApplicationFactory.cs b/tests/Jellyfin.Api.Tests/JellyfinApplicationFactory.cs index 54f8eb225..262e8f912 100644 --- a/tests/Jellyfin.Api.Tests/JellyfinApplicationFactory.cs +++ b/tests/Jellyfin.Api.Tests/JellyfinApplicationFactory.cs @@ -8,6 +8,7 @@ using MediaBrowser.Common; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Serilog; @@ -77,6 +78,7 @@ namespace Jellyfin.Api.Tests appPaths, loggerFactory, commandLineOpts, + new ConfigurationBuilder().Build(), new ManagedFileSystem(loggerFactory.CreateLogger(), appPaths), serviceCollection); _disposableComponents.Add(appHost); -- cgit v1.2.3 From 1d6f489f17919e557987b2616048dc8def790f43 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sun, 28 Feb 2021 10:11:37 +0000 Subject: comment change --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 785a3e89c..7740b4fc5 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -231,7 +231,7 @@ namespace Emby.Server.Implementations public int HttpsPort { get; private set; } /// - /// Gets the PublishedServerUrl setting. + /// Gets the value of the PublishedServerUrl setting. /// public string PublishedServerUrl => _startupOptions.PublishedServerUrl ?? _startupConfig["PublishedServerUrl"]; -- cgit v1.2.3 From 159ecb882f419e485a95e727b647f0e2cf6eeb3d Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sun, 28 Feb 2021 10:14:05 +0000 Subject: Fixed bad sync --- Emby.Server.Implementations/ApplicationHost.cs | 3 --- 1 file changed, 3 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 6880b1842..37047a4f7 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -137,9 +137,6 @@ namespace Emby.Server.Implementations public bool CoreStartupHasCompleted { get; private set; } - /// - public Uri PublishedServerUrl => _startupOptions.PublishedServerUrl; - public virtual bool CanLaunchWebBrowser { get -- cgit v1.2.3 From 16694b0cfcc51ba009a0aedce0d383ab010e8b99 Mon Sep 17 00:00:00 2001 From: David Date: Sat, 27 Feb 2021 22:46:03 +0100 Subject: Add nfo thumb tag support --- Emby.Server.Implementations/ApplicationHost.cs | 2 + .../Providers/MetadataResult.cs | 12 ++-- MediaBrowser.Providers/Manager/MetadataService.cs | 6 ++ MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 78 +++++++++++++++++++++- .../Parsers/EpisodeNfoParser.cs | 6 +- .../Parsers/MovieNfoParser.cs | 6 +- .../Parsers/SeasonNfoParser.cs | 6 +- .../Parsers/SeriesNfoParser.cs | 6 +- .../Providers/AlbumNfoProvider.cs | 8 ++- .../Providers/ArtistNfoProvider.cs | 8 ++- .../Providers/BaseVideoNfoProvider.cs | 9 ++- .../Providers/EpisodeNfoProvider.cs | 8 ++- .../Providers/MovieNfoProvider.cs | 6 +- .../Providers/MusicVideoNfoProvider.cs | 6 +- .../Providers/SeasonNfoProvider.cs | 8 ++- .../Providers/SeriesNfoProvider.cs | 8 ++- .../Providers/VideoNfoProvider.cs | 6 +- .../Parsers/EpisodeNfoProviderTests.cs | 11 ++- .../Parsers/MovieNfoParserTests.cs | 64 +++++++++++++++++- .../Parsers/MusicAlbumNfoProviderTests.cs | 11 ++- .../Parsers/MusicArtistNfoParserTests.cs | 9 ++- .../Parsers/MusicVideoNfoParserTests.cs | 9 ++- .../Parsers/SeasonNfoProviderTests.cs | 9 ++- .../Parsers/SeriesNfoParserTests.cs | 3 +- .../Test Data/Justice League.nfo | 2 + 25 files changed, 266 insertions(+), 41 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 1b9bb86bb..788e08e48 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -682,6 +682,8 @@ namespace Emby.Server.Implementations ServiceCollection.AddScoped(); ServiceCollection.AddScoped(); ServiceCollection.AddScoped(); + + ServiceCollection.AddSingleton(); } /// diff --git a/MediaBrowser.Controller/Providers/MetadataResult.cs b/MediaBrowser.Controller/Providers/MetadataResult.cs index 1c695cafa..864cb3050 100644 --- a/MediaBrowser.Controller/Providers/MetadataResult.cs +++ b/MediaBrowser.Controller/Providers/MetadataResult.cs @@ -4,21 +4,25 @@ using System; using System.Collections.Generic; using System.Globalization; using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Providers { public class MetadataResult { - public List Images { get; set; } - - public List UserDataList { get; set; } - public MetadataResult() { Images = new List(); + RemoteImages = new List<(string url, ImageType type)>(); ResultLanguage = "en"; } + public List Images { get; set; } + + public List<(string url, ImageType type)> RemoteImages { get; set; } + + public List UserDataList { get; set; } + public List People { get; set; } public bool HasMetadata { get; set; } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 8b3ca17ca..494e479a5 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -706,6 +706,12 @@ namespace MediaBrowser.Providers.Manager if (localItem.HasMetadata) { + foreach (var remoteImage in localItem.RemoteImages) + { + await ProviderManager.SaveImage(item, remoteImage.url, remoteImage.type, null, cancellationToken).ConfigureAwait(false); + refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.ImageUpdate; + } + if (imageService.MergeImages(item, localItem.Images)) { refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.ImageUpdate; diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 6f164caf3..aa89936d0 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -27,6 +27,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers private readonly IConfigurationManager _config; private readonly IUserManager _userManager; private readonly IUserDataManager _userDataManager; + private readonly IDirectoryService _directoryService; private Dictionary _validProviderIds; /// @@ -37,12 +38,14 @@ namespace MediaBrowser.XbmcMetadata.Parsers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public BaseNfoParser( ILogger logger, IConfigurationManager config, IProviderManager providerManager, IUserManager userManager, - IUserDataManager userDataManager) + IUserDataManager userDataManager, + IDirectoryService directoryService) { Logger = logger; _config = config; @@ -50,6 +53,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers _validProviderIds = new Dictionary(); _userManager = userManager; _userDataManager = userDataManager; + _directoryService = directoryService; } protected CultureInfo UsCulture { get; } = new CultureInfo("en-US"); @@ -785,6 +789,78 @@ namespace MediaBrowser.XbmcMetadata.Parsers break; } + case "thumb": + { + var artType = reader.GetAttribute("aspect"); + var val = reader.ReadElementContentAsString(); + + // skip: + // - empty aspect tag + // - empty uri + // - tag containing '.' because we can't set images for seasons, episodes or movie sets within series or movies + if (string.IsNullOrEmpty(artType) || string.IsNullOrEmpty(val) || artType.Contains('.', StringComparison.Ordinal)) + { + break; + } + + ImageType imageType = artType switch + { + "banner" => ImageType.Banner, + "clearlogo" => ImageType.Logo, + "discart" => ImageType.Disc, + "landscape" => ImageType.Thumb, + "clearart" => ImageType.Art, + // unknown type (including "poster") --> primary + _ => ImageType.Primary, + }; + + Uri uri; + try + { + uri = new Uri(val); + } + catch (UriFormatException ex) + { + Logger.LogError(ex, "Image location {Path} specified in nfo file for {ItemName} is not a valid URL or file path.", val, item.Name); + break; + } + + if (uri.IsFile) + { + // only allow one item of each type + if (itemResult.Images.Any(x => x.Type == imageType)) + { + break; + } + + var fileSystemMetadata = _directoryService.GetFile(val); + // non existing file returns null + if (fileSystemMetadata == null || !fileSystemMetadata.Exists) + { + Logger.LogWarning("Artwork file {Path} specified in nfo file for {ItemName} does not exist.", uri, item.Name); + break; + } + + itemResult.Images.Add(new LocalImageInfo() + { + FileInfo = fileSystemMetadata, + Type = imageType + }); + } + else + { + // only allow one item of each type + if (itemResult.RemoteImages.Any(x => x.type == imageType)) + { + break; + } + + itemResult.RemoteImages.Add((uri.ToString(), imageType)); + } + + break; + } + default: string readerName = reader.Name; if (_validProviderIds.TryGetValue(readerName, out string? providerIdValue)) diff --git a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs index f0c50d8e5..7ae55c791 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs @@ -25,13 +25,15 @@ namespace MediaBrowser.XbmcMetadata.Parsers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public EpisodeNfoParser( ILogger logger, IConfigurationManager config, IProviderManager providerManager, IUserManager userManager, - IUserDataManager userDataManager) - : base(logger, config, providerManager, userManager, userDataManager) + IUserDataManager userDataManager, + IDirectoryService directoryService) + : base(logger, config, providerManager, userManager, userDataManager, directoryService) { } diff --git a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs index 2d0eb8433..b466fa25a 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs @@ -25,13 +25,15 @@ namespace MediaBrowser.XbmcMetadata.Parsers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public MovieNfoParser( ILogger logger, IConfigurationManager config, IProviderManager providerManager, IUserManager userManager, - IUserDataManager userDataManager) - : base(logger, config, providerManager, userManager, userDataManager) + IUserDataManager userDataManager, + IDirectoryService directoryService) + : base(logger, config, providerManager, userManager, userDataManager, directoryService) { } diff --git a/MediaBrowser.XbmcMetadata/Parsers/SeasonNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/SeasonNfoParser.cs index bd2607bd8..2f5fd40e2 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/SeasonNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/SeasonNfoParser.cs @@ -21,13 +21,15 @@ namespace MediaBrowser.XbmcMetadata.Parsers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public SeasonNfoParser( ILogger logger, IConfigurationManager config, IProviderManager providerManager, IUserManager userManager, - IUserDataManager userDataManager) - : base(logger, config, providerManager, userManager, userDataManager) + IUserDataManager userDataManager, + IDirectoryService directoryService) + : base(logger, config, providerManager, userManager, userDataManager, directoryService) { } diff --git a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs index fbab8b521..f6574c365 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs @@ -22,13 +22,15 @@ namespace MediaBrowser.XbmcMetadata.Parsers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public SeriesNfoParser( ILogger logger, IConfigurationManager config, IProviderManager providerManager, IUserManager userManager, - IUserDataManager userDataManager) - : base(logger, config, providerManager, userManager, userDataManager) + IUserDataManager userDataManager, + IDirectoryService directoryService) + : base(logger, config, providerManager, userManager, userDataManager, directoryService) { } diff --git a/MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs index 24f127411..bd557d783 100644 --- a/MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs @@ -20,6 +20,7 @@ namespace MediaBrowser.XbmcMetadata.Providers private readonly IProviderManager _providerManager; private readonly IUserManager _userManager; private readonly IUserDataManager _userDataManager; + private readonly IDirectoryService _directoryService; /// /// Initializes a new instance of the class. @@ -30,13 +31,15 @@ namespace MediaBrowser.XbmcMetadata.Providers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public AlbumNfoProvider( ILogger logger, IFileSystem fileSystem, IConfigurationManager config, IProviderManager providerManager, IUserManager userManager, - IUserDataManager userDataManager) + IUserDataManager userDataManager, + IDirectoryService directoryService) : base(fileSystem) { _logger = logger; @@ -44,12 +47,13 @@ namespace MediaBrowser.XbmcMetadata.Providers _providerManager = providerManager; _userManager = userManager; _userDataManager = userDataManager; + _directoryService = directoryService; } /// protected override void Fetch(MetadataResult result, string path, CancellationToken cancellationToken) { - new BaseNfoParser(_logger, _config, _providerManager, _userManager, _userDataManager).Fetch(result, path, cancellationToken); + new BaseNfoParser(_logger, _config, _providerManager, _userManager, _userDataManager, _directoryService).Fetch(result, path, cancellationToken); } /// diff --git a/MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs index fac28ab59..54bb83114 100644 --- a/MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs @@ -20,6 +20,7 @@ namespace MediaBrowser.XbmcMetadata.Providers private readonly IProviderManager _providerManager; private readonly IUserManager _userManager; private readonly IUserDataManager _userDataManager; + private readonly IDirectoryService _directoryService; /// /// Initializes a new instance of the class. @@ -30,13 +31,15 @@ namespace MediaBrowser.XbmcMetadata.Providers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public ArtistNfoProvider( IFileSystem fileSystem, ILogger logger, IConfigurationManager config, IProviderManager providerManager, IUserManager userManager, - IUserDataManager userDataManager) + IUserDataManager userDataManager, + IDirectoryService directoryService) : base(fileSystem) { _logger = logger; @@ -44,12 +47,13 @@ namespace MediaBrowser.XbmcMetadata.Providers _providerManager = providerManager; _userManager = userManager; _userDataManager = userDataManager; + _directoryService = directoryService; } /// protected override void Fetch(MetadataResult result, string path, CancellationToken cancellationToken) { - new BaseNfoParser(_logger, _config, _providerManager, _userManager, _userDataManager).Fetch(result, path, cancellationToken); + new BaseNfoParser(_logger, _config, _providerManager, _userManager, _userDataManager, _directoryService).Fetch(result, path, cancellationToken); } /// diff --git a/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs index af722748b..b8f76f31d 100644 --- a/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs @@ -21,6 +21,7 @@ namespace MediaBrowser.XbmcMetadata.Providers private readonly IProviderManager _providerManager; private readonly IUserManager _userManager; private readonly IUserDataManager _userDataManager; + private readonly IDirectoryService _directoryService; public BaseVideoNfoProvider( ILogger> logger, @@ -28,7 +29,8 @@ namespace MediaBrowser.XbmcMetadata.Providers IConfigurationManager config, IProviderManager providerManager, IUserManager userManager, - IUserDataManager userDataManager) + IUserDataManager userDataManager, + IDirectoryService directoryService) : base(fileSystem) { _logger = logger; @@ -36,6 +38,7 @@ namespace MediaBrowser.XbmcMetadata.Providers _providerManager = providerManager; _userManager = userManager; _userDataManager = userDataManager; + _directoryService = directoryService; } /// @@ -45,10 +48,12 @@ namespace MediaBrowser.XbmcMetadata.Providers { Item = result.Item }; - new MovieNfoParser(_logger, _config, _providerManager, _userManager, _userDataManager).Fetch(tmpItem, path, cancellationToken); + new MovieNfoParser(_logger, _config, _providerManager, _userManager, _userDataManager, _directoryService).Fetch(tmpItem, path, cancellationToken); result.Item = (T)tmpItem.Item; result.People = tmpItem.People; + result.Images = tmpItem.Images; + result.RemoteImages = tmpItem.RemoteImages; if (tmpItem.UserDataList != null) { diff --git a/MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs index 7233f99dc..64b208345 100644 --- a/MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs @@ -20,6 +20,7 @@ namespace MediaBrowser.XbmcMetadata.Providers private readonly IProviderManager _providerManager; private readonly IUserManager _userManager; private readonly IUserDataManager _userDataManager; + private readonly IDirectoryService _directoryService; /// /// Initializes a new instance of the class. @@ -30,13 +31,15 @@ namespace MediaBrowser.XbmcMetadata.Providers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public EpisodeNfoProvider( ILogger logger, IFileSystem fileSystem, IConfigurationManager config, IProviderManager providerManager, IUserManager userManager, - IUserDataManager userDataManager) + IUserDataManager userDataManager, + IDirectoryService directoryService) : base(fileSystem) { _logger = logger; @@ -44,12 +47,13 @@ namespace MediaBrowser.XbmcMetadata.Providers _providerManager = providerManager; _userManager = userManager; _userDataManager = userDataManager; + _directoryService = directoryService; } /// protected override void Fetch(MetadataResult result, string path, CancellationToken cancellationToken) { - new EpisodeNfoParser(_logger, _config, _providerManager, _userManager, _userDataManager).Fetch(result, path, cancellationToken); + new EpisodeNfoParser(_logger, _config, _providerManager, _userManager, _userDataManager, _directoryService).Fetch(result, path, cancellationToken); } /// diff --git a/MediaBrowser.XbmcMetadata/Providers/MovieNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/MovieNfoProvider.cs index 811d39a9d..cdbc5a918 100644 --- a/MediaBrowser.XbmcMetadata/Providers/MovieNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/MovieNfoProvider.cs @@ -21,14 +21,16 @@ namespace MediaBrowser.XbmcMetadata.Providers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public MovieNfoProvider( ILogger logger, IFileSystem fileSystem, IConfigurationManager config, IProviderManager providerManager, IUserManager userManager, - IUserDataManager userDataManager) - : base(logger, fileSystem, config, providerManager, userManager, userDataManager) + IUserDataManager userDataManager, + IDirectoryService directoryService) + : base(logger, fileSystem, config, providerManager, userManager, userDataManager, directoryService) { } } diff --git a/MediaBrowser.XbmcMetadata/Providers/MusicVideoNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/MusicVideoNfoProvider.cs index 09df509ee..9d1f3e61d 100644 --- a/MediaBrowser.XbmcMetadata/Providers/MusicVideoNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/MusicVideoNfoProvider.cs @@ -21,14 +21,16 @@ namespace MediaBrowser.XbmcMetadata.Providers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public MusicVideoNfoProvider( ILogger logger, IFileSystem fileSystem, IConfigurationManager config, IProviderManager providerManager, IUserManager userManager, - IUserDataManager userDataManager) - : base(logger, fileSystem, config, providerManager, userManager, userDataManager) + IUserDataManager userDataManager, + IDirectoryService directoryService) + : base(logger, fileSystem, config, providerManager, userManager, userDataManager, directoryService) { } } diff --git a/MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs index 8f0ed6df7..97220cf7e 100644 --- a/MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs @@ -20,6 +20,7 @@ namespace MediaBrowser.XbmcMetadata.Providers private readonly IProviderManager _providerManager; private readonly IUserManager _userManager; private readonly IUserDataManager _userDataManager; + private readonly IDirectoryService _directoryService; /// /// Initializes a new instance of the class. @@ -30,13 +31,15 @@ namespace MediaBrowser.XbmcMetadata.Providers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public SeasonNfoProvider( ILogger logger, IFileSystem fileSystem, IConfigurationManager config, IProviderManager providerManager, IUserManager userManager, - IUserDataManager userDataManager) + IUserDataManager userDataManager, + IDirectoryService directoryService) : base(fileSystem) { _logger = logger; @@ -44,12 +47,13 @@ namespace MediaBrowser.XbmcMetadata.Providers _providerManager = providerManager; _userManager = userManager; _userDataManager = userDataManager; + _directoryService = directoryService; } /// protected override void Fetch(MetadataResult result, string path, CancellationToken cancellationToken) { - new SeasonNfoParser(_logger, _config, _providerManager, _userManager, _userDataManager).Fetch(result, path, cancellationToken); + new SeasonNfoParser(_logger, _config, _providerManager, _userManager, _userDataManager, _directoryService).Fetch(result, path, cancellationToken); } /// diff --git a/MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs index 3e496dc58..9a9b94123 100644 --- a/MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs @@ -20,6 +20,7 @@ namespace MediaBrowser.XbmcMetadata.Providers private readonly IProviderManager _providerManager; private readonly IUserManager _userManager; private readonly IUserDataManager _userDataManager; + private readonly IDirectoryService _directoryService; /// /// Initializes a new instance of the class. @@ -30,13 +31,15 @@ namespace MediaBrowser.XbmcMetadata.Providers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public SeriesNfoProvider( ILogger logger, IFileSystem fileSystem, IConfigurationManager config, IProviderManager providerManager, IUserManager userManager, - IUserDataManager userDataManager) + IUserDataManager userDataManager, + IDirectoryService directoryService) : base(fileSystem) { _logger = logger; @@ -44,12 +47,13 @@ namespace MediaBrowser.XbmcMetadata.Providers _providerManager = providerManager; _userManager = userManager; _userDataManager = userDataManager; + _directoryService = directoryService; } /// protected override void Fetch(MetadataResult result, string path, CancellationToken cancellationToken) { - new SeriesNfoParser(_logger, _config, _providerManager, _userManager, _userDataManager).Fetch(result, path, cancellationToken); + new SeriesNfoParser(_logger, _config, _providerManager, _userManager, _userDataManager, _directoryService).Fetch(result, path, cancellationToken); } /// diff --git a/MediaBrowser.XbmcMetadata/Providers/VideoNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/VideoNfoProvider.cs index 4717d81e6..93b1be62f 100644 --- a/MediaBrowser.XbmcMetadata/Providers/VideoNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/VideoNfoProvider.cs @@ -21,14 +21,16 @@ namespace MediaBrowser.XbmcMetadata.Providers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public VideoNfoProvider( ILogger logger, IFileSystem fileSystem, IConfigurationManager config, IProviderManager providerManager, IUserManager userManager, - IUserDataManager userDataManager) - : base(logger, fileSystem, config, providerManager, userManager, userDataManager) + IUserDataManager userDataManager, + IDirectoryService directoryService) + : base(logger, fileSystem, config, providerManager, userManager, userDataManager, directoryService) { } } diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs index d10ef9b47..438684473 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs @@ -37,8 +37,15 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers .Returns(new XbmcMetadataOptions()); var user = new Mock(); var userData = new Mock(); - - _parser = new EpisodeNfoParser(new NullLogger(), config.Object, providerManager.Object, user.Object, userData.Object); + var directoryService = new Mock(); + + _parser = new EpisodeNfoParser( + new NullLogger(), + config.Object, + providerManager.Object, + user.Object, + userData.Object, + directoryService.Object); } [Fact] diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs index 76231391e..76e10b451 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs @@ -9,7 +9,9 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; using MediaBrowser.Model.Providers; +using MediaBrowser.Model.System; using MediaBrowser.Providers.Plugins.Tmdb.Movies; using MediaBrowser.XbmcMetadata.Parsers; using Microsoft.Extensions.Logging.Abstractions; @@ -23,6 +25,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers private readonly MovieNfoParser _parser; private readonly IUserDataManager _userDataManager; private readonly User _testUser; + private readonly FileSystemMetadata _localImageFileMetadata; public MovieNfoParserTests() { @@ -52,8 +55,36 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers userData.Setup(x => x.GetUserData(_testUser, It.IsAny())) .Returns(new UserItemData()); + var directoryService = new Mock(); + if (MediaBrowser.Common.System.OperatingSystem.Id != OperatingSystemId.Windows) + { + _localImageFileMetadata = new FileSystemMetadata() + { + Exists = true, + FullName = "/media/movies/Justice League (2017).jpg" + }; + directoryService.Setup(x => x.GetFile(_localImageFileMetadata.FullName)) + .Returns(_localImageFileMetadata); + } + else + { + _localImageFileMetadata = new FileSystemMetadata() + { + Exists = true, + FullName = "C:\\media\\movies\\Justice League (2017).jpg" + }; + directoryService.Setup(x => x.GetFile(_localImageFileMetadata.FullName)) + .Returns(_localImageFileMetadata); + } + _userDataManager = userData.Object; - _parser = new MovieNfoParser(new NullLogger(), configManager.Object, providerManager.Object, user.Object, userData.Object); + _parser = new MovieNfoParser( + new NullLogger(), + configManager.Object, + providerManager.Object, + user.Object, + userData.Object, + directoryService.Object); } [Fact] @@ -134,6 +165,37 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers // Movie set Assert.Equal("702342", item.ProviderIds[MetadataProvider.TmdbCollection.ToString()]); Assert.Equal("Justice League Collection", item.CollectionName); + + // Images + Assert.Equal(6, result.RemoteImages.Count); + + var posters = result.RemoteImages.Where(x => x.type == ImageType.Primary).ToList(); + Assert.Single(posters); + Assert.Equal("http://image.tmdb.org/t/p/original/9rtrRGeRnL0JKtu9IMBWsmlmmZz.jpg", posters[0].url); + + var logos = result.RemoteImages.Where(x => x.type == ImageType.Logo).ToList(); + Assert.Single(logos); + Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/hdmovielogo/justice-league-5865bf95cbadb.png", logos[0].url); + + var banners = result.RemoteImages.Where(x => x.type == ImageType.Banner).ToList(); + Assert.Single(banners); + Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/moviebanner/justice-league-586017e95adbd.jpg", banners[0].url); + + var thumbs = result.RemoteImages.Where(x => x.type == ImageType.Thumb).ToList(); + Assert.Single(thumbs); + Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/moviethumb/justice-league-585fb155c3743.jpg", thumbs[0].url); + + var art = result.RemoteImages.Where(x => x.type == ImageType.Art).ToList(); + Assert.Single(art); + Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/hdmovieclearart/justice-league-5865c23193041.png", art[0].url); + + var discArt = result.RemoteImages.Where(x => x.type == ImageType.Disc).ToList(); + Assert.Single(discArt); + Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/moviedisc/justice-league-5a3af26360617.png", discArt[0].url); + + // Local Image - contains only one item depending on operating system + Assert.Single(result.Images); + Assert.Equal(_localImageFileMetadata.Name, result.Images[0].FileInfo.Name); } [Theory] diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicAlbumNfoProviderTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicAlbumNfoProviderTests.cs index 2183d2a2f..29de2a95e 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicAlbumNfoProviderTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicAlbumNfoProviderTests.cs @@ -1,7 +1,6 @@ #pragma warning disable CA5369 using System; -using System.Linq; using System.Threading; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Entities.Audio; @@ -11,7 +10,6 @@ using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; using MediaBrowser.Providers.Music; -using MediaBrowser.Providers.Plugins.MusicBrainz; using MediaBrowser.XbmcMetadata.Parsers; using Microsoft.Extensions.Logging.Abstractions; using Moq; @@ -38,8 +36,15 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers .Returns(new XbmcMetadataOptions()); var user = new Mock(); var userData = new Mock(); + var directoryService = new Mock(); - _parser = new BaseNfoParser(new NullLogger>(), config.Object, providerManager.Object, user.Object, userData.Object); + _parser = new BaseNfoParser( + new NullLogger>(), + config.Object, + providerManager.Object, + user.Object, + userData.Object, + directoryService.Object); } [Fact] diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicArtistNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicArtistNfoParserTests.cs index f86b7604e..e54b35eb5 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicArtistNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicArtistNfoParserTests.cs @@ -35,8 +35,15 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers .Returns(new XbmcMetadataOptions()); var user = new Mock(); var userData = new Mock(); + var directoryService = new Mock(); - _parser = new BaseNfoParser(new NullLogger>(), config.Object, providerManager.Object, user.Object, userData.Object); + _parser = new BaseNfoParser( + new NullLogger>(), + config.Object, + providerManager.Object, + user.Object, + userData.Object, + directoryService.Object); } [Fact] diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicVideoNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicVideoNfoParserTests.cs index 898554936..bf887cab1 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicVideoNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicVideoNfoParserTests.cs @@ -30,8 +30,15 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers var user = new Mock(); var userData = new Mock(); + var directoryService = new Mock(); - _parser = new MovieNfoParser(new NullLogger>(), config.Object, providerManager.Object, user.Object, userData.Object); + _parser = new MovieNfoParser( + new NullLogger>(), + config.Object, + providerManager.Object, + user.Object, + userData.Object, + directoryService.Object); } [Fact] diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeasonNfoProviderTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeasonNfoProviderTests.cs index 602db7c09..c497d4fa2 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeasonNfoProviderTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeasonNfoProviderTests.cs @@ -31,8 +31,15 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers .Returns(new XbmcMetadataOptions()); var user = new Mock(); var userData = new Mock(); + var directoryService = new Mock(); - _parser = new SeasonNfoParser(new NullLogger(), config.Object, providerManager.Object, user.Object, userData.Object); + _parser = new SeasonNfoParser( + new NullLogger(), + config.Object, + providerManager.Object, + user.Object, + userData.Object, + directoryService.Object); } [Fact] diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeriesNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeriesNfoParserTests.cs index f8eb04b3a..7c7d698f0 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeriesNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeriesNfoParserTests.cs @@ -29,8 +29,9 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers .Returns(new XbmcMetadataOptions()); var user = new Mock(); var userData = new Mock(); + var directoryService = new Mock(); - _parser = new SeriesNfoParser(new NullLogger(), config.Object, providerManager.Object, user.Object, userData.Object); + _parser = new SeriesNfoParser(new NullLogger(), config.Object, providerManager.Object, user.Object, userData.Object, directoryService.Object); } [Fact] diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Test Data/Justice League.nfo b/tests/Jellyfin.XbmcMetadata.Tests/Test Data/Justice League.nfo index 72e27fe50..c35d37b18 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Test Data/Justice League.nfo +++ b/tests/Jellyfin.XbmcMetadata.Tests/Test Data/Justice League.nfo @@ -59,6 +59,8 @@ http://image.tmdb.org/t/p/original/exLtrlI7JjKcfQVTccI7XdQRFMz.jpg http://image.tmdb.org/t/p/original/paLcue01KpfQftorfjKqqD4qvlL.jpg http://image.tmdb.org/t/p/original/yVDIfiKIsCbdFcgLXW34bAsnQvy.jpg + C:\media\movies\Justice League (2017).jpg + /media/movies/Justice League (2017).jpg https://assets.fanart.tv/fanart/movies/141052/hdmovielogo/justice-league-5865bf95cbadb.png https://assets.fanart.tv/fanart/movies/141052/hdmovielogo/justice-league-585e9ca3bcf6a.png https://assets.fanart.tv/fanart/movies/141052/hdmovielogo/justice-league-57b476a831d74.png -- cgit v1.2.3 From 0fde0a82e4a914e1d9b4b9814d9f4942307a3c15 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 28 Feb 2021 12:12:37 +0000 Subject: Translated using Weblate (Swedish) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sv/ --- Emby.Server.Implementations/Localization/Core/sv.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/sv.json b/Emby.Server.Implementations/Localization/Core/sv.json index 345d41e9e..b5a7fa5b8 100644 --- a/Emby.Server.Implementations/Localization/Core/sv.json +++ b/Emby.Server.Implementations/Localization/Core/sv.json @@ -117,5 +117,6 @@ "TaskCleanActivityLogDescription": "Radera aktivitets logg inlägg som är äldre än definerad ålder.", "TaskCleanActivityLog": "Rensa Aktivitets Logg", "Undefined": "odefinierad", - "Forced": "Tvingad" + "Forced": "Tvingad", + "Default": "Standard" } -- cgit v1.2.3 From 4bbfcaef83579239a9bef708c71a889cb3d829b4 Mon Sep 17 00:00:00 2001 From: Moshe Schmidt Date: Wed, 17 Feb 2021 21:18:27 +0100 Subject: Include specials in the calculation for the "Next Up" episode. Fixes #1479 --- CONTRIBUTORS.md | 1 + .../Sorting/AiredEpisodeOrderComparer.cs | 4 +- Emby.Server.Implementations/TV/TVSeriesManager.cs | 46 ++++++++++++++++++---- 3 files changed, 41 insertions(+), 10 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 1200275d5..bcc27b4dd 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -104,6 +104,7 @@ - [shemanaev](https://github.com/shemanaev) - [skaro13](https://github.com/skaro13) - [sl1288](https://github.com/sl1288) + - [Smith00101010](https://github.com/Smith00101010) - [sorinyo2004](https://github.com/sorinyo2004) - [sparky8251](https://github.com/sparky8251) - [spookbits](https://github.com/spookbits) diff --git a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs index 1f68a9c81..60698e803 100644 --- a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -131,11 +131,11 @@ namespace Emby.Server.Implementations.Sorting return GetSpecialCompareValue(x).CompareTo(GetSpecialCompareValue(y)); } - private static int GetSpecialCompareValue(Episode item) + private static long GetSpecialCompareValue(Episode item) { // First sort by season number // Since there are three sort orders, pad with 9 digits (3 for each, figure 1000 episode buffer should be enough) - var val = (item.AirsAfterSeasonNumber ?? item.AirsBeforeSeasonNumber ?? 0) * 1000000000; + var val = (item.AirsAfterSeasonNumber ?? item.AirsBeforeSeasonNumber ?? 0) * 1000000000L; // Second sort order is if it airs after the season if (item.AirsAfterSeasonNumber.HasValue) diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index 839b62448..d111e1a1c 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; @@ -11,7 +10,6 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.TV; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using Episode = MediaBrowser.Controller.Entities.TV.Episode; using Series = MediaBrowser.Controller.Entities.TV.Series; @@ -23,12 +21,14 @@ namespace Emby.Server.Implementations.TV private readonly IUserManager _userManager; private readonly IUserDataManager _userDataManager; private readonly ILibraryManager _libraryManager; + private readonly IServerConfigurationManager _configurationManager; - public TVSeriesManager(IUserManager userManager, IUserDataManager userDataManager, ILibraryManager libraryManager) + public TVSeriesManager(IUserManager userManager, IUserDataManager userDataManager, ILibraryManager libraryManager, IServerConfigurationManager configurationManager) { _userManager = userManager; _userDataManager = userDataManager; _libraryManager = libraryManager; + _configurationManager = configurationManager; } public QueryResult GetNextUp(NextUpQuery request, DtoOptions dtoOptions) @@ -200,13 +200,10 @@ namespace Emby.Server.Implementations.TV ParentIndexNumberNotEquals = 0, DtoOptions = new DtoOptions { - Fields = new ItemFields[] - { - ItemFields.SortName - }, + Fields = new[] { ItemFields.SortName }, EnableImages = false } - }).FirstOrDefault(); + }).Cast().FirstOrDefault(); Func getEpisode = () => { @@ -224,6 +221,39 @@ namespace Emby.Server.Implementations.TV DtoOptions = dtoOptions }).Cast().FirstOrDefault(); + if (_configurationManager.Configuration.DisplaySpecialsWithinSeasons) + { + var consideredEpisodes = _libraryManager.GetItemList(new InternalItemsQuery(user) + { + AncestorWithPresentationUniqueKey = null, + SeriesPresentationUniqueKey = seriesKey, + ParentIndexNumber = 0, + IncludeItemTypes = new[] { nameof(Episode) }, + IsPlayed = false, + IsVirtualItem = false, + DtoOptions = dtoOptions + }).Cast().Where(episode => episode.AirsBeforeSeasonNumber != null || episode.AirsAfterSeasonNumber != null).ToList(); + + if (lastWatchedEpisode != null) + { + // Last watched episode is added, because there could be specials that aired before the last watched episode + consideredEpisodes.Add(lastWatchedEpisode); + } + + if (nextEpisode != null) + { + consideredEpisodes.Add(nextEpisode); + } + + var sortedConsideredEpisodes = _libraryManager.Sort(consideredEpisodes, user, new[] { (ItemSortBy.AiredEpisodeOrder, SortOrder.Ascending) }).Cast(); + if (lastWatchedEpisode != null) + { + sortedConsideredEpisodes = sortedConsideredEpisodes.SkipWhile(episode => episode.Id != lastWatchedEpisode.Id).Skip(1); + } + + nextEpisode = sortedConsideredEpisodes.FirstOrDefault(); + } + if (nextEpisode != null) { var userData = _userDataManager.GetUserData(user, nextEpisode); -- cgit v1.2.3 From 18cd634ec8316fe5978d7ad3867de66b85cd5fba Mon Sep 17 00:00:00 2001 From: Mister Rajoy Date: Sun, 28 Feb 2021 23:03:28 +0100 Subject: Fix duplicated movies when group movies into collections is enabled --- .../Collections/CollectionManager.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index 1ab2bdfbe..449f8872f 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -344,7 +344,20 @@ namespace Emby.Server.Implementations.Collections } else { - results[item.Id] = item; + var alreadyInResults = false; + foreach (var child in item.GetMediaSources(true)) + { + + if (results.ContainsKey(Guid.Parse(child.Id))) + { + alreadyInResults = true; + } + } + if (!alreadyInResults) + { + + results[item.Id] = item; + } } } } -- cgit v1.2.3 From f6c49f1373554609257f2126e34e04fc2790e715 Mon Sep 17 00:00:00 2001 From: Csaba Date: Mon, 1 Mar 2021 09:12:46 +0000 Subject: Translated using Weblate (Hungarian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/hu/ --- Emby.Server.Implementations/Localization/Core/hu.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/hu.json b/Emby.Server.Implementations/Localization/Core/hu.json index e5707e78c..ef8070503 100644 --- a/Emby.Server.Implementations/Localization/Core/hu.json +++ b/Emby.Server.Implementations/Localization/Core/hu.json @@ -49,7 +49,7 @@ "NotificationOptionAudioPlayback": "Audió lejátszás elkezdve", "NotificationOptionAudioPlaybackStopped": "Audió lejátszás leállítva", "NotificationOptionCameraImageUploaded": "Kamera kép feltöltve", - "NotificationOptionInstallationFailed": "Telepítési hiba", + "NotificationOptionInstallationFailed": "Telepítés sikertelen", "NotificationOptionNewLibraryContent": "Új tartalom hozzáadva", "NotificationOptionPluginError": "Bővítmény hiba", "NotificationOptionPluginInstalled": "Bővítmény telepítve", -- cgit v1.2.3 From ed7154db68f089cb8366aedaaeb93f1d5405251a Mon Sep 17 00:00:00 2001 From: Nichgon Date: Fri, 5 Mar 2021 07:42:03 +0000 Subject: Translated using Weblate (Thai) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/th/ --- Emby.Server.Implementations/Localization/Core/th.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/th.json b/Emby.Server.Implementations/Localization/Core/th.json index 71dd2c7a3..5bf58baf8 100644 --- a/Emby.Server.Implementations/Localization/Core/th.json +++ b/Emby.Server.Implementations/Localization/Core/th.json @@ -50,7 +50,7 @@ "HeaderFavoriteArtists": "ศิลปินที่ชื่นชอบ", "HeaderFavoriteAlbums": "อัมบั้มที่ชื่นชอบ", "HeaderContinueWatching": "ดูต่อ", - "HeaderAlbumArtists": "อัลบั้มศิลปิน", + "HeaderAlbumArtists": "ศิลปินอัลบั้ม", "Genres": "ประเภท", "Folders": "โฟลเดอร์", "Favorites": "รายการโปรด", @@ -112,5 +112,6 @@ "System": "ระบบ", "Sync": "ซิงค์", "SubtitleDownloadFailureFromForItem": "ไม่สามารถดาวน์โหลดคำบรรยายจาก {0} สำหรับ {1} ได้", - "StartupEmbyServerIsLoading": "กำลังโหลดเซิร์ฟเวอร์ Jellyfin โปรดลองอีกครั้งในอีกสักครู่" + "StartupEmbyServerIsLoading": "กำลังโหลดเซิร์ฟเวอร์ Jellyfin โปรดลองอีกครั้งในอีกสักครู่", + "Default": "ค่าเริ่มต้น" } -- cgit v1.2.3 From a6d0db5d0409f72e2abb02291268b6971eaf1fcf Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 5 Mar 2021 11:15:14 +0100 Subject: 100% branch coverage for DashboardController --- Emby.Server.Implementations/Plugins/PluginManager.cs | 4 ++-- Jellyfin.Api/Controllers/DashboardController.cs | 4 ++-- MediaBrowser.Common/Plugins/IPluginManager.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index 7bc9f0a7e..c579fc8cb 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -34,7 +34,7 @@ namespace Emby.Server.Implementations.Plugins private readonly ILogger _logger; private readonly IApplicationHost _appHost; private readonly ServerConfiguration _config; - private readonly IList _plugins; + private readonly List _plugins; private readonly Version _minimumVersion; private IHttpClientFactory? _httpClientFactory; @@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.Plugins /// /// Gets the Plugins. /// - public IList Plugins => _plugins; + public IReadOnlyList Plugins => _plugins; /// /// Returns all the assemblies. diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs index a2c2ecd66..445733c24 100644 --- a/Jellyfin.Api/Controllers/DashboardController.cs +++ b/Jellyfin.Api/Controllers/DashboardController.cs @@ -95,9 +95,9 @@ namespace Jellyfin.Api.Controllers return GetPluginPages(plugin).Select(i => new ConfigurationPageInfo(plugin.Instance, i.Item1)); } - private IEnumerable> GetPluginPages(LocalPlugin? plugin) + private IEnumerable> GetPluginPages(LocalPlugin plugin) { - if (plugin?.Instance is not IHasWebPages hasWebPages) + if (plugin.Instance is not IHasWebPages hasWebPages) { return Enumerable.Empty>(); } diff --git a/MediaBrowser.Common/Plugins/IPluginManager.cs b/MediaBrowser.Common/Plugins/IPluginManager.cs index fc2fcb517..f9a8fb6f7 100644 --- a/MediaBrowser.Common/Plugins/IPluginManager.cs +++ b/MediaBrowser.Common/Plugins/IPluginManager.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Common.Plugins /// /// Gets the Plugins. /// - IList Plugins { get; } + IReadOnlyList Plugins { get; } /// /// Creates the plugins. -- cgit v1.2.3 From 37e374d33d73403470d07d814b5ee1367ca12e85 Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 5 Mar 2021 14:09:23 +0100 Subject: make sure network path substitution matches correctly --- .../Library/LibraryManager.cs | 64 ++++------------- .../Library/PathExtensions.cs | 80 ++++++++++++++++++++++ .../Library/PathExtensionsTests.cs | 23 +++++++ 3 files changed, 117 insertions(+), 50 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index d9ffe64b3..973b2df8a 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2788,10 +2788,9 @@ namespace Emby.Server.Implementations.Library continue; } - var substitutionResult = SubstitutePathInternal(path, pathInfo.Path, pathInfo.NetworkPath); - if (substitutionResult.Item2) + if (path.TryReplaceSubPath(pathInfo.Path, pathInfo.NetworkPath, out var newPath)) { - return substitutionResult.Item1; + return newPath; } } } @@ -2802,22 +2801,22 @@ namespace Emby.Server.Implementations.Library if (!string.IsNullOrWhiteSpace(metadataPath) && !string.IsNullOrWhiteSpace(metadataNetworkPath)) { - var metadataSubstitutionResult = SubstitutePathInternal(path, metadataPath, metadataNetworkPath); - if (metadataSubstitutionResult.Item2) + if (path.TryReplaceSubPath(metadataPath, metadataNetworkPath, out var newPath)) { - return metadataSubstitutionResult.Item1; + return newPath; } } foreach (var map in _configurationManager.Configuration.PathSubstitutions) { - if (!string.IsNullOrWhiteSpace(map.From)) + if (string.IsNullOrWhiteSpace(map.From)) { - var substitutionResult = SubstitutePathInternal(path, map.From, map.To); - if (substitutionResult.Item2) - { - return substitutionResult.Item1; - } + continue; + } + + if (path.TryReplaceSubPath(map.From, map.To, out var newPath)) + { + return newPath; } } @@ -2826,47 +2825,12 @@ namespace Emby.Server.Implementations.Library public string SubstitutePath(string path, string from, string to) { - return SubstitutePathInternal(path, from, to).Item1; - } - - private Tuple SubstitutePathInternal(string path, string from, string to) - { - if (string.IsNullOrWhiteSpace(path)) - { - throw new ArgumentNullException(nameof(path)); - } - - if (string.IsNullOrWhiteSpace(from)) - { - throw new ArgumentNullException(nameof(from)); - } - - if (string.IsNullOrWhiteSpace(to)) + if (path.TryReplaceSubPath(from, to, out var newPath)) { - throw new ArgumentNullException(nameof(to)); + return newPath; } - from = from.Trim(); - to = to.Trim(); - - var newPath = path.Replace(from, to, StringComparison.OrdinalIgnoreCase); - var changed = false; - - if (!string.Equals(newPath, path, StringComparison.Ordinal)) - { - if (to.IndexOf('/', StringComparison.Ordinal) != -1) - { - newPath = newPath.Replace('\\', '/'); - } - else - { - newPath = newPath.Replace('/', '\\'); - } - - changed = true; - } - - return new Tuple(newPath, changed); + return path; } private void SetExtraTypeFromFilename(Video item) diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs index 06ff3e611..1fc5526ae 100644 --- a/Emby.Server.Implementations/Library/PathExtensions.cs +++ b/Emby.Server.Implementations/Library/PathExtensions.cs @@ -1,6 +1,7 @@ #nullable enable using System; +using System.Diagnostics.CodeAnalysis; using System.Text.RegularExpressions; namespace Emby.Server.Implementations.Library @@ -47,5 +48,84 @@ namespace Emby.Server.Implementations.Library return null; } + + /// + /// Replaces a sub path with another sub path and normalizes the final path. + /// + /// The original path. + /// The original sub path. + /// The new sub path. + /// The result of the sub path replacement + /// The path after replacing the sub path. + /// , or is empty. + public static bool TryReplaceSubPath(this string path, string subPath, string newSubPath, [NotNullWhen(true)] out string? newPath) + { + if (string.IsNullOrWhiteSpace(path)) + { + throw new ArgumentNullException(nameof(path)); + } + + if (string.IsNullOrWhiteSpace(subPath)) + { + throw new ArgumentNullException(nameof(subPath)); + } + + if (string.IsNullOrWhiteSpace(newSubPath)) + { + throw new ArgumentNullException(nameof(newSubPath)); + } + + char oldDirectorySeparatorChar; + char newDirectorySeparatorChar; + // True normalization is still not possible https://github.com/dotnet/runtime/issues/2162 + // The reasoning behind this is that a forward slash likely means it's a Linux path and + // so the whole path should be normalized to use / and vice versa for Windows (although Windows doesn't care much). + if (newSubPath.Contains('/', StringComparison.Ordinal)) + { + oldDirectorySeparatorChar = '\\'; + newDirectorySeparatorChar = '/'; + } + else + { + oldDirectorySeparatorChar = '/'; + newDirectorySeparatorChar = '\\'; + } + + if (path.Contains(oldDirectorySeparatorChar, StringComparison.Ordinal)) + { + path = path.Replace(oldDirectorySeparatorChar, newDirectorySeparatorChar); + } + + if (subPath.Contains(oldDirectorySeparatorChar, StringComparison.Ordinal)) + { + subPath = subPath.Replace(oldDirectorySeparatorChar, newDirectorySeparatorChar); + } + + // We have to ensure that the sub path ends with a directory separator otherwise we'll get weird results + // when the sub path matches a similar but in-complete subpath + if (!subPath.EndsWith(newDirectorySeparatorChar)) + { + subPath += newDirectorySeparatorChar; + } + + if (newSubPath.Contains(oldDirectorySeparatorChar, StringComparison.Ordinal)) + { + newSubPath = newSubPath.Replace(oldDirectorySeparatorChar, newDirectorySeparatorChar); + } + + if (!newSubPath.EndsWith(newDirectorySeparatorChar)) + { + newSubPath += newDirectorySeparatorChar; + } + + if (!path.Contains(subPath, StringComparison.OrdinalIgnoreCase)) + { + newPath = null; + return false; + } + + newPath = path.Replace(subPath, newSubPath, StringComparison.OrdinalIgnoreCase); + return true; + } } } diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs index 6d768af89..a96a05377 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs @@ -24,5 +24,28 @@ namespace Jellyfin.Server.Implementations.Tests.Library { Assert.Throws(() => PathExtensions.GetAttributeValue(input, attribute)); } + + [Theory] + [InlineData("C:/Users/jeff/myfile.mkv", "C:/Users/jeff", "/home/jeff", true, "/home/jeff/myfile.mkv")] + [InlineData("C:/Users/jeff/myfile.mkv", "C:/Users/jeff/", "/home/jeff", true, "/home/jeff/myfile.mkv")] + [InlineData("/home/jeff/music/jeff's band/consistently inconsistent.mp3", "/home/jeff/music/not jeff's band", "/home/not jeff", false, null)] + [InlineData("/home/jeff/music/jeff's band/consistently inconsistent.mp3", "/home/jeff/music/jeff's band", "/home/not jeff", true, "/home/not jeff/consistently inconsistent.mp3")] + [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff", "/home/jeff", true, "/home/jeff/myfile.mkv")] + public void TryReplaceSubPath_ValidArgs_Correct(string path, string subPath, string newSubPath, bool succeeded, string? expectedResult) + { + var status = PathExtensions.TryReplaceSubPath(path, subPath, newSubPath, out var result); + Assert.Equal(succeeded, status); + Assert.Equal(expectedResult, result); + } + + [Theory] + [InlineData("", "", "")] + [InlineData("/my/path", "", "")] + [InlineData("", "/another/path", "")] + [InlineData("", "", "/new/subpath")] + public void TryReplaceSubPath_EmptyString_ThrowsArgumentNullException(string path, string subPath, string newSubPath) + { + Assert.Throws(() => PathExtensions.TryReplaceSubPath(path, subPath, newSubPath, out _)); + } } } -- cgit v1.2.3 From 6293629d3263722c49c14f7642fb33b2986b0e19 Mon Sep 17 00:00:00 2001 From: Smith00101010 Date: Fri, 5 Mar 2021 22:51:08 +0100 Subject: Apply suggested formatting changes Co-authored-by: BaronGreenback --- Emby.Server.Implementations/TV/TVSeriesManager.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index d111e1a1c..d3f6fa34d 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -232,7 +232,10 @@ namespace Emby.Server.Implementations.TV IsPlayed = false, IsVirtualItem = false, DtoOptions = dtoOptions - }).Cast().Where(episode => episode.AirsBeforeSeasonNumber != null || episode.AirsAfterSeasonNumber != null).ToList(); + }) + .Cast() + .Where(episode => episode.AirsBeforeSeasonNumber != null || episode.AirsAfterSeasonNumber != null) + .ToList(); if (lastWatchedEpisode != null) { @@ -245,7 +248,8 @@ namespace Emby.Server.Implementations.TV consideredEpisodes.Add(nextEpisode); } - var sortedConsideredEpisodes = _libraryManager.Sort(consideredEpisodes, user, new[] { (ItemSortBy.AiredEpisodeOrder, SortOrder.Ascending) }).Cast(); + var sortedConsideredEpisodes = _libraryManager.Sort(consideredEpisodes, user, new[] { (ItemSortBy.AiredEpisodeOrder, SortOrder.Ascending) }) + .Cast(); if (lastWatchedEpisode != null) { sortedConsideredEpisodes = sortedConsideredEpisodes.SkipWhile(episode => episode.Id != lastWatchedEpisode.Id).Skip(1); -- cgit v1.2.3 From bc661c16e19413cbe6a94832280e3a24b6cf3c20 Mon Sep 17 00:00:00 2001 From: cvium Date: Sat, 6 Mar 2021 14:01:37 +0100 Subject: simplify --- .../Library/PathExtensions.cs | 26 +++++++--------------- .../Library/PathExtensionsTests.cs | 23 ++++++++++--------- 2 files changed, 21 insertions(+), 28 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs index 1fc5526ae..41e64abf3 100644 --- a/Emby.Server.Implementations/Library/PathExtensions.cs +++ b/Emby.Server.Implementations/Library/PathExtensions.cs @@ -103,28 +103,18 @@ namespace Emby.Server.Implementations.Library // We have to ensure that the sub path ends with a directory separator otherwise we'll get weird results // when the sub path matches a similar but in-complete subpath - if (!subPath.EndsWith(newDirectorySeparatorChar)) + var oldSubPathEndsWithSeparator = subPath[^1] == newDirectorySeparatorChar; + if (!path.StartsWith(subPath, StringComparison.OrdinalIgnoreCase) + || (!oldSubPathEndsWithSeparator && path[subPath.Length] != newDirectorySeparatorChar)) { - subPath += newDirectorySeparatorChar; - } - - if (newSubPath.Contains(oldDirectorySeparatorChar, StringComparison.Ordinal)) - { - newSubPath = newSubPath.Replace(oldDirectorySeparatorChar, newDirectorySeparatorChar); - } - - if (!newSubPath.EndsWith(newDirectorySeparatorChar)) - { - newSubPath += newDirectorySeparatorChar; - } - - if (!path.Contains(subPath, StringComparison.OrdinalIgnoreCase)) - { - newPath = null; return false; } - newPath = path.Replace(subPath, newSubPath, StringComparison.OrdinalIgnoreCase); + var newSubPathTrimmed = newSubPath.AsSpan().TrimEnd(newDirectorySeparatorChar); + // Ensure that the path with the old subpath removed starts with a leading dir separator + int idx = oldSubPathEndsWithSeparator ? subPath.Length - 1 : subPath.Length; + newPath = string.Concat(newSubPathTrimmed, path.AsSpan(idx)); + return true; } } diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs index a96a05377..a6fe90566 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs @@ -26,15 +26,16 @@ namespace Jellyfin.Server.Implementations.Tests.Library } [Theory] - [InlineData("C:/Users/jeff/myfile.mkv", "C:/Users/jeff", "/home/jeff", true, "/home/jeff/myfile.mkv")] - [InlineData("C:/Users/jeff/myfile.mkv", "C:/Users/jeff/", "/home/jeff", true, "/home/jeff/myfile.mkv")] - [InlineData("/home/jeff/music/jeff's band/consistently inconsistent.mp3", "/home/jeff/music/not jeff's band", "/home/not jeff", false, null)] - [InlineData("/home/jeff/music/jeff's band/consistently inconsistent.mp3", "/home/jeff/music/jeff's band", "/home/not jeff", true, "/home/not jeff/consistently inconsistent.mp3")] - [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff", "/home/jeff", true, "/home/jeff/myfile.mkv")] - public void TryReplaceSubPath_ValidArgs_Correct(string path, string subPath, string newSubPath, bool succeeded, string? expectedResult) + [InlineData("C:/Users/jeff/myfile.mkv", "C:/Users/jeff", "/home/jeff", "/home/jeff/myfile.mkv")] + [InlineData("C:/Users/jeff/myfile.mkv", "C:/Users/jeff/", "/home/jeff", "/home/jeff/myfile.mkv")] + [InlineData("/home/jeff/music/jeff's band/consistently inconsistent.mp3", "/home/jeff/music/jeff's band", "/home/not jeff", "/home/not jeff/consistently inconsistent.mp3")] + [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff", "/home/jeff", "/home/jeff/myfile.mkv")] + [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff", "/home/jeff/", "/home/jeff/myfile.mkv")] + [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff/", "/home/jeff/", "/home/jeff/myfile.mkv")] + [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff/", "/", "/myfile.mkv")] + public void TryReplaceSubPath_ValidArgs_Correct(string path, string subPath, string newSubPath, string? expectedResult) { - var status = PathExtensions.TryReplaceSubPath(path, subPath, newSubPath, out var result); - Assert.Equal(succeeded, status); + Assert.True(PathExtensions.TryReplaceSubPath(path, subPath, newSubPath, out var result)); Assert.Equal(expectedResult, result); } @@ -43,9 +44,11 @@ namespace Jellyfin.Server.Implementations.Tests.Library [InlineData("/my/path", "", "")] [InlineData("", "/another/path", "")] [InlineData("", "", "/new/subpath")] - public void TryReplaceSubPath_EmptyString_ThrowsArgumentNullException(string path, string subPath, string newSubPath) + [InlineData("/home/jeff/music/jeff's band/consistently inconsistent.mp3", "/home/jeff/music/not jeff's band", "/home/not jeff")] + public void TryReplaceSubPath_InvalidInput_ReturnsFalseAndNull(string path, string subPath, string newSubPath) { - Assert.Throws(() => PathExtensions.TryReplaceSubPath(path, subPath, newSubPath, out _)); + Assert.False(PathExtensions.TryReplaceSubPath(path, subPath, newSubPath, out var result)); + Assert.Null(result); } } } -- cgit v1.2.3 From 54211b921c86a4aa69e7390a662a48bf99011de1 Mon Sep 17 00:00:00 2001 From: cvium Date: Sat, 6 Mar 2021 19:07:02 +0100 Subject: rider is a prick --- .../Library/PathExtensions.cs | 26 +++++----------------- 1 file changed, 6 insertions(+), 20 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs index 41e64abf3..d9e20e19a 100644 --- a/Emby.Server.Implementations/Library/PathExtensions.cs +++ b/Emby.Server.Implementations/Library/PathExtensions.cs @@ -2,6 +2,7 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.IO; using System.Text.RegularExpressions; namespace Emby.Server.Implementations.Library @@ -60,19 +61,11 @@ namespace Emby.Server.Implementations.Library /// , or is empty. public static bool TryReplaceSubPath(this string path, string subPath, string newSubPath, [NotNullWhen(true)] out string? newPath) { - if (string.IsNullOrWhiteSpace(path)) - { - throw new ArgumentNullException(nameof(path)); - } - - if (string.IsNullOrWhiteSpace(subPath)) - { - throw new ArgumentNullException(nameof(subPath)); - } + newPath = null; - if (string.IsNullOrWhiteSpace(newSubPath)) + if (path.Length == 0 || subPath.Length == 0 || newSubPath.Length == 0 || subPath.Length > path.Length) { - throw new ArgumentNullException(nameof(newSubPath)); + return false; } char oldDirectorySeparatorChar; @@ -91,15 +84,8 @@ namespace Emby.Server.Implementations.Library newDirectorySeparatorChar = '\\'; } - if (path.Contains(oldDirectorySeparatorChar, StringComparison.Ordinal)) - { - path = path.Replace(oldDirectorySeparatorChar, newDirectorySeparatorChar); - } - - if (subPath.Contains(oldDirectorySeparatorChar, StringComparison.Ordinal)) - { - subPath = subPath.Replace(oldDirectorySeparatorChar, newDirectorySeparatorChar); - } + path = path.Replace(oldDirectorySeparatorChar, newDirectorySeparatorChar); + subPath = subPath.Replace(oldDirectorySeparatorChar, newDirectorySeparatorChar); // We have to ensure that the sub path ends with a directory separator otherwise we'll get weird results // when the sub path matches a similar but in-complete subpath -- cgit v1.2.3 From 67af30d1ff41734215db4c64f777568c647c2ad3 Mon Sep 17 00:00:00 2001 From: cvium Date: Sat, 6 Mar 2021 20:53:50 +0100 Subject: Remove redundant checks --- Emby.Server.Implementations/Library/LibraryManager.cs | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 973b2df8a..9a43405f4 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2783,11 +2783,6 @@ namespace Emby.Server.Implementations.Library { foreach (var pathInfo in libraryOptions.PathInfos) { - if (string.IsNullOrWhiteSpace(pathInfo.Path) || string.IsNullOrWhiteSpace(pathInfo.NetworkPath)) - { - continue; - } - if (path.TryReplaceSubPath(pathInfo.Path, pathInfo.NetworkPath, out var newPath)) { return newPath; @@ -2809,11 +2804,6 @@ namespace Emby.Server.Implementations.Library foreach (var map in _configurationManager.Configuration.PathSubstitutions) { - if (string.IsNullOrWhiteSpace(map.From)) - { - continue; - } - if (path.TryReplaceSubPath(map.From, map.To, out var newPath)) { return newPath; -- cgit v1.2.3 From 946411be8e85344ad4f33fb7ffb9a1666cf8e6be Mon Sep 17 00:00:00 2001 From: cvium Date: Sat, 6 Mar 2021 21:18:20 +0100 Subject: Remove redundant check --- Emby.Server.Implementations/Library/LibraryManager.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 9a43405f4..0957b8cf7 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2776,6 +2776,7 @@ namespace Emby.Server.Implementations.Library public string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem) { + string newPath; if (ownerItem != null) { var libraryOptions = GetLibraryOptions(ownerItem); @@ -2783,7 +2784,7 @@ namespace Emby.Server.Implementations.Library { foreach (var pathInfo in libraryOptions.PathInfos) { - if (path.TryReplaceSubPath(pathInfo.Path, pathInfo.NetworkPath, out var newPath)) + if (path.TryReplaceSubPath(pathInfo.Path, pathInfo.NetworkPath, out newPath)) { return newPath; } @@ -2794,17 +2795,14 @@ namespace Emby.Server.Implementations.Library var metadataPath = _configurationManager.Configuration.MetadataPath; var metadataNetworkPath = _configurationManager.Configuration.MetadataNetworkPath; - if (!string.IsNullOrWhiteSpace(metadataPath) && !string.IsNullOrWhiteSpace(metadataNetworkPath)) + if (path.TryReplaceSubPath(metadataPath, metadataNetworkPath, out newPath)) { - if (path.TryReplaceSubPath(metadataPath, metadataNetworkPath, out var newPath)) - { - return newPath; - } + return newPath; } foreach (var map in _configurationManager.Configuration.PathSubstitutions) { - if (path.TryReplaceSubPath(map.From, map.To, out var newPath)) + if (path.TryReplaceSubPath(map.From, map.To, out newPath)) { return newPath; } -- cgit v1.2.3 From 7c413a323b0d22a59532687b854ea228d544ecb7 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 6 Mar 2021 20:07:55 -0500 Subject: Move EF Core dependency out of Jellyfin.Data --- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 1 + Jellyfin.Data/Jellyfin.Data.csproj | 3 +-- Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index f03f04e02..93a4c3a7d 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -27,6 +27,7 @@ + diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index a2b6f074e..8651dee25 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -42,8 +42,7 @@ - - + diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 4f24da0ee..e3278cfd0 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -26,6 +26,8 @@ + + all runtime; build; native; contentfiles; analyzers; buildtransitive -- cgit v1.2.3 From 60ffa6f514656ed7256b555d483771c36164fce7 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 7 Mar 2021 14:43:28 +0100 Subject: Use FileShare.None when creating files --- Emby.Dlna/DlnaManager.cs | 3 ++- Emby.Server.Implementations/AppBase/ConfigurationHelper.cs | 3 ++- Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs | 6 ++++-- Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 6 ++++-- Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs | 3 ++- .../LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 3 ++- Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs | 3 ++- Jellyfin.Api/Controllers/ItemLookupController.cs | 3 ++- Jellyfin.Api/Controllers/RemoteImageController.cs | 3 ++- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 3 ++- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 3 ++- MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 3 ++- MediaBrowser.Providers/Manager/ImageSaver.cs | 3 ++- MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs | 3 ++- MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs | 3 ++- MediaBrowser.Providers/Subtitles/SubtitleManager.cs | 3 ++- 16 files changed, 36 insertions(+), 18 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 9ab324038..d7b75f979 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -395,7 +395,8 @@ namespace Emby.Dlna { Directory.CreateDirectory(systemProfilesPath); - using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) { await stream.CopyToAsync(fileStream).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs index 77819c764..3f7076383 100644 --- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs +++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs @@ -53,7 +53,8 @@ namespace Emby.Server.Implementations.AppBase Directory.CreateDirectory(directory); // Save it after load in case we got new items - using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) { fs.Write(newBytes, 0, newBytesLen); } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 341194f23..7a6b1d8b6 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -45,7 +45,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { Directory.CreateDirectory(Path.GetDirectoryName(targetFile)); - using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None)) { onStarted(); @@ -70,7 +71,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(targetFile)); - await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.Read); + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None); onStarted(); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 13b5a1c55..91a21db60 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1856,7 +1856,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.None)) { var settings = new XmlWriterSettings { @@ -1920,7 +1921,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.None)) { var settings = new XmlWriterSettings { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 78a82118e..40b934d32 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -91,7 +91,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); await JsonSerializer.SerializeAsync(_logFileStream, mediaSource, _jsonOptions, cancellationToken).ConfigureAwait(false); await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index b16ccc561..08832bae1 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -193,7 +193,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { var resolved = false; - using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None)) { while (true) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index eeb2426f4..233c3d83a 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -136,7 +136,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath); using var message = response; await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read); + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.None); await StreamHelper.CopyToAsync( stream, fileStream, diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs index dfc68ffce..dabd4deb7 100644 --- a/Jellyfin.Api/Controllers/ItemLookupController.cs +++ b/Jellyfin.Api/Controllers/ItemLookupController.cs @@ -344,11 +344,12 @@ namespace Jellyfin.Api.Controllers Directory.CreateDirectory(directory); using (var stream = result.Content) { + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . await using var fileStream = new FileStream( fullCachePath, FileMode.Create, FileAccess.Write, - FileShare.Read, + FileShare.None, IODefaults.FileStreamBufferSize, true); diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index 5284888d8..e226adc64 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -259,7 +259,8 @@ namespace Jellyfin.Api.Controllers var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException($"Provided path ({fullCachePath}) is not valid."); Directory.CreateDirectory(fullCacheDirectory); - await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); await response.Content.CopyToAsync(fileStream).ConfigureAwait(false); var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ArgumentException($"Provided path ({pointerCachePath}) is not valid.", nameof(pointerCachePath)); diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 240d132b1..7cd9024b0 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -553,7 +553,8 @@ namespace Jellyfin.Api.Helpers $"{logFilePrefix}{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{state.Request.MediaSourceId}_{Guid.NewGuid().ToString()[..8]}.log"); // FFmpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(request.Path + Environment.NewLine + Environment.NewLine + JsonSerializer.Serialize(state.MediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); await logStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationTokenSource.Token).ConfigureAwait(false); diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index a337521c6..e59fcb965 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -133,7 +133,8 @@ namespace MediaBrowser.LocalMetadata.Savers // On Windows, savint the file will fail if the file is hidden or readonly FileSystem.SetAttributes(path, false, false); - using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) { stream.CopyTo(filestream); } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index d19538730..fbb1563bb 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -677,7 +677,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (!string.Equals(text, newText, StringComparison.Ordinal)) { - using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None)) using (var writer = new StreamWriter(fileStream, encoding)) { await writer.WriteAsync(newText.AsMemory(), cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 9dd87aef5..5bb85be7b 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -261,7 +261,8 @@ namespace MediaBrowser.Providers.Manager _fileSystem.SetAttributes(path, false, false); - await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) { await source.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs index f463a3566..0a79f5bb5 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs @@ -171,7 +171,8 @@ namespace MediaBrowser.Providers.Plugins.AudioDb using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs index 7a15adb8e..4b1d91567 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs @@ -155,7 +155,8 @@ namespace MediaBrowser.Providers.Plugins.AudioDb Directory.CreateDirectory(Path.GetDirectoryName(path)); - await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 47e9d5ee8..d4d79d27b 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -228,7 +228,8 @@ namespace MediaBrowser.Providers.Subtitles { Directory.CreateDirectory(Path.GetDirectoryName(savePath)); - using (var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.Read, FileStreamBufferSize, true)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, FileStreamBufferSize, true)) { await stream.CopyToAsync(fs).ConfigureAwait(false); } -- cgit v1.2.3 From bc95268bd6a81db3f8e1c192aad48df5b879d231 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Sun, 7 Mar 2021 21:40:56 +0000 Subject: Translated using Weblate (Kazakh) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/kk/ --- Emby.Server.Implementations/Localization/Core/kk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/kk.json b/Emby.Server.Implementations/Localization/Core/kk.json index a321e35d0..bdfb786c9 100644 --- a/Emby.Server.Implementations/Localization/Core/kk.json +++ b/Emby.Server.Implementations/Localization/Core/kk.json @@ -109,7 +109,7 @@ "TasksMaintenanceCategory": "Qyzmet körsetu", "Undefined": "Anyqtalmağan", "Forced": "Mäjbürlı", - "TaskDownloadMissingSubtitlesDescription": "Metaderekter teŋşelımderı negızınde joq subtitrlerdı Internetten ızdeidı.", + "TaskDownloadMissingSubtitlesDescription": "Metaderekter teŋşelımderı negızınde joq subtitrlerdı İnternetten ızdeidı.", "TaskRefreshChannelsDescription": "Internet-arnalar mälımetterın jaŋğyrtady.", "TaskCleanTranscodeDescription": "Bіr künnen asqan qaita kodtau faildaryn joiady.", "TaskUpdatePluginsDescription": "Avtomatty türde jaŋartuğa teŋşelgen plaginder üşın jaŋartulardy jüktep alady jäne ornatady.", -- cgit v1.2.3 From d4201f812cac5d1b5f4cdd618770df421b3fad70 Mon Sep 17 00:00:00 2001 From: Ikomhoog Date: Mon, 8 Mar 2021 11:02:51 +0100 Subject: Changed string.Length == 0 to string.IsNullOrEmpty in case of null --- Emby.Server.Implementations/Library/PathExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs index d9e20e19a..7dcc925c2 100644 --- a/Emby.Server.Implementations/Library/PathExtensions.cs +++ b/Emby.Server.Implementations/Library/PathExtensions.cs @@ -63,7 +63,7 @@ namespace Emby.Server.Implementations.Library { newPath = null; - if (path.Length == 0 || subPath.Length == 0 || newSubPath.Length == 0 || subPath.Length > path.Length) + if (string.IsNullOrEmpty(path) || string.IsNullOrEmpty(subPath) || string.IsNullOrEmpty(newSubPath) || subPath.Length > path.Length) { return false; } -- cgit v1.2.3 From 54f81c4da484e3bb3d62669f0216c2a3a239166d Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 8 Mar 2021 12:08:17 +0100 Subject: Call ToLower on CollectionTypeOptions.ToString --- Emby.Server.Implementations/Library/LibraryManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index d9ffe64b3..6d92e12b3 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1247,7 +1247,7 @@ namespace Emby.Server.Implementations.Library { // TODO: @bond use a ReadOnlySpan here when Enum.TryParse supports it // https://github.com/dotnet/runtime/issues/20008 - if (Enum.TryParse(Path.GetExtension(file), true, out var res)) + if (Enum.TryParse(Path.GetFileNameWithoutExtension(file), true, out var res)) { return res; } @@ -3001,7 +3001,7 @@ namespace Emby.Server.Implementations.Library if (collectionType != null) { - var path = Path.Combine(virtualFolderPath, collectionType.ToString() + ".collection"); + var path = Path.Combine(virtualFolderPath, collectionType.ToString().ToLowerInvariant() + ".collection"); File.WriteAllBytes(path, Array.Empty()); } -- cgit v1.2.3 From d3390302f9c3d62bb9c878f52cf11f9f00438cb1 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Mon, 8 Mar 2021 11:43:59 +0000 Subject: Update ApplicationHost.cs --- Emby.Server.Implementations/ApplicationHost.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 37047a4f7..49febdb96 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -43,6 +43,7 @@ using Emby.Server.Implementations.Serialization; using Emby.Server.Implementations.Session; using Emby.Server.Implementations.SyncPlay; using Emby.Server.Implementations.TV; +using Emby.Server.Implementations.Udp; using Emby.Server.Implementations.Updates; using Jellyfin.Api.Helpers; using Jellyfin.Networking.Configuration; @@ -233,7 +234,7 @@ namespace Emby.Server.Implementations /// /// Gets the value of the PublishedServerUrl setting. /// - public string PublishedServerUrl => _startupOptions.PublishedServerUrl ?? _startupConfig["PublishedServerUrl"]; + public string PublishedServerUrl => _startupOptions.PublishedServerUrl ?? _startupConfig[UdpServer.AddressOverrideConfigKey]; /// /// Gets the server configuration manager. -- cgit v1.2.3 From 5241bd41ef4917e0a3071f961f08dd2eeec5a5dd Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 9 Mar 2021 01:28:21 +0100 Subject: Add code analysis attributes where appropriate --- Emby.Naming/Video/CleanStringParser.cs | 15 ++++----- Emby.Naming/Video/VideoResolver.cs | 3 +- .../Library/PathExtensions.cs | 11 +++++-- .../Video/CleanStringTests.cs | 36 ++++++++++++---------- .../Library/PathExtensionsTests.cs | 6 +++- 5 files changed, 43 insertions(+), 28 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Naming/Video/CleanStringParser.cs b/Emby.Naming/Video/CleanStringParser.cs index bd7553a91..4eef3ebc5 100644 --- a/Emby.Naming/Video/CleanStringParser.cs +++ b/Emby.Naming/Video/CleanStringParser.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Text.RegularExpressions; namespace Emby.Naming.Video @@ -16,8 +17,14 @@ namespace Emby.Naming.Video /// List of regex to parse name and year from. /// Parsing result string. /// True if parsing was successful. - public static bool TryClean(string name, IReadOnlyList expressions, out ReadOnlySpan newName) + public static bool TryClean([NotNullWhen(true)] string? name, IReadOnlyList expressions, out ReadOnlySpan newName) { + if (string.IsNullOrEmpty(name)) + { + newName = ReadOnlySpan.Empty; + return false; + } + var len = expressions.Count; for (int i = 0; i < len; i++) { @@ -33,12 +40,6 @@ namespace Emby.Naming.Video private static bool TryClean(string name, Regex expression, out ReadOnlySpan newName) { - if (string.IsNullOrEmpty(name)) - { - newName = ReadOnlySpan.Empty; - return false; - } - var match = expression.Match(name); int index = match.Index; if (match.Success && index != 0) diff --git a/Emby.Naming/Video/VideoResolver.cs b/Emby.Naming/Video/VideoResolver.cs index 619d1520e..79a6da8f7 100644 --- a/Emby.Naming/Video/VideoResolver.cs +++ b/Emby.Naming/Video/VideoResolver.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using Emby.Naming.Common; @@ -146,7 +147,7 @@ namespace Emby.Naming.Video /// Raw name. /// Clean name. /// True if cleaning of name was successful. - public bool TryCleanString(string name, out ReadOnlySpan newName) + public bool TryCleanString([NotNullWhen(true)] string? name, out ReadOnlySpan newName) { return CleanStringParser.TryClean(name, _options.CleanStringRegexes, out newName); } diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs index 7dcc925c2..57d0c26b9 100644 --- a/Emby.Server.Implementations/Library/PathExtensions.cs +++ b/Emby.Server.Implementations/Library/PathExtensions.cs @@ -59,11 +59,18 @@ namespace Emby.Server.Implementations.Library /// The result of the sub path replacement /// The path after replacing the sub path. /// , or is empty. - public static bool TryReplaceSubPath(this string path, string subPath, string newSubPath, [NotNullWhen(true)] out string? newPath) + public static bool TryReplaceSubPath( + [NotNullWhen(true)] this string? path, + [NotNullWhen(true)] string? subPath, + [NotNullWhen(true)] string? newSubPath, + [NotNullWhen(true)] out string? newPath) { newPath = null; - if (string.IsNullOrEmpty(path) || string.IsNullOrEmpty(subPath) || string.IsNullOrEmpty(newSubPath) || subPath.Length > path.Length) + if (string.IsNullOrEmpty(path) + || string.IsNullOrEmpty(subPath) + || string.IsNullOrEmpty(newSubPath) + || subPath.Length > path.Length) { return false; } diff --git a/tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs b/tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs index 4b363843a..a720bdade 100644 --- a/tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs @@ -7,18 +7,13 @@ namespace Jellyfin.Naming.Tests.Video { public sealed class CleanStringTests { - private readonly NamingOptions _namingOptions = new NamingOptions(); + private readonly VideoResolver _videoResolver = new VideoResolver(new NamingOptions()); [Theory] [InlineData("Super movie 480p.mp4", "Super movie")] [InlineData("Super movie 480p 2001.mp4", "Super movie")] [InlineData("Super movie [480p].mp4", "Super movie")] [InlineData("480 Super movie [tmdbid=12345].mp4", "480 Super movie")] - [InlineData("Super movie(2009).mp4", "Super movie(2009).mp4")] - [InlineData("Run lola run (lola rennt) (2009).mp4", "Run lola run (lola rennt) (2009).mp4")] - [InlineData(@"American.Psycho.mkv", "American.Psycho.mkv")] - [InlineData(@"American Psycho.mkv", "American Psycho.mkv")] - [InlineData(@"[rec].mkv", "[rec].mkv")] [InlineData("Crouching.Tiger.Hidden.Dragon.4k.mkv", "Crouching.Tiger.Hidden.Dragon")] [InlineData("Crouching.Tiger.Hidden.Dragon.UltraHD.mkv", "Crouching.Tiger.Hidden.Dragon")] [InlineData("Crouching.Tiger.Hidden.Dragon.UHD.mkv", "Crouching.Tiger.Hidden.Dragon")] @@ -28,19 +23,26 @@ namespace Jellyfin.Naming.Tests.Video [InlineData("Crouching.Tiger.Hidden.Dragon.BDrip.mkv", "Crouching.Tiger.Hidden.Dragon")] [InlineData("Crouching.Tiger.Hidden.Dragon.BDrip-HDC.mkv", "Crouching.Tiger.Hidden.Dragon")] [InlineData("Crouching.Tiger.Hidden.Dragon.4K.UltraHD.HDR.BDrip-HDC.mkv", "Crouching.Tiger.Hidden.Dragon")] - [InlineData(null, null)] // FIXME: [InlineData("After The Sunset - [0004].mkv", "After The Sunset")] - public void CleanStringTest(string input, string expectedName) + public void CleanStringTest_NeedsCleaning_Success(string input, string expectedName) { - if (new VideoResolver(_namingOptions).TryCleanString(input, out ReadOnlySpan newName)) - { - // TODO: compare spans when XUnit supports it - Assert.Equal(expectedName, newName.ToString()); - } - else - { - Assert.Equal(expectedName, input); - } + Assert.True(_videoResolver.TryCleanString(input, out ReadOnlySpan newName)); + // TODO: compare spans when XUnit supports it + Assert.Equal(expectedName, newName.ToString()); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData("Super movie(2009).mp4")] + [InlineData("[rec].mkv")] + [InlineData("American.Psycho.mkv")] + [InlineData("American Psycho.mkv")] + [InlineData("Run lola run (lola rennt) (2009).mp4")] + public void CleanStringTest_DoesntNeedCleaning_False(string? input) + { + Assert.False(_videoResolver.TryCleanString(input, out ReadOnlySpan newName)); + Assert.True(newName.IsEmpty); } } } diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs index a6fe90566..e5508243f 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs @@ -40,12 +40,16 @@ namespace Jellyfin.Server.Implementations.Tests.Library } [Theory] + [InlineData(null, null, null)] + [InlineData(null, "/my/path", "/another/path")] + [InlineData("/my/path", null, "/another/path")] + [InlineData("/my/path", "/another/path", null)] [InlineData("", "", "")] [InlineData("/my/path", "", "")] [InlineData("", "/another/path", "")] [InlineData("", "", "/new/subpath")] [InlineData("/home/jeff/music/jeff's band/consistently inconsistent.mp3", "/home/jeff/music/not jeff's band", "/home/not jeff")] - public void TryReplaceSubPath_InvalidInput_ReturnsFalseAndNull(string path, string subPath, string newSubPath) + public void TryReplaceSubPath_InvalidInput_ReturnsFalseAndNull(string? path, string? subPath, string? newSubPath) { Assert.False(PathExtensions.TryReplaceSubPath(path, subPath, newSubPath, out var result)); Assert.Null(result); -- cgit v1.2.3 From 9ed7f429c01c3f54a154442250d3447fd66d1b02 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 9 Mar 2021 03:04:47 +0100 Subject: FxCop -> Net Analyzers (part 1) --- Emby.Dlna/Emby.Dlna.csproj | 1 - Emby.Drawing/Emby.Drawing.csproj | 1 - Emby.Naming/Emby.Naming.csproj | 1 - Emby.Notifications/Emby.Notifications.csproj | 1 - Emby.Photos/Emby.Photos.csproj | 1 - .../Emby.Server.Implementations.csproj | 1 - Jellyfin.Api/Jellyfin.Api.csproj | 1 - Jellyfin.Data/Jellyfin.Data.csproj | 1 - Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 1 - Jellyfin.Networking/Jellyfin.Networking.csproj | 1 - .../Jellyfin.Server.Implementations.csproj | 1 - Jellyfin.Server/Jellyfin.Server.csproj | 1 - Jellyfin.sln | 14 +- MediaBrowser.Common/MediaBrowser.Common.csproj | 1 - .../MediaBrowser.Controller.csproj | 1 - .../MediaBrowser.LocalMetadata.csproj | 1 - .../BdInfo/BdInfoDirectoryInfo.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 92 +--- MediaBrowser.MediaEncoding/FfmpegException.cs | 39 ++ .../MediaBrowser.MediaEncoding.csproj | 8 +- .../Probing/ProbeResultNormalizer.cs | 18 +- .../Subtitles/SubtitleEncoder.cs | 6 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 9 +- .../MediaBrowser.Providers.csproj | 8 +- .../MediaBrowser.XbmcMetadata.csproj | 8 +- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 4 +- .../Providers/BaseVideoNfoProvider.cs | 2 +- MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs | 18 +- MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs | 13 +- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 16 +- .../Savers/EpisodeNfoSaver.cs | 31 +- MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs | 17 +- MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs | 11 +- MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs | 21 +- jellyfin.ruleset | 8 +- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 8 +- .../Jellyfin.Common.Tests.csproj | 8 +- .../Jellyfin.Controller.Tests.csproj | 8 +- .../Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj | 8 +- .../Jellyfin.MediaEncoding.Tests.csproj | 8 +- .../Jellyfin.Model.Tests.csproj | 8 +- .../AudioBook/AudioBookResolverTests.cs | 4 +- .../Jellyfin.Naming.Tests.csproj | 10 +- .../Video/VideoResolverTests.cs | 4 +- .../Jellyfin.Networking.Tests.csproj | 42 ++ .../Jellyfin.Networking.Tests/NetworkParseTests.cs | 518 ++++++++++++++++++++ .../Jellyfin.Networking.Tests.csproj | 39 -- .../NetworkTesting/NetworkParseTests.cs | 519 --------------------- .../Jellyfin.Server.Implementations.Tests.csproj | 8 +- .../Jellyfin.XbmcMetadata.Tests.csproj | 8 +- 50 files changed, 750 insertions(+), 810 deletions(-) create mode 100644 MediaBrowser.MediaEncoding/FfmpegException.cs create mode 100644 tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj create mode 100644 tests/Jellyfin.Networking.Tests/NetworkParseTests.cs delete mode 100644 tests/Jellyfin.Networking.Tests/NetworkTesting/Jellyfin.Networking.Tests.csproj delete mode 100644 tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index 8b057a095..480621dd7 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -25,7 +25,6 @@ - diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index 7d479a5c6..5c5afe1c6 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -25,7 +25,6 @@ - diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index b43203e9d..63116f368 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -44,7 +44,6 @@ - diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj index 16ee918c4..526a27229 100644 --- a/Emby.Notifications/Emby.Notifications.csproj +++ b/Emby.Notifications/Emby.Notifications.csproj @@ -25,7 +25,6 @@ - diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index 62e33e6c4..e64a658c5 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -28,7 +28,6 @@ - diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index f03f04e02..5a9792b51 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -49,7 +49,6 @@ - diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 67d0a3b5a..d5372d752 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -28,7 +28,6 @@ - diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index a8ac45645..42731bb11 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -34,7 +34,6 @@ - diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index 466a12e67..1a8415ae0 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -32,7 +32,6 @@ - diff --git a/Jellyfin.Networking/Jellyfin.Networking.csproj b/Jellyfin.Networking/Jellyfin.Networking.csproj index cbda74361..f89a18426 100644 --- a/Jellyfin.Networking/Jellyfin.Networking.csproj +++ b/Jellyfin.Networking/Jellyfin.Networking.csproj @@ -13,7 +13,6 @@ - diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 4f24da0ee..19c7ac567 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -14,7 +14,6 @@ - diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index bf4f80669..6bfb5b878 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -26,7 +26,6 @@ - diff --git a/Jellyfin.sln b/Jellyfin.sln index d83013dab..02ac1c7e9 100644 --- a/Jellyfin.sln +++ b/Jellyfin.sln @@ -68,14 +68,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Server.Implementat EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Networking", "Jellyfin.Networking\Jellyfin.Networking.csproj", "{0A3FCC4D-C714-4072-B90F-E374A15F9FF9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Networking.Tests", "tests\Jellyfin.Networking.Tests\NetworkTesting\Jellyfin.Networking.Tests.csproj", "{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Dlna.Tests", "tests\Jellyfin.Dlna.Tests\Jellyfin.Dlna.Tests.csproj", "{B8AE4B9D-E8D3-4B03-A95E-7FD8CECECC50}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.XbmcMetadata.Tests", "tests\Jellyfin.XbmcMetadata.Tests\Jellyfin.XbmcMetadata.Tests.csproj", "{30922383-D513-4F4D-B890-A940B57FA353}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Model.Tests", "tests\Jellyfin.Model.Tests\Jellyfin.Model.Tests.csproj", "{FC1BC0CE-E8D2-4AE9-A6AB-8A02143B335D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Networking.Tests", "tests\Jellyfin.Networking.Tests\Jellyfin.Networking.Tests.csproj", "{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -190,10 +190,6 @@ Global {0A3FCC4D-C714-4072-B90F-E374A15F9FF9}.Debug|Any CPU.Build.0 = Debug|Any CPU {0A3FCC4D-C714-4072-B90F-E374A15F9FF9}.Release|Any CPU.ActiveCfg = Release|Any CPU {0A3FCC4D-C714-4072-B90F-E374A15F9FF9}.Release|Any CPU.Build.0 = Release|Any CPU - {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Release|Any CPU.Build.0 = Release|Any CPU {B8AE4B9D-E8D3-4B03-A95E-7FD8CECECC50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B8AE4B9D-E8D3-4B03-A95E-7FD8CECECC50}.Debug|Any CPU.Build.0 = Debug|Any CPU {B8AE4B9D-E8D3-4B03-A95E-7FD8CECECC50}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -206,6 +202,10 @@ Global {FC1BC0CE-E8D2-4AE9-A6AB-8A02143B335D}.Debug|Any CPU.Build.0 = Debug|Any CPU {FC1BC0CE-E8D2-4AE9-A6AB-8A02143B335D}.Release|Any CPU.ActiveCfg = Release|Any CPU {FC1BC0CE-E8D2-4AE9-A6AB-8A02143B335D}.Release|Any CPU.Build.0 = Release|Any CPU + {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -217,10 +217,10 @@ Global {A2FD0A10-8F62-4F9D-B171-FFDF9F0AFA9D} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {2E3A1B4B-4225-4AAA-8B29-0181A84E7AEE} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {462584F7-5023-4019-9EAC-B98CA458C0A0} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} - {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {B8AE4B9D-E8D3-4B03-A95E-7FD8CECECC50} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {30922383-D513-4F4D-B890-A940B57FA353} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {FC1BC0CE-E8D2-4AE9-A6AB-8A02143B335D} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} + {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3448830C-EBDC-426C-85CD-7BBB9651A7FE} diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 8bb30c565..34e1934e2 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -46,7 +46,6 @@ - diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 6b1c096ac..d487a324f 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -47,7 +47,6 @@ - diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index 3ce9ff4cc..1792f1d9b 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -24,7 +24,6 @@ - diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs index 4a54b677d..ef9943722 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs @@ -71,7 +71,7 @@ namespace MediaBrowser.MediaEncoding.BdInfo _impl.FullName, new[] { searchPattern }, false, - searchOption.HasFlag(System.IO.SearchOption.AllDirectories)).ToArray(), + (searchOption & System.IO.SearchOption.AllDirectories) == System.IO.SearchOption.AllDirectories).ToArray(), x => new BdInfoFileInfo(x)); } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index a52019384..8a25a64c7 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -448,7 +448,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (result == null || (result.Streams == null && result.Format == null)) { - throw new Exception("ffprobe failed - streams and format are both null."); + throw new FfmpegException("ffprobe failed - streams and format are both null."); } if (result.Streams != null) @@ -571,32 +571,18 @@ namespace MediaBrowser.MediaEncoding.Encoder // apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar. // This filter chain may have adverse effects on recorded tv thumbnails if ar changes during presentation ex. commercials @ diff ar - var vf = string.Empty; - - if (threedFormat.HasValue) + var vf = threedFormat switch { - switch (threedFormat.Value) - { - case Video3DFormat.HalfSideBySide: - vf = "-vf crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; - // hsbs crop width in half,scale to correct size, set the display aspect,crop out any black bars we may have made. Work out the correct height based on the display aspect it will maintain the aspect where -1 in this case (3d) may not. - break; - case Video3DFormat.FullSideBySide: - vf = "-vf crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; - // fsbs crop width in half,set the display aspect,crop out any black bars we may have made - break; - case Video3DFormat.HalfTopAndBottom: - vf = "-vf crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; - // htab crop heigh in half,scale to correct size, set the display aspect,crop out any black bars we may have made - break; - case Video3DFormat.FullTopAndBottom: - vf = "-vf crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; - // ftab crop heigt in half, set the display aspect,crop out any black bars we may have made - break; - default: - break; - } - } + // hsbs crop width in half,scale to correct size, set the display aspect,crop out any black bars we may have made. Work out the correct height based on the display aspect it will maintain the aspect where -1 in this case (3d) may not. + Video3DFormat.HalfSideBySide => "-vf crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", + // fsbs crop width in half,set the display aspect,crop out any black bars we may have made + Video3DFormat.FullSideBySide => "-vf crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", + // htab crop heigh in half,scale to correct size, set the display aspect,crop out any black bars we may have made + Video3DFormat.HalfTopAndBottom => "-vf crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", + // ftab crop heigt in half, set the display aspect,crop out any black bars we may have made + Video3DFormat.FullTopAndBottom => "-vf crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", + _ => string.Empty + }; var mapArg = imageStreamIndex.HasValue ? (" -map 0:v:" + imageStreamIndex.Value.ToString(CultureInfo.InvariantCulture)) : string.Empty; @@ -604,7 +590,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (enableHdrExtraction) { string tonemapFilters = "zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0:peak=100,zscale=t=bt709:m=bt709,format=yuv420p"; - if (string.IsNullOrEmpty(vf)) + if (vf.Length == 0) { vf = "-vf " + tonemapFilters; } @@ -633,35 +619,11 @@ namespace MediaBrowser.MediaEncoding.Encoder var args = string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 {2} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, threads); - var probeSizeArgument = string.Empty; - var analyzeDurationArgument = string.Empty; - - if (!string.IsNullOrWhiteSpace(probeSizeArgument)) - { - args = probeSizeArgument + " " + args; - } - - if (!string.IsNullOrWhiteSpace(analyzeDurationArgument)) - { - args = analyzeDurationArgument + " " + args; - } - if (offset.HasValue) { args = string.Format(CultureInfo.InvariantCulture, "-ss {0} ", GetTimeParameter(offset.Value)) + args; } - if (videoStream != null) - { - /* fix - var decoder = encodinghelper.GetHardwareAcceleratedVideoDecoder(VideoType.VideoFile, videoStream, GetEncodingOptions()); - if (!string.IsNullOrWhiteSpace(decoder)) - { - args = decoder + " " + args; - } - */ - } - if (!string.IsNullOrWhiteSpace(container)) { var inputFormat = EncodingHelper.GetInputFormat(container); @@ -723,7 +685,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.LogError(msg); - throw new Exception(msg); + throw new FfmpegException(msg); } return tempExtractPath; @@ -770,30 +732,6 @@ namespace MediaBrowser.MediaEncoding.Encoder var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads {3} -v quiet {2} -f image2 \"{1}\"", inputArgument, outputPath, vf, threads); - var probeSizeArgument = string.Empty; - var analyzeDurationArgument = string.Empty; - - if (!string.IsNullOrWhiteSpace(probeSizeArgument)) - { - args = probeSizeArgument + " " + args; - } - - if (!string.IsNullOrWhiteSpace(analyzeDurationArgument)) - { - args = analyzeDurationArgument + " " + args; - } - - if (videoStream != null) - { - /* fix - var decoder = encodinghelper.GetHardwareAcceleratedVideoDecoder(VideoType.VideoFile, videoStream, GetEncodingOptions()); - if (!string.IsNullOrWhiteSpace(decoder)) - { - args = decoder + " " + args; - } - */ - } - if (!string.IsNullOrWhiteSpace(container)) { var inputFormat = EncodingHelper.GetInputFormat(container); @@ -872,7 +810,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.LogError(msg); - throw new Exception(msg); + throw new FfmpegException(msg); } } } diff --git a/MediaBrowser.MediaEncoding/FfmpegException.cs b/MediaBrowser.MediaEncoding/FfmpegException.cs new file mode 100644 index 000000000..1697fd33a --- /dev/null +++ b/MediaBrowser.MediaEncoding/FfmpegException.cs @@ -0,0 +1,39 @@ +using System; + +namespace MediaBrowser.MediaEncoding +{ + /// + /// Represents errors that occur during interaction with FFmpeg. + /// + public class FfmpegException : Exception + { + /// + /// Initializes a new instance of the class. + /// + public FfmpegException() + { + } + + /// + /// Initializes a new instance of the class with a specified error message. + /// + /// The message that describes the error. + public FfmpegException(string message) : base(message) + { + } + + /// + /// Initializes a new instance of the class with a specified error message and a + /// reference to the inner exception that is the cause of this exception. + /// + /// The error message that explains the reason for the exception. + /// + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if + /// no inner exception is specified. + /// + public FfmpegException(string message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 3d6b4f98a..de00920ba 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -10,6 +10,9 @@ false true true + true + AllEnabledByDefault + ../jellyfin.ruleset @@ -30,13 +33,8 @@ - - ../jellyfin.ruleset - - - diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index b9cb49cf2..75067315f 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -640,7 +640,7 @@ namespace MediaBrowser.MediaEncoding.Probing } // Filter out junk - if (!string.IsNullOrWhiteSpace(streamInfo.CodecTagString) && streamInfo.CodecTagString.IndexOf("[0]", StringComparison.OrdinalIgnoreCase) == -1) + if (!string.IsNullOrWhiteSpace(streamInfo.CodecTagString) && !streamInfo.CodecTagString.Contains("[0]", StringComparison.OrdinalIgnoreCase)) { stream.CodecTag = streamInfo.CodecTagString; } @@ -1500,11 +1500,23 @@ namespace MediaBrowser.MediaEncoding.Probing } else { - throw new Exception(); // Switch to default parsing + // Switch to default parsing + if (subtitle.Contains('.', StringComparison.Ordinal)) + { + // skip the comment, keep the subtitle + description = string.Join('.', subtitle.Split('.'), 1, subtitle.Split('.').Length - 1).Trim(); // skip the first + } + else + { + description = subtitle.Trim(); // Clean up whitespaces and save it + } } } - catch // Default parsing + catch (Exception ex) { + _logger.LogError(ex, "Error while parsing subtitle field"); + + // Default parsing if (subtitle.Contains('.', StringComparison.Ordinal)) { // skip the comment, keep the subtitle diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index fbb1563bb..39bec8da1 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -25,7 +25,7 @@ using UtfUnknown; namespace MediaBrowser.MediaEncoding.Subtitles { - public class SubtitleEncoder : ISubtitleEncoder + public sealed class SubtitleEncoder : ISubtitleEncoder { private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; @@ -484,7 +484,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { _logger.LogError("ffmpeg subtitle conversion failed for {Path}", inputPath); - throw new Exception( + throw new FfmpegException( string.Format(CultureInfo.InvariantCulture, "ffmpeg subtitle conversion failed for {0}", inputPath)); } @@ -637,7 +637,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles _logger.LogError(msg); - throw new Exception(msg); + throw new FfmpegException(msg); } else { diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index b6d916913..30403219f 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -19,7 +19,9 @@ true true enable - latest + true + + ../jellyfin.ruleset true true true @@ -44,7 +46,6 @@ - @@ -53,8 +54,4 @@ - - ../jellyfin.ruleset - - diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 071a149db..5e7b8043f 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -30,20 +30,18 @@ false true true + true + AllEnabledByDefault + ../jellyfin.ruleset - - - ../jellyfin.ruleset - - diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index 40f06c731..95327d3ae 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -20,18 +20,16 @@ true true enable + true + AllEnabledByDefault + ../jellyfin.ruleset - - - ../jellyfin.ruleset - - diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 6f164caf3..c4bbaf301 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -1168,11 +1168,9 @@ namespace MediaBrowser.XbmcMetadata.Parsers /// IEnumerable{System.String}. private IEnumerable SplitNames(string value) { - value = value ?? string.Empty; - // Only split by comma if there is no pipe in the string // We have to be careful to not split names like Matthew, Jr. - var separator = value.IndexOf('|', StringComparison.Ordinal) == -1 && value.IndexOf(';', StringComparison.Ordinal) == -1 + var separator = !value.Contains('|', StringComparison.Ordinal) && !value.Contains(';', StringComparison.Ordinal) ? new[] { ',' } : new[] { '|', ';' }; diff --git a/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs index af722748b..64cfc098f 100644 --- a/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.XbmcMetadata.Providers private readonly IUserManager _userManager; private readonly IUserDataManager _userDataManager; - public BaseVideoNfoProvider( + protected BaseVideoNfoProvider( ILogger> logger, IFileSystem fileSystem, IConfigurationManager config, diff --git a/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs index c22f77dcd..2385e7048 100644 --- a/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs @@ -96,18 +96,16 @@ namespace MediaBrowser.XbmcMetadata.Savers } /// - protected override List GetTagsUsed(BaseItem item) + protected override IEnumerable GetTagsUsed(BaseItem item) { - var list = base.GetTagsUsed(item); - list.AddRange( - new string[] - { - "track", - "artist", - "albumartist" - }); + foreach (var tag in base.GetTagsUsed(item)) + { + yield return tag; + } - return list; + yield return "track"; + yield return "artist"; + yield return "albumartist"; } } } diff --git a/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs index 6365cdecb..71b58cddb 100644 --- a/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs @@ -88,16 +88,15 @@ namespace MediaBrowser.XbmcMetadata.Savers } /// - protected override List GetTagsUsed(BaseItem item) + protected override IEnumerable GetTagsUsed(BaseItem item) { - var list = base.GetTagsUsed(item); - list.AddRange(new string[] + foreach (var tag in base.GetTagsUsed(item)) { - "album", - "disbanded" - }); + yield return tag; + } - return list; + yield return "album"; + yield return "disbanded"; } } } diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 0edab3787..3be35e2d9 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -166,19 +166,16 @@ namespace MediaBrowser.XbmcMetadata.Savers /// public abstract bool IsEnabledFor(BaseItem item, ItemUpdateType updateType); - protected virtual List GetTagsUsed(BaseItem item) + protected virtual IEnumerable GetTagsUsed(BaseItem item) { - var list = new List(); foreach (var providerKey in item.ProviderIds.Keys) { var providerIdTagName = GetTagForProviderKey(providerKey); if (!_commonTags.Contains(providerIdTagName)) { - list.Add(providerIdTagName); + yield return providerIdTagName; } } - - return list; } /// @@ -261,7 +258,7 @@ namespace MediaBrowser.XbmcMetadata.Savers AddMediaInfo(hasMediaSources, writer); } - var tagsUsed = GetTagsUsed(item); + var tagsUsed = GetTagsUsed(item).ToList(); try { @@ -351,10 +348,7 @@ namespace MediaBrowser.XbmcMetadata.Savers } var scanType = stream.IsInterlaced ? "interlaced" : "progressive"; - if (!string.IsNullOrEmpty(scanType)) - { - writer.WriteElementString("scantype", scanType); - } + writer.WriteElementString("scantype", scanType); if (stream.Channels.HasValue) { @@ -968,7 +962,7 @@ namespace MediaBrowser.XbmcMetadata.Savers => string.Equals(person.Type, type, StringComparison.OrdinalIgnoreCase) || string.Equals(person.Role, type, StringComparison.OrdinalIgnoreCase); - private void AddCustomTags(string path, List xmlTagsUsed, XmlWriter writer, ILogger logger) + private void AddCustomTags(string path, IReadOnlyCollection xmlTagsUsed, XmlWriter writer, ILogger logger) { var settings = new XmlReaderSettings() { diff --git a/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs index 5d3d17893..62f80e81b 100644 --- a/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs @@ -111,24 +111,23 @@ namespace MediaBrowser.XbmcMetadata.Savers } /// - protected override List GetTagsUsed(BaseItem item) + protected override IEnumerable GetTagsUsed(BaseItem item) { - var list = base.GetTagsUsed(item); - list.AddRange(new string[] + foreach (var tag in base.GetTagsUsed(item)) { - "aired", - "season", - "episode", - "episodenumberend", - "airsafter_season", - "airsbefore_episode", - "airsbefore_season", - "displayseason", - "displayepisode", - "showtitle" - }); - - return list; + yield return tag; + } + + yield return "aired"; + yield return "season"; + yield return "episode"; + yield return "episodenumberend"; + yield return "airsafter_season"; + yield return "airsbefore_episode"; + yield return "airsbefore_season"; + yield return "displayseason"; + yield return "displayepisode"; + yield return "showtitle"; } } } diff --git a/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs index 841121735..412e8031b 100644 --- a/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs @@ -123,18 +123,17 @@ namespace MediaBrowser.XbmcMetadata.Savers } /// - protected override List GetTagsUsed(BaseItem item) + protected override IEnumerable GetTagsUsed(BaseItem item) { - var list = base.GetTagsUsed(item); - list.AddRange(new string[] + foreach (var tag in base.GetTagsUsed(item)) { - "album", - "artist", - "set", - "id" - }); + yield return tag; + } - return list; + yield return "album"; + yield return "artist"; + yield return "set"; + yield return "id"; } } } diff --git a/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs index 925a230bd..b9d73ba82 100644 --- a/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs @@ -72,15 +72,14 @@ namespace MediaBrowser.XbmcMetadata.Savers } /// - protected override List GetTagsUsed(BaseItem item) + protected override IEnumerable GetTagsUsed(BaseItem item) { - var list = base.GetTagsUsed(item); - list.AddRange(new string[] + foreach (var tag in base.GetTagsUsed(item)) { - "seasonnumber" - }); + yield return tag; + } - return list; + yield return "seasonnumber"; } } } diff --git a/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs index 42285db76..083f22e5d 100644 --- a/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs @@ -90,20 +90,19 @@ namespace MediaBrowser.XbmcMetadata.Savers } /// - protected override List GetTagsUsed(BaseItem item) + protected override IEnumerable GetTagsUsed(BaseItem item) { - var list = base.GetTagsUsed(item); - list.AddRange(new string[] + foreach (var tag in base.GetTagsUsed(item)) { - "id", - "episodeguide", - "season", - "episode", - "status", - "displayorder" - }); + yield return tag; + } - return list; + yield return "id"; + yield return "episodeguide"; + yield return "season"; + yield return "episode"; + yield return "status"; + yield return "displayorder"; } } } diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 81337390c..b012d2b00 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -38,7 +38,7 @@ - + @@ -53,6 +53,8 @@ + + @@ -61,7 +63,11 @@ + + + + diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 873ff0ab4..0d8176bb2 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -10,6 +10,9 @@ false true enable + true + AllEnabledByDefault + ../jellyfin-tests.ruleset @@ -27,7 +30,6 @@ - @@ -37,10 +39,6 @@ - - ../jellyfin-tests.ruleset - - diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index 278f34109..78e3061f7 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -10,6 +10,9 @@ false true enable + true + AllEnabledByDefault + ../jellyfin-tests.ruleset @@ -21,7 +24,6 @@ - @@ -32,8 +34,4 @@ - - ../jellyfin-tests.ruleset - - diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index b02a68a3d..df1eb8617 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -10,6 +10,9 @@ false true enable + true + AllEnabledByDefault + ../jellyfin-tests.ruleset @@ -21,7 +24,6 @@ - @@ -31,8 +33,4 @@ - - ../jellyfin-tests.ruleset - - diff --git a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj index 850db1c75..d173d5c93 100644 --- a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj +++ b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj @@ -5,6 +5,9 @@ false true enable + true + AllEnabledByDefault + ../jellyfin-tests.ruleset @@ -16,7 +19,6 @@ - @@ -26,8 +28,4 @@ - - ../jellyfin-tests.ruleset - - diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index e729dbb09..84306e0f7 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -10,6 +10,9 @@ false true enable + true + AllEnabledByDefault + ../jellyfin-tests.ruleset @@ -27,7 +30,6 @@ - @@ -37,8 +39,4 @@ - - ../jellyfin-tests.ruleset - - diff --git a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj index b6d2c63bd..b458c06ff 100644 --- a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj +++ b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj @@ -5,6 +5,9 @@ false true enable + true + AllEnabledByDefault + ../jellyfin-tests.ruleset @@ -16,7 +19,6 @@ - @@ -26,8 +28,4 @@ - - ../jellyfin-tests.ruleset - - diff --git a/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs b/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs index b3257ace3..ad63adadc 100644 --- a/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs +++ b/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs @@ -10,7 +10,7 @@ namespace Jellyfin.Naming.Tests.AudioBook { private readonly NamingOptions _namingOptions = new NamingOptions(); - public static IEnumerable GetResolveFileTestData() + public static IEnumerable Resolve_ValidFileNameTestData() { yield return new object[] { @@ -36,7 +36,7 @@ namespace Jellyfin.Naming.Tests.AudioBook } [Theory] - [MemberData(nameof(GetResolveFileTestData))] + [MemberData(nameof(Resolve_ValidFileNameTestData))] public void Resolve_ValidFileName_Success(AudioBookFileInfo expectedResult) { var result = new AudioBookResolver(_namingOptions).Resolve(expectedResult.Path); diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index 99185c975..0f8a0333a 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -8,8 +8,11 @@ net5.0 false - enable true + enable + true + AllEnabledByDefault + ../jellyfin-tests.ruleset @@ -25,14 +28,9 @@ - - - ../jellyfin-tests.ruleset - - diff --git a/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs b/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs index ba5eaf1af..9bbbe2970 100644 --- a/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs @@ -11,7 +11,7 @@ namespace Jellyfin.Naming.Tests.Video { private readonly VideoResolver _videoResolver = new VideoResolver(new NamingOptions()); - public static IEnumerable GetResolveFileTestData() + public static IEnumerable ResolveFile_ValidFileNameTestData() { yield return new object[] { @@ -156,7 +156,7 @@ namespace Jellyfin.Naming.Tests.Video } [Theory] - [MemberData(nameof(GetResolveFileTestData))] + [MemberData(nameof(ResolveFile_ValidFileNameTestData))] public void ResolveFile_ValidFileName_Success(VideoFileInfo expectedResult) { var result = _videoResolver.ResolveFile(expectedResult.Path); diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj new file mode 100644 index 000000000..61eead0e9 --- /dev/null +++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj @@ -0,0 +1,42 @@ + + + + + {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6} + + + + net5.0 + false + true + enable + true + AllEnabledByDefault + ../jellyfin-tests.ruleset + + + + + + + + + + + + + + + + + + + + + + + + DEBUG + + + diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs new file mode 100644 index 000000000..c3469035e --- /dev/null +++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs @@ -0,0 +1,518 @@ +using System; +using System.Collections.ObjectModel; +using System.Net; +using Jellyfin.Networking.Configuration; +using Jellyfin.Networking.Manager; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Net; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Jellyfin.Networking.Tests +{ + public class NetworkParseTests + { + private static IConfigurationManager GetMockConfig(NetworkConfiguration conf) + { + var configManager = new Mock + { + CallBase = true + }; + configManager.Setup(x => x.GetConfiguration(It.IsAny())).Returns(conf); + return (IConfigurationManager)configManager.Object; + } + + /// + /// Checks the ability to ignore virtual interfaces. + /// + /// Mock network setup, in the format (IP address, interface index, interface name) | .... + /// LAN addresses. + /// Bind addresses that are excluded. + [Theory] + // All valid + [InlineData("192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11", "192.168.1.0/24;200.200.200.0/24", "[192.168.1.208/24,200.200.200.200/24]")] + // eth16 only + [InlineData("192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[192.168.1.208/24]")] + // All interfaces excluded. + [InlineData("192.168.1.208/24,-16,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[]")] + // vEthernet1 and vEthernet212 should be excluded. + [InlineData("192.168.1.200/24,-20,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24;200.200.200.200/24", "[200.200.200.200/24]")] + public void IgnoreVirtualInterfaces(string interfaces, string lan, string value) + { + var conf = new NetworkConfiguration() + { + EnableIPV6 = true, + EnableIPV4 = true, + LocalNetworkSubnets = lan?.Split(';') ?? throw new ArgumentNullException(nameof(lan)) + }; + + NetworkManager.MockNetworkSettings = interfaces; + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); + NetworkManager.MockNetworkSettings = string.Empty; + + Assert.Equal(nm.GetInternalBindAddresses().AsString(), value); + } + + /// + /// Check that the value given is in the network provided. + /// + /// Network address. + /// Value to check. + [Theory] + [InlineData("192.168.10.0/24, !192.168.10.60/32", "192.168.10.60")] + public void IsInNetwork(string network, string value) + { + if (network == null) + { + throw new ArgumentNullException(nameof(network)); + } + + var conf = new NetworkConfiguration() + { + EnableIPV6 = true, + EnableIPV4 = true, + LocalNetworkSubnets = network.Split(',') + }; + + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); + + Assert.False(nm.IsInLocalNetwork(value)); + } + + /// + /// Checks IP address formats. + /// + /// + [Theory] + [InlineData("127.0.0.1")] + [InlineData("127.0.0.1:123")] + [InlineData("localhost")] + [InlineData("localhost:1345")] + [InlineData("www.google.co.uk")] + [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517")] + [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517/56")] + [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517]:124")] + [InlineData("fe80::7add:12ff:febb:c67b%16")] + [InlineData("[fe80::7add:12ff:febb:c67b%16]:123")] + [InlineData("fe80::7add:12ff:febb:c67b%16:123")] + [InlineData("[fe80::7add:12ff:febb:c67b%16]")] + [InlineData("192.168.1.2/255.255.255.0")] + [InlineData("192.168.1.2/24")] + public void ValidHostStrings(string address) + { + Assert.True(IPHost.TryParse(address, out _)); + } + + /// + /// Checks IP address formats. + /// + /// + [Theory] + [InlineData("127.0.0.1")] + [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517")] + [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517/56")] + [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517]")] + [InlineData("fe80::7add:12ff:febb:c67b%16")] + [InlineData("[fe80::7add:12ff:febb:c67b%16]:123")] + [InlineData("fe80::7add:12ff:febb:c67b%16:123")] + [InlineData("[fe80::7add:12ff:febb:c67b%16]")] + [InlineData("192.168.1.2/255.255.255.0")] + [InlineData("192.168.1.2/24")] + public void ValidIPStrings(string address) + { + Assert.True(IPNetAddress.TryParse(address, out _)); + } + + /// + /// All should be invalid address strings. + /// + /// Invalid address strings. + [Theory] + [InlineData("256.128.0.0.0.1")] + [InlineData("127.0.0.1#")] + [InlineData("localhost!")] + [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517:1231")] + [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517:1231]")] + public void InvalidAddressString(string address) + { + Assert.False(IPNetAddress.TryParse(address, out _)); + Assert.False(IPHost.TryParse(address, out _)); + } + + /// + /// Test collection parsing. + /// + /// Collection to parse. + /// Included addresses from the collection. + /// Included IP4 addresses from the collection. + /// Excluded addresses from the collection. + /// Excluded IP4 addresses from the collection. + /// Network addresses of the collection. + [Theory] + [InlineData( + "127.0.0.1#", + "[]", + "[]", + "[]", + "[]", + "[]")] + [InlineData( + "!127.0.0.1", + "[]", + "[]", + "[127.0.0.1/32]", + "[127.0.0.1/32]", + "[]")] + [InlineData( + "", + "[]", + "[]", + "[]", + "[]", + "[]")] + [InlineData( + "192.158.1.2/16, localhost, fd23:184f:2029:0:3139:7386:67d7:d517, !10.10.10.10", + "[192.158.1.2/16,[127.0.0.1/32,::1/128],fd23:184f:2029:0:3139:7386:67d7:d517/128]", + "[192.158.1.2/16,127.0.0.1/32]", + "[10.10.10.10/32]", + "[10.10.10.10/32]", + "[192.158.0.0/16,127.0.0.1/32,::1/128,fd23:184f:2029:0:3139:7386:67d7:d517/128]")] + [InlineData( + "192.158.1.2/255.255.0.0,192.169.1.2/8", + "[192.158.1.2/16,192.169.1.2/8]", + "[192.158.1.2/16,192.169.1.2/8]", + "[]", + "[]", + "[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)); + } + + var conf = new NetworkConfiguration() + { + EnableIPV6 = true, + EnableIPV4 = true, + }; + + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); + + // Test included. + Collection nc = nm.CreateIPCollection(settings.Split(","), false); + Assert.Equal(nc.AsString(), result1); + + // Test excluded. + nc = nm.CreateIPCollection(settings.Split(","), true); + Assert.Equal(nc.AsString(), result3); + + conf.EnableIPV6 = false; + nm.UpdateSettings(conf); + + // Test IP4 included. + nc = nm.CreateIPCollection(settings.Split(","), false); + Assert.Equal(nc.AsString(), result2); + + // Test IP4 excluded. + nc = nm.CreateIPCollection(settings.Split(","), true); + Assert.Equal(nc.AsString(), result4); + + conf.EnableIPV6 = true; + nm.UpdateSettings(conf); + + // Test network addresses of collection. + nc = nm.CreateIPCollection(settings.Split(","), false); + nc = nc.AsNetworks(); + Assert.Equal(nc.AsString(), result5); + } + + /// + /// Union two collections. + /// + /// Source. + /// Destination. + /// Result. + [Theory] + [InlineData("127.0.0.1", "fd23:184f:2029:0:3139:7386:67d7:d517/64,fd23:184f:2029:0:c0f0:8a8a:7605:fffa/128,fe80::3139:7386:67d7:d517%16/64,192.168.1.208/24,::1/128,127.0.0.1/8", "[127.0.0.1/32]")] + [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)); + } + + if (compare == null) + { + throw new ArgumentNullException(nameof(compare)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + var conf = new NetworkConfiguration() + { + EnableIPV6 = true, + EnableIPV4 = true, + }; + + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); + + Collection nc1 = nm.CreateIPCollection(settings.Split(","), false); + Collection nc2 = nm.CreateIPCollection(compare.Split(","), false); + + Assert.Equal(nc1.Union(nc2).AsString(), result); + } + + [Theory] + [InlineData("192.168.5.85/24", "192.168.5.1")] + [InlineData("192.168.5.85/24", "192.168.5.254")] + [InlineData("10.128.240.50/30", "10.128.240.48")] + [InlineData("10.128.240.50/30", "10.128.240.49")] + [InlineData("10.128.240.50/30", "10.128.240.50")] + [InlineData("10.128.240.50/30", "10.128.240.51")] + [InlineData("127.0.0.1/8", "127.0.0.1")] + public void IpV4SubnetMaskMatchesValidIpAddress(string netMask, string ipAddress) + { + var ipAddressObj = IPNetAddress.Parse(netMask); + Assert.True(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); + } + + [Theory] + [InlineData("192.168.5.85/24", "192.168.4.254")] + [InlineData("192.168.5.85/24", "191.168.5.254")] + [InlineData("10.128.240.50/30", "10.128.240.47")] + [InlineData("10.128.240.50/30", "10.128.240.52")] + [InlineData("10.128.240.50/30", "10.128.239.50")] + [InlineData("10.128.240.50/30", "10.127.240.51")] + public void IpV4SubnetMaskDoesNotMatchInvalidIpAddress(string netMask, string ipAddress) + { + var ipAddressObj = IPNetAddress.Parse(netMask); + Assert.False(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); + } + + [Theory] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:0000:0000:0000:0000")] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFFF")] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:0001:0000:0000:0000")] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFF0")] + [InlineData("2001:db8:abcd:0012::0/128", "2001:0DB8:ABCD:0012:0000:0000:0000:0000")] + public void IpV6SubnetMaskMatchesValidIpAddress(string netMask, string ipAddress) + { + var ipAddressObj = IPNetAddress.Parse(netMask); + Assert.True(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); + } + + [Theory] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0011:FFFF:FFFF:FFFF:FFFF")] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0013:0000:0000:0000:0000")] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0013:0001:0000:0000:0000")] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0011:FFFF:FFFF:FFFF:FFF0")] + [InlineData("2001:db8:abcd:0012::0/128", "2001:0DB8:ABCD:0012:0000:0000:0000:0001")] + public void IpV6SubnetMaskDoesNotMatchInvalidIpAddress(string netMask, string ipAddress) + { + var ipAddressObj = IPNetAddress.Parse(netMask); + Assert.False(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); + } + + [Theory] + [InlineData("10.0.0.0/255.0.0.0", "10.10.10.1/32")] + [InlineData("10.0.0.0/8", "10.10.10.1/32")] + [InlineData("10.0.0.0/255.0.0.0", "10.10.10.1")] + + [InlineData("10.10.0.0/255.255.0.0", "10.10.10.1/32")] + [InlineData("10.10.0.0/16", "10.10.10.1/32")] + [InlineData("10.10.0.0/255.255.0.0", "10.10.10.1")] + + [InlineData("10.10.10.0/255.255.255.0", "10.10.10.1/32")] + [InlineData("10.10.10.0/24", "10.10.10.1/32")] + [InlineData("10.10.10.0/255.255.255.0", "10.10.10.1")] + + public void TestSubnetContains(string network, string ip) + { + Assert.True(IPNetAddress.TryParse(network, out var networkObj)); + Assert.True(IPNetAddress.TryParse(ip, out var ipObj)); + Assert.True(networkObj.Contains(ipObj)); + } + + [Theory] + [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "172.168.1.2/24", "172.168.1.2/24")] + [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "172.168.1.2/24, 10.10.10.1", "172.168.1.2/24,10.10.10.1/24")] + [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "192.168.1.2/255.255.255.0, 10.10.10.1", "192.168.1.2/24,10.10.10.1/24")] + [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "192.168.1.2/24, 100.10.10.1", "192.168.1.2/24")] + [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "194.168.1.2/24, 100.10.10.1", "")] + + public void TestCollectionEquality(string source, string dest, string result) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dest == null) + { + throw new ArgumentNullException(nameof(dest)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + var conf = new NetworkConfiguration() + { + EnableIPV6 = true, + EnableIPV4 = true + }; + + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); + + // Test included, IP6. + Collection ncSource = nm.CreateIPCollection(source.Split(",")); + Collection ncDest = nm.CreateIPCollection(dest.Split(",")); + Collection ncResult = ncSource.Union(ncDest); + Collection resultCollection = nm.CreateIPCollection(result.Split(",")); + Assert.True(ncResult.Compare(resultCollection)); + } + + [Theory] + [InlineData("10.1.1.1/32", "10.1.1.1")] + [InlineData("192.168.1.254/32", "192.168.1.254/255.255.255.255")] + + public void TestEquals(string source, string dest) + { + Assert.True(IPNetAddress.Parse(source).Equals(IPNetAddress.Parse(dest))); + Assert.True(IPNetAddress.Parse(dest).Equals(IPNetAddress.Parse(source))); + } + + [Theory] + + // Testing bind interfaces. + // On my system eth16 is internal, eth11 external (Windows defines the indexes). + // + // This test is to replicate how DNLA requests work throughout the system. + + // User on internal network, we're bound internal and external - so result is internal. + [InlineData("192.168.1.1", "eth16,eth11", false, "eth16")] + // User on external network, we're bound internal and external - so result is external. + [InlineData("8.8.8.8", "eth16,eth11", false, "eth11")] + // User on internal network, we're bound internal only - so result is internal. + [InlineData("10.10.10.10", "eth16", false, "eth16")] + // User on internal network, no binding specified - so result is the 1st internal. + [InlineData("192.168.1.1", "", false, "eth16")] + // User on external network, internal binding only - so result is the 1st internal. + [InlineData("jellyfin.org", "eth16", false, "eth16")] + // User on external network, no binding - so result is the 1st external. + [InlineData("jellyfin.org", "", false, "eth11")] + // User assumed to be internal, no binding - so result is the 1st internal. + [InlineData("", "", false, "eth16")] + public void TestBindInterfaces(string source, string bindAddresses, bool ipv6enabled, string result) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (bindAddresses == null) + { + throw new ArgumentNullException(nameof(bindAddresses)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + var conf = new NetworkConfiguration() + { + LocalNetworkAddresses = bindAddresses.Split(','), + EnableIPV6 = ipv6enabled, + EnableIPV4 = true + }; + + NetworkManager.MockNetworkSettings = "192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11"; + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); + NetworkManager.MockNetworkSettings = string.Empty; + + _ = nm.TryParseInterface(result, out Collection? resultObj); + + if (resultObj != null) + { + result = ((IPNetAddress)resultObj[0]).ToString(true); + var intf = nm.GetBindInterface(source, out int? _); + + Assert.Equal(intf, result); + } + } + + [Theory] + + // Testing bind interfaces. These are set for my system so won't work elsewhere. + // On my system eth16 is internal, eth11 external (Windows defines the indexes). + // + // This test is to replicate how subnet bound ServerPublisherUri work throughout the system. + + // User on internal network, we're bound internal and external - so result is internal override. + [InlineData("192.168.1.1", "192.168.1.0/24", "eth16,eth11", false, "192.168.1.0/24=internal.jellyfin", "internal.jellyfin")] + + // User on external network, we're bound internal and external - so result is override. + [InlineData("8.8.8.8", "192.168.1.0/24", "eth16,eth11", false, "0.0.0.0=http://helloworld.com", "http://helloworld.com")] + + // User on internal network, we're bound internal only, but the address isn't in the LAN - so return the override. + [InlineData("10.10.10.10", "192.168.1.0/24", "eth16", false, "0.0.0.0=http://internalButNotDefinedAsLan.com", "http://internalButNotDefinedAsLan.com")] + + // User on internal network, no binding specified - so result is the 1st internal. + [InlineData("192.168.1.1", "192.168.1.0/24", "", false, "0.0.0.0=http://helloworld.com", "eth16")] + + // User on external network, internal binding only - so assumption is a proxy forward, return external override. + [InlineData("jellyfin.org", "192.168.1.0/24", "eth16", false, "0.0.0.0=http://helloworld.com", "http://helloworld.com")] + + // User on external network, no binding - so result is the 1st external which is overriden. + [InlineData("jellyfin.org", "192.168.1.0/24", "", false, "0.0.0.0 = http://helloworld.com", "http://helloworld.com")] + + // User assumed to be internal, no binding - so result is the 1st internal. + [InlineData("", "192.168.1.0/24", "", false, "0.0.0.0=http://helloworld.com", "eth16")] + + // User is internal, no binding - so result is the 1st internal, which is then overridden. + [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)); + } + + if (bindAddresses == null) + { + throw new ArgumentNullException(nameof(bindAddresses)); + } + + var conf = new NetworkConfiguration() + { + LocalNetworkSubnets = lan.Split(','), + LocalNetworkAddresses = bindAddresses.Split(','), + EnableIPV6 = ipv6enabled, + EnableIPV4 = true, + PublishedServerUriBySubnet = new string[] { publishedServers } + }; + + NetworkManager.MockNetworkSettings = "192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11"; + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); + NetworkManager.MockNetworkSettings = string.Empty; + + if (nm.TryParseInterface(result, out Collection? resultObj) && resultObj != null) + { + // Parse out IPAddresses so we can do a string comparison. (Ignore subnet masks). + result = ((IPNetAddress)resultObj[0]).ToString(true); + } + + var intf = nm.GetBindInterface(source, out int? _); + + Assert.Equal(intf, result); + } + } +} diff --git a/tests/Jellyfin.Networking.Tests/NetworkTesting/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/NetworkTesting/Jellyfin.Networking.Tests.csproj deleted file mode 100644 index fd77397ba..000000000 --- a/tests/Jellyfin.Networking.Tests/NetworkTesting/Jellyfin.Networking.Tests.csproj +++ /dev/null @@ -1,39 +0,0 @@ - - - - - {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6} - - - - net5.0 - false - enable - true - - - - - - - - - - - - - - - - - - - - - - ../../jellyfin-tests.ruleset - - - DEBUG - - diff --git a/tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs deleted file mode 100644 index 9f928ded1..000000000 --- a/tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs +++ /dev/null @@ -1,519 +0,0 @@ -using System; -using System.Net; -using Jellyfin.Networking.Configuration; -using Jellyfin.Networking.Manager; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using Moq; -using Microsoft.Extensions.Logging.Abstractions; -using Xunit; -using System.Collections.ObjectModel; - -namespace Jellyfin.Networking.Tests -{ - public class NetworkParseTests - { - private static IConfigurationManager GetMockConfig(NetworkConfiguration conf) - { - var configManager = new Mock - { - CallBase = true - }; - configManager.Setup(x => x.GetConfiguration(It.IsAny())).Returns(conf); - return (IConfigurationManager)configManager.Object; - } - - /// - /// Checks the ability to ignore virtual interfaces. - /// - /// Mock network setup, in the format (IP address, interface index, interface name) | .... - /// LAN addresses. - /// Bind addresses that are excluded. - [Theory] - // All valid - [InlineData("192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11", "192.168.1.0/24;200.200.200.0/24", "[192.168.1.208/24,200.200.200.200/24]")] - // eth16 only - [InlineData("192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[192.168.1.208/24]")] - // All interfaces excluded. - [InlineData("192.168.1.208/24,-16,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[]")] - // vEthernet1 and vEthernet212 should be excluded. - [InlineData("192.168.1.200/24,-20,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24;200.200.200.200/24", "[200.200.200.200/24]")] - public void IgnoreVirtualInterfaces(string interfaces, string lan, string value) - { - var conf = new NetworkConfiguration() - { - EnableIPV6 = true, - EnableIPV4 = true, - LocalNetworkSubnets = lan?.Split(';') ?? throw new ArgumentNullException(nameof(lan)) - }; - - NetworkManager.MockNetworkSettings = interfaces; - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); - NetworkManager.MockNetworkSettings = string.Empty; - - Assert.Equal(nm.GetInternalBindAddresses().AsString(), value); - } - - /// - /// Check that the value given is in the network provided. - /// - /// Network address. - /// Value to check. - [Theory] - [InlineData("192.168.10.0/24, !192.168.10.60/32", "192.168.10.60")] - public void IsInNetwork(string network, string value) - { - if (network == null) - { - throw new ArgumentNullException(nameof(network)); - } - - var conf = new NetworkConfiguration() - { - EnableIPV6 = true, - EnableIPV4 = true, - LocalNetworkSubnets = network.Split(',') - }; - - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); - - Assert.False(nm.IsInLocalNetwork(value)); - } - - /// - /// Checks IP address formats. - /// - /// - [Theory] - [InlineData("127.0.0.1")] - [InlineData("127.0.0.1:123")] - [InlineData("localhost")] - [InlineData("localhost:1345")] - [InlineData("www.google.co.uk")] - [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517")] - [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517/56")] - [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517]:124")] - [InlineData("fe80::7add:12ff:febb:c67b%16")] - [InlineData("[fe80::7add:12ff:febb:c67b%16]:123")] - [InlineData("fe80::7add:12ff:febb:c67b%16:123")] - [InlineData("[fe80::7add:12ff:febb:c67b%16]")] - [InlineData("192.168.1.2/255.255.255.0")] - [InlineData("192.168.1.2/24")] - public void ValidHostStrings(string address) - { - Assert.True(IPHost.TryParse(address, out _)); - } - - /// - /// Checks IP address formats. - /// - /// - [Theory] - [InlineData("127.0.0.1")] - [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517")] - [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517/56")] - [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517]")] - [InlineData("fe80::7add:12ff:febb:c67b%16")] - [InlineData("[fe80::7add:12ff:febb:c67b%16]:123")] - [InlineData("fe80::7add:12ff:febb:c67b%16:123")] - [InlineData("[fe80::7add:12ff:febb:c67b%16]")] - [InlineData("192.168.1.2/255.255.255.0")] - [InlineData("192.168.1.2/24")] - public void ValidIPStrings(string address) - { - Assert.True(IPNetAddress.TryParse(address, out _)); - } - - - /// - /// All should be invalid address strings. - /// - /// Invalid address strings. - [Theory] - [InlineData("256.128.0.0.0.1")] - [InlineData("127.0.0.1#")] - [InlineData("localhost!")] - [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517:1231")] - [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517:1231]")] - public void InvalidAddressString(string address) - { - Assert.False(IPNetAddress.TryParse(address, out _)); - Assert.False(IPHost.TryParse(address, out _)); - } - - - /// - /// Test collection parsing. - /// - /// Collection to parse. - /// Included addresses from the collection. - /// Included IP4 addresses from the collection. - /// Excluded addresses from the collection. - /// Excluded IP4 addresses from the collection. - /// Network addresses of the collection. - [Theory] - [InlineData("127.0.0.1#", - "[]", - "[]", - "[]", - "[]", - "[]")] - [InlineData("!127.0.0.1", - "[]", - "[]", - "[127.0.0.1/32]", - "[127.0.0.1/32]", - "[]")] - [InlineData("", - "[]", - "[]", - "[]", - "[]", - "[]")] - [InlineData( - "192.158.1.2/16, localhost, fd23:184f:2029:0:3139:7386:67d7:d517, !10.10.10.10", - "[192.158.1.2/16,[127.0.0.1/32,::1/128],fd23:184f:2029:0:3139:7386:67d7:d517/128]", - "[192.158.1.2/16,127.0.0.1/32]", - "[10.10.10.10/32]", - "[10.10.10.10/32]", - "[192.158.0.0/16,127.0.0.1/32,::1/128,fd23:184f:2029:0:3139:7386:67d7:d517/128]")] - [InlineData("192.158.1.2/255.255.0.0,192.169.1.2/8", - "[192.158.1.2/16,192.169.1.2/8]", - "[192.158.1.2/16,192.169.1.2/8]", - "[]", - "[]", - "[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)); - } - - var conf = new NetworkConfiguration() - { - EnableIPV6 = true, - EnableIPV4 = true, - }; - - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); - - // Test included. - Collection nc = nm.CreateIPCollection(settings.Split(","), false); - Assert.Equal(nc.AsString(), result1); - - // Test excluded. - nc = nm.CreateIPCollection(settings.Split(","), true); - Assert.Equal(nc.AsString(), result3); - - conf.EnableIPV6 = false; - nm.UpdateSettings(conf); - - // Test IP4 included. - nc = nm.CreateIPCollection(settings.Split(","), false); - Assert.Equal(nc.AsString(), result2); - - // Test IP4 excluded. - nc = nm.CreateIPCollection(settings.Split(","), true); - Assert.Equal(nc.AsString(), result4); - - conf.EnableIPV6 = true; - nm.UpdateSettings(conf); - - // Test network addresses of collection. - nc = nm.CreateIPCollection(settings.Split(","), false); - nc = nc.AsNetworks(); - Assert.Equal(nc.AsString(), result5); - } - - /// - /// Union two collections. - /// - /// Source. - /// Destination. - /// Result. - [Theory] - [InlineData("127.0.0.1", "fd23:184f:2029:0:3139:7386:67d7:d517/64,fd23:184f:2029:0:c0f0:8a8a:7605:fffa/128,fe80::3139:7386:67d7:d517%16/64,192.168.1.208/24,::1/128,127.0.0.1/8", "[127.0.0.1/32]")] - [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)); - } - - if (compare == null) - { - throw new ArgumentNullException(nameof(compare)); - } - - if (result == null) - { - throw new ArgumentNullException(nameof(result)); - } - - - var conf = new NetworkConfiguration() - { - EnableIPV6 = true, - EnableIPV4 = true, - }; - - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); - - Collection nc1 = nm.CreateIPCollection(settings.Split(","), false); - Collection nc2 = nm.CreateIPCollection(compare.Split(","), false); - - Assert.Equal(nc1.Union(nc2).AsString(), result); - } - - [Theory] - [InlineData("192.168.5.85/24", "192.168.5.1")] - [InlineData("192.168.5.85/24", "192.168.5.254")] - [InlineData("10.128.240.50/30", "10.128.240.48")] - [InlineData("10.128.240.50/30", "10.128.240.49")] - [InlineData("10.128.240.50/30", "10.128.240.50")] - [InlineData("10.128.240.50/30", "10.128.240.51")] - [InlineData("127.0.0.1/8", "127.0.0.1")] - public void IpV4SubnetMaskMatchesValidIpAddress(string netMask, string ipAddress) - { - var ipAddressObj = IPNetAddress.Parse(netMask); - Assert.True(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); - } - - [Theory] - [InlineData("192.168.5.85/24", "192.168.4.254")] - [InlineData("192.168.5.85/24", "191.168.5.254")] - [InlineData("10.128.240.50/30", "10.128.240.47")] - [InlineData("10.128.240.50/30", "10.128.240.52")] - [InlineData("10.128.240.50/30", "10.128.239.50")] - [InlineData("10.128.240.50/30", "10.127.240.51")] - public void IpV4SubnetMaskDoesNotMatchInvalidIpAddress(string netMask, string ipAddress) - { - var ipAddressObj = IPNetAddress.Parse(netMask); - Assert.False(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); - } - - [Theory] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:0000:0000:0000:0000")] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFFF")] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:0001:0000:0000:0000")] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFF0")] - [InlineData("2001:db8:abcd:0012::0/128", "2001:0DB8:ABCD:0012:0000:0000:0000:0000")] - public void IpV6SubnetMaskMatchesValidIpAddress(string netMask, string ipAddress) - { - var ipAddressObj = IPNetAddress.Parse(netMask); - Assert.True(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); - } - - [Theory] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0011:FFFF:FFFF:FFFF:FFFF")] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0013:0000:0000:0000:0000")] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0013:0001:0000:0000:0000")] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0011:FFFF:FFFF:FFFF:FFF0")] - [InlineData("2001:db8:abcd:0012::0/128", "2001:0DB8:ABCD:0012:0000:0000:0000:0001")] - public void IpV6SubnetMaskDoesNotMatchInvalidIpAddress(string netMask, string ipAddress) - { - var ipAddressObj = IPNetAddress.Parse(netMask); - Assert.False(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); - } - - [Theory] - [InlineData("10.0.0.0/255.0.0.0", "10.10.10.1/32")] - [InlineData("10.0.0.0/8", "10.10.10.1/32")] - [InlineData("10.0.0.0/255.0.0.0", "10.10.10.1")] - - [InlineData("10.10.0.0/255.255.0.0", "10.10.10.1/32")] - [InlineData("10.10.0.0/16", "10.10.10.1/32")] - [InlineData("10.10.0.0/255.255.0.0", "10.10.10.1")] - - [InlineData("10.10.10.0/255.255.255.0", "10.10.10.1/32")] - [InlineData("10.10.10.0/24", "10.10.10.1/32")] - [InlineData("10.10.10.0/255.255.255.0", "10.10.10.1")] - - public void TestSubnetContains(string network, string ip) - { - Assert.True(IPNetAddress.TryParse(network, out var networkObj)); - Assert.True(IPNetAddress.TryParse(ip, out var ipObj)); - Assert.True(networkObj.Contains(ipObj)); - } - - [Theory] - [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "172.168.1.2/24", "172.168.1.2/24")] - [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "172.168.1.2/24, 10.10.10.1", "172.168.1.2/24,10.10.10.1/24")] - [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "192.168.1.2/255.255.255.0, 10.10.10.1", "192.168.1.2/24,10.10.10.1/24")] - [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "192.168.1.2/24, 100.10.10.1", "192.168.1.2/24")] - [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "194.168.1.2/24, 100.10.10.1", "")] - - public void TestCollectionEquality(string source, string dest, string result) - { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } - - if (dest == null) - { - throw new ArgumentNullException(nameof(dest)); - } - - if (result == null) - { - throw new ArgumentNullException(nameof(result)); - } - - var conf = new NetworkConfiguration() - { - EnableIPV6 = true, - EnableIPV4 = true - }; - - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); - - // Test included, IP6. - Collection ncSource = nm.CreateIPCollection(source.Split(",")); - Collection ncDest = nm.CreateIPCollection(dest.Split(",")); - Collection ncResult = ncSource.Union(ncDest); - Collection resultCollection = nm.CreateIPCollection(result.Split(",")); - Assert.True(ncResult.Compare(resultCollection)); - } - - - [Theory] - [InlineData("10.1.1.1/32", "10.1.1.1")] - [InlineData("192.168.1.254/32", "192.168.1.254/255.255.255.255")] - - public void TestEquals(string source, string dest) - { - Assert.True(IPNetAddress.Parse(source).Equals(IPNetAddress.Parse(dest))); - Assert.True(IPNetAddress.Parse(dest).Equals(IPNetAddress.Parse(source))); - } - - [Theory] - - // Testing bind interfaces. - // On my system eth16 is internal, eth11 external (Windows defines the indexes). - // - // This test is to replicate how DNLA requests work throughout the system. - - // User on internal network, we're bound internal and external - so result is internal. - [InlineData("192.168.1.1", "eth16,eth11", false, "eth16")] - // User on external network, we're bound internal and external - so result is external. - [InlineData("8.8.8.8", "eth16,eth11", false, "eth11")] - // User on internal network, we're bound internal only - so result is internal. - [InlineData("10.10.10.10", "eth16", false, "eth16")] - // User on internal network, no binding specified - so result is the 1st internal. - [InlineData("192.168.1.1", "", false, "eth16")] - // User on external network, internal binding only - so result is the 1st internal. - [InlineData("jellyfin.org", "eth16", false, "eth16")] - // User on external network, no binding - so result is the 1st external. - [InlineData("jellyfin.org", "", false, "eth11")] - // User assumed to be internal, no binding - so result is the 1st internal. - [InlineData("", "", false, "eth16")] - public void TestBindInterfaces(string source, string bindAddresses, bool ipv6enabled, string result) - { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } - - if (bindAddresses == null) - { - throw new ArgumentNullException(nameof(bindAddresses)); - } - - if (result == null) - { - throw new ArgumentNullException(nameof(result)); - } - - var conf = new NetworkConfiguration() - { - LocalNetworkAddresses = bindAddresses.Split(','), - EnableIPV6 = ipv6enabled, - EnableIPV4 = true - }; - - NetworkManager.MockNetworkSettings = "192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11"; - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); - NetworkManager.MockNetworkSettings = string.Empty; - - _ = nm.TryParseInterface(result, out Collection? resultObj); - - if (resultObj != null) - { - result = ((IPNetAddress)resultObj[0]).ToString(true); - var intf = nm.GetBindInterface(source, out int? _); - - Assert.Equal(intf, result); - } - } - - [Theory] - - // Testing bind interfaces. These are set for my system so won't work elsewhere. - // On my system eth16 is internal, eth11 external (Windows defines the indexes). - // - // This test is to replicate how subnet bound ServerPublisherUri work throughout the system. - - // User on internal network, we're bound internal and external - so result is internal override. - [InlineData("192.168.1.1", "192.168.1.0/24", "eth16,eth11", false, "192.168.1.0/24=internal.jellyfin", "internal.jellyfin")] - - // User on external network, we're bound internal and external - so result is override. - [InlineData("8.8.8.8", "192.168.1.0/24", "eth16,eth11", false, "0.0.0.0=http://helloworld.com", "http://helloworld.com")] - - // User on internal network, we're bound internal only, but the address isn't in the LAN - so return the override. - [InlineData("10.10.10.10", "192.168.1.0/24", "eth16", false, "0.0.0.0=http://internalButNotDefinedAsLan.com", "http://internalButNotDefinedAsLan.com")] - - // User on internal network, no binding specified - so result is the 1st internal. - [InlineData("192.168.1.1", "192.168.1.0/24", "", false, "0.0.0.0=http://helloworld.com", "eth16")] - - // User on external network, internal binding only - so assumption is a proxy forward, return external override. - [InlineData("jellyfin.org", "192.168.1.0/24", "eth16", false, "0.0.0.0=http://helloworld.com", "http://helloworld.com")] - - // User on external network, no binding - so result is the 1st external which is overriden. - [InlineData("jellyfin.org", "192.168.1.0/24", "", false, "0.0.0.0 = http://helloworld.com", "http://helloworld.com")] - - // User assumed to be internal, no binding - so result is the 1st internal. - [InlineData("", "192.168.1.0/24", "", false, "0.0.0.0=http://helloworld.com", "eth16")] - - // User is internal, no binding - so result is the 1st internal, which is then overridden. - [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)); - } - - if (bindAddresses == null) - { - throw new ArgumentNullException(nameof(bindAddresses)); - } - - var conf = new NetworkConfiguration() - { - LocalNetworkSubnets = lan.Split(','), - LocalNetworkAddresses = bindAddresses.Split(','), - EnableIPV6 = ipv6enabled, - EnableIPV4 = true, - PublishedServerUriBySubnet = new string[] { publishedServers } - }; - - NetworkManager.MockNetworkSettings = "192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11"; - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); - NetworkManager.MockNetworkSettings = string.Empty; - - if (nm.TryParseInterface(result, out Collection? resultObj) && resultObj != null) - { - // Parse out IPAddresses so we can do a string comparison. (Ignore subnet masks). - result = ((IPNetAddress)resultObj[0]).ToString(true); - } - - var intf = nm.GetBindInterface(source, out int? _); - - Assert.Equal(intf, result); - } - } -} 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 1ad8171be..8debb08c5 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -10,6 +10,9 @@ false true enable + true + AllEnabledByDefault + ../jellyfin-tests.ruleset Jellyfin.Server.Implementations.Tests @@ -31,7 +34,6 @@ - @@ -42,8 +44,4 @@ - - ../jellyfin-tests.ruleset - - diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj index d6aab3f85..2bb94c81f 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj +++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj @@ -5,6 +5,9 @@ false true enable + true + AllEnabledByDefault + ../jellyfin-tests.ruleset @@ -23,7 +26,6 @@ - @@ -34,8 +36,4 @@ - - ../jellyfin-tests.ruleset - - -- cgit v1.2.3 From e89bd8ba02cd5d5a98bba1bd8b1562af8fdaf5cf Mon Sep 17 00:00:00 2001 From: pkreuzt Date: Tue, 9 Mar 2021 01:58:03 +0000 Subject: Translated using Weblate (Galician) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/gl/ --- .../Localization/Core/gl.json | 24 +++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/gl.json b/Emby.Server.Implementations/Localization/Core/gl.json index 12bcd793e..11139d32a 100644 --- a/Emby.Server.Implementations/Localization/Core/gl.json +++ b/Emby.Server.Implementations/Localization/Core/gl.json @@ -57,5 +57,27 @@ "DeviceOnlineWithName": "{0} conectouse", "DeviceOfflineWithName": "{0} desconectouse", "Default": "Por defecto", - "AppDeviceValues": "Aplicación: {0}, Dispositivo: {1}" + "AppDeviceValues": "Aplicación: {0}, Dispositivo: {1}", + "TaskCleanLogs": "Limpar Carpeta de Rexistros", + "TaskCleanActivityLog": "Limpar Rexistro de Actividade", + "TasksChannelsCategory": "Canáis de Internet", + "TaskUpdatePlugins": "Actualizar Plugins", + "User": "Usuario", + "Undefined": "Sen definir", + "TvShows": "Programas de TV", + "System": "Sistema", + "Sync": "Sincronizar", + "SubtitleDownloadFailureFromForItem": "Fallou a descarga de subtítulos para {1} dende {0}", + "StartupEmbyServerIsLoading": "O Servidor Jellyfin está cargando. Por favor, reinténteo en breve.", + "Songs": "Cancións", + "Shows": "Programas", + "ServerNameNeedsToBeRestarted": "{0} precisa ser reiniciado", + "ScheduledTaskStartedWithName": "{0} comezou", + "ScheduledTaskFailedWithName": "{0} fallou", + "ProviderValue": "Provedor: {0}", + "PluginUpdatedWithName": "{0} foi actualizado", + "PluginUninstalledWithName": "{0} foi desinstalado", + "PluginInstalledWithName": "{0} foi instalado", + "Playlists": "Listas de reproducción", + "Photos": "Fotos" } -- cgit v1.2.3 From eca3b37d6eae727bd46b7a719cbf5b70a84627f8 Mon Sep 17 00:00:00 2001 From: David Date: Tue, 9 Mar 2021 17:01:05 +0100 Subject: Use FileShare.Read to fix HdHomeRun --- .../LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 3 +-- Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 08832bae1..b16ccc561 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -193,8 +193,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { var resolved = false; - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None)) + using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read)) { while (true) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index 233c3d83a..eeb2426f4 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -136,8 +136,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath); using var message = response; await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.None); + await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read); await StreamHelper.CopyToAsync( stream, fileStream, -- cgit v1.2.3 From ece0d67f99240324aafdcde85def3e933e413b69 Mon Sep 17 00:00:00 2001 From: David Date: Tue, 9 Mar 2021 17:31:31 +0100 Subject: Use FileShare.Read for log files --- Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs | 3 +-- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 40b934d32..78a82118e 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -91,8 +91,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); + _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); await JsonSerializer.SerializeAsync(_logFileStream, mediaSource, _jsonOptions, cancellationToken).ConfigureAwait(false); await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false); diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 7cd9024b0..240d132b1 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -553,8 +553,7 @@ namespace Jellyfin.Api.Helpers $"{logFilePrefix}{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{state.Request.MediaSourceId}_{Guid.NewGuid().ToString()[..8]}.log"); // FFmpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); + Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(request.Path + Environment.NewLine + Environment.NewLine + JsonSerializer.Serialize(state.MediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); await logStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationTokenSource.Token).ConfigureAwait(false); -- cgit v1.2.3 From 80846a1c66eb7f669d95d021786b5273ba3b15f6 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Fri, 12 Mar 2021 12:58:05 +0000 Subject: Translated using Weblate (Kazakh) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/kk/ --- Emby.Server.Implementations/Localization/Core/kk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/kk.json b/Emby.Server.Implementations/Localization/Core/kk.json index bdfb786c9..829a29ad4 100644 --- a/Emby.Server.Implementations/Localization/Core/kk.json +++ b/Emby.Server.Implementations/Localization/Core/kk.json @@ -116,7 +116,7 @@ "TaskRefreshPeopleDescription": "Tasyğyşhanadağy aktörler men rejisörler metaderekterın jaŋartady.", "TaskCleanLogsDescription": "{0} künnen asqan jūrnal faildaryn joiady.", "TaskRefreshLibraryDescription": "Tasyğyşhanadağy jaŋa faildardy skanerleidі jäne metaderekterdı jaŋğyrtady.", - "TaskRefreshChapterImagesDescription": "Sahnalary bar beineler üşіn nobailar jasaidy.", + "TaskRefreshChapterImagesDescription": "Sahnalary bar beineler üşın nobailar jasaidy.", "TaskCleanCacheDescription": "Jüiede qajet emes keştelgen faildardy joiady.", "TaskCleanActivityLogDescription": "Äreket jūrnalyndağy teŋşelgen jasynan asqan jazbalary joiady." } -- cgit v1.2.3 From f5789483fd5288fe735057bbf6e38a260e6915d2 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 13 Mar 2021 19:18:11 +0100 Subject: Add test for HdHomerunManager.WriteSetMessage --- .../TunerHosts/HdHomerun/HdHomerunManager.cs | 2 +- .../LiveTv/HdHomerunManagerTests.cs | 37 ++++++++++++++++++---- 2 files changed, 32 insertions(+), 7 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index 20a4d87fb..579333254 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -292,7 +292,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return FinishPacket(buffer, offset); } - private static int WriteSetMessage(Span buffer, int tuner, string name, string value, uint? lockkey) + internal static int WriteSetMessage(Span buffer, int tuner, string name, string value, uint? lockkey) { var byteName = string.Format(CultureInfo.InvariantCulture, "/tuner{0}/{1}", tuner, name); int offset = WriteHeaderAndPayload(buffer, byteName); diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs index 7e04a1ec1..e8634be4c 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs @@ -17,8 +17,9 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv Span buffer = stackalloc byte[128]; int len = HdHomerunManager.WriteNullTerminatedString(buffer, string.Empty); - Assert.Equal(expected.Length, len); - Assert.True(expected.SequenceEqual(buffer.Slice(0, len))); + Assert.Equal( + Convert.ToHexString(expected), + Convert.ToHexString(buffer.Slice(0, len))); } [Fact] @@ -32,8 +33,9 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv Span buffer = stackalloc byte[128]; int len = HdHomerunManager.WriteNullTerminatedString(buffer, "The quick"); - Assert.Equal(expected.Length, len); - Assert.True(expected.SequenceEqual(buffer.Slice(0, len))); + Assert.Equal( + Convert.ToHexString(expected), + Convert.ToHexString(buffer.Slice(0, len))); } [Fact] @@ -51,8 +53,31 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv Span buffer = stackalloc byte[128]; int len = HdHomerunManager.WriteGetMessage(buffer, 0, "N"); - Assert.Equal(expected.Length, len); - Assert.True(expected.SequenceEqual(buffer.Slice(0, len))); + Assert.Equal( + Convert.ToHexString(expected), + Convert.ToHexString(buffer.Slice(0, len))); + } + + [Fact] + public void WriteSetMessage_NoLockKey_Success() + { + ReadOnlySpan expected = stackalloc byte[] + { + 0, 4, + 0, 20, + 3, + 10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0, + 4, + 6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0, + 0xa9, 0x49, 0xd0, 0x68 + }; + + Span buffer = stackalloc byte[128]; + int len = HdHomerunManager.WriteSetMessage(buffer, 0, "N", "value", null); + + Assert.Equal( + Convert.ToHexString(expected), + Convert.ToHexString(buffer.Slice(0, len))); } } } -- cgit v1.2.3 From 4b17648df348ac17b359e2dcfe3e361798d45f2b Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 13 Mar 2021 19:23:52 +0100 Subject: Remove empty line Co-authored-by: Cody Robibero --- Emby.Server.Implementations/Collections/CollectionManager.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index 449f8872f..907b58886 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -347,7 +347,6 @@ namespace Emby.Server.Implementations.Collections var alreadyInResults = false; foreach (var child in item.GetMediaSources(true)) { - if (results.ContainsKey(Guid.Parse(child.Id))) { alreadyInResults = true; -- cgit v1.2.3 From 7a3109104bf4154d285c94a48504083368556c55 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 13 Mar 2021 19:24:02 +0100 Subject: Remove empty line Co-authored-by: Cody Robibero --- Emby.Server.Implementations/Collections/CollectionManager.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index 907b58886..151e86948 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -354,7 +354,6 @@ namespace Emby.Server.Implementations.Collections } if (!alreadyInResults) { - results[item.Id] = item; } } -- cgit v1.2.3 From e8b18e5f8fe87f981b11237d24032ab11589bcd2 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 13 Mar 2021 19:32:40 +0100 Subject: Add test for HdHomerunManager.ParseReturnMessage --- .../LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs | 2 +- .../LiveTv/HdHomerunManagerTests.cs | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index 579333254..9c113bc7c 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -355,7 +355,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return offset + 4; } - private static bool ParseReturnMessage(byte[] buf, int numBytes, out string returnVal) + internal static bool ParseReturnMessage(byte[] buf, int numBytes, out string returnVal) { returnVal = string.Empty; diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs index 2991fe1ed..355cfa641 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs @@ -103,5 +103,23 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv Convert.ToHexString(expected), Convert.ToHexString(buffer.Slice(0, len))); } + + [Fact] + public void ParseReturnMessage_Valid_Success() + { + ReadOnlySpan packet = stackalloc byte[] + { + 0, 5, + 0, 20, + 3, + 10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0, + 4, + 6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0, + 0x7d, 0xa3, 0xa3, 0xf3 + }; + + Assert.True(HdHomerunManager.ParseReturnMessage(packet.ToArray(), packet.Length, out var value)); + Assert.Equal("value", value); + } } } -- cgit v1.2.3 From 4cc3b938fa7913bccf7229dafce4b9f1d369dd16 Mon Sep 17 00:00:00 2001 From: Mister Rajoy Date: Sat, 13 Mar 2021 20:33:05 +0100 Subject: Change Guid.Parse to Guid.TryParse --- Emby.Server.Implementations/Collections/CollectionManager.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index 449f8872f..b5d95134b 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -348,11 +348,13 @@ namespace Emby.Server.Implementations.Collections foreach (var child in item.GetMediaSources(true)) { - if (results.ContainsKey(Guid.Parse(child.Id))) + if (Guid.TryParse(child.Id, out var id) && results.ContainsKey(id)) { alreadyInResults = true; + break; } } + if (!alreadyInResults) { -- cgit v1.2.3 From f9640f43663fdf443c130f61cab3521fcb1c7823 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 13 Mar 2021 21:12:11 +0100 Subject: Rewrite HdHomerunManager.ParseReturnMessage --- .../TunerHosts/HdHomerun/HdHomerunManager.cs | 75 ++++---- .../LiveTv/HdHomerunManagerTests.cs | 209 ++++++++++++++++++++- 2 files changed, 244 insertions(+), 40 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index 9c113bc7c..a7fda1d72 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -130,9 +130,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun int receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); - ParseReturnMessage(buffer, receivedBytes, out string returnVal); - - return string.Equals(returnVal, "none", StringComparison.OrdinalIgnoreCase); + return VerifyReturnValueOfGetSet(buffer.AsSpan(receivedBytes), "none"); } finally { @@ -173,7 +171,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun int receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); // parse response to make sure it worked - if (!ParseReturnMessage(buffer, receivedBytes, out _)) + if (!TryGetReturnValueOfGetSet(buffer.AsSpan(0, receivedBytes), out _)) { continue; } @@ -185,7 +183,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); // parse response to make sure it worked - if (!ParseReturnMessage(buffer, receivedBytes, out _)) + if (!TryGetReturnValueOfGetSet(buffer.AsSpan(0, receivedBytes), out _)) { await ReleaseLockkey(_tcpClient, lockKeyValue).ConfigureAwait(false); continue; @@ -199,7 +197,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); // parse response to make sure it worked - if (!ParseReturnMessage(buffer, receivedBytes, out _)) + if (!TryGetReturnValueOfGetSet(buffer.AsSpan(0, receivedBytes), out _)) { await ReleaseLockkey(_tcpClient, lockKeyValue).ConfigureAwait(false); continue; @@ -239,7 +237,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun int receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); // parse response to make sure it worked - if (!ParseReturnMessage(buffer, receivedBytes, out _)) + if (!TryGetReturnValueOfGetSet(buffer.AsSpan(0, receivedBytes), out _)) { return; } @@ -355,60 +353,65 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return offset + 4; } - internal static bool ParseReturnMessage(byte[] buf, int numBytes, out string returnVal) + internal static bool VerifyReturnValueOfGetSet(ReadOnlySpan buffer, string expected) { - returnVal = string.Empty; + return TryGetReturnValueOfGetSet(buffer, out var value) + && string.Equals(Encoding.UTF8.GetString(value), expected, StringComparison.OrdinalIgnoreCase); + } - if (numBytes < 4) + internal static bool TryGetReturnValueOfGetSet(ReadOnlySpan buffer, out ReadOnlySpan value) + { + value = ReadOnlySpan.Empty; + + if (buffer.Length < 8) { return false; } - var flipEndian = BitConverter.IsLittleEndian; - int offset = 0; - byte[] msgTypeBytes = new byte[2]; - Buffer.BlockCopy(buf, offset, msgTypeBytes, 0, msgTypeBytes.Length); - - if (flipEndian) + uint crc = BinaryPrimitives.ReadUInt32LittleEndian(buffer[^4..]); + if (crc != Crc32.Compute(buffer[..^4])) { - Array.Reverse(msgTypeBytes); + return false; } - var msgType = BitConverter.ToUInt16(msgTypeBytes, 0); - offset += 2; - - if (msgType != GetSetReply) + if (BinaryPrimitives.ReadUInt16BigEndian(buffer) != GetSetReply) { return false; } - byte[] msgLengthBytes = new byte[2]; - Buffer.BlockCopy(buf, offset, msgLengthBytes, 0, msgLengthBytes.Length); - if (flipEndian) + var msgLength = BinaryPrimitives.ReadUInt16BigEndian(buffer.Slice(2)); + if (buffer.Length != 2 + 2 + 4 + msgLength) { - Array.Reverse(msgLengthBytes); + return false; } - var msgLength = BitConverter.ToUInt16(msgLengthBytes, 0); - offset += 2; - - if (numBytes < msgLength + 8) + var offset = 4; + if (buffer[offset++] != GetSetName) { return false; } - offset++; // Name Tag - - var nameLength = buf[offset++]; + var nameLength = buffer[offset++]; + if (buffer.Length < 4 + 1 + offset + nameLength) + { + return false; + } - // skip the name field to get to value for return offset += nameLength; - offset++; // Value Tag + if (buffer[offset++] != GetSetValue) + { + return false; + } - var valueLength = buf[offset++]; + var valueLength = buffer[offset++]; + if (buffer.Length < 4 + offset + valueLength) + { + return false; + } - returnVal = Encoding.UTF8.GetString(buf, offset, valueLength - 1); // remove null terminator + // remove null terminator + value = buffer.Slice(offset, valueLength - 1); return true; } } diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs index 355cfa641..c404e6ed5 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs @@ -1,4 +1,5 @@ using System; +using System.Text; using Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun; using Xunit; @@ -105,9 +106,9 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv } [Fact] - public void ParseReturnMessage_Valid_Success() + public void TryGetReturnValueOfGetSet_Valid_Success() { - ReadOnlySpan packet = stackalloc byte[] + ReadOnlySpan packet = new byte[] { 0, 5, 0, 20, @@ -118,8 +119,208 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv 0x7d, 0xa3, 0xa3, 0xf3 }; - Assert.True(HdHomerunManager.ParseReturnMessage(packet.ToArray(), packet.Length, out var value)); - Assert.Equal("value", value); + Assert.True(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out var value)); + Assert.Equal("value", Encoding.UTF8.GetString(value)); + } + + [Fact] + public void TryGetReturnValueOfGetSet_InvalidPacketType_False() + { + ReadOnlySpan packet = new byte[] + { + 0, 4, + 0, 20, + 3, + 10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0, + 4, + 6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0, + 0x7d, 0xa3, 0xa3, 0xf3 + }; + + Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _)); + } + + [Fact] + public void TryGetReturnValueOfGetSet_InvalidCrc_False() + { + ReadOnlySpan packet = new byte[] + { + 0, 5, + 0, 20, + 3, + 10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0, + 4, + 6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0, + 0x7d, 0xa3, 0xa3, 0xf4 + }; + + Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _)); + } + + [Fact] + public void TryGetReturnValueOfGetSet_InvalidPacket_False() + { + ReadOnlySpan packet = new byte[] + { + 0, 5, + 0, 20, + 0x7d, 0xa3, 0xa3 + }; + + Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _)); + } + + [Fact] + public void TryGetReturnValueOfGetSet_TooSmallMessageLength_False() + { + ReadOnlySpan packet = new byte[] + { + 0, 5, + 0, 19, + 3, + 10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0, + 4, + 6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0, + 0x25, 0x25, 0x44, 0x9a + }; + + Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _)); + } + + [Fact] + public void TryGetReturnValueOfGetSet_TooLargeMessageLength_False() + { + ReadOnlySpan packet = new byte[] + { + 0, 5, + 0, 21, + 3, + 10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0, + 4, + 6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0, + 0xe3, 0x20, 0x79, 0x6c + }; + + Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _)); + } + + [Fact] + public void TryGetReturnValueOfGetSet_TooLargeNameLength_False() + { + ReadOnlySpan packet = new byte[] + { + 0, 5, + 0, 20, + 3, + 20, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0, + 4, + 6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0, + 0xe1, 0x8e, 0x9c, 0x74 + }; + + Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _)); + } + + [Fact] + public void TryGetReturnValueOfGetSet_InvalidGetSetNameTag_False() + { + ReadOnlySpan packet = new byte[] + { + 0, 5, + 0, 20, + 4, + 10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0, + 4, + 6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0, + 0xee, 0x05, 0xe7, 0x12 + }; + + Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _)); + } + + [Fact] + public void TryGetReturnValueOfGetSet_InvalidGetSetValueTag_False() + { + ReadOnlySpan packet = new byte[] + { + 0, 5, + 0, 20, + 3, + 10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0, + 3, + 6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0, + 0x64, 0xaa, 0x66, 0xf9 + }; + + Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _)); + } + + [Fact] + public void TryGetReturnValueOfGetSet_TooLargeValueLength_False() + { + ReadOnlySpan packet = new byte[] + { + 0, 5, + 0, 20, + 3, + 10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0, + 4, + 7, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0, + 0xc9, 0xa8, 0xd4, 0x55 + }; + + Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _)); + } + + [Fact] + public void VerifyReturnValueOfGetSet_Valid_True() + { + ReadOnlySpan packet = new byte[] + { + 0, 5, + 0, 20, + 3, + 10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0, + 4, + 6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0, + 0x7d, 0xa3, 0xa3, 0xf3 + }; + + Assert.True(HdHomerunManager.VerifyReturnValueOfGetSet(packet, "value")); + } + + [Fact] + public void VerifyReturnValueOfGetSet_WrongValue_False() + { + ReadOnlySpan packet = new byte[] + { + 0, 5, + 0, 20, + 3, + 10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0, + 4, + 6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0, + 0x7d, 0xa3, 0xa3, 0xf3 + }; + + Assert.False(HdHomerunManager.VerifyReturnValueOfGetSet(packet, "none")); + } + + [Fact] + public void VerifyReturnValueOfGetSet_InvalidPacket_False() + { + ReadOnlySpan packet = new byte[] + { + 0, 4, + 0, 20, + 3, + 10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0, + 4, + 6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0, + 0x7d, 0xa3, 0xa3, 0xf3 + }; + + Assert.False(HdHomerunManager.VerifyReturnValueOfGetSet(packet, "value")); } } } -- cgit v1.2.3 From a8ed753f6c890f74d3a70c2653ac5548d2399737 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 9 Mar 2021 05:57:38 +0100 Subject: FxCop -> Net Analyzers (part 2) --- Emby.Dlna/DlnaManager.cs | 2 +- Emby.Server.Implementations/ApplicationHost.cs | 5 +- .../Channels/ChannelManager.cs | 2 +- .../Data/SqliteItemRepository.cs | 2 +- .../HttpServer/WebSocketConnection.cs | 2 +- .../Library/LiveStreamHelper.cs | 2 +- .../Library/MediaSourceManager.cs | 2 +- .../LiveTv/EmbyTV/EncodedRecorder.cs | 2 +- .../LiveTv/EmbyTV/ItemDataProvider.cs | 2 +- .../LiveTv/Listings/SchedulesDirect.cs | 2 +- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 2 +- .../Localization/LocalizationManager.cs | 2 +- .../Plugins/PluginManager.cs | 4 +- .../ScheduledTasks/ScheduledTaskWorker.cs | 2 +- .../Updates/InstallationManager.cs | 2 +- .../Controllers/ConfigurationController.cs | 2 +- Jellyfin.Api/Controllers/PluginsController.cs | 2 +- Jellyfin.Data/DayOfWeekHelper.cs | 60 +++------------------- Jellyfin.Data/Entities/Libraries/Collection.cs | 1 + .../Entities/Libraries/MediaFileStream.cs | 2 + Jellyfin.Data/Entities/Permission.cs | 2 + Jellyfin.Data/Jellyfin.Data.csproj | 6 +-- Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 11 ++-- Jellyfin.Drawing.Skia/SkiaEncoder.cs | 13 ++--- Jellyfin.Networking/Jellyfin.Networking.csproj | 6 +-- .../Security/AuthenticationSucceededLogger.cs | 8 +-- .../Events/Consumers/System/TaskCompletedLogger.cs | 14 ++--- .../Consumers/Updates/PluginUninstalledLogger.cs | 4 +- .../Events/Consumers/Users/UserUpdatedNotifier.cs | 6 +-- .../Jellyfin.Server.Implementations.csproj | 2 + .../Users/DefaultPasswordResetProvider.cs | 2 +- .../Users/DisplayPreferencesManager.cs | 3 +- .../Extensions/ApiServiceCollectionExtensions.cs | 2 +- .../Formatters/CamelCaseJsonProfileFormatter.cs | 2 +- .../Formatters/PascalCaseJsonProfileFormatter.cs | 2 +- Jellyfin.Server/Jellyfin.Server.csproj | 8 ++- Jellyfin.Server/Migrations/MigrationOptions.cs | 3 ++ .../Migrations/Routines/MigrateUserDb.cs | 2 +- Jellyfin.Server/Program.cs | 4 +- MediaBrowser.Common/IApplicationHost.cs | 4 +- MediaBrowser.Common/Json/JsonDefaults.cs | 6 +-- MediaBrowser.Common/MediaBrowser.Common.csproj | 6 +-- MediaBrowser.Common/Net/IPHost.cs | 2 +- MediaBrowser.Common/Net/IPNetAddress.cs | 6 +-- MediaBrowser.Common/Plugins/BasePlugin.cs | 2 +- MediaBrowser.Common/Plugins/BasePluginOfT.cs | 36 ++++++------- MediaBrowser.Common/Plugins/LocalPlugin.cs | 6 +-- MediaBrowser.Common/Progress/ActionableProgress.cs | 1 + MediaBrowser.Common/Progress/SimpleProgress.cs | 1 + .../Entities/CollectionFolder.cs | 2 +- .../MediaBrowser.Controller.csproj | 6 +-- .../Providers/ILocalImageProvider.cs | 2 +- .../Images/CollectionFolderLocalImageProvider.cs | 2 +- .../Images/EpisodeLocalImageProvider.cs | 2 +- .../Images/InternalMetadataFolderImageProvider.cs | 7 +-- .../Images/LocalImageProvider.cs | 14 +++-- .../MediaBrowser.LocalMetadata.csproj | 6 +-- .../Parsers/BaseItemXmlParser.cs | 4 +- .../Parsers/BoxSetXmlParser.cs | 6 +-- .../Parsers/PlaylistXmlParser.cs | 6 +-- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 17 ++---- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- .../Plugins/AudioDb/AlbumImageProvider.cs | 2 +- .../Plugins/AudioDb/AlbumProvider.cs | 2 +- .../Plugins/AudioDb/ArtistImageProvider.cs | 2 +- .../Plugins/AudioDb/ArtistProvider.cs | 2 +- .../Plugins/Omdb/OmdbItemProvider.cs | 2 +- .../Plugins/Omdb/OmdbProvider.cs | 2 +- .../FFprobeParserTests.cs | 2 +- .../Controllers/DashboardControllerTests.cs | 2 +- 70 files changed, 151 insertions(+), 213 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index d7b75f979..552cd501b 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -36,7 +36,7 @@ namespace Emby.Dlna private readonly ILogger _logger; private readonly IServerApplicationHost _appHost; private static readonly Assembly _assembly = typeof(DlnaManager).Assembly; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private readonly Dictionary> _profiles = new Dictionary>(StringComparer.Ordinal); diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 835dc33b0..164e6d49d 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -10,8 +10,6 @@ using System.Net; using System.Reflection; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; -using System.Text; -using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Emby.Dlna; @@ -51,7 +49,6 @@ using Jellyfin.Networking.Manager; using MediaBrowser.Common; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Events; -using MediaBrowser.Common.Json; using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; @@ -470,7 +467,7 @@ namespace Emby.Server.Implementations } /// - public IReadOnlyCollection GetExports(CreationDelegate defaultFunc, bool manageLifetime = true) + public IReadOnlyCollection GetExports(CreationDelegateFactory defaultFunc, bool manageLifetime = true) { // Convert to list so this isn't executed for each iteration var parts = GetExportTypes() diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 8c5fa09f6..87ebe960a 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -49,7 +49,7 @@ namespace Emby.Server.Implementations.Channels private readonly IProviderManager _providerManager; private readonly IMemoryCache _memoryCache; private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(1, 1); - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; /// /// Initializes a new instance of the class. diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index d78b93bd7..2ae805447 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -88,7 +88,7 @@ namespace Emby.Server.Implementations.Data _imageProcessor = imageProcessor; _typeMapper = new TypeMapper(); - _jsonOptions = JsonDefaults.GetOptions(); + _jsonOptions = JsonDefaults.Options; DbFilePath = Path.Combine(_config.ApplicationPaths.DataPath, "library.db"); } diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 7e0c2c1da..06acb5606 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -56,7 +56,7 @@ namespace Emby.Server.Implementations.HttpServer RemoteEndPoint = remoteEndPoint; QueryString = query; - _jsonOptions = JsonDefaults.GetOptions(); + _jsonOptions = JsonDefaults.Options; LastActivityDate = DateTime.Now; } diff --git a/Emby.Server.Implementations/Library/LiveStreamHelper.cs b/Emby.Server.Implementations/Library/LiveStreamHelper.cs index 2070df31e..c2951dd15 100644 --- a/Emby.Server.Implementations/Library/LiveStreamHelper.cs +++ b/Emby.Server.Implementations/Library/LiveStreamHelper.cs @@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.Library private readonly IMediaEncoder _mediaEncoder; private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; public LiveStreamHelper(IMediaEncoder mediaEncoder, ILogger logger, IApplicationPaths appPaths) { diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index c63eb7017..b2943020c 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -46,7 +46,7 @@ namespace Emby.Server.Implementations.Library private readonly ConcurrentDictionary _openStreams = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1); - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private IMediaSourceProvider[] _providers; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 78a82118e..44a8cdee4 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -28,7 +28,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private readonly IServerApplicationPaths _appPaths; private readonly TaskCompletionSource _taskCompletionSource = new TaskCompletionSource(); private readonly IServerConfigurationManager _serverConfigurationManager; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private bool _hasExited; private Stream _logFileStream; private string _targetPath; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index 57424f043..c20b08088 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { private readonly string _dataPath; private readonly object _fileDataLock = new object(); - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private T[] _items; public ItemDataProvider( diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 6d7c5ac6e..1926e738f 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -35,7 +35,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings private readonly ICryptoProvider _cryptoProvider; private readonly ConcurrentDictionary _tokens = new ConcurrentDictionary(); - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private DateTime _lastErrorResponse; public SchedulesDirect( diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 0760e8127..68173a0ef 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun _networkManager = networkManager; _streamHelper = streamHelper; - _jsonOptions = JsonDefaults.GetOptions(); + _jsonOptions = JsonDefaults.Options; } public string Name => "HD Homerun"; diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 3f9e22106..98de848bc 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -36,7 +36,7 @@ namespace Emby.Server.Implementations.Localization private List _cultures; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; /// /// Initializes a new instance of the class. diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index c579fc8cb..700396c4c 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -70,7 +70,7 @@ namespace Emby.Server.Implementations.Plugins _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _pluginsPath = pluginsPath; _appVersion = appVersion ?? throw new ArgumentNullException(nameof(appVersion)); - _jsonOptions = new JsonSerializerOptions(JsonDefaults.GetOptions()) + _jsonOptions = new JsonSerializerOptions(JsonDefaults.Options) { WriteIndented = true }; @@ -678,7 +678,7 @@ namespace Emby.Server.Implementations.Plugins var entry = versions[x]; if (!string.Equals(lastName, entry.Name, StringComparison.OrdinalIgnoreCase)) { - entry.DllFiles.AddRange(Directory.EnumerateFiles(entry.Path, "*.dll", SearchOption.AllDirectories)); + entry.DllFiles = Directory.GetFiles(entry.Path, "*.dll", SearchOption.AllDirectories); if (entry.IsEnabledAndSupported) { lastName = entry.Name; diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index b302303f8..a145a8423 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -69,7 +69,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// /// The options for the json Serializer. /// - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; /// /// Initializes a new instance of the class. diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 7af52ea65..fc34f93cd 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -92,7 +92,7 @@ namespace Emby.Server.Implementations.Updates _httpClientFactory = httpClientFactory; _config = config; _zipClient = zipClient; - _jsonSerializerOptions = JsonDefaults.GetOptions(); + _jsonSerializerOptions = JsonDefaults.Options; _pluginManager = pluginManager; } diff --git a/Jellyfin.Api/Controllers/ConfigurationController.cs b/Jellyfin.Api/Controllers/ConfigurationController.cs index e1c9f69f6..049a4bed7 100644 --- a/Jellyfin.Api/Controllers/ConfigurationController.cs +++ b/Jellyfin.Api/Controllers/ConfigurationController.cs @@ -25,7 +25,7 @@ namespace Jellyfin.Api.Controllers private readonly IServerConfigurationManager _configurationManager; private readonly IMediaEncoder _mediaEncoder; - private readonly JsonSerializerOptions _serializerOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _serializerOptions = JsonDefaults.Options; /// /// Initializes a new instance of the class. diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index a5aa9bfca..24285bfb9 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -45,7 +45,7 @@ namespace Jellyfin.Api.Controllers { _installationManager = installationManager; _pluginManager = pluginManager; - _serializerOptions = JsonDefaults.GetOptions(); + _serializerOptions = JsonDefaults.Options; _config = config; } diff --git a/Jellyfin.Data/DayOfWeekHelper.cs b/Jellyfin.Data/DayOfWeekHelper.cs index 4e75f4cfd..8d760a155 100644 --- a/Jellyfin.Data/DayOfWeekHelper.cs +++ b/Jellyfin.Data/DayOfWeekHelper.cs @@ -1,67 +1,21 @@ #pragma warning disable CS1591 using System; -using System.Collections.Generic; using Jellyfin.Data.Enums; namespace Jellyfin.Data { public static class DayOfWeekHelper { - public static List GetDaysOfWeek(DynamicDayOfWeek day) + public static DayOfWeek[] GetDaysOfWeek(DynamicDayOfWeek day) { - var days = new List(7); - - if (day == DynamicDayOfWeek.Sunday - || day == DynamicDayOfWeek.Weekend - || day == DynamicDayOfWeek.Everyday) - { - days.Add(DayOfWeek.Sunday); - } - - if (day == DynamicDayOfWeek.Monday - || day == DynamicDayOfWeek.Weekday - || day == DynamicDayOfWeek.Everyday) - { - days.Add(DayOfWeek.Monday); - } - - if (day == DynamicDayOfWeek.Tuesday - || day == DynamicDayOfWeek.Weekday - || day == DynamicDayOfWeek.Everyday) - { - days.Add(DayOfWeek.Tuesday); - } - - if (day == DynamicDayOfWeek.Wednesday - || day == DynamicDayOfWeek.Weekday - || day == DynamicDayOfWeek.Everyday) + return day switch { - days.Add(DayOfWeek.Wednesday); - } - - if (day == DynamicDayOfWeek.Thursday - || day == DynamicDayOfWeek.Weekday - || day == DynamicDayOfWeek.Everyday) - { - days.Add(DayOfWeek.Thursday); - } - - if (day == DynamicDayOfWeek.Friday - || day == DynamicDayOfWeek.Weekday - || day == DynamicDayOfWeek.Everyday) - { - days.Add(DayOfWeek.Friday); - } - - if (day == DynamicDayOfWeek.Saturday - || day == DynamicDayOfWeek.Weekend - || day == DynamicDayOfWeek.Everyday) - { - days.Add(DayOfWeek.Saturday); - } - - return days; + DynamicDayOfWeek.Everyday => new[] { DayOfWeek.Sunday, DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday, DayOfWeek.Saturday, DayOfWeek.Sunday }, + DynamicDayOfWeek.Weekday => new[] { DayOfWeek.Sunday, DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday }, + DynamicDayOfWeek.Weekend => new[] { DayOfWeek.Saturday, DayOfWeek.Sunday }, + _ => new[] { (DayOfWeek)day } + }; } } } diff --git a/Jellyfin.Data/Entities/Libraries/Collection.cs b/Jellyfin.Data/Entities/Libraries/Collection.cs index 39eded752..854f17f80 100644 --- a/Jellyfin.Data/Entities/Libraries/Collection.cs +++ b/Jellyfin.Data/Entities/Libraries/Collection.cs @@ -1,3 +1,4 @@ +#pragma warning disable CA1711 // Identifiers should not have incorrect suffix #pragma warning disable CA2227 using System.Collections.Generic; diff --git a/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs b/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs index 5b03e260e..5e27156a4 100644 --- a/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs +++ b/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs @@ -1,3 +1,5 @@ +#pragma warning disable CA1711 // Identifiers should not have incorrect suffix + using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; diff --git a/Jellyfin.Data/Entities/Permission.cs b/Jellyfin.Data/Entities/Permission.cs index d92e5d9d2..0162e1acf 100644 --- a/Jellyfin.Data/Entities/Permission.cs +++ b/Jellyfin.Data/Entities/Permission.cs @@ -1,3 +1,5 @@ +#pragma warning disable CA1711 // Identifiers should not have incorrect suffix + using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Jellyfin.Data.Enums; diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 42731bb11..0340cda01 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -5,6 +5,8 @@ false true true + AllEnabledByDefault + ../jellyfin.ruleset true true true @@ -24,10 +26,6 @@ GPL-3.0-only - - ../jellyfin.ruleset - - diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index 1a8415ae0..3fc44640b 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -11,6 +11,8 @@ true true enable + AllEnabledByDefault + ../jellyfin.ruleset @@ -30,6 +32,11 @@ + + + + + @@ -37,8 +44,4 @@ - - ../jellyfin.ruleset - - diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs index eab5777d5..fd7cb5ec5 100644 --- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -274,8 +274,8 @@ namespace Jellyfin.Drawing.Skia if (requiresTransparencyHack || forceCleanBitmap) { - using var codec = SKCodec.Create(NormalizePath(path)); - if (codec == null) + using SKCodec codec = SKCodec.Create(NormalizePath(path), out SKCodecResult res); + if (res != SKCodecResult.Success) { origin = GetSKEncodedOrigin(orientation); return null; @@ -345,11 +345,6 @@ namespace Jellyfin.Drawing.Skia private SKBitmap OrientImage(SKBitmap bitmap, SKEncodedOrigin origin) { - if (origin == SKEncodedOrigin.Default) - { - return bitmap; - } - var needsFlip = origin == SKEncodedOrigin.LeftBottom || origin == SKEncodedOrigin.LeftTop || origin == SKEncodedOrigin.RightBottom @@ -447,7 +442,7 @@ namespace Jellyfin.Drawing.Skia } /// - public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) + public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat outputFormat) { if (inputPath.Length == 0) { @@ -459,7 +454,7 @@ namespace Jellyfin.Drawing.Skia throw new ArgumentException("String can't be empty.", nameof(outputPath)); } - var skiaOutputFormat = GetImageFormat(selectedOutputFormat); + var skiaOutputFormat = GetImageFormat(outputFormat); var hasBackgroundColor = !string.IsNullOrWhiteSpace(options.BackgroundColor); var hasForegroundColor = !string.IsNullOrWhiteSpace(options.ForegroundLayer); diff --git a/Jellyfin.Networking/Jellyfin.Networking.csproj b/Jellyfin.Networking/Jellyfin.Networking.csproj index f89a18426..63557e91f 100644 --- a/Jellyfin.Networking/Jellyfin.Networking.csproj +++ b/Jellyfin.Networking/Jellyfin.Networking.csproj @@ -5,6 +5,8 @@ true true enable + AllEnabledByDefault + ../jellyfin.ruleset @@ -18,10 +20,6 @@ - - ../jellyfin.ruleset - - diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs index 2f9f44ed6..8b0bd84c6 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs @@ -29,20 +29,20 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Security } /// - public async Task OnEvent(GenericEventArgs e) + public async Task OnEvent(GenericEventArgs eventArgs) { await _activityManager.CreateAsync(new ActivityLog( string.Format( CultureInfo.InvariantCulture, _localizationManager.GetLocalizedString("AuthenticationSucceededWithUserName"), - e.Argument.User.Name), + eventArgs.Argument.User.Name), "AuthenticationSucceeded", - e.Argument.User.Id) + eventArgs.Argument.User.Id) { ShortOverview = string.Format( CultureInfo.InvariantCulture, _localizationManager.GetLocalizedString("LabelIpAddressValue"), - e.Argument.SessionInfo.RemoteEndPoint), + eventArgs.Argument.SessionInfo.RemoteEndPoint), }).ConfigureAwait(false); } } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedLogger.cs index 05201a346..cbc9f3017 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedLogger.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedLogger.cs @@ -33,10 +33,10 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.System } /// - public async Task OnEvent(TaskCompletionEventArgs e) + public async Task OnEvent(TaskCompletionEventArgs eventArgs) { - var result = e.Result; - var task = e.Task; + var result = eventArgs.Result; + var task = eventArgs.Task; if (task.ScheduledTask is IConfigurableScheduledTask activityTask && !activityTask.IsLogged) @@ -54,14 +54,14 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.System { var vals = new List(); - if (!string.IsNullOrEmpty(e.Result.ErrorMessage)) + if (!string.IsNullOrEmpty(eventArgs.Result.ErrorMessage)) { - vals.Add(e.Result.ErrorMessage); + vals.Add(eventArgs.Result.ErrorMessage); } - if (!string.IsNullOrEmpty(e.Result.LongErrorMessage)) + if (!string.IsNullOrEmpty(eventArgs.Result.LongErrorMessage)) { - vals.Add(e.Result.LongErrorMessage); + vals.Add(eventArgs.Result.LongErrorMessage); } await _activityManager.CreateAsync(new ActivityLog( diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledLogger.cs index 91a30069e..eb7572ac6 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledLogger.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledLogger.cs @@ -30,13 +30,13 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Updates } /// - public async Task OnEvent(PluginUninstalledEventArgs e) + public async Task OnEvent(PluginUninstalledEventArgs eventArgs) { await _activityManager.CreateAsync(new ActivityLog( string.Format( CultureInfo.InvariantCulture, _localizationManager.GetLocalizedString("PluginUninstalledWithName"), - e.Argument.Name), + eventArgs.Argument.Name), NotificationType.PluginUninstalled.ToString(), Guid.Empty)) .ConfigureAwait(false); diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs index a14911b94..9beb6f2f2 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs @@ -30,12 +30,12 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Users } /// - public async Task OnEvent(UserUpdatedEventArgs e) + public async Task OnEvent(UserUpdatedEventArgs eventArgs) { await _sessionManager.SendMessageToUserSessions( - new List { e.Argument.Id }, + new List { eventArgs.Argument.Id }, SessionMessageType.UserUpdated, - _userManager.GetUserDto(e.Argument), + _userManager.GetUserDto(eventArgs.Argument), CancellationToken.None).ConfigureAwait(false); } } diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 19c7ac567..5a5992bd6 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -6,6 +6,8 @@ true true enable + AllEnabledByDefault + ../jellyfin.ruleset diff --git a/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs b/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs index 9cc1c3e5e..c99c5e4ef 100644 --- a/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs +++ b/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs @@ -66,7 +66,7 @@ namespace Jellyfin.Server.Implementations.Users else if (string.Equals( spr.Pin.Replace("-", string.Empty, StringComparison.Ordinal), pin.Replace("-", string.Empty, StringComparison.Ordinal), - StringComparison.InvariantCultureIgnoreCase)) + StringComparison.OrdinalIgnoreCase)) { var resetUser = userManager.GetUserByName(spr.UserName) ?? throw new ResourceNotFoundException($"User with a username of {spr.UserName} not found"); diff --git a/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs b/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs index c8a589cab..a3e9516b9 100644 --- a/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs +++ b/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs @@ -1,4 +1,5 @@ #pragma warning disable CA1307 +#pragma warning disable CA1309 using System; using System.Collections.Generic; @@ -35,7 +36,7 @@ namespace Jellyfin.Server.Implementations.Users if (prefs == null) { - prefs = new DisplayPreferences(userId, itemId, client); + prefs = new DisplayPreferences(userId, itemId, client); _dbContext.DisplayPreferences.Add(prefs); } diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 1828f1a7e..a3f49e6cb 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -225,7 +225,7 @@ namespace Jellyfin.Server.Extensions .AddJsonOptions(options => { // Update all properties that are set in JsonDefaults - var jsonOptions = JsonDefaults.GetPascalCaseOptions(); + var jsonOptions = JsonDefaults.PascalCaseOptions; // From JsonDefaults options.JsonSerializerOptions.ReadCommentHandling = jsonOptions.ReadCommentHandling; diff --git a/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs b/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs index 8043989b1..c349e3dca 100644 --- a/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs +++ b/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs @@ -12,7 +12,7 @@ namespace Jellyfin.Server.Formatters /// /// Initializes a new instance of the class. /// - public CamelCaseJsonProfileFormatter() : base(JsonDefaults.GetCamelCaseOptions()) + public CamelCaseJsonProfileFormatter() : base(JsonDefaults.CamelCaseOptions) { SupportedMediaTypes.Clear(); SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse(JsonDefaults.CamelCaseMediaType)); diff --git a/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs b/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs index d0110b125..0480f5e0e 100644 --- a/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs +++ b/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs @@ -13,7 +13,7 @@ namespace Jellyfin.Server.Formatters /// /// Initializes a new instance of the class. /// - public PascalCaseJsonProfileFormatter() : base(JsonDefaults.GetPascalCaseOptions()) + public PascalCaseJsonProfileFormatter() : base(JsonDefaults.PascalCaseOptions) { SupportedMediaTypes.Clear(); // Add application/json for default formatter diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 6bfb5b878..09799307b 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -13,7 +13,9 @@ true true enable - true + AllEnabledByDefault + ../jellyfin.ruleset + @@ -31,10 +33,6 @@ - - ../jellyfin.ruleset - - diff --git a/Jellyfin.Server/Migrations/MigrationOptions.cs b/Jellyfin.Server/Migrations/MigrationOptions.cs index 816dd9ee7..c9710f1fd 100644 --- a/Jellyfin.Server/Migrations/MigrationOptions.cs +++ b/Jellyfin.Server/Migrations/MigrationOptions.cs @@ -16,9 +16,12 @@ namespace Jellyfin.Server.Migrations Applied = new List<(Guid Id, string Name)>(); } +// .Net xml serializer can't handle interfaces +#pragma warning disable CA1002 // Do not expose generic lists /// /// Gets the list of applied migration routine names. /// public List<(Guid Id, string Name)> Applied { get; } +#pragma warning restore CA1002 } } diff --git a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs index 33f039c39..d61c04447 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs @@ -76,7 +76,7 @@ namespace Jellyfin.Server.Migrations.Routines foreach (var entry in queryResult) { - UserMockup? mockup = JsonSerializer.Deserialize(entry[2].ToBlob(), JsonDefaults.GetOptions()); + UserMockup? mockup = JsonSerializer.Deserialize(entry[2].ToBlob(), JsonDefaults.Options); if (mockup == null) { continue; diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 6ae0542c0..4f203b7a9 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -222,7 +222,7 @@ namespace Jellyfin.Server } finally { - appHost?.Dispose(); + appHost.Dispose(); } if (_restartOnShutdown) @@ -623,7 +623,7 @@ namespace Jellyfin.Server string commandLineArgsString; if (options.RestartArgs != null) { - commandLineArgsString = options.RestartArgs ?? string.Empty; + commandLineArgsString = options.RestartArgs; } else { diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index ddcf2ac17..c3e4ed6db 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -10,7 +10,7 @@ namespace MediaBrowser.Common /// /// Type to create. /// New instance of type type. - public delegate object CreationDelegate(Type type); + public delegate object CreationDelegateFactory(Type type); /// /// An interface to be implemented by the applications hosting a kernel. @@ -112,7 +112,7 @@ namespace MediaBrowser.Common /// Delegate function that gets called to create the object. /// If set to true [manage lifetime]. /// . - IReadOnlyCollection GetExports(CreationDelegate defaultFunc, bool manageLifetime = true); + IReadOnlyCollection GetExports(CreationDelegateFactory defaultFunc, bool manageLifetime = true); /// /// Gets the export types. diff --git a/MediaBrowser.Common/Json/JsonDefaults.cs b/MediaBrowser.Common/Json/JsonDefaults.cs index 2ef24a884..177ad39fa 100644 --- a/MediaBrowser.Common/Json/JsonDefaults.cs +++ b/MediaBrowser.Common/Json/JsonDefaults.cs @@ -61,7 +61,7 @@ namespace MediaBrowser.Common.Json /// If the defaults must be modified the author must use the copy constructor. /// /// The default options. - public static JsonSerializerOptions GetOptions() + public static JsonSerializerOptions Options => _jsonSerializerOptions; /// @@ -72,7 +72,7 @@ namespace MediaBrowser.Common.Json /// If the defaults must be modified the author must use the copy constructor. /// /// The camelCase options. - public static JsonSerializerOptions GetCamelCaseOptions() + public static JsonSerializerOptions CamelCaseOptions => _camelCaseJsonSerializerOptions; /// @@ -83,7 +83,7 @@ namespace MediaBrowser.Common.Json /// If the defaults must be modified the author must use the copy constructor. /// /// The PascalCase options. - public static JsonSerializerOptions GetPascalCaseOptions() + public static JsonSerializerOptions PascalCaseOptions => _pascalCaseJsonSerializerOptions; } } diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 34e1934e2..0d9f78704 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -33,6 +33,8 @@ false true true + AllEnabledByDefault + ../jellyfin.ruleset true true true @@ -51,10 +53,6 @@ - - ../jellyfin.ruleset - - <_Parameter1>Jellyfin.Common.Tests diff --git a/MediaBrowser.Common/Net/IPHost.cs b/MediaBrowser.Common/Net/IPHost.cs index 4a7c70190..d67b6b8e1 100644 --- a/MediaBrowser.Common/Net/IPHost.cs +++ b/MediaBrowser.Common/Net/IPHost.cs @@ -406,7 +406,7 @@ namespace MediaBrowser.Common.Net } // If we haven't resolved before, or our timer has run out... - if ((_addresses.Length == 0 && !Resolved) || (DateTime.UtcNow > _lastResolved?.AddMinutes(Timeout))) + if ((_addresses.Length == 0 && !Resolved) || (DateTime.UtcNow > _lastResolved.Value.AddMinutes(Timeout))) { _lastResolved = DateTime.UtcNow; ResolveHostInternal().GetAwaiter().GetResult(); diff --git a/MediaBrowser.Common/Net/IPNetAddress.cs b/MediaBrowser.Common/Net/IPNetAddress.cs index 5fab52eac..59e37a5c6 100644 --- a/MediaBrowser.Common/Net/IPNetAddress.cs +++ b/MediaBrowser.Common/Net/IPNetAddress.cs @@ -216,11 +216,11 @@ namespace MediaBrowser.Common.Net } /// - public override bool Equals(IPAddress address) + public override bool Equals(IPAddress ip) { - if (address != null && !address.Equals(IPAddress.None) && !Address.Equals(IPAddress.None)) + if (ip != null && !ip.Equals(IPAddress.None) && !Address.Equals(IPAddress.None)) { - return address.Equals(Address); + return ip.Equals(Address); } return false; diff --git a/MediaBrowser.Common/Plugins/BasePlugin.cs b/MediaBrowser.Common/Plugins/BasePlugin.cs index 7b162c0e1..ad5a7338d 100644 --- a/MediaBrowser.Common/Plugins/BasePlugin.cs +++ b/MediaBrowser.Common/Plugins/BasePlugin.cs @@ -50,7 +50,7 @@ namespace MediaBrowser.Common.Plugins /// Gets a value indicating whether the plugin can be uninstalled. /// public bool CanUninstall => !Path.GetDirectoryName(AssemblyFilePath) - .Equals(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), StringComparison.InvariantCulture); + .Equals(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), StringComparison.Ordinal); /// /// Gets the plugin info. diff --git a/MediaBrowser.Common/Plugins/BasePluginOfT.cs b/MediaBrowser.Common/Plugins/BasePluginOfT.cs index d5c780851..99c226f50 100644 --- a/MediaBrowser.Common/Plugins/BasePluginOfT.cs +++ b/MediaBrowser.Common/Plugins/BasePluginOfT.cs @@ -39,29 +39,27 @@ namespace MediaBrowser.Common.Plugins { ApplicationPaths = applicationPaths; XmlSerializer = xmlSerializer; - if (this is IPluginAssembly assemblyPlugin) - { - var assembly = GetType().Assembly; - var assemblyName = assembly.GetName(); - var assemblyFilePath = assembly.Location; - var dataFolderPath = Path.Combine(ApplicationPaths.PluginsPath, Path.GetFileNameWithoutExtension(assemblyFilePath)); - if (!Directory.Exists(dataFolderPath) && Version != null) - { - // Try again with the version number appended to the folder name. - dataFolderPath = dataFolderPath + "_" + Version.ToString(); - } + var assembly = GetType().Assembly; + var assemblyName = assembly.GetName(); + var assemblyFilePath = assembly.Location; - assemblyPlugin.SetAttributes(assemblyFilePath, dataFolderPath, assemblyName.Version); + var dataFolderPath = Path.Combine(ApplicationPaths.PluginsPath, Path.GetFileNameWithoutExtension(assemblyFilePath)); + if (!Directory.Exists(dataFolderPath) && Version != null) + { + // Try again with the version number appended to the folder name. + dataFolderPath = dataFolderPath + "_" + Version.ToString(); + } - var idAttributes = assembly.GetCustomAttributes(typeof(GuidAttribute), true); - if (idAttributes.Length > 0) - { - var attribute = (GuidAttribute)idAttributes[0]; - var assemblyId = new Guid(attribute.Value); + SetAttributes(assemblyFilePath, dataFolderPath, assemblyName.Version); - assemblyPlugin.SetId(assemblyId); - } + var idAttributes = assembly.GetCustomAttributes(typeof(GuidAttribute), true); + if (idAttributes.Length > 0) + { + var attribute = (GuidAttribute)idAttributes[0]; + var assemblyId = new Guid(attribute.Value); + + SetId(assemblyId); } } diff --git a/MediaBrowser.Common/Plugins/LocalPlugin.cs b/MediaBrowser.Common/Plugins/LocalPlugin.cs index 23b6cfa81..12a1ad1ec 100644 --- a/MediaBrowser.Common/Plugins/LocalPlugin.cs +++ b/MediaBrowser.Common/Plugins/LocalPlugin.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Common.Plugins public LocalPlugin(string path, bool isSupported, PluginManifest manifest) { Path = path; - DllFiles = new List(); + DllFiles = Array.Empty(); _supported = isSupported; Manifest = manifest; } @@ -59,9 +59,9 @@ namespace MediaBrowser.Common.Plugins public string Path { get; } /// - /// Gets the list of dll files for this plugin. + /// Gets or sets the list of dll files for this plugin. /// - public List DllFiles { get; } + public IReadOnlyList DllFiles { get; set; } /// /// Gets or sets the instance of this plugin. diff --git a/MediaBrowser.Common/Progress/ActionableProgress.cs b/MediaBrowser.Common/Progress/ActionableProgress.cs index d5bcd5be9..fe7cb1078 100644 --- a/MediaBrowser.Common/Progress/ActionableProgress.cs +++ b/MediaBrowser.Common/Progress/ActionableProgress.cs @@ -1,4 +1,5 @@ #pragma warning disable CS1591 +#pragma warning disable CA1003 using System; diff --git a/MediaBrowser.Common/Progress/SimpleProgress.cs b/MediaBrowser.Common/Progress/SimpleProgress.cs index d75675bf1..988d8ad34 100644 --- a/MediaBrowser.Common/Progress/SimpleProgress.cs +++ b/MediaBrowser.Common/Progress/SimpleProgress.cs @@ -1,4 +1,5 @@ #pragma warning disable CS1591 +#pragma warning disable CA1003 using System; diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 65fd1654c..76b6d39a9 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Entities /// public class CollectionFolder : Folder, ICollectionFolder { - private static readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private static readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; public static IXmlSerializer XmlSerializer { get; set; } public static IServerApplicationHost ApplicationHost { get; set; } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index d487a324f..8c68b47dd 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -34,6 +34,8 @@ false true true + AllEnabledByDefault + ../jellyfin.ruleset true true true @@ -52,8 +54,4 @@ - - ../jellyfin.ruleset - - diff --git a/MediaBrowser.Controller/Providers/ILocalImageProvider.cs b/MediaBrowser.Controller/Providers/ILocalImageProvider.cs index c129eddb3..f78bd6ddf 100644 --- a/MediaBrowser.Controller/Providers/ILocalImageProvider.cs +++ b/MediaBrowser.Controller/Providers/ILocalImageProvider.cs @@ -10,6 +10,6 @@ namespace MediaBrowser.Controller.Providers /// public interface ILocalImageProvider : IImageProvider { - List GetImages(BaseItem item, IDirectoryService directoryService); + IEnumerable GetImages(BaseItem item, IDirectoryService directoryService); } } diff --git a/MediaBrowser.LocalMetadata/Images/CollectionFolderLocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/CollectionFolderLocalImageProvider.cs index 556bb6a0e..b6189bcdd 100644 --- a/MediaBrowser.LocalMetadata/Images/CollectionFolderLocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/CollectionFolderLocalImageProvider.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.LocalMetadata.Images } /// - public List GetImages(BaseItem item, IDirectoryService directoryService) + public IEnumerable GetImages(BaseItem item, IDirectoryService directoryService) { var collectionFolder = (CollectionFolder)item; diff --git a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs index 393ad2efb..2d3b2d889 100644 --- a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs @@ -39,7 +39,7 @@ namespace MediaBrowser.LocalMetadata.Images } /// - public List GetImages(BaseItem item, IDirectoryService directoryService) + public IEnumerable GetImages(BaseItem item, IDirectoryService directoryService) { var parentPath = Path.GetDirectoryName(item.Path); diff --git a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs index 509b5d700..10d691b3e 100644 --- a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Linq; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -69,13 +70,13 @@ namespace MediaBrowser.LocalMetadata.Images } /// - public List GetImages(BaseItem item, IDirectoryService directoryService) + public IEnumerable GetImages(BaseItem item, IDirectoryService directoryService) { var path = item.GetInternalMetadataPath(); if (!Directory.Exists(path)) { - return new List(); + return Enumerable.Empty(); } try @@ -85,7 +86,7 @@ namespace MediaBrowser.LocalMetadata.Images catch (IOException ex) { _logger.LogError(ex, "Error while getting images for {Library}", item.Name); - return new List(); + return Enumerable.Empty(); } } } diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs index 84c3ed8b0..7ad8c24e8 100644 --- a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs @@ -108,7 +108,7 @@ namespace MediaBrowser.LocalMetadata.Images { if (!item.IsFileProtocol) { - return new List(); + return Enumerable.Empty(); } var path = item.ContainingFolderPath; @@ -116,7 +116,7 @@ namespace MediaBrowser.LocalMetadata.Images // Exit if the cache dir does not exist, alternative solution is to create it, but that's a lot of empty dirs... if (!Directory.Exists(path)) { - return Array.Empty(); + return Enumerable.Empty(); } if (includeDirectories) @@ -133,7 +133,7 @@ namespace MediaBrowser.LocalMetadata.Images } /// - public List GetImages(BaseItem item, IDirectoryService directoryService) + public IEnumerable GetImages(BaseItem item, IDirectoryService directoryService) { var files = GetFiles(item, true, directoryService).ToList(); @@ -151,7 +151,7 @@ namespace MediaBrowser.LocalMetadata.Images /// The images path. /// Instance of the interface. /// The local image info. - public List GetImages(BaseItem item, string path, IDirectoryService directoryService) + public IEnumerable GetImages(BaseItem item, string path, IDirectoryService directoryService) { return GetImages(item, new[] { path }, directoryService); } @@ -163,7 +163,7 @@ namespace MediaBrowser.LocalMetadata.Images /// The image paths. /// Instance of the interface. /// The local image info. - public List GetImages(BaseItem item, IEnumerable paths, IDirectoryService directoryService) + public IEnumerable GetImages(BaseItem item, IEnumerable paths, IDirectoryService directoryService) { IEnumerable files = paths.SelectMany(i => _fileSystem.GetFiles(i, BaseItem.SupportedImageExtensions, true, false)); @@ -181,9 +181,7 @@ namespace MediaBrowser.LocalMetadata.Images { if (supportParentSeriesFiles) { - var season = item as Season; - - if (season != null) + if (item is Season season) { PopulateSeasonImagesFromSeriesFolder(season, images, directoryService); } diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index 1792f1d9b..eb2077a5f 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -16,6 +16,8 @@ true true enable + AllEnabledByDefault + ../jellyfin.ruleset @@ -29,8 +31,4 @@ - - ../jellyfin.ruleset - - diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index b0afb834b..5f620634f 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -1275,8 +1275,8 @@ namespace MediaBrowser.LocalMetadata.Parsers // Only split by comma if there is no pipe in the string // We have to be careful to not split names like Matthew, Jr. - var separator = value.IndexOf('|', StringComparison.Ordinal) == -1 - && value.IndexOf(';', StringComparison.Ordinal) == -1 ? new[] { ',' } : new[] { '|', ';' }; + var separator = !value.Contains('|', StringComparison.Ordinal) + && !value.Contains(';', StringComparison.Ordinal) ? new[] { ',' } : new[] { '|', ';' }; value = value.Trim().Trim(separator); diff --git a/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs index ff846830b..7df800971 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.LocalMetadata.Parsers } /// - protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult item) + protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult itemResult) { switch (reader.Name) { @@ -33,7 +33,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { using (var subReader = reader.ReadSubtree()) { - FetchFromCollectionItemsNode(subReader, item); + FetchFromCollectionItemsNode(subReader, itemResult); } } else @@ -44,7 +44,7 @@ namespace MediaBrowser.LocalMetadata.Parsers break; default: - base.FetchDataFromXmlNode(reader, item); + base.FetchDataFromXmlNode(reader, itemResult); break; } } diff --git a/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs index 78c0fa8ad..b84307cb2 100644 --- a/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs @@ -23,9 +23,9 @@ namespace MediaBrowser.LocalMetadata.Parsers } /// - protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult result) + protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult itemResult) { - var item = result.Item; + var item = itemResult.Item; switch (reader.Name) { @@ -53,7 +53,7 @@ namespace MediaBrowser.LocalMetadata.Parsers break; default: - base.FetchDataFromXmlNode(reader, result); + base.FetchDataFromXmlNode(reader, itemResult); break; } } diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index e59fcb965..dfbce5f49 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Text; using System.Threading; using System.Xml; -using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -37,7 +36,7 @@ namespace MediaBrowser.LocalMetadata.Savers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - public BaseXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger) + protected BaseXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger) { FileSystem = fileSystem; ConfigurationManager = configurationManager; @@ -421,20 +420,17 @@ namespace MediaBrowser.LocalMetadata.Savers writer.WriteEndElement(); } - var boxset = item as BoxSet; - if (boxset != null) + if (item is BoxSet boxset) { AddLinkedChildren(boxset, writer, "CollectionItems", "CollectionItem"); } - var playlist = item as Playlist; - if (playlist != null && !Playlist.IsPlaylistFile(playlist.Path)) + if (item is Playlist playlist && !Playlist.IsPlaylistFile(playlist.Path)) { AddLinkedChildren(playlist, writer, "PlaylistItems", "PlaylistItem"); } - var hasShares = item as IHasShares; - if (hasShares != null) + if (item is IHasShares hasShares) { AddShares(hasShares, writer); } @@ -542,10 +538,5 @@ namespace MediaBrowser.LocalMetadata.Savers writer.WriteEndElement(); } - - private bool IsPersonType(PersonInfo person, string type) - { - return string.Equals(person.Type, type, StringComparison.OrdinalIgnoreCase) || string.Equals(person.Role, type, StringComparison.OrdinalIgnoreCase); - } } } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 8a25a64c7..47cf020b4 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -86,7 +86,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _localization = localization; _encodingHelperFactory = encodingHelperFactory; _startupOptionFFmpegPath = config.GetValue(Controller.Extensions.ConfigurationExtensions.FfmpegPathKey) ?? string.Empty; - _jsonSerializerOptions = JsonDefaults.GetOptions(); + _jsonSerializerOptions = JsonDefaults.Options; } /// diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs index cd9e47743..2adb11908 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb { private readonly IServerConfigurationManager _config; private readonly IHttpClientFactory _httpClientFactory; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; public AudioDbAlbumImageProvider(IServerConfigurationManager config, IHttpClientFactory httpClientFactory) { diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs index 0a79f5bb5..00feeec1f 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs @@ -29,7 +29,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; private readonly IHttpClientFactory _httpClientFactory; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; public static AudioDbAlbumProvider Current; diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs index 36700d191..b8095ff04 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb { private readonly IServerConfigurationManager _config; private readonly IHttpClientFactory _httpClientFactory; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; public AudioDbArtistImageProvider(IServerConfigurationManager config, IHttpClientFactory httpClientFactory) { diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs index 4b1d91567..59ecbc017 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs @@ -31,7 +31,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; private readonly IHttpClientFactory _httpClientFactory; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; public AudioDbArtistProvider(IServerConfigurationManager config, IFileSystem fileSystem, IHttpClientFactory httpClientFactory) { diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs index 97fcbfb6f..428b0ded1 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs @@ -48,7 +48,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb _configurationManager = configurationManager; _appHost = appHost; - _jsonOptions = new JsonSerializerOptions(JsonDefaults.GetOptions()); + _jsonOptions = new JsonSerializerOptions(JsonDefaults.Options); _jsonOptions.Converters.Add(new JsonOmdbNotAvailableStringConverter()); _jsonOptions.Converters.Add(new JsonOmdbNotAvailableInt32Converter()); } diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index e3301ff32..d35805a84 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -39,7 +39,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb _configurationManager = configurationManager; _appHost = appHost; - _jsonOptions = new JsonSerializerOptions(JsonDefaults.GetOptions()); + _jsonOptions = new JsonSerializerOptions(JsonDefaults.Options); _jsonOptions.Converters.Add(new JsonOmdbNotAvailableStringConverter()); _jsonOptions.Converters.Add(new JsonOmdbNotAvailableInt32Converter()); } diff --git a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs index c39ef0ce9..415682e85 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs @@ -16,7 +16,7 @@ namespace Jellyfin.MediaEncoding.Tests var path = Path.Join("Test Data", fileName); using (var stream = File.OpenRead(path)) { - await JsonSerializer.DeserializeAsync(stream, JsonDefaults.GetOptions()).ConfigureAwait(false); + await JsonSerializer.DeserializeAsync(stream, JsonDefaults.Options).ConfigureAwait(false); } } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs index 86d6326d8..f5411dcb8 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs @@ -13,7 +13,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public sealed class DashboardControllerTests : IClassFixture { private readonly JellyfinApplicationFactory _factory; - private readonly JsonSerializerOptions _jsonOpions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOpions = JsonDefaults.Options; public DashboardControllerTests(JellyfinApplicationFactory factory) { -- cgit v1.2.3 From ab0cff8556403e123642dc9717ba778329554634 Mon Sep 17 00:00:00 2001 From: cvium Date: Sun, 14 Mar 2021 19:56:45 +0100 Subject: do not resolve episode-like files if they are in extras folders --- .../Library/Resolvers/BaseVideoResolver.cs | 2 +- .../Library/Resolvers/Books/BookResolver.cs | 2 +- .../Library/Resolvers/Movies/MovieResolver.cs | 208 ++++++++++----------- .../Library/Resolvers/TV/EpisodeResolver.cs | 12 +- .../Resolvers/BaseItemResolver.cs | 2 +- 5 files changed, 114 insertions(+), 112 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index 2f5e46038..dd92e252f 100644 --- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -30,7 +30,7 @@ namespace Emby.Server.Implementations.Library.Resolvers /// /// The args. /// `0. - protected override T Resolve(ItemResolveArgs args) + public override T Resolve(ItemResolveArgs args) { return ResolveVideo(args, false); } diff --git a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs index 86242d137..0525c7e30 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs @@ -13,7 +13,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books { private readonly string[] _validExtensions = { ".azw", ".azw3", ".cb7", ".cbr", ".cbt", ".cbz", ".epub", ".mobi", ".pdf" }; - protected override Book Resolve(ItemResolveArgs args) + public override Book Resolve(ItemResolveArgs args) { var collectionType = args.GetCollectionType(); diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 8ef7172de..714bc3a84 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -69,6 +69,110 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return result; } + /// + /// Resolves the specified args. + /// + /// The args. + /// Video. + public override Video Resolve(ItemResolveArgs args) + { + var collectionType = args.GetCollectionType(); + + // Find movies with their own folders + if (args.IsDirectory) + { + if (IsInvalid(args.Parent, collectionType)) + { + return null; + } + + var files = args.FileSystemChildren + .Where(i => !LibraryManager.IgnoreFile(i, args.Parent)) + .ToList(); + + if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) + { + return FindMovie(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false); + } + + if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase)) + { + return FindMovie /// The args. /// Episode. - protected override Episode Resolve(ItemResolveArgs args) + public override Episode Resolve(ItemResolveArgs args) { var parent = args.Parent; @@ -34,11 +35,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV season = parent.GetParents().OfType().FirstOrDefault(); } - // If the parent is a Season or Series, then this is an Episode if the VideoResolver returns something + // If the parent is a Season or Series and the parent is not an extras folder, then this is an Episode if the VideoResolver returns something // Also handle flat tv folders - if (season != null || - string.Equals(args.GetCollectionType(), CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) || - args.HasParent()) + if ((season != null || + string.Equals(args.GetCollectionType(), CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) || + args.HasParent()) + && !BaseItem.AllExtrasTypesFolderNames.Contains(parent.Name, StringComparer.OrdinalIgnoreCase)) { var episode = ResolveVideo(args, false); diff --git a/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs b/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs index 67acdd9a3..25128a5cd 100644 --- a/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs +++ b/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Resolvers /// /// The args. /// `0. - protected virtual T Resolve(ItemResolveArgs args) + public virtual T Resolve(ItemResolveArgs args) { return null; } -- cgit v1.2.3 From 025e351f619137426a0a64074ca2ada863ccc493 Mon Sep 17 00:00:00 2001 From: cvium Date: Mon, 15 Mar 2021 08:25:20 +0100 Subject: add unit tests --- .../Library/Resolvers/BaseVideoResolver.cs | 2 +- .../Library/Resolvers/TV/EpisodeResolver.cs | 20 +++---- .../Library/EpisodeResolverTest.cs | 65 ++++++++++++++++++++++ 3 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index dd92e252f..6e688693b 100644 --- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -42,7 +42,7 @@ namespace Emby.Server.Implementations.Library.Resolvers /// The args. /// if set to true [parse name]. /// ``0. - protected TVideoType ResolveVideo(ItemResolveArgs args, bool parseName) + protected virtual TVideoType ResolveVideo(ItemResolveArgs args, bool parseName) where TVideoType : Video, new() { var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs index da65c746d..9b4cd7a3d 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs @@ -12,6 +12,15 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV /// public class EpisodeResolver : BaseVideoResolver { + /// + /// Initializes a new instance of the class. + /// + /// The library manager. + public EpisodeResolver(ILibraryManager libraryManager) + : base(libraryManager) + { + } + /// /// Resolves the specified args. /// @@ -40,7 +49,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV if ((season != null || string.Equals(args.GetCollectionType(), CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) || args.HasParent()) - && !BaseItem.AllExtrasTypesFolderNames.Contains(parent.Name, StringComparer.OrdinalIgnoreCase)) + && (parent is Series || !BaseItem.AllExtrasTypesFolderNames.Contains(parent.Name, StringComparer.OrdinalIgnoreCase))) { var episode = ResolveVideo(args, false); @@ -76,14 +85,5 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return null; } - - /// - /// Initializes a new instance of the class. - /// - /// The library manager. - public EpisodeResolver(ILibraryManager libraryManager) - : base(libraryManager) - { - } } } diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs new file mode 100644 index 000000000..876519215 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs @@ -0,0 +1,65 @@ +using System; +using Emby.Server.Implementations.Library.Resolvers.TV; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using Moq; +using Xunit; + +namespace Jellyfin.Server.Implementations.Tests.Library +{ + public class EpisodeResolverTest + { + [Fact] + public void Resolve_GivenVideoInExtrasFolder_DoesNotResolveToEpisode() + { + var season = new Season { Name = "Season 1" }; + var parent = new Folder { Name = "extras" }; + var libraryManagerMock = new Mock(); + libraryManagerMock.Setup(x => x.GetItemById(It.IsAny())).Returns(season); + + var episodeResolver = new EpisodeResolver(libraryManagerMock.Object); + var itemResolveArgs = new ItemResolveArgs( + Mock.Of(), + Mock.Of()) + { + Parent = parent, + CollectionType = CollectionType.TvShows, + Path = "All My Children/Season 01/Extras/All My Children S01E01 - Behind The Scenes.mkv" + }; + + Assert.Null(episodeResolver.Resolve(itemResolveArgs)); + } + + [Fact] + public void Resolve_GivenVideoInExtrasSeriesFolder_ResolvesToEpisode() + { + var series = new Series { Name = "Extras" }; + + // Have to create a mock because of moq proxies not being castable to a concrete implementation + // https://github.com/jellyfin/jellyfin/blob/ab0cff8556403e123642dc9717ba778329554634/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs#L48 + var episodeResolver = new EpisodeResolverMock(Mock.Of()); + var itemResolveArgs = new ItemResolveArgs( + Mock.Of(), + Mock.Of()) + { + Parent = series, + CollectionType = CollectionType.TvShows, + Path = "Extras/Extras S01E01.mkv" + }; + Assert.NotNull(episodeResolver.Resolve(itemResolveArgs)); + } + + private class EpisodeResolverMock : EpisodeResolver + { + public EpisodeResolverMock(ILibraryManager libraryManager) : base(libraryManager) + { + } + + protected override TVideoType ResolveVideo(ItemResolveArgs args, bool parseName) => new (); + } + } +} -- cgit v1.2.3 From e14311ca8b86fa14033d2c02f9b003f235fa7e6a Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Tue, 16 Mar 2021 17:40:56 +0000 Subject: Translated using Weblate (Esperanto) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/ --- .../Localization/Core/eo.json | 23 +++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/eo.json b/Emby.Server.Implementations/Localization/Core/eo.json index 3ff7eddae..ca615cc8c 100644 --- a/Emby.Server.Implementations/Localization/Core/eo.json +++ b/Emby.Server.Implementations/Localization/Core/eo.json @@ -22,5 +22,26 @@ "Artists": "Artistoj", "Application": "Aplikaĵo", "AppDeviceValues": "Aplikaĵo: {0}, Aparato: {1}", - "Albums": "Albumoj" + "Albums": "Albumoj", + "TasksLibraryCategory": "Libraro", + "VersionNumber": "Versio {0}", + "UserDownloadingItemWithValues": "{0} elŝutas {1}", + "UserCreatedWithName": "Uzanto {0} kreiĝis", + "User": "Uzanto", + "System": "Sistemo", + "Songs": "Kantoj", + "ScheduledTaskStartedWithName": "{0} komencis", + "ScheduledTaskFailedWithName": "{0} malsukcesis", + "PluginUninstalledWithName": "{0} malinstaliĝis", + "PluginInstalledWithName": "{0} instaliĝis", + "Plugin": "Kromprogramo", + "Playlists": "Ludlistoj", + "Photos": "Fotoj", + "NotificationOptionPluginUninstalled": "Kromprogramo malinstaliĝis", + "NotificationOptionNewLibraryContent": "Nova enhavo aldoniĝis", + "NotificationOptionPluginInstalled": "Kromprogramo instaliĝis", + "MusicVideos": "Muzikvideoj", + "LabelIpAddressValue": "IP-adreso: {0}", + "Genres": "Ĝenroj", + "DeviceOfflineWithName": "{0} malkonektis" } -- cgit v1.2.3 From 14cbd22fbe0a1989f70895edbd0a0f52d850d55e Mon Sep 17 00:00:00 2001 From: David Date: Tue, 16 Mar 2021 21:11:34 +0100 Subject: Use Helper Methods for provider url parsing --- .../Library/PathExtensions.cs | 5 +- MediaBrowser.Common/Providers/ProviderIdParsers.cs | 119 +++++++++++++++++++++ MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 35 +++--- .../Parsers/SeriesNfoParser.cs | 3 - .../Providers/ProviderIdParserTests.cs | 63 +++++++++++ 5 files changed, 201 insertions(+), 24 deletions(-) create mode 100644 MediaBrowser.Common/Providers/ProviderIdParsers.cs create mode 100644 tests/Jellyfin.Common.Tests/Providers/ProviderIdParserTests.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs index 7dcc925c2..72fe5a854 100644 --- a/Emby.Server.Implementations/Library/PathExtensions.cs +++ b/Emby.Server.Implementations/Library/PathExtensions.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text.RegularExpressions; +using MediaBrowser.Common.Providers; namespace Emby.Server.Implementations.Library { @@ -43,8 +44,8 @@ namespace Emby.Server.Implementations.Library // for imdbid we also accept pattern matching if (string.Equals(attribute, "imdbid", StringComparison.OrdinalIgnoreCase)) { - var m = Regex.Match(str, "tt([0-9]{7,8})", RegexOptions.IgnoreCase); - return m.Success ? m.Value : null; + var match = ProviderIdParsers.TryParseImdbId(str, out var imdbId); + return match ? imdbId : null; } return null; diff --git a/MediaBrowser.Common/Providers/ProviderIdParsers.cs b/MediaBrowser.Common/Providers/ProviderIdParsers.cs new file mode 100644 index 000000000..56e0112dd --- /dev/null +++ b/MediaBrowser.Common/Providers/ProviderIdParsers.cs @@ -0,0 +1,119 @@ +#nullable enable + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace MediaBrowser.Common.Providers +{ + /// + /// Parsers for provider ids. + /// + public static class ProviderIdParsers + { + /// + /// Parses an IMDb id from a string. + /// + /// The text to parse. + /// The parsed IMDb id. + /// True if parsing was successful, false otherwise. + public static bool TryParseImdbId(string text, [NotNullWhen(true)] out string? imdbId) + { + var span = text.AsSpan(); + var tt = "tt".AsSpan(); + + while (true) + { + var ttPos = span.IndexOf(tt); + if (ttPos == -1) + { + imdbId = default; + return false; + } + + span = span.Slice(ttPos + tt.Length); + + int i = 0; + // IMDb id has a maximum of 8 digits + int max = span.Length > 8 ? 8 : span.Length; + for (; i < max; i++) + { + var c = span[i]; + + if (c < '0' || c > '9') + { + break; + } + } + + // IMDb id has a minimum of 7 digits + if (i >= 7) + { + imdbId = string.Concat(tt, span.Slice(0, i)); + return true; + } + } + } + + /// + /// Parses an TMDb id from a movie url. + /// + /// The text with the url to parse. + /// The parsed TMDb id. + /// True if parsing was successful, false otherwise. + public static bool TryParseTmdbMovieId(string text, [NotNullWhen(true)] out string? tmdbId) + => TryParseProviderId(text, "themoviedb.org/movie/", out tmdbId); + + /// + /// Parses an TMDb id from a series url. + /// + /// The text with the url to parse. + /// The parsed TMDb id. + /// True if parsing was successful, false otherwise. + public static bool TryParseTmdbSeriesId(string text, [NotNullWhen(true)] out string? tmdbId) + => TryParseProviderId(text, "themoviedb.org/tv/", out tmdbId); + + /// + /// Parses an TVDb id from a url. + /// + /// The text with the url to parse. + /// The parsed TVDb id. + /// True if parsing was successful, false otherwise. + public static bool TryParseTvdbId(string text, [NotNullWhen(true)] out string? tvdbId) + => TryParseProviderId(text, "thetvdb.com/?tab=series&id=", out tvdbId); + + private static bool TryParseProviderId(string text, string searchString, [NotNullWhen(true)] out string? providerId) + { + var span = text.AsSpan(); + var searchSpan = searchString.AsSpan(); + + while (true) + { + var searchPos = span.IndexOf(searchSpan); + if (searchPos == -1) + { + providerId = default; + return false; + } + + span = span.Slice(searchPos + searchSpan.Length); + + int i = 0; + for (; i < span.Length; i++) + { + var c = span[i]; + + if (c < '0' || c > '9') + { + break; + } + } + + if (i >= 1) + { + providerId = span.Slice(0, i).ToString(); + return true; + } + } + } + } +} diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 3129c131d..d2fa120e8 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -6,11 +6,12 @@ using System.Globalization; using System.IO; using System.Linq; using System.Text; -using System.Text.RegularExpressions; using System.Threading; using System.Xml; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Providers; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; @@ -63,8 +64,6 @@ namespace MediaBrowser.XbmcMetadata.Parsers protected virtual bool SupportsUrlAfterClosingXmlTag => false; - protected virtual string TmdbRegex => "themoviedb\\.org\\/movie\\/([0-9]+)"; - /// /// Fetches metadata for an item from one xml file. /// @@ -220,31 +219,29 @@ namespace MediaBrowser.XbmcMetadata.Parsers protected void ParseProviderLinks(T item, string xml) { - // IMDB: - // https://www.imdb.com/title/tt4154796 - var imdbRegex = Regex.Match(xml, "tt([0-9]{7,8})", RegexOptions.Compiled); - if (imdbRegex.Success) + if (ProviderIdParsers.TryParseImdbId(xml, out var imdbId)) { - item.SetProviderId(MetadataProvider.Imdb, imdbRegex.Value); + item.SetProviderId(MetadataProvider.Imdb, imdbId); } - // TMDB: - // https://www.themoviedb.org/movie/30287-fallo (movie) - // https://www.themoviedb.org/tv/1668-friends (tv) - var tmdbRegex = Regex.Match(xml, TmdbRegex, RegexOptions.Compiled); - if (tmdbRegex.Success) + if (item is Movie) { - item.SetProviderId(MetadataProvider.Tmdb, tmdbRegex.Groups[1].Value); + if (ProviderIdParsers.TryParseTmdbMovieId(xml, out var tmdbId)) + { + item.SetProviderId(MetadataProvider.Tmdb, tmdbId); + } } - // TVDB: - // https://www.thetvdb.com/?tab=series&id=121361 if (item is Series) { - var tvdbRegex = Regex.Match(xml, "thetvdb\\.com\\/\\?tab=series\\&id=([0-9]+)", RegexOptions.Compiled); - if (tvdbRegex.Success) + if (ProviderIdParsers.TryParseTmdbSeriesId(xml, out var tmdbId)) + { + item.SetProviderId(MetadataProvider.Tmdb, tmdbId); + } + + if (ProviderIdParsers.TryParseTvdbId(xml, out var tvdbId)) { - item.SetProviderId(MetadataProvider.Tvdb, tvdbRegex.Groups[1].Value); + item.SetProviderId(MetadataProvider.Tvdb, tvdbId); } } } diff --git a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs index c09781b1a..1dce378dc 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs @@ -35,9 +35,6 @@ namespace MediaBrowser.XbmcMetadata.Parsers /// protected override bool SupportsUrlAfterClosingXmlTag => true; - /// - protected override string TmdbRegex => "themoviedb\\.org\\/tv\\/([0-9]+)"; - /// protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult itemResult) { diff --git a/tests/Jellyfin.Common.Tests/Providers/ProviderIdParserTests.cs b/tests/Jellyfin.Common.Tests/Providers/ProviderIdParserTests.cs new file mode 100644 index 000000000..a493dda64 --- /dev/null +++ b/tests/Jellyfin.Common.Tests/Providers/ProviderIdParserTests.cs @@ -0,0 +1,63 @@ +using MediaBrowser.Common.Providers; +using Xunit; + +namespace Jellyfin.Common.Tests.Providers +{ + public class ProviderIdParserTests + { + [Theory] + [InlineData("tt123456", false, null)] + [InlineData("tt1234567", true, "tt1234567")] + [InlineData("tt12345678", true, "tt12345678")] + [InlineData("https://www.imdb.com/title/tt123456", false, null)] + [InlineData("https://www.imdb.com/title/tt1234567", true, "tt1234567")] + [InlineData("https://www.imdb.com/title/tt12345678", true, "tt12345678")] + [InlineData(@"multiline\nhttps://www.imdb.com/title/tt1234567", true, "tt1234567")] + [InlineData(@"multiline\nhttps://www.imdb.com/title/tt12345678", true, "tt12345678")] + [InlineData("Jellyfin", false, null)] + [InlineData("tt1234567tt7654321", true, "tt1234567")] + [InlineData("tt12345678tt7654321", true, "tt12345678")] + public void Parse_Imdb(string text, bool shouldSucceed, string? imdbId) + { + var succeeded = ProviderIdParsers.TryParseImdbId(text, out string? parsedId); + Assert.Equal(shouldSucceed, succeeded); + Assert.Equal(imdbId, parsedId); + } + + [Theory] + [InlineData("https://www.themoviedb.org/movie/30287-fallo", true, "30287")] + [InlineData("themoviedb.org/movie/30287", true, "30287")] + [InlineData("https://www.themoviedb.org/movie/fallo-30287", false, null)] + [InlineData("https://www.themoviedb.org/tv/1668-friends", false, null)] + public void Parse_TmdbMovie(string text, bool shouldSucceed, string? tmdbId) + { + var succeeded = ProviderIdParsers.TryParseTmdbMovieId(text, out string? parsedId); + Assert.Equal(shouldSucceed, succeeded); + Assert.Equal(tmdbId, parsedId); + } + + [Theory] + [InlineData("https://www.themoviedb.org/tv/1668-friends", true, "1668")] + [InlineData("themoviedb.org/tv/1668", true, "1668")] + [InlineData("https://www.themoviedb.org/tv/friends-1668", false, null)] + [InlineData("https://www.themoviedb.org/movie/30287-fallo", false, null)] + public void Parse_TmdbSeries(string text, bool shouldSucceed, string? tmdbId) + { + var succeeded = ProviderIdParsers.TryParseTmdbSeriesId(text, out string? parsedId); + Assert.Equal(shouldSucceed, succeeded); + Assert.Equal(tmdbId, parsedId); + } + + [Theory] + [InlineData("https://www.thetvdb.com/?tab=series&id=121361", true, "121361")] + [InlineData("thetvdb.com/?tab=series&id=121361", true, "121361")] + [InlineData("thetvdb.com/?tab=series&id=Jellyfin121361", false, null)] + [InlineData("https://www.themoviedb.org/tv/1668-friends", false, null)] + public void Parse_Tvdb(string text, bool shouldSucceed, string? tvdbId) + { + var succeeded = ProviderIdParsers.TryParseTvdbId(text, out string? parsedId); + Assert.Equal(shouldSucceed, succeeded); + Assert.Equal(tvdbId, parsedId); + } + } +} -- cgit v1.2.3 From 37aa3e8735bf0089333cd19d6a0d03ed496e9f17 Mon Sep 17 00:00:00 2001 From: Vitorvlv Date: Wed, 17 Mar 2021 01:13:53 +0000 Subject: Translated using Weblate (Portuguese (Brazil)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pt_BR/ --- Emby.Server.Implementations/Localization/Core/pt-BR.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/pt-BR.json b/Emby.Server.Implementations/Localization/Core/pt-BR.json index 5ec8f1e88..323dcced0 100644 --- a/Emby.Server.Implementations/Localization/Core/pt-BR.json +++ b/Emby.Server.Implementations/Localization/Core/pt-BR.json @@ -16,7 +16,7 @@ "Folders": "Pastas", "Genres": "Gêneros", "HeaderAlbumArtists": "Artistas do Álbum", - "HeaderContinueWatching": "Continuar Assistindo", + "HeaderContinueWatching": "Continuar assistindo", "HeaderFavoriteAlbums": "Álbuns Favoritos", "HeaderFavoriteArtists": "Artistas favoritos", "HeaderFavoriteEpisodes": "Episódios favoritos", -- cgit v1.2.3 From 9857c21717380261e11ec948c3520a673ffd83ae Mon Sep 17 00:00:00 2001 From: andrewthemeow Date: Fri, 19 Mar 2021 06:29:39 +0000 Subject: Translated using Weblate (Lithuanian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/lt/ --- Emby.Server.Implementations/Localization/Core/lt-LT.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/lt-LT.json b/Emby.Server.Implementations/Localization/Core/lt-LT.json index d4cb592ef..9920ef4d5 100644 --- a/Emby.Server.Implementations/Localization/Core/lt-LT.json +++ b/Emby.Server.Implementations/Localization/Core/lt-LT.json @@ -113,5 +113,9 @@ "TasksChannelsCategory": "Internetiniai Kanalai", "TasksApplicationCategory": "Programa", "TasksLibraryCategory": "Mediateka", - "TasksMaintenanceCategory": "Priežiūra" + "TasksMaintenanceCategory": "Priežiūra", + "TaskCleanActivityLog": "Švarus veiklos žurnalas", + "Undefined": "Neapibrėžtas", + "Forced": "Priverstas", + "Default": "Numatytas" } -- cgit v1.2.3 From 32853ca2441d4b730258e6911faa56eba608dc1d Mon Sep 17 00:00:00 2001 From: LIAUD Date: Sat, 20 Mar 2021 20:15:19 +0100 Subject: Add 'group-title' channel parsing --- Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs | 5 +++++ MediaBrowser.Controller/LiveTv/ChannelInfo.cs | 6 ++++++ 2 files changed, 11 insertions(+) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index c4f173c7a..2af635492 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -133,6 +133,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts channel.ImageUrl = value; } + if (attributes.TryGetValue("group-title", out string groupTitle)) + { + channel.ChannelGroup = groupTitle; + } + channel.Name = GetChannelName(extInf, attributes); channel.Number = GetChannelNumber(extInf, attributes, mediaUrl); diff --git a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs index 44bd38b54..0f3f87847 100644 --- a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs +++ b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs @@ -45,6 +45,12 @@ namespace MediaBrowser.Controller.LiveTv /// The type of the channel. public ChannelType ChannelType { get; set; } + /// + /// Gets or sets the group of the channel + /// + /// The group of the channel + public string ChannelGroup { get; set; } + /// /// Supply the image path if it can be accessed directly from the file system. /// -- cgit v1.2.3 From 4637bbc723b2462ca01cb6cc5bd7e5e8b70b10c2 Mon Sep 17 00:00:00 2001 From: Kenneth SB Date: Mon, 22 Mar 2021 15:24:00 +0000 Subject: Translated using Weblate (Danish) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/da/ --- Emby.Server.Implementations/Localization/Core/da.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/da.json b/Emby.Server.Implementations/Localization/Core/da.json index 4ee4eb989..051d6d009 100644 --- a/Emby.Server.Implementations/Localization/Core/da.json +++ b/Emby.Server.Implementations/Localization/Core/da.json @@ -1,5 +1,5 @@ { - "Albums": "Albums", + "Albums": "Albummer", "AppDeviceValues": "App: {0}, Enhed: {1}", "Application": "Applikation", "Artists": "Kunstnere", -- cgit v1.2.3 From 19e4ef82dda1cbba9d533047950afb42c425749a Mon Sep 17 00:00:00 2001 From: David Date: Tue, 23 Mar 2021 17:16:10 +0100 Subject: Remove conversion from IPAddress to string to IPAddress --- .../HttpServer/Security/SessionContext.cs | 2 +- Jellyfin.Api/Controllers/UserController.cs | 25 ++++++++++++++++------ Jellyfin.Api/Helpers/DynamicHlsHelper.cs | 2 +- Jellyfin.Api/Helpers/MediaInfoHelper.cs | 5 +++-- Jellyfin.Api/Helpers/RequestHelpers.cs | 2 +- .../Extensions/HttpContextExtensions.cs | 4 ++-- .../LocalAccessPolicy/LocalAccessHandlerTests.cs | 3 ++- 7 files changed, 28 insertions(+), 15 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs index 040b6b9e4..dd77b45d8 100644 --- a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs @@ -28,7 +28,7 @@ namespace Emby.Server.Implementations.HttpServer.Security var authorization = _authContext.GetAuthorizationInfo(requestContext); var user = authorization.User; - return _sessionManager.LogSessionActivity(authorization.Client, authorization.Version, authorization.DeviceId, authorization.Device, requestContext.GetNormalizedRemoteIp(), user); + return _sessionManager.LogSessionActivity(authorization.Client, authorization.Version, authorization.DeviceId, authorization.Device, requestContext.GetNormalizedRemoteIp().ToString(), user); } public SessionInfo GetSession(object requestContext) diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index 43ee309b7..3c0d2aca1 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -21,6 +21,7 @@ using MediaBrowser.Model.Users; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; namespace Jellyfin.Api.Controllers { @@ -36,6 +37,7 @@ namespace Jellyfin.Api.Controllers private readonly IDeviceManager _deviceManager; private readonly IAuthorizationContext _authContext; private readonly IServerConfigurationManager _config; + private readonly ILogger _logger; /// /// Initializes a new instance of the class. @@ -46,13 +48,15 @@ namespace Jellyfin.Api.Controllers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public UserController( IUserManager userManager, ISessionManager sessionManager, INetworkManager networkManager, IDeviceManager deviceManager, IAuthorizationContext authContext, - IServerConfigurationManager config) + IServerConfigurationManager config, + ILogger logger) { _userManager = userManager; _sessionManager = sessionManager; @@ -60,6 +64,7 @@ namespace Jellyfin.Api.Controllers _deviceManager = deviceManager; _authContext = authContext; _config = config; + _logger = logger; } /// @@ -118,7 +123,7 @@ namespace Jellyfin.Api.Controllers return NotFound("User not found"); } - var result = _userManager.GetUserDto(user, HttpContext.GetNormalizedRemoteIp()); + var result = _userManager.GetUserDto(user, HttpContext.GetNormalizedRemoteIp().ToString()); return result; } @@ -204,7 +209,7 @@ namespace Jellyfin.Api.Controllers DeviceName = auth.Device, Password = request.Pw, PasswordSha1 = request.Password, - RemoteEndPoint = HttpContext.GetNormalizedRemoteIp(), + RemoteEndPoint = HttpContext.GetNormalizedRemoteIp().ToString(), Username = request.Username }).ConfigureAwait(false); @@ -291,7 +296,7 @@ namespace Jellyfin.Api.Controllers user.Username, request.CurrentPw, request.CurrentPw, - HttpContext.GetNormalizedRemoteIp(), + HttpContext.GetNormalizedRemoteIp().ToString(), false).ConfigureAwait(false); if (success == null) @@ -483,7 +488,7 @@ namespace Jellyfin.Api.Controllers await _userManager.ChangePassword(newUser, request.Password).ConfigureAwait(false); } - var result = _userManager.GetUserDto(newUser, HttpContext.GetNormalizedRemoteIp()); + var result = _userManager.GetUserDto(newUser, HttpContext.GetNormalizedRemoteIp().ToString()); return result; } @@ -498,8 +503,14 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public async Task> ForgotPassword([FromBody, Required] ForgotPasswordDto forgotPasswordRequest) { + var ip = HttpContext.GetNormalizedRemoteIp(); var isLocal = HttpContext.IsLocal() - || _networkManager.IsInLocalNetwork(HttpContext.GetNormalizedRemoteIp()); + || _networkManager.IsInLocalNetwork(ip); + + if (isLocal) + { + _logger.LogWarning("Password reset proccess initiated from outside the local network with IP: {IP}", ip); + } var result = await _userManager.StartForgotPasswordProcess(forgotPasswordRequest.EnteredUsername, isLocal).ConfigureAwait(false); @@ -581,7 +592,7 @@ namespace Jellyfin.Api.Controllers var result = users .OrderBy(u => u.Username) - .Select(i => _userManager.GetUserDto(i, HttpContext.GetNormalizedRemoteIp())); + .Select(i => _userManager.GetUserDto(i, HttpContext.GetNormalizedRemoteIp().ToString())); return result; } diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index 16380f0bb..751b48682 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -434,7 +434,7 @@ namespace Jellyfin.Api.Helpers } } - private bool EnableAdaptiveBitrateStreaming(StreamState state, bool isLiveStream, bool enableAdaptiveBitrateStreaming, string ipAddress) + private bool EnableAdaptiveBitrateStreaming(StreamState state, bool isLiveStream, bool enableAdaptiveBitrateStreaming, IPAddress ipAddress) { // Within the local network this will likely do more harm than good. if (_networkManager.IsInLocalNetwork(ipAddress)) diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs index ce6740fc9..a2d0e7030 100644 --- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs +++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.Linq; +using System.Net; using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -179,7 +180,7 @@ namespace Jellyfin.Api.Helpers bool enableTranscoding, bool allowVideoStreamCopy, bool allowAudioStreamCopy, - string ipAddress) + IPAddress ipAddress) { var streamBuilder = new StreamBuilder(_mediaEncoder, _logger); @@ -551,7 +552,7 @@ namespace Jellyfin.Api.Helpers } } - private int? GetMaxBitrate(int? clientMaxBitrate, User user, string ipAddress) + private int? GetMaxBitrate(int? clientMaxBitrate, User user, IPAddress ipAddress) { var maxBitrate = clientMaxBitrate; var remoteClientMaxBitrate = user.RemoteClientBitrateLimit ?? 0; diff --git a/Jellyfin.Api/Helpers/RequestHelpers.cs b/Jellyfin.Api/Helpers/RequestHelpers.cs index 94856e03e..56585aeab 100644 --- a/Jellyfin.Api/Helpers/RequestHelpers.cs +++ b/Jellyfin.Api/Helpers/RequestHelpers.cs @@ -84,7 +84,7 @@ namespace Jellyfin.Api.Helpers authorization.Version, authorization.DeviceId, authorization.Device, - request.HttpContext.GetNormalizedRemoteIp(), + request.HttpContext.GetNormalizedRemoteIp().ToString(), user); if (session == null) diff --git a/MediaBrowser.Common/Extensions/HttpContextExtensions.cs b/MediaBrowser.Common/Extensions/HttpContextExtensions.cs index 19fa95480..e51ad42d1 100644 --- a/MediaBrowser.Common/Extensions/HttpContextExtensions.cs +++ b/MediaBrowser.Common/Extensions/HttpContextExtensions.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Common.Extensions /// /// The HTTP context. /// The remote caller IP address. - public static string GetNormalizedRemoteIp(this HttpContext context) + public static IPAddress GetNormalizedRemoteIp(this HttpContext context) { // Default to the loopback address if no RemoteIpAddress is specified (i.e. during integration tests) var ip = context.Connection.RemoteIpAddress ?? IPAddress.Loopback; @@ -35,7 +35,7 @@ namespace MediaBrowser.Common.Extensions ip = ip.MapToIPv4(); } - return ip.ToString(); + return ip; } } } diff --git a/tests/Jellyfin.Api.Tests/Auth/LocalAccessPolicy/LocalAccessHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/LocalAccessPolicy/LocalAccessHandlerTests.cs index 09ffa8468..5b3d784ff 100644 --- a/tests/Jellyfin.Api.Tests/Auth/LocalAccessPolicy/LocalAccessHandlerTests.cs +++ b/tests/Jellyfin.Api.Tests/Auth/LocalAccessPolicy/LocalAccessHandlerTests.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Net; using System.Threading.Tasks; using AutoFixture; using AutoFixture.AutoMoq; @@ -41,7 +42,7 @@ namespace Jellyfin.Api.Tests.Auth.LocalAccessPolicy public async Task LocalAccessOnly(bool isInLocalNetwork, bool shouldSucceed) { _networkManagerMock - .Setup(n => n.IsInLocalNetwork(It.IsAny())) + .Setup(n => n.IsInLocalNetwork(It.IsAny())) .Returns(isInLocalNetwork); TestHelpers.SetupConfigurationManager(_configurationManagerMock, true); -- cgit v1.2.3 From 066c19a26b1dbc36c20439426110738b2ce1c2d6 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 24 Mar 2021 21:06:03 +0100 Subject: Fix possible null ref exception --- Emby.Server.Implementations/Library/LibraryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 46a7feb7f..c18838caf 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -208,7 +208,7 @@ namespace Emby.Server.Implementations.Library /// Gets or sets the list of entity resolution ignore rules. /// /// The entity resolution ignore rules. - private IResolverIgnoreRule[] EntityResolutionIgnoreRules { get; set; } + private IResolverIgnoreRule[] EntityResolutionIgnoreRules { get; set; } = Array.Empty(); /// /// Gets or sets the list of currently registered entity resolvers. -- cgit v1.2.3 From 5bb7d99b48feb66a393da73f4a056b6dd5f38739 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Thu, 25 Mar 2021 13:16:09 +0100 Subject: Remove DVDs from files exempt from chapter image extraction --- Emby.Server.Implementations/MediaEncoder/EncodingManager.cs | 5 ----- 1 file changed, 5 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index c6e931448..a9dab9138 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -82,11 +82,6 @@ namespace Emby.Server.Implementations.MediaEncoder return false; } - if (video.VideoType == VideoType.Dvd) - { - return false; - } - if (video.IsShortcut) { return false; -- cgit v1.2.3 From 78f7fdeaccee7f321740ede24dee797622b44f8b Mon Sep 17 00:00:00 2001 From: David Date: Fri, 26 Mar 2021 17:06:01 +0100 Subject: Rename methods and optimize allocations --- .../Library/PathExtensions.cs | 4 +-- MediaBrowser.Common/Providers/ProviderIdParsers.cs | 34 ++++++++++++---------- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 16 +++++----- .../Providers/ProviderIdParserTests.cs | 19 ++++++------ 4 files changed, 38 insertions(+), 35 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs index 72fe5a854..73236bad8 100644 --- a/Emby.Server.Implementations/Library/PathExtensions.cs +++ b/Emby.Server.Implementations/Library/PathExtensions.cs @@ -44,8 +44,8 @@ namespace Emby.Server.Implementations.Library // for imdbid we also accept pattern matching if (string.Equals(attribute, "imdbid", StringComparison.OrdinalIgnoreCase)) { - var match = ProviderIdParsers.TryParseImdbId(str, out var imdbId); - return match ? imdbId : null; + var match = ProviderIdParsers.TryFindImdbId(str, out var imdbId); + return match ? imdbId.ToString() : null; } return null; diff --git a/MediaBrowser.Common/Providers/ProviderIdParsers.cs b/MediaBrowser.Common/Providers/ProviderIdParsers.cs index 7744124ea..26eaccac5 100644 --- a/MediaBrowser.Common/Providers/ProviderIdParsers.cs +++ b/MediaBrowser.Common/Providers/ProviderIdParsers.cs @@ -12,6 +12,7 @@ namespace MediaBrowser.Common.Providers { private const int ImdbMinNumbers = 7; private const int ImdbMaxNumbers = 8; + private const string ImdbPrefix = "tt"; /// /// Parses an IMDb id from a string. @@ -19,9 +20,9 @@ namespace MediaBrowser.Common.Providers /// The text to parse. /// The parsed IMDb id. /// True if parsing was successful, false otherwise. - public static bool TryParseImdbId(ReadOnlySpan text, [NotNullWhen(true)] out string? imdbId) + public static bool TryFindImdbId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan imdbId) { - var tt = "tt".AsSpan(); + var tt = ImdbPrefix.AsSpan(); // imdb id is at least 9 chars (tt + 7 numbers) while (text.Length >= 2 + ImdbMinNumbers) @@ -33,9 +34,10 @@ namespace MediaBrowser.Common.Providers return false; } - text = text.Slice(ttPos + tt.Length); - var i = 0; - for (; i < Math.Min(text.Length, ImdbMaxNumbers); i++) + text = text.Slice(ttPos); + var i = 2; + var limit = Math.Min(text.Length, ImdbMaxNumbers + 2); + for (; i < limit; i++) { var c = text[i]; if (!IsDigit(c)) @@ -44,10 +46,10 @@ namespace MediaBrowser.Common.Providers } } - // skip if more than 8 digits - if (i <= ImdbMaxNumbers && i >= ImdbMinNumbers) + // skip if more than 8 digits + 2 chars for tt + if (i <= ImdbMaxNumbers + 2 && i >= ImdbMinNumbers + 2) { - imdbId = string.Concat(tt, text.Slice(0, i)); + imdbId = text.Slice(0, i); return true; } @@ -64,8 +66,8 @@ namespace MediaBrowser.Common.Providers /// The text with the url to parse. /// The parsed TMDb id. /// True if parsing was successful, false otherwise. - public static bool TryParseTmdbMovieId(ReadOnlySpan text, [NotNullWhen(true)] out string? tmdbId) - => TryParseProviderId(text, "themoviedb.org/movie/", out tmdbId); + public static bool TryFindTmdbMovieId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan tmdbId) + => TryFindProviderId(text, "themoviedb.org/movie/", out tmdbId); /// /// Parses an TMDb id from a series url. @@ -73,8 +75,8 @@ namespace MediaBrowser.Common.Providers /// The text with the url to parse. /// The parsed TMDb id. /// True if parsing was successful, false otherwise. - public static bool TryParseTmdbSeriesId(ReadOnlySpan text, [NotNullWhen(true)] out string? tmdbId) - => TryParseProviderId(text, "themoviedb.org/tv/", out tmdbId); + public static bool TryFindTmdbSeriesId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan tmdbId) + => TryFindProviderId(text, "themoviedb.org/tv/", out tmdbId); /// /// Parses an TVDb id from a url. @@ -82,10 +84,10 @@ namespace MediaBrowser.Common.Providers /// The text with the url to parse. /// The parsed TVDb id. /// True if parsing was successful, false otherwise. - public static bool TryParseTvdbId(ReadOnlySpan text, [NotNullWhen(true)] out string? tvdbId) - => TryParseProviderId(text, "thetvdb.com/?tab=series&id=", out tvdbId); + public static bool TryFindTvdbId(ReadOnlySpan text, [NotNullWhen(true)] out ReadOnlySpan tvdbId) + => TryFindProviderId(text, "thetvdb.com/?tab=series&id=", out tvdbId); - private static bool TryParseProviderId(ReadOnlySpan text, ReadOnlySpan searchString, [NotNullWhen(true)] out string? providerId) + private static bool TryFindProviderId(ReadOnlySpan text, ReadOnlySpan searchString, [NotNullWhen(true)] out ReadOnlySpan providerId) { var searchPos = text.IndexOf(searchString); if (searchPos == -1) @@ -109,7 +111,7 @@ namespace MediaBrowser.Common.Providers if (i >= 1) { - providerId = text.Slice(0, i).ToString(); + providerId = text.Slice(0, i); return true; } diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index d2fa120e8..c5627f880 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -219,29 +219,29 @@ namespace MediaBrowser.XbmcMetadata.Parsers protected void ParseProviderLinks(T item, string xml) { - if (ProviderIdParsers.TryParseImdbId(xml, out var imdbId)) + if (ProviderIdParsers.TryFindImdbId(xml, out var imdbId)) { - item.SetProviderId(MetadataProvider.Imdb, imdbId); + item.SetProviderId(MetadataProvider.Imdb, imdbId.ToString()); } if (item is Movie) { - if (ProviderIdParsers.TryParseTmdbMovieId(xml, out var tmdbId)) + if (ProviderIdParsers.TryFindTmdbMovieId(xml, out var tmdbId)) { - item.SetProviderId(MetadataProvider.Tmdb, tmdbId); + item.SetProviderId(MetadataProvider.Tmdb, tmdbId.ToString()); } } if (item is Series) { - if (ProviderIdParsers.TryParseTmdbSeriesId(xml, out var tmdbId)) + if (ProviderIdParsers.TryFindTmdbSeriesId(xml, out var tmdbId)) { - item.SetProviderId(MetadataProvider.Tmdb, tmdbId); + item.SetProviderId(MetadataProvider.Tmdb, tmdbId.ToString()); } - if (ProviderIdParsers.TryParseTvdbId(xml, out var tvdbId)) + if (ProviderIdParsers.TryFindTvdbId(xml, out var tvdbId)) { - item.SetProviderId(MetadataProvider.Tvdb, tvdbId); + item.SetProviderId(MetadataProvider.Tvdb, tvdbId.ToString()); } } } diff --git a/tests/Jellyfin.Common.Tests/Providers/ProviderIdParserTests.cs b/tests/Jellyfin.Common.Tests/Providers/ProviderIdParserTests.cs index cfe1ea86b..1ce54c59b 100644 --- a/tests/Jellyfin.Common.Tests/Providers/ProviderIdParserTests.cs +++ b/tests/Jellyfin.Common.Tests/Providers/ProviderIdParserTests.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Providers; +using System; +using MediaBrowser.Common.Providers; using Xunit; namespace Jellyfin.Common.Tests.Providers @@ -20,9 +21,9 @@ namespace Jellyfin.Common.Tests.Providers [InlineData("tt123456789", true, "tt12345678")] public void Parse_Imdb(string text, bool shouldSucceed, string? imdbId) { - var succeeded = ProviderIdParsers.TryParseImdbId(text, out string? parsedId); + var succeeded = ProviderIdParsers.TryFindImdbId(text, out ReadOnlySpan parsedId); Assert.Equal(shouldSucceed, succeeded); - Assert.Equal(imdbId, parsedId); + Assert.Equal(imdbId ?? Span.Empty.ToString(), parsedId.ToString()); } [Theory] @@ -32,9 +33,9 @@ namespace Jellyfin.Common.Tests.Providers [InlineData("https://www.themoviedb.org/tv/1668-friends", false, null)] public void Parse_TmdbMovie(string text, bool shouldSucceed, string? tmdbId) { - var succeeded = ProviderIdParsers.TryParseTmdbMovieId(text, out string? parsedId); + var succeeded = ProviderIdParsers.TryFindTmdbMovieId(text, out ReadOnlySpan parsedId); Assert.Equal(shouldSucceed, succeeded); - Assert.Equal(tmdbId, parsedId); + Assert.Equal(tmdbId ?? Span.Empty.ToString(), parsedId.ToString()); } [Theory] @@ -44,9 +45,9 @@ namespace Jellyfin.Common.Tests.Providers [InlineData("https://www.themoviedb.org/movie/30287-fallo", false, null)] public void Parse_TmdbSeries(string text, bool shouldSucceed, string? tmdbId) { - var succeeded = ProviderIdParsers.TryParseTmdbSeriesId(text, out string? parsedId); + var succeeded = ProviderIdParsers.TryFindTmdbSeriesId(text, out ReadOnlySpan parsedId); Assert.Equal(shouldSucceed, succeeded); - Assert.Equal(tmdbId, parsedId); + Assert.Equal(tmdbId ?? Span.Empty.ToString(), parsedId.ToString()); } [Theory] @@ -56,9 +57,9 @@ namespace Jellyfin.Common.Tests.Providers [InlineData("https://www.themoviedb.org/tv/1668-friends", false, null)] public void Parse_Tvdb(string text, bool shouldSucceed, string? tvdbId) { - var succeeded = ProviderIdParsers.TryParseTvdbId(text, out string? parsedId); + var succeeded = ProviderIdParsers.TryFindTvdbId(text, out ReadOnlySpan parsedId); Assert.Equal(shouldSucceed, succeeded); - Assert.Equal(tvdbId, parsedId); + Assert.Equal(tvdbId ?? Span.Empty.ToString(), parsedId.ToString()); } } } -- cgit v1.2.3 From aa769573387b051fb79246885be8eb5e8cf97e76 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 1 Apr 2021 19:16:00 +0200 Subject: Remove useless code --- Emby.Dlna/ConnectionManager/ControlHandler.cs | 2 +- Emby.Dlna/ContentDirectory/ControlHandler.cs | 45 +++++++--------------- Emby.Dlna/MediaReceiverRegistrar/ControlHandler.cs | 2 +- Emby.Dlna/Service/BaseControlHandler.cs | 2 +- .../Library/Resolvers/TV/SeriesResolver.cs | 22 +---------- .../LiveTv/EmbyTV/EpgChannelData.cs | 43 ++++++++------------- 6 files changed, 35 insertions(+), 81 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/ConnectionManager/ControlHandler.cs b/Emby.Dlna/ConnectionManager/ControlHandler.cs index 2f8d197a7..1a1790ee6 100644 --- a/Emby.Dlna/ConnectionManager/ControlHandler.cs +++ b/Emby.Dlna/ConnectionManager/ControlHandler.cs @@ -31,7 +31,7 @@ namespace Emby.Dlna.ConnectionManager } /// - protected override void WriteResult(string methodName, IDictionary methodParams, XmlWriter xmlWriter) + protected override void WriteResult(string methodName, IReadOnlyDictionary methodParams, XmlWriter xmlWriter) { if (string.Equals(methodName, "GetProtocolInfo", StringComparison.OrdinalIgnoreCase)) { diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index 27f1fdaba..713f95099 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -121,7 +121,7 @@ namespace Emby.Dlna.ContentDirectory } /// - protected override void WriteResult(string methodName, IDictionary methodParams, XmlWriter xmlWriter) + protected override void WriteResult(string methodName, IReadOnlyDictionary methodParams, XmlWriter xmlWriter) { if (xmlWriter == null) { @@ -201,8 +201,8 @@ namespace Emby.Dlna.ContentDirectory /// /// Adds a "XSetBookmark" element to the xml document. /// - /// The . - private void HandleXSetBookmark(IDictionary sparams) + /// The method parameters. + private void HandleXSetBookmark(IReadOnlyDictionary sparams) { var id = sparams["ObjectID"]; @@ -305,35 +305,18 @@ namespace Emby.Dlna.ContentDirectory return builder.ToString(); } - /// - /// Returns the value in the key of the dictionary, or defaultValue if it doesn't exist. - /// - /// The . - /// The key. - /// The defaultValue. - /// The . - public static string GetValueOrDefault(IDictionary sparams, string key, string defaultValue) - { - if (sparams != null && sparams.TryGetValue(key, out string val)) - { - return val; - } - - return defaultValue; - } - /// /// Builds the "Browse" xml response. /// /// The . - /// The . + /// The method parameters. /// The device Id to use. - private void HandleBrowse(XmlWriter xmlWriter, IDictionary sparams, string deviceId) + private void HandleBrowse(XmlWriter xmlWriter, IReadOnlyDictionary sparams, string deviceId) { var id = sparams["ObjectID"]; var flag = sparams["BrowseFlag"]; - var filter = new Filter(GetValueOrDefault(sparams, "Filter", "*")); - var sortCriteria = new SortCriteria(GetValueOrDefault(sparams, "SortCriteria", string.Empty)); + var filter = new Filter(sparams.GetValueOrDefault("Filter", "*")); + var sortCriteria = new SortCriteria(sparams.GetValueOrDefault("SortCriteria", string.Empty)); var provided = 0; @@ -435,9 +418,9 @@ namespace Emby.Dlna.ContentDirectory /// Builds the response to the "X_BrowseByLetter request. /// /// The . - /// The . + /// The method parameters. /// The device id. - private void HandleXBrowseByLetter(XmlWriter xmlWriter, IDictionary sparams, string deviceId) + private void HandleXBrowseByLetter(XmlWriter xmlWriter, IReadOnlyDictionary sparams, string deviceId) { // TODO: Implement this method HandleSearch(xmlWriter, sparams, deviceId); @@ -447,13 +430,13 @@ namespace Emby.Dlna.ContentDirectory /// Builds a response to the "Search" request. /// /// The xmlWriter. - /// The sparams. + /// The method parameters. /// The deviceId. - private void HandleSearch(XmlWriter xmlWriter, IDictionary sparams, string deviceId) + private void HandleSearch(XmlWriter xmlWriter, IReadOnlyDictionary sparams, string deviceId) { - var searchCriteria = new SearchCriteria(GetValueOrDefault(sparams, "SearchCriteria", string.Empty)); - var sortCriteria = new SortCriteria(GetValueOrDefault(sparams, "SortCriteria", string.Empty)); - var filter = new Filter(GetValueOrDefault(sparams, "Filter", "*")); + var searchCriteria = new SearchCriteria(sparams.GetValueOrDefault("SearchCriteria", string.Empty)); + var sortCriteria = new SortCriteria(sparams.GetValueOrDefault("SortCriteria", string.Empty)); + var filter = new Filter(sparams.GetValueOrDefault("Filter", "*")); // sort example: dc:title, dc:date diff --git a/Emby.Dlna/MediaReceiverRegistrar/ControlHandler.cs b/Emby.Dlna/MediaReceiverRegistrar/ControlHandler.cs index 464f71a6f..d8fb12742 100644 --- a/Emby.Dlna/MediaReceiverRegistrar/ControlHandler.cs +++ b/Emby.Dlna/MediaReceiverRegistrar/ControlHandler.cs @@ -24,7 +24,7 @@ namespace Emby.Dlna.MediaReceiverRegistrar } /// - protected override void WriteResult(string methodName, IDictionary methodParams, XmlWriter xmlWriter) + protected override void WriteResult(string methodName, IReadOnlyDictionary methodParams, XmlWriter xmlWriter) { if (string.Equals(methodName, "IsAuthorized", StringComparison.OrdinalIgnoreCase)) { diff --git a/Emby.Dlna/Service/BaseControlHandler.cs b/Emby.Dlna/Service/BaseControlHandler.cs index 8d2486fee..fda8346f9 100644 --- a/Emby.Dlna/Service/BaseControlHandler.cs +++ b/Emby.Dlna/Service/BaseControlHandler.cs @@ -210,7 +210,7 @@ namespace Emby.Dlna.Service } } - protected abstract void WriteResult(string methodName, IDictionary methodParams, XmlWriter xmlWriter); + protected abstract void WriteResult(string methodName, IReadOnlyDictionary methodParams, XmlWriter xmlWriter); private void LogRequest(ControlRequest request) { diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index 732bfd94d..e8b5f4fe7 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -127,7 +127,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV { if (child.IsDirectory) { - if (IsSeasonFolder(child.FullName, isTvContentType, libraryManager)) + if (IsSeasonFolder(child.FullName, isTvContentType)) { logger.LogDebug("{Path} is a series because of season folder {Dir}.", path, child.FullName); return true; @@ -160,24 +160,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return false; } - /// - /// Determines whether [is place holder] [the specified path]. - /// - /// The path. - /// true if [is place holder] [the specified path]; otherwise, false. - /// path - private static bool IsVideoPlaceHolder(string path) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException(nameof(path)); - } - - var extension = Path.GetExtension(path); - - return string.Equals(extension, ".disc", StringComparison.OrdinalIgnoreCase); - } - /// /// Determines whether [is season folder] [the specified path]. /// @@ -185,7 +167,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV /// if set to true [is tv content type]. /// The library manager. /// true if [is season folder] [the specified path]; otherwise, false. - private static bool IsSeasonFolder(string path, bool isTvContentType, ILibraryManager libraryManager) + private static bool IsSeasonFolder(string path, bool isTvContentType) { var seasonNumber = SeasonPathParser.Parse(path, isTvContentType, isTvContentType).SeasonNumber; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs index 463d0ed0a..8c27ca76e 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs @@ -9,55 +9,44 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV internal class EpgChannelData { + + private readonly Dictionary _channelsById; + + private readonly Dictionary _channelsByNumber; + + private readonly Dictionary _channelsByName; + public EpgChannelData(IEnumerable channels) { - ChannelsById = new Dictionary(StringComparer.OrdinalIgnoreCase); - ChannelsByNumber = new Dictionary(StringComparer.OrdinalIgnoreCase); - ChannelsByName = new Dictionary(StringComparer.OrdinalIgnoreCase); + _channelsById = new Dictionary(StringComparer.OrdinalIgnoreCase); + _channelsByNumber = new Dictionary(StringComparer.OrdinalIgnoreCase); + _channelsByName = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (var channel in channels) { - ChannelsById[channel.Id] = channel; + _channelsById[channel.Id] = channel; if (!string.IsNullOrEmpty(channel.Number)) { - ChannelsByNumber[channel.Number] = channel; + _channelsByNumber[channel.Number] = channel; } var normalizedName = NormalizeName(channel.Name ?? string.Empty); if (!string.IsNullOrWhiteSpace(normalizedName)) { - ChannelsByName[normalizedName] = channel; + _channelsByName[normalizedName] = channel; } } } - private Dictionary ChannelsById { get; set; } - - private Dictionary ChannelsByNumber { get; set; } - - private Dictionary ChannelsByName { get; set; } - public ChannelInfo GetChannelById(string id) - { - ChannelsById.TryGetValue(id, out var result); - - return result; - } + => _channelsById.GetValueOrDefault(id); public ChannelInfo GetChannelByNumber(string number) - { - ChannelsByNumber.TryGetValue(number, out var result); - - return result; - } + => _channelsByNumber.GetValueOrDefault(number); public ChannelInfo GetChannelByName(string name) - { - ChannelsByName.TryGetValue(name, out var result); - - return result; - } + => _channelsByName.GetValueOrDefault(name); public static string NormalizeName(string value) { -- cgit v1.2.3 From c533b204961b8fe19272b31b5fb5473be0eb801b Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 1 Apr 2021 19:39:00 +0200 Subject: Remove ManagedFileSystem.IsRootPath `Path.IsPathRooted` should be used instead --- .../IO/ManagedFileSystem.cs | 32 ++++++---------------- MediaBrowser.Model/IO/IFileSystem.cs | 7 ----- 2 files changed, 9 insertions(+), 30 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index c0e757543..679795dd2 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -55,7 +55,7 @@ namespace Emby.Server.Implementations.IO } var extension = Path.GetExtension(filename); - return _shortcutHandlers.Any(i => string.Equals(extension, i.Extension, StringComparison.OrdinalIgnoreCase)); + return _shortcutHandlers.Any(i => string.Equals(extension, i.Extension, _isEnvironmentCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)); } /// @@ -487,26 +487,9 @@ namespace Emby.Server.Implementations.IO throw new ArgumentNullException(nameof(path)); } - var separatorChar = Path.DirectorySeparatorChar; - - return path.IndexOf(parentPath.TrimEnd(separatorChar) + separatorChar, StringComparison.OrdinalIgnoreCase) != -1; - } - - public virtual bool IsRootPath(string path) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException(nameof(path)); - } - - var parent = Path.GetDirectoryName(path); - - if (!string.IsNullOrEmpty(parent)) - { - return false; - } - - return true; + return path.Contains( + Path.TrimEndingDirectorySeparator(parentPath) + Path.DirectorySeparatorChar, + _isEnvironmentCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal); } public virtual string NormalizePath(string path) @@ -521,7 +504,7 @@ namespace Emby.Server.Implementations.IO return path; } - return path.TrimEnd(Path.DirectorySeparatorChar); + return Path.TrimEndingDirectorySeparator(path); } public virtual bool AreEqual(string path1, string path2) @@ -536,7 +519,10 @@ namespace Emby.Server.Implementations.IO return false; } - return string.Equals(NormalizePath(path1), NormalizePath(path2), StringComparison.OrdinalIgnoreCase); + return string.Equals( + NormalizePath(path1), + NormalizePath(path2), + _isEnvironmentCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal); } public virtual string GetFileNameWithoutExtension(FileSystemMetadata info) diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs index ef08ecec6..e5c26430a 100644 --- a/MediaBrowser.Model/IO/IFileSystem.cs +++ b/MediaBrowser.Model/IO/IFileSystem.cs @@ -117,13 +117,6 @@ namespace MediaBrowser.Model.IO /// true if [contains sub path] [the specified parent path]; otherwise, false. bool ContainsSubPath(string parentPath, string path); - /// - /// Determines whether [is root path] [the specified path]. - /// - /// The path. - /// true if [is root path] [the specified path]; otherwise, false. - bool IsRootPath(string path); - /// /// Normalizes the path. /// -- cgit v1.2.3 From a0258618acc66b80e9f5cdd535a31baf12857fb0 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Thu, 1 Apr 2021 21:24:34 +0200 Subject: Update Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs Co-authored-by: Claus Vium --- Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index e8b5f4fe7..4a9d2cf8c 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -165,7 +165,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV /// /// The path. /// if set to true [is tv content type]. - /// The library manager. /// true if [is season folder] [the specified path]; otherwise, false. private static bool IsSeasonFolder(string path, bool isTvContentType) { -- cgit v1.2.3 From 14d0acf28572c6b5f5ecac6728b7a8184683b5f2 Mon Sep 17 00:00:00 2001 From: cvium Date: Mon, 5 Apr 2021 15:12:47 +0200 Subject: add simple auth handling to websocketmanager --- Emby.Server.Implementations/HttpServer/WebSocketManager.cs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs index d6cf6233e..1bee1ac31 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs @@ -14,15 +14,18 @@ namespace Emby.Server.Implementations.HttpServer public class WebSocketManager : IWebSocketManager { private readonly IWebSocketListener[] _webSocketListeners; + private readonly IAuthService _authService; private readonly ILogger _logger; private readonly ILoggerFactory _loggerFactory; public WebSocketManager( + IAuthService authService, IEnumerable webSocketListeners, ILogger logger, ILoggerFactory loggerFactory) { _webSocketListeners = webSocketListeners.ToArray(); + _authService = authService; _logger = logger; _loggerFactory = loggerFactory; } @@ -30,6 +33,7 @@ namespace Emby.Server.Implementations.HttpServer /// public async Task WebSocketRequestHandler(HttpContext context) { + _ = _authService.Authenticate(context.Request); try { _logger.LogInformation("WS {IP} request", context.Connection.RemoteIpAddress); -- cgit v1.2.3 From 95327b842e9eb50ca2c53740674b8ed2f6615eae Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 6 Apr 2021 20:02:06 +0200 Subject: Enable NetAnalyzers for more projects --- Emby.Drawing/NullImageEncoder.cs | 2 +- Emby.Notifications/Emby.Notifications.csproj | 6 ++---- Emby.Photos/Emby.Photos.csproj | 6 ++---- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 6 ++---- 4 files changed, 7 insertions(+), 13 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Drawing/NullImageEncoder.cs b/Emby.Drawing/NullImageEncoder.cs index 2a1cfd3da..1c05aa916 100644 --- a/Emby.Drawing/NullImageEncoder.cs +++ b/Emby.Drawing/NullImageEncoder.cs @@ -32,7 +32,7 @@ namespace Emby.Drawing => throw new NotImplementedException(); /// - public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) + public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat outputFormat) { throw new NotImplementedException(); } diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj index 526a27229..5a2aea642 100644 --- a/Emby.Notifications/Emby.Notifications.csproj +++ b/Emby.Notifications/Emby.Notifications.csproj @@ -11,6 +11,8 @@ true true enable + AllEnabledByDefault + ../jellyfin.ruleset @@ -30,8 +32,4 @@ - - ../jellyfin.ruleset - - diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index e64a658c5..2b6618159 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -24,6 +24,8 @@ true true enable + AllEnabledByDefault + ../jellyfin.ruleset @@ -33,8 +35,4 @@ - - ../jellyfin.ruleset - - diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index be552ef93..9248053f5 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -46,6 +46,8 @@ true AD0001 + AllEnabledByDefault + ../jellyfin.ruleset @@ -55,10 +57,6 @@ - - ../jellyfin.ruleset - - -- cgit v1.2.3 From 65f880be323e154655505c702822ce381fc5569e Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Tue, 6 Apr 2021 20:59:47 +0100 Subject: Keep plugin status after update. --- Emby.Server.Implementations/Plugins/PluginManager.cs | 7 ++++--- Emby.Server.Implementations/Updates/InstallationManager.cs | 12 +++++++----- MediaBrowser.Common/Plugins/IPluginManager.cs | 4 +++- 3 files changed, 14 insertions(+), 9 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index 700396c4c..3a8296455 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Net.Http; @@ -368,7 +369,7 @@ namespace Emby.Server.Implementations.Plugins } /// - public async Task GenerateManifest(PackageInfo packageInfo, Version version, string path) + public async Task GenerateManifest(PackageInfo packageInfo, Version version, string path, PluginStatus status) { if (packageInfo == null) { @@ -411,9 +412,9 @@ namespace Emby.Server.Implementations.Plugins Overview = packageInfo.Overview, Owner = packageInfo.Owner, TargetAbi = versionInfo.TargetAbi ?? string.Empty, - Timestamp = string.IsNullOrEmpty(versionInfo.Timestamp) ? DateTime.MinValue : DateTime.Parse(versionInfo.Timestamp), + Timestamp = string.IsNullOrEmpty(versionInfo.Timestamp) ? DateTime.MinValue : DateTime.Parse(versionInfo.Timestamp, CultureInfo.InvariantCulture), Version = versionInfo.Version, - Status = PluginStatus.Active, + Status = status == PluginStatus.Disabled ? PluginStatus.Disabled : PluginStatus.Active, // Keep disabled state. AutoUpdate = true, ImagePath = imagePath }; diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index fc34f93cd..e7307aefe 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -22,6 +22,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Events.Updates; using MediaBrowser.Model.IO; +using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Updates; using Microsoft.Extensions.Logging; @@ -194,7 +195,7 @@ namespace Emby.Server.Implementations.Updates var plugin = _pluginManager.GetPlugin(packageGuid, version.VersionNumber); if (plugin != null) { - await _pluginManager.GenerateManifest(package, version.VersionNumber, plugin.Path); + await _pluginManager.GenerateManifest(package, version.VersionNumber, plugin.Path, plugin.Manifest.Status).ConfigureAwait(false); } // Remove versions with a target ABI greater then the current application version. @@ -500,7 +501,8 @@ namespace Emby.Server.Implementations.Updates var plugins = _pluginManager.Plugins; foreach (var plugin in plugins) { - if (plugin.Manifest?.AutoUpdate == false) + // Don't auto update when plugin marked not to, or when it's disabled. + if (plugin.Manifest?.AutoUpdate == false || plugin.Manifest?.Status == MediaBrowser.Model.Plugins.PluginStatus.Disabled) { continue; } @@ -515,7 +517,7 @@ namespace Emby.Server.Implementations.Updates } } - private async Task PerformPackageInstallation(InstallationInfo package, CancellationToken cancellationToken) + private async Task PerformPackageInstallation(InstallationInfo package, PluginStatus status, CancellationToken cancellationToken) { var extension = Path.GetExtension(package.SourceUrl); if (!string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase)) @@ -567,7 +569,7 @@ namespace Emby.Server.Implementations.Updates stream.Position = 0; _zipClient.ExtractAllFromZip(stream, targetDir, true); - await _pluginManager.GenerateManifest(package.PackageInfo, package.Version, targetDir); + await _pluginManager.GenerateManifest(package.PackageInfo, package.Version, targetDir, status).ConfigureAwait(false); _pluginManager.ImportPluginFrom(targetDir); } @@ -576,7 +578,7 @@ namespace Emby.Server.Implementations.Updates LocalPlugin? plugin = _pluginManager.Plugins.FirstOrDefault(p => p.Id.Equals(package.Id) && p.Version.Equals(package.Version)) ?? _pluginManager.Plugins.FirstOrDefault(p => p.Name.Equals(package.Name, StringComparison.OrdinalIgnoreCase) && p.Version.Equals(package.Version)); - await PerformPackageInstallation(package, cancellationToken).ConfigureAwait(false); + await PerformPackageInstallation(package, plugin?.Manifest.Status ?? PluginStatus.Active, cancellationToken).ConfigureAwait(false); _logger.LogInformation(plugin == null ? "New plugin installed: {PluginName} {PluginVersion}" : "Plugin updated: {PluginName} {PluginVersion}", package.Name, package.Version); return plugin != null; diff --git a/MediaBrowser.Common/Plugins/IPluginManager.cs b/MediaBrowser.Common/Plugins/IPluginManager.cs index f9a8fb6f7..0e2e814cb 100644 --- a/MediaBrowser.Common/Plugins/IPluginManager.cs +++ b/MediaBrowser.Common/Plugins/IPluginManager.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Reflection; using System.Threading.Tasks; +using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Updates; using Microsoft.Extensions.DependencyInjection; @@ -51,8 +52,9 @@ namespace MediaBrowser.Common.Plugins /// The used to generate a manifest. /// Version to be installed. /// The path where to save the manifest. + /// Initial status of the plugin. /// True if successful. - Task GenerateManifest(PackageInfo packageInfo, Version version, string path); + Task GenerateManifest(PackageInfo packageInfo, Version version, string path, PluginStatus status); /// /// Imports plugin details from a folder. -- cgit v1.2.3 From b645bb20deb92225e17dd87fcc7fbf2fc1631e80 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Thu, 8 Apr 2021 14:38:25 +0100 Subject: Update Emby.Server.Implementations/Updates/InstallationManager.cs Co-authored-by: Cody Robibero --- Emby.Server.Implementations/Updates/InstallationManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index e7307aefe..653b1381b 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -502,7 +502,7 @@ namespace Emby.Server.Implementations.Updates foreach (var plugin in plugins) { // Don't auto update when plugin marked not to, or when it's disabled. - if (plugin.Manifest?.AutoUpdate == false || plugin.Manifest?.Status == MediaBrowser.Model.Plugins.PluginStatus.Disabled) + if (plugin.Manifest?.AutoUpdate == false || plugin.Manifest?.Status == PluginStatus.Disabled) { continue; } -- cgit v1.2.3 From db530e61f5ac7047f8c5b88b3a30aa17e9253bbc Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Fri, 9 Apr 2021 11:32:19 +0200 Subject: move IsPlayed to outerquery IsPlayed is a column in UserDatas and does not belong in the inner query. None of the other UserDatas columns are in the innerquery. --- Emby.Server.Implementations/Data/SqliteItemRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 2ae805447..694805ebe 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -5415,7 +5415,6 @@ AND Type = @InternalPersonType)"); ItemIds = query.ItemIds, TopParentIds = query.TopParentIds, ParentId = query.ParentId, - IsPlayed = query.IsPlayed, IsAiring = query.IsAiring, IsMovie = query.IsMovie, IsSports = query.IsSports, @@ -5441,6 +5440,7 @@ AND Type = @InternalPersonType)"); var outerQuery = new InternalItemsQuery(query.User) { + IsPlayed = query.IsPlayed, IsFavorite = query.IsFavorite, IsFavoriteOrLiked = query.IsFavoriteOrLiked, IsLiked = query.IsLiked, -- cgit v1.2.3 From a21b2714e7957640afa140361d9886877e57d6df Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Fri, 9 Apr 2021 12:03:56 +0200 Subject: fetching images should not kill the scanner --- Emby.Server.Implementations/Library/LibraryManager.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index c18838caf..494eb5929 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1914,12 +1914,17 @@ namespace Emby.Server.Implementations.Library } catch (ArgumentException) { - _logger.LogWarning("Cannot get image index for {0}", img.Path); + _logger.LogWarning("Cannot get image index for {ImagePath}", img.Path); continue; } catch (InvalidOperationException) { - _logger.LogWarning("Cannot fetch image from {0}", img.Path); + _logger.LogWarning("Cannot fetch image from {ImagePath}", img.Path); + continue; + } + catch (HttpRequestException ex) + { + _logger.LogWarning("Cannot fetch image from {ImagePath}. Http status code: {HttpStatus}", img.Path, ex.StatusCode); continue; } } @@ -1932,7 +1937,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError(ex, "Cannot get image dimensions for {0}", image.Path); + _logger.LogError(ex, "Cannot get image dimensions for {ImagePath}", image.Path); image.Width = 0; image.Height = 0; continue; @@ -1944,7 +1949,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError(ex, "Cannot compute blurhash for {0}", image.Path); + _logger.LogError(ex, "Cannot compute blurhash for {ImagePath}", image.Path); image.BlurHash = string.Empty; } @@ -1954,7 +1959,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError(ex, "Cannot update DateModified for {0}", image.Path); + _logger.LogError(ex, "Cannot update DateModified for {ImagePath}", image.Path); } } -- cgit v1.2.3 From 08ccf2a49cc5c67026b324570a975aa9adab8915 Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 9 Apr 2021 13:20:12 +0200 Subject: Resolve name from episode folder --- .../Library/LibraryManager.cs | 33 +++++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index c18838caf..f92c30093 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -27,6 +27,7 @@ using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; @@ -48,6 +49,7 @@ using MediaBrowser.Providers.MediaInfo; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using Episode = MediaBrowser.Controller.Entities.TV.Episode; +using EpisodeInfo = Emby.Naming.TV.EpisodeInfo; using Genre = MediaBrowser.Controller.Entities.Genre; using Person = MediaBrowser.Controller.Entities.Person; using VideoResolver = Emby.Naming.Video.VideoResolver; @@ -2512,7 +2514,7 @@ namespace Emby.Server.Implementations.Library public bool FillMissingEpisodeNumbersFromPath(Episode episode, bool forceRefresh) { var series = episode.Series; - bool? isAbsoluteNaming = series == null ? false : string.Equals(series.DisplayOrder, "absolute", StringComparison.OrdinalIgnoreCase); + bool? isAbsoluteNaming = series != null && string.Equals(series.DisplayOrder, "absolute", StringComparison.OrdinalIgnoreCase); if (!isAbsoluteNaming.Value) { // In other words, no filter applied @@ -2524,9 +2526,32 @@ namespace Emby.Server.Implementations.Library var isFolder = episode.VideoType == VideoType.BluRay || episode.VideoType == VideoType.Dvd; // TODO nullable - what are we trying to do there with empty episodeInfo? - var episodeInfo = episode.IsFileProtocol - ? resolver.Resolve(episode.Path, isFolder, null, null, isAbsoluteNaming) ?? new Naming.TV.EpisodeInfo(episode.Path) - : new Naming.TV.EpisodeInfo(episode.Path); + EpisodeInfo episodeInfo = null; + if (episode.IsFileProtocol) + { + episodeInfo = resolver.Resolve(episode.Path, isFolder, null, null, isAbsoluteNaming) ?? new EpisodeInfo(episode.Path); + // Resolve from parent folder if it's not the Season folder + if (!episodeInfo.EpisodeNumber.HasValue && episode.Parent is not Season) + { + var episodeInfoFromFolder = resolver.Resolve(Path.GetDirectoryName(episode.Path)!, true, null, null, isAbsoluteNaming); + // merge the missing information + episodeInfo.SeriesName = episodeInfoFromFolder?.SeriesName; + episodeInfo.EpisodeNumber ??= episodeInfoFromFolder?.EpisodeNumber; + episodeInfo.EndingEpisodeNumber ??= episodeInfoFromFolder?.EndingEpisodeNumber; + episodeInfo.SeasonNumber ??= episodeInfoFromFolder?.SeasonNumber; + episodeInfo.Container ??= episodeInfoFromFolder?.Container; + episodeInfo.Format3D ??= episodeInfoFromFolder?.Format3D; + episodeInfo.Is3D = episodeInfoFromFolder?.Is3D ?? episodeInfo.Is3D; + episodeInfo.IsStub = episodeInfoFromFolder?.IsStub ?? episodeInfo.IsStub; + episodeInfo.StubType = episodeInfoFromFolder?.StubType; + episodeInfo.IsByDate = episodeInfoFromFolder?.IsStub ?? episodeInfo.IsByDate; + episodeInfo.Day ??= episodeInfoFromFolder?.Day; + episodeInfo.Month ??= episodeInfoFromFolder?.Month; + episodeInfo.Year ??= episodeInfoFromFolder?.Year; + } + } + + episodeInfo ??= new EpisodeInfo(episode.Path); try { -- cgit v1.2.3 From e7fc18d0f31c5516889c9dbb65d3cb3421d8b271 Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 9 Apr 2021 13:28:27 +0200 Subject: Fix type check --- Emby.Server.Implementations/Library/LibraryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index f92c30093..c69b8991b 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2531,7 +2531,7 @@ namespace Emby.Server.Implementations.Library { episodeInfo = resolver.Resolve(episode.Path, isFolder, null, null, isAbsoluteNaming) ?? new EpisodeInfo(episode.Path); // Resolve from parent folder if it's not the Season folder - if (!episodeInfo.EpisodeNumber.HasValue && episode.Parent is not Season) + if (!episodeInfo.EpisodeNumber.HasValue && episode.Parent.GetType() == typeof(Folder)) { var episodeInfoFromFolder = resolver.Resolve(Path.GetDirectoryName(episode.Path)!, true, null, null, isAbsoluteNaming); // merge the missing information -- cgit v1.2.3 From 69d2368fbcf734f48341edf73a9e8baae6229343 Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 9 Apr 2021 13:31:17 +0200 Subject: Copy paste error --- Emby.Server.Implementations/Library/LibraryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index c69b8991b..aed098e1b 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2544,7 +2544,7 @@ namespace Emby.Server.Implementations.Library episodeInfo.Is3D = episodeInfoFromFolder?.Is3D ?? episodeInfo.Is3D; episodeInfo.IsStub = episodeInfoFromFolder?.IsStub ?? episodeInfo.IsStub; episodeInfo.StubType = episodeInfoFromFolder?.StubType; - episodeInfo.IsByDate = episodeInfoFromFolder?.IsStub ?? episodeInfo.IsByDate; + episodeInfo.IsByDate = episodeInfoFromFolder?.IsByDate ?? episodeInfo.IsByDate; episodeInfo.Day ??= episodeInfoFromFolder?.Day; episodeInfo.Month ??= episodeInfoFromFolder?.Month; episodeInfo.Year ??= episodeInfoFromFolder?.Year; -- cgit v1.2.3 From 457229c56de2bf13af8852611a9c47c4950f1561 Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 9 Apr 2021 13:43:40 +0200 Subject: Simplification --- Emby.Naming/TV/EpisodeResolver.cs | 5 ++++ .../Library/LibraryManager.cs | 27 ++++++++-------------- 2 files changed, 14 insertions(+), 18 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Naming/TV/EpisodeResolver.cs b/Emby.Naming/TV/EpisodeResolver.cs index f7df58786..eac192be5 100644 --- a/Emby.Naming/TV/EpisodeResolver.cs +++ b/Emby.Naming/TV/EpisodeResolver.cs @@ -68,6 +68,11 @@ namespace Emby.Naming.TV var parsingResult = new EpisodePathParser(_options) .Parse(path, isDirectory, isNamed, isOptimistic, supportsAbsoluteNumbers, fillExtendedInfo); + if (!parsingResult.Success) + { + return null; + } + return new EpisodeInfo(path) { Container = container, diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index aed098e1b..f840f3695 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2529,25 +2529,16 @@ namespace Emby.Server.Implementations.Library EpisodeInfo episodeInfo = null; if (episode.IsFileProtocol) { - episodeInfo = resolver.Resolve(episode.Path, isFolder, null, null, isAbsoluteNaming) ?? new EpisodeInfo(episode.Path); + episodeInfo = resolver.Resolve(episode.Path, isFolder, null, null, isAbsoluteNaming); // Resolve from parent folder if it's not the Season folder - if (!episodeInfo.EpisodeNumber.HasValue && episode.Parent.GetType() == typeof(Folder)) - { - var episodeInfoFromFolder = resolver.Resolve(Path.GetDirectoryName(episode.Path)!, true, null, null, isAbsoluteNaming); - // merge the missing information - episodeInfo.SeriesName = episodeInfoFromFolder?.SeriesName; - episodeInfo.EpisodeNumber ??= episodeInfoFromFolder?.EpisodeNumber; - episodeInfo.EndingEpisodeNumber ??= episodeInfoFromFolder?.EndingEpisodeNumber; - episodeInfo.SeasonNumber ??= episodeInfoFromFolder?.SeasonNumber; - episodeInfo.Container ??= episodeInfoFromFolder?.Container; - episodeInfo.Format3D ??= episodeInfoFromFolder?.Format3D; - episodeInfo.Is3D = episodeInfoFromFolder?.Is3D ?? episodeInfo.Is3D; - episodeInfo.IsStub = episodeInfoFromFolder?.IsStub ?? episodeInfo.IsStub; - episodeInfo.StubType = episodeInfoFromFolder?.StubType; - episodeInfo.IsByDate = episodeInfoFromFolder?.IsByDate ?? episodeInfo.IsByDate; - episodeInfo.Day ??= episodeInfoFromFolder?.Day; - episodeInfo.Month ??= episodeInfoFromFolder?.Month; - episodeInfo.Year ??= episodeInfoFromFolder?.Year; + if (episodeInfo == null && episode.Parent.GetType() == typeof(Folder)) + { + episodeInfo = resolver.Resolve(Path.GetDirectoryName(episode.Path)!, true, null, null, isAbsoluteNaming); + if (episodeInfo != null) + { + // add the container + episodeInfo.Container = Path.GetExtension(episode.Path)?.TrimStart('.'); + } } } -- cgit v1.2.3 From 53db1a1ffcba7edf9e5da677b6ed7e7e67f0d63a Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 9 Apr 2021 13:47:47 +0200 Subject: ... --- Emby.Server.Implementations/Library/LibraryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index f840f3695..dd678eca0 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2533,7 +2533,7 @@ namespace Emby.Server.Implementations.Library // Resolve from parent folder if it's not the Season folder if (episodeInfo == null && episode.Parent.GetType() == typeof(Folder)) { - episodeInfo = resolver.Resolve(Path.GetDirectoryName(episode.Path)!, true, null, null, isAbsoluteNaming); + episodeInfo = resolver.Resolve(episode.Parent.Path, true, null, null, isAbsoluteNaming); if (episodeInfo != null) { // add the container -- cgit v1.2.3 From 5c4be2416d89bf31c6f62042f833e8f91621d8f6 Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 9 Apr 2021 13:48:25 +0200 Subject: Remove unused import --- Emby.Server.Implementations/Library/LibraryManager.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index dd678eca0..ac5028827 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -27,7 +27,6 @@ using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; -- cgit v1.2.3 From 1a3352003d0736d4d18513fb0055ae3b6452cded Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 9 Apr 2021 23:02:36 +0200 Subject: don't die on dangling symlinks --- Emby.Server.Implementations/IO/ManagedFileSystem.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 679795dd2..7c9b7c2d0 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -249,9 +249,18 @@ namespace Emby.Server.Implementations.IO // Issue #2354 get the size of files behind symbolic links if (fileInfo.Attributes.HasFlag(FileAttributes.ReparsePoint)) { - using (Stream thisFileStream = File.OpenRead(fileInfo.FullName)) + try { - result.Length = thisFileStream.Length; + using (Stream thisFileStream = File.OpenRead(fileInfo.FullName)) + { + result.Length = thisFileStream.Length; + } + } + catch (FileNotFoundException ex) + { + // Dangling symlinks cannot be detected before opening the file unfortunately... + Logger.LogError("Reading the file size of the symlink at {Path} failed. Marking the file as not existing.", ex); + result.Exists = false; } } -- cgit v1.2.3 From f2cba352e58f5d52693875365fdd400ad7c11863 Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 9 Apr 2021 23:30:07 +0200 Subject: catch ioexception and include stack trace --- Emby.Server.Implementations/Library/LibraryManager.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 494eb5929..7f29e3e99 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1917,14 +1917,14 @@ namespace Emby.Server.Implementations.Library _logger.LogWarning("Cannot get image index for {ImagePath}", img.Path); continue; } - catch (InvalidOperationException) + catch (Exception ex) when (ex is InvalidOperationException || ex is IOException) { - _logger.LogWarning("Cannot fetch image from {ImagePath}", img.Path); + _logger.LogWarning(ex, "Cannot fetch image from {ImagePath}", img.Path); continue; } catch (HttpRequestException ex) { - _logger.LogWarning("Cannot fetch image from {ImagePath}. Http status code: {HttpStatus}", img.Path, ex.StatusCode); + _logger.LogWarning(ex, "Cannot fetch image from {ImagePath}. Http status code: {HttpStatus}", img.Path, ex.StatusCode); continue; } } -- cgit v1.2.3 From ef527df28f1a48f31aa4bbab36c9443075b68084 Mon Sep 17 00:00:00 2001 From: cvium Date: Sat, 10 Apr 2021 00:06:48 +0200 Subject: Set mediatype to Audio for playlists in a music library --- Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs index c76d41e5c..5f051321f 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs @@ -63,7 +63,8 @@ namespace Emby.Server.Implementations.Library.Resolvers { Path = args.Path, Name = Path.GetFileNameWithoutExtension(args.Path), - IsInMixedFolder = true + IsInMixedFolder = true, + PlaylistMediaType = MediaType.Audio }; } } -- cgit v1.2.3 From f99237cf9b7c2c33c18fefafe79d50b5b414781f Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Sat, 10 Apr 2021 00:16:37 +0200 Subject: Update Emby.Server.Implementations/IO/ManagedFileSystem.cs Co-authored-by: Cody Robibero --- Emby.Server.Implementations/IO/ManagedFileSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 7c9b7c2d0..3893a1577 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -259,7 +259,7 @@ namespace Emby.Server.Implementations.IO catch (FileNotFoundException ex) { // Dangling symlinks cannot be detected before opening the file unfortunately... - Logger.LogError("Reading the file size of the symlink at {Path} failed. Marking the file as not existing.", ex); + Logger.LogError(ex, "Reading the file size of the symlink at {Path} failed. Marking the file as not existing.", fileInfo.FullName); result.Exists = false; } } -- cgit v1.2.3 From 42bcf171d98276cd8472a8400e6bd960f475e19b Mon Sep 17 00:00:00 2001 From: cvium Date: Sat, 10 Apr 2021 23:54:35 +0200 Subject: Use sync Serialize when writing scheduled tasks to disk --- Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index a145a8423..3cc2cefb9 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -178,7 +178,8 @@ namespace Emby.Server.Implementations.ScheduledTasks lock (_lastExecutionResultSyncLock) { using FileStream createStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None); - JsonSerializer.SerializeAsync(createStream, value, _jsonOptions); + using Utf8JsonWriter jsonStream = new Utf8JsonWriter(createStream); + JsonSerializer.Serialize(jsonStream, value, _jsonOptions); } } } @@ -578,7 +579,8 @@ namespace Emby.Server.Implementations.ScheduledTasks Directory.CreateDirectory(Path.GetDirectoryName(path)); using FileStream createStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None); - JsonSerializer.SerializeAsync(createStream, triggers, _jsonOptions); + using Utf8JsonWriter jsonWriter = new Utf8JsonWriter(createStream); + JsonSerializer.Serialize(jsonWriter, triggers, _jsonOptions); } /// -- cgit v1.2.3 From a4ffc7a813389e8cc2e075d3c9e740a66896ad5c Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 12 Apr 2021 00:28:17 +0200 Subject: Fix random failing of tests Fully initialize the configuration manager at the init stage ``` Failed Jellyfin.Server.Integration.Tests.Controllers.ActivityLogControllerTests.ActivityLog_GetEntries_Ok [2 s] Error Message: MediaBrowser.Common.Extensions.ResourceNotFoundException : Configuration with key metadata not found. Stack Trace: at Emby.Server.Implementations.AppBase.BaseConfigurationManager.<>c__DisplayClass43_0.b__0(String k) in D:\a\1\s\Emby.Server.Implementations\AppBase\BaseConfigurationManager.cs:line 309 at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory) at Emby.Server.Implementations.AppBase.BaseConfigurationManager.GetConfiguration(String key) in D:\a\1\s\Emby.Server.Implementations\AppBase\BaseConfigurationManager.cs:line 300 at MediaBrowser.Common.Configuration.ConfigurationManagerExtensions.GetConfiguration[T](IConfigurationManager manager, String key) in D:\a\1\s\MediaBrowser.Common\Configuration\IConfigurationManager.cs:line 88 at MediaBrowser.Controller.Library.MetadataConfigurationExtensions.GetMetadataConfiguration(IConfigurationManager config) in D:\a\1\s\MediaBrowser.Controller\Library\MetadataConfigurationStore.cs:line 28 at Emby.Server.Implementations.Library.ResolverHelper.SetDateCreated(BaseItem item, IFileSystem fileSystem, FileSystemMetadata info) in D:\a\1\s\Emby.Server.Implementations\Library\ResolverHelper.cs:line 159 at Emby.Server.Implementations.Library.ResolverHelper.EnsureDates(IFileSystem fileSystem, BaseItem item, ItemResolveArgs args) in D:\a\1\s\Emby.Server.Implementations\Library\ResolverHelper.cs:line 153 at Emby.Server.Implementations.Library.ResolverHelper.SetInitialItemValues(BaseItem item, ItemResolveArgs args, IFileSystem fileSystem, ILibraryManager libraryManager) in D:\a\1\s\Emby.Server.Implementations\Library\ResolverHelper.cs:line 81 at Emby.Server.Implementations.Library.LibraryManager.ResolveItem(ItemResolveArgs args, IItemResolver[] resolvers) in D:\a\1\s\Emby.Server.Implementations\Library\LibraryManager.cs:line 480 at Emby.Server.Implementations.Library.LibraryManager.ResolvePath(FileSystemMetadata fileInfo, IDirectoryService directoryService, IItemResolver[] resolvers, Folder parent, String collectionType, LibraryOptions libraryOptions) in D:\a\1\s\Emby.Server.Implementations\Library\LibraryManager.cs:line 618 at Emby.Server.Implementations.Library.LibraryManager.ResolvePath(FileSystemMetadata fileInfo, Folder parent) in D:\a\1\s\Emby.Server.Implementations\Library\LibraryManager.cs:line 536 at Emby.Server.Implementations.Library.LibraryManager.CreateRootFolder() in D:\a\1\s\Emby.Server.Implementations\Library\LibraryManager.cs:line 732 at Emby.Server.Implementations.Library.LibraryManager.get_RootFolder() in D:\a\1\s\Emby.Server.Implementations\Library\LibraryManager.cs:line 180 at Emby.Server.Implementations.IO.LibraryMonitor.Start() in D:\a\1\s\Emby.Server.Implementations\IO\LibraryMonitor.cs:line 135 at Emby.Server.Implementations.IO.LibraryMonitorStartup.RunAsync() in D:\a\1\s\Emby.Server.Implementations\IO\LibraryMonitorStartup.cs:line 26 at Emby.Server.Implementations.ApplicationHost.StartEntryPoints(IEnumerable`1 entryPoints, Boolean isBeforeStartup)+MoveNext() in D:\a\1\s\Emby.Server.Implementations\ApplicationHost.cs:line 541 at System.Threading.Tasks.Task.WhenAll(IEnumerable`1 tasks) at Emby.Server.Implementations.ApplicationHost.RunStartupTasksAsync(CancellationToken cancellationToken) in D:\a\1\s\Emby.Server.Implementations\ApplicationHost.cs:line 525 at Jellyfin.Server.Integration.Tests.JellyfinApplicationFactory.CreateServer(IWebHostBuilder builder) in D:\a\1\s\tests\Jellyfin.Server.Integration.Tests\JellyfinApplicationFactory.cs:line 101 at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.EnsureServer() at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateDefaultClient(DelegatingHandler[] handlers) at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateDefaultClient(Uri baseAddress, DelegatingHandler[] handlers) at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateClient(WebApplicationFactoryClientOptions options) at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateClient() at Jellyfin.Server.Integration.Tests.Controllers.ActivityLogControllerTests.ActivityLog_GetEntries_Ok() in D:\a\1\s\tests\Jellyfin.Server.Integration.Tests\Controllers\ActivityLogControllerTests.cs:line 21 --- End of stack trace from previous location --- ``` --- Emby.Server.Implementations/ApplicationHost.cs | 87 +++++++++------------- Jellyfin.Server/Migrations/MigrationRunner.cs | 8 +- Jellyfin.Server/Program.cs | 2 +- .../Library/MetadataConfigurationExtensions.cs | 15 ++++ .../Library/MetadataConfigurationStore.cs | 12 +-- 5 files changed, 59 insertions(+), 65 deletions(-) create mode 100644 MediaBrowser.Controller/Library/MetadataConfigurationExtensions.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 3846de5fd..0512adf10 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -210,7 +210,7 @@ namespace Emby.Server.Implementations /// Gets or sets the configuration manager. /// /// The configuration manager. - protected IConfigurationManager ConfigurationManager { get; set; } + public ServerConfigurationManager ConfigurationManager { get; set; } /// /// Gets or sets the service provider. @@ -232,12 +232,6 @@ namespace Emby.Server.Implementations /// public string PublishedServerUrl => _startupOptions.PublishedServerUrl ?? _startupConfig[UdpServer.AddressOverrideConfigKey]; - /// - /// Gets the server configuration manager. - /// - /// The server configuration manager. - public IServerConfigurationManager ServerConfigurationManager => (IServerConfigurationManager)ConfigurationManager; - /// /// Initializes a new instance of the class. /// @@ -255,43 +249,26 @@ namespace Emby.Server.Implementations IFileSystem fileSystem, IServiceCollection serviceCollection) { - _xmlSerializer = new MyXmlSerializer(); - - ServiceCollection = serviceCollection; - ApplicationPaths = applicationPaths; LoggerFactory = loggerFactory; - _fileSystemManager = fileSystem; - - ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, _xmlSerializer, _fileSystemManager); - // Have to migrate settings here as migration subsystem not yet initialised. - MigrateNetworkConfiguration(); - - // Have to pre-register the NetworkConfigurationFactory, as the configuration sub-system is not yet initialised. - ConfigurationManager.RegisterConfiguration(); - NetManager = new NetworkManager((IServerConfigurationManager)ConfigurationManager, LoggerFactory.CreateLogger()); - - Logger = LoggerFactory.CreateLogger(); - _startupOptions = options; _startupConfig = startupConfig; + _fileSystemManager = fileSystem; + ServiceCollection = serviceCollection; - // Initialize runtime stat collection - if (ServerConfigurationManager.Configuration.EnableMetrics) - { - DotNetRuntimeStatsBuilder.Default().StartCollecting(); - } - + Logger = LoggerFactory.CreateLogger(); fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); ApplicationVersion = typeof(ApplicationHost).Assembly.GetName().Version; ApplicationVersionString = ApplicationVersion.ToString(3); ApplicationUserAgent = Name.Replace(' ', '-') + "/" + ApplicationVersionString; + _xmlSerializer = new MyXmlSerializer(); + ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, _xmlSerializer, _fileSystemManager); _pluginManager = new PluginManager( LoggerFactory.CreateLogger(), this, - ServerConfigurationManager.Configuration, + ConfigurationManager.Configuration, ApplicationPaths.PluginsPath, ApplicationVersion); } @@ -306,9 +283,9 @@ namespace Emby.Server.Implementations if (!File.Exists(path)) { var networkSettings = new NetworkConfiguration(); - ClassMigrationHelper.CopyProperties(ServerConfigurationManager.Configuration, networkSettings); + ClassMigrationHelper.CopyProperties(ConfigurationManager.Configuration, networkSettings); _xmlSerializer.SerializeToFile(networkSettings, path); - Logger?.LogDebug("Successfully migrated network settings."); + Logger.LogDebug("Successfully migrated network settings."); } } @@ -545,7 +522,21 @@ namespace Emby.Server.Implementations /// public void Init() { - var networkConfiguration = ServerConfigurationManager.GetNetworkConfiguration(); + DiscoverTypes(); + + ConfigurationManager.AddParts(GetExports()); + + // Have to migrate settings here as migration subsystem not yet initialised. + MigrateNetworkConfiguration(); + NetManager = new NetworkManager(ConfigurationManager, LoggerFactory.CreateLogger()); + + // Initialize runtime stat collection + if (ConfigurationManager.Configuration.EnableMetrics) + { + DotNetRuntimeStatsBuilder.Default().StartCollecting(); + } + + var networkConfiguration = ConfigurationManager.GetNetworkConfiguration(); HttpPort = networkConfiguration.HttpServerPortNumber; HttpsPort = networkConfiguration.HttpsPortNumber; @@ -563,8 +554,6 @@ namespace Emby.Server.Implementations }; Certificate = GetCertificate(CertificateInfo); - DiscoverTypes(); - RegisterServices(); _pluginManager.RegisterServices(ServiceCollection); @@ -579,7 +568,8 @@ namespace Emby.Server.Implementations ServiceCollection.AddMemoryCache(); - ServiceCollection.AddSingleton(ConfigurationManager); + ServiceCollection.AddSingleton(ConfigurationManager); + ServiceCollection.AddSingleton(ConfigurationManager); ServiceCollection.AddSingleton(this); ServiceCollection.AddSingleton(_pluginManager); ServiceCollection.AddSingleton(ApplicationPaths); @@ -606,8 +596,6 @@ namespace Emby.Server.Implementations ServiceCollection.AddSingleton(this); ServiceCollection.AddSingleton(ApplicationPaths); - ServiceCollection.AddSingleton(ServerConfigurationManager); - ServiceCollection.AddSingleton(); ServiceCollection.AddSingleton(); @@ -796,7 +784,7 @@ namespace Emby.Server.Implementations { // For now there's no real way to inject these properly BaseItem.Logger = Resolve>(); - BaseItem.ConfigurationManager = ServerConfigurationManager; + BaseItem.ConfigurationManager = ConfigurationManager; BaseItem.LibraryManager = Resolve(); BaseItem.ProviderManager = Resolve(); BaseItem.LocalizationManager = Resolve(); @@ -818,13 +806,12 @@ namespace Emby.Server.Implementations /// private void FindParts() { - if (!ServerConfigurationManager.Configuration.IsPortAuthorized) + if (!ConfigurationManager.Configuration.IsPortAuthorized) { - ServerConfigurationManager.Configuration.IsPortAuthorized = true; + ConfigurationManager.Configuration.IsPortAuthorized = true; ConfigurationManager.SaveConfiguration(); } - ConfigurationManager.AddParts(GetExports()); _pluginManager.CreatePlugins(); _urlPrefixes = GetUrlPrefixes().ToArray(); @@ -928,7 +915,7 @@ namespace Emby.Server.Implementations protected void OnConfigurationUpdated(object sender, EventArgs e) { var requiresRestart = false; - var networkConfiguration = ServerConfigurationManager.GetNetworkConfiguration(); + var networkConfiguration = ConfigurationManager.GetNetworkConfiguration(); // Don't do anything if these haven't been set yet if (HttpPort != 0 && HttpsPort != 0) @@ -937,10 +924,10 @@ namespace Emby.Server.Implementations if (networkConfiguration.HttpServerPortNumber != HttpPort || networkConfiguration.HttpsPortNumber != HttpsPort) { - if (ServerConfigurationManager.Configuration.IsPortAuthorized) + if (ConfigurationManager.Configuration.IsPortAuthorized) { - ServerConfigurationManager.Configuration.IsPortAuthorized = false; - ServerConfigurationManager.SaveConfiguration(); + ConfigurationManager.Configuration.IsPortAuthorized = false; + ConfigurationManager.SaveConfiguration(); requiresRestart = true; } @@ -1156,7 +1143,7 @@ namespace Emby.Server.Implementations } /// - public bool ListenWithHttps => Certificate != null && ServerConfigurationManager.GetNetworkConfiguration().EnableHttps; + public bool ListenWithHttps => Certificate != null && ConfigurationManager.GetNetworkConfiguration().EnableHttps; /// public string GetSmartApiUrl(IPAddress ipAddress, int? port = null) @@ -1240,14 +1227,14 @@ namespace Emby.Server.Implementations Scheme = scheme ?? (ListenWithHttps ? Uri.UriSchemeHttps : Uri.UriSchemeHttp), Host = host, Port = port ?? (ListenWithHttps ? HttpsPort : HttpPort), - Path = ServerConfigurationManager.GetNetworkConfiguration().BaseUrl + Path = ConfigurationManager.GetNetworkConfiguration().BaseUrl }.ToString().TrimEnd('/'); } public string FriendlyName => - string.IsNullOrEmpty(ServerConfigurationManager.Configuration.ServerName) + string.IsNullOrEmpty(ConfigurationManager.Configuration.ServerName) ? Environment.MachineName - : ServerConfigurationManager.Configuration.ServerName; + : ConfigurationManager.Configuration.ServerName; /// /// Shuts down. diff --git a/Jellyfin.Server/Migrations/MigrationRunner.cs b/Jellyfin.Server/Migrations/MigrationRunner.cs index 305660ae6..cf938ab8c 100644 --- a/Jellyfin.Server/Migrations/MigrationRunner.cs +++ b/Jellyfin.Server/Migrations/MigrationRunner.cs @@ -40,15 +40,15 @@ namespace Jellyfin.Server.Migrations .Select(m => ActivatorUtilities.CreateInstance(host.ServiceProvider, m)) .OfType() .ToArray(); - var migrationOptions = ((IConfigurationManager)host.ServerConfigurationManager).GetConfiguration(MigrationsListStore.StoreKey); + var migrationOptions = ((IConfigurationManager)host.ConfigurationManager).GetConfiguration(MigrationsListStore.StoreKey); - if (!host.ServerConfigurationManager.Configuration.IsStartupWizardCompleted && migrationOptions.Applied.Count == 0) + if (!host.ConfigurationManager.Configuration.IsStartupWizardCompleted && migrationOptions.Applied.Count == 0) { // If startup wizard is not finished, this is a fresh install. // Don't run any migrations, just mark all of them as applied. logger.LogInformation("Marking all known migrations as applied because this is a fresh install"); migrationOptions.Applied.AddRange(migrations.Where(m => !m.PerformOnNewInstall).Select(m => (m.Id, m.Name))); - host.ServerConfigurationManager.SaveConfiguration(MigrationsListStore.StoreKey, migrationOptions); + host.ConfigurationManager.SaveConfiguration(MigrationsListStore.StoreKey, migrationOptions); } var appliedMigrationIds = migrationOptions.Applied.Select(m => m.Id).ToHashSet(); @@ -77,7 +77,7 @@ namespace Jellyfin.Server.Migrations // Mark the migration as completed logger.LogInformation("Migration '{Name}' applied successfully", migrationRoutine.Name); migrationOptions.Applied.Add((migrationRoutine.Id, migrationRoutine.Name)); - host.ServerConfigurationManager.SaveConfiguration(MigrationsListStore.StoreKey, migrationOptions); + host.ConfigurationManager.SaveConfiguration(MigrationsListStore.StoreKey, migrationOptions); logger.LogDebug("Migration '{Name}' marked as applied in configuration.", migrationRoutine.Name); } } diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 4f203b7a9..464e02419 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -173,7 +173,7 @@ namespace Jellyfin.Server // If hosting the web client, validate the client content path if (startupConfig.HostWebClient()) { - string? webContentPath = appHost.ServerConfigurationManager.ApplicationPaths.WebPath; + string? webContentPath = appHost.ConfigurationManager.ApplicationPaths.WebPath; if (!Directory.Exists(webContentPath) || Directory.GetFiles(webContentPath).Length == 0) { throw new InvalidOperationException( diff --git a/MediaBrowser.Controller/Library/MetadataConfigurationExtensions.cs b/MediaBrowser.Controller/Library/MetadataConfigurationExtensions.cs new file mode 100644 index 000000000..884f9e773 --- /dev/null +++ b/MediaBrowser.Controller/Library/MetadataConfigurationExtensions.cs @@ -0,0 +1,15 @@ +#pragma warning disable CS1591 + +using MediaBrowser.Common.Configuration; +using MediaBrowser.Model.Configuration; + +namespace MediaBrowser.Controller.Library +{ + public static class MetadataConfigurationExtensions + { + public static MetadataConfiguration GetMetadataConfiguration(this IConfigurationManager config) + { + return config.GetConfiguration("metadata"); + } + } +} diff --git a/MediaBrowser.Controller/Library/MetadataConfigurationStore.cs b/MediaBrowser.Controller/Library/MetadataConfigurationStore.cs index f16304db0..a6be6c0d3 100644 --- a/MediaBrowser.Controller/Library/MetadataConfigurationStore.cs +++ b/MediaBrowser.Controller/Library/MetadataConfigurationStore.cs @@ -14,18 +14,10 @@ namespace MediaBrowser.Controller.Library { new ConfigurationStore { - Key = "metadata", - ConfigurationType = typeof(MetadataConfiguration) + Key = "metadata", + ConfigurationType = typeof(MetadataConfiguration) } }; } } - - public static class MetadataConfigurationExtensions - { - public static MetadataConfiguration GetMetadataConfiguration(this IConfigurationManager config) - { - return config.GetConfiguration("metadata"); - } - } } -- cgit v1.2.3 From 8045a488ceccc5c85195be3ef694a418c1c326aa Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 12 Apr 2021 22:01:35 +0200 Subject: Fix possible ArgumentNullException ``` Error Message: System.ArgumentNullException : Value cannot be null. (Parameter 'source') Stack Trace: at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument) at System.Linq.Enumerable.Select[TSource,TResult](IEnumerable`1 source, Func`2 selector) at Emby.Server.Implementations.Library.LibraryManager.ResolveItem(ItemResolveArgs args, IItemResolver[] resolvers) in /home/vsts/work/1/s/Emby.Server.Implementations/Library/LibraryManager.cs:line 475 at Emby.Server.Implementations.Library.LibraryManager.ResolvePath(FileSystemMetadata fileInfo, IDirectoryService directoryService, IItemResolver[] resolvers, Folder parent, String collectionType, LibraryOptions libraryOptions) in /home/vsts/work/1/s/Emby.Server.Implementations/Library/LibraryManager.cs:line 618 at Emby.Server.Implementations.Library.LibraryManager.ResolvePath(FileSystemMetadata fileInfo, Folder parent) in /home/vsts/work/1/s/Emby.Server.Implementations/Library/LibraryManager.cs:line 536 at Emby.Server.Implementations.Library.LibraryManager.GetUserRootFolder() in /home/vsts/work/1/s/Emby.Server.Implementations/Library/LibraryManager.cs:line 812 at Emby.Server.Implementations.Library.LibraryManager.GetCollectionFolders(BaseItem item) in /home/vsts/work/1/s/Emby.Server.Implementations/Library/LibraryManager.cs:line 2080 at Emby.Server.Implementations.Library.LibraryManager.GetLibraryOptions(BaseItem item) in /home/vsts/work/1/s/Emby.Server.Implementations/Library/LibraryManager.cs:line 2116 at MediaBrowser.Providers.Manager.ProviderManager.SaveMetadata(BaseItem item, ItemUpdateType updateType, IEnumerable`1 savers) in /home/vsts/work/1/s/MediaBrowser.Providers/Manager/ProviderManager.cs:line 672 at MediaBrowser.Providers.Manager.ProviderManager.SaveMetadata(BaseItem item, ItemUpdateType updateType) in /home/vsts/work/1/s/MediaBrowser.Providers/Manager/ProviderManager.cs:line 655 at Emby.Server.Implementations.Library.LibraryManager.RunMetadataSavers(BaseItem item, ItemUpdateType updateReason) in /home/vsts/work/1/s/Emby.Server.Implementations/Library/LibraryManager.cs:line 2017 at Emby.Server.Implementations.Library.LibraryManager.UpdateItemsAsync(IReadOnlyList`1 items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken) in /home/vsts/work/1/s/Emby.Server.Implementations/Library/LibraryManager.cs:line 1975 at Emby.Server.Implementations.Library.LibraryManager.CreateRootFolder() in /home/vsts/work/1/s/Emby.Server.Implementations/Library/LibraryManager.cs:line 775 at Emby.Server.Implementations.Library.LibraryManager.get_RootFolder() in /home/vsts/work/1/s/Emby.Server.Implementations/Library/LibraryManager.cs:line 180 at Emby.Server.Implementations.IO.LibraryMonitor.Start() in /home/vsts/work/1/s/Emby.Server.Implementations/IO/LibraryMonitor.cs:line 135 at Emby.Server.Implementations.IO.LibraryMonitorStartup.RunAsync() in /home/vsts/work/1/s/Emby.Server.Implementations/IO/LibraryMonitorStartup.cs:line 26 at Emby.Server.Implementations.ApplicationHost.StartEntryPoints(IEnumerable`1 entryPoints, Boolean isBeforeStartup)+MoveNext() in /home/vsts/work/1/s/Emby.Server.Implementations/ApplicationHost.cs:line 518 at System.Threading.Tasks.Task.WhenAll(IEnumerable`1 tasks) at Emby.Server.Implementations.ApplicationHost.RunStartupTasksAsync(CancellationToken cancellationToken) in /home/vsts/work/1/s/Emby.Server.Implementations/ApplicationHost.cs:line 502 at Jellyfin.Server.Integration.Tests.JellyfinApplicationFactory.CreateServer(IWebHostBuilder builder) in /home/vsts/work/1/s/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs:line 101 at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.EnsureServer() at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateDefaultClient(DelegatingHandler[] handlers) at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateDefaultClient(Uri baseAddress, DelegatingHandler[] handlers) at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateClient(WebApplicationFactoryClientOptions options) at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateClient() at Jellyfin.Server.Integration.Tests.Controllers.ActivityLogControllerTests.ActivityLog_GetEntries_Ok() in /home/vsts/work/1/s/tests/Jellyfin.Server.Integration.Tests/Controllers/ActivityLogControllerTests.cs:line 21 --- End of stack trace from previous location --- ``` --- Emby.Server.Implementations/Library/LibraryManager.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 7f29e3e99..6a9f4174d 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -196,13 +196,13 @@ namespace Emby.Server.Implementations.Library /// Gets or sets the postscan tasks. /// /// The postscan tasks. - private ILibraryPostScanTask[] PostscanTasks { get; set; } + private ILibraryPostScanTask[] PostscanTasks { get; set; } = Array.Empty(); /// /// Gets or sets the intro providers. /// /// The intro providers. - private IIntroProvider[] IntroProviders { get; set; } + private IIntroProvider[] IntroProviders { get; set; } = Array.Empty(); /// /// Gets or sets the list of entity resolution ignore rules. @@ -214,15 +214,15 @@ namespace Emby.Server.Implementations.Library /// Gets or sets the list of currently registered entity resolvers. /// /// The entity resolvers enumerable. - private IItemResolver[] EntityResolvers { get; set; } + private IItemResolver[] EntityResolvers { get; set; } = Array.Empty(); - private IMultiItemResolver[] MultiItemResolvers { get; set; } + private IMultiItemResolver[] MultiItemResolvers { get; set; } = Array.Empty(); /// /// Gets or sets the comparers. /// /// The comparers. - private IBaseItemComparer[] Comparers { get; set; } + private IBaseItemComparer[] Comparers { get; set; } = Array.Empty(); public bool IsScanRunning { get; private set; } -- cgit v1.2.3 From 723b6abcb392b1a65e46db91aa35f7e13de0c2a8 Mon Sep 17 00:00:00 2001 From: cvium Date: Tue, 13 Apr 2021 15:37:11 +0200 Subject: Optimize the way items are grouped into collections --- .../Collections/CollectionManager.cs | 56 ++++++++++++++-------- MediaBrowser.Controller/Entities/Folder.cs | 4 +- 2 files changed, 38 insertions(+), 22 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index db532ce5b..6dbbd5530 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -124,7 +124,7 @@ namespace Emby.Server.Implementations.Collections private IEnumerable GetCollections(User user) { - var folder = GetCollectionsFolder(false).Result; + var folder = GetCollectionsFolder(false).GetAwaiter().GetResult(); return folder == null ? Enumerable.Empty() @@ -319,11 +319,11 @@ namespace Emby.Server.Implementations.Collections { var results = new Dictionary(); - var allBoxsets = GetCollections(user).ToList(); + var allBoxSets = GetCollections(user).ToList(); foreach (var item in items) { - if (!(item is ISupportsBoxSetGrouping)) + if (item is not ISupportsBoxSetGrouping) { results[item.Id] = item; } @@ -331,34 +331,50 @@ namespace Emby.Server.Implementations.Collections { var itemId = item.Id; - var currentBoxSets = allBoxsets - .Where(i => i.ContainsLinkedChildByItemId(itemId)) - .ToList(); - - if (currentBoxSets.Count > 0) + var itemIsInBoxSet = false; + foreach (var boxSet in allBoxSets) { - foreach (var boxset in currentBoxSets) + if (!boxSet.ContainsLinkedChildByItemId(itemId)) + { + continue; + } + + itemIsInBoxSet = true; + + if (results.ContainsKey(boxSet.Id)) { - results[boxset.Id] = boxset; + continue; } + + results[boxSet.Id] = boxSet; } - else + + // skip any item that is in a box set + if (itemIsInBoxSet) { - var alreadyInResults = false; - foreach (var child in item.GetMediaSources(true)) + continue; + } + + var alreadyInResults = false; + // this is kind of a performance hack because only Video has alternate versions that should be in a box set? + if (item is Video video) + { + foreach (var childId in video.GetLocalAlternateVersionIds()) { - if (Guid.TryParse(child.Id, out var id) && results.ContainsKey(id)) + if (!results.ContainsKey(childId)) { - alreadyInResults = true; - break; + continue; } - } - if (!alreadyInResults) - { - results[item.Id] = item; + alreadyInResults = true; + break; } } + + if (!alreadyInResults) + { + results[item.Id] = item; + } } } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index cac5026f7..485733abb 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1434,9 +1434,9 @@ namespace MediaBrowser.Controller.Entities var linkedChildren = LinkedChildren; foreach (var i in linkedChildren) { - if (i.ItemId.HasValue && i.ItemId.Value == itemId) + if (i.ItemId.HasValue) { - return true; + return i.ItemId.Value == itemId; } var child = GetLinkedChild(i); -- cgit v1.2.3 From d44b2e2ee5ecb06016b8b88eb03fc6dc28a04ee9 Mon Sep 17 00:00:00 2001 From: cvium Date: Tue, 13 Apr 2021 20:12:50 +0200 Subject: fixes --- Emby.Server.Implementations/Collections/CollectionManager.cs | 9 ++------- MediaBrowser.Controller/Entities/Folder.cs | 7 ++++++- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index 6dbbd5530..81758d9a7 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -341,12 +341,7 @@ namespace Emby.Server.Implementations.Collections itemIsInBoxSet = true; - if (results.ContainsKey(boxSet.Id)) - { - continue; - } - - results[boxSet.Id] = boxSet; + results.TryAdd(boxSet.Id, boxSet); } // skip any item that is in a box set @@ -373,7 +368,7 @@ namespace Emby.Server.Implementations.Collections if (!alreadyInResults) { - results[item.Id] = item; + results[itemId] = item; } } } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 485733abb..bd1fbb473 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1436,7 +1436,12 @@ namespace MediaBrowser.Controller.Entities { if (i.ItemId.HasValue) { - return i.ItemId.Value == itemId; + if (i.ItemId.Value == itemId) + { + return true; + } + + continue; } var child = GetLinkedChild(i); -- cgit v1.2.3 From b63f615fd4f92f40394d04c9ae764b35aadc000d Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Thu, 15 Apr 2021 07:39:59 -0600 Subject: Enable nullability for ServerDiscoveryInfo (#5804) --- Emby.Server.Implementations/Udp/UdpServer.cs | 7 +--- .../ApiClient/ServerDiscoveryInfo.cs | 41 ++++++++++++++-------- 2 files changed, 27 insertions(+), 21 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Udp/UdpServer.cs b/Emby.Server.Implementations/Udp/UdpServer.cs index d01184e0b..db5265e79 100644 --- a/Emby.Server.Implementations/Udp/UdpServer.cs +++ b/Emby.Server.Implementations/Udp/UdpServer.cs @@ -53,12 +53,7 @@ namespace Emby.Server.Implementations.Udp if (!string.IsNullOrEmpty(localUrl)) { - var response = new ServerDiscoveryInfo - { - Address = localUrl, - Id = _appHost.SystemId, - Name = _appHost.FriendlyName - }; + var response = new ServerDiscoveryInfo(localUrl, _appHost.SystemId, _appHost.FriendlyName); try { diff --git a/MediaBrowser.Model/ApiClient/ServerDiscoveryInfo.cs b/MediaBrowser.Model/ApiClient/ServerDiscoveryInfo.cs index fcc90a1f7..f9f474586 100644 --- a/MediaBrowser.Model/ApiClient/ServerDiscoveryInfo.cs +++ b/MediaBrowser.Model/ApiClient/ServerDiscoveryInfo.cs @@ -1,32 +1,43 @@ -#nullable disable -#pragma warning disable CS1591 - namespace MediaBrowser.Model.ApiClient { + /// + /// The server discovery info model. + /// public class ServerDiscoveryInfo { /// - /// Gets or sets the address. + /// Initializes a new instance of the class. + /// + /// The server address. + /// The server id. + /// The server name. + /// The endpoint address. + public ServerDiscoveryInfo(string address, string id, string name, string? endpointAddress = null) + { + Address = address; + Id = id; + Name = name; + EndpointAddress = endpointAddress; + } + + /// + /// Gets the address. /// - /// The address. - public string Address { get; set; } + public string Address { get; } /// - /// Gets or sets the server identifier. + /// Gets the server identifier. /// - /// The server identifier. - public string Id { get; set; } + public string Id { get; } /// - /// Gets or sets the name. + /// Gets the name. /// - /// The name. - public string Name { get; set; } + public string Name { get; } /// - /// Gets or sets the endpoint address. + /// Gets the endpoint address. /// - /// The endpoint address. - public string EndpointAddress { get; set; } + public string? EndpointAddress { get; } } } -- cgit v1.2.3 From bb6fddde9ac48905b876717806754a052bf0ad24 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sat, 17 Apr 2021 11:19:09 +0100 Subject: Group Methods --- Emby.Server.Implementations/Playlists/PlaylistManager.cs | 2 +- Jellyfin.Api/Helpers/StreamingHelpers.cs | 4 ++-- Jellyfin.Networking/Manager/NetworkManager.cs | 2 +- Jellyfin.Server/Migrations/Routines/CreateUserLoggingConfigFile.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 2 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs index 932f721ab..2d1a559f1 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs @@ -215,7 +215,7 @@ namespace Emby.Server.Implementations.Playlists // Create a list of the new linked children to add to the playlist var childrenToAdd = newItems - .Select(i => LinkedChild.Create(i)) + .Select(LinkedChild.Create) .ToList(); // Log duplicates that have been ignored, if any diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index e2306aa27..404cb3a46 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -121,14 +121,14 @@ namespace Jellyfin.Api.Helpers if (!string.IsNullOrWhiteSpace(streamingRequest.AudioCodec)) { state.SupportedAudioCodecs = streamingRequest.AudioCodec.Split(',', StringSplitOptions.RemoveEmptyEntries); - state.Request.AudioCodec = state.SupportedAudioCodecs.FirstOrDefault(i => mediaEncoder.CanEncodeToAudioCodec(i)) + state.Request.AudioCodec = state.SupportedAudioCodecs.FirstOrDefault(mediaEncoder.CanEncodeToAudioCodec) ?? state.SupportedAudioCodecs.FirstOrDefault(); } if (!string.IsNullOrWhiteSpace(streamingRequest.SubtitleCodec)) { state.SupportedSubtitleCodecs = streamingRequest.SubtitleCodec.Split(',', StringSplitOptions.RemoveEmptyEntries); - state.Request.SubtitleCodec = state.SupportedSubtitleCodecs.FirstOrDefault(i => mediaEncoder.CanEncodeToSubtitleCodec(i)) + state.Request.SubtitleCodec = state.SupportedSubtitleCodecs.FirstOrDefault(mediaEncoder.CanEncodeToSubtitleCodec) ?? state.SupportedSubtitleCodecs.FirstOrDefault(); } diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index 73e8b2cd7..4078fd126 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -1067,7 +1067,7 @@ namespace Jellyfin.Networking.Manager } // Internal interfaces must be private, not excluded and part of the LocalNetworkSubnet. - _internalInterfaces = CreateCollection(_interfaceAddresses.Where(i => IsInLocalNetwork(i))); + _internalInterfaces = CreateCollection(_interfaceAddresses.Where(IsInLocalNetwork)); } _logger.LogInformation("Defined LAN addresses : {0}", _lanSubnets.AsString()); diff --git a/Jellyfin.Server/Migrations/Routines/CreateUserLoggingConfigFile.cs b/Jellyfin.Server/Migrations/Routines/CreateUserLoggingConfigFile.cs index 6821630db..ee4f8b0ba 100644 --- a/Jellyfin.Server/Migrations/Routines/CreateUserLoggingConfigFile.cs +++ b/Jellyfin.Server/Migrations/Routines/CreateUserLoggingConfigFile.cs @@ -75,7 +75,7 @@ namespace Jellyfin.Server.Migrations.Routines { var existingConfigJson = JToken.Parse(File.ReadAllText(oldConfigPath)); return _defaultConfigHistory - .Select(historicalConfigText => JToken.Parse(historicalConfigText)) + .Select(JToken.Parse) .Any(historicalConfigJson => JToken.DeepEquals(existingConfigJson, historicalConfigJson)); } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 53d45261e..1b69c6646 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2324,7 +2324,7 @@ namespace MediaBrowser.Controller.Entities .Where(i => i.IsLocalFile) .Select(i => System.IO.Path.GetDirectoryName(i.Path)) .Distinct(StringComparer.OrdinalIgnoreCase) - .SelectMany(i => directoryService.GetFilePaths(i)) + .SelectMany(directoryService.GetFilePaths) .ToList(); var deletedImages = ImageInfos diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index a87104cd6..ee2e5fcde 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.MediaEncoding.Probing .Where(i => i.Type != MediaStreamType.Subtitle || !string.IsNullOrWhiteSpace(i.Codec)) .ToList(); - info.MediaAttachments = internalStreams.Select(s => GetMediaAttachment(s)) + info.MediaAttachments = internalStreams.Select(GetMediaAttachment) .Where(i => i != null) .ToList(); diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 398d47d5f..f4c69fe8f 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -297,7 +297,7 @@ namespace MediaBrowser.Model.Dlna int? inputAudioSampleRate = audioStream?.SampleRate; int? inputAudioBitDepth = audioStream?.BitDepth; - if (directPlayMethods.Count() > 0) + if (directPlayMethods.Any()) { string audioCodec = audioStream?.Codec; -- cgit v1.2.3 From bc1cc2d04ae0e823becf59964e5bdc5a74ae7741 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sat, 17 Apr 2021 11:37:55 +0100 Subject: Remove unused using directives --- Emby.Dlna/ContentDirectory/ControlHandler.cs | 2 -- Emby.Dlna/Main/DlnaEntryPoint.cs | 1 - .../MediaReceiverRegistrar/MediaReceiverRegistrarXmlBuilder.cs | 1 - Emby.Dlna/PlayTo/SsdpHttpClient.cs | 1 - Emby.Server.Implementations/AppBase/ConfigurationHelper.cs | 1 - Emby.Server.Implementations/Channels/ChannelManager.cs | 1 - Emby.Server.Implementations/Collections/CollectionManager.cs | 3 --- Emby.Server.Implementations/ConfigurationOptions.cs | 1 - Emby.Server.Implementations/HttpServer/Security/AuthService.cs | 1 - Emby.Server.Implementations/IStartupOptions.cs | 1 - Emby.Server.Implementations/Images/ArtistImageProvider.cs | 8 -------- Emby.Server.Implementations/Images/DynamicImageProvider.cs | 1 - Emby.Server.Implementations/Library/PathExtensions.cs | 2 -- Emby.Server.Implementations/Library/SearchEngine.cs | 1 - Emby.Server.Implementations/Library/UserDataManager.cs | 2 +- Emby.Server.Implementations/Library/UserViewManager.cs | 1 - Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 1 - Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs | 2 -- Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs | 1 - .../LiveTv/Listings/XmlTvListingsProvider.cs | 1 - .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 3 --- Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs | 1 - Emby.Server.Implementations/Localization/LocalizationManager.cs | 1 - Emby.Server.Implementations/MediaEncoder/EncodingManager.cs | 1 - Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs | 1 - Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs | 1 - .../ScheduledTasks/Tasks/ChapterImagesTask.cs | 2 +- .../ScheduledTasks/Tasks/PeopleValidationTask.cs | 2 +- .../ScheduledTasks/Tasks/PluginUpdateTask.cs | 1 - .../ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs | 2 +- Jellyfin.Api/Controllers/PluginsController.cs | 1 - Jellyfin.Api/Extensions/DtoExtensions.cs | 1 - Jellyfin.Api/Helpers/AudioHelper.cs | 3 +-- Jellyfin.Api/Helpers/DynamicHlsHelper.cs | 1 - Jellyfin.Data/Entities/HomeSection.cs | 3 +-- Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs | 1 - Jellyfin.Networking/Configuration/NetworkConfiguration.cs | 1 - .../Configuration/NetworkConfigurationExtensions.cs | 1 - Jellyfin.Server/Filters/ParameterObsoleteFilter.cs | 1 - Jellyfin.Server/Formatters/CssOutputFormatter.cs | 3 +-- Jellyfin.Server/Middleware/IpBasedAccessValidationMiddleware.cs | 2 -- Jellyfin.Server/Middleware/LanFilteringMiddleware.cs | 3 --- .../Migrations/Routines/DisableTranscodingThrottling.cs | 1 - Jellyfin.Server/Program.cs | 2 -- Jellyfin.Server/StartupOptions.cs | 3 --- MediaBrowser.Common/Cryptography/PasswordHash.cs | 1 - MediaBrowser.Common/Net/INetworkManager.cs | 1 - MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs | 1 - MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs | 1 - MediaBrowser.Controller/Drawing/ImageHelper.cs | 3 --- MediaBrowser.Controller/Entities/Folder.cs | 1 - .../Events/Updates/PluginUninstalledEventArgs.cs | 1 - MediaBrowser.Controller/IServerApplicationHost.cs | 3 --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 2 -- MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs | 1 - MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs | 1 - MediaBrowser.Controller/MediaEncoding/JobLogger.cs | 1 - MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs | 5 ----- MediaBrowser.Controller/Playlists/Playlist.cs | 1 - MediaBrowser.Controller/Providers/IRemoteImageProvider.cs | 1 - MediaBrowser.Controller/Providers/IRemoteSearchProvider.cs | 1 - MediaBrowser.Controller/Subtitles/ISubtitleManager.cs | 1 - MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 1 - MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs | 1 - MediaBrowser.Model/Dto/NameIdPair.cs | 2 -- MediaBrowser.Model/LiveTv/TunerHostInfo.cs | 3 --- MediaBrowser.Model/Notifications/NotificationOptions.cs | 2 -- MediaBrowser.Providers/Manager/ProviderManager.cs | 1 - MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs | 1 - MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs | 1 - MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs | 1 - MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs | 1 - MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs | 2 -- MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs | 4 ++-- tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs | 1 - .../Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs | 1 - tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs | 1 - .../Jellyfin.Naming.Tests/AudioBook/AudioBookListResolverTests.cs | 1 - tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs | 1 - tests/Jellyfin.Naming.Tests/Subtitles/SubtitleParserTests.cs | 1 - tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs | 1 - .../IO/ManagedFileSystemTests.cs | 1 - tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs | 2 -- tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs | 1 - tests/Jellyfin.Server.Tests/ParseNetworkTests.cs | 1 - .../Parsers/MusicArtistNfoParserTests.cs | 1 - 86 files changed, 9 insertions(+), 125 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index 713f95099..90ba601b4 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -7,7 +6,6 @@ using System.Linq; using System.Text; using System.Threading; using System.Xml; -using Emby.Dlna.Configuration; using Emby.Dlna.Didl; using Emby.Dlna.Service; using Jellyfin.Data.Entities; diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index d3e9a41ec..bdfe430cf 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -5,7 +5,6 @@ using System.Globalization; using System.Linq; using System.Net.Http; using System.Net.Sockets; -using System.Threading; using System.Threading.Tasks; using Emby.Dlna.PlayTo; using Emby.Dlna.Ssdp; diff --git a/Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarXmlBuilder.cs b/Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarXmlBuilder.cs index 37840cd09..f3789a791 100644 --- a/Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarXmlBuilder.cs +++ b/Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarXmlBuilder.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using Emby.Dlna.Common; using Emby.Dlna.Service; -using MediaBrowser.Model.Dlna; namespace Emby.Dlna.MediaReceiverRegistrar { diff --git a/Emby.Dlna/PlayTo/SsdpHttpClient.cs b/Emby.Dlna/PlayTo/SsdpHttpClient.cs index e750f5bbc..d9f1ce490 100644 --- a/Emby.Dlna/PlayTo/SsdpHttpClient.cs +++ b/Emby.Dlna/PlayTo/SsdpHttpClient.cs @@ -2,7 +2,6 @@ using System; using System.Globalization; -using System.IO; using System.Net.Http; using System.Net.Mime; using System.Text; diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs index 3f7076383..29bac6634 100644 --- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs +++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs @@ -3,7 +3,6 @@ using System; using System.IO; using System.Linq; -using MediaBrowser.Common.Extensions; using MediaBrowser.Model.Serialization; namespace Emby.Server.Implementations.AppBase diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 87ebe960a..7324b0ee9 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; -using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index db532ce5b..e984afdba 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; using System.Threading; @@ -8,11 +7,9 @@ using System.Threading.Tasks; using Jellyfin.Data.Entities; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Collections; -using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; diff --git a/Emby.Server.Implementations/ConfigurationOptions.cs b/Emby.Server.Implementations/ConfigurationOptions.cs index cd9dbb1bd..01dc728c1 100644 --- a/Emby.Server.Implementations/ConfigurationOptions.cs +++ b/Emby.Server.Implementations/ConfigurationOptions.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Emby.Server.Implementations.HttpServer; using static MediaBrowser.Controller.Extensions.ConfigurationExtensions; namespace Emby.Server.Implementations diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs index 4a0fc8239..9afabf527 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs @@ -1,6 +1,5 @@ #pragma warning disable CS1591 -using System; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Net; diff --git a/Emby.Server.Implementations/IStartupOptions.cs b/Emby.Server.Implementations/IStartupOptions.cs index 0b823ff06..f719dc5f8 100644 --- a/Emby.Server.Implementations/IStartupOptions.cs +++ b/Emby.Server.Implementations/IStartupOptions.cs @@ -1,6 +1,5 @@ #pragma warning disable CS1591 #nullable enable -using System; namespace Emby.Server.Implementations { diff --git a/Emby.Server.Implementations/Images/ArtistImageProvider.cs b/Emby.Server.Implementations/Images/ArtistImageProvider.cs index afa4ec7b1..e96b64595 100644 --- a/Emby.Server.Implementations/Images/ArtistImageProvider.cs +++ b/Emby.Server.Implementations/Images/ArtistImageProvider.cs @@ -2,20 +2,12 @@ using System; using System.Collections.Generic; -using System.Linq; -using Emby.Server.Implementations.Images; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; -using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Images { diff --git a/Emby.Server.Implementations/Images/DynamicImageProvider.cs b/Emby.Server.Implementations/Images/DynamicImageProvider.cs index 462eb03a8..50c531482 100644 --- a/Emby.Server.Implementations/Images/DynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/DynamicImageProvider.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using Emby.Server.Implementations.Images; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs index 6eaecff0f..770cf6bb0 100644 --- a/Emby.Server.Implementations/Library/PathExtensions.cs +++ b/Emby.Server.Implementations/Library/PathExtensions.cs @@ -2,8 +2,6 @@ using System; using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Text.RegularExpressions; using MediaBrowser.Common.Providers; namespace Emby.Server.Implementations.Library diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index 94602582b..bcdf854ca 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -12,7 +12,6 @@ using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Search; -using Microsoft.Extensions.Logging; using Genre = MediaBrowser.Controller.Entities.Genre; using Person = MediaBrowser.Controller.Entities.Person; diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs index d16275b19..e8caea196 100644 --- a/Emby.Server.Implementations/Library/UserDataManager.cs +++ b/Emby.Server.Implementations/Library/UserDataManager.cs @@ -13,8 +13,8 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using Book = MediaBrowser.Controller.Entities.Book; using AudioBook = MediaBrowser.Controller.Entities.AudioBook; +using Book = MediaBrowser.Controller.Entities.Book; namespace Emby.Server.Implementations.Library { diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs index b6b7ea949..ac041bcf6 100644 --- a/Emby.Server.Implementations/Library/UserViewManager.cs +++ b/Emby.Server.Implementations/Library/UserViewManager.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Threading; using Jellyfin.Data.Entities; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 91a21db60..c9d9cc49a 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -17,7 +17,6 @@ using Jellyfin.Data.Enums; using Jellyfin.Data.Events; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; using MediaBrowser.Common.Progress; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index c20b08088..1cac9cb96 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -4,9 +4,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; using System.Text.Json; -using System.Threading.Tasks; using MediaBrowser.Common.Json; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs index da707fec6..b1259de23 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs @@ -2,7 +2,6 @@ using System; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.EmbyTV diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 76c875737..6824aa442 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; -using System.IO.Compression; using System.Linq; using System.Net.Http; using System.Threading; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 68173a0ef..1dcc78687 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -8,10 +8,8 @@ using System.Linq; using System.Net; using System.Net.Http; using System.Text.Json; -using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Json; using MediaBrowser.Common.Net; @@ -19,7 +17,6 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 2af635492..cc30a516d 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; using System.Net.Http; using System.Text.RegularExpressions; using System.Threading; diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 98de848bc..2fdc2b4d9 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -11,7 +11,6 @@ using MediaBrowser.Common.Json; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; -using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Localization diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index a9dab9138..031b5d2e7 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -15,7 +15,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; -using MediaBrowser.Model.MediaInfo; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.MediaEncoder diff --git a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs index 7bed06de3..22739a008 100644 --- a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs +++ b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs @@ -3,7 +3,6 @@ using System.Collections.Concurrent; using System.Globalization; using System.Linq; using System.Security.Cryptography; -using MediaBrowser.Common; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller; using MediaBrowser.Controller.Authentication; diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 3cc2cefb9..9c0e92705 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -4,7 +4,6 @@ using System; using System.Globalization; using System.IO; using System.Linq; -using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs index 649305fd5..2312c85d9 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs @@ -12,9 +12,9 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.Tasks; -using MediaBrowser.Model.Globalization; namespace Emby.Server.Implementations.ScheduledTasks { diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs index c384cf4bb..57d294a40 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs @@ -5,8 +5,8 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Tasks; namespace Emby.Server.Implementations.ScheduledTasks { diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs index a69380cbb..11a5fb79f 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs @@ -9,7 +9,6 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Updates; using MediaBrowser.Model.Globalization; -using MediaBrowser.Model.Net; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs index e470adcf4..51b620404 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs @@ -6,8 +6,8 @@ using System.Threading; using System.Threading.Tasks; using Emby.Server.Implementations.Library; using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Tasks; namespace Emby.Server.Implementations.ScheduledTasks { diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index 24285bfb9..adec86a10 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -12,7 +12,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Json; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Net; using MediaBrowser.Model.Plugins; using Microsoft.AspNetCore.Authorization; diff --git a/Jellyfin.Api/Extensions/DtoExtensions.cs b/Jellyfin.Api/Extensions/DtoExtensions.cs index e0c744325..06173315a 100644 --- a/Jellyfin.Api/Extensions/DtoExtensions.cs +++ b/Jellyfin.Api/Extensions/DtoExtensions.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using Jellyfin.Api.Helpers; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Dto; diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index 21ec2d32f..9c35d1ec1 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -1,5 +1,4 @@ -using System; -using System.Net.Http; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Models.StreamingDtos; diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index 751b48682..1bb504ad1 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net; -using System.Net.Mime; using System.Security.Claims; using System.Text; using System.Threading; diff --git a/Jellyfin.Data/Entities/HomeSection.cs b/Jellyfin.Data/Entities/HomeSection.cs index 5adc52491..d03d0f7a8 100644 --- a/Jellyfin.Data/Entities/HomeSection.cs +++ b/Jellyfin.Data/Entities/HomeSection.cs @@ -1,5 +1,4 @@ -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations.Schema; using Jellyfin.Data.Enums; namespace Jellyfin.Data.Entities diff --git a/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs b/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs index 730deccae..cc04d033a 100644 --- a/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs +++ b/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries diff --git a/Jellyfin.Networking/Configuration/NetworkConfiguration.cs b/Jellyfin.Networking/Configuration/NetworkConfiguration.cs index 91bf0015f..faf814c06 100644 --- a/Jellyfin.Networking/Configuration/NetworkConfiguration.cs +++ b/Jellyfin.Networking/Configuration/NetworkConfiguration.cs @@ -1,7 +1,6 @@ #pragma warning disable CA1819 // Properties should not return arrays using System; -using MediaBrowser.Model.Configuration; namespace Jellyfin.Networking.Configuration { diff --git a/Jellyfin.Networking/Configuration/NetworkConfigurationExtensions.cs b/Jellyfin.Networking/Configuration/NetworkConfigurationExtensions.cs index e77b17ba9..8cbe398b0 100644 --- a/Jellyfin.Networking/Configuration/NetworkConfigurationExtensions.cs +++ b/Jellyfin.Networking/Configuration/NetworkConfigurationExtensions.cs @@ -1,4 +1,3 @@ -using Jellyfin.Networking.Configuration; using MediaBrowser.Common.Configuration; namespace Jellyfin.Networking.Configuration diff --git a/Jellyfin.Server/Filters/ParameterObsoleteFilter.cs b/Jellyfin.Server/Filters/ParameterObsoleteFilter.cs index e54044d0e..b9ce221f5 100644 --- a/Jellyfin.Server/Filters/ParameterObsoleteFilter.cs +++ b/Jellyfin.Server/Filters/ParameterObsoleteFilter.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using Jellyfin.Api.Attributes; -using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; diff --git a/Jellyfin.Server/Formatters/CssOutputFormatter.cs b/Jellyfin.Server/Formatters/CssOutputFormatter.cs index e8dd48e4e..cfc9d1ad3 100644 --- a/Jellyfin.Server/Formatters/CssOutputFormatter.cs +++ b/Jellyfin.Server/Formatters/CssOutputFormatter.cs @@ -1,5 +1,4 @@ -using System; -using System.Text; +using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Formatters; diff --git a/Jellyfin.Server/Middleware/IpBasedAccessValidationMiddleware.cs b/Jellyfin.Server/Middleware/IpBasedAccessValidationMiddleware.cs index 7d92bd7d3..0afcd61a0 100644 --- a/Jellyfin.Server/Middleware/IpBasedAccessValidationMiddleware.cs +++ b/Jellyfin.Server/Middleware/IpBasedAccessValidationMiddleware.cs @@ -1,9 +1,7 @@ using System.Net; using System.Threading.Tasks; -using Jellyfin.Networking.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; using Microsoft.AspNetCore.Http; namespace Jellyfin.Server.Middleware diff --git a/Jellyfin.Server/Middleware/LanFilteringMiddleware.cs b/Jellyfin.Server/Middleware/LanFilteringMiddleware.cs index 8065054a1..67bf24d2a 100644 --- a/Jellyfin.Server/Middleware/LanFilteringMiddleware.cs +++ b/Jellyfin.Server/Middleware/LanFilteringMiddleware.cs @@ -1,9 +1,6 @@ -using System; -using System.Linq; using System.Net; using System.Threading.Tasks; using Jellyfin.Networking.Configuration; -using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using Microsoft.AspNetCore.Http; diff --git a/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs b/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs index bf0225e98..378e88e25 100644 --- a/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs +++ b/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs @@ -1,6 +1,5 @@ using System; using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.Configuration; using Microsoft.Extensions.Logging; namespace Jellyfin.Server.Migrations.Routines diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 464e02419..c10b2ddb3 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -12,12 +12,10 @@ using System.Threading.Tasks; using CommandLine; using Emby.Server.Implementations; using Emby.Server.Implementations.IO; -using Jellyfin.Api.Controllers; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Extensions; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; diff --git a/Jellyfin.Server/StartupOptions.cs b/Jellyfin.Server/StartupOptions.cs index 6d8210527..a1cecc8c6 100644 --- a/Jellyfin.Server/StartupOptions.cs +++ b/Jellyfin.Server/StartupOptions.cs @@ -1,10 +1,7 @@ -using System; using System.Collections.Generic; using CommandLine; using Emby.Server.Implementations; -using Emby.Server.Implementations.EntryPoints; using Emby.Server.Implementations.Udp; -using Emby.Server.Implementations.Updates; using MediaBrowser.Controller.Extensions; namespace Jellyfin.Server diff --git a/MediaBrowser.Common/Cryptography/PasswordHash.cs b/MediaBrowser.Common/Cryptography/PasswordHash.cs index f2ecc4741..ec21d0580 100644 --- a/MediaBrowser.Common/Cryptography/PasswordHash.cs +++ b/MediaBrowser.Common/Cryptography/PasswordHash.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.IO; using System.Text; namespace MediaBrowser.Common.Cryptography diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs index 012824f65..185df5b77 100644 --- a/MediaBrowser.Common/Net/INetworkManager.cs +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Net; using System.Net.NetworkInformation; -using MediaBrowser.Common.Net; using Microsoft.AspNetCore.Http; namespace MediaBrowser.Common.Net diff --git a/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs b/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs index 31dd95402..a233c358e 100644 --- a/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs +++ b/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using System.Threading; -using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs b/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs index e1f5d05a6..8a8736427 100644 --- a/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs +++ b/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs @@ -1,4 +1,3 @@ -using System; using System.Threading; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Configuration; diff --git a/MediaBrowser.Controller/Drawing/ImageHelper.cs b/MediaBrowser.Controller/Drawing/ImageHelper.cs index 181f8e905..596fcbc8c 100644 --- a/MediaBrowser.Controller/Drawing/ImageHelper.cs +++ b/MediaBrowser.Controller/Drawing/ImageHelper.cs @@ -1,10 +1,7 @@ #pragma warning disable CS1591 #nullable enable -using System; -using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Drawing; -using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Drawing { diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index cac5026f7..bdca5c0ee 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -2,7 +2,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.Controller/Events/Updates/PluginUninstalledEventArgs.cs b/MediaBrowser.Controller/Events/Updates/PluginUninstalledEventArgs.cs index a111e6d82..0f27be9bb 100644 --- a/MediaBrowser.Controller/Events/Updates/PluginUninstalledEventArgs.cs +++ b/MediaBrowser.Controller/Events/Updates/PluginUninstalledEventArgs.cs @@ -1,5 +1,4 @@ using Jellyfin.Data.Events; -using MediaBrowser.Common.Plugins; using MediaBrowser.Model.Plugins; namespace MediaBrowser.Controller.Events.Updates diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 20bfa697e..6a65a8e47 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -3,10 +3,7 @@ using System; using System.Collections.Generic; using System.Net; -using System.Threading; -using System.Threading.Tasks; using MediaBrowser.Common; -using MediaBrowser.Common.Plugins; using MediaBrowser.Model.System; using Microsoft.AspNetCore.Http; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 92b9a8c7e..1379efacb 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -10,8 +10,6 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading; using Jellyfin.Data.Enums; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Extensions; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index dacd6dea6..d47a689f4 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -9,7 +9,6 @@ using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Net; using MediaBrowser.Model.Session; diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 5cbb57990..05dd1a69b 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.System; diff --git a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs index cc8820f39..227c5f258 100644 --- a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs +++ b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs @@ -3,7 +3,6 @@ using System; using System.Globalization; using System.IO; -using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs index 281d50372..89e01c08b 100644 --- a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs +++ b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs @@ -1,10 +1,5 @@ #pragma warning disable CS1591 -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using MediaBrowser.Model.IO; namespace MediaBrowser.Controller.MediaEncoding { diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index 977b14cb0..a5b7363fb 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -14,7 +14,6 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; namespace MediaBrowser.Controller.Playlists diff --git a/MediaBrowser.Controller/Providers/IRemoteImageProvider.cs b/MediaBrowser.Controller/Providers/IRemoteImageProvider.cs index ee8f5b860..de1631dcf 100644 --- a/MediaBrowser.Controller/Providers/IRemoteImageProvider.cs +++ b/MediaBrowser.Controller/Providers/IRemoteImageProvider.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Net.Http; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; diff --git a/MediaBrowser.Controller/Providers/IRemoteSearchProvider.cs b/MediaBrowser.Controller/Providers/IRemoteSearchProvider.cs index 9592baa7c..e401ed211 100644 --- a/MediaBrowser.Controller/Providers/IRemoteSearchProvider.cs +++ b/MediaBrowser.Controller/Providers/IRemoteSearchProvider.cs @@ -3,7 +3,6 @@ using System.Net.Http; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Net; namespace MediaBrowser.Controller.Providers { diff --git a/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs b/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs index feb26bc10..6d63286ef 100644 --- a/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs +++ b/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; -using System.IO; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 205933ae2..36bf77c84 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -16,7 +16,6 @@ using MediaBrowser.Common.Json; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.MediaEncoding.Probing; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs index 8a7c032c5..7b7744163 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Text.Json.Serialization; -using MediaBrowser.Common.Json.Converters; namespace MediaBrowser.MediaEncoding.Probing { diff --git a/MediaBrowser.Model/Dto/NameIdPair.cs b/MediaBrowser.Model/Dto/NameIdPair.cs index 7f18b4502..31516947f 100644 --- a/MediaBrowser.Model/Dto/NameIdPair.cs +++ b/MediaBrowser.Model/Dto/NameIdPair.cs @@ -1,8 +1,6 @@ #nullable disable #pragma warning disable CS1591 -using System; - namespace MediaBrowser.Model.Dto { public class NameIdPair diff --git a/MediaBrowser.Model/LiveTv/TunerHostInfo.cs b/MediaBrowser.Model/LiveTv/TunerHostInfo.cs index 7d4bbb2d0..05576a0f8 100644 --- a/MediaBrowser.Model/LiveTv/TunerHostInfo.cs +++ b/MediaBrowser.Model/LiveTv/TunerHostInfo.cs @@ -1,9 +1,6 @@ #nullable disable #pragma warning disable CS1591 -using System; -using MediaBrowser.Model.Dto; - namespace MediaBrowser.Model.LiveTv { public class TunerHostInfo diff --git a/MediaBrowser.Model/Notifications/NotificationOptions.cs b/MediaBrowser.Model/Notifications/NotificationOptions.cs index 94bb5d6e3..12e093b21 100644 --- a/MediaBrowser.Model/Notifications/NotificationOptions.cs +++ b/MediaBrowser.Model/Notifications/NotificationOptions.cs @@ -5,8 +5,6 @@ using System; using System.Linq; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.Users; namespace MediaBrowser.Model.Notifications { diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index b4b0b826f..3bb2c6f0b 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -25,7 +25,6 @@ using MediaBrowser.Controller.Subtitles; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; -using MediaBrowser.Model.Net; using MediaBrowser.Model.Providers; using Microsoft.Extensions.Logging; using Priority_Queue; diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs index 2adb11908..85a28747f 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs @@ -14,7 +14,6 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; namespace MediaBrowser.Providers.Plugins.AudioDb { diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs index 00feeec1f..25bb3f9ce 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs @@ -19,7 +19,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; using MediaBrowser.Providers.Music; namespace MediaBrowser.Providers.Plugins.AudioDb diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs index b8095ff04..db8536cc9 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs @@ -14,7 +14,6 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; namespace MediaBrowser.Providers.Plugins.AudioDb { diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs index 59ecbc017..cbb61fa35 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs @@ -18,7 +18,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; using MediaBrowser.Providers.Music; namespace MediaBrowser.Providers.Plugins.AudioDb diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index d35805a84..46d303890 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -6,9 +6,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Net.Http; -using System.Text; using System.Text.Json; -using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs index 833d1ae38..d22c1b50a 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs @@ -7,8 +7,6 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; -using TMDbLib.Objects.Find; -using TMDbLib.Objects.Search; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -16,6 +14,8 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; +using TMDbLib.Objects.Find; +using TMDbLib.Objects.Search; namespace MediaBrowser.Providers.Plugins.Tmdb.Movies { diff --git a/tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs index 1e1cde957..dbfad3c2f 100644 --- a/tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs +++ b/tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs @@ -1,5 +1,4 @@ using System; -using System.Globalization; using System.Text.Json; using MediaBrowser.Common.Json.Converters; using Xunit; diff --git a/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs index 22bc7afb9..cb3b66c4c 100644 --- a/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs +++ b/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs @@ -1,5 +1,4 @@ using System; -using System.Globalization; using System.Text.Json; using MediaBrowser.Common.Json.Converters; using Xunit; diff --git a/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs b/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs index 51633e157..5864a0509 100644 --- a/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs +++ b/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs @@ -1,4 +1,3 @@ -using System; using MediaBrowser.Model.Extensions; using Xunit; diff --git a/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookListResolverTests.cs b/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookListResolverTests.cs index e5768b620..d9e77dd2e 100644 --- a/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookListResolverTests.cs +++ b/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookListResolverTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using Emby.Naming.AudioBook; using Emby.Naming.Common; diff --git a/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs b/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs index ad63adadc..53b35c2d6 100644 --- a/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs +++ b/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using Emby.Naming.AudioBook; using Emby.Naming.Common; diff --git a/tests/Jellyfin.Naming.Tests/Subtitles/SubtitleParserTests.cs b/tests/Jellyfin.Naming.Tests/Subtitles/SubtitleParserTests.cs index f3abacb4f..2446660f3 100644 --- a/tests/Jellyfin.Naming.Tests/Subtitles/SubtitleParserTests.cs +++ b/tests/Jellyfin.Naming.Tests/Subtitles/SubtitleParserTests.cs @@ -1,4 +1,3 @@ -using System; using Emby.Naming.Common; using Emby.Naming.Subtitles; using Xunit; diff --git a/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs b/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs index d34f65409..2f173b0ce 100644 --- a/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs @@ -1,4 +1,3 @@ -using System; using Emby.Naming.Common; using Emby.Naming.Video; using MediaBrowser.Model.Entities; diff --git a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs index 5a535ac51..614a68975 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.InteropServices; diff --git a/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs b/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs index 3cbd638f9..0ade345a1 100644 --- a/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs @@ -1,8 +1,6 @@ using System.IO; using System.Reflection; -using System.Text.Json; using System.Threading.Tasks; -using MediaBrowser.Model.Branding; using Xunit; using Xunit.Abstractions; diff --git a/tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs b/tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs index 4e5d0fcb6..0a463cfa3 100644 --- a/tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs +++ b/tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Reflection; using Emby.Server.Implementations; -using Jellyfin.Server; using MediaBrowser.Controller; using MediaBrowser.Model.IO; using Microsoft.Extensions.Configuration; diff --git a/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs index 0b714e80a..146b16cf9 100644 --- a/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs +++ b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs @@ -1,4 +1,3 @@ -using System; using System.Globalization; using System.Text; using Jellyfin.Networking.Configuration; diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicArtistNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicArtistNfoParserTests.cs index 3d8e13e96..8ca3dd96e 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicArtistNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicArtistNfoParserTests.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Threading; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Entities.Audio; -- cgit v1.2.3 From e841922ffd9211cfeee5cca1bda4c139cbda9379 Mon Sep 17 00:00:00 2001 From: Stephen Moore Date: Sat, 17 Apr 2021 17:21:40 +0100 Subject: Fix ArgumentOutOfRangeException scanning AudioBooks AudioResolver.ResolveMultipleAudio method can attempt to access the first item in a List without checking if the list is empty which throws an ArgumentOutOfRangeException and stops the 'Scan Library' process. --- Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs index 90b6a8a7d..4ad84579d 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs @@ -201,6 +201,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio continue; } + if (resolvedItem.Files.Count == 0) + { + continue; + } + var firstMedia = resolvedItem.Files[0]; var libraryItem = new T -- cgit v1.2.3 From 8933389753cc95413576b2fcfdf2ccb160464ad3 Mon Sep 17 00:00:00 2001 From: cvium Date: Mon, 19 Apr 2021 10:49:52 +0200 Subject: Respect user settings for transcode and remux --- Emby.Server.Implementations/Library/MediaSourceManager.cs | 12 +++++++++--- Jellyfin.Api/Helpers/MediaInfoHelper.cs | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index b2943020c..d0b85f07d 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -199,10 +199,15 @@ namespace Emby.Server.Implementations.Library { source.SupportsTranscoding = user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding); } + else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) + { + source.SupportsTranscoding = user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding); + source.SupportsDirectStream = user.HasPermission(PermissionKind.EnablePlaybackRemuxing); + } } } - return SortMediaSources(list).Where(i => i.Type != MediaSourceType.Placeholder).ToList(); + return SortMediaSources(list); } public MediaProtocol GetPathProtocol(string path) @@ -436,7 +441,7 @@ namespace Emby.Server.Implementations.Library } } - private static IEnumerable SortMediaSources(IEnumerable sources) + private static List SortMediaSources(IEnumerable sources) { return sources.OrderBy(i => { @@ -451,8 +456,9 @@ namespace Emby.Server.Implementations.Library { var stream = i.VideoStream; - return stream == null || stream.Width == null ? 0 : stream.Width.Value; + return stream?.Width ?? 0; }) + .Where(i => i.Type != MediaSourceType.Placeholder) .ToList(); } diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs index f07271821..295cfaf08 100644 --- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs +++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs @@ -309,7 +309,7 @@ namespace Jellyfin.Api.Helpers { if (!user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding) && !user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding) - && !user.HasPermission(PermissionKind.EnablePlaybackRemuxing)) + && user.HasPermission(PermissionKind.EnablePlaybackRemuxing)) { options.ForceDirectStream = true; } -- cgit v1.2.3 From 499bac51854cf880beb4add835babf8abd8eb738 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 20 Apr 2021 23:03:36 +0200 Subject: EncodingHelper: Fix circular dependency --- Emby.Server.Implementations/ApplicationHost.cs | 3 +-- Jellyfin.Api/Controllers/DynamicHlsController.cs | 24 ++++++------------- Jellyfin.Api/Controllers/VideoHlsController.cs | 24 +++++-------------- Jellyfin.Api/Controllers/VideosController.cs | 25 ++++++-------------- Jellyfin.Api/Helpers/AudioHelper.cs | 25 ++++++-------------- Jellyfin.Api/Helpers/DynamicHlsHelper.cs | 27 +++++++--------------- Jellyfin.Api/Helpers/StreamingHelpers.cs | 9 ++------ Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 8 +++---- .../MediaEncoding/EncodingHelper.cs | 8 +------ MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 3 --- 10 files changed, 42 insertions(+), 114 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 0512adf10..1ed74210d 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -610,9 +610,8 @@ namespace Emby.Server.Implementations // TODO: Refactor to eliminate the circular dependency here so that Lazy isn't required ServiceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); - // TODO: Refactor to eliminate the circular dependency here so that Lazy isn't required - ServiceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); ServiceCollection.AddSingleton(); + ServiceCollection.AddSingleton(); // TODO: Refactor to eliminate the circular dependencies here so that Lazy isn't required ServiceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index c4e75fe85..b4154b361 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -52,8 +52,6 @@ namespace Jellyfin.Api.Controllers private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; private readonly IFileSystem _fileSystem; - private readonly ISubtitleEncoder _subtitleEncoder; - private readonly IConfiguration _configuration; private readonly IDeviceManager _deviceManager; private readonly TranscodingJobHelper _transcodingJobHelper; private readonly ILogger _logger; @@ -72,12 +70,11 @@ namespace Jellyfin.Api.Controllers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. /// Instance of the class. /// Instance of the interface. /// Instance of . + /// Instance of . public DynamicHlsController( ILibraryManager libraryManager, IUserManager userManager, @@ -87,15 +84,12 @@ namespace Jellyfin.Api.Controllers IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration, IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, ILogger logger, - DynamicHlsHelper dynamicHlsHelper) + DynamicHlsHelper dynamicHlsHelper, + EncodingHelper encodingHelper) { - _encodingHelper = new EncodingHelper(mediaEncoder, fileSystem, subtitleEncoder, configuration); - _libraryManager = libraryManager; _userManager = userManager; _dlnaManager = dlnaManager; @@ -104,12 +98,12 @@ namespace Jellyfin.Api.Controllers _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; _fileSystem = fileSystem; - _subtitleEncoder = subtitleEncoder; - _configuration = configuration; _deviceManager = deviceManager; _transcodingJobHelper = transcodingJobHelper; _logger = logger; _dynamicHlsHelper = dynamicHlsHelper; + _encodingHelper = encodingHelper; + _encodingOptions = serverConfigurationManager.GetEncodingOptions(); } @@ -1126,9 +1120,7 @@ namespace Jellyfin.Api.Controllers _libraryManager, _serverConfigurationManager, _mediaEncoder, - _fileSystem, - _subtitleEncoder, - _configuration, + _encodingHelper, _dlnaManager, _deviceManager, _transcodingJobHelper, @@ -1211,9 +1203,7 @@ namespace Jellyfin.Api.Controllers _libraryManager, _serverConfigurationManager, _mediaEncoder, - _fileSystem, - _subtitleEncoder, - _configuration, + _encodingHelper, _dlnaManager, _deviceManager, _transcodingJobHelper, diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index e95410d02..308334b23 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -48,9 +48,6 @@ namespace Jellyfin.Api.Controllers private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; - private readonly IFileSystem _fileSystem; - private readonly ISubtitleEncoder _subtitleEncoder; - private readonly IConfiguration _configuration; private readonly IDeviceManager _deviceManager; private readonly TranscodingJobHelper _transcodingJobHelper; private readonly ILogger _logger; @@ -60,9 +57,6 @@ namespace Jellyfin.Api.Controllers /// Initializes a new instance of the class. /// /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. @@ -72,11 +66,9 @@ namespace Jellyfin.Api.Controllers /// Instance of the interface. /// The singleton. /// Instance of the . + /// Instance of . public VideoHlsController( IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration, IDlnaManager dlnaManager, IUserManager userManger, IAuthorizationContext authorizationContext, @@ -85,10 +77,9 @@ namespace Jellyfin.Api.Controllers IServerConfigurationManager serverConfigurationManager, IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, - ILogger logger) + ILogger logger, + EncodingHelper encodingHelper) { - _encodingHelper = new EncodingHelper(mediaEncoder, fileSystem, subtitleEncoder, configuration); - _dlnaManager = dlnaManager; _authContext = authorizationContext; _userManager = userManger; @@ -96,12 +87,11 @@ namespace Jellyfin.Api.Controllers _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; - _fileSystem = fileSystem; - _subtitleEncoder = subtitleEncoder; - _configuration = configuration; _deviceManager = deviceManager; _transcodingJobHelper = transcodingJobHelper; _logger = logger; + _encodingHelper = encodingHelper; + _encodingOptions = serverConfigurationManager.GetEncodingOptions(); } @@ -285,9 +275,7 @@ namespace Jellyfin.Api.Controllers _libraryManager, _serverConfigurationManager, _mediaEncoder, - _fileSystem, - _subtitleEncoder, - _configuration, + _encodingHelper, _dlnaManager, _deviceManager, _transcodingJobHelper, diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 699ca5327..8dbb6aaa5 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -49,12 +49,10 @@ namespace Jellyfin.Api.Controllers private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; - private readonly IFileSystem _fileSystem; - private readonly ISubtitleEncoder _subtitleEncoder; - private readonly IConfiguration _configuration; private readonly IDeviceManager _deviceManager; private readonly TranscodingJobHelper _transcodingJobHelper; private readonly IHttpClientFactory _httpClientFactory; + private readonly EncodingHelper _encodingHelper; private readonly TranscodingJobType _transcodingJobType = TranscodingJobType.Progressive; @@ -69,12 +67,10 @@ namespace Jellyfin.Api.Controllers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. /// Instance of the class. /// Instance of the interface. + /// Instance of . public VideosController( ILibraryManager libraryManager, IUserManager userManager, @@ -84,12 +80,10 @@ namespace Jellyfin.Api.Controllers IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration, IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, - IHttpClientFactory httpClientFactory) + IHttpClientFactory httpClientFactory, + EncodingHelper encodingHelper) { _libraryManager = libraryManager; _userManager = userManager; @@ -99,12 +93,10 @@ namespace Jellyfin.Api.Controllers _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; - _fileSystem = fileSystem; - _subtitleEncoder = subtitleEncoder; - _configuration = configuration; _deviceManager = deviceManager; _transcodingJobHelper = transcodingJobHelper; _httpClientFactory = httpClientFactory; + _encodingHelper = encodingHelper; } /// @@ -444,9 +436,7 @@ namespace Jellyfin.Api.Controllers _libraryManager, _serverConfigurationManager, _mediaEncoder, - _fileSystem, - _subtitleEncoder, - _configuration, + _encodingHelper, _dlnaManager, _deviceManager, _transcodingJobHelper, @@ -515,8 +505,7 @@ namespace Jellyfin.Api.Controllers // Need to start ffmpeg (because media can't be returned directly) var encodingOptions = _serverConfigurationManager.GetEncodingOptions(); - var encodingHelper = new EncodingHelper(_mediaEncoder, _fileSystem, _subtitleEncoder, _configuration); - var ffmpegCommandLineArguments = encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, outputPath, "superfast"); + var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, outputPath, "superfast"); return await FileStreamResponseHelpers.GetTranscodedFile( state, isHeadRequest, diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index 9c35d1ec1..cf35ee23a 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -32,13 +32,11 @@ namespace Jellyfin.Api.Helpers private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; - private readonly IFileSystem _fileSystem; - private readonly ISubtitleEncoder _subtitleEncoder; - private readonly IConfiguration _configuration; private readonly IDeviceManager _deviceManager; private readonly TranscodingJobHelper _transcodingJobHelper; private readonly IHttpClientFactory _httpClientFactory; private readonly IHttpContextAccessor _httpContextAccessor; + private readonly EncodingHelper _encodingHelper; /// /// Initializes a new instance of the class. @@ -50,13 +48,11 @@ namespace Jellyfin.Api.Helpers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. /// Instance of . /// Instance of the interface. /// Instance of the interface. + /// Instance of . public AudioHelper( IDlnaManager dlnaManager, IAuthorizationContext authContext, @@ -65,13 +61,11 @@ namespace Jellyfin.Api.Helpers IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration, IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, IHttpClientFactory httpClientFactory, - IHttpContextAccessor httpContextAccessor) + IHttpContextAccessor httpContextAccessor, + EncodingHelper encodingHelper) { _dlnaManager = dlnaManager; _authContext = authContext; @@ -80,13 +74,11 @@ namespace Jellyfin.Api.Helpers _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; - _fileSystem = fileSystem; - _subtitleEncoder = subtitleEncoder; - _configuration = configuration; _deviceManager = deviceManager; _transcodingJobHelper = transcodingJobHelper; _httpClientFactory = httpClientFactory; _httpContextAccessor = httpContextAccessor; + _encodingHelper = encodingHelper; } /// @@ -116,9 +108,7 @@ namespace Jellyfin.Api.Helpers _libraryManager, _serverConfigurationManager, _mediaEncoder, - _fileSystem, - _subtitleEncoder, - _configuration, + _encodingHelper, _dlnaManager, _deviceManager, _transcodingJobHelper, @@ -187,8 +177,7 @@ namespace Jellyfin.Api.Helpers // Need to start ffmpeg (because media can't be returned directly) var encodingOptions = _serverConfigurationManager.GetEncodingOptions(); - var encodingHelper = new EncodingHelper(_mediaEncoder, _fileSystem, _subtitleEncoder, _configuration); - var ffmpegCommandLineArguments = encodingHelper.GetProgressiveAudioFullCommandLine(state, encodingOptions, outputPath); + var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveAudioFullCommandLine(state, encodingOptions, outputPath); return await FileStreamResponseHelpers.GetTranscodedFile( state, isHeadRequest, diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index 1bb504ad1..fcada0e77 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -40,14 +40,12 @@ namespace Jellyfin.Api.Helpers private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; - private readonly IFileSystem _fileSystem; - private readonly ISubtitleEncoder _subtitleEncoder; - private readonly IConfiguration _configuration; private readonly IDeviceManager _deviceManager; private readonly TranscodingJobHelper _transcodingJobHelper; private readonly INetworkManager _networkManager; private readonly ILogger _logger; private readonly IHttpContextAccessor _httpContextAccessor; + private readonly EncodingHelper _encodingHelper; /// /// Initializes a new instance of the class. @@ -59,14 +57,12 @@ namespace Jellyfin.Api.Helpers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. /// Instance of . /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of . public DynamicHlsHelper( ILibraryManager libraryManager, IUserManager userManager, @@ -75,14 +71,12 @@ namespace Jellyfin.Api.Helpers IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration, IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, INetworkManager networkManager, ILogger logger, - IHttpContextAccessor httpContextAccessor) + IHttpContextAccessor httpContextAccessor, + EncodingHelper encodingHelper) { _libraryManager = libraryManager; _userManager = userManager; @@ -91,14 +85,12 @@ namespace Jellyfin.Api.Helpers _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; - _fileSystem = fileSystem; - _subtitleEncoder = subtitleEncoder; - _configuration = configuration; _deviceManager = deviceManager; _transcodingJobHelper = transcodingJobHelper; _networkManager = networkManager; _logger = logger; _httpContextAccessor = httpContextAccessor; + _encodingHelper = encodingHelper; } /// @@ -144,9 +136,7 @@ namespace Jellyfin.Api.Helpers _libraryManager, _serverConfigurationManager, _mediaEncoder, - _fileSystem, - _subtitleEncoder, - _configuration, + _encodingHelper, _dlnaManager, _deviceManager, _transcodingJobHelper, @@ -227,9 +217,8 @@ namespace Jellyfin.Api.Helpers var sdrVideoUrl = ReplaceProfile(playlistUrl, "hevc", string.Join(',', requestedVideoProfiles), "main"); sdrVideoUrl += "&AllowVideoStreamCopy=false"; - EncodingHelper encodingHelper = new EncodingHelper(_mediaEncoder, _fileSystem, _subtitleEncoder, _configuration); - var sdrOutputVideoBitrate = encodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec) ?? 0; - var sdrOutputAudioBitrate = encodingHelper.GetAudioBitrateParam(state.VideoRequest, state.AudioStream) ?? 0; + var sdrOutputVideoBitrate = _encodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec) ?? 0; + var sdrOutputAudioBitrate = _encodingHelper.GetAudioBitrateParam(state.VideoRequest, state.AudioStream) ?? 0; var sdrTotalBitrate = sdrOutputAudioBitrate + sdrOutputVideoBitrate; AppendPlaylist(builder, state, sdrVideoUrl, sdrTotalBitrate, subtitleGroup); diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index e2306aa27..bab901c15 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -41,9 +41,7 @@ namespace Jellyfin.Api.Helpers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. + /// Instance of . /// Instance of the interface. /// Instance of the interface. /// Initialized . @@ -59,16 +57,13 @@ namespace Jellyfin.Api.Helpers ILibraryManager libraryManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration, + EncodingHelper encodingHelper, IDlnaManager dlnaManager, IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, TranscodingJobType transcodingJobType, CancellationToken cancellationToken) { - EncodingHelper encodingHelper = new EncodingHelper(mediaEncoder, fileSystem, subtitleEncoder, configuration); // Parse the DLNA time seek header if (!streamingRequest.StartTimeTicks.HasValue) { diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 240d132b1..0879cbd18 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -62,8 +62,7 @@ namespace Jellyfin.Api.Helpers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. + /// Instance of . /// Instance of the interface. public TranscodingJobHelper( ILogger logger, @@ -73,8 +72,7 @@ namespace Jellyfin.Api.Helpers IServerConfigurationManager serverConfigurationManager, ISessionManager sessionManager, IAuthorizationContext authorizationContext, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration, + EncodingHelper encodingHelper, ILoggerFactory loggerFactory) { _logger = logger; @@ -84,8 +82,8 @@ namespace Jellyfin.Api.Helpers _serverConfigurationManager = serverConfigurationManager; _sessionManager = sessionManager; _authorizationContext = authorizationContext; + _encodingHelper = encodingHelper; _loggerFactory = loggerFactory; - _encodingHelper = new EncodingHelper(mediaEncoder, fileSystem, subtitleEncoder, configuration); DeleteEncodedMediaCache(); diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 1379efacb..2b5364775 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -25,9 +25,7 @@ namespace MediaBrowser.Controller.MediaEncoding private static readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly IMediaEncoder _mediaEncoder; - private readonly IFileSystem _fileSystem; private readonly ISubtitleEncoder _subtitleEncoder; - private readonly IConfiguration _configuration; private static readonly string[] _videoProfiles = new[] { @@ -42,14 +40,10 @@ namespace MediaBrowser.Controller.MediaEncoding public EncodingHelper( IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration) + ISubtitleEncoder subtitleEncoder) { _mediaEncoder = mediaEncoder; - _fileSystem = fileSystem; _subtitleEncoder = subtitleEncoder; - _configuration = configuration; } public string GetH264Encoder(EncodingJobInfo state, EncodingOptions encodingOptions) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 36bf77c84..62c0c0bb1 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -52,7 +52,6 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly IServerConfigurationManager _configurationManager; private readonly IFileSystem _fileSystem; private readonly ILocalizationManager _localization; - private readonly Lazy _encodingHelperFactory; private readonly string _startupOptionFFmpegPath; private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(2, 2); @@ -76,14 +75,12 @@ namespace MediaBrowser.MediaEncoding.Encoder IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization, - Lazy encodingHelperFactory, IConfiguration config) { _logger = logger; _configurationManager = configurationManager; _fileSystem = fileSystem; _localization = localization; - _encodingHelperFactory = encodingHelperFactory; _startupOptionFFmpegPath = config.GetValue(Controller.Extensions.ConfigurationExtensions.FfmpegPathKey) ?? string.Empty; _jsonSerializerOptions = JsonDefaults.Options; } -- cgit v1.2.3 From dcd96909cdade6b8889ae29054af2927a416c0fe Mon Sep 17 00:00:00 2001 From: artiume Date: Tue, 20 Apr 2021 19:28:18 -0400 Subject: Fix Audiobook Resume https://github.com/jellyfin/jellyfin/issues/5703 --- Emby.Server.Implementations/Library/UserDataManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs index e8caea196..78dc95b62 100644 --- a/Emby.Server.Implementations/Library/UserDataManager.cs +++ b/Emby.Server.Implementations/Library/UserDataManager.cs @@ -251,7 +251,7 @@ namespace Emby.Server.Implementations.Library var minIn = TimeSpan.FromTicks(positionTicks).TotalMinutes; var minOut = TimeSpan.FromTicks(runtimeTicks - positionTicks).TotalMinutes; - if (minIn > _config.Configuration.MinAudiobookResume) + if (minIn < _config.Configuration.MinAudiobookResume) { // ignore progress during the beginning positionTicks = 0; -- cgit v1.2.3 From 005ae80b31c8f354f83390a7b587f058e6792702 Mon Sep 17 00:00:00 2001 From: artiume Date: Wed, 21 Apr 2021 07:11:14 -0400 Subject: Update var names --- Emby.Server.Implementations/Library/UserDataManager.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs index 78dc95b62..827e3c64b 100644 --- a/Emby.Server.Implementations/Library/UserDataManager.cs +++ b/Emby.Server.Implementations/Library/UserDataManager.cs @@ -248,15 +248,15 @@ namespace Emby.Server.Implementations.Library } else if (positionTicks > 0 && hasRuntime && item is AudioBook) { - var minIn = TimeSpan.FromTicks(positionTicks).TotalMinutes; - var minOut = TimeSpan.FromTicks(runtimeTicks - positionTicks).TotalMinutes; + var playbackPositionInMinutes = TimeSpan.FromTicks(positionTicks).TotalMinutes; + var remainingTimeInMinutes = TimeSpan.FromTicks(runtimeTicks - positionTicks).TotalMinutes; - if (minIn < _config.Configuration.MinAudiobookResume) + if (playbackPositionInMinutes < _config.Configuration.MinAudiobookResume) { // ignore progress during the beginning positionTicks = 0; } - else if (minOut < _config.Configuration.MaxAudiobookResume || positionTicks >= runtimeTicks) + else if (remainingTimeInMinutes < _config.Configuration.MaxAudiobookResume || positionTicks >= runtimeTicks) { // mark as completed close to the end positionTicks = 0; -- cgit v1.2.3 From b0914f9f2c16b538241b74dd22a7bb896fd56b4b Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 22 Apr 2021 01:20:55 +0200 Subject: Remove unused/duplicate services --- Emby.Server.Implementations/ApplicationHost.cs | 5 ----- 1 file changed, 5 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 1ed74210d..703f8d20d 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -607,9 +607,6 @@ namespace Emby.Server.Implementations ServiceCollection.AddSingleton(); - // TODO: Refactor to eliminate the circular dependency here so that Lazy isn't required - ServiceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); - ServiceCollection.AddSingleton(); ServiceCollection.AddSingleton(); @@ -676,8 +673,6 @@ namespace Emby.Server.Implementations ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); ServiceCollection.AddSingleton(); -- cgit v1.2.3 From b323044139fd7a0b63a717101f7ccb7f03f3f125 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 22 Apr 2021 01:23:24 +0200 Subject: Reduce string allocations/fs lookups in resolve code --- .../Library/LibraryManager.cs | 1 - .../Library/ResolverHelper.cs | 58 ++++++---------------- .../Entities/AggregateFolder.cs | 3 +- .../Entities/CollectionFolder.cs | 1 - MediaBrowser.Controller/Library/ItemResolveArgs.cs | 6 +-- .../Library/EpisodeResolverTest.cs | 11 +++- 6 files changed, 29 insertions(+), 51 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 6a9f4174d..d869c7e39 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -558,7 +558,6 @@ namespace Emby.Server.Implementations.Library var args = new ItemResolveArgs(_configurationManager.ApplicationPaths, directoryService) { Parent = parent, - Path = fullPath, FileInfo = fileInfo, CollectionType = collectionType, LibraryOptions = libraryOptions diff --git a/Emby.Server.Implementations/Library/ResolverHelper.cs b/Emby.Server.Implementations/Library/ResolverHelper.cs index 4e4cac75b..8be80d726 100644 --- a/Emby.Server.Implementations/Library/ResolverHelper.cs +++ b/Emby.Server.Implementations/Library/ResolverHelper.cs @@ -1,3 +1,5 @@ +#nullable enable + using System; using System.IO; using System.Linq; @@ -21,8 +23,8 @@ namespace Emby.Server.Implementations.Library /// The file system. /// The library manager. /// The directory service. - /// Item must have a path - public static void SetInitialItemValues(BaseItem item, Folder parent, IFileSystem fileSystem, ILibraryManager libraryManager, IDirectoryService directoryService) + /// Item must have a path. + public static void SetInitialItemValues(BaseItem item, Folder? parent, IFileSystem fileSystem, ILibraryManager libraryManager, IDirectoryService directoryService) { // This version of the below method has no ItemResolveArgs, so we have to require the path already being set if (string.IsNullOrEmpty(item.Path)) @@ -43,9 +45,9 @@ namespace Emby.Server.Implementations.Library // Make sure DateCreated and DateModified have values var fileInfo = directoryService.GetFile(item.Path); - SetDateCreated(item, fileSystem, fileInfo); + SetDateCreated(item, fileInfo); - EnsureName(item, item.Path, fileInfo); + EnsureName(item, fileInfo); } /// @@ -72,9 +74,9 @@ namespace Emby.Server.Implementations.Library item.Id = libraryManager.GetNewItemId(item.Path, item.GetType()); // Make sure the item has a name - EnsureName(item, item.Path, args.FileInfo); + EnsureName(item, args.FileInfo); - item.IsLocked = item.Path.IndexOf("[dontfetchmeta]", StringComparison.OrdinalIgnoreCase) != -1 || + item.IsLocked = item.Path.Contains("[dontfetchmeta]", StringComparison.OrdinalIgnoreCase) || item.GetParents().Any(i => i.IsLocked); // Make sure DateCreated and DateModified have values @@ -84,28 +86,15 @@ namespace Emby.Server.Implementations.Library /// /// Ensures the name. /// - private static void EnsureName(BaseItem item, string fullPath, FileSystemMetadata fileInfo) + private static void EnsureName(BaseItem item, FileSystemMetadata fileInfo) { // If the subclass didn't supply a name, add it here - if (string.IsNullOrEmpty(item.Name) && !string.IsNullOrEmpty(fullPath)) + if (string.IsNullOrEmpty(item.Name) && !string.IsNullOrEmpty(item.Path)) { - var fileName = fileInfo == null ? Path.GetFileName(fullPath) : fileInfo.Name; - - item.Name = GetDisplayName(fileName, fileInfo != null && fileInfo.IsDirectory); + item.Name = fileInfo.IsDirectory ? fileInfo.Name : Path.GetFileNameWithoutExtension(fileInfo.Name); } } - /// - /// Gets the display name. - /// - /// The path. - /// if set to true [is directory]. - /// System.String. - private static string GetDisplayName(string path, bool isDirectory) - { - return isDirectory ? Path.GetFileName(path) : Path.GetFileNameWithoutExtension(path); - } - /// /// Ensures DateCreated and DateModified have values. /// @@ -114,21 +103,6 @@ namespace Emby.Server.Implementations.Library /// The args. private static void EnsureDates(IFileSystem fileSystem, BaseItem item, ItemResolveArgs args) { - if (fileSystem == null) - { - throw new ArgumentNullException(nameof(fileSystem)); - } - - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } - - if (args == null) - { - throw new ArgumentNullException(nameof(args)); - } - // See if a different path came out of the resolver than what went in if (!fileSystem.AreEqual(args.Path, item.Path)) { @@ -136,7 +110,7 @@ namespace Emby.Server.Implementations.Library if (childData != null) { - SetDateCreated(item, fileSystem, childData); + SetDateCreated(item, childData); } else { @@ -144,17 +118,17 @@ namespace Emby.Server.Implementations.Library if (fileData.Exists) { - SetDateCreated(item, fileSystem, fileData); + SetDateCreated(item, fileData); } } } else { - SetDateCreated(item, fileSystem, args.FileInfo); + SetDateCreated(item, args.FileInfo); } } - private static void SetDateCreated(BaseItem item, IFileSystem fileSystem, FileSystemMetadata info) + private static void SetDateCreated(BaseItem item, FileSystemMetadata? info) { var config = BaseItem.ConfigurationManager.GetMetadataConfiguration(); @@ -163,7 +137,7 @@ namespace Emby.Server.Implementations.Library // directoryService.getFile may return null if (info != null) { - var dateCreated = fileSystem.GetCreationTimeUtc(info); + var dateCreated = info.CreationTimeUtc; if (dateCreated.Equals(DateTime.MinValue)) { diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs index 6ebea5f44..6a92200dd 100644 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs @@ -120,8 +120,7 @@ namespace MediaBrowser.Controller.Entities var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService) { - FileInfo = FileSystem.GetDirectoryInfo(path), - Path = path + FileInfo = FileSystem.GetDirectoryInfo(path) }; // Gather child folder and files diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 76b6d39a9..16a2c77e9 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -271,7 +271,6 @@ namespace MediaBrowser.Controller.Entities var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService) { FileInfo = FileSystem.GetDirectoryInfo(path), - Path = path, Parent = GetParent() as Folder, CollectionType = CollectionType }; diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index 12a311dc3..df8842237 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -60,10 +60,10 @@ namespace MediaBrowser.Controller.Library public FileSystemMetadata FileInfo { get; set; } /// - /// Gets or sets the path. + /// Gets the path. /// /// The path. - public string Path { get; set; } + public string Path => FileInfo.FullName; /// /// Gets a value indicating whether this instance is directory. @@ -87,7 +87,7 @@ namespace MediaBrowser.Controller.Library return false; } - var parentDir = System.IO.Path.GetDirectoryName(Path) ?? string.Empty; + var parentDir = FileInfo.DirectoryName ?? string.Empty; return parentDir.Length > _appPaths.RootFolderPath.Length && parentDir.StartsWith(_appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase); diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs index 876519215..c393742eb 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs @@ -6,6 +6,7 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; using Moq; using Xunit; @@ -28,7 +29,10 @@ namespace Jellyfin.Server.Implementations.Tests.Library { Parent = parent, CollectionType = CollectionType.TvShows, - Path = "All My Children/Season 01/Extras/All My Children S01E01 - Behind The Scenes.mkv" + FileInfo = new FileSystemMetadata() + { + FullName = "All My Children/Season 01/Extras/All My Children S01E01 - Behind The Scenes.mkv" + } }; Assert.Null(episodeResolver.Resolve(itemResolveArgs)); @@ -48,7 +52,10 @@ namespace Jellyfin.Server.Implementations.Tests.Library { Parent = series, CollectionType = CollectionType.TvShows, - Path = "Extras/Extras S01E01.mkv" + FileInfo = new FileSystemMetadata() + { + FullName = "Extras/Extras S01E01.mkv" + } }; Assert.NotNull(episodeResolver.Resolve(itemResolveArgs)); } -- cgit v1.2.3 From 81209258abeade8614d848f7e7cceeb6bb37a7d7 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 22 Apr 2021 03:11:21 +0200 Subject: ManagedFileSystem: Rewrite GetValidFilename and more improvements --- .../IO/ManagedFileSystem.cs | 62 ++++++++++++---------- .../IO/ManagedFileSystemTests.cs | 10 ++++ 2 files changed, 43 insertions(+), 29 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 3893a1577..0d72cb00f 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -2,11 +2,10 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; -using System.Text; +using System.Runtime.InteropServices; using MediaBrowser.Common.Configuration; using MediaBrowser.Model.IO; using MediaBrowser.Model.System; @@ -24,7 +23,7 @@ namespace Emby.Server.Implementations.IO private readonly List _shortcutHandlers = new List(); private readonly string _tempPath; - private readonly bool _isEnvironmentCaseInsensitive; + private static readonly bool _isEnvironmentCaseInsensitive = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); public ManagedFileSystem( ILogger logger, @@ -32,8 +31,6 @@ namespace Emby.Server.Implementations.IO { Logger = logger; _tempPath = applicationPaths.TempDirectory; - - _isEnvironmentCaseInsensitive = OperatingSystem.Id == OperatingSystemId.Windows; } public virtual void AddShortcutHandler(IShortcutHandler handler) @@ -55,7 +52,7 @@ namespace Emby.Server.Implementations.IO } var extension = Path.GetExtension(filename); - return _shortcutHandlers.Any(i => string.Equals(extension, i.Extension, _isEnvironmentCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)); + return _shortcutHandlers.Any(i => string.Equals(extension, i.Extension, StringComparison.OrdinalIgnoreCase)); } /// @@ -72,7 +69,7 @@ namespace Emby.Server.Implementations.IO } var extension = Path.GetExtension(filename); - var handler = _shortcutHandlers.FirstOrDefault(i => string.Equals(extension, i.Extension, StringComparison.OrdinalIgnoreCase)); + var handler = _shortcutHandlers.Find(i => string.Equals(extension, i.Extension, StringComparison.OrdinalIgnoreCase)); return handler?.Resolve(filename); } @@ -303,16 +300,38 @@ namespace Emby.Server.Implementations.IO /// The filename. /// System.String. /// The filename is null. - public virtual string GetValidFilename(string filename) + public string GetValidFilename(string filename) { - var builder = new StringBuilder(filename); + return string.Create( + filename.Length, + filename, + (chars, state) => + { + state.AsSpan().CopyTo(chars); - foreach (var c in Path.GetInvalidFileNameChars()) - { - builder = builder.Replace(c, ' '); - } + var invalid = Path.GetInvalidFileNameChars(); - return builder.ToString(); + var first = state.AsSpan().IndexOfAny(invalid); + if (first == -1) + { + // Fast path for clean strings + return; + } + + chars[first++] = ' '; + + var len = chars.Length; + foreach (var c in invalid) + { + for (int i = first; i < len; i++) + { + if (chars[i] == c) + { + chars[i] = ' '; + } + } + } + }); } /// @@ -684,20 +703,5 @@ namespace Emby.Server.Implementations.IO AttributesToSkip = 0 }; } - - private static void RunProcess(string path, string args, string workingDirectory) - { - using (var process = Process.Start(new ProcessStartInfo - { - Arguments = args, - FileName = path, - CreateNoWindow = true, - WorkingDirectory = workingDirectory, - WindowStyle = ProcessWindowStyle.Normal - })) - { - process.WaitForExit(); - } - } } } diff --git a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs index 614a68975..30e6542f9 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs @@ -42,6 +42,16 @@ namespace Jellyfin.Server.Implementations.Tests.IO } } + [Theory] + [InlineData("ValidFileName", "ValidFileName")] + [InlineData("AC/DC", "AC DC")] + [InlineData("Invalid\0", "Invalid ")] + [InlineData("AC/DC\0KD/A", "AC DC KD A")] + public void GetValidFilename_ReturnsValidFilename(string filename, string expectedFileName) + { + Assert.Equal(expectedFileName, _sut.GetValidFilename(filename)); + } + [SkippableFact] public void GetFileInfo_DanglingSymlink_ExistsFalse() { -- cgit v1.2.3 From 33327aa1a951a1d0717b39f8f71356f09eb7bd6e Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 22 Apr 2021 12:31:47 +0200 Subject: Improve fast path of ManagedFileSystem.GetValidFilename | Method | Data | Mean | Error | StdDev | Median | Gen 0 | Gen 1 | Gen 2 | Allocated | |---------------------------- |-------------- |------------:|----------:|----------:|------------:|-------:|------:|------:|----------:| | GetValidFilenameBench | AC/DCKD/A | 52.29 ns | 0.537 ns | 0.448 ns | 52.35 ns | 0.0255 | - | - | 80 B | | GetValidFilenameOldBench | AC/DCKD/A | 86.68 ns | 1.205 ns | 1.127 ns | 86.33 ns | 0.0587 | - | - | 184 B | | GetValidFilenameWinBench | AC/DCKD/A | 448.55 ns | 1.228 ns | 1.088 ns | 448.33 ns | 0.0505 | - | - | 160 B | | GetValidFilenameOldWinBench | AC/DCKD/A | 865.21 ns | 5.734 ns | 5.083 ns | 866.60 ns | 0.0839 | - | - | 264 B | | GetValidFilenameBench | ValidFileName | 16.00 ns | 0.234 ns | 0.207 ns | 16.02 ns | 0.0102 | - | - | 32 B | | GetValidFilenameOldBench | ValidFileName | 100.66 ns | 1.255 ns | 1.174 ns | 101.21 ns | 0.0587 | - | - | 184 B | | GetValidFilenameWinBench | ValidFileName | 116.60 ns | 1.624 ns | 1.519 ns | 116.88 ns | 0.0356 | - | - | 112 B | | GetValidFilenameOldWinBench | ValidFileName | 1,052.66 ns | 18.077 ns | 33.056 ns | 1,037.25 ns | 0.0839 | - | - | 264 B | --- .../IO/ManagedFileSystem.cs | 27 +++++++++++----------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 0d72cb00f..df973f971 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -302,28 +302,27 @@ namespace Emby.Server.Implementations.IO /// The filename is null. public string GetValidFilename(string filename) { + var invalid = Path.GetInvalidFileNameChars(); + var first = filename.IndexOfAny(invalid); + if (first == -1) + { + // Fast path for clean strings + return filename; + } + return string.Create( filename.Length, - filename, + (filename, invalid, first), (chars, state) => { - state.AsSpan().CopyTo(chars); - - var invalid = Path.GetInvalidFileNameChars(); - - var first = state.AsSpan().IndexOfAny(invalid); - if (first == -1) - { - // Fast path for clean strings - return; - } + state.filename.AsSpan().CopyTo(chars); - chars[first++] = ' '; + chars[state.first++] = ' '; var len = chars.Length; - foreach (var c in invalid) + foreach (var c in state.invalid) { - for (int i = first; i < len; i++) + for (int i = state.first; i < len; i++) { if (chars[i] == c) { -- cgit v1.2.3 From 940c30081ef8b9290d9f3c24b5529b2e593f924c Mon Sep 17 00:00:00 2001 From: crobibero Date: Thu, 22 Apr 2021 06:49:54 -0600 Subject: Mark PasswordSha1 as obsolete --- Emby.Server.Implementations/Session/SessionManager.cs | 2 +- MediaBrowser.Controller/Session/AuthenticationRequest.cs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 10e28c33a..6f21ec31e 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -1485,7 +1485,7 @@ namespace Emby.Server.Implementations.Session user = await _userManager.AuthenticateUser( request.Username, request.Password, - request.PasswordSha1, + null, request.RemoteEndPoint, true).ConfigureAwait(false); } diff --git a/MediaBrowser.Controller/Session/AuthenticationRequest.cs b/MediaBrowser.Controller/Session/AuthenticationRequest.cs index cc321fd22..8c3ac58f2 100644 --- a/MediaBrowser.Controller/Session/AuthenticationRequest.cs +++ b/MediaBrowser.Controller/Session/AuthenticationRequest.cs @@ -12,6 +12,7 @@ namespace MediaBrowser.Controller.Session public string Password { get; set; } + [Obsolete("Send full password in Password field")] public string PasswordSha1 { get; set; } public string App { get; set; } -- cgit v1.2.3 From a02e37daa009bebc3c5076b0e407dffe41e84c55 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 22 Apr 2021 15:28:24 +0200 Subject: SqliteItemRepository: remove redundant operations removed: * nameof -> FullName lookup * IndexOf before Replace * Enum.GetNames -> Enum.Parse roundtrip --- .../Data/SqliteItemRepository.cs | 185 ++++++++------------- .../Library/LibraryManager.cs | 2 +- .../Persistence/IItemRepository.cs | 3 +- 3 files changed, 68 insertions(+), 122 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 694805ebe..28e59913c 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -2116,9 +2116,7 @@ namespace Emby.Server.Implementations.Data || query.IsLiked.HasValue; } - private readonly ItemFields[] _allFields = Enum.GetNames(typeof(ItemFields)) - .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)) - .ToArray(); + private readonly ItemFields[] _allFields = Enum.GetValues(); private string[] GetColumnNamesFromField(ItemFields field) { @@ -2721,87 +2719,22 @@ namespace Emby.Server.Implementations.Data private string FixUnicodeChars(string buffer) { - if (buffer.IndexOf('\u2013', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace('\u2013', '-'); // en dash - } - - if (buffer.IndexOf('\u2014', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace('\u2014', '-'); // em dash - } - - if (buffer.IndexOf('\u2015', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace('\u2015', '-'); // horizontal bar - } - - if (buffer.IndexOf('\u2017', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace('\u2017', '_'); // double low line - } - - if (buffer.IndexOf('\u2018', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace('\u2018', '\''); // left single quotation mark - } - - if (buffer.IndexOf('\u2019', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace('\u2019', '\''); // right single quotation mark - } - - if (buffer.IndexOf('\u201a', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace('\u201a', ','); // single low-9 quotation mark - } - - if (buffer.IndexOf('\u201b', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace('\u201b', '\''); // single high-reversed-9 quotation mark - } - - if (buffer.IndexOf('\u201c', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace('\u201c', '\"'); // left double quotation mark - } - - if (buffer.IndexOf('\u201d', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace('\u201d', '\"'); // right double quotation mark - } - - if (buffer.IndexOf('\u201e', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace('\u201e', '\"'); // double low-9 quotation mark - } - - if (buffer.IndexOf('\u2026', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace("\u2026", "...", StringComparison.Ordinal); // horizontal ellipsis - } - - if (buffer.IndexOf('\u2032', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace('\u2032', '\''); // prime - } - - if (buffer.IndexOf('\u2033', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace('\u2033', '\"'); // double prime - } - - if (buffer.IndexOf('\u0060', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace('\u0060', '\''); // grave accent - } - - if (buffer.IndexOf('\u00B4', StringComparison.Ordinal) > -1) - { - buffer = buffer.Replace('\u00B4', '\''); // acute accent - } - - return buffer; + buffer = buffer.Replace('\u2013', '-'); // en dash + buffer = buffer.Replace('\u2014', '-'); // em dash + buffer = buffer.Replace('\u2015', '-'); // horizontal bar + buffer = buffer.Replace('\u2017', '_'); // double low line + buffer = buffer.Replace('\u2018', '\''); // left single quotation mark + buffer = buffer.Replace('\u2019', '\''); // right single quotation mark + buffer = buffer.Replace('\u201a', ','); // single low-9 quotation mark + buffer = buffer.Replace('\u201b', '\''); // single high-reversed-9 quotation mark + buffer = buffer.Replace('\u201c', '\"'); // left double quotation mark + buffer = buffer.Replace('\u201d', '\"'); // right double quotation mark + buffer = buffer.Replace('\u201e', '\"'); // double low-9 quotation mark + buffer = buffer.Replace("\u2026", "...", StringComparison.Ordinal); // horizontal ellipsis + buffer = buffer.Replace('\u2032', '\''); // prime + buffer = buffer.Replace('\u2033', '\"'); // double prime + buffer = buffer.Replace('\u0060', '\''); // grave accent + return buffer.Replace('\u00B4', '\''); // acute accent } private void AddItem(List items, BaseItem newItem) @@ -3584,11 +3517,11 @@ namespace Emby.Server.Implementations.Data statement?.TryBind("@IsFolder", query.IsFolder); } - var includeTypes = query.IncludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray(); + var includeTypes = query.IncludeItemTypes.Select(MapIncludeItemTypes).Where(x => x != null).ToArray(); // Only specify excluded types if no included types are specified if (includeTypes.Length == 0) { - var excludeTypes = query.ExcludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray(); + var excludeTypes = query.ExcludeItemTypes.Select(MapIncludeItemTypes).Where(x => x != null).ToArray(); if (excludeTypes.Length == 1) { whereClauses.Add("type<>@type"); @@ -4532,7 +4465,7 @@ namespace Emby.Server.Implementations.Data whereClauses.Add(GetProviderIdClause(query.HasTvdbId.Value, "tvdb")); } - var includedItemByNameTypes = GetItemByNameTypesInQuery(query).SelectMany(MapIncludeItemTypes).ToList(); + var includedItemByNameTypes = GetItemByNameTypesInQuery(query); var enableItemsByName = (query.IncludeItemsByName ?? false) && includedItemByNameTypes.Count > 0; var queryTopParentIds = query.TopParentIds; @@ -4790,27 +4723,27 @@ namespace Emby.Server.Implementations.Data if (IsTypeInQuery(nameof(Person), query)) { - list.Add(nameof(Person)); + list.Add(typeof(Person).FullName); } if (IsTypeInQuery(nameof(Genre), query)) { - list.Add(nameof(Genre)); + list.Add(typeof(Genre).FullName); } if (IsTypeInQuery(nameof(MusicGenre), query)) { - list.Add(nameof(MusicGenre)); + list.Add(typeof(MusicGenre).FullName); } if (IsTypeInQuery(nameof(MusicArtist), query)) { - list.Add(nameof(MusicArtist)); + list.Add(typeof(MusicArtist).FullName); } if (IsTypeInQuery(nameof(Studio), query)) { - list.Add(nameof(Studio)); + list.Add(typeof(Studio).FullName); } return list; @@ -4915,15 +4848,10 @@ namespace Emby.Server.Implementations.Data typeof(AggregateFolder) }; - public void UpdateInheritedValues(CancellationToken cancellationToken) - { - UpdateInheritedTags(cancellationToken); - } - - private void UpdateInheritedTags(CancellationToken cancellationToken) + public void UpdateInheritedValues() { string sql = string.Join( - ";", + ';', new string[] { "delete from itemvalues where type = 6", @@ -4946,37 +4874,38 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } } - private static Dictionary GetTypeMapDictionary() + private static Dictionary GetTypeMapDictionary() { - var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); + var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (var t in _knownTypes) { - dict[t.Name] = new[] { t.FullName }; + dict[t.Name] = t.FullName ; } - dict["Program"] = new[] { typeof(LiveTvProgram).FullName }; - dict["TvChannel"] = new[] { typeof(LiveTvChannel).FullName }; + dict["Program"] = typeof(LiveTvProgram).FullName; + dict["TvChannel"] = typeof(LiveTvChannel).FullName; return dict; } // Not crazy about having this all the way down here, but at least it's in one place - private readonly Dictionary _types = GetTypeMapDictionary(); + private readonly Dictionary _types = GetTypeMapDictionary(); - private string[] MapIncludeItemTypes(string value) + private string MapIncludeItemTypes(string value) { - if (_types.TryGetValue(value, out string[] result)) + if (_types.TryGetValue(value, out string result)) { return result; } if (IsValidType(value)) { - return new[] { value }; + return value; } - return Array.Empty(); + Logger.LogWarning("Unknown item type: {ItemType}", value); + return null; } public void DeleteItem(Guid id) @@ -5279,31 +5208,46 @@ AND Type = @InternalPersonType)"); public List GetStudioNames() { - return GetItemValueNames(new[] { 3 }, new List(), new List()); + return GetItemValueNames(new[] { 3 }, Array.Empty(), Array.Empty()); } public List GetAllArtistNames() { - return GetItemValueNames(new[] { 0, 1 }, new List(), new List()); + return GetItemValueNames(new[] { 0, 1 }, Array.Empty(), Array.Empty()); } public List GetMusicGenreNames() { - return GetItemValueNames(new[] { 2 }, new List { "Audio", "MusicVideo", "MusicAlbum", "MusicArtist" }, new List()); + return GetItemValueNames( + new[] { 2 }, + new string[] + { + typeof(Audio).FullName, + typeof(MusicVideo).FullName, + typeof(MusicAlbum).FullName, + typeof(MusicArtist).FullName + }, + Array.Empty()); } public List GetGenreNames() { - return GetItemValueNames(new[] { 2 }, new List(), new List { "Audio", "MusicVideo", "MusicAlbum", "MusicArtist" }); + return GetItemValueNames( + new[] { 2 }, + Array.Empty(), + new string[] + { + typeof(Audio).FullName, + typeof(MusicVideo).FullName, + typeof(MusicAlbum).FullName, + typeof(MusicArtist).FullName + }); } - private List GetItemValueNames(int[] itemValueTypes, List withItemTypes, List excludeItemTypes) + private List GetItemValueNames(int[] itemValueTypes, IReadOnlyList withItemTypes, IReadOnlyList excludeItemTypes) { CheckDisposed(); - withItemTypes = withItemTypes.SelectMany(MapIncludeItemTypes).ToList(); - excludeItemTypes = excludeItemTypes.SelectMany(MapIncludeItemTypes).ToList(); - var now = DateTime.UtcNow; var typeClause = itemValueTypes.Length == 1 ? @@ -5809,7 +5753,10 @@ AND Type = @InternalPersonType)"); var endIndex = Math.Min(people.Count, startIndex + Limit); for (var i = startIndex; i < endIndex; i++) { - insertText.AppendFormat("(@ItemId, @Name{0}, @Role{0}, @PersonType{0}, @SortOrder{0}, @ListOrder{0}),", i.ToString(CultureInfo.InvariantCulture)); + insertText.AppendFormat( + CultureInfo.InvariantCulture, + "(@ItemId, @Name{0}, @Role{0}, @PersonType{0}, @SortOrder{0}, @ListOrder{0}),", + i.ToString(CultureInfo.InvariantCulture)); } // Remove last comma @@ -6261,7 +6208,7 @@ AND Type = @InternalPersonType)"); CheckDisposed(); if (id == Guid.Empty) { - throw new ArgumentException(nameof(id)); + throw new ArgumentException("Guid can't be empty.", nameof(id)); } if (attachments == null) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 6a9f4174d..9c5172fb4 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1163,7 +1163,7 @@ namespace Emby.Server.Implementations.Library progress.Report(percent * 100); } - _itemRepository.UpdateInheritedValues(cancellationToken); + _itemRepository.UpdateInheritedValues(); progress.Report(100); } diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 45c6805f0..ed473c749 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -153,8 +153,7 @@ namespace MediaBrowser.Controller.Persistence /// /// Updates the inherited values. /// - /// The cancellation token. - void UpdateInheritedValues(CancellationToken cancellationToken); + void UpdateInheritedValues(); int GetCount(InternalItemsQuery query); -- cgit v1.2.3 From e4691d45f5ffccded535a683a6c2f76a2c8536cb Mon Sep 17 00:00:00 2001 From: Ian Walton Date: Sat, 24 Apr 2021 10:54:42 -0400 Subject: Leave SyncPlay group on session disconnect. --- Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs b/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs index aee959c53..315277985 100644 --- a/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs +++ b/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs @@ -87,7 +87,7 @@ namespace Emby.Server.Implementations.SyncPlay _sessionManager = sessionManager; _libraryManager = libraryManager; _logger = loggerFactory.CreateLogger(); - _sessionManager.SessionControllerConnected += OnSessionControllerConnected; + _sessionManager.SessionEnded += OnSessionEnded; } /// @@ -352,18 +352,18 @@ namespace Emby.Server.Implementations.SyncPlay return; } - _sessionManager.SessionControllerConnected -= OnSessionControllerConnected; + _sessionManager.SessionEnded -= OnSessionEnded; _disposed = true; } - private void OnSessionControllerConnected(object sender, SessionEventArgs e) + private void OnSessionEnded(object sender, SessionEventArgs e) { var session = e.SessionInfo; if (_sessionToGroupMap.TryGetValue(session.Id, out var group)) { - var request = new JoinGroupRequest(group.GroupId); - JoinGroup(session, request, CancellationToken.None); + var leaveGroupRequest = new LeaveGroupRequest(); + LeaveGroup(session, leaveGroupRequest, CancellationToken.None); } } -- cgit v1.2.3 From 77261a844541efdff96088c047908109d6063133 Mon Sep 17 00:00:00 2001 From: cvium Date: Sat, 24 Apr 2021 20:22:23 +0200 Subject: add UpdatePeopleAsync and add people to both tables --- .../Library/LibraryManager.cs | 60 ++++++++++++++++++++++ MediaBrowser.Controller/Library/ILibraryManager.cs | 9 ++++ MediaBrowser.Providers/Manager/MetadataService.cs | 59 ++------------------- 3 files changed, 72 insertions(+), 56 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 6a9f4174d..7d030418a 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2880,6 +2880,12 @@ namespace Emby.Server.Implementations.Library } public void UpdatePeople(BaseItem item, List people) + { + UpdatePeopleAsync(item, people, CancellationToken.None).GetAwaiter().GetResult(); + } + + /// + public async Task UpdatePeopleAsync(BaseItem item, List people, CancellationToken cancellationToken) { if (!item.SupportsPeople) { @@ -2887,6 +2893,8 @@ namespace Emby.Server.Implementations.Library } _itemRepository.UpdatePeople(item.Id, people); + + await SavePeopleMetadataAsync(people, cancellationToken).ConfigureAwait(false); } public async Task ConvertImageToLocal(BaseItem item, ItemImageInfo image, int imageIndex) @@ -2990,6 +2998,58 @@ namespace Emby.Server.Implementations.Library } } + private async Task SavePeopleMetadataAsync(IEnumerable people, CancellationToken cancellationToken) + { + var personsToSave = new List(); + + foreach (var person in people) + { + cancellationToken.ThrowIfCancellationRequested(); + + var itemUpdateType = ItemUpdateType.MetadataDownload; + var saveEntity = false; + var personEntity = GetPerson(person.Name); + + // if PresentationUniqueKey is empty it's likely a new item. + if (string.IsNullOrEmpty(personEntity.PresentationUniqueKey)) + { + personEntity.PresentationUniqueKey = personEntity.CreatePresentationUniqueKey(); + saveEntity = true; + } + + foreach (var id in person.ProviderIds) + { + if (!string.Equals(personEntity.GetProviderId(id.Key), id.Value, StringComparison.OrdinalIgnoreCase)) + { + personEntity.SetProviderId(id.Key, id.Value); + saveEntity = true; + } + } + + if (!string.IsNullOrWhiteSpace(person.ImageUrl) && !personEntity.HasImage(ImageType.Primary)) + { + personEntity.SetImage( + new ItemImageInfo + { + Path = person.ImageUrl, + Type = ImageType.Primary + }, + 0); + + saveEntity = true; + itemUpdateType = ItemUpdateType.ImageUpdate; + } + + if (saveEntity) + { + personsToSave.Add(personEntity); + await RunMetadataSavers(personEntity, itemUpdateType).ConfigureAwait(false); + } + } + + CreateItems(personsToSave, null, CancellationToken.None); + } + private void StartScanInBackground() { Task.Run(() => diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 80fcf71f3..6d9b568da 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -466,6 +466,15 @@ namespace MediaBrowser.Controller.Library /// The people. void UpdatePeople(BaseItem item, List people); + /// + /// Asynchronously updates the people. + /// + /// The item. + /// The people. + /// The cancellation token. + /// The async task. + Task UpdatePeopleAsync(BaseItem item, List people, CancellationToken cancellationToken); + /// /// Gets the item ids. /// diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index f12586665..6b778a090 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -201,7 +201,7 @@ namespace MediaBrowser.Providers.Manager } // Save to database - await SaveItemAsync(metadataResult, libraryOptions, updateType, cancellationToken).ConfigureAwait(false); + await SaveItemAsync(metadataResult, updateType, cancellationToken).ConfigureAwait(false); } await AfterMetadataRefresh(itemOfType, refreshOptions, cancellationToken).ConfigureAwait(false); @@ -216,71 +216,18 @@ namespace MediaBrowser.Providers.Manager lookupInfo.Year = result.ProductionYear; } - protected async Task SaveItemAsync(MetadataResult result, LibraryOptions libraryOptions, ItemUpdateType reason, CancellationToken cancellationToken) + protected async Task SaveItemAsync(MetadataResult result, ItemUpdateType reason, CancellationToken cancellationToken) { if (result.Item.SupportsPeople && result.People != null) { var baseItem = result.Item; - LibraryManager.UpdatePeople(baseItem, result.People); - await SavePeopleMetadataAsync(result.People, cancellationToken).ConfigureAwait(false); + await LibraryManager.UpdatePeopleAsync(baseItem, result.People, cancellationToken).ConfigureAwait(false); } await result.Item.UpdateToRepositoryAsync(reason, cancellationToken).ConfigureAwait(false); } - private async Task SavePeopleMetadataAsync(IEnumerable people, CancellationToken cancellationToken) - { - var personsToSave = new List(); - - foreach (var person in people) - { - cancellationToken.ThrowIfCancellationRequested(); - - var itemUpdateType = ItemUpdateType.MetadataDownload; - var saveEntity = false; - var personEntity = LibraryManager.GetPerson(person.Name); - - // if PresentationUniqueKey is empty it's likely a new item. - if (string.IsNullOrEmpty(personEntity.PresentationUniqueKey)) - { - personEntity.PresentationUniqueKey = personEntity.CreatePresentationUniqueKey(); - saveEntity = true; - } - - foreach (var id in person.ProviderIds) - { - if (!string.Equals(personEntity.GetProviderId(id.Key), id.Value, StringComparison.OrdinalIgnoreCase)) - { - personEntity.SetProviderId(id.Key, id.Value); - saveEntity = true; - } - } - - if (!string.IsNullOrWhiteSpace(person.ImageUrl) && !personEntity.HasImage(ImageType.Primary)) - { - personEntity.SetImage( - new ItemImageInfo - { - Path = person.ImageUrl, - Type = ImageType.Primary - }, - 0); - - saveEntity = true; - itemUpdateType = ItemUpdateType.ImageUpdate; - } - - if (saveEntity) - { - personsToSave.Add(personEntity); - await LibraryManager.RunMetadataSavers(personEntity, itemUpdateType).ConfigureAwait(false); - } - } - - LibraryManager.CreateItems(personsToSave, null, CancellationToken.None); - } - protected virtual Task AfterMetadataRefresh(TItemType item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) { item.AfterMetadataRefresh(); -- cgit v1.2.3 From 24a05bc9f83236a2e52b5c754c2a775ac1e6c1c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Apr 2021 12:00:57 +0000 Subject: Bump sharpcompress from 0.28.1 to 0.28.2 Bumps [sharpcompress](https://github.com/adamhathcock/sharpcompress) from 0.28.1 to 0.28.2. - [Release notes](https://github.com/adamhathcock/sharpcompress/releases) - [Commits](https://github.com/adamhathcock/sharpcompress/compare/0.28.1...0.28.2) Signed-off-by: dependabot[bot] --- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 9248053f5..4ee23127e 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -30,7 +30,7 @@ - + -- cgit v1.2.3 From 47c54166e14a89a6895f6ceda3ab48591c097fad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Apr 2021 14:43:14 +0000 Subject: Bump prometheus-net.DotNetRuntime from 3.4.1 to 4.0.0 Bumps [prometheus-net.DotNetRuntime](https://github.com/djluck/prometheus-net.DotNetRuntime) from 3.4.1 to 4.0.0. - [Release notes](https://github.com/djluck/prometheus-net.DotNetRuntime/releases) - [Commits](https://github.com/djluck/prometheus-net.DotNetRuntime/compare/3.4.1...4.0.0) Signed-off-by: dependabot[bot] --- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 4ee23127e..adbfe52c4 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -29,7 +29,7 @@ - + -- cgit v1.2.3 From 34313ef2165b4889454eaac92b563fe1998854c0 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 29 Apr 2021 16:23:29 +0200 Subject: SqliteItemRepository: Parse ChannelId directly from utf-8 data --- Emby.Server.Implementations/Data/SqliteItemRepository.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 694805ebe..8d220c807 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System; +using System.Buffers.Text; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -1311,7 +1312,14 @@ namespace Emby.Server.Implementations.Data if (!reader.IsDBNull(index)) { - item.ChannelId = new Guid(reader.GetString(index)); + if (!Utf8Parser.TryParse(reader[index].ToBlob(), out Guid value, out _, standardFormat: 'N')) + { + var str = reader.GetString(index); + Logger.LogWarning("{ChannelId} isn't in the expected format", str); + value = new Guid(str); + } + + item.ChannelId = value; } index++; -- cgit v1.2.3 From 608cba817c54df60959079719bafca4d7d54269a Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 30 Apr 2021 15:09:36 +0200 Subject: Reduce some allocations with the magic of spans etc. --- .../Data/SqliteItemRepository.cs | 153 ++++++++++++++------- .../Library/MediaSourceManager.cs | 13 +- .../LiveTv/EmbyTV/EmbyTV.cs | 14 +- .../Localization/LocalizationManager.cs | 3 +- .../QuickConnect/QuickConnectManager.cs | 15 +- .../SyncPlay/SyncPlayManager.cs | 13 +- .../Extensions/SplitLinesStringExtensions.cs | 102 ++++++++++++++ MediaBrowser.Controller/Entities/Folder.cs | 17 +-- .../Entities/ProviderIdsExtensions.cs | 30 ++++ 9 files changed, 266 insertions(+), 94 deletions(-) create mode 100644 MediaBrowser.Common/Extensions/SplitLinesStringExtensions.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 28e59913c..bd5a3e30b 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1007,15 +1007,12 @@ namespace Emby.Server.Implementations.Data return; } - var parts = value.Split('|', StringSplitOptions.RemoveEmptyEntries); - - foreach (var part in parts) + foreach (var part in value.SpanSplit('|')) { - var idParts = part.Split('='); - - if (idParts.Length == 2) + var providerDelimiterIndex = part.IndexOf('='); + if (providerDelimiterIndex != -1 && providerDelimiterIndex == part.LastIndexOf('=')) { - item.SetProviderId(idParts[0], idParts[1]); + item.SetProviderId(part.Slice(0, providerDelimiterIndex), part.Slice(providerDelimiterIndex + 1)); } } } @@ -1057,9 +1054,8 @@ namespace Emby.Server.Implementations.Data return; } - var parts = value.Split('|' , StringSplitOptions.RemoveEmptyEntries); var list = new List(); - foreach (var part in parts) + foreach (var part in value.SpanSplit('|')) { var image = ItemImageInfoFromValueString(part); @@ -1094,41 +1090,89 @@ namespace Emby.Server.Implementations.Data .Append(hash.Replace('*', '/').Replace('|', '\\')); } - public ItemImageInfo ItemImageInfoFromValueString(string value) + private ItemImageInfo ItemImageInfoFromValueString(ReadOnlySpan value) { - var parts = value.Split('*', StringSplitOptions.None); + var nextSegment = value.IndexOf('*'); + if (nextSegment == -1) + { + return null; + } - if (parts.Length < 3) + ReadOnlySpan path = value[..nextSegment]; + value = value[(nextSegment + 1)..]; + nextSegment = value.IndexOf('*'); + if (nextSegment == -1) { return null; } - var image = new ItemImageInfo(); + ReadOnlySpan dateModified = value[..nextSegment]; + value = value[(nextSegment + 1)..]; + nextSegment = value.IndexOf('*'); + if (nextSegment == -1) + { + return null; + } + + ReadOnlySpan imageType = value[..nextSegment]; - image.Path = RestorePath(parts[0]); + var image = new ItemImageInfo + { + Path = RestorePath(path.ToString()) + }; - if (long.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out var ticks)) + if (long.TryParse(dateModified, NumberStyles.Any, CultureInfo.InvariantCulture, out var ticks)) { image.DateModified = new DateTime(ticks, DateTimeKind.Utc); } - if (Enum.TryParse(parts[2], true, out ImageType type)) + if (Enum.TryParse(imageType.ToString(), true, out ImageType type)) { image.Type = type; } - if (parts.Length >= 5) + // Optional parameters: width*height*blurhash + if (nextSegment + 1 < value.Length - 1) { - if (int.TryParse(parts[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out var width) - && int.TryParse(parts[4], NumberStyles.Integer, CultureInfo.InvariantCulture, out var height)) + value = value[(nextSegment + 1)..]; + nextSegment = value.IndexOf('*'); + ReadOnlySpan widthSpan = value[..nextSegment]; + + value = value[(nextSegment + 1)..]; + nextSegment = value.IndexOf('*'); + if (nextSegment == -1) + { + return image; + } + + ReadOnlySpan heightSpan = value[..nextSegment]; + + if (int.TryParse(widthSpan, NumberStyles.Integer, CultureInfo.InvariantCulture, out var width) + && int.TryParse(heightSpan, NumberStyles.Integer, CultureInfo.InvariantCulture, out var height)) { image.Width = width; image.Height = height; } - if (parts.Length >= 6) + nextSegment += 1; + if (nextSegment < value.Length - 1) { - image.BlurHash = parts[5].Replace('/', '*').Replace('\\', '|'); + value = value[nextSegment..]; + var length = value.Length; + + Span blurHashSpan = stackalloc char[length]; + for (int i = 0; i < length; i++) + { + var c = value[i]; + blurHashSpan[i] = c switch + { + '/' => '*', + '\\' => '|', + _ => c + }; + } + + image.BlurHash = new string(blurHashSpan); } } @@ -2118,27 +2162,6 @@ namespace Emby.Server.Implementations.Data private readonly ItemFields[] _allFields = Enum.GetValues(); - private string[] GetColumnNamesFromField(ItemFields field) - { - switch (field) - { - case ItemFields.Settings: - return new[] { "IsLocked", "PreferredMetadataCountryCode", "PreferredMetadataLanguage", "LockedFields" }; - case ItemFields.ServiceName: - return new[] { "ExternalServiceId" }; - case ItemFields.SortName: - return new[] { "ForcedSortName" }; - case ItemFields.Taglines: - return new[] { "Tagline" }; - case ItemFields.Tags: - return new[] { "Tags" }; - case ItemFields.IsHD: - return Array.Empty(); - default: - return new[] { field.ToString() }; - } - } - private bool HasField(InternalItemsQuery query, ItemFields name) { switch (name) @@ -2327,9 +2350,32 @@ namespace Emby.Server.Implementations.Data { if (!HasField(query, field)) { - foreach (var fieldToRemove in GetColumnNamesFromField(field)) + switch (field) { - list.Remove(fieldToRemove); + case ItemFields.Settings: + list.Remove("IsLocked"); + list.Remove("PreferredMetadataCountryCode"); + list.Remove("PreferredMetadataLanguage"); + list.Remove("LockedFields"); + break; + case ItemFields.ServiceName: + list.Remove("ExternalServiceId"); + break; + case ItemFields.SortName: + list.Remove("ForcedSortName"); + break; + case ItemFields.Taglines: + list.Remove("Tagline"); + break; + case ItemFields.Tags: + list.Remove("Tags"); + break; + case ItemFields.IsHD: + // do nothing + break; + default: + list.Remove(field.ToString()); + break; } } } @@ -2575,10 +2621,21 @@ namespace Emby.Server.Implementations.Data query.Limit = query.Limit.Value + 4; } - var commandText = "select " - + string.Join(',', GetFinalColumnsToSelect(query, new[] { "count(distinct PresentationUniqueKey)" })) - + GetFromText() - + GetJoinUserDataText(query); + var commandText = "select "; + if (EnableGroupByPresentationUniqueKey(query)) + { + commandText += "count (distinct PresentationUniqueKey)"; + } + else if (query.GroupBySeriesPresentationUniqueKey) + { + commandText += "count (distinct SeriesPresentationUniqueKey)"; + } + else + { + commandText += "count (guid)"; + } + + commandText += GetFromText() + GetJoinUserDataText(query); var whereClauses = GetWhereClauses(query, null); if (whereClauses.Count != 0) diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index d0b85f07d..85d6d3043 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -590,18 +590,9 @@ namespace Emby.Server.Implementations.Library public Task GetDirectStreamProviderByUniqueId(string uniqueId, CancellationToken cancellationToken) { - var info = _openStreams.Values.FirstOrDefault(i => - { - var liveStream = i as ILiveStream; - if (liveStream != null) - { - return string.Equals(liveStream.UniqueId, uniqueId, StringComparison.OrdinalIgnoreCase); - } - - return false; - }); + var info = _openStreams.FirstOrDefault(i => i.Value != null && string.Equals(i.Value.UniqueId, uniqueId, StringComparison.OrdinalIgnoreCase)); - return Task.FromResult(info as IDirectStreamProvider); + return Task.FromResult(info.Value as IDirectStreamProvider); } public async Task OpenLiveStream(LiveStreamRequest request, CancellationToken cancellationToken) diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index c9d9cc49a..665fbfa0f 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -801,22 +801,22 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public ActiveRecordingInfo GetActiveRecordingInfo(string path) { - if (string.IsNullOrWhiteSpace(path)) + if (string.IsNullOrWhiteSpace(path) || _activeRecordings.IsEmpty) { return null; } - foreach (var recording in _activeRecordings.Values) + foreach (var (_, recordingInfo) in _activeRecordings) { - if (string.Equals(recording.Path, path, StringComparison.Ordinal) && !recording.CancellationTokenSource.IsCancellationRequested) + if (string.Equals(recordingInfo.Path, path, StringComparison.Ordinal) && !recordingInfo.CancellationTokenSource.IsCancellationRequested) { - var timer = recording.Timer; + var timer = recordingInfo.Timer; if (timer.Status != RecordingStatus.InProgress) { return null; } - return recording; + return recordingInfo; } } @@ -1621,9 +1621,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } return _activeRecordings - .Values - .ToList() - .Any(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) && !string.Equals(i.Timer.Id, timerId, StringComparison.OrdinalIgnoreCase)); + .Any(i => string.Equals(i.Value.Path, path, StringComparison.OrdinalIgnoreCase) && !string.Equals(i.Value.Timer.Id, timerId, StringComparison.OrdinalIgnoreCase)); } private IRecorder GetRecorder(MediaSourceInfo mediaSource) diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 2fdc2b4d9..46858b4fb 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -315,10 +315,9 @@ namespace Emby.Server.Implementations.Localization } const string Prefix = "Core"; - var key = Prefix + culture; return _dictionaries.GetOrAdd( - key, + culture, f => GetDictionary(Prefix, culture, DefaultCulture + ".json").GetAwaiter().GetResult()); } diff --git a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs index 22739a008..0259dc436 100644 --- a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs +++ b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs @@ -257,20 +257,17 @@ namespace Emby.Server.Implementations.QuickConnect } // Expire stale connection requests - var code = string.Empty; - var values = _currentRequests.Values.ToList(); - - for (int i = 0; i < values.Count; i++) + foreach (var (_, currentRequest) in _currentRequests) { - var added = values[i].DateAdded ?? DateTime.UnixEpoch; - if (DateTime.UtcNow > added.AddMinutes(Timeout) || expireAll) + var added = currentRequest.DateAdded ?? DateTime.UnixEpoch; + if (expireAll || DateTime.UtcNow > added.AddMinutes(Timeout)) { - code = values[i].Code; - _logger.LogDebug("Removing expired request {code}", code); + var code = currentRequest.Code; + _logger.LogDebug("Removing expired request {Code}", code); if (!_currentRequests.TryRemove(code, out _)) { - _logger.LogWarning("Request {code} already expired", code); + _logger.LogWarning("Request {Code} already expired", code); } } } diff --git a/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs b/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs index 315277985..72c0a838e 100644 --- a/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs +++ b/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs @@ -269,14 +269,17 @@ namespace Emby.Server.Implementations.SyncPlay var user = _userManager.GetUserById(session.UserId); List list = new List(); - foreach (var group in _groups.Values) + lock (_groupsLock) { - // Locking required as group is not thread-safe. - lock (group) + foreach (var (_, group) in _groups) { - if (group.HasAccessToPlayQueue(user)) + // Locking required as group is not thread-safe. + lock (group) { - list.Add(group.GetInfo()); + if (group.HasAccessToPlayQueue(user)) + { + list.Add(group.GetInfo()); + } } } } diff --git a/MediaBrowser.Common/Extensions/SplitLinesStringExtensions.cs b/MediaBrowser.Common/Extensions/SplitLinesStringExtensions.cs new file mode 100644 index 000000000..5332aba9f --- /dev/null +++ b/MediaBrowser.Common/Extensions/SplitLinesStringExtensions.cs @@ -0,0 +1,102 @@ +/* +MIT License + +Copyright (c) 2019 Gérald Barré + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ +#nullable enable +#pragma warning disable CS1591 +#pragma warning disable CA1034 +using System; +using System.Diagnostics.Contracts; +using System.Runtime.InteropServices; + +namespace MediaBrowser.Common.Extensions +{ + /// + /// Extension class for splitting lines without unnecessary allocations. + /// + public static class SplitLinesStringExtensions + { + /// + /// Creates a new line split enumerator. + /// + /// The string to split. + /// The separator to split on. + /// The enumerator struct. + [Pure] + public static LineSplitEnumerator SpanSplit(this string str, char separator) => new (str.AsSpan(), separator); + + /// + /// Creates a new line split enumerator. + /// + /// The span to split. + /// The separator to split on. + /// The enumerator struct. + [Pure] + public static LineSplitEnumerator Split(this ReadOnlySpan str, char separator) => new (str, separator); + + [StructLayout(LayoutKind.Auto)] + public ref struct LineSplitEnumerator + { + private readonly char _separator; + private ReadOnlySpan _str; + + public LineSplitEnumerator(ReadOnlySpan str, char separator) + { + _str = str; + _separator = separator; + Current = default; + } + + public ReadOnlySpan Current { get; private set; } + + public readonly LineSplitEnumerator GetEnumerator() => this; + + public bool MoveNext() + { + if (_str.Length == 0) + { + return false; + } + + var span = _str; + var index = span.IndexOf(_separator); + if (index == -1) + { + _str = ReadOnlySpan.Empty; + Current = span; + return true; + } + + if (index < span.Length - 1 && span[index] == _separator) + { + Current = span.Slice(0, index); + _str = span[(index + 1)..]; + return true; + } + + Current = span.Slice(0, index); + _str = span[(index + 1)..]; + return true; + } + } + } +} diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index d45f8758c..d74e6f9d8 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1768,20 +1768,15 @@ namespace MediaBrowser.Controller.Entities { EnableImages = false } - }); - - double unplayedCount = unplayedQueryResult.TotalRecordCount; + }).TotalRecordCount; - dto.UnplayedItemCount = unplayedQueryResult.TotalRecordCount; + dto.UnplayedItemCount = unplayedQueryResult; - if (itemDto != null && itemDto.RecursiveItemCount.HasValue) + if (itemDto?.RecursiveItemCount > 0) { - if (itemDto.RecursiveItemCount.Value > 0) - { - var unplayedPercentage = (unplayedCount / itemDto.RecursiveItemCount.Value) * 100; - dto.PlayedPercentage = 100 - unplayedPercentage; - dto.Played = dto.PlayedPercentage.Value >= 100; - } + var unplayedPercentage = ((double)unplayedQueryResult / itemDto.RecursiveItemCount.Value) * 100; + dto.PlayedPercentage = 100 - unplayedPercentage; + dto.Played = dto.PlayedPercentage.Value >= 100; } else { diff --git a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs index 09d14dc6a..bc14da7f2 100644 --- a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs +++ b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs @@ -132,6 +132,36 @@ namespace MediaBrowser.Model.Entities } } + /// + /// Sets a provider id. + /// + /// The instance. + /// The name. + /// The value. + public static void SetProviderId(this IHasProviderIds instance, ReadOnlySpan name, ReadOnlySpan value) + { + if (instance == null) + { + throw new ArgumentNullException(nameof(instance)); + } + + // If it's null remove the key from the dictionary + if (value.IsEmpty) + { + instance.ProviderIds?.Remove(name.ToString()); + } + else + { + // Ensure it exists + if (instance.ProviderIds == null) + { + instance.ProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); + } + + instance.ProviderIds[name.ToString()] = value.ToString(); + } + } + /// /// Sets a provider id. /// -- cgit v1.2.3 From a6726730fc181599db0ba68545adce9b88c11f7b Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 30 Apr 2021 15:11:16 +0200 Subject: revert the last bits of the getcount experiment --- .../Data/SqliteItemRepository.cs | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index bd5a3e30b..7cee309d0 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -2621,21 +2621,10 @@ namespace Emby.Server.Implementations.Data query.Limit = query.Limit.Value + 4; } - var commandText = "select "; - if (EnableGroupByPresentationUniqueKey(query)) - { - commandText += "count (distinct PresentationUniqueKey)"; - } - else if (query.GroupBySeriesPresentationUniqueKey) - { - commandText += "count (distinct SeriesPresentationUniqueKey)"; - } - else - { - commandText += "count (guid)"; - } - - commandText += GetFromText() + GetJoinUserDataText(query); + var commandText = "select " + + string.Join(',', GetFinalColumnsToSelect(query, new[] { "count(distinct PresentationUniqueKey)" })) + + GetFromText() + + GetJoinUserDataText(query); var whereClauses = GetWhereClauses(query, null); if (whereClauses.Count != 0) -- cgit v1.2.3 From ba2e346d1246cc51e186a64d38a9b7385492ca4f Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 30 Apr 2021 15:27:07 +0200 Subject: prevent cancellationtoken leakage --- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 4 +++- Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs | 3 ++- Jellyfin.Api/Helpers/ProgressiveFileCopier.cs | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 1dcc78687..c32ca2fb6 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -661,7 +661,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun _modelCache.Clear(); } - cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(new CancellationTokenSource(discoveryDurationMs).Token, cancellationToken).Token; + using var timedCancellationToken = new CancellationTokenSource(discoveryDurationMs); + using var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(timedCancellationToken.Token, cancellationToken); + cancellationToken = linkedCancellationTokenSource.Token; var list = new List(); // Create udp broadcast discovery message diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 78e62ff0a..f8baf55da 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -150,7 +150,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts public async Task CopyToAsync(Stream stream, CancellationToken cancellationToken) { - cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, LiveStreamCancellationTokenSource.Token).Token; + using var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, LiveStreamCancellationTokenSource.Token); + cancellationToken = linkedCancellationTokenSource.Token; // use non-async filestream on windows along with read due to https://github.com/dotnet/corefx/issues/6039 var allowAsync = Environment.OSVersion.Platform != PlatformID.Win32NT; diff --git a/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs b/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs index 8bddf00d5..963e17724 100644 --- a/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs +++ b/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs @@ -71,7 +71,8 @@ namespace Jellyfin.Api.Helpers /// A . public async Task WriteToAsync(Stream outputStream, CancellationToken cancellationToken) { - cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _cancellationToken).Token; + using var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _cancellationToken); + cancellationToken = linkedCancellationTokenSource.Token; try { -- cgit v1.2.3 From 716cbb06958da987ab917c1f6408396d4ace7a0c Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 30 Apr 2021 23:35:29 +0200 Subject: remove span based setproviderid --- .../Data/SqliteItemRepository.cs | 2 +- .../Entities/ProviderIdsExtensions.cs | 30 ---------------------- 2 files changed, 1 insertion(+), 31 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 7cee309d0..e78ebbc50 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1012,7 +1012,7 @@ namespace Emby.Server.Implementations.Data var providerDelimiterIndex = part.IndexOf('='); if (providerDelimiterIndex != -1 && providerDelimiterIndex == part.LastIndexOf('=')) { - item.SetProviderId(part.Slice(0, providerDelimiterIndex), part.Slice(providerDelimiterIndex + 1)); + item.SetProviderId(part.Slice(0, providerDelimiterIndex).ToString(), part.Slice(providerDelimiterIndex + 1).ToString()); } } } diff --git a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs index bc14da7f2..09d14dc6a 100644 --- a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs +++ b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs @@ -132,36 +132,6 @@ namespace MediaBrowser.Model.Entities } } - /// - /// Sets a provider id. - /// - /// The instance. - /// The name. - /// The value. - public static void SetProviderId(this IHasProviderIds instance, ReadOnlySpan name, ReadOnlySpan value) - { - if (instance == null) - { - throw new ArgumentNullException(nameof(instance)); - } - - // If it's null remove the key from the dictionary - if (value.IsEmpty) - { - instance.ProviderIds?.Remove(name.ToString()); - } - else - { - // Ensure it exists - if (instance.ProviderIds == null) - { - instance.ProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); - } - - instance.ProviderIds[name.ToString()] = value.ToString(); - } - } - /// /// Sets a provider id. /// -- cgit v1.2.3 From c608d5104df7b7281e35595552734d77e42b5036 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 1 May 2021 15:56:16 +0200 Subject: Fix scanning --- Emby.Server.Implementations/IO/ManagedFileSystem.cs | 2 -- Emby.Server.Implementations/Library/LibraryManager.cs | 2 +- Emby.Server.Implementations/Library/ResolverHelper.cs | 3 +-- MediaBrowser.Controller/Library/ItemResolveArgs.cs | 2 +- MediaBrowser.Model/IO/FileSystemMetadata.cs | 6 ------ 5 files changed, 3 insertions(+), 12 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index df973f971..27096ed33 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -260,8 +260,6 @@ namespace Emby.Server.Implementations.IO result.Exists = false; } } - - result.DirectoryName = fileInfo.DirectoryName; } result.CreationTimeUtc = GetCreationTimeUtc(info); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index ec59ca9b9..7629676f5 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -683,7 +683,7 @@ namespace Emby.Server.Implementations.Library foreach (var item in items) { - ResolverHelper.SetInitialItemValues(item, parent, _fileSystem, this, directoryService); + ResolverHelper.SetInitialItemValues(item, parent, this, directoryService); } items.AddRange(ResolveFileList(result.ExtraFiles, directoryService, parent, collectionType, resolvers, libraryOptions)); diff --git a/Emby.Server.Implementations/Library/ResolverHelper.cs b/Emby.Server.Implementations/Library/ResolverHelper.cs index 8be80d726..b1a2e9284 100644 --- a/Emby.Server.Implementations/Library/ResolverHelper.cs +++ b/Emby.Server.Implementations/Library/ResolverHelper.cs @@ -20,11 +20,10 @@ namespace Emby.Server.Implementations.Library /// /// The item. /// The parent. - /// The file system. /// The library manager. /// The directory service. /// Item must have a path. - public static void SetInitialItemValues(BaseItem item, Folder? parent, IFileSystem fileSystem, ILibraryManager libraryManager, IDirectoryService directoryService) + public static void SetInitialItemValues(BaseItem item, Folder? parent, ILibraryManager libraryManager, IDirectoryService directoryService) { // This version of the below method has no ItemResolveArgs, so we have to require the path already being set if (string.IsNullOrEmpty(item.Path)) diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index df8842237..f86f7df25 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -87,7 +87,7 @@ namespace MediaBrowser.Controller.Library return false; } - var parentDir = FileInfo.DirectoryName ?? string.Empty; + var parentDir = System.IO.Path.GetDirectoryName(Path) ?? string.Empty; return parentDir.Length > _appPaths.RootFolderPath.Length && parentDir.StartsWith(_appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase); diff --git a/MediaBrowser.Model/IO/FileSystemMetadata.cs b/MediaBrowser.Model/IO/FileSystemMetadata.cs index 118c78e80..fb74886bf 100644 --- a/MediaBrowser.Model/IO/FileSystemMetadata.cs +++ b/MediaBrowser.Model/IO/FileSystemMetadata.cs @@ -37,12 +37,6 @@ namespace MediaBrowser.Model.IO /// The length. public long Length { get; set; } - /// - /// Gets or sets the name of the directory. - /// - /// The name of the directory. - public string DirectoryName { get; set; } - /// /// Gets or sets the last write time UTC. /// -- cgit v1.2.3 From 8a6b9e1fb6d89ac77bd8d62da66bd05abd75ca65 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 2 May 2021 00:26:30 +0200 Subject: Add tests for SqliteItemRepository.(De)SerializeImages --- .../Data/SqliteItemRepository.cs | 41 +++-- .../Data/SqliteItemRepositoryTests.cs | 172 +++++++++++++++++++++ 2 files changed, 191 insertions(+), 22 deletions(-) create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 28e59913c..9b558d34b 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -502,7 +502,7 @@ namespace Emby.Server.Implementations.Data using (var saveImagesStatement = base.PrepareStatement(db, "Update TypedBaseItems set Images=@Images where guid=@Id")) { saveImagesStatement.TryBind("@Id", item.Id.ToByteArray()); - saveImagesStatement.TryBind("@Images", SerializeImages(item)); + saveImagesStatement.TryBind("@Images", SerializeImages(item.ImageInfos)); saveImagesStatement.MoveNext(); } @@ -898,7 +898,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@Tagline", item.Tagline); saveItemStatement.TryBind("@ProviderIds", SerializeProviderIds(item)); - saveItemStatement.TryBind("@Images", SerializeImages(item)); + saveItemStatement.TryBind("@Images", SerializeImages(item.ImageInfos)); if (item.ProductionLocations.Length > 0) { @@ -1020,10 +1020,8 @@ namespace Emby.Server.Implementations.Data } } - private string SerializeImages(BaseItem item) + internal string SerializeImages(ItemImageInfo[] images) { - var images = item.ImageInfos; - if (images.Length == 0) { return null; @@ -1045,16 +1043,11 @@ namespace Emby.Server.Implementations.Data return str.ToString(); } - private void DeserializeImages(string value, BaseItem item) + internal ItemImageInfo[] DeserializeImages(string value) { if (string.IsNullOrWhiteSpace(value)) { - return; - } - - if (item.ImageInfos.Length > 0) - { - return; + return Array.Empty(); } var parts = value.Split('|' , StringSplitOptions.RemoveEmptyEntries); @@ -1069,15 +1062,14 @@ namespace Emby.Server.Implementations.Data } } - item.ImageInfos = list.ToArray(); + return list.ToArray(); } - public void AppendItemImageInfo(StringBuilder bldr, ItemImageInfo image) + private void AppendItemImageInfo(StringBuilder bldr, ItemImageInfo image) { const char Delimiter = '*'; var path = image.Path ?? string.Empty; - var hash = image.BlurHash ?? string.Empty; bldr.Append(GetPathToSave(path)) .Append(Delimiter) @@ -1087,11 +1079,16 @@ namespace Emby.Server.Implementations.Data .Append(Delimiter) .Append(image.Width) .Append(Delimiter) - .Append(image.Height) - .Append(Delimiter) - // Replace delimiters with other characters. - // This can be removed when we migrate to a proper DB. - .Append(hash.Replace('*', '/').Replace('|', '\\')); + .Append(image.Height); + + var hash = image.BlurHash; + if (!string.IsNullOrEmpty(hash)) + { + bldr.Append(Delimiter) + // Replace delimiters with other characters. + // This can be removed when we migrate to a proper DB. + .Append(hash.Replace('*', '/').Replace('|', '\\')); + } } public ItemImageInfo ItemImageInfoFromValueString(string value) @@ -1797,11 +1794,11 @@ namespace Emby.Server.Implementations.Data index++; - if (query.DtoOptions.EnableImages) + if (query.DtoOptions.EnableImages && item.ImageInfos.Length == 0) { if (!reader.IsDBNull(index)) { - DeserializeImages(reader.GetString(index), item); + item.ImageInfos = DeserializeImages(reader.GetString(index)); } index++; diff --git a/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs new file mode 100644 index 000000000..e9cfd5b12 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using AutoFixture; +using AutoFixture.AutoMoq; +using Emby.Server.Implementations.Data; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Entities; +using Moq; +using Xunit; + +namespace Jellyfin.Server.Implementations.Tests.Data +{ + public class SqliteItemRepositoryTests + { + public const string VirtualMetaDataPath = "%MetadataPath%"; + public const string MetaDataPath = "/meta/data/path"; + + private readonly IFixture _fixture; + private readonly SqliteItemRepository _sqliteItemRepository; + + public SqliteItemRepositoryTests() + { + var appHost = new Mock(); + appHost.Setup(x => x.ExpandVirtualPath(It.IsAny())) + .Returns((string x) => x.Replace(VirtualMetaDataPath, MetaDataPath, StringComparison.Ordinal)); + appHost.Setup(x => x.ReverseVirtualPath(It.IsAny())) + .Returns((string x) => x.Replace(MetaDataPath, VirtualMetaDataPath, StringComparison.Ordinal)); + + _fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true }); + _fixture.Inject(appHost); + _sqliteItemRepository = _fixture.Create(); + } + + public static IEnumerable ItemImageInfoFromValueString_Valid_TestData() + { + yield return new object[] + { + "/mnt/series/Family Guy/Season 1/Family Guy - S01E01-thumb.jpg*637452096478512963*Primary*1920*1080*WjQbtJtSO8nhNZ%L_Io#R/oaS6o}-;adXAoIn7j[%hW9s:WGw[nN", + new ItemImageInfo() + { + Path = "/mnt/series/Family Guy/Season 1/Family Guy - S01E01-thumb.jpg", + Type = ImageType.Primary, + DateModified = new DateTime(637452096478512963, DateTimeKind.Utc), + Width = 1920, + Height = 1080, + BlurHash = "WjQbtJtSO8nhNZ%L_Io#R*oaS6o}-;adXAoIn7j[%hW9s:WGw[nN" + } + }; + + yield return new object[] + { + "https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg*0*Primary*0*0", + new ItemImageInfo() + { + Path = "https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg", + Type = ImageType.Primary, + } + }; + + yield return new object[] + { + "%MetadataPath%/library/68/68578562b96c80a7ebd530848801f645/poster.jpg*637264380567586027*Primary*600*336", + new ItemImageInfo() + { + Path = "/meta/data/path/library/68/68578562b96c80a7ebd530848801f645/poster.jpg", + Type = ImageType.Primary, + DateModified = new DateTime(637264380567586027, DateTimeKind.Utc), + Width = 600, + Height = 336 + } + }; + } + + [Theory] + [MemberData(nameof(ItemImageInfoFromValueString_Valid_TestData))] + public void ItemImageInfoFromValueString_Valid_Success(string value, ItemImageInfo expected) + { + var result = _sqliteItemRepository.ItemImageInfoFromValueString(value); + Assert.Equal(expected.Path, result.Path); + Assert.Equal(expected.Type, result.Type); + Assert.Equal(expected.DateModified, result.DateModified); + Assert.Equal(expected.Width, result.Width); + Assert.Equal(expected.Height, result.Height); + Assert.Equal(expected.BlurHash, result.BlurHash); + } + + [Theory] + [InlineData("")] + [InlineData("*")] + public void ItemImageInfoFromValueString_Invalid_Null(string value) + { + Assert.Null(_sqliteItemRepository.ItemImageInfoFromValueString(value)); + } + + public static IEnumerable DeserializeImages_Valid_TestData() + { + yield return new object[] + { + "/mnt/series/Family Guy/Season 1/Family Guy - S01E01-thumb.jpg*637452096478512963*Primary*1920*1080*WjQbtJtSO8nhNZ%L_Io#R/oaS6o}-;adXAoIn7j[%hW9s:WGw[nN", + new ItemImageInfo[] + { + new ItemImageInfo() + { + Path = "/mnt/series/Family Guy/Season 1/Family Guy - S01E01-thumb.jpg", + Type = ImageType.Primary, + DateModified = new DateTime(637452096478512963, DateTimeKind.Utc), + Width = 1920, + Height = 1080, + BlurHash = "WjQbtJtSO8nhNZ%L_Io#R*oaS6o}-;adXAoIn7j[%hW9s:WGw[nN" + } + } + }; + + yield return new object[] + { + "%MetadataPath%/library/2a/2a27372f1e9bc757b1db99721bbeae1e/poster.jpg*637261226720645297*Primary*0*0|%MetadataPath%/library/2a/2a27372f1e9bc757b1db99721bbeae1e/logo.png*637261226720805297*Logo*0*0|%MetadataPath%/library/2a/2a27372f1e9bc757b1db99721bbeae1e/landscape.jpg*637261226721285297*Thumb*0*0|%MetadataPath%/library/2a/2a27372f1e9bc757b1db99721bbeae1e/backdrop.jpg*637261226721685297*Backdrop*0*0", + new ItemImageInfo[] + { + new ItemImageInfo() + { + Path = "/meta/data/path/library/2a/2a27372f1e9bc757b1db99721bbeae1e/poster.jpg", + Type = ImageType.Primary, + DateModified = new DateTime(637261226720645297, DateTimeKind.Utc), + }, + new ItemImageInfo() + { + Path = "/meta/data/path/library/2a/2a27372f1e9bc757b1db99721bbeae1e/logo.png", + Type = ImageType.Logo, + DateModified = new DateTime(637261226720805297, DateTimeKind.Utc), + }, + new ItemImageInfo() + { + Path = "/meta/data/path/library/2a/2a27372f1e9bc757b1db99721bbeae1e/landscape.jpg", + Type = ImageType.Thumb, + DateModified = new DateTime(637261226721285297, DateTimeKind.Utc), + }, + new ItemImageInfo() + { + Path = "/meta/data/path/library/2a/2a27372f1e9bc757b1db99721bbeae1e/backdrop.jpg", + Type = ImageType.Backdrop, + DateModified = new DateTime(637261226721685297, DateTimeKind.Utc), + } + } + }; + } + + [Theory] + [MemberData(nameof(DeserializeImages_Valid_TestData))] + public void DeserializeImages_Valid_Success(string value, ItemImageInfo[] expected) + { + var result = _sqliteItemRepository.DeserializeImages(value); + Assert.Equal(expected.Length, result.Length); + for (int i = 0; i < expected.Length; i++) + { + Assert.Equal(expected[i].Path, result[i].Path); + Assert.Equal(expected[i].Type, result[i].Type); + Assert.Equal(expected[i].DateModified, result[i].DateModified); + Assert.Equal(expected[i].Width, result[i].Width); + Assert.Equal(expected[i].Height, result[i].Height); + Assert.Equal(expected[i].BlurHash, result[i].BlurHash); + } + } + + [Theory] + [MemberData(nameof(DeserializeImages_Valid_TestData))] + public void SerializeImages_Valid_Success(string expected, ItemImageInfo[] value) + { + Assert.Equal(expected, _sqliteItemRepository.SerializeImages(value)); + } + } +} -- cgit v1.2.3 From 874f92e93a1411fbba7097f0665db68234441dfa Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 2 May 2021 12:45:02 +0200 Subject: Add tests for SqliteItemRepository.(De)SerializeProviderIds --- .../Data/SqliteItemRepository.cs | 19 +++----- .../Data/SqliteItemRepositoryTests.cs | 57 ++++++++++++++++++++++ 2 files changed, 64 insertions(+), 12 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 9b558d34b..786e3b6fa 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -897,7 +897,7 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@ExternalSeriesId", item.ExternalSeriesId); saveItemStatement.TryBind("@Tagline", item.Tagline); - saveItemStatement.TryBind("@ProviderIds", SerializeProviderIds(item)); + saveItemStatement.TryBind("@ProviderIds", SerializeProviderIds(item.ProviderIds)); saveItemStatement.TryBind("@Images", SerializeImages(item.ImageInfos)); if (item.ProductionLocations.Length > 0) @@ -968,10 +968,10 @@ namespace Emby.Server.Implementations.Data saveItemStatement.MoveNext(); } - private static string SerializeProviderIds(BaseItem item) + internal static string SerializeProviderIds(Dictionary providerIds) { StringBuilder str = new StringBuilder(); - foreach (var i in item.ProviderIds) + foreach (var i in providerIds) { // Ideally we shouldn't need this IsNullOrWhiteSpace check, // but we're seeing some cases of bad data slip through @@ -995,18 +995,13 @@ namespace Emby.Server.Implementations.Data return str.ToString(); } - private static void DeserializeProviderIds(string value, BaseItem item) + internal static void DeserializeProviderIds(string value, IHasProviderIds item) { if (string.IsNullOrWhiteSpace(value)) { return; } - if (item.ProviderIds.Count > 0) - { - return; - } - var parts = value.Split('|', StringSplitOptions.RemoveEmptyEntries); foreach (var part in parts) @@ -1787,16 +1782,16 @@ namespace Emby.Server.Implementations.Data index++; } - if (!reader.IsDBNull(index)) + if (item.ProviderIds.Count == 0 && !reader.IsDBNull(index)) { DeserializeProviderIds(reader.GetString(index), item); } index++; - if (query.DtoOptions.EnableImages && item.ImageInfos.Length == 0) + if (query.DtoOptions.EnableImages) { - if (!reader.IsDBNull(index)) + if (item.ImageInfos.Length == 0 && !reader.IsDBNull(index)) { item.ImageInfos = DeserializeImages(reader.GetString(index)); } diff --git a/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs index e9cfd5b12..af6ec3245 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs @@ -168,5 +168,62 @@ namespace Jellyfin.Server.Implementations.Tests.Data { Assert.Equal(expected, _sqliteItemRepository.SerializeImages(value)); } + + public static IEnumerable DeserializeProviderIds_Valid_TestData() + { + yield return new object[] + { + "Imdb=tt0119567", + new Dictionary() + { + { "Imdb", "tt0119567" }, + } + }; + + yield return new object[] + { + "Imdb=tt0119567|Tmdb=330|TmdbCollection=328", + new Dictionary() + { + { "Imdb", "tt0119567" }, + { "Tmdb", "330" }, + { "TmdbCollection", "328" }, + } + }; + + yield return new object[] + { + "MusicBrainzAlbum=9d363e43-f24f-4b39-bc5a-7ef305c677c7|MusicBrainzReleaseGroup=63eba062-847c-3b73-8b0f-6baf27bba6fa|AudioDbArtist=111352|AudioDbAlbum=2116560|MusicBrainzAlbumArtist=20244d07-534f-4eff-b4d4-930878889970", + new Dictionary() + { + { "MusicBrainzAlbum", "9d363e43-f24f-4b39-bc5a-7ef305c677c7" }, + { "MusicBrainzReleaseGroup", "63eba062-847c-3b73-8b0f-6baf27bba6fa" }, + { "AudioDbArtist", "111352" }, + { "AudioDbAlbum", "2116560" }, + { "MusicBrainzAlbumArtist", "20244d07-534f-4eff-b4d4-930878889970" }, + } + }; + } + + [Theory] + [MemberData(nameof(DeserializeProviderIds_Valid_TestData))] + public void DeserializeProviderIds_Valid_Success(string value, Dictionary expected) + { + var result = new ProviderIdsExtensionsTestsObject(); + SqliteItemRepository.DeserializeProviderIds(value, result); + Assert.Equal(expected, result.ProviderIds); + } + + [Theory] + [MemberData(nameof(DeserializeProviderIds_Valid_TestData))] + public void SerializeProviderIds_Valid_Success(string expected, Dictionary values) + { + Assert.Equal(expected, SqliteItemRepository.SerializeProviderIds(values)); + } + + private class ProviderIdsExtensionsTestsObject : IHasProviderIds + { + public Dictionary ProviderIds { get; set; } = new Dictionary(); + } } } -- cgit v1.2.3 From bcba501dfbe1e0f422829f26159d9a9625530231 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sun, 2 May 2021 19:25:04 +0100 Subject: minor optimization. --- Emby.Server.Implementations/Plugins/PluginManager.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index 3a8296455..fd2ee6b7a 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -166,9 +166,7 @@ namespace Emby.Server.Implementations.Plugins /// public void CreatePlugins() { - _ = _appHost.GetExports(CreatePluginInstance) - .Where(i => i != null) - .ToArray(); + _ = _appHost.GetExports(CreatePluginInstance); } /// -- cgit v1.2.3 From 9b1243cf5ef21bffdd31054e35121d811688ba3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 May 2021 12:00:50 +0000 Subject: Bump SQLitePCL.pretty.netstandard from 2.1.0 to 2.2.0 Bumps [SQLitePCL.pretty.netstandard](https://github.com/jellyfin/SQLitePCL.pretty.netstandard) from 2.1.0 to 2.2.0. - [Release notes](https://github.com/jellyfin/SQLitePCL.pretty.netstandard/releases) - [Commits](https://github.com/jellyfin/SQLitePCL.pretty.netstandard/commits) Signed-off-by: dependabot[bot] --- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index adbfe52c4..b8a544b8c 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -31,7 +31,7 @@ - + -- cgit v1.2.3 From c0feb3694b86ccc242a637468070daff9120e631 Mon Sep 17 00:00:00 2001 From: cvium Date: Mon, 3 May 2021 23:51:45 +0200 Subject: rename to SplitEnumerator and fix test --- .../Data/SqliteItemRepository.cs | 14 ++- .../Extensions/SplitLinesStringExtensions.cs | 102 --------------------- .../Extensions/SplitStringExtensions.cs | 102 +++++++++++++++++++++ .../Data/SqliteItemRepositoryTests.cs | 31 ++++++- 4 files changed, 137 insertions(+), 112 deletions(-) delete mode 100644 MediaBrowser.Common/Extensions/SplitLinesStringExtensions.cs create mode 100644 MediaBrowser.Common/Extensions/SplitStringExtensions.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 292ff48fa..4b9b0bed0 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1082,7 +1082,7 @@ namespace Emby.Server.Implementations.Data } } - private ItemImageInfo ItemImageInfoFromValueString(ReadOnlySpan value) + internal ItemImageInfo ItemImageInfoFromValueString(ReadOnlySpan value) { var nextSegment = value.IndexOf('*'); if (nextSegment == -1) @@ -1103,7 +1103,7 @@ namespace Emby.Server.Implementations.Data nextSegment = value.IndexOf('*'); if (nextSegment == -1) { - return null; + nextSegment = value.Length; } ReadOnlySpan imageType = value[..nextSegment]; @@ -1128,13 +1128,18 @@ namespace Emby.Server.Implementations.Data { value = value[(nextSegment + 1)..]; nextSegment = value.IndexOf('*'); + if (nextSegment == -1 || nextSegment == value.Length) + { + return image; + } + ReadOnlySpan widthSpan = value[..nextSegment]; value = value[(nextSegment + 1)..]; nextSegment = value.IndexOf('*'); if (nextSegment == -1) { - return image; + nextSegment = value.Length; } ReadOnlySpan heightSpan = value[..nextSegment]; @@ -1146,10 +1151,9 @@ namespace Emby.Server.Implementations.Data image.Height = height; } - nextSegment += 1; if (nextSegment < value.Length - 1) { - value = value[nextSegment..]; + value = value[(nextSegment + 1)..]; var length = value.Length; Span blurHashSpan = stackalloc char[length]; diff --git a/MediaBrowser.Common/Extensions/SplitLinesStringExtensions.cs b/MediaBrowser.Common/Extensions/SplitLinesStringExtensions.cs deleted file mode 100644 index 5332aba9f..000000000 --- a/MediaBrowser.Common/Extensions/SplitLinesStringExtensions.cs +++ /dev/null @@ -1,102 +0,0 @@ -/* -MIT License - -Copyright (c) 2019 Gérald Barré - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - */ -#nullable enable -#pragma warning disable CS1591 -#pragma warning disable CA1034 -using System; -using System.Diagnostics.Contracts; -using System.Runtime.InteropServices; - -namespace MediaBrowser.Common.Extensions -{ - /// - /// Extension class for splitting lines without unnecessary allocations. - /// - public static class SplitLinesStringExtensions - { - /// - /// Creates a new line split enumerator. - /// - /// The string to split. - /// The separator to split on. - /// The enumerator struct. - [Pure] - public static LineSplitEnumerator SpanSplit(this string str, char separator) => new (str.AsSpan(), separator); - - /// - /// Creates a new line split enumerator. - /// - /// The span to split. - /// The separator to split on. - /// The enumerator struct. - [Pure] - public static LineSplitEnumerator Split(this ReadOnlySpan str, char separator) => new (str, separator); - - [StructLayout(LayoutKind.Auto)] - public ref struct LineSplitEnumerator - { - private readonly char _separator; - private ReadOnlySpan _str; - - public LineSplitEnumerator(ReadOnlySpan str, char separator) - { - _str = str; - _separator = separator; - Current = default; - } - - public ReadOnlySpan Current { get; private set; } - - public readonly LineSplitEnumerator GetEnumerator() => this; - - public bool MoveNext() - { - if (_str.Length == 0) - { - return false; - } - - var span = _str; - var index = span.IndexOf(_separator); - if (index == -1) - { - _str = ReadOnlySpan.Empty; - Current = span; - return true; - } - - if (index < span.Length - 1 && span[index] == _separator) - { - Current = span.Slice(0, index); - _str = span[(index + 1)..]; - return true; - } - - Current = span.Slice(0, index); - _str = span[(index + 1)..]; - return true; - } - } - } -} diff --git a/MediaBrowser.Common/Extensions/SplitStringExtensions.cs b/MediaBrowser.Common/Extensions/SplitStringExtensions.cs new file mode 100644 index 000000000..6c1c45013 --- /dev/null +++ b/MediaBrowser.Common/Extensions/SplitStringExtensions.cs @@ -0,0 +1,102 @@ +/* +MIT License + +Copyright (c) 2019 Gérald Barré + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ +#nullable enable +#pragma warning disable CS1591 +#pragma warning disable CA1034 +using System; +using System.Diagnostics.Contracts; +using System.Runtime.InteropServices; + +namespace MediaBrowser.Common.Extensions +{ + /// + /// Extension class for splitting lines without unnecessary allocations. + /// + public static class SplitStringExtensions + { + /// + /// Creates a new string split enumerator. + /// + /// The string to split. + /// The separator to split on. + /// The enumerator struct. + [Pure] + public static SplitEnumerator SpanSplit(this string str, char separator) => new (str.AsSpan(), separator); + + /// + /// Creates a new span split enumerator. + /// + /// The span to split. + /// The separator to split on. + /// The enumerator struct. + [Pure] + public static SplitEnumerator Split(this ReadOnlySpan str, char separator) => new (str, separator); + + [StructLayout(LayoutKind.Auto)] + public ref struct SplitEnumerator + { + private readonly char _separator; + private ReadOnlySpan _str; + + public SplitEnumerator(ReadOnlySpan str, char separator) + { + _str = str; + _separator = separator; + Current = default; + } + + public ReadOnlySpan Current { get; private set; } + + public readonly SplitEnumerator GetEnumerator() => this; + + public bool MoveNext() + { + if (_str.Length == 0) + { + return false; + } + + var span = _str; + var index = span.IndexOf(_separator); + if (index == -1) + { + _str = ReadOnlySpan.Empty; + Current = span; + return true; + } + + if (index < span.Length - 1 && span[index] == _separator) + { + Current = span.Slice(0, index); + _str = span[(index + 1)..]; + return true; + } + + Current = span.Slice(0, index); + _str = span[(index + 1)..]; + return true; + } + } + } +} diff --git a/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs index af6ec3245..c0f34afa7 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs @@ -37,7 +37,7 @@ namespace Jellyfin.Server.Implementations.Tests.Data yield return new object[] { "/mnt/series/Family Guy/Season 1/Family Guy - S01E01-thumb.jpg*637452096478512963*Primary*1920*1080*WjQbtJtSO8nhNZ%L_Io#R/oaS6o}-;adXAoIn7j[%hW9s:WGw[nN", - new ItemImageInfo() + new ItemImageInfo { Path = "/mnt/series/Family Guy/Season 1/Family Guy - S01E01-thumb.jpg", Type = ImageType.Primary, @@ -51,7 +51,27 @@ namespace Jellyfin.Server.Implementations.Tests.Data yield return new object[] { "https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg*0*Primary*0*0", - new ItemImageInfo() + new ItemImageInfo + { + Path = "https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg", + Type = ImageType.Primary, + } + }; + + yield return new object[] + { + "https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg*0*Primary", + new ItemImageInfo + { + Path = "https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg", + Type = ImageType.Primary, + } + }; + + yield return new object[] + { + "https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg*0*Primary*600", + new ItemImageInfo { Path = "https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg", Type = ImageType.Primary, @@ -61,7 +81,7 @@ namespace Jellyfin.Server.Implementations.Tests.Data yield return new object[] { "%MetadataPath%/library/68/68578562b96c80a7ebd530848801f645/poster.jpg*637264380567586027*Primary*600*336", - new ItemImageInfo() + new ItemImageInfo { Path = "/meta/data/path/library/68/68578562b96c80a7ebd530848801f645/poster.jpg", Type = ImageType.Primary, @@ -76,7 +96,7 @@ namespace Jellyfin.Server.Implementations.Tests.Data [MemberData(nameof(ItemImageInfoFromValueString_Valid_TestData))] public void ItemImageInfoFromValueString_Valid_Success(string value, ItemImageInfo expected) { - var result = _sqliteItemRepository.ItemImageInfoFromValueString(value); + var result = _sqliteItemRepository.ItemImageInfoFromValueString(value.AsSpan()); Assert.Equal(expected.Path, result.Path); Assert.Equal(expected.Type, result.Type); Assert.Equal(expected.DateModified, result.DateModified); @@ -88,9 +108,10 @@ namespace Jellyfin.Server.Implementations.Tests.Data [Theory] [InlineData("")] [InlineData("*")] + [InlineData("https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg*0")] public void ItemImageInfoFromValueString_Invalid_Null(string value) { - Assert.Null(_sqliteItemRepository.ItemImageInfoFromValueString(value)); + Assert.Null(_sqliteItemRepository.ItemImageInfoFromValueString(value.AsSpan())); } public static IEnumerable DeserializeImages_Valid_TestData() -- cgit v1.2.3 From f2c10471bf00263adc6411b38db60ba931d0ec15 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Wed, 5 May 2021 12:37:36 +0100 Subject: Code Clean up: Use Pattern Matching (#5838) Co-authored-by: Cody Robibero Co-authored-by: Patrick Barron <18354464+barronpm@users.noreply.github.com> --- .../Images/PlaylistImageProvider.cs | 4 +--- Emby.Server.Implementations/Library/MusicManager.cs | 3 +-- .../ScheduledTasks/ScheduledTaskWorker.cs | 4 +--- Emby.Server.Implementations/TV/TVSeriesManager.cs | 8 ++------ MediaBrowser.Controller/Entities/CollectionFolder.cs | 4 +--- MediaBrowser.Controller/Entities/Movies/BoxSet.cs | 3 +-- MediaBrowser.Controller/Entities/Photo.cs | 3 +-- MediaBrowser.Controller/Entities/TV/Series.cs | 11 ++--------- MediaBrowser.Controller/Providers/ItemInfo.cs | 3 +-- MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs | 3 +-- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 6 ++---- MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs | 16 ++++------------ MediaBrowser.Providers/Manager/MetadataService.cs | 6 ++---- MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs | 4 +--- MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs | 4 +--- MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs | 4 +--- 16 files changed, 23 insertions(+), 63 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Images/PlaylistImageProvider.cs b/Emby.Server.Implementations/Images/PlaylistImageProvider.cs index 0ce1b91e8..a4c106e87 100644 --- a/Emby.Server.Implementations/Images/PlaylistImageProvider.cs +++ b/Emby.Server.Implementations/Images/PlaylistImageProvider.cs @@ -29,9 +29,7 @@ namespace Emby.Server.Implementations.Images { var subItem = i.Item2; - var episode = subItem as Episode; - - if (episode != null) + if (subItem is Episode episode) { var series = episode.Series; if (series != null && series.HasImage(ImageType.Primary)) diff --git a/Emby.Server.Implementations/Library/MusicManager.cs b/Emby.Server.Implementations/Library/MusicManager.cs index 658c53f28..f8bae4fd1 100644 --- a/Emby.Server.Implementations/Library/MusicManager.cs +++ b/Emby.Server.Implementations/Library/MusicManager.cs @@ -100,8 +100,7 @@ namespace Emby.Server.Implementations.Library public List GetInstantMixFromItem(BaseItem item, User user, DtoOptions dtoOptions) { - var genre = item as MusicGenre; - if (genre != null) + if (item is MusicGenre genre) { return GetInstantMixFromGenreIds(new[] { item.Id }, user, dtoOptions); } diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 9c0e92705..61dccaa19 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -348,9 +348,7 @@ namespace Emby.Server.Implementations.ScheduledTasks { var trigger = (ITaskTrigger)sender; - var configurableTask = ScheduledTask as IConfigurableScheduledTask; - - if (configurableTask != null && !configurableTask.IsEnabled) + if (ScheduledTask is IConfigurableScheduledTask configurableTask && !configurableTask.IsEnabled) { return; } diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index d3f6fa34d..829df64bf 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -43,9 +43,7 @@ namespace Emby.Server.Implementations.TV string presentationUniqueKey = null; if (!string.IsNullOrEmpty(request.SeriesId)) { - var series = _libraryManager.GetItemById(request.SeriesId) as Series; - - if (series != null) + if (_libraryManager.GetItemById(request.SeriesId) is Series series) { presentationUniqueKey = GetUniqueSeriesKey(series); } @@ -95,9 +93,7 @@ namespace Emby.Server.Implementations.TV int? limit = null; if (!string.IsNullOrEmpty(request.SeriesId)) { - var series = _libraryManager.GetItemById(request.SeriesId) as Series; - - if (series != null) + if (_libraryManager.GetItemById(request.SeriesId) is Series series) { presentationUniqueKey = GetUniqueSeriesKey(series); limit = 1; diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 16a2c77e9..347d5b73c 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -354,9 +354,7 @@ namespace MediaBrowser.Controller.Entities if (result.Count == 0) { - var folder = LibraryManager.FindByPath(path, true) as Folder; - - if (folder != null) + if (LibraryManager.FindByPath(path, true) is Folder folder) { result.Add(folder); } diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index 05e4229ca..507f400f1 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -217,8 +217,7 @@ namespace MediaBrowser.Controller.Entities.Movies private IEnumerable FlattenItems(BaseItem item, List expandedFolders) { - var boxset = item as BoxSet; - if (boxset != null) + if (item is BoxSet boxset) { if (!expandedFolders.Contains(item.Id)) { diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs index 2fc66176f..0f82f742f 100644 --- a/MediaBrowser.Controller/Entities/Photo.cs +++ b/MediaBrowser.Controller/Entities/Photo.cs @@ -24,8 +24,7 @@ namespace MediaBrowser.Controller.Entities var parents = GetParents(); foreach (var parent in parents) { - var photoAlbum = parent as PhotoAlbum; - if (photoAlbum != null) + if (parent is PhotoAlbum photoAlbum) { return photoAlbum; } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 9f9a2ad50..06a405121 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -316,20 +316,13 @@ namespace MediaBrowser.Controller.Entities.TV cancellationToken.ThrowIfCancellationRequested(); - var skipItem = false; - - var episode = item as Episode; - - if (episode != null + bool skipItem = item is Episode episode && refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh && !refreshOptions.ReplaceAllMetadata && episode.IsMissingEpisode && episode.LocationType == LocationType.Virtual && episode.PremiereDate.HasValue - && (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30) - { - skipItem = true; - } + && (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30; if (!skipItem) { diff --git a/MediaBrowser.Controller/Providers/ItemInfo.cs b/MediaBrowser.Controller/Providers/ItemInfo.cs index b50def043..3a97127ea 100644 --- a/MediaBrowser.Controller/Providers/ItemInfo.cs +++ b/MediaBrowser.Controller/Providers/ItemInfo.cs @@ -14,8 +14,7 @@ namespace MediaBrowser.Controller.Providers ContainingFolderPath = item.ContainingFolderPath; IsInMixedFolder = item.IsInMixedFolder; - var video = item as Video; - if (video != null) + if (item is Video video) { VideoType = video.VideoType; IsPlaceHolder = video.IsPlaceHolder; diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 5f620634f..32e5ac761 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -468,8 +468,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { var val = reader.ReadElementContentAsString(); - var hasDisplayOrder = item as IHasDisplayOrder; - if (hasDisplayOrder != null) + if (item is IHasDisplayOrder hasDisplayOrder) { if (!string.IsNullOrWhiteSpace(val)) { diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index dfbce5f49..98ed3dcf7 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -296,8 +296,7 @@ namespace MediaBrowser.LocalMetadata.Savers writer.WriteEndElement(); } - var hasDisplayOrder = item as IHasDisplayOrder; - if (hasDisplayOrder != null && !string.IsNullOrEmpty(hasDisplayOrder.DisplayOrder)) + if (item is IHasDisplayOrder hasDisplayOrder && !string.IsNullOrEmpty(hasDisplayOrder.DisplayOrder)) { writer.WriteElementString("DisplayOrder", hasDisplayOrder.DisplayOrder); } @@ -312,8 +311,7 @@ namespace MediaBrowser.LocalMetadata.Savers writer.WriteElementString("ProductionYear", item.ProductionYear.Value.ToString(_usCulture)); } - var hasAspectRatio = item as IHasAspectRatio; - if (hasAspectRatio != null) + if (item is IHasAspectRatio hasAspectRatio) { if (!string.IsNullOrEmpty(hasAspectRatio.AspectRatio)) { diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs index 9108d9649..6ebaa4fff 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs @@ -61,33 +61,25 @@ namespace MediaBrowser.MediaEncoding.BdInfo foreach (var stream in playlist.SortedStreams) { - var videoStream = stream as TSVideoStream; - - if (videoStream != null) + if (stream is TSVideoStream videoStream) { AddVideoStream(mediaStreams, videoStream); continue; } - var audioStream = stream as TSAudioStream; - - if (audioStream != null) + if (stream is TSAudioStream audioStream) { AddAudioStream(mediaStreams, audioStream); continue; } - var textStream = stream as TSTextStream; - - if (textStream != null) + if (stream is TSTextStream textStream) { AddSubtitleStream(mediaStreams, textStream); continue; } - var graphicsStream = stream as TSGraphicsStream; - - if (graphicsStream != null) + if (stream is TSGraphicsStream graphicsStream) { AddSubtitleStream(mediaStreams, graphicsStream); } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 6b778a090..401c7e99f 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -281,8 +281,7 @@ namespace MediaBrowser.Providers.Manager return true; } - var folder = item as Folder; - if (folder != null) + if (item is Folder folder) { return folder.SupportsDateLastMediaAdded || folder.SupportsCumulativeRunTimeTicks; } @@ -336,8 +335,7 @@ namespace MediaBrowser.Providers.Manager private ItemUpdateType UpdateCumulativeRunTimeTicks(TItemType item, IList children) { - var folder = item as Folder; - if (folder != null && folder.SupportsCumulativeRunTimeTicks) + if (item is Folder folder && folder.SupportsCumulativeRunTimeTicks) { long ticks = 0; diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index 64ad1bddf..03e45fb86 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -137,9 +137,7 @@ namespace MediaBrowser.Providers.MediaInfo return false; } - var audio = item as Audio; - - return audio != null; + return item is Audio; } } } diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs index 912aedb0d..44ab5aa5b 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs @@ -172,9 +172,7 @@ namespace MediaBrowser.Providers.MediaInfo SubtitleFetcherOrder = subtitleFetcherOrder }; - var episode = video as Episode; - - if (episode != null) + if (video is Episode episode) { request.IndexNumberEnd = episode.IndexNumberEnd; request.SeriesName = episode.SeriesName; diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index c36c3af6a..30af6710a 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -154,9 +154,7 @@ namespace MediaBrowser.Providers.MediaInfo return false; } - var video = item as Video; - - if (video != null && !video.IsPlaceHolder && video.IsCompleteMedia) + if (item is Video video && !video.IsPlaceHolder && video.IsCompleteMedia) { return true; } -- cgit v1.2.3 From 2e98de90628e9a4e42fb182f2d5a2a296acfd827 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Wed, 5 May 2021 12:51:14 +0100 Subject: Code Clean up: Convert to null-coalescing operator ?? (#5845) Co-authored-by: Cody Robibero Co-authored-by: Patrick Barron <18354464+barronpm@users.noreply.github.com> --- Emby.Server.Implementations/ApplicationHost.cs | 10 +---- Emby.Server.Implementations/Dto/DtoService.cs | 15 ++------ .../Library/LibraryManager.cs | 5 +-- .../Library/Resolvers/TV/EpisodeResolver.cs | 14 ++----- .../LiveTv/EmbyTV/EmbyTV.cs | 10 ++--- .../LiveTv/Listings/SchedulesDirect.cs | 7 +--- .../LiveTv/LiveTvManager.cs | 15 ++------ .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 5 +-- .../Plugins/PluginManager.cs | 13 +------ .../ScheduledTasks/ScheduledTaskWorker.cs | 7 +--- .../Session/SessionManager.cs | 5 +-- Jellyfin.Api/Controllers/PluginsController.cs | 7 +--- Jellyfin.Api/Controllers/SearchController.cs | 5 +-- Jellyfin.Api/Helpers/StreamingHelpers.cs | 5 +-- MediaBrowser.Common/Net/IPHost.cs | 5 +-- MediaBrowser.Common/Plugins/BasePluginOfT.cs | 5 +-- MediaBrowser.Controller/Entities/BaseItem.cs | 26 ++++--------- MediaBrowser.Controller/Entities/UserView.cs | 5 +-- MediaBrowser.Controller/Library/ItemResolveArgs.cs | 5 +-- MediaBrowser.Controller/Playlists/Playlist.cs | 5 +-- .../Providers/MetadataRefreshOptions.cs | 5 +-- .../Providers/MetadataResult.cs | 16 +++----- .../Probing/ProbeResultNormalizer.cs | 45 ++++++---------------- .../Entities/ProviderIdsExtensions.cs | 5 +-- .../MediaInfo/FFProbeVideoInfo.cs | 5 +-- .../Subtitles/SubtitleManager.cs | 5 +-- RSSDP/SsdpCommunicationsServer.cs | 5 +-- 27 files changed, 60 insertions(+), 200 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 703f8d20d..75d8fc113 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -335,10 +335,7 @@ namespace Emby.Server.Implementations { get { - if (_deviceId == null) - { - _deviceId = new DeviceId(ApplicationPaths, LoggerFactory); - } + _deviceId ??= new DeviceId(ApplicationPaths, LoggerFactory); return _deviceId.Value; } @@ -370,10 +367,7 @@ namespace Emby.Server.Implementations /// System.Object. protected object CreateInstanceSafe(Type type) { - if (_creatingInstances == null) - { - _creatingInstances = new List(); - } + _creatingInstances ??= new List(); if (_creatingInstances.IndexOf(type) != -1) { diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 54b18a8c8..4ae35039a 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -665,10 +665,7 @@ namespace Emby.Server.Implementations.Dto var tag = GetImageCacheTag(item, image); if (!string.IsNullOrEmpty(image.BlurHash)) { - if (dto.ImageBlurHashes == null) - { - dto.ImageBlurHashes = new Dictionary>(); - } + dto.ImageBlurHashes ??= new Dictionary>(); if (!dto.ImageBlurHashes.ContainsKey(image.Type)) { @@ -702,10 +699,7 @@ namespace Emby.Server.Implementations.Dto if (hashes.Count > 0) { - if (dto.ImageBlurHashes == null) - { - dto.ImageBlurHashes = new Dictionary>(); - } + dto.ImageBlurHashes ??= new Dictionary>(); dto.ImageBlurHashes[imageType] = hashes; } @@ -898,10 +892,7 @@ namespace Emby.Server.Implementations.Dto dto.Taglines = new string[] { item.Tagline }; } - if (dto.Taglines == null) - { - dto.Taglines = Array.Empty(); - } + dto.Taglines ??= Array.Empty(); } dto.Type = item.GetBaseItemKind(); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index a44edad16..4d207471a 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -176,10 +176,7 @@ namespace Emby.Server.Implementations.Library { lock (_rootFolderSyncLock) { - if (_rootFolder == null) - { - _rootFolder = CreateRootFolder(); - } + _rootFolder ??= CreateRootFolder(); } } diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs index 9b4cd7a3d..6f29bc649 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs @@ -35,14 +35,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return null; } - var season = parent as Season; - // Just in case the user decided to nest episodes. // Not officially supported but in some cases we can handle it. - if (season == null) - { - season = parent.GetParents().OfType().FirstOrDefault(); - } + + var season = parent as Season ?? parent.GetParents().OfType().FirstOrDefault(); // If the parent is a Season or Series and the parent is not an extras folder, then this is an Episode if the VideoResolver returns something // Also handle flat tv folders @@ -55,11 +51,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV if (episode != null) { - var series = parent as Series; - if (series == null) - { - series = parent.GetParents().OfType().FirstOrDefault(); - } + var series = parent as Series ?? parent.GetParents().OfType().FirstOrDefault(); if (series != null) { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 665fbfa0f..28a2095e1 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -2237,14 +2237,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var enabledTimersForSeries = new List(); foreach (var timer in allTimers) { - var existingTimer = _timerProvider.GetTimer(timer.Id); - - if (existingTimer == null) - { - existingTimer = string.IsNullOrWhiteSpace(timer.ProgramId) + var existingTimer = _timerProvider.GetTimer(timer.Id) + ?? (string.IsNullOrWhiteSpace(timer.ProgramId) ? null - : _timerProvider.GetTimerByProgramId(timer.ProgramId); - } + : _timerProvider.GetTimerByProgramId(timer.ProgramId)); if (existingTimer == null) { diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 1926e738f..9af65cabb 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -787,14 +787,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings { var channelNumber = GetChannelNumber(channel); - var station = allStations.Find(item => string.Equals(item.stationID, channel.stationID, StringComparison.OrdinalIgnoreCase)); - if (station == null) - { - station = new ScheduleDirect.Station + var station = allStations.Find(item => string.Equals(item.stationID, channel.stationID, StringComparison.OrdinalIgnoreCase)) + ?? new ScheduleDirect.Station { stationID = channel.stationID }; - } var channelInfo = new ChannelInfo { diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 63a3146aa..1145d8aa1 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -987,10 +987,7 @@ namespace Emby.Server.Implementations.LiveTv var externalProgramId = programTuple.Item2; string externalSeriesId = programTuple.Item3; - if (timerList == null) - { - timerList = (await GetTimersInternal(new TimerQuery(), cancellationToken).ConfigureAwait(false)).Items; - } + timerList ??= (await GetTimersInternal(new TimerQuery(), cancellationToken).ConfigureAwait(false)).Items; var timer = timerList.FirstOrDefault(i => string.Equals(i.ProgramId, externalProgramId, StringComparison.OrdinalIgnoreCase)); var foundSeriesTimer = false; @@ -1018,10 +1015,7 @@ namespace Emby.Server.Implementations.LiveTv continue; } - if (seriesTimerList == null) - { - seriesTimerList = (await GetSeriesTimersInternal(new SeriesTimerQuery(), cancellationToken).ConfigureAwait(false)).Items; - } + seriesTimerList ??= (await GetSeriesTimersInternal(new SeriesTimerQuery(), cancellationToken).ConfigureAwait(false)).Items; var seriesTimer = seriesTimerList.FirstOrDefault(i => string.Equals(i.SeriesId, externalSeriesId, StringComparison.OrdinalIgnoreCase)); @@ -1974,10 +1968,7 @@ namespace Emby.Server.Implementations.LiveTv }; } - if (service == null) - { - service = _services[0]; - } + service ??= _services[0]; var info = await service.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index c32ca2fb6..4aa5832b1 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -421,10 +421,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun string audioCodec = channelInfo.AudioCodec; - if (!videoBitrate.HasValue) - { - videoBitrate = isHd ? 15000000 : 2000000; - } + videoBitrate ??= isHd ? 15000000 : 2000000; int? audioBitrate = isHd ? 448000 : 192000; diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index fd2ee6b7a..14df20936 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -44,12 +44,7 @@ namespace Emby.Server.Implementations.Plugins { get { - if (_httpClientFactory == null) - { - _httpClientFactory = _appHost.Resolve(); - } - - return _httpClientFactory; + return _httpClientFactory ?? (_httpClientFactory = _appHost.Resolve()); } } @@ -276,11 +271,7 @@ namespace Emby.Server.Implementations.Plugins // If no version is given, return the current instance. var plugins = _plugins.Where(p => p.Id.Equals(id)).ToList(); - plugin = plugins.FirstOrDefault(p => p.Instance != null); - if (plugin == null) - { - plugin = plugins.OrderByDescending(p => p.Version).FirstOrDefault(); - } + plugin = plugins.FirstOrDefault(p => p.Instance != null) ?? plugins.OrderByDescending(p => p.Version).FirstOrDefault(); } else { diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 61dccaa19..101d9b537 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -301,12 +301,7 @@ namespace Emby.Server.Implementations.ScheduledTasks { get { - if (_id == null) - { - _id = ScheduledTask.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture); - } - - return _id; + return _id ??= ScheduledTask.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture); } } diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 6f21ec31e..6844152ea 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -1475,10 +1475,7 @@ namespace Emby.Server.Implementations.Session user = _userManager.GetUserById(request.UserId); } - if (user == null) - { - user = _userManager.GetUserByName(request.Username); - } + user ??= _userManager.GetUserByName(request.Username); if (enforcePassword) { diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index adec86a10..7a6130719 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -207,12 +207,7 @@ namespace Jellyfin.Api.Controllers var plugins = _pluginManager.Plugins.Where(p => p.Id.Equals(pluginId)); // Select the un-instanced one first. - var plugin = plugins.FirstOrDefault(p => p.Instance == null); - if (plugin == null) - { - // Then by the status. - plugin = plugins.OrderBy(p => p.Manifest.Status).FirstOrDefault(); - } + var plugin = plugins.FirstOrDefault(p => p.Instance == null) ?? plugins.OrderBy(p => p.Manifest.Status).FirstOrDefault(); if (plugin != null) { diff --git a/Jellyfin.Api/Controllers/SearchController.cs b/Jellyfin.Api/Controllers/SearchController.cs index 6c22050a7..73bdf9018 100644 --- a/Jellyfin.Api/Controllers/SearchController.cs +++ b/Jellyfin.Api/Controllers/SearchController.cs @@ -228,10 +228,7 @@ namespace Jellyfin.Api.Controllers itemWithImage = GetParentWithImage(item, ImageType.Thumb); } - if (itemWithImage == null) - { - itemWithImage = GetParentWithImage(item, ImageType.Thumb); - } + itemWithImage ??= GetParentWithImage(item, ImageType.Thumb); if (itemWithImage != null) { diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index 583e613b4..8cffe9c4c 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -292,10 +292,7 @@ namespace Jellyfin.Api.Helpers } } - if (profile == null) - { - profile = dlnaManager.GetDefaultProfile(); - } + profile ??= dlnaManager.GetDefaultProfile(); var audioCodec = state.ActualOutputAudioCodec; diff --git a/MediaBrowser.Common/Net/IPHost.cs b/MediaBrowser.Common/Net/IPHost.cs index fb3ef9b12..7156ce618 100644 --- a/MediaBrowser.Common/Net/IPHost.cs +++ b/MediaBrowser.Common/Net/IPHost.cs @@ -400,10 +400,7 @@ namespace MediaBrowser.Common.Net private bool ResolveHost() { // When was the last time we resolved? - if (_lastResolved == null) - { - _lastResolved = DateTime.UtcNow; - } + _lastResolved ??= DateTime.UtcNow; // If we haven't resolved before, or our timer has run out... if ((_addresses.Length == 0 && !Resolved) || (DateTime.UtcNow > _lastResolved.Value.AddMinutes(Timeout))) diff --git a/MediaBrowser.Common/Plugins/BasePluginOfT.cs b/MediaBrowser.Common/Plugins/BasePluginOfT.cs index 99c226f50..e074cc6a0 100644 --- a/MediaBrowser.Common/Plugins/BasePluginOfT.cs +++ b/MediaBrowser.Common/Plugins/BasePluginOfT.cs @@ -105,10 +105,7 @@ namespace MediaBrowser.Common.Plugins { lock (_configurationSyncLock) { - if (_configuration == null) - { - _configuration = LoadConfiguration(); - } + _configuration ??= LoadConfiguration(); } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 1b69c6646..32ae15498 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -106,15 +106,10 @@ namespace MediaBrowser.Controller.Entities { get { - if (_themeSongIds == null) - { - _themeSongIds = GetExtras() - .Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeSong) - .Select(song => song.Id) - .ToArray(); - } - - return _themeSongIds; + return _themeSongIds ??= GetExtras() + .Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeSong) + .Select(song => song.Id) + .ToArray(); } private set @@ -128,15 +123,10 @@ namespace MediaBrowser.Controller.Entities { get { - if (_themeVideoIds == null) - { - _themeVideoIds = GetExtras() - .Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeVideo) - .Select(song => song.Id) - .ToArray(); - } - - return _themeVideoIds; + return _themeVideoIds ??= GetExtras() + .Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeVideo) + .Select(song => song.Id) + .ToArray(); } private set diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index b1da4d64c..fec83dd94 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -75,10 +75,7 @@ namespace MediaBrowser.Controller.Entities public override List GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) { - if (query == null) - { - query = new InternalItemsQuery(user); - } + query ??= new InternalItemsQuery(user); query.EnableTotalRecordCount = false; var result = GetItemList(query); diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index f86f7df25..f9086066d 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -147,10 +147,7 @@ namespace MediaBrowser.Controller.Library throw new ArgumentException("The path was empty or null.", nameof(path)); } - if (AdditionalLocations == null) - { - AdditionalLocations = new List(); - } + AdditionalLocations ??= new List(); AdditionalLocations.Add(path); } diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index c9c168c4c..3c93cfc79 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -126,10 +126,7 @@ namespace MediaBrowser.Controller.Playlists private List GetPlayableItems(User user, InternalItemsQuery query) { - if (query == null) - { - query = new InternalItemsQuery(user); - } + query ??= new InternalItemsQuery(user); query.IsFolder = false; diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs index b92b83701..db0ef7072 100644 --- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs +++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs @@ -45,10 +45,7 @@ namespace MediaBrowser.Controller.Providers if (copy.RefreshPaths != null && copy.RefreshPaths.Length > 0) { - if (RefreshPaths == null) - { - RefreshPaths = Array.Empty(); - } + RefreshPaths ??= Array.Empty(); RefreshPaths = copy.RefreshPaths.ToArray(); } diff --git a/MediaBrowser.Controller/Providers/MetadataResult.cs b/MediaBrowser.Controller/Providers/MetadataResult.cs index 864cb3050..98c7eadfe 100644 --- a/MediaBrowser.Controller/Providers/MetadataResult.cs +++ b/MediaBrowser.Controller/Providers/MetadataResult.cs @@ -37,10 +37,7 @@ namespace MediaBrowser.Controller.Providers public void AddPerson(PersonInfo p) { - if (People == null) - { - People = new List(); - } + People ??= new List(); PeopleHelper.AddPerson(People, p); } @@ -54,16 +51,15 @@ namespace MediaBrowser.Controller.Providers { People = new List(); } - - People.Clear(); + else + { + People.Clear(); + } } public UserItemData GetOrAddUserData(string userId) { - if (UserDataList == null) - { - UserDataList = new List(); - } + UserDataList ??= new List(); UserItemData userData = null; diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index ee2e5fcde..2e96f8cb0 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1187,43 +1187,28 @@ namespace MediaBrowser.MediaEncoding.Probing FetchStudios(audio, tags, "label"); // These support mulitple values, but for now we only store the first. - var mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")); - if (mb == null) - { - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMARTISTID")); - } + var mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")) + ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMARTISTID")); audio.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")); - if (mb == null) - { - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ARTISTID")); - } + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")) + ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ARTISTID")); audio.SetProviderId(MetadataProvider.MusicBrainzArtist, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")); - if (mb == null) - { - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMID")); - } + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")) + ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMID")); audio.SetProviderId(MetadataProvider.MusicBrainzAlbum, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")); - if (mb == null) - { - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASEGROUPID")); - } + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")) + ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASEGROUPID")); audio.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")); - if (mb == null) - { - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASETRACKID")); - } + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")) + ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASETRACKID")); audio.SetProviderId(MetadataProvider.MusicBrainzTrack, mb); } @@ -1290,15 +1275,7 @@ namespace MediaBrowser.MediaEncoding.Probing private IEnumerable GetSplitWhitelist() { - if (_splitWhiteList == null) - { - _splitWhiteList = new List - { - "AC/DC" - }; - } - - return _splitWhiteList; + return _splitWhiteList ??= new List { "AC/DC" }; } /// diff --git a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs index 09d14dc6a..ce4b0ec92 100644 --- a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs +++ b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs @@ -123,10 +123,7 @@ namespace MediaBrowser.Model.Entities else { // Ensure it exists - if (instance.ProviderIds == null) - { - instance.ProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); - } + instance.ProviderIds ??= new Dictionary(StringComparer.OrdinalIgnoreCase); instance.ProviderIds[name] = value; } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 74849a522..f049cc81f 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -111,10 +111,7 @@ namespace MediaBrowser.Providers.MediaInfo } } - if (streamFileNames == null) - { - streamFileNames = Array.Empty(); - } + streamFileNames ??= Array.Empty(); mediaInfoResult = await GetMediaInfo(item, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 1f3d9acff..8d62343cb 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -256,10 +256,7 @@ namespace MediaBrowser.Providers.Subtitles } catch (Exception ex) { - if (exceptionToThrow == null) - { - exceptionToThrow = ex; - } + exceptionToThrow ??= ex; } finally { diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index 8f1f0fa61..f448ad38b 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -415,10 +415,7 @@ namespace Rssdp.Infrastructure { lock (_SendSocketSynchroniser) { - if (_sendSockets == null) - { - _sendSockets = CreateSocketAndListenForResponsesAsync(); - } + _sendSockets ??= CreateSocketAndListenForResponsesAsync(); } } } -- cgit v1.2.3 From bcb4010db615b7c732856629553cba4e7ccc3358 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 5 May 2021 15:30:32 +0200 Subject: More improvements --- .../Library/Resolvers/ItemResolver.cs | 12 ++++++------ .../Library/Resolvers/Movies/MovieResolver.cs | 2 +- .../Library/Resolvers/PhotoAlbumResolver.cs | 12 ++++++------ .../Library/Resolvers/PhotoResolver.cs | 2 +- .../Library/Resolvers/TV/SeasonResolver.cs | 2 +- .../Library/Resolvers/TV/SeriesResolver.cs | 18 ++---------------- MediaBrowser.Controller/Entities/CollectionFolder.cs | 1 - MediaBrowser.Controller/Library/ItemResolveArgs.cs | 18 +++++++++--------- MediaBrowser.Controller/Resolvers/BaseItemResolver.cs | 12 ++++++------ 9 files changed, 32 insertions(+), 47 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs b/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs index 9ca76095b..92fb2a753 100644 --- a/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs @@ -11,6 +11,12 @@ namespace Emby.Server.Implementations.Library.Resolvers public abstract class ItemResolver : IItemResolver where T : BaseItem, new() { + /// + /// Gets the priority. + /// + /// The priority. + public virtual ResolverPriority Priority => ResolverPriority.First; + /// /// Resolves the specified args. /// @@ -21,12 +27,6 @@ namespace Emby.Server.Implementations.Library.Resolvers return null; } - /// - /// Gets the priority. - /// - /// The priority. - public virtual ResolverPriority Priority => ResolverPriority.First; - /// /// Sets initial values on the newly resolved item. /// diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 714bc3a84..16bf4dc4a 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -376,7 +376,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies { var multiDiscFolders = new List(); - var libraryOptions = args.GetLibraryOptions(); + var libraryOptions = args.LibraryOptions; var supportPhotos = string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) && libraryOptions.EnablePhotos; var photos = new List(); diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs index 3ac837057..204c8a62e 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs @@ -13,7 +13,7 @@ namespace Emby.Server.Implementations.Library.Resolvers public class PhotoAlbumResolver : FolderResolver { private readonly IImageProcessor _imageProcessor; - private ILibraryManager _libraryManager; + private readonly ILibraryManager _libraryManager; /// /// Initializes a new instance of the class. @@ -26,6 +26,9 @@ namespace Emby.Server.Implementations.Library.Resolvers _libraryManager = libraryManager; } + /// + public override ResolverPriority Priority => ResolverPriority.Second; + /// /// Resolves the specified args. /// @@ -39,8 +42,8 @@ namespace Emby.Server.Implementations.Library.Resolvers // Must be an image file within a photo collection var collectionType = args.GetCollectionType(); - if (string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase) || - (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) && args.GetLibraryOptions().EnablePhotos)) + if (string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase) + || (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) && args.LibraryOptions.EnablePhotos)) { if (HasPhotos(args)) { @@ -84,8 +87,5 @@ namespace Emby.Server.Implementations.Library.Resolvers return false; } - - /// - public override ResolverPriority Priority => ResolverPriority.Second; } } diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs index bcfcee9c6..3cb6542cf 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -47,7 +47,7 @@ namespace Emby.Server.Implementations.Library.Resolvers var collectionType = args.CollectionType; if (string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase) - || (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) && args.GetLibraryOptions().EnablePhotos)) + || (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) && args.LibraryOptions.EnablePhotos)) { if (IsImageFile(args.Path, _imageProcessor)) { diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs index 3332e1806..768e2e4f5 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs @@ -88,7 +88,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV CultureInfo.InvariantCulture, _localization.GetLocalizedString("NameSeasonNumber"), seasonNumber, - args.GetLibraryOptions().PreferredMetadataLanguage); + args.LibraryOptions.PreferredMetadataLanguage); } return season; diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index 4a9d2cf8c..8fc3e3e75 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -19,19 +19,16 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV /// public class SeriesResolver : FolderResolver { - private readonly IFileSystem _fileSystem; private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; /// /// Initializes a new instance of the class. /// - /// The file system. /// The logger. /// The library manager. - public SeriesResolver(IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager) + public SeriesResolver(ILogger logger, ILibraryManager libraryManager) { - _fileSystem = fileSystem; _logger = logger; _libraryManager = libraryManager; } @@ -59,15 +56,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV var collectionType = args.GetCollectionType(); if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) { - // if (args.ContainsFileSystemEntryByName("tvshow.nfo")) - //{ - // return new Series - // { - // Path = args.Path, - // Name = Path.GetFileName(args.Path) - // }; - //} - var configuredContentType = _libraryManager.GetConfiguredContentType(args.Path); if (!string.Equals(configuredContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) { @@ -100,7 +88,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return null; } - if (IsSeriesFolder(args.Path, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger, _libraryManager, false)) + if (IsSeriesFolder(args.Path, args.FileSystemChildren, _logger, _libraryManager, false)) { return new Series { @@ -117,8 +105,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV public static bool IsSeriesFolder( string path, IEnumerable fileSystemChildren, - IDirectoryService directoryService, - IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager, bool isTvContentType) diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 347d5b73c..bc5f38256 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -61,7 +61,6 @@ namespace MediaBrowser.Controller.Entities try { var result = XmlSerializer.DeserializeFromFile(typeof(LibraryOptions), GetLibraryOptionsPath(path)) as LibraryOptions; - if (result == null) { return new LibraryOptions(); diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index f9086066d..5f9aed341 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -14,14 +14,14 @@ namespace MediaBrowser.Controller.Library /// These are arguments relating to the file system that are collected once and then referred to /// whenever needed. Primarily for entity resolution. /// - public class ItemResolveArgs : EventArgs + public class ItemResolveArgs { /// /// The _app paths. /// private readonly IServerApplicationPaths _appPaths; - public IDirectoryService DirectoryService { get; private set; } + private LibraryOptions _libraryOptions; /// /// Initializes a new instance of the class. @@ -34,17 +34,18 @@ namespace MediaBrowser.Controller.Library DirectoryService = directoryService; } + public IDirectoryService DirectoryService { get; } + /// /// Gets the file system children. /// /// The file system children. public FileSystemMetadata[] FileSystemChildren { get; set; } - public LibraryOptions LibraryOptions { get; set; } - - public LibraryOptions GetLibraryOptions() + public LibraryOptions LibraryOptions { - return LibraryOptions ?? (LibraryOptions = Parent == null ? new LibraryOptions() : BaseItem.LibraryManager.GetLibraryOptions(Parent)); + get => _libraryOptions ??= Parent == null ? new LibraryOptions() : BaseItem.LibraryManager.GetLibraryOptions(Parent); + set => _libraryOptions = value; } /// @@ -139,7 +140,7 @@ namespace MediaBrowser.Controller.Library /// Adds the additional location. /// /// The path. - /// + /// is null or empty. public void AddAdditionalLocation(string path) { if (string.IsNullOrEmpty(path)) @@ -148,7 +149,6 @@ namespace MediaBrowser.Controller.Library } AdditionalLocations ??= new List(); - AdditionalLocations.Add(path); } @@ -172,7 +172,7 @@ namespace MediaBrowser.Controller.Library /// /// The name. /// FileSystemInfo. - /// + /// is null or empty. public FileSystemMetadata GetFileSystemEntryByName(string name) { if (string.IsNullOrEmpty(name)) diff --git a/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs b/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs index 25128a5cd..a904c7424 100644 --- a/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs +++ b/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs @@ -10,6 +10,12 @@ namespace MediaBrowser.Controller.Resolvers public abstract class ItemResolver : IItemResolver where T : BaseItem, new() { + /// + /// Gets the priority. + /// + /// The priority. + public virtual ResolverPriority Priority => ResolverPriority.First; + /// /// Resolves the specified args. /// @@ -20,12 +26,6 @@ namespace MediaBrowser.Controller.Resolvers return null; } - /// - /// Gets the priority. - /// - /// The priority. - public virtual ResolverPriority Priority => ResolverPriority.First; - /// /// Sets initial values on the newly resolved item. /// -- cgit v1.2.3 From 47e7c1356c1364e5e834ce37cd4a9ace5e2d838e Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 5 May 2021 16:43:20 +0200 Subject: PathExtensions: Fix index out of bounds in TryReplaceSubPath Fixes #5977 --- Emby.Server.Implementations/Library/PathExtensions.cs | 10 ++++++++-- .../Library/PathExtensionsTests.cs | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs index 770cf6bb0..0de4edb7e 100644 --- a/Emby.Server.Implementations/Library/PathExtensions.cs +++ b/Emby.Server.Implementations/Library/PathExtensions.cs @@ -96,8 +96,14 @@ namespace Emby.Server.Implementations.Library // We have to ensure that the sub path ends with a directory separator otherwise we'll get weird results // when the sub path matches a similar but in-complete subpath var oldSubPathEndsWithSeparator = subPath[^1] == newDirectorySeparatorChar; - if (!path.StartsWith(subPath, StringComparison.OrdinalIgnoreCase) - || (!oldSubPathEndsWithSeparator && path[subPath.Length] != newDirectorySeparatorChar)) + if (!path.StartsWith(subPath, StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + if (path.Length > subPath.Length + && !oldSubPathEndsWithSeparator + && path[subPath.Length] != newDirectorySeparatorChar) { return false; } diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs index e5508243f..c5cc056f5 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs @@ -33,6 +33,7 @@ namespace Jellyfin.Server.Implementations.Tests.Library [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff", "/home/jeff/", "/home/jeff/myfile.mkv")] [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff/", "/home/jeff/", "/home/jeff/myfile.mkv")] [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff/", "/", "/myfile.mkv")] + [InlineData("/o", "/o", "/s", "/s")] // regression test for #5977 public void TryReplaceSubPath_ValidArgs_Correct(string path, string subPath, string newSubPath, string? expectedResult) { Assert.True(PathExtensions.TryReplaceSubPath(path, subPath, newSubPath, out var result)); -- cgit v1.2.3 From ddb04dc12b8bdf33c2020cb1c539664463e61bc3 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 8 Jan 2021 23:57:27 +0100 Subject: Use new ReadAllLines extensions --- .../LiveTv/EmbyTV/EncodedRecorder.cs | 7 ++--- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 14 ++++----- .../LiveTv/TunerHosts/M3uParser.cs | 34 ++++++++-------------- .../Localization/LocalizationManager.cs | 10 +++---- Jellyfin.Api/Helpers/HlsHelpers.cs | 5 +--- MediaBrowser.Common/Extensions/StreamExtensions.cs | 20 +++++++++++-- .../Studios/StudiosImageProvider.cs | 9 +++--- 7 files changed, 48 insertions(+), 51 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 44a8cdee4..9372b0f6c 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -10,6 +10,7 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Json; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; @@ -307,13 +308,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { using (var reader = new StreamReader(source)) { - while (!reader.EndOfStream) + await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) { - var line = await reader.ReadLineAsync().ConfigureAwait(false); - var bytes = Encoding.UTF8.GetBytes(Environment.NewLine + line); - await target.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); + await target.WriteAsync(bytes.AsMemory()).ConfigureAwait(false); await target.FlushAsync().ConfigureAwait(false); } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 4aa5832b1..324109bcf 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -182,16 +182,16 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); using var sr = new StreamReader(stream, System.Text.Encoding.UTF8); var tuners = new List(); - while (!sr.EndOfStream) + await foreach (var line in sr.ReadAllLinesAsync().ConfigureAwait(false)) { - string line = StripXML(sr.ReadLine()); - if (line.Contains("Channel", StringComparison.Ordinal)) + string stripedLine = StripXML(line); + if (stripedLine.Contains("Channel", StringComparison.Ordinal)) { LiveTvTunerStatus status; - var index = line.IndexOf("Channel", StringComparison.OrdinalIgnoreCase); - var name = line.Substring(0, index - 1); - var currentChannel = line.Substring(index + 7); - if (currentChannel != "none") + var index = stripedLine.IndexOf("Channel", StringComparison.OrdinalIgnoreCase); + var name = stripedLine.Substring(0, index - 1); + var currentChannel = stripedLine.Substring(index + 7); + if (string.Equals(currentChannel, "none", StringComparison.Ordinal)) { status = LiveTvTunerStatus.LiveTv; } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index cc30a516d..84d416149 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -35,16 +35,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts // Read the file and display it line by line. using (var reader = new StreamReader(await GetListingsStream(info, cancellationToken).ConfigureAwait(false))) { - return GetChannels(reader, channelIdPrefix, info.Id); - } - } - - public List ParseString(string text, string channelIdPrefix, string tunerHostId) - { - // Read the file and display it line by line. - using (var reader = new StringReader(text)) - { - return GetChannels(reader, channelIdPrefix, tunerHostId); + return await GetChannelsAsync(reader, channelIdPrefix, info.Id).ConfigureAwait(false); } } @@ -70,43 +61,42 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts private const string ExtInfPrefix = "#EXTINF:"; - private List GetChannels(TextReader reader, string channelIdPrefix, string tunerHostId) + private async Task> GetChannelsAsync(TextReader reader, string channelIdPrefix, string tunerHostId) { var channels = new List(); - string line; string extInf = string.Empty; - while ((line = reader.ReadLine()) != null) + await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) { - line = line.Trim(); - if (string.IsNullOrWhiteSpace(line)) + var trimmedLine = line.Trim(); + if (string.IsNullOrWhiteSpace(trimmedLine)) { continue; } - if (line.StartsWith("#EXTM3U", StringComparison.OrdinalIgnoreCase)) + if (trimmedLine.StartsWith("#EXTM3U", StringComparison.OrdinalIgnoreCase)) { continue; } - if (line.StartsWith(ExtInfPrefix, StringComparison.OrdinalIgnoreCase)) + if (trimmedLine.StartsWith(ExtInfPrefix, StringComparison.OrdinalIgnoreCase)) { - extInf = line.Substring(ExtInfPrefix.Length).Trim(); + extInf = trimmedLine.Substring(ExtInfPrefix.Length).Trim(); _logger.LogInformation("Found m3u channel: {0}", extInf); } - else if (!string.IsNullOrWhiteSpace(extInf) && !line.StartsWith('#')) + else if (!string.IsNullOrWhiteSpace(extInf) && !trimmedLine.StartsWith('#')) { - var channel = GetChannelnfo(extInf, tunerHostId, line); + var channel = GetChannelnfo(extInf, tunerHostId, trimmedLine); if (string.IsNullOrWhiteSpace(channel.Id)) { - channel.Id = channelIdPrefix + line.GetMD5().ToString("N", CultureInfo.InvariantCulture); + channel.Id = channelIdPrefix + trimmedLine.GetMD5().ToString("N", CultureInfo.InvariantCulture); } else { channel.Id = channelIdPrefix + channel.Id.GetMD5().ToString("N", CultureInfo.InvariantCulture); } - channel.Path = line; + channel.Path = trimmedLine; channels.Add(channel); extInf = string.Empty; } diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 46858b4fb..220e423bf 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Reflection; using System.Text.Json; using System.Threading.Tasks; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Json; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Entities; @@ -72,8 +73,7 @@ namespace Emby.Server.Implementations.Localization using (var str = _assembly.GetManifestResourceStream(resource)) using (var reader = new StreamReader(str)) { - string line; - while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) != null) + await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) { if (string.IsNullOrWhiteSpace(line)) { @@ -118,10 +118,8 @@ namespace Emby.Server.Implementations.Localization using (var stream = _assembly.GetManifestResourceStream(ResourcePath)) using (var reader = new StreamReader(stream)) { - while (!reader.EndOfStream) + await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) { - var line = await reader.ReadLineAsync().ConfigureAwait(false); - if (string.IsNullOrWhiteSpace(line)) { continue; @@ -179,7 +177,7 @@ namespace Emby.Server.Implementations.Localization /// public IEnumerable GetCountries() { - StreamReader reader = new StreamReader(_assembly.GetManifestResourceStream("Emby.Server.Implementations.Localization.countries.json")); + using StreamReader reader = new StreamReader(_assembly.GetManifestResourceStream("Emby.Server.Implementations.Localization.countries.json")); return JsonSerializer.Deserialize>(reader.ReadToEnd(), _jsonOptions); } diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs index 18e23fb5c..d0666034e 100644 --- a/Jellyfin.Api/Helpers/HlsHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsHelpers.cs @@ -118,10 +118,7 @@ namespace Jellyfin.Api.Helpers /// The playlist text as a string. public static string GetLivePlaylistText(string path, StreamState state) { - using var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - using var reader = new StreamReader(stream); - - var text = reader.ReadToEnd(); + var text = File.ReadAllText(path); var segmentFormat = EncodingHelper.GetSegmentFileExtension(state.Request.SegmentContainer).TrimStart('.'); if (string.Equals(segmentFormat, "mp4", StringComparison.OrdinalIgnoreCase)) diff --git a/MediaBrowser.Common/Extensions/StreamExtensions.cs b/MediaBrowser.Common/Extensions/StreamExtensions.cs index cd77be7b2..d49bf1d46 100644 --- a/MediaBrowser.Common/Extensions/StreamExtensions.cs +++ b/MediaBrowser.Common/Extensions/StreamExtensions.cs @@ -35,11 +35,11 @@ namespace MediaBrowser.Common.Extensions } /// - /// Reads all lines in the . + /// Reads all lines in the . /// - /// The to read from. + /// The to read from. /// All lines in the stream. - public static IEnumerable ReadAllLines(this StreamReader reader) + public static IEnumerable ReadAllLines(this TextReader reader) { string? line; while ((line = reader.ReadLine()) != null) @@ -47,5 +47,19 @@ namespace MediaBrowser.Common.Extensions yield return line; } } + + /// + /// Reads all lines in the . + /// + /// The to read from. + /// All lines in the stream. + public static async IAsyncEnumerable ReadAllLinesAsync(this TextReader reader) + { + string? line; + while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) != null) + { + yield return line; + } + } } } diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs index 5fcf6d9aa..5ec9a02cb 100644 --- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; @@ -177,13 +178,11 @@ namespace MediaBrowser.Providers.Studios { var lines = new List(); - while (!reader.EndOfStream) + foreach (var line in reader.ReadAllLines()) { - var text = reader.ReadLine(); - - if (!string.IsNullOrWhiteSpace(text)) + if (!string.IsNullOrWhiteSpace(line)) { - lines.Add(text); + lines.Add(line); } } -- cgit v1.2.3 From 4367b97a54f31233e242ef1afe6714b934ecf4d9 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 7 May 2021 00:52:06 +0200 Subject: Fix build --- Emby.Server.Implementations/Library/ResolverHelper.cs | 5 +++++ MediaBrowser.Controller/Library/TVUtils.cs | 2 +- MediaBrowser.Controller/Providers/DirectoryService.cs | 19 +++++++++---------- .../Providers/IDirectoryService.cs | 2 +- MediaBrowser.LocalMetadata/BaseXmlProvider.cs | 2 +- .../Providers/BoxSetXmlProvider.cs | 2 +- .../Providers/PlaylistXmlProvider.cs | 2 +- .../Providers/AlbumNfoProvider.cs | 2 +- .../Providers/ArtistNfoProvider.cs | 2 +- .../Providers/EpisodeNfoProvider.cs | 2 +- .../Providers/SeasonNfoProvider.cs | 2 +- .../Providers/SeriesNfoProvider.cs | 2 +- 12 files changed, 24 insertions(+), 20 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/ResolverHelper.cs b/Emby.Server.Implementations/Library/ResolverHelper.cs index b1a2e9284..1d9b44874 100644 --- a/Emby.Server.Implementations/Library/ResolverHelper.cs +++ b/Emby.Server.Implementations/Library/ResolverHelper.cs @@ -44,6 +44,11 @@ namespace Emby.Server.Implementations.Library // Make sure DateCreated and DateModified have values var fileInfo = directoryService.GetFile(item.Path); + if (fileInfo == null) + { + throw new FileNotFoundException("Can't find item path.", item.Path); + } + SetDateCreated(item, fileInfo); EnsureName(item, fileInfo); diff --git a/MediaBrowser.Controller/Library/TVUtils.cs b/MediaBrowser.Controller/Library/TVUtils.cs index 8cbfc78aa..968338dc6 100644 --- a/MediaBrowser.Controller/Library/TVUtils.cs +++ b/MediaBrowser.Controller/Library/TVUtils.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.Controller.Library /// The day. /// List{DayOfWeek}. [return: NotNullIfNotNull("day")] - public static DayOfWeek[] GetAirDays(string? day) + public static DayOfWeek[]? GetAirDays(string? day) { if (!string.IsNullOrEmpty(day)) { diff --git a/MediaBrowser.Controller/Providers/DirectoryService.cs b/MediaBrowser.Controller/Providers/DirectoryService.cs index 5c92069b4..291a26883 100644 --- a/MediaBrowser.Controller/Providers/DirectoryService.cs +++ b/MediaBrowser.Controller/Providers/DirectoryService.cs @@ -43,18 +43,17 @@ namespace MediaBrowser.Controller.Providers return list; } - public FileSystemMetadata GetFile(string path) + public FileSystemMetadata? GetFile(string path) { - var result = _fileCache.GetOrAdd(path, p => + if (!_fileCache.TryGetValue(path, out var result)) { - var file = _fileSystem.GetFileInfo(p); - return file != null && file.Exists ? file : null; - }); - - if (result == null) - { - // lets not store null results in the cache - _fileCache.TryRemove(path, out _); + var file = _fileSystem.GetFileInfo(path); + var res = file != null && file.Exists ? file : null; + if (res != null) + { + result = res; + _fileCache.TryAdd(path, result); + } } return result; diff --git a/MediaBrowser.Controller/Providers/IDirectoryService.cs b/MediaBrowser.Controller/Providers/IDirectoryService.cs index f06481c7a..9cee06a4c 100644 --- a/MediaBrowser.Controller/Providers/IDirectoryService.cs +++ b/MediaBrowser.Controller/Providers/IDirectoryService.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Controller.Providers List GetFiles(string path); - FileSystemMetadata GetFile(string path); + FileSystemMetadata? GetFile(string path); IReadOnlyList GetFilePaths(string path); diff --git a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs index b036a2cc8..9f8e921b4 100644 --- a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs @@ -91,7 +91,7 @@ namespace MediaBrowser.LocalMetadata /// Item inf. /// Instance of the interface. /// The file system metadata. - protected abstract FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService); + protected abstract FileSystemMetadata? GetXmlFile(ItemInfo info, IDirectoryService directoryService); /// public bool HasChanged(BaseItem item, IDirectoryService directoryService) diff --git a/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs index cc705a9df..ea123bbf2 100644 --- a/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.LocalMetadata.Providers } /// - protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService) + protected override FileSystemMetadata? GetXmlFile(ItemInfo info, IDirectoryService directoryService) { return directoryService.GetFile(Path.Combine(info.Path, "collection.xml")); } diff --git a/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs index 36f3048ad..899035652 100644 --- a/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs @@ -39,7 +39,7 @@ namespace MediaBrowser.LocalMetadata.Providers } /// - protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService) + protected override FileSystemMetadata? GetXmlFile(ItemInfo info, IDirectoryService directoryService) { return directoryService.GetFile(PlaylistXmlSaver.GetSavePath(info.Path)); } diff --git a/MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs index bd557d783..f7a85a07e 100644 --- a/MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.XbmcMetadata.Providers } /// - protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService) + protected override FileSystemMetadata? GetXmlFile(ItemInfo info, IDirectoryService directoryService) => directoryService.GetFile(Path.Combine(info.Path, "album.nfo")); } } diff --git a/MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs index 54bb83114..2b563b7fa 100644 --- a/MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.XbmcMetadata.Providers } /// - protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService) + protected override FileSystemMetadata? GetXmlFile(ItemInfo info, IDirectoryService directoryService) => directoryService.GetFile(Path.Combine(info.Path, "artist.nfo")); } } diff --git a/MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs index 64b208345..f6c5877b4 100644 --- a/MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.XbmcMetadata.Providers } /// - protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService) + protected override FileSystemMetadata? GetXmlFile(ItemInfo info, IDirectoryService directoryService) { var path = Path.ChangeExtension(info.Path, ".nfo"); diff --git a/MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs index 97220cf7e..d01abadf6 100644 --- a/MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.XbmcMetadata.Providers } /// - protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService) + protected override FileSystemMetadata? GetXmlFile(ItemInfo info, IDirectoryService directoryService) => directoryService.GetFile(Path.Combine(info.Path, "season.nfo")); } } diff --git a/MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs index 9a9b94123..002b94463 100644 --- a/MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.XbmcMetadata.Providers } /// - protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService) + protected override FileSystemMetadata? GetXmlFile(ItemInfo info, IDirectoryService directoryService) => directoryService.GetFile(Path.Combine(info.Path, "tvshow.nfo")); } } -- cgit v1.2.3