diff options
Diffstat (limited to 'Emby.Server.Implementations/LiveTv')
8 files changed, 79 insertions, 95 deletions
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index b9d0f170a..74b62ca3f 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1851,7 +1851,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - await using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None)) + var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None); + await using (stream.ConfigureAwait(false)) { var settings = new XmlWriterSettings { @@ -1860,7 +1861,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Async = true }; - await using (var writer = XmlWriter.Create(stream, settings)) + var writer = XmlWriter.Create(stream, settings); + await using (writer.ConfigureAwait(false)) { await writer.WriteStartDocumentAsync(true).ConfigureAwait(false); await writer.WriteStartElementAsync(null, "tvshow", null).ConfigureAwait(false); @@ -1914,7 +1916,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - await using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None)) + var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None); + await using (stream.ConfigureAwait(false)) { var settings = new XmlWriterSettings { @@ -1927,7 +1930,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var isSeriesEpisode = timer.IsProgramSeries; - await using (var writer = XmlWriter.Create(stream, settings)) + var writer = XmlWriter.Create(stream, settings); + await using (writer.ConfigureAwait(false)) { await writer.WriteStartDocumentAsync(true).ConfigureAwait(false); @@ -1965,7 +1969,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } else { - await writer.WriteStartElementAsync(null, "movie", null); + await writer.WriteStartElementAsync(null, "movie", null).ConfigureAwait(false); if (!string.IsNullOrWhiteSpace(item.Name)) { diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 7645c6c52..6b0520ad0 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -106,8 +106,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings options.Content = JsonContent.Create(requestList, options: _jsonOptions); options.Headers.TryAddWithoutValidation("token", token); using var response = await Send(options, true, info, cancellationToken).ConfigureAwait(false); - await using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var dailySchedules = await JsonSerializer.DeserializeAsync<IReadOnlyList<DayDto>>(responseStream, _jsonOptions, cancellationToken).ConfigureAwait(false); + var dailySchedules = await response.Content.ReadFromJsonAsync<IReadOnlyList<DayDto>>(_jsonOptions, cancellationToken).ConfigureAwait(false); if (dailySchedules is null) { return Array.Empty<ProgramInfo>(); @@ -122,8 +121,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings programRequestOptions.Content = JsonContent.Create(programIds, options: _jsonOptions); using var innerResponse = await Send(programRequestOptions, true, info, cancellationToken).ConfigureAwait(false); - await using var innerResponseStream = await innerResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var programDetails = await JsonSerializer.DeserializeAsync<IReadOnlyList<ProgramDetailsDto>>(innerResponseStream, _jsonOptions, cancellationToken).ConfigureAwait(false); + var programDetails = await innerResponse.Content.ReadFromJsonAsync<IReadOnlyList<ProgramDetailsDto>>(_jsonOptions, cancellationToken).ConfigureAwait(false); if (programDetails is null) { return Array.Empty<ProgramInfo>(); @@ -482,8 +480,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings try { using var innerResponse2 = await Send(message, true, info, cancellationToken).ConfigureAwait(false); - await using var response = await innerResponse2.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - return await JsonSerializer.DeserializeAsync<IReadOnlyList<ShowImagesDto>>(response, _jsonOptions, cancellationToken).ConfigureAwait(false); + return await innerResponse2.Content.ReadFromJsonAsync<IReadOnlyList<ShowImagesDto>>(_jsonOptions, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { @@ -510,10 +507,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings try { using var httpResponse = await Send(options, false, info, cancellationToken).ConfigureAwait(false); - await using var response = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - - var root = await JsonSerializer.DeserializeAsync<IReadOnlyList<HeadendsDto>>(response, _jsonOptions, cancellationToken).ConfigureAwait(false); - + var root = await httpResponse.Content.ReadFromJsonAsync<IReadOnlyList<HeadendsDto>>(_jsonOptions, cancellationToken).ConfigureAwait(false); if (root is not null) { foreach (HeadendsDto headend in root) @@ -649,8 +643,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var response = await Send(options, false, null, cancellationToken).ConfigureAwait(false); response.EnsureSuccessStatusCode(); - await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var root = await JsonSerializer.DeserializeAsync<TokenDto>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); + var root = await response.Content.ReadFromJsonAsync<TokenDto>(_jsonOptions, cancellationToken).ConfigureAwait(false); if (string.Equals(root?.Message, "OK", StringComparison.Ordinal)) { _logger.LogInformation("Authenticated with Schedules Direct token: {Token}", root.Token); @@ -691,10 +684,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { using var httpResponse = await Send(options, false, null, cancellationToken).ConfigureAwait(false); httpResponse.EnsureSuccessStatusCode(); - await using var stream = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - using var response = httpResponse.Content; - var root = await JsonSerializer.DeserializeAsync<LineupsDto>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); - + var root = await httpResponse.Content.ReadFromJsonAsync<LineupsDto>(_jsonOptions, cancellationToken).ConfigureAwait(false); return root?.Lineups.Any(i => string.Equals(info.ListingsId, i.Lineup, StringComparison.OrdinalIgnoreCase)) ?? false; } catch (HttpRequestException ex) @@ -748,8 +738,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings options.Headers.TryAddWithoutValidation("token", token); using var httpResponse = await Send(options, true, info, cancellationToken).ConfigureAwait(false); - await using var stream = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var root = await JsonSerializer.DeserializeAsync<ChannelDto>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); + var root = await httpResponse.Content.ReadFromJsonAsync<ChannelDto>(_jsonOptions, cancellationToken).ConfigureAwait(false); if (root is null) { return new List<ChannelInfo>(); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index 7b6c8b80a..ff25ee585 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -3,6 +3,7 @@ #pragma warning disable CS1591 using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -16,21 +17,20 @@ using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.Dto; using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; -using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.TunerHosts { public abstract class BaseTunerHost { - private readonly IMemoryCache _memoryCache; + private readonly ConcurrentDictionary<string, List<ChannelInfo>> _cache; - protected BaseTunerHost(IServerConfigurationManager config, ILogger<BaseTunerHost> logger, IFileSystem fileSystem, IMemoryCache memoryCache) + protected BaseTunerHost(IServerConfigurationManager config, ILogger<BaseTunerHost> logger, IFileSystem fileSystem) { Config = config; Logger = logger; - _memoryCache = memoryCache; FileSystem = fileSystem; + _cache = new ConcurrentDictionary<string, List<ChannelInfo>>(); } protected IServerConfigurationManager Config { get; } @@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { var key = tuner.Id; - if (enableCache && !string.IsNullOrEmpty(key) && _memoryCache.TryGetValue(key, out List<ChannelInfo> cache)) + if (enableCache && !string.IsNullOrEmpty(key) && _cache.TryGetValue(key, out List<ChannelInfo> cache)) { return cache; } @@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts if (!string.IsNullOrEmpty(key) && list.Count > 0) { - _memoryCache.Set(key, list); + _cache[key] = list; } return list; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 98bbc1540..8cd0c4ffb 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -9,6 +9,7 @@ using System.IO; using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Http.Json; using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -27,7 +28,6 @@ using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Net; -using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun @@ -50,9 +50,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun IHttpClientFactory httpClientFactory, IServerApplicationHost appHost, ISocketFactory socketFactory, - IStreamHelper streamHelper, - IMemoryCache memoryCache) - : base(config, logger, fileSystem, memoryCache) + IStreamHelper streamHelper) + : base(config, logger, fileSystem) { _httpClientFactory = httpClientFactory; _appHost = appHost; @@ -77,13 +76,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(model.LineupURL ?? model.BaseURL + "/lineup.json", HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var lineup = await JsonSerializer.DeserializeAsync<List<Channels>>(stream, _jsonOptions, cancellationToken) - .ConfigureAwait(false) ?? new List<Channels>(); - + var lineup = await response.Content.ReadFromJsonAsync<IEnumerable<Channels>>(_jsonOptions, cancellationToken).ConfigureAwait(false) ?? Enumerable.Empty<Channels>(); if (info.ImportFavoritesOnly) { - lineup = lineup.Where(i => i.Favorite).ToList(); + lineup = lineup.Where(i => i.Favorite); } return lineup.Where(i => !i.DRM).ToList(); @@ -130,9 +126,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun .GetAsync(GetApiUrl(info) + "/discover.json", HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); response.EnsureSuccessStatusCode(); - await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var discoverResponse = await JsonSerializer.DeserializeAsync<DiscoverResponse>(stream, _jsonOptions, cancellationToken) - .ConfigureAwait(false); + var discoverResponse = await response.Content.ReadFromJsonAsync<DiscoverResponse>(_jsonOptions, cancellationToken).ConfigureAwait(false); if (!string.IsNullOrEmpty(cacheKey)) { @@ -176,34 +170,37 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun using var response = await _httpClientFactory.CreateClient(NamedClient.Default) .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - using var sr = new StreamReader(stream, System.Text.Encoding.UTF8); var tuners = new List<LiveTvTunerInfo>(); - await foreach (var line in sr.ReadAllLinesAsync().ConfigureAwait(false)) + var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); + await using (stream.ConfigureAwait(false)) { - string stripedLine = StripXML(line); - if (stripedLine.Contains("Channel", StringComparison.Ordinal)) + using var sr = new StreamReader(stream, System.Text.Encoding.UTF8); + await foreach (var line in sr.ReadAllLinesAsync().ConfigureAwait(false)) { - LiveTvTunerStatus status; - var index = stripedLine.IndexOf("Channel", StringComparison.OrdinalIgnoreCase); - var name = stripedLine.Substring(0, index - 1); - var currentChannel = stripedLine.Substring(index + 7); - if (string.Equals(currentChannel, "none", StringComparison.Ordinal)) + string stripedLine = StripXML(line); + if (stripedLine.Contains("Channel", StringComparison.Ordinal)) { - status = LiveTvTunerStatus.LiveTv; - } - else - { - status = LiveTvTunerStatus.Available; - } + LiveTvTunerStatus status; + var index = stripedLine.IndexOf("Channel", StringComparison.OrdinalIgnoreCase); + var name = stripedLine.Substring(0, index - 1); + var currentChannel = stripedLine.Substring(index + 7); + if (string.Equals(currentChannel, "none", StringComparison.Ordinal)) + { + status = LiveTvTunerStatus.LiveTv; + } + else + { + status = LiveTvTunerStatus.Available; + } - tuners.Add(new LiveTvTunerInfo - { - Name = name, - SourceType = string.IsNullOrWhiteSpace(model.ModelNumber) ? Name : model.ModelNumber, - ProgramName = currentChannel, - Status = status - }); + tuners.Add(new LiveTvTunerInfo + { + Name = name, + SourceType = string.IsNullOrWhiteSpace(model.ModelNumber) ? Name : model.ModelNumber, + ProgramName = currentChannel, + Status = status + }); + } } } @@ -661,18 +658,18 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun // Need a way to set the Receive timeout on the socket otherwise this might never timeout? try { - await udpClient.SendToAsync(discBytes, 0, discBytes.Length, new IPEndPoint(IPAddress.Parse("255.255.255.255"), 65001), cancellationToken).ConfigureAwait(false); + await udpClient.SendToAsync(discBytes, new IPEndPoint(IPAddress.Broadcast, 65001), cancellationToken).ConfigureAwait(false); var receiveBuffer = new byte[8192]; while (!cancellationToken.IsCancellationRequested) { - var response = await udpClient.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, cancellationToken).ConfigureAwait(false); - var deviceIp = response.RemoteEndPoint.Address.ToString(); + var response = await udpClient.ReceiveMessageFromAsync(receiveBuffer, new IPEndPoint(IPAddress.Any, 0), cancellationToken).ConfigureAwait(false); + var deviceIP = ((IPEndPoint)response.RemoteEndPoint).Address.ToString(); - // check to make sure we have enough bytes received to be a valid message and make sure the 2nd byte is the discover reply byte - if (response.ReceivedBytes > 13 && response.Buffer[1] == 3) + // Check to make sure we have enough bytes received to be a valid message and make sure the 2nd byte is the discover reply byte + if (response.ReceivedBytes > 13 && receiveBuffer[1] == 3) { - var deviceAddress = "http://" + deviceIp; + var deviceAddress = "http://" + deviceIP; var info = await TryGetTunerHostInfo(deviceAddress, cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index 7bc209d6b..68383a554 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -44,14 +44,12 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun StopStreaming(socket).GetAwaiter().GetResult(); } } - - GC.SuppressFinalize(this); } - public async Task<bool> CheckTunerAvailability(IPAddress remoteIp, int tuner, CancellationToken cancellationToken) + public async Task<bool> CheckTunerAvailability(IPAddress remoteIP, int tuner, CancellationToken cancellationToken) { using var client = new TcpClient(); - await client.ConnectAsync(remoteIp, HdHomeRunPort, cancellationToken).ConfigureAwait(false); + await client.ConnectAsync(remoteIP, HdHomeRunPort, cancellationToken).ConfigureAwait(false); using var stream = client.GetStream(); return await CheckTunerAvailability(stream, tuner, cancellationToken).ConfigureAwait(false); @@ -75,9 +73,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } - public async Task StartStreaming(IPAddress remoteIp, IPAddress localIp, int localPort, IHdHomerunChannelCommands commands, int numTuners, CancellationToken cancellationToken) + public async Task StartStreaming(IPAddress remoteIP, IPAddress localIP, int localPort, IHdHomerunChannelCommands commands, int numTuners, CancellationToken cancellationToken) { - _remoteEndPoint = new IPEndPoint(remoteIp, HdHomeRunPort); + _remoteEndPoint = new IPEndPoint(remoteIP, HdHomeRunPort); _tcpClient = new TcpClient(); await _tcpClient.ConnectAsync(_remoteEndPoint, cancellationToken).ConfigureAwait(false); @@ -125,7 +123,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } - var targetValue = string.Format(CultureInfo.InvariantCulture, "rtp://{0}:{1}", localIp, localPort); + var targetValue = string.Format(CultureInfo.InvariantCulture, "rtp://{0}:{1}", localIP, localPort); var targetMsgLen = WriteSetMessage(buffer, i, "target", targetValue, lockKeyValue); await stream.WriteAsync(buffer.AsMemory(0, targetMsgLen), cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs index 3450f971f..654474e97 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs @@ -5,7 +5,7 @@ using System.Text.RegularExpressions; namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { - public class LegacyHdHomerunChannelCommands : IHdHomerunChannelCommands + public partial class LegacyHdHomerunChannelCommands : IHdHomerunChannelCommands { private string? _channel; private string? _program; @@ -13,7 +13,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun public LegacyHdHomerunChannelCommands(string url) { // parse url for channel and program - var match = Regex.Match(url, @"\/ch([0-9]+)-?([0-9]*)"); + var match = ChannelAndProgramRegex().Match(url); if (match.Success) { _channel = match.Groups[1].Value; @@ -21,6 +21,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } + [GeneratedRegex(@"\/ch([0-9]+)-?([0-9]*)")] + private static partial Regex ChannelAndProgramRegex(); + public IEnumerable<(string CommandName, string CommandValue)> GetCommands() { if (!string.IsNullOrEmpty(_channel)) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index acf3964c8..db5e81df5 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.IO; using System.Linq; using System.Net.Http; using System.Threading; @@ -22,7 +21,6 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.MediaInfo; -using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using Microsoft.Net.Http.Headers; @@ -54,9 +52,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts IHttpClientFactory httpClientFactory, IServerApplicationHost appHost, INetworkManager networkManager, - IStreamHelper streamHelper, - IMemoryCache memoryCache) - : base(config, logger, fileSystem, memoryCache) + IStreamHelper streamHelper) + : base(config, logger, fileSystem) { _httpClientFactory = httpClientFactory; _appHost = appHost; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index b41816230..341782d9d 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -20,7 +20,7 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.TunerHosts { - public class M3uParser + public partial class M3uParser { private const string ExtInfPrefix = "#EXTINF:"; @@ -33,6 +33,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts _httpClientFactory = httpClientFactory; } + [GeneratedRegex(@"([a-z0-9\-_]+)=\""([^""]+)\""", RegexOptions.IgnoreCase, "en-US")] + private static partial Regex KeyValueRegex(); + public async Task<List<ChannelInfo>> Parse(TunerHostInfo info, string channelIdPrefix, CancellationToken cancellationToken) { // Read the file and display it line by line. @@ -91,14 +94,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts else if (!string.IsNullOrWhiteSpace(extInf) && !trimmedLine.StartsWith('#')) { var channel = GetChannelnfo(extInf, tunerHostId, trimmedLine); - if (string.IsNullOrWhiteSpace(channel.Id)) - { - channel.Id = channelIdPrefix + trimmedLine.GetMD5().ToString("N", CultureInfo.InvariantCulture); - } - else - { - channel.Id = channelIdPrefix + channel.Id.GetMD5().ToString("N", CultureInfo.InvariantCulture); - } + channel.Id = channelIdPrefix + trimmedLine.GetMD5().ToString("N", CultureInfo.InvariantCulture); channel.Path = trimmedLine; channels.Add(channel); @@ -311,7 +307,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - var matches = Regex.Matches(line, @"([a-z0-9\-_]+)=\""([^""]+)\""", RegexOptions.IgnoreCase); + var matches = KeyValueRegex().Matches(line); remaining = line; @@ -320,7 +316,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts var key = match.Groups[1].Value; var value = match.Groups[2].Value; - dict[match.Groups[1].Value] = match.Groups[2].Value; + dict[key] = value; remaining = remaining.Replace(key + "=\"" + value + "\"", string.Empty, StringComparison.OrdinalIgnoreCase); } |
