Merge pull request #3405 from crobibero/api-livetv

Move LiveTvService.cs to Jellyfin.Api
This commit is contained in:
David 2020-07-03 19:12:44 +02:00 committed by GitHub
commit c675a9bec9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 1538 additions and 1359 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,84 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.IO;
namespace Jellyfin.Api.Helpers
{
/// <summary>
/// Progressive file copier.
/// </summary>
public class ProgressiveFileCopier
{
private readonly string? _path;
private readonly IDirectStreamProvider? _directStreamProvider;
private readonly IStreamHelper _streamHelper;
/// <summary>
/// Initializes a new instance of the <see cref="ProgressiveFileCopier"/> class.
/// </summary>
/// <param name="streamHelper">Instance of the <see cref="IStreamHelper"/> interface.</param>
/// <param name="path">Filepath to stream from.</param>
public ProgressiveFileCopier(IStreamHelper streamHelper, string path)
{
_path = path;
_streamHelper = streamHelper;
_directStreamProvider = null;
}
/// <summary>
/// Initializes a new instance of the <see cref="ProgressiveFileCopier"/> class.
/// </summary>
/// <param name="streamHelper">Instance of the <see cref="IStreamHelper"/> interface.</param>
/// <param name="directStreamProvider">Instance of the <see cref="IDirectStreamProvider"/> interface.</param>
public ProgressiveFileCopier(IStreamHelper streamHelper, IDirectStreamProvider directStreamProvider)
{
_directStreamProvider = directStreamProvider;
_streamHelper = streamHelper;
_path = null;
}
/// <summary>
/// Write source stream to output.
/// </summary>
/// <param name="outputStream">Output stream.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>A <see cref="Task"/>.</returns>
public async Task WriteToAsync(Stream outputStream, CancellationToken cancellationToken)
{
if (_directStreamProvider != null)
{
await _directStreamProvider.CopyToAsync(outputStream, cancellationToken).ConfigureAwait(false);
return;
}
var fileOptions = FileOptions.SequentialScan;
// use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
{
fileOptions |= FileOptions.Asynchronous;
}
await using var inputStream = new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, fileOptions);
const int emptyReadLimit = 100;
var eofCount = 0;
while (eofCount < emptyReadLimit)
{
var bytesRead = await _streamHelper.CopyToAsync(inputStream, outputStream, cancellationToken).ConfigureAwait(false);
if (bytesRead == 0)
{
eofCount++;
await Task.Delay(100, cancellationToken).ConfigureAwait(false);
}
else
{
eofCount = 0;
}
}
}
}
}

View file

@ -144,5 +144,31 @@ namespace Jellyfin.Api.Helpers
: Split(filters, ',', true)
.Select(v => Enum.Parse<ItemFilter>(v, true)).ToArray();
}
/// <summary>
/// Gets the item fields.
/// </summary>
/// <param name="fields">The fields string.</param>
/// <returns>IEnumerable{ItemFields}.</returns>
internal static ItemFields[] GetItemFields(string? fields)
{
if (string.IsNullOrEmpty(fields))
{
return Array.Empty<ItemFields>();
}
return Split(fields, ',', true)
.Select(v =>
{
if (Enum.TryParse(v, true, out ItemFields value))
{
return (ItemFields?)value;
}
return null;
}).Where(i => i.HasValue)
.Select(i => i!.Value)
.ToArray();
}
}
}

View file

@ -0,0 +1,36 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.Dto;
namespace Jellyfin.Api.Models.LiveTvDtos
{
/// <summary>
/// Channel mapping options dto.
/// </summary>
public class ChannelMappingOptionsDto
{
/// <summary>
/// Gets or sets list of tuner channels.
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA2227:ReadOnlyRemoveSetter", MessageId = "TunerChannels", Justification = "Imported from ServiceStack")]
public List<TunerChannelMapping> TunerChannels { get; set; } = null!;
/// <summary>
/// Gets or sets list of provider channels.
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA2227:ReadOnlyRemoveSetter", MessageId = "ProviderChannels", Justification = "Imported from ServiceStack")]
public List<NameIdPair> ProviderChannels { get; set; } = null!;
/// <summary>
/// Gets or sets list of mappings.
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA1819:DontReturnArrays", MessageId = "Mappings", Justification = "Imported from ServiceStack")]
public NameValuePair[] Mappings { get; set; } = null!;
/// <summary>
/// Gets or sets provider name.
/// </summary>
public string? ProviderName { get; set; }
}
}

View file

