aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ci/azure-pipelines-package.yml2
-rw-r--r--Emby.Dlna/DlnaManager.cs18
-rw-r--r--Emby.Server.Implementations/Channels/ChannelManager.cs23
-rw-r--r--Emby.Server.Implementations/Devices/DeviceManager.cs23
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs17
-rw-r--r--Emby.Server.Implementations/Localization/Core/de.json4
-rw-r--r--Emby.Server.Implementations/Networking/NetworkManager.cs2
-rw-r--r--Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj4
-rw-r--r--Jellyfin.Drawing.Skia/SkiaEncoder.cs3
-rw-r--r--Jellyfin.Server.Implementations/JellyfinDbProvider.cs14
-rw-r--r--Jellyfin.Server/CoreAppHost.cs11
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs3
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs14
-rw-r--r--MediaBrowser.Api/Subtitles/SubtitleService.cs15
-rw-r--r--MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs11
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs12
-rw-r--r--MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs6
-rw-r--r--MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs4
-rw-r--r--MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs4
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs4
-rw-r--r--MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs22
-rw-r--r--SharedVersion.cs4
-rw-r--r--build.yaml2
-rwxr-xr-xbump_version3
-rw-r--r--debian/changelog6
-rw-r--r--debian/metapackage/jellyfin2
-rw-r--r--fedora/jellyfin.spec4
28 files changed, 139 insertions, 100 deletions
diff --git a/.ci/azure-pipelines-package.yml b/.ci/azure-pipelines-package.yml
index 64d40e7f5..1677f71c7 100644
--- a/.ci/azure-pipelines-package.yml
+++ b/.ci/azure-pipelines-package.yml
@@ -85,7 +85,7 @@ jobs:
value: 0.0.0
steps:
- - script: echo '##vso[task.setvariable variable=JellyfinVersion]$( awk -F "/" "{ print $NF }" <<<"$(Build.SourceBranch)" | sed "s/^v//" )'
+ - script: echo "##vso[task.setvariable variable=JellyfinVersion]$( awk -F '/' '{ print $NF }' <<<'$(Build.SourceBranch)' | sed 's/^v//' )"
displayName: Set release version (stable)
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags')
diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs
index 1e20ff92b..269f7ee43 100644
--- a/Emby.Dlna/DlnaManager.cs
+++ b/Emby.Dlna/DlnaManager.cs
@@ -122,15 +122,15 @@ namespace Emby.Dlna
var builder = new StringBuilder();
builder.AppendLine("No matching device profile found. The default will need to be used.");
- builder.AppendLine(string.Format("DeviceDescription:{0}", profile.DeviceDescription ?? string.Empty));
- builder.AppendLine(string.Format("FriendlyName:{0}", profile.FriendlyName ?? string.Empty));
- builder.AppendLine(string.Format("Manufacturer:{0}", profile.Manufacturer ?? string.Empty));
- builder.AppendLine(string.Format("ManufacturerUrl:{0}", profile.ManufacturerUrl ?? string.Empty));
- builder.AppendLine(string.Format("ModelDescription:{0}", profile.ModelDescription ?? string.Empty));
- builder.AppendLine(string.Format("ModelName:{0}", profile.ModelName ?? string.Empty));
- builder.AppendLine(string.Format("ModelNumber:{0}", profile.ModelNumber ?? string.Empty));
- builder.AppendLine(string.Format("ModelUrl:{0}", profile.ModelUrl ?? string.Empty));
- builder.AppendLine(string.Format("SerialNumber:{0}", profile.SerialNumber ?? string.Empty));
+ builder.AppendFormat(CultureInfo.InvariantCulture, "DeviceDescription:{0}", profile.DeviceDescription ?? string.Empty).AppendLine();
+ builder.AppendFormat(CultureInfo.InvariantCulture, "FriendlyName:{0}", profile.FriendlyName ?? string.Empty).AppendLine();
+ builder.AppendFormat(CultureInfo.InvariantCulture, "Manufacturer:{0}", profile.Manufacturer ?? string.Empty).AppendLine();
+ builder.AppendFormat(CultureInfo.InvariantCulture, "ManufacturerUrl:{0}", profile.ManufacturerUrl ?? string.Empty).AppendLine();
+ builder.AppendFormat(CultureInfo.InvariantCulture, "ModelDescription:{0}", profile.ModelDescription ?? string.Empty).AppendLine();
+ builder.AppendFormat(CultureInfo.InvariantCulture, "ModelName:{0}", profile.ModelName ?? string.Empty).AppendLine();
+ builder.AppendFormat(CultureInfo.InvariantCulture, "ModelNumber:{0}", profile.ModelNumber ?? string.Empty).AppendLine();
+ builder.AppendFormat(CultureInfo.InvariantCulture, "ModelUrl:{0}", profile.ModelUrl ?? string.Empty).AppendLine();
+ builder.AppendFormat(CultureInfo.InvariantCulture, "SerialNumber:{0}", profile.SerialNumber ?? string.Empty).AppendLine();
_logger.LogInformation(builder.ToString());
}
diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs
index c803d9d82..4c3161ef4 100644
--- a/Emby.Server.Implementations/Channels/ChannelManager.cs
+++ b/Emby.Server.Implementations/Channels/ChannelManager.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
@@ -22,6 +21,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Serialization;
+using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
@@ -45,10 +45,7 @@ namespace Emby.Server.Implementations.Channels
private readonly IFileSystem _fileSystem;
private readonly IJsonSerializer _jsonSerializer;
private readonly IProviderManager _providerManager;
-
- private readonly ConcurrentDictionary<string, Tuple<DateTime, List<MediaSourceInfo>>> _channelItemMediaInfo =
- new ConcurrentDictionary<string, Tuple<DateTime, List<MediaSourceInfo>>>();
-
+ private readonly IMemoryCache _memoryCache;
private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(1, 1);
/// <summary>
@@ -63,6 +60,7 @@ namespace Emby.Server.Implementations.Channels
/// <param name="userDataManager">The user data manager.</param>
/// <param name="jsonSerializer">The JSON serializer.</param>
/// <param name="providerManager">The provider manager.</param>
+ /// <param name="memoryCache">The memory cache.</param>
public ChannelManager(
IUserManager userManager,
IDtoService dtoService,
@@ -72,7 +70,8 @@ namespace Emby.Server.Implementations.Channels
IFileSystem fileSystem,
IUserDataManager userDataManager,
IJsonSerializer jsonSerializer,
- IProviderManager providerManager)
+ IProviderManager providerManager,
+ IMemoryCache memoryCache)
{
_userManager = userManager;
_dtoService = dtoService;
@@ -83,6 +82,7 @@ namespace Emby.Server.Implementations.Channels
_userDataManager = userDataManager;
_jsonSerializer = jsonSerializer;
_providerManager = providerManager;
+ _memoryCache = memoryCache;
}
internal IChannel[] Channels { get; private set; }
@@ -417,20 +417,15 @@ namespace Emby.Server.Implementations.Channels
private async Task<IEnumerable<MediaSourceInfo>> GetChannelItemMediaSourcesInternal(IRequiresMediaInfoCallback channel, string id, CancellationToken cancellationToken)
{
- if (_channelItemMediaInfo.TryGetValue(id, out Tuple<DateTime, List<MediaSourceInfo>> cachedInfo))
+ if (_memoryCache.TryGetValue(id, out List<MediaSourceInfo> cachedInfo))
{
- if ((DateTime.UtcNow - cachedInfo.Item1).TotalMinutes < 5)
- {
- return cachedInfo.Item2;
- }
+ return cachedInfo;
}
var mediaInfo = await channel.GetChannelItemMediaInfo(id, cancellationToken)
.ConfigureAwait(false);
var list = mediaInfo.ToList();
-
- var item2 = new Tuple<DateTime, List<MediaSourceInfo>>(DateTime.UtcNow, list);
- _channelItemMediaInfo.AddOrUpdate(id, item2, (key, oldValue) => item2);
+ _memoryCache.CreateEntry(id).SetValue(list).SetAbsoluteExpiration(DateTimeOffset.UtcNow.AddMinutes(5));
return list;
}
diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs
index e75745cc6..2921a7f0e 100644
--- a/Emby.Server.Implementations/Devices/DeviceManager.cs
+++ b/Emby.Server.Implementations/Devices/DeviceManager.cs
@@ -5,8 +5,8 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
-using Jellyfin.Data.Enums;
using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices;
@@ -17,16 +17,17 @@ using MediaBrowser.Model.Events;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Session;
+using Microsoft.Extensions.Caching.Memory;
namespace Emby.Server.Implementations.Devices
{
public class DeviceManager : IDeviceManager
{
+ private readonly IMemoryCache _memoryCache;
private readonly IJsonSerializer _json;
private readonly IUserManager _userManager;
private readonly IServerConfigurationManager _config;
private readonly IAuthenticationRepository _authRepo;
- private readonly Dictionary<string, ClientCapabilities> _capabilitiesCache;
private readonly object _capabilitiesSyncLock = new object();
public event EventHandler<GenericEventArgs<Tuple<string, DeviceOptions>>> DeviceOptionsUpdated;
@@ -35,13 +36,14 @@ namespace Emby.Server.Implementations.Devices
IAuthenticationRepository authRepo,
IJsonSerializer json,
IUserManager userManager,
- IServerConfigurationManager config)
+ IServerConfigurationManager config,
+ IMemoryCache memoryCache)
{
_json = json;
_userManager = userManager;
_config = config;
+ _memoryCache = memoryCache;
_authRepo = authRepo;
- _capabilitiesCache = new Dictionary<string, ClientCapabilities>(StringComparer.OrdinalIgnoreCase);
}
public void SaveCapabilities(string deviceId, ClientCapabilities capabilities)
@@ -51,8 +53,7 @@ namespace Emby.Server.Implementations.Devices
lock (_capabilitiesSyncLock)
{
- _capabilitiesCache[deviceId] = capabilities;
-
+ _memoryCache.CreateEntry(deviceId).SetValue(capabilities);
_json.SerializeToFile(capabilities, path);
}
}
@@ -71,13 +72,13 @@ namespace Emby.Server.Implementations.Devices
public ClientCapabilities GetCapabilities(string id)
{
- lock (_capabilitiesSyncLock)
+ if (_memoryCache.TryGetValue(id, out ClientCapabilities result))
{
- if (_capabilitiesCache.TryGetValue(id, out var result))
- {
- return result;
- }
+ return result;
+ }
+ lock (_capabilitiesSyncLock)
+ {
var path = Path.Combine(GetDevicePath(id), "capabilities.json");
try
{
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index 9165ede35..f3c2f0e03 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -1,7 +1,6 @@
#pragma warning disable CS1591
using System;
-using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
@@ -46,6 +45,7 @@ using MediaBrowser.Model.Net;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Tasks;
using MediaBrowser.Providers.MediaInfo;
+using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Genre = MediaBrowser.Controller.Entities.Genre;
@@ -63,6 +63,7 @@ namespace Emby.Server.Implementations.Library
private const string ShortcutFileExtension = ".mblink";
private readonly ILogger<LibraryManager> _logger;
+ private readonly IMemoryCache _memoryCache;
private readonly ITaskManager _taskManager;
private readonly IUserManager _userManager;
private readonly IUserDataManager _userDataRepository;
@@ -74,7 +75,6 @@ namespace Emby.Server.Implementations.Library
private readonly IMediaEncoder _mediaEncoder;
private readonly IFileSystem _fileSystem;
private readonly IItemRepository _itemRepository;
- private readonly ConcurrentDictionary<Guid, BaseItem> _libraryItemsCache;
private readonly IImageProcessor _imageProcessor;
/// <summary>
@@ -112,6 +112,7 @@ namespace Emby.Server.Implementations.Library
/// <param name="mediaEncoder">The media encoder.</param>
/// <param name="itemRepository">The item repository.</param>
/// <param name="imageProcessor">The image processor.</param>
+ /// <param name="memoryCache">The memory cache.</param>
public LibraryManager(
IServerApplicationHost appHost,
ILogger<LibraryManager> logger,
@@ -125,7 +126,8 @@ namespace Emby.Server.Implementations.Library
Lazy<IUserViewManager> userviewManagerFactory,
IMediaEncoder mediaEncoder,
IItemRepository itemRepository,
- IImageProcessor imageProcessor)
+ IImageProcessor imageProcessor,
+ IMemoryCache memoryCache)
{
_appHost = appHost;
_logger = logger;
@@ -140,8 +142,7 @@ namespace Emby.Server.Implementations.Library
_mediaEncoder = mediaEncoder;
_itemRepository = itemRepository;
_imageProcessor = imageProcessor;
-
- _libraryItemsCache = new ConcurrentDictionary<Guid, BaseItem>();
+ _memoryCache = memoryCache;
_configurationManager.ConfigurationUpdated += ConfigurationUpdated;
@@ -299,7 +300,7 @@ namespace Emby.Server.Implementations.Library
}
}
- _libraryItemsCache.AddOrUpdate(item.Id, item, delegate { return item; });
+ _memoryCache.CreateEntry(item.Id).SetValue(item);
}
public void DeleteItem(BaseItem item, DeleteOptions options)
@@ -447,7 +448,7 @@ namespace Emby.Server.Implementations.Library
_itemRepository.DeleteItem(child.Id);
}
- _libraryItemsCache.TryRemove(item.Id, out BaseItem removed);
+ _memoryCache.Remove(item.Id);
ReportItemRemoved(item, parent);
}
@@ -1248,7 +1249,7 @@ namespace Emby.Server.Implementations.Library
throw new ArgumentException("Guid can't be empty", nameof(id));
}
- if (_libraryItemsCache.TryGetValue(id, out BaseItem item))
+ if (_memoryCache.TryGetValue(id, out BaseItem item))
{
return item;
}
diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json
index a6e9779c9..eec880208 100644
--- a/Emby.Server.Implementations/Localization/Core/de.json
+++ b/Emby.Server.Implementations/Localization/Core/de.json
@@ -101,8 +101,8 @@
"TaskCleanTranscode": "Lösche Transkodier Pfad",
"TaskUpdatePluginsDescription": "Lädt Updates für Plugins herunter, welche dazu eingestellt sind automatisch zu updaten und installiert sie.",
"TaskUpdatePlugins": "Update Plugins",
- "TaskRefreshPeopleDescription": "Erneuert Metadaten für Schausteller und Regisseure in deinen Bibliotheken.",
- "TaskRefreshPeople": "Erneuere Schausteller",
+ "TaskRefreshPeopleDescription": "Erneuert Metadaten für Schauspieler und Regisseure in deinen Bibliotheken.",
+ "TaskRefreshPeople": "Erneuere Schauspieler",
"TaskCleanLogsDescription": "Lösche Log Dateien die älter als {0} Tage sind.",
"TaskCleanLogs": "Lösche Log Pfad",
"TaskRefreshLibraryDescription": "Scanne alle Bibliotheken für hinzugefügte Datein und erneuere Metadaten.",
diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs
index ff95302ee..089ec30e6 100644
--- a/Emby.Server.Implementations/Networking/NetworkManager.cs
+++ b/Emby.Server.Implementations/Networking/NetworkManager.cs
@@ -165,7 +165,7 @@ namespace Emby.Server.Implementations.Networking
(octet[0] == 127) || // RFC1122
(octet[0] == 169 && octet[1] == 254)) // RFC3927
{
- return false;
+ return true;
}
if (checkSubnets && IsInPrivateAddressSpaceAndLocalSubnet(endpoint))
diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj
index 6db514b2e..65a439459 100644
--- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj
+++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj
@@ -18,8 +18,8 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="BlurHashSharp" Version="1.0.1" />
- <PackageReference Include="BlurHashSharp.SkiaSharp" Version="1.0.0" />
+ <PackageReference Include="BlurHashSharp" Version="1.1.0" />
+ <PackageReference Include="BlurHashSharp.SkiaSharp" Version="1.1.0" />
<PackageReference Include="SkiaSharp" Version="1.68.3" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="1.68.3" />
<PackageReference Include="Jellyfin.SkiaSharp.NativeAssets.LinuxArm" Version="1.68.1" />
diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs
index 8f45ba674..1f7c43de8 100644
--- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs
+++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs
@@ -199,7 +199,8 @@ namespace Jellyfin.Drawing.Skia
throw new ArgumentNullException(nameof(path));
}
- return BlurHashEncoder.Encode(xComp, yComp, path);
+ // Any larger than 128x128 is too slow and there's no visually discernible difference
+ return BlurHashEncoder.Encode(xComp, yComp, path, 128, 128);
}
private static bool HasDiacritics(string text)
diff --git a/Jellyfin.Server.Implementations/JellyfinDbProvider.cs b/Jellyfin.Server.Implementations/JellyfinDbProvider.cs
index 8f5c19900..486be6053 100644
--- a/Jellyfin.Server.Implementations/JellyfinDbProvider.cs
+++ b/Jellyfin.Server.Implementations/JellyfinDbProvider.cs
@@ -1,4 +1,6 @@
using System;
+using System.IO;
+using MediaBrowser.Common.Configuration;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
@@ -10,15 +12,20 @@ namespace Jellyfin.Server.Implementations
public class JellyfinDbProvider
{
private readonly IServiceProvider _serviceProvider;
+ private readonly IApplicationPaths _appPaths;
/// <summary>
/// Initializes a new instance of the <see cref="JellyfinDbProvider"/> class.
/// </summary>
/// <param name="serviceProvider">The application's service provider.</param>
- public JellyfinDbProvider(IServiceProvider serviceProvider)
+ /// <param name="appPaths">The application paths.</param>
+ public JellyfinDbProvider(IServiceProvider serviceProvider, IApplicationPaths appPaths)
{
_serviceProvider = serviceProvider;
- serviceProvider.GetRequiredService<JellyfinDb>().Database.Migrate();
+ _appPaths = appPaths;
+
+ using var jellyfinDb = CreateContext();
+ jellyfinDb.Database.Migrate();
}
/// <summary>
@@ -27,7 +34,8 @@ namespace Jellyfin.Server.Implementations
/// <returns>The newly created context.</returns>
public JellyfinDb CreateContext()
{
- return _serviceProvider.GetRequiredService<JellyfinDb>();
+ var contextOptions = new DbContextOptionsBuilder<JellyfinDb>().UseSqlite($"Filename={Path.Combine(_appPaths.DataPath, "jellyfin.db")}");
+ return ActivatorUtilities.CreateInstance<JellyfinDb>(_serviceProvider, contextOptions.Options);
}
}
}
diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs
index 71b0fd8f3..7db3db36b 100644
--- a/Jellyfin.Server/CoreAppHost.cs
+++ b/Jellyfin.Server/CoreAppHost.cs
@@ -64,11 +64,12 @@ namespace Jellyfin.Server
Logger.LogWarning($"Skia not available. Will fallback to {nameof(NullImageEncoder)}.");
}
- // TODO: Set up scoping and use AddDbContextPool
- serviceCollection.AddDbContext<JellyfinDb>(
- options => options
- .UseSqlite($"Filename={Path.Combine(ApplicationPaths.DataPath, "jellyfin.db")}"),
- ServiceLifetime.Transient);
+ // TODO: Set up scoping and use AddDbContextPool,
+ // can't register as Transient since tracking transient in GC is funky
+ // serviceCollection.AddDbContext<JellyfinDb>(
+ // options => options
+ // .UseSqlite($"Filename={Path.Combine(ApplicationPaths.DataPath, "jellyfin.db")}"),
+ // ServiceLifetime.Transient);
serviceCollection.AddSingleton<JellyfinDbProvider>();
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 418cd92b3..c80e8e64f 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -194,7 +194,8 @@ namespace MediaBrowser.Api.Playback.Hls
var paddedBitrate = Convert.ToInt32(bitrate * 1.15);
// Main stream
- builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + paddedBitrate.ToString(CultureInfo.InvariantCulture));
+ builder.Append("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=")
+ .AppendLine(paddedBitrate.ToString(CultureInfo.InvariantCulture));
var playlistUrl = "hls/" + Path.GetFileName(firstPlaylist).Replace(".m3u8", "/stream.m3u8");
builder.AppendLine(playlistUrl);
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index 6ff96ac56..661c1ba5f 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -968,7 +968,8 @@ namespace MediaBrowser.Api.Playback.Hls
builder.AppendLine("#EXTM3U");
builder.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
builder.AppendLine("#EXT-X-VERSION:3");
- builder.AppendLine("#EXT-X-TARGETDURATION:" + Math.Ceiling(segmentLengths.Length > 0 ? segmentLengths.Max() : state.SegmentLength).ToString(CultureInfo.InvariantCulture));
+ builder.Append("#EXT-X-TARGETDURATION:")
+ .AppendLine(Math.Ceiling(segmentLengths.Length > 0 ? segmentLengths.Max() : state.SegmentLength).ToString(CultureInfo.InvariantCulture));
builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
var queryStringIndex = Request.RawUrl.IndexOf('?');
@@ -983,14 +984,17 @@ namespace MediaBrowser.Api.Playback.Hls
foreach (var length in segmentLengths)
{
- builder.AppendLine("#EXTINF:" + length.ToString("0.0000", CultureInfo.InvariantCulture) + ", nodesc");
-
- builder.AppendLine(string.Format("hls1/{0}/{1}{2}{3}",
+ builder.Append("#EXTINF:")
+ .Append(length.ToString("0.0000", CultureInfo.InvariantCulture))
+ .AppendLine(", nodesc");
+ builder.AppendFormat(
+ CultureInfo.InvariantCulture,
+ "hls1/{0}/{1}{2}{3}",
name,
index.ToString(CultureInfo.InvariantCulture),
GetSegmentFileExtension(request),
- queryString));
+ queryString).AppendLine();
index++;
}
diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs
index a70da8e56..6a6196d8a 100644
--- a/MediaBrowser.Api/Subtitles/SubtitleService.cs
+++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs
@@ -175,11 +175,12 @@ namespace MediaBrowser.Api.Subtitles
throw new ArgumentException("segmentLength was not given, or it was given incorrectly. (It should be bigger than 0)");
}
- builder.AppendLine("#EXTM3U");
- builder.AppendLine("#EXT-X-TARGETDURATION:" + request.SegmentLength.ToString(CultureInfo.InvariantCulture));
- builder.AppendLine("#EXT-X-VERSION:3");
- builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
- builder.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
+ builder.AppendLine("#EXTM3U")
+ .Append("#EXT-X-TARGETDURATION:")
+ .AppendLine(request.SegmentLength.ToString(CultureInfo.InvariantCulture))
+ .AppendLine("#EXT-X-VERSION:3")
+ .AppendLine("#EXT-X-MEDIA-SEQUENCE:0")
+ .AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
long positionTicks = 0;
@@ -190,7 +191,9 @@ namespace MediaBrowser.Api.Subtitles
var remaining = runtime - positionTicks;
var lengthTicks = Math.Min(remaining, segmentLengthTicks);
- builder.AppendLine("#EXTINF:" + TimeSpan.FromTicks(lengthTicks).TotalSeconds.ToString(CultureInfo.InvariantCulture) + ",");
+ builder.Append("#EXTINF:")
+ .Append(TimeSpan.FromTicks(lengthTicks).TotalSeconds.ToString(CultureInfo.InvariantCulture))
+ .AppendLine(",");
var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks);
diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
index c85d963ed..0b447e3e6 100644
--- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
+++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
@@ -1367,7 +1367,9 @@ namespace MediaBrowser.MediaEncoding.Probing
// OR -> COMMENT. SUBTITLE: DESCRIPTION
// e.g. -> 4/13. The Doctor's Wife: Science fiction drama. When he follows a Time Lord distress signal, the Doctor puts Amy, Rory and his beloved TARDIS in grave danger. Also in HD. [AD,S]
// e.g. -> CBeebies Bedtime Hour. The Mystery: Animated adventures of two friends who live on an island in the middle of the big city. Some of Abney and Teal's favourite objects are missing. [S]
- if (string.IsNullOrWhiteSpace(subTitle) && !string.IsNullOrWhiteSpace(description) && description.Substring(0, Math.Min(description.Length, MaxSubtitleDescriptionExtractionLength)).Contains(":")) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename
+ if (string.IsNullOrWhiteSpace(subTitle)
+ && !string.IsNullOrWhiteSpace(description)
+ && description.AsSpan().Slice(0, Math.Min(description.Length, MaxSubtitleDescriptionExtractionLength)).IndexOf(':') != -1) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename
{
string[] parts = description.Split(':');
if (parts.Length > 0)
@@ -1375,7 +1377,7 @@ namespace MediaBrowser.MediaEncoding.Probing
string subtitle = parts[0];
try
{
- if (subtitle.Contains("/")) // It contains a episode number and season number
+ if (subtitle.Contains('/', StringComparison.Ordinal)) // It contains a episode number and season number
{
string[] numbers = subtitle.Split(' ');
video.IndexNumber = int.Parse(numbers[0].Replace(".", "").Split('/')[0]);
@@ -1390,8 +1392,11 @@ namespace MediaBrowser.MediaEncoding.Probing
}
catch // Default parsing
{
- if (subtitle.Contains(".")) // skip the comment, keep the subtitle
+ 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
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
index f850f5c2e..2afa89cda 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
@@ -731,19 +731,19 @@ namespace MediaBrowser.MediaEncoding.Subtitles
var date = _fileSystem.GetLastWriteTimeUtc(mediaPath);
- var filename = (mediaPath + "_" + subtitleStreamIndex.ToString(CultureInfo.InvariantCulture) + "_" + date.Ticks.ToString(CultureInfo.InvariantCulture) + ticksParam).GetMD5() + outputSubtitleExtension;
+ ReadOnlySpan<char> filename = (mediaPath + "_" + subtitleStreamIndex.ToString(CultureInfo.InvariantCulture) + "_" + date.Ticks.ToString(CultureInfo.InvariantCulture) + ticksParam).GetMD5() + outputSubtitleExtension;
- var prefix = filename.Substring(0, 1);
+ var prefix = filename.Slice(0, 1);
- return Path.Combine(SubtitleCachePath, prefix, filename);
+ return Path.Join(SubtitleCachePath, prefix, filename);
}
else
{
- var filename = (mediaPath + "_" + subtitleStreamIndex.ToString(CultureInfo.InvariantCulture)).GetMD5() + outputSubtitleExtension;
+ ReadOnlySpan<char> filename = (mediaPath + "_" + subtitleStreamIndex.ToString(CultureInfo.InvariantCulture)).GetMD5() + outputSubtitleExtension;
- var prefix = filename.Substring(0, 1);
+ var prefix = filename.Slice(0, 1);
- return Path.Combine(SubtitleCachePath, prefix, filename);
+ return Path.Join(SubtitleCachePath, prefix, filename);
}
}
diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
index 80acb2c05..f69ec9744 100644
--- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
@@ -93,7 +93,7 @@ namespace MediaBrowser.Providers.MediaInfo
private string GetAudioImagePath(Audio item)
{
- string filename = null;
+ string filename;
if (item.GetType() == typeof(Audio))
{
@@ -116,9 +116,9 @@ namespace MediaBrowser.Providers.MediaInfo
filename = item.Id.ToString("N", CultureInfo.InvariantCulture) + ".jpg";
}
- var prefix = filename.Substring(0, 1);
+ var prefix = filename.AsSpan().Slice(0, 1);
- return Path.Combine(AudioImagesPath, prefix, filename);
+ return Path.Join(AudioImagesPath, prefix, filename);
}
public string AudioImagesPath => Path.Combine(_config.ApplicationPaths.CachePath, "extracted-audio-images");
diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs
index 944ba26af..12aecba84 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs
@@ -170,7 +170,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
item.SetProviderId(MetadataProvider.Imdb, result.imdbID);
if (result.Year.Length > 0
- && int.TryParse(result.Year.Substring(0, Math.Min(result.Year.Length, 4)), NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedYear))
+ && int.TryParse(result.Year.AsSpan().Slice(0, Math.Min(result.Year.Length, 4)), NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedYear))
{
item.ProductionYear = parsedYear;
}
diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
index 9700f3b18..13098d140 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
@@ -62,7 +62,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
}
if (!string.IsNullOrEmpty(result.Year) && result.Year.Length >= 4
- && int.TryParse(result.Year.Substring(0, 4), NumberStyles.Number, _usCulture, out var year)
+ && int.TryParse(result.Year.AsSpan().Slice(0, 4), NumberStyles.Number, _usCulture, out var year)
&& year >= 0)
{
item.ProductionYear = year;
@@ -163,7 +163,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
}
if (!string.IsNullOrEmpty(result.Year) && result.Year.Length >= 4
- && int.TryParse(result.Year.Substring(0, 4), NumberStyles.Number, _usCulture, out var year)
+ && int.TryParse(result.Year.AsSpan().Slice(0, 4), NumberStyles.Number, _usCulture, out var year)
&& year >= 0)
{
item.ProductionYear = year;
diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs
index ced287d54..52fc53872 100644
--- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs
@@ -188,7 +188,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
for (var i = 0; i < episode.GuestStars.Length; ++i)
{
var currentActor = episode.GuestStars[i];
- var roleStartIndex = currentActor.IndexOf('(');
+ var roleStartIndex = currentActor.IndexOf('(', StringComparison.Ordinal);
if (roleStartIndex == -1)
{
@@ -207,7 +207,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
for (var j = i + 1; j < episode.GuestStars.Length; ++j)
{
var currentRole = episode.GuestStars[j];
- var roleEndIndex = currentRole.IndexOf(')');
+ var roleEndIndex = currentRole.IndexOf(')', StringComparison.Ordinal);
if (roleEndIndex == -1)
{
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
index 76d3f8224..58cbf9eef 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
@@ -251,9 +251,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
private static string GetPersonDataPath(IApplicationPaths appPaths, string tmdbId)
{
- var letter = tmdbId.GetMD5().ToString().Substring(0, 1);
+ var letter = tmdbId.GetMD5().ToString().AsSpan().Slice(0, 1);
- return Path.Combine(GetPersonsDataPath(appPaths), letter, tmdbId);
+ return Path.Join(GetPersonsDataPath(appPaths), letter, tmdbId);
}
internal static string GetPersonDataFilePath(IApplicationPaths appPaths, string tmdbId)
diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
index b2d99c1a1..b06464409 100644
--- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
+++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
@@ -222,8 +222,16 @@ namespace MediaBrowser.XbmcMetadata.Parsers
if (index != -1)
{
- var tmdbId = xml.Substring(index + srch.Length).TrimEnd('/').Split('-')[0];
- if (!string.IsNullOrWhiteSpace(tmdbId) && int.TryParse(tmdbId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value))
+ var tmdbId = xml.AsSpan().Slice(index + srch.Length).TrimEnd('/');
+ index = tmdbId.IndexOf('-');
+ if (index != -1)
+ {
+ tmdbId = tmdbId.Slice(0, index);
+ }
+
+ if (!tmdbId.IsEmpty
+ && !tmdbId.IsWhiteSpace()
+ && int.TryParse(tmdbId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value))
{
item.SetProviderId(MetadataProvider.Tmdb, value.ToString(UsCulture));
}
@@ -237,8 +245,10 @@ namespace MediaBrowser.XbmcMetadata.Parsers
if (index != -1)
{
- var tvdbId = xml.Substring(index + srch.Length).TrimEnd('/');
- if (!string.IsNullOrWhiteSpace(tvdbId) && int.TryParse(tvdbId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value))
+ var tvdbId = xml.AsSpan().Slice(index + srch.Length).TrimEnd('/');
+ if (!tvdbId.IsEmpty
+ && !tvdbId.IsWhiteSpace()
+ && int.TryParse(tvdbId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value))
{
item.SetProviderId(MetadataProvider.Tvdb, value.ToString(UsCulture));
}
@@ -442,8 +452,8 @@ namespace MediaBrowser.XbmcMetadata.Parsers
{
var val = reader.ReadElementContentAsString();
- var hasAspectRatio = item as IHasAspectRatio;
- if (!string.IsNullOrWhiteSpace(val) && hasAspectRatio != null)
+ if (!string.IsNullOrWhiteSpace(val)
+ && item is IHasAspectRatio hasAspectRatio)
{
hasAspectRatio.AspectRatio = val;
}
diff --git a/SharedVersion.cs b/SharedVersion.cs
index 6981c1ca9..d17074fc0 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,4 +1,4 @@
using System.Reflection;
-[assembly: AssemblyVersion("10.6.0")]
-[assembly: AssemblyFileVersion("10.6.0")]
+[assembly: AssemblyVersion("10.7.0")]
+[assembly: AssemblyFileVersion("10.7.0")]
diff --git a/build.yaml b/build.yaml
index 9e590e5a0..7c32d955c 100644
--- a/build.yaml
+++ b/build.yaml
@@ -1,7 +1,7 @@
---
# We just wrap `build` so this is really it
name: "jellyfin"
-version: "10.6.0"
+version: "10.7.0"
packages:
- debian.amd64
- debian.arm64
diff --git a/bump_version b/bump_version
index 46b7f86e0..1c943f691 100755
--- a/bump_version
+++ b/bump_version
@@ -4,6 +4,7 @@
set -o errexit
set -o pipefail
+set -o xtrace
usage() {
echo -e "bump_version - increase the shared version and generate changelogs"
@@ -58,7 +59,7 @@ sed -i "s/${old_version_sed}/${new_version}/g" ${debian_equivs_file}
debian_changelog_file="debian/changelog"
debian_changelog_temp="$( mktemp )"
# Create new temp file with our changelog
-echo -e "jellyfin (${new_version_deb}) unstable; urgency=medium
+echo -e "jellyfin-server (${new_version_deb}) unstable; urgency=medium
* New upstream version ${new_version}; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v${new_version}
diff --git a/debian/changelog b/debian/changelog
index d38d03805..184143fe9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+jellyfin-server (10.7.0-1) unstable; urgency=medium
+
+ * Forthcoming stable release
+
+ -- Jellyfin Packaging Team <packaging@jellyfin.org> Mon, 27 Jul 2020 19:09:45 -0400
+
jellyfin-server (10.6.0-2) unstable; urgency=medium
* Fix upgrade bug
diff --git a/debian/metapackage/jellyfin b/debian/metapackage/jellyfin
index 9a41eafae..026fcb821 100644
--- a/debian/metapackage/jellyfin
+++ b/debian/metapackage/jellyfin
@@ -5,7 +5,7 @@ Homepage: https://jellyfin.org
Standards-Version: 3.9.2
Package: jellyfin
-Version: 10.6.0
+Version: 10.7.0
Maintainer: Jellyfin Packaging Team <packaging@jellyfin.org>
Depends: jellyfin-server, jellyfin-web
Description: Provides the Jellyfin Free Software Media System
diff --git a/fedora/jellyfin.spec b/fedora/jellyfin.spec
index 9311864a6..b0a729a9e 100644
--- a/fedora/jellyfin.spec
+++ b/fedora/jellyfin.spec
@@ -7,7 +7,7 @@
%endif
Name: jellyfin
-Version: 10.6.0
+Version: 10.7.0
Release: 1%{?dist}
Summary: The Free Software Media System
License: GPLv3
@@ -139,6 +139,8 @@ fi
%systemd_postun_with_restart jellyfin.service
%changelog
+* Mon Jul 27 2020 Jellyfin Packaging Team <packaging@jellyfin.org>
+- Forthcoming stable release
* Mon Mar 23 2020 Jellyfin Packaging Team <packaging@jellyfin.org>
- Forthcoming stable release
* Fri Oct 11 2019 Jellyfin Packaging Team <packaging@jellyfin.org>