mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-06-09 17:28:48 +01:00
Merge branch 'master' into httpclient
This commit is contained in:
@@ -33,7 +33,6 @@ using MediaBrowser.Model.LiveTv;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using MediaBrowser.Model.Providers;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using MediaBrowser.Model.Reflection;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -58,7 +57,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
private readonly IProviderManager _providerManager;
|
||||
private readonly IMediaEncoder _mediaEncoder;
|
||||
private readonly IProcessFactory _processFactory;
|
||||
private readonly IAssemblyInfo _assemblyInfo;
|
||||
private IMediaSourceManager _mediaSourceManager;
|
||||
|
||||
public static EmbyTV Current;
|
||||
@@ -74,7 +72,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
public EmbyTV(IServerApplicationHost appHost,
|
||||
IStreamHelper streamHelper,
|
||||
IMediaSourceManager mediaSourceManager,
|
||||
IAssemblyInfo assemblyInfo,
|
||||
ILogger logger,
|
||||
IJsonSerializer jsonSerializer,
|
||||
IHttpClient httpClient,
|
||||
@@ -101,7 +98,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
_processFactory = processFactory;
|
||||
_liveTvManager = (LiveTvManager)liveTvManager;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
_assemblyInfo = assemblyInfo;
|
||||
_mediaSourceManager = mediaSourceManager;
|
||||
_streamHelper = streamHelper;
|
||||
|
||||
@@ -265,7 +261,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
|
||||
public string HomePageUrl => "https://github.com/jellyfin/jellyfin";
|
||||
|
||||
public async Task RefreshSeriesTimers(CancellationToken cancellationToken, IProgress<double> progress)
|
||||
public async Task RefreshSeriesTimers(CancellationToken cancellationToken)
|
||||
{
|
||||
var seriesTimers = await GetSeriesTimersAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -275,7 +271,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RefreshTimers(CancellationToken cancellationToken, IProgress<double> progress)
|
||||
public async Task RefreshTimers(CancellationToken cancellationToken)
|
||||
{
|
||||
var timers = await GetTimersAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
|
||||
@@ -1087,8 +1087,8 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
|
||||
if (coreService != null)
|
||||
{
|
||||
await coreService.RefreshSeriesTimers(cancellationToken, new SimpleProgress<double>()).ConfigureAwait(false);
|
||||
await coreService.RefreshTimers(cancellationToken, new SimpleProgress<double>()).ConfigureAwait(false);
|
||||
await coreService.RefreshSeriesTimers(cancellationToken).ConfigureAwait(false);
|
||||
await coreService.RefreshTimers(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
// Load these now which will prefetch metadata
|
||||
|
||||
@@ -151,7 +151,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||
});
|
||||
}
|
||||
|
||||
private static int RtpHeaderBytes = 12;
|
||||
private const int RtpHeaderBytes = 12;
|
||||
|
||||
private async Task CopyTo(MediaBrowser.Model.Net.ISocket udpClient, string file, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken)
|
||||
{
|
||||
var bufferSize = 81920;
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
|
||||
public string OriginalStreamId { get; set; }
|
||||
public bool EnableStreamSharing { get; set; }
|
||||
public string UniqueId { get; private set; }
|
||||
public string UniqueId { get; }
|
||||
|
||||
protected readonly IFileSystem FileSystem;
|
||||
protected readonly IServerApplicationPaths AppPaths;
|
||||
@@ -31,12 +31,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
protected readonly ILogger Logger;
|
||||
protected readonly CancellationTokenSource LiveStreamCancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
public string TunerHostId { get; private set; }
|
||||
public string TunerHostId { get; }
|
||||
|
||||
public DateTime DateOpened { get; protected set; }
|
||||
|
||||
public Func<Task> OnClose { get; set; }
|
||||
|
||||
public LiveStream(MediaSourceInfo mediaSource, TunerHostInfo tuner, IFileSystem fileSystem, ILogger logger, IServerApplicationPaths appPaths)
|
||||
{
|
||||
OriginalMediaSource = mediaSource;
|
||||
@@ -76,26 +74,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
|
||||
LiveStreamCancellationTokenSource.Cancel();
|
||||
|
||||
if (OnClose != null)
|
||||
{
|
||||
return CloseWithExternalFn();
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task CloseWithExternalFn()
|
||||
{
|
||||
try
|
||||
{
|
||||
await OnClose().ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error closing live stream");
|
||||
}
|
||||
}
|
||||
|
||||
protected Stream GetInputStream(string path, bool allowAsyncFileRead)
|
||||
{
|
||||
var fileOpenOptions = FileOpenOptions.SequentialScan;
|
||||
@@ -113,27 +94,26 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
return DeleteTempFiles(GetStreamFilePaths());
|
||||
}
|
||||
|
||||
protected async Task DeleteTempFiles(List<string> paths, int retryCount = 0)
|
||||
protected async Task DeleteTempFiles(IEnumerable<string> paths, int retryCount = 0)
|
||||
{
|
||||
if (retryCount == 0)
|
||||
{
|
||||
Logger.LogInformation("Deleting temp files {0}", string.Join(", ", paths.ToArray()));
|
||||
Logger.LogInformation("Deleting temp files {0}", paths);
|
||||
}
|
||||
|
||||
var failedFiles = new List<string>();
|
||||
|
||||
foreach (var path in paths)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
FileSystem.DeleteFile(path);
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error deleting file {path}", path);
|
||||
@@ -157,8 +137,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
{
|
||||
cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, LiveStreamCancellationTokenSource.Token).Token;
|
||||
|
||||
var allowAsync = false;
|
||||
// use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
|
||||
// use non-async filestream on windows along with read due to https://github.com/dotnet/corefx/issues/6039
|
||||
var allowAsync = Environment.OSVersion.Platform != PlatformID.Win32NT;
|
||||
|
||||
bool seekFile = (DateTime.UtcNow - DateOpened).TotalSeconds > 10;
|
||||
|
||||
@@ -181,28 +161,24 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
Logger.LogInformation("Live Stream ended.");
|
||||
}
|
||||
|
||||
private Tuple<string, bool> GetNextFile(string currentFile)
|
||||
private (string file, bool isLastFile) GetNextFile(string currentFile)
|
||||
{
|
||||
var files = GetStreamFilePaths();
|
||||
|
||||
//logger.LogInformation("Live stream files: {0}", string.Join(", ", files.ToArray()));
|
||||
|
||||
if (string.IsNullOrEmpty(currentFile))
|
||||
{
|
||||
return new Tuple<string, bool>(files.Last(), true);
|
||||
return (files.Last(), true);
|
||||
}
|
||||
|
||||
var nextIndex = files.FindIndex(i => string.Equals(i, currentFile, StringComparison.OrdinalIgnoreCase)) + 1;
|
||||
|
||||
var isLastFile = nextIndex == files.Count - 1;
|
||||
|
||||
return new Tuple<string, bool>(files.ElementAtOrDefault(nextIndex), isLastFile);
|
||||
return (files.ElementAtOrDefault(nextIndex), isLastFile);
|
||||
}
|
||||
|
||||
private async Task CopyFile(string path, bool seekFile, int emptyReadLimit, bool allowAsync, Stream stream, CancellationToken cancellationToken)
|
||||
{
|
||||
//logger.LogInformation("Opening live stream file {0}. Empty read limit: {1}", path, emptyReadLimit);
|
||||
|
||||
using (var inputStream = (FileStream)GetInputStream(path, allowAsync))
|
||||
{
|
||||
if (seekFile)
|
||||
@@ -218,7 +194,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
|
||||
private void TrySeek(FileStream stream, long offset)
|
||||
{
|
||||
//logger.LogInformation("TrySeek live stream");
|
||||
if (!stream.CanSeek)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
stream.Seek(offset, SeekOrigin.End);
|
||||
|
||||
@@ -10,14 +10,12 @@ using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Controller.MediaEncoding;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.LiveTv;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Model.System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
@@ -52,9 +50,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
{
|
||||
var channelIdPrefix = GetFullChannelIdPrefix(info);
|
||||
|
||||
var result = await new M3uParser(Logger, _httpClient, _appHost).Parse(info.Url, channelIdPrefix, info.Id, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return result.Cast<ChannelInfo>().ToList();
|
||||
return await new M3uParser(Logger, _httpClient, _appHost).Parse(info.Url, channelIdPrefix, info.Id, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public Task<List<LiveTvTunerInfo>> GetTunerInfos(CancellationToken cancellationToken)
|
||||
@@ -73,7 +69,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
return Task.FromResult(list);
|
||||
}
|
||||
|
||||
private string[] _disallowedSharedStreamExtensions = new string[]
|
||||
private static readonly string[] _disallowedSharedStreamExtensions = new string[]
|
||||
{
|
||||
".mkv",
|
||||
".mp4",
|
||||
@@ -88,9 +84,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
if (tunerCount > 0)
|
||||
{
|
||||
var tunerHostId = info.Id;
|
||||
var liveStreams = currentLiveStreams.Where(i => string.Equals(i.TunerHostId, tunerHostId, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
var liveStreams = currentLiveStreams.Where(i => string.Equals(i.TunerHostId, tunerHostId, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (liveStreams.Count >= tunerCount)
|
||||
if (liveStreams.Count() >= tunerCount)
|
||||
{
|
||||
throw new LiveTvConflictException("M3U simultaneous stream limit has been reached.");
|
||||
}
|
||||
@@ -98,7 +94,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
|
||||
var sources = await GetChannelStreamMediaSources(info, channelInfo, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var mediaSource = sources.First();
|
||||
var mediaSource = sources[0];
|
||||
|
||||
if (mediaSource.Protocol == MediaProtocol.Http && !mediaSource.RequiresLooping)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,6 @@ using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
using MediaBrowser.Model.IO;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
@@ -62,12 +61,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
return Task.FromResult((Stream)File.OpenRead(url));
|
||||
}
|
||||
|
||||
const string ExtInfPrefix = "#EXTINF:";
|
||||
private const string ExtInfPrefix = "#EXTINF:";
|
||||
|
||||
private List<ChannelInfo> GetChannels(TextReader reader, string channelIdPrefix, string tunerHostId)
|
||||
{
|
||||
var channels = new List<ChannelInfo>();
|
||||
string line;
|
||||
string extInf = "";
|
||||
string extInf = string.Empty;
|
||||
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
@@ -101,7 +101,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
|
||||
channel.Path = line;
|
||||
channels.Add(channel);
|
||||
extInf = "";
|
||||
extInf = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,8 +110,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
|
||||
private ChannelInfo GetChannelnfo(string extInf, string tunerHostId, string mediaUrl)
|
||||
{
|
||||
var channel = new ChannelInfo();
|
||||
channel.TunerHostId = tunerHostId;
|
||||
var channel = new ChannelInfo()
|
||||
{
|
||||
TunerHostId = tunerHostId
|
||||
};
|
||||
|
||||
extInf = extInf.Trim();
|
||||
|
||||
@@ -137,13 +139,15 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
{
|
||||
channelIdValues.Add(channelId);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(tvgId))
|
||||
{
|
||||
channelIdValues.Add(tvgId);
|
||||
}
|
||||
|
||||
if (channelIdValues.Count > 0)
|
||||
{
|
||||
channel.Id = string.Join("_", channelIdValues.ToArray());
|
||||
channel.Id = string.Join("_", channelIdValues);
|
||||
}
|
||||
|
||||
return channel;
|
||||
@@ -152,7 +156,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
private string GetChannelNumber(string extInf, Dictionary<string, string> attributes, string mediaUrl)
|
||||
{
|
||||
var nameParts = extInf.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var nameInExtInf = nameParts.Length > 1 ? nameParts.Last().Trim() : null;
|
||||
var nameInExtInf = nameParts.Length > 1 ? nameParts[nameParts.Length - 1].Trim() : null;
|
||||
|
||||
string numberString = null;
|
||||
string attributeValue;
|
||||
|
||||
Reference in New Issue
Block a user