aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations')
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs6
-rw-r--r--Emby.Server.Implementations/Channels/ChannelManager.cs38
-rw-r--r--Emby.Server.Implementations/Data/SqliteItemRepository.cs21
-rw-r--r--Emby.Server.Implementations/Dto/DtoService.cs24
-rw-r--r--Emby.Server.Implementations/Emby.Server.Implementations.csproj6
-rw-r--r--Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs4
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs24
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs2
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs10
-rw-r--r--Emby.Server.Implementations/Library/SearchEngine.cs10
-rw-r--r--Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs79
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs20
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs126
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs6
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvManager.cs64
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs5
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs18
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs2
-rw-r--r--Emby.Server.Implementations/Localization/Core/cs.json2
-rw-r--r--Emby.Server.Implementations/Localization/Core/fr.json2
-rw-r--r--Emby.Server.Implementations/Localization/Core/ro.json4
-rw-r--r--Emby.Server.Implementations/Localization/Core/th.json3
-rw-r--r--Emby.Server.Implementations/Localization/Core/ug.json9
-rw-r--r--Emby.Server.Implementations/Net/UdpSocket.cs4
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs4
-rw-r--r--Emby.Server.Implementations/TV/TVSeriesManager.cs9
27 files changed, 296 insertions, 208 deletions
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 8ed51a194..e7efc81d7 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -47,6 +47,7 @@ using Emby.Server.Implementations.TV;
using Emby.Server.Implementations.Udp;
using Emby.Server.Implementations.Updates;
using Jellyfin.Api.Helpers;
+using Jellyfin.MediaEncoding.Hls.Playlist;
using Jellyfin.Networking.Configuration;
using Jellyfin.Networking.Manager;
using MediaBrowser.Common;
@@ -973,7 +974,7 @@ namespace Emby.Server.Implementations
yield return typeof(IServerApplicationHost).Assembly;
// Include composable parts in the Providers assembly
- yield return typeof(ProviderUtils).Assembly;
+ yield return typeof(ProviderManager).Assembly;
// Include composable parts in the Photos assembly
yield return typeof(PhotoProvider).Assembly;
@@ -999,6 +1000,9 @@ namespace Emby.Server.Implementations
// Network
yield return typeof(NetworkManager).Assembly;
+ // Hls
+ yield return typeof(DynamicHlsPlaylistGenerator).Assembly;
+
foreach (var i in GetAssembliesWithPartsInternal())
{
yield return i;
diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs
index 43c8a451b..a107e7a52 100644
--- a/Emby.Server.Implementations/Channels/ChannelManager.cs
+++ b/Emby.Server.Implementations/Channels/ChannelManager.cs
@@ -264,11 +264,10 @@ namespace Emby.Server.Implementations.Channels
}
}
- return new QueryResult<Channel>
- {
- Items = all,
- TotalRecordCount = totalCount
- };
+ return new QueryResult<Channel>(
+ query.StartIndex,
+ totalCount,
+ all);
}
/// <inheritdoc />
@@ -285,11 +284,10 @@ namespace Emby.Server.Implementations.Channels
// TODO Fix The co-variant conversion (internalResult.Items) between Folder[] and BaseItem[], this can generate runtime issues.
var returnItems = _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user);
- var result = new QueryResult<BaseItemDto>
- {
- Items = returnItems,
- TotalRecordCount = internalResult.TotalRecordCount
- };
+ var result = new QueryResult<BaseItemDto>(
+ query.StartIndex,
+ internalResult.TotalRecordCount,
+ returnItems);
return result;
}
@@ -333,7 +331,7 @@ namespace Emby.Server.Implementations.Channels
private Channel GetChannelEntity(IChannel channel)
{
- return GetChannel(GetInternalChannelId(channel.Name)) ?? GetChannel(channel, CancellationToken.None).Result;
+ return GetChannel(GetInternalChannelId(channel.Name)) ?? GetChannel(channel, CancellationToken.None).GetAwaiter().GetResult();
}
private MediaSourceInfo[] GetSavedMediaSources(BaseItem item)
@@ -620,11 +618,10 @@ namespace Emby.Server.Implementations.Channels
var returnItems = _dtoService.GetBaseItemDtos(items, query.DtoOptions, query.User);
- var result = new QueryResult<BaseItemDto>
- {
- Items = returnItems,
- TotalRecordCount = totalRecordCount
- };
+ var result = new QueryResult<BaseItemDto>(
+ query.StartIndex,
+ totalRecordCount,
+ returnItems);
return result;
}
@@ -786,11 +783,10 @@ namespace Emby.Server.Implementations.Channels
var returnItems = _dtoService.GetBaseItemDtos(internalResult.Items, query.DtoOptions, query.User);
- var result = new QueryResult<BaseItemDto>
- {
- Items = returnItems,
- TotalRecordCount = internalResult.TotalRecordCount
- };
+ var result = new QueryResult<BaseItemDto>(
+ query.StartIndex,
+ internalResult.TotalRecordCount,
+ returnItems);
return result;
}
diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
index 5ab9e02fe..1da9b4650 100644
--- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
@@ -2810,11 +2810,10 @@ namespace Emby.Server.Implementations.Data
if (!query.EnableTotalRecordCount || (!query.Limit.HasValue && (query.StartIndex ?? 0) == 0))
{
var returnList = GetItemList(query);
- return new QueryResult<BaseItem>
- {
- Items = returnList,
- TotalRecordCount = returnList.Count
- };
+ return new QueryResult<BaseItem>(
+ query.StartIndex,
+ returnList.Count,
+ returnList);
}
var now = DateTime.UtcNow;
@@ -2978,6 +2977,7 @@ namespace Emby.Server.Implementations.Data
ReadTransactionMode);
}
+ result.StartIndex = query.StartIndex ?? 0;
result.Items = list;
return result;
}
@@ -3265,11 +3265,10 @@ namespace Emby.Server.Implementations.Data
if (!query.EnableTotalRecordCount || (!query.Limit.HasValue && (query.StartIndex ?? 0) == 0))
{
var returnList = GetItemIdsList(query);
- return new QueryResult<Guid>
- {
- Items = returnList,
- TotalRecordCount = returnList.Count
- };
+ return new QueryResult<Guid>(
+ query.StartIndex,
+ returnList.Count,
+ returnList);
}
var now = DateTime.UtcNow;
@@ -3395,6 +3394,7 @@ namespace Emby.Server.Implementations.Data
LogQueryTime("GetItemIds", commandText, now);
+ result.StartIndex = query.StartIndex ?? 0;
result.Items = list;
return result;
}
@@ -5599,6 +5599,7 @@ AND Type = @InternalPersonType)");
result.TotalRecordCount = list.Count;
}
+ result.StartIndex = query.StartIndex ?? 0;
result.Items = list;
return result;
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs
index 7ba34e74a..f5ca006dd 100644
--- a/Emby.Server.Implementations/Dto/DtoService.cs
+++ b/Emby.Server.Implementations/Dto/DtoService.cs
@@ -458,11 +458,6 @@ namespace Emby.Server.Implementations.Dto
}
}
- private string GetDtoId(BaseItem item)
- {
- return item.Id.ToString("N", CultureInfo.InvariantCulture);
- }
-
private void SetMusicVideoProperties(BaseItemDto dto, MusicVideo item)
{
if (!string.IsNullOrEmpty(item.Album))
@@ -584,7 +579,7 @@ namespace Emby.Server.Implementations.Dto
if (dictionary.TryGetValue(person.Name, out Person entity))
{
baseItemPerson.PrimaryImageTag = GetTagAndFillBlurhash(dto, entity, ImageType.Primary);
- baseItemPerson.Id = entity.Id.ToString("N", CultureInfo.InvariantCulture);
+ baseItemPerson.Id = entity.Id;
if (dto.ImageBlurHashes != null)
{
// Only add BlurHash for the person's image.
@@ -1102,12 +1097,13 @@ namespace Emby.Server.Implementations.Dto
if (options.ContainsField(ItemFields.LocalTrailerCount))
{
- allExtras ??= item.GetExtras().ToArray();
- dto.LocalTrailerCount = allExtras.Count(i => i.ExtraType == ExtraType.Trailer);
-
if (item is IHasTrailers hasTrailers)
{
- dto.LocalTrailerCount += hasTrailers.GetTrailerCount();
+ dto.LocalTrailerCount = hasTrailers.GetTrailerCount();
+ }
+ else
+ {
+ dto.LocalTrailerCount = (allExtras ?? item.GetExtras()).Count(i => i.ExtraType == ExtraType.Trailer);
}
}
@@ -1323,7 +1319,7 @@ namespace Emby.Server.Implementations.Dto
if (image != null)
{
- dto.ParentLogoItemId = GetDtoId(parent);
+ dto.ParentLogoItemId = parent.Id;
dto.ParentLogoImageTag = GetTagAndFillBlurhash(dto, parent, image);
}
}
@@ -1334,7 +1330,7 @@ namespace Emby.Server.Implementations.Dto
if (image != null)
{
- dto.ParentArtItemId = GetDtoId(parent);
+ dto.ParentArtItemId = parent.Id;
dto.ParentArtImageTag = GetTagAndFillBlurhash(dto, parent, image);
}
}
@@ -1345,7 +1341,7 @@ namespace Emby.Server.Implementations.Dto
if (image != null)
{
- dto.ParentThumbItemId = GetDtoId(parent);
+ dto.ParentThumbItemId = parent.Id;
dto.ParentThumbImageTag = GetTagAndFillBlurhash(dto, parent, image);
}
}
@@ -1356,7 +1352,7 @@ namespace Emby.Server.Implementations.Dto
if (images.Count > 0)
{
- dto.ParentBackdropItemId = GetDtoId(parent);
+ dto.ParentBackdropItemId = parent.Id;
dto.ParentBackdropImageTags = GetTagsAndFillBlurhashes(dto, parent, ImageType.Backdrop, images);
}
}
diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index 1e09a98cf..3226a3b19 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -31,7 +31,7 @@
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.1" />
<PackageReference Include="Mono.Nat" Version="3.0.2" />
- <PackageReference Include="prometheus-net.DotNetRuntime" Version="4.2.2" />
+ <PackageReference Include="prometheus-net.DotNetRuntime" Version="4.2.3" />
<PackageReference Include="sharpcompress" Version="0.30.1" />
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="3.1.0" />
<PackageReference Include="DotNet.Glob" Version="3.1.3" />
@@ -55,6 +55,10 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs
index 7958eb8f5..8a0e627b9 100644
--- a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs
+++ b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs
@@ -42,6 +42,10 @@ namespace Emby.Server.Implementations.Images
{
includeItemTypes = new[] { BaseItemKind.MusicAlbum };
}
+ else if (string.Equals(viewType, CollectionType.MusicVideos, StringComparison.Ordinal))
+ {
+ includeItemTypes = new[] { BaseItemKind.MusicVideo };
+ }
else if (string.Equals(viewType, CollectionType.Books, StringComparison.Ordinal))
{
includeItemTypes = new[] { BaseItemKind.Book, BaseItemKind.AudioBook };
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index bd0c178fd..064fd2372 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -1360,10 +1360,10 @@ namespace Emby.Server.Implementations.Library
return _itemRepository.GetItems(query);
}
- return new QueryResult<BaseItem>
- {
- Items = _itemRepository.GetItemList(query)
- };
+ return new QueryResult<BaseItem>(
+ query.StartIndex,
+ null,
+ _itemRepository.GetItemList(query));
}
public List<Guid> GetItemIds(InternalItemsQuery query)
@@ -1493,10 +1493,10 @@ namespace Emby.Server.Implementations.Library
return _itemRepository.GetItems(query);
}
- return new QueryResult<BaseItem>
- {
- Items = _itemRepository.GetItemList(query)
- };
+ return new QueryResult<BaseItem>(
+ query.StartIndex,
+ null,
+ _itemRepository.GetItemList(query));
}
private void SetTopParentIdsOrAncestors(InternalItemsQuery query, List<BaseItem> parents)
@@ -2014,16 +2014,16 @@ namespace Emby.Server.Implementations.Library
public Task UpdateItemAsync(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken)
=> UpdateItemsAsync(new[] { item }, parent, updateReason, cancellationToken);
- public Task RunMetadataSavers(BaseItem item, ItemUpdateType updateReason)
+ public async Task RunMetadataSavers(BaseItem item, ItemUpdateType updateReason)
{
if (item.IsFileProtocol)
{
- ProviderManager.SaveMetadata(item, updateReason);
+ await ProviderManager.SaveMetadataAsync(item, updateReason).ConfigureAwait(false);
}
item.DateLastSaved = DateTime.UtcNow;
- return UpdateImagesAsync(item, updateReason >= ItemUpdateType.ImageUpdate);
+ await UpdateImagesAsync(item, updateReason >= ItemUpdateType.ImageUpdate).ConfigureAwait(false);
}
/// <summary>
@@ -2686,7 +2686,7 @@ namespace Emby.Server.Implementations.Library
};
}
- public IEnumerable<BaseItem> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
+ public IEnumerable<BaseItem> FindExtras(BaseItem owner, IReadOnlyList<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
{
var ownerVideoInfo = VideoResolver.Resolve(owner.Path, owner.IsFolder, _namingOptions);
if (ownerVideoInfo == null)
diff --git a/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs b/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs
index 3d06ceb5e..807913b5d 100644
--- a/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs
@@ -20,7 +20,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
private readonly IItemResolver[] _videoResolvers;
/// <summary>
- /// Initializes an new instance of the <see cref="ExtraResolver"/> class.
+ /// Initializes a new instance of the <see cref="ExtraResolver"/> class.
/// </summary>
/// <param name="namingOptions">An instance of <see cref="NamingOptions"/>.</param>
public ExtraResolver(NamingOptions namingOptions)
diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
index 1a9295dc8..be1460928 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
@@ -32,7 +32,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
CollectionType.Movies,
CollectionType.HomeVideos,
CollectionType.MusicVideos,
- CollectionType.Movies,
+ CollectionType.TvShows,
CollectionType.Photos
};
@@ -128,10 +128,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
return movie?.ExtraType == null ? movie : null;
}
- // Owned items will be caught by the video extra resolver
if (args.Parent == null)
{
- return null;
+ return base.Resolve(args);
}
if (IsInvalid(args.Parent, collectionType))
@@ -222,6 +221,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
return ResolveVideos<Movie>(parent, files, true, collectionType, true);
}
+ if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
+ {
+ return ResolveVideos<Episode>(parent, files, true, collectionType, true);
+ }
+
return null;
}
diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs
index 55911933a..70d9cbc98 100644
--- a/Emby.Server.Implementations/Library/SearchEngine.cs
+++ b/Emby.Server.Implementations/Library/SearchEngine.cs
@@ -48,12 +48,10 @@ namespace Emby.Server.Implementations.Library
results = results.GetRange(0, Math.Min(query.Limit.Value, results.Count));
}
- return new QueryResult<SearchHintInfo>
- {
- TotalRecordCount = totalRecordCount,
-
- Items = results
- };
+ return new QueryResult<SearchHintInfo>(
+ query.StartIndex,
+ totalRecordCount,
+ results);
}
private static void AddIfMissing(List<BaseItemKind> list, BaseItemKind value)
diff --git a/Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs b/Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs
new file mode 100644
index 000000000..320685b1f
--- /dev/null
+++ b/Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Data.Enums;
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Querying;
+using Microsoft.Extensions.Logging;
+
+namespace Emby.Server.Implementations.Library;
+
+/// <summary>
+/// The splashscreen post scan task.
+/// </summary>
+public class SplashscreenPostScanTask : ILibraryPostScanTask
+{
+ private readonly IItemRepository _itemRepository;
+ private readonly IImageEncoder _imageEncoder;
+ private readonly ILogger<SplashscreenPostScanTask> _logger;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SplashscreenPostScanTask"/> class.
+ /// </summary>
+ /// <param name="itemRepository">Instance of the <see cref="IItemRepository"/> interface.</param>
+ /// <param name="imageEncoder">Instance of the <see cref="IImageEncoder"/> interface.</param>
+ /// <param name="logger">Instance of the <see cref="ILogger{SplashscreenPostScanTask}"/> interface.</param>
+ public SplashscreenPostScanTask(
+ IItemRepository itemRepository,
+ IImageEncoder imageEncoder,
+ ILogger<SplashscreenPostScanTask> logger)
+ {
+ _itemRepository = itemRepository;
+ _imageEncoder = imageEncoder;
+ _logger = logger;
+ }
+
+ /// <inheritdoc />
+ public Task Run(IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ var posters = GetItemsWithImageType(ImageType.Primary).Select(x => x.GetImages(ImageType.Primary).First().Path).ToList();
+ var backdrops = GetItemsWithImageType(ImageType.Thumb).Select(x => x.GetImages(ImageType.Thumb).First().Path).ToList();
+ if (backdrops.Count == 0)
+ {
+ // Thumb images fit better because they include the title in the image but are not provided with TMDb.
+ // Using backdrops as a fallback to generate an image at all
+ _logger.LogDebug("No thumb images found. Using backdrops to generate splashscreen");
+ backdrops = GetItemsWithImageType(ImageType.Backdrop).Select(x => x.GetImages(ImageType.Backdrop).First().Path).ToList();
+ }
+
+ _imageEncoder.CreateSplashscreen(posters, backdrops);
+ return Task.CompletedTask;
+ }
+
+ private IReadOnlyList<BaseItem> GetItemsWithImageType(ImageType imageType)
+ {
+ // TODO make included libraries configurable
+ return _itemRepository.GetItemList(new InternalItemsQuery
+ {
+ CollapseBoxSetItems = false,
+ Recursive = true,
+ DtoOptions = new DtoOptions(false),
+ ImageTypes = new[] { imageType },
+ Limit = 30,
+ // TODO max parental rating configurable
+ MaxParentalRating = 10,
+ OrderBy = new[]
+ {
+ (ItemSortBy.Random, SortOrder.Ascending)
+ },
+ IncludeItemTypes = new[] { BaseItemKind.Movie, BaseItemKind.Series }
+ });
+ }
+}
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
index 6937cc097..b2d25fdae 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
@@ -46,7 +46,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile)));
- using (var output = new FileStream(targetFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
+ await using (var output = new FileStream(targetFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
{
onStarted();
@@ -56,14 +56,16 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
using var durationToken = new CancellationTokenSource(duration);
using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token);
var linkedCancellationToken = cancellationTokenSource.Token;
-
- await using var fileStream = new ProgressiveFileStream(directStreamProvider.GetStream());
- await _streamHelper.CopyToAsync(
- fileStream,
- output,
- IODefaults.CopyToBufferSize,
- 1000,
- linkedCancellationToken).ConfigureAwait(false);
+ var fileStream = new ProgressiveFileStream(directStreamProvider.GetStream());
+ await using (fileStream.ConfigureAwait(false))
+ {
+ await _streamHelper.CopyToAsync(
+ fileStream,
+ output,
+ IODefaults.CopyToBufferSize,
+ 1000,
+ linkedCancellationToken).ConfigureAwait(false);
+ }
}
_logger.LogInformation("Recording completed: {FilePath}", targetFile);
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index e7834ffd6..bba584854 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -1819,16 +1819,16 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
if (timer.IsProgramSeries)
{
- SaveSeriesNfo(timer, seriesPath);
- SaveVideoNfo(timer, recordingPath, program, false);
+ await SaveSeriesNfoAsync(timer, seriesPath).ConfigureAwait(false);
+ await SaveVideoNfoAsync(timer, recordingPath, program, false).ConfigureAwait(false);
}
else if (!timer.IsMovie || timer.IsSports || timer.IsNews)
{
- SaveVideoNfo(timer, recordingPath, program, true);
+ await SaveVideoNfoAsync(timer, recordingPath, program, true).ConfigureAwait(false);
}
else
{
- SaveVideoNfo(timer, recordingPath, program, false);
+ await SaveVideoNfoAsync(timer, recordingPath, program, false).ConfigureAwait(false);
}
await SaveRecordingImages(recordingPath, program).ConfigureAwait(false);
@@ -1839,7 +1839,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
}
- private void SaveSeriesNfo(TimerInfo timer, string seriesPath)
+ private async Task SaveSeriesNfoAsync(TimerInfo timer, string seriesPath)
{
var nfoPath = Path.Combine(seriesPath, "tvshow.nfo");
@@ -1848,61 +1848,62 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return;
}
- using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
+ await using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
{
var settings = new XmlWriterSettings
{
Indent = true,
- Encoding = Encoding.UTF8
+ Encoding = Encoding.UTF8,
+ Async = true
};
- using (var writer = XmlWriter.Create(stream, settings))
+ await using (var writer = XmlWriter.Create(stream, settings))
{
- writer.WriteStartDocument(true);
- writer.WriteStartElement("tvshow");
+ await writer.WriteStartDocumentAsync(true).ConfigureAwait(false);
+ await writer.WriteStartElementAsync(null, "tvshow", null).ConfigureAwait(false);
string id;
if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Tvdb.ToString(), out id))
{
- writer.WriteElementString("id", id);
+ await writer.WriteElementStringAsync(null, "id", null, id).ConfigureAwait(false);
}
if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out id))
{
- writer.WriteElementString("imdb_id", id);
+ await writer.WriteElementStringAsync(null, "imdb_id", null, id).ConfigureAwait(false);
}
if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Tmdb.ToString(), out id))
{
- writer.WriteElementString("tmdbid", id);
+ await writer.WriteElementStringAsync(null, "tmdbid", null, id).ConfigureAwait(false);
}
if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Zap2It.ToString(), out id))
{
- writer.WriteElementString("zap2itid", id);
+ await writer.WriteElementStringAsync(null, "zap2itid", null, id).ConfigureAwait(false);
}
if (!string.IsNullOrWhiteSpace(timer.Name))
{
- writer.WriteElementString("title", timer.Name);
+ await writer.WriteElementStringAsync(null, "title", null, timer.Name).ConfigureAwait(false);
}
if (!string.IsNullOrWhiteSpace(timer.OfficialRating))
{
- writer.WriteElementString("mpaa", timer.OfficialRating);
+ await writer.WriteElementStringAsync(null, "mpaa", null, timer.OfficialRating).ConfigureAwait(false);
}
foreach (var genre in timer.Genres)
{
- writer.WriteElementString("genre", genre);
+ await writer.WriteElementStringAsync(null, "genre", null, genre).ConfigureAwait(false);
}
- writer.WriteEndElement();
- writer.WriteEndDocument();
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
+ await writer.WriteEndDocumentAsync().ConfigureAwait(false);
}
}
}
- private void SaveVideoNfo(TimerInfo timer, string recordingPath, BaseItem item, bool lockData)
+ private async Task SaveVideoNfoAsync(TimerInfo timer, string recordingPath, BaseItem item, bool lockData)
{
var nfoPath = Path.ChangeExtension(recordingPath, ".nfo");
@@ -1911,29 +1912,30 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return;
}
- using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
+ await using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
{
var settings = new XmlWriterSettings
{
Indent = true,
- Encoding = Encoding.UTF8
+ Encoding = Encoding.UTF8,
+ Async = true
};
var options = _config.GetNfoConfiguration();
var isSeriesEpisode = timer.IsProgramSeries;
- using (var writer = XmlWriter.Create(stream, settings))
+ await using (var writer = XmlWriter.Create(stream, settings))
{
- writer.WriteStartDocument(true);
+ await writer.WriteStartDocumentAsync(true).ConfigureAwait(false);
if (isSeriesEpisode)
{
- writer.WriteStartElement("episodedetails");
+ await writer.WriteStartElementAsync(null, "episodedetails", null).ConfigureAwait(false);
if (!string.IsNullOrWhiteSpace(timer.EpisodeTitle))
{
- writer.WriteElementString("title", timer.EpisodeTitle);
+ await writer.WriteElementStringAsync(null, "title", null, timer.EpisodeTitle).ConfigureAwait(false);
}
var premiereDate = item.PremiereDate ?? (!timer.IsRepeat ? DateTime.UtcNow : null);
@@ -1942,76 +1944,84 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
var formatString = options.ReleaseDateFormat;
- writer.WriteElementString(
+ await writer.WriteElementStringAsync(
+ null,
"aired",
- premiereDate.Value.ToLocalTime().ToString(formatString, CultureInfo.InvariantCulture));
+ null,
+ premiereDate.Value.ToLocalTime().ToString(formatString, CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
if (item.IndexNumber.HasValue)
{
- writer.WriteElementString("episode", item.IndexNumber.Value.ToString(CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "episode", null, item.IndexNumber.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
if (item.ParentIndexNumber.HasValue)
{
- writer.WriteElementString("season", item.ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "season", null, item.ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
}
else
{
- writer.WriteStartElement("movie");
+ await writer.WriteStartElementAsync(null, "movie", null);
if (!string.IsNullOrWhiteSpace(item.Name))
{
- writer.WriteElementString("title", item.Name);
+ await writer.WriteElementStringAsync(null, "title", null, item.Name).ConfigureAwait(false);
}
if (!string.IsNullOrWhiteSpace(item.OriginalTitle))
{
- writer.WriteElementString("originaltitle", item.OriginalTitle);
+ await writer.WriteElementStringAsync(null, "originaltitle", null, item.OriginalTitle).ConfigureAwait(false);
}
if (item.PremiereDate.HasValue)
{
var formatString = options.ReleaseDateFormat;
- writer.WriteElementString(
+ await writer.WriteElementStringAsync(
+ null,
"premiered",
- item.PremiereDate.Value.ToLocalTime().ToString(formatString, CultureInfo.InvariantCulture));
- writer.WriteElementString(
+ null,
+ item.PremiereDate.Value.ToLocalTime().ToString(formatString, CultureInfo.InvariantCulture)).ConfigureAwait(false);
+ await writer.WriteElementStringAsync(
+ null,
"releasedate",
- item.PremiereDate.Value.ToLocalTime().ToString(formatString, CultureInfo.InvariantCulture));
+ null,
+ item.PremiereDate.Value.ToLocalTime().ToString(formatString, CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
}
- writer.WriteElementString(
+ await writer.WriteElementStringAsync(
+ null,
"dateadded",
- DateTime.Now.ToString(DateAddedFormat, CultureInfo.InvariantCulture));
+ null,
+ DateTime.Now.ToString(DateAddedFormat, CultureInfo.InvariantCulture)).ConfigureAwait(false);
if (item.ProductionYear.HasValue)
{
- writer.WriteElementString("year", item.ProductionYear.Value.ToString(CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "year", null, item.ProductionYear.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
if (!string.IsNullOrEmpty(item.OfficialRating))
{
- writer.WriteElementString("mpaa", item.OfficialRating);
+ await writer.WriteElementStringAsync(null, "mpaa", null, item.OfficialRating).ConfigureAwait(false);
}
var overview = (item.Overview ?? string.Empty)
.StripHtml()
.Replace("&quot;", "'", StringComparison.Ordinal);
- writer.WriteElementString("plot", overview);
+ await writer.WriteElementStringAsync(null, "plot", null, overview).ConfigureAwait(false);
if (item.CommunityRating.HasValue)
{
- writer.WriteElementString("rating", item.CommunityRating.Value.ToString(CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "rating", null, item.CommunityRating.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
foreach (var genre in item.Genres)
{
- writer.WriteElementString("genre", genre);
+ await writer.WriteElementStringAsync(null, "genre", null, genre).ConfigureAwait(false);
}
var people = item.Id.Equals(Guid.Empty) ? new List<PersonInfo>() : _libraryManager.GetPeople(item);
@@ -2023,7 +2033,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
foreach (var person in directors)
{
- writer.WriteElementString("director", person);
+ await writer.WriteElementStringAsync(null, "director", null, person).ConfigureAwait(false);
}
var writers = people
@@ -2034,19 +2044,19 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
foreach (var person in writers)
{
- writer.WriteElementString("writer", person);
+ await writer.WriteElementStringAsync(null, "writer", null, person).ConfigureAwait(false);
}
foreach (var person in writers)
{
- writer.WriteElementString("credits", person);
+ await writer.WriteElementStringAsync(null, "credits", null, person).ConfigureAwait(false);
}
var tmdbCollection = item.GetProviderId(MetadataProvider.TmdbCollection);
if (!string.IsNullOrEmpty(tmdbCollection))
{
- writer.WriteElementString("collectionnumber", tmdbCollection);
+ await writer.WriteElementStringAsync(null, "collectionnumber", null, tmdbCollection).ConfigureAwait(false);
}
var imdb = item.GetProviderId(MetadataProvider.Imdb);
@@ -2054,10 +2064,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
if (!isSeriesEpisode)
{
- writer.WriteElementString("id", imdb);
+ await writer.WriteElementStringAsync(null, "id", null, imdb).ConfigureAwait(false);
}
- writer.WriteElementString("imdbid", imdb);
+ await writer.WriteElementStringAsync(null, "imdbid", null, imdb).ConfigureAwait(false);
// No need to lock if we have identified the content already
lockData = false;
@@ -2066,7 +2076,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var tvdb = item.GetProviderId(MetadataProvider.Tvdb);
if (!string.IsNullOrEmpty(tvdb))
{
- writer.WriteElementString("tvdbid", tvdb);
+ await writer.WriteElementStringAsync(null, "tvdbid", null, tvdb).ConfigureAwait(false);
// No need to lock if we have identified the content already
lockData = false;
@@ -2075,7 +2085,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var tmdb = item.GetProviderId(MetadataProvider.Tmdb);
if (!string.IsNullOrEmpty(tmdb))
{
- writer.WriteElementString("tmdbid", tmdb);
+ await writer.WriteElementStringAsync(null, "tmdbid", null, tmdb).ConfigureAwait(false);
// No need to lock if we have identified the content already
lockData = false;
@@ -2083,26 +2093,26 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
if (lockData)
{
- writer.WriteElementString("lockdata", true.ToString(CultureInfo.InvariantCulture).ToLowerInvariant());
+ await writer.WriteElementStringAsync(null, "lockdata", null, "true").ConfigureAwait(false);
}
if (item.CriticRating.HasValue)
{
- writer.WriteElementString("criticrating", item.CriticRating.Value.ToString(CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "criticrating", null, item.CriticRating.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
if (!string.IsNullOrWhiteSpace(item.Tagline))
{
- writer.WriteElementString("tagline", item.Tagline);
+ await writer.WriteElementStringAsync(null, "tagline", null, item.Tagline).ConfigureAwait(false);
}
foreach (var studio in item.Studios)
{
- writer.WriteElementString("studio", studio);
+ await writer.WriteElementStringAsync(null, "studio", null, studio).ConfigureAwait(false);
}
- writer.WriteEndElement();
- writer.WriteEndDocument();
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
+ await writer.WriteEndDocumentAsync().ConfigureAwait(false);
}
}
}
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
index 7fa47e7db..f1d4b6097 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
@@ -29,7 +29,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
private readonly ILogger _logger;
private readonly IMediaEncoder _mediaEncoder;
private readonly IServerApplicationPaths _appPaths;
- private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>();
+ private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
private readonly IServerConfigurationManager _serverConfigurationManager;
private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
private bool _hasExited;
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
index 323b96021..fbce7af2d 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
@@ -176,7 +176,7 @@ namespace Emby.Server.Implementations.LiveTv
try
{
dto.ParentThumbImageTag = _imageProcessor.GetImageCacheTag(librarySeries, image);
- dto.ParentThumbItemId = librarySeries.Id.ToString("N", CultureInfo.InvariantCulture);
+ dto.ParentThumbItemId = librarySeries.Id;
}
catch (Exception ex)
{
@@ -193,7 +193,7 @@ namespace Emby.Server.Implementations.LiveTv
{
_imageProcessor.GetImageCacheTag(librarySeries, image)
};
- dto.ParentBackdropItemId = librarySeries.Id.ToString("N", CultureInfo.InvariantCulture);
+ dto.ParentBackdropItemId = librarySeries.Id;
}
catch (Exception ex)
{
@@ -240,7 +240,7 @@ namespace Emby.Server.Implementations.LiveTv
_imageProcessor.GetImageCacheTag(program, image)
};
- dto.ParentBackdropItemId = program.Id.ToString("N", CultureInfo.InvariantCulture);
+ dto.ParentBackdropItemId = program.Id;
}
catch (Exception ex)
{
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index aa3598c8b..6a9a3077c 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -857,11 +857,10 @@ namespace Emby.Server.Implementations.LiveTv
var returnArray = _dtoService.GetBaseItemDtos(queryResult.Items, options, user);
- return new QueryResult<BaseItemDto>
- {
- Items = returnArray,
- TotalRecordCount = queryResult.TotalRecordCount
- };
+ return new QueryResult<BaseItemDto>(
+ query.StartIndex,
+ queryResult.TotalRecordCount,
+ returnArray);
}
public QueryResult<BaseItem> GetRecommendedProgramsInternal(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken)
@@ -910,29 +909,27 @@ namespace Emby.Server.Implementations.LiveTv
programs = programs.Take(query.Limit.Value);
}
- return new QueryResult<BaseItem>
- {
- Items = programs.ToArray(),
- TotalRecordCount = totalCount
- };
+ return new QueryResult<BaseItem>(
+ query.StartIndex,
+ totalCount,
+ programs.ToArray());
}
- public QueryResult<BaseItemDto> GetRecommendedPrograms(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken)
+ public Task<QueryResult<BaseItemDto>> GetRecommendedProgramsAsync(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken)
{
if (!(query.IsAiring ?? false))
{
- return GetPrograms(query, options, cancellationToken).Result;
+ return GetPrograms(query, options, cancellationToken);
}
RemoveFields(options);
var internalResult = GetRecommendedProgramsInternal(query, options, cancellationToken);
- return new QueryResult<BaseItemDto>
- {
- Items = _dtoService.GetBaseItemDtos(internalResult.Items, options, query.User),
- TotalRecordCount = internalResult.TotalRecordCount
- };
+ return Task.FromResult(new QueryResult<BaseItemDto>(
+ query.StartIndex,
+ internalResult.TotalRecordCount,
+ _dtoService.GetBaseItemDtos(internalResult.Items, options, query.User)));
}
private int GetRecommendationScore(LiveTvProgram program, User user, bool factorChannelWatchCount)
@@ -1541,11 +1538,10 @@ namespace Emby.Server.Implementations.LiveTv
var returnArray = _dtoService.GetBaseItemDtos(internalResult.Items, options, user);
- return new QueryResult<BaseItemDto>
- {
- Items = returnArray,
- TotalRecordCount = internalResult.TotalRecordCount
- };
+ return new QueryResult<BaseItemDto>(
+ query.StartIndex,
+ internalResult.TotalRecordCount,
+ returnArray);
}
private async Task<QueryResult<TimerInfo>> GetTimersInternal(TimerQuery query, CancellationToken cancellationToken)
@@ -1615,11 +1611,7 @@ namespace Emby.Server.Implementations.LiveTv
.OrderBy(i => i.StartDate)
.ToArray();
- return new QueryResult<TimerInfo>
- {
- Items = returnArray,
- TotalRecordCount = returnArray.Length
- };
+ return new QueryResult<TimerInfo>(returnArray);
}
public async Task<QueryResult<TimerInfoDto>> GetTimers(TimerQuery query, CancellationToken cancellationToken)
@@ -1701,11 +1693,7 @@ namespace Emby.Server.Implementations.LiveTv
.OrderBy(i => i.StartDate)
.ToArray();
- return new QueryResult<TimerInfoDto>
- {
- Items = returnArray,
- TotalRecordCount = returnArray.Length
- };
+ return new QueryResult<TimerInfoDto>(returnArray);
}
public async Task CancelTimer(string id)
@@ -1801,11 +1789,7 @@ namespace Emby.Server.Implementations.LiveTv
.Select(i => i.Item1)
.ToArray();
- return new QueryResult<SeriesTimerInfo>
- {
- Items = returnArray,
- TotalRecordCount = returnArray.Length
- };
+ return new QueryResult<SeriesTimerInfo>(returnArray);
}
public async Task<QueryResult<SeriesTimerInfoDto>> GetSeriesTimers(SeriesTimerQuery query, CancellationToken cancellationToken)
@@ -1855,11 +1839,7 @@ namespace Emby.Server.Implementations.LiveTv
})
.ToArray();
- return new QueryResult<SeriesTimerInfoDto>
- {
- Items = returnArray,
- TotalRecordCount = returnArray.Length
- };
+ return new QueryResult<SeriesTimerInfoDto>(returnArray);
}
public BaseItem GetLiveTvChannel(TimerInfo timer, ILiveTvService service)
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
index a5edd35cc..6195c7648 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
@@ -133,7 +133,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
}
}
- var taskCompletionSource = new TaskCompletionSource<bool>();
+ var taskCompletionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
_ = StartStreaming(
udpClient,
@@ -186,7 +186,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
var resolved = false;
- using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read))
+ var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read);
+ await using (fileStream.ConfigureAwait(false))
{
while (true)
{
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
index 5581ba87c..2748794b3 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
@@ -97,7 +97,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
public Stream GetStream()
{
- var stream = GetInputStream(TempFilePath);
+ var stream = new FileStream(
+ TempFilePath,
+ FileMode.Open,
+ FileAccess.Read,
+ FileShare.ReadWrite,
+ IODefaults.FileStreamBufferSize,
+ FileOptions.SequentialScan | FileOptions.Asynchronous);
+
bool seekFile = (DateTime.UtcNow - DateOpened).TotalSeconds > 10;
if (seekFile)
{
@@ -107,15 +114,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
return stream;
}
- protected FileStream GetInputStream(string path)
- => new FileStream(
- path,
- FileMode.Open,
- FileAccess.Read,
- FileShare.ReadWrite,
- IODefaults.FileStreamBufferSize,
- FileOptions.SequentialScan | FileOptions.Asynchronous);
-
protected async Task DeleteTempFiles(string path, int retryCount = 0)
{
if (retryCount == 0)
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
index ab4beb15b..e84e1e074 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
@@ -73,7 +73,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
SetTempFilePath("ts");
- var taskCompletionSource = new TaskCompletionSource<bool>();
+ var taskCompletionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
_ = StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token);
diff --git a/Emby.Server.Implementations/Localization/Core/cs.json b/Emby.Server.Implementations/Localization/Core/cs.json
index 25f51db16..65a31e676 100644
--- a/Emby.Server.Implementations/Localization/Core/cs.json
+++ b/Emby.Server.Implementations/Localization/Core/cs.json
@@ -23,7 +23,7 @@
"HeaderFavoriteShows": "Oblíbené seriály",
"HeaderFavoriteSongs": "Oblíbená hudba",
"HeaderLiveTV": "Televize",
- "HeaderNextUp": "Nadcházející",
+ "HeaderNextUp": "Další díly",
"HeaderRecordingGroups": "Skupiny nahrávek",
"HomeVideos": "Domácí videa",
"Inherit": "Zdědit",
diff --git a/Emby.Server.Implementations/Localization/Core/fr.json b/Emby.Server.Implementations/Localization/Core/fr.json
index bfafe7650..e56ae6071 100644
--- a/Emby.Server.Implementations/Localization/Core/fr.json
+++ b/Emby.Server.Implementations/Localization/Core/fr.json
@@ -1,7 +1,7 @@
{
"Albums": "Albums",
"AppDeviceValues": "Application : {0}, Appareil : {1}",
- "Application": "Applications",
+ "Application": "Application",
"Artists": "Artistes",
"AuthenticationSucceededWithUserName": "{0} authentifié avec succès",
"Books": "Livres",
diff --git a/Emby.Server.Implementations/Localization/Core/ro.json b/Emby.Server.Implementations/Localization/Core/ro.json
index f8fad7b63..8af5449a7 100644
--- a/Emby.Server.Implementations/Localization/Core/ro.json
+++ b/Emby.Server.Implementations/Localization/Core/ro.json
@@ -117,5 +117,7 @@
"TaskCleanActivityLog": "Curăță Jurnalul de Activitate",
"Undefined": "Nedefinit",
"Forced": "Forțat",
- "Default": "Implicit"
+ "Default": "Implicit",
+ "TaskOptimizeDatabaseDescription": "Compactează baza de date și trunchiază spațiul liber. Rularea acestei sarcini după scanarea bibliotecii sau după efectuarea altor modificări care implică modificări ale bazei de date poate îmbunătăți performanța.",
+ "TaskOptimizeDatabase": "Optimizează baza de date"
}
diff --git a/Emby.Server.Implementations/Localization/Core/th.json b/Emby.Server.Implementations/Localization/Core/th.json
index 89fbb84b6..bed67fa4f 100644
--- a/Emby.Server.Implementations/Localization/Core/th.json
+++ b/Emby.Server.Implementations/Localization/Core/th.json
@@ -118,5 +118,6 @@
"TaskCleanActivityLog": "ล้างบันทึกกิจกรรม",
"Undefined": "ไม่ได้กำหนด",
"Forced": "บังคับใช้",
- "TaskOptimizeDatabase": "ปรับฐานข้อมูลให้เหมาะสม"
+ "TaskOptimizeDatabase": "ปรับปรุงประสิทธิภาพฐานข้อมูล",
+ "TaskOptimizeDatabaseDescription": "ลดขนาดการจัดเก็บฐานข้อมูล ใช้งานคำสั่งนี้หลังจากสแกนไลบรารีหรือหลังจากการเปลี่ยนแปลงฐานข้อมูล อาจจะทำให้ระบบทำงานเร็วขึ้น"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ug.json b/Emby.Server.Implementations/Localization/Core/ug.json
new file mode 100644
index 000000000..aea93c7fa
--- /dev/null
+++ b/Emby.Server.Implementations/Localization/Core/ug.json
@@ -0,0 +1,9 @@
+{
+ "ChapterNameValue": "باب {0}",
+ "Channels": "قانال",
+ "CameraImageUploadedFrom": "{0} ئورۇندىن يېڭى سۈرەت چىقىرىلدى",
+ "Books": "كىتاب",
+ "AuthenticationSucceededWithUserName": "تىزىملىتىش مۇۋەپپەقىيەتلىك بول",
+ "Artists": "سەنئەتكار",
+ "Albums": "پىلاستىنكا"
+}
diff --git a/Emby.Server.Implementations/Net/UdpSocket.cs b/Emby.Server.Implementations/Net/UdpSocket.cs
index 0c451ccb6..bbbca4fc0 100644
--- a/Emby.Server.Implementations/Net/UdpSocket.cs
+++ b/Emby.Server.Implementations/Net/UdpSocket.cs
@@ -159,7 +159,7 @@ namespace Emby.Server.Implementations.Net
{
ThrowIfDisposed();
- var taskCompletion = new TaskCompletionSource<SocketReceiveResult>();
+ var taskCompletion = new TaskCompletionSource<SocketReceiveResult>(TaskCreationOptions.RunContinuationsAsynchronously);
bool isResultSet = false;
Action<IAsyncResult> callback = callbackResult =>
@@ -195,7 +195,7 @@ namespace Emby.Server.Implementations.Net
{
ThrowIfDisposed();
- var taskCompletion = new TaskCompletionSource<int>();
+ var taskCompletion = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
bool isResultSet = false;
Action<IAsyncResult> callback = callbackResult =>
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs
index f7b3cfedc..7c27ae384 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs
@@ -25,8 +25,8 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
/// <summary>
/// Initializes a new instance of the <see cref="RefreshMediaLibraryTask" /> class.
/// </summary>
- /// <param name="libraryManager">The library manager.</param>
- /// <param name="localization">The localization manager.</param>
+ /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
+ /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
public RefreshMediaLibraryTask(ILibraryManager libraryManager, ILocalizationManager localization)
{
_libraryManager = libraryManager;
diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs
index c994ffc90..a18af27f3 100644
--- a/Emby.Server.Implementations/TV/TVSeriesManager.cs
+++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs
@@ -304,11 +304,10 @@ namespace Emby.Server.Implementations.TV
items = items.Take(query.Limit.Value);
}
- return new QueryResult<BaseItem>
- {
- TotalRecordCount = totalCount,
- Items = items.ToArray()
- };
+ return new QueryResult<BaseItem>(
+ query.StartIndex,
+ totalCount,
+ items.ToArray());
}
}
}