@ -0,0 +1,166 @@
using System;
namespace Jellyfin.Api.Models.LiveTvDtos
{
/// <summary>
/// Get programs dto.
/// </summary>
public class GetProgramsDto
{
/// <summary>
/// Gets or sets the channels to return guide information for.
/// </summary>
public string? ChannelIds { get; set; }
/// <summary>
/// Gets or sets optional. Filter by user id.
/// </summary>
public Guid UserId { get; set; }
/// <summary>
/// Gets or sets the minimum premiere start date.
/// Optional.
/// </summary>
public DateTime? MinStartDate { get; set; }
/// <summary>
/// Gets or sets filter by programs that have completed airing, or not.
/// Optional.
/// </summary>
public bool? HasAired { get; set; }
/// <summary>
/// Gets or sets filter by programs that are currently airing, or not.
/// Optional.
/// </summary>
public bool? IsAiring { get; set; }
/// <summary>
/// Gets or sets the maximum premiere start date.
/// Optional.
/// </summary>
public DateTime? MaxStartDate { get; set; }
/// <summary>
/// Gets or sets the minimum premiere end date.
/// Optional.
/// </summary>
public DateTime? MinEndDate { get; set; }
/// <summary>
/// Gets or sets the maximum premiere end date.
/// Optional.
/// </summary>
public DateTime? MaxEndDate { get; set; }
/// <summary>
/// Gets or sets filter for movies.
/// Optional.
/// </summary>
public bool? IsMovie { get; set; }
/// <summary>
/// Gets or sets filter for series.
/// Optional.
/// </summary>
public bool? IsSeries { get; set; }
/// <summary>
/// Gets or sets filter for news.
/// Optional.
/// </summary>
public bool? IsNews { get; set; }
/// <summary>
/// Gets or sets filter for kids.
/// Optional.
/// </summary>
public bool? IsKids { get; set; }
/// <summary>
/// Gets or sets filter for sports.
/// Optional.
/// </summary>
public bool? IsSports { get; set; }
/// <summary>
/// Gets or sets the record index to start at. All items with a lower index will be dropped from the results.
/// Optional.
/// </summary>
public int? StartIndex { get; set; }
/// <summary>
/// Gets or sets the maximum number of records to return.
/// Optional.
/// </summary>
public int? Limit { get; set; }
/// <summary>
/// Gets or sets specify one or more sort orders, comma delimited. Options: Name, StartDate.
/// Optional.
/// </summary>
public string? SortBy { get; set; }
/// <summary>
/// Gets or sets sort Order - Ascending,Descending.
/// </summary>
public string? SortOrder { get; set; }
/// <summary>
/// Gets or sets the genres to return guide information for.
/// </summary>
public string? Genres { get; set; }
/// <summary>
/// Gets or sets the genre ids to return guide information for.
/// </summary>
public string? GenreIds { get; set; }
/// <summary>
/// Gets or sets include image information in output.
/// Optional.
/// </summary>
public bool? EnableImages { get; set; }
/// <summary>
/// Gets or sets a value indicating whether retrieve total record count.
/// </summary>
public bool EnableTotalRecordCount { get; set; } = true;
/// <summary>
/// Gets or sets the max number of images to return, per image type.
/// Optional.
/// </summary>
public int? ImageTypeLimit { get; set; }
/// <summary>
/// Gets or sets the image types to include in the output.
/// Optional.
/// </summary>
public string? EnableImageTypes { get; set; }
/// <summary>
/// Gets or sets include user data.
/// Optional.
/// </summary>
public bool? EnableUserData { get; set; }
/// <summary>
/// Gets or sets filter by series timer id.
/// Optional.
/// </summary>
public string? SeriesTimerId { get; set; }
/// <summary>
/// Gets or sets filter by library series id.
/// Optional.
/// </summary>
public Guid LibrarySeriesId { get; set; }
/// <summary>
/// Gets or sets specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.
/// Optional.
/// </summary>
public string? Fields { get; set; }
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,80 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Services;
using Microsoft.Extensions.Logging;
namespace MediaBrowser.Api.LiveTv
{
public class ProgressiveFileCopier : IAsyncStreamWriter, IHasHeaders
{
private readonly ILogger _logger;
private readonly string _path;
private readonly Dictionary<string, string> _outputHeaders;
public bool AllowEndOfFile = true;
private readonly IDirectStreamProvider _directStreamProvider;
private IStreamHelper _streamHelper;
public ProgressiveFileCopier(IStreamHelper streamHelper, string path, Dictionary<string, string> outputHeaders, ILogger logger)
{
_path = path;
_outputHeaders = outputHeaders;
_logger = logger;
_streamHelper = streamHelper;
}
public ProgressiveFileCopier(IDirectStreamProvider directStreamProvider, IStreamHelper streamHelper, Dictionary<string, string> outputHeaders, ILogger logger)
{
_directStreamProvider = directStreamProvider;
_outputHeaders = outputHeaders;
_logger = logger;
_streamHelper = streamHelper;
}
public IDictionary<string, string> Headers => _outputHeaders;
public async Task WriteToAsync(Stream outputStream, CancellationToken cancellationToken)
{
if (_directStreamProvider != null)
{
await _directStreamProvider.CopyToAsync(outputStream, cancellationToken).ConfigureAwait(false);
return;
}
var fileOptions = FileOptions.SequentialScan;
// use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
{
fileOptions |= FileOptions.Asynchronous;
}
using (var inputStream = new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, fileOptions))
{
var emptyReadLimit = AllowEndOfFile ? 20 : 100;
var eofCount = 0;
while (eofCount < emptyReadLimit)
{
int bytesRead;
bytesRead = await _streamHelper.CopyToAsync(inputStream, outputStream, cancellationToken).ConfigureAwait(false);
if (bytesRead == 0)
{
eofCount++;
await Task.Delay(100, cancellationToken).ConfigureAwait(false);
}
else
{
eofCount = 0;
}
}
}
}
}
}