diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fee81515..27c890f07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +### Fixed +- Fix streaming mode inconsistencies when `mode` parameter is unspecified ## [0.4.4-alpha] - 2022-03-10 ### Fixed diff --git a/ErsatzTV.Application/Channels/Queries/GetChannelByNumber.cs b/ErsatzTV.Application/Channels/Queries/GetChannelByNumber.cs new file mode 100644 index 000000000..88466de8d --- /dev/null +++ b/ErsatzTV.Application/Channels/Queries/GetChannelByNumber.cs @@ -0,0 +1,3 @@ +namespace ErsatzTV.Application.Channels; + +public record GetChannelByNumber(string ChannelNumber) : IRequest>; diff --git a/ErsatzTV.Application/Channels/Queries/GetChannelByNumberHandler.cs b/ErsatzTV.Application/Channels/Queries/GetChannelByNumberHandler.cs new file mode 100644 index 000000000..cfd044476 --- /dev/null +++ b/ErsatzTV.Application/Channels/Queries/GetChannelByNumberHandler.cs @@ -0,0 +1,14 @@ +using ErsatzTV.Core.Interfaces.Repositories; +using static ErsatzTV.Application.Channels.Mapper; + +namespace ErsatzTV.Application.Channels; + +public class GetChannelByNumberHandler : IRequestHandler> +{ + private readonly IChannelRepository _channelRepository; + + public GetChannelByNumberHandler(IChannelRepository channelRepository) => _channelRepository = channelRepository; + + public Task> Handle(GetChannelByNumber request, CancellationToken cancellationToken) => + _channelRepository.GetByNumber(request.ChannelNumber).MapT(ProjectToViewModel); +} \ No newline at end of file diff --git a/ErsatzTV.Application/Streaming/Queries/GetHlsPlaylistByChannelNumberHandler.cs b/ErsatzTV.Application/Streaming/Queries/GetHlsPlaylistByChannelNumberHandler.cs index 1032ef037..c7583cde0 100644 --- a/ErsatzTV.Application/Streaming/Queries/GetHlsPlaylistByChannelNumberHandler.cs +++ b/ErsatzTV.Application/Streaming/Queries/GetHlsPlaylistByChannelNumberHandler.cs @@ -25,10 +25,10 @@ public class GetHlsPlaylistByChannelNumberHandler : GetHlsPlaylistByChannelNumber request, CancellationToken cancellationToken) { - await using TvContext dbContext = _dbContextFactory.CreateDbContext(); + await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken); DateTimeOffset now = DateTimeOffset.Now; Validation validation = await Validate(dbContext, request, now); - return await LanguageExtensions.Apply(validation, parameters => GetPlaylist(dbContext, request, parameters, now)); + return await validation.Apply(parameters => GetPlaylist(dbContext, request, parameters, now)); } private Task GetPlaylist( diff --git a/ErsatzTV/Controllers/IptvController.cs b/ErsatzTV/Controllers/IptvController.cs index a5fd9a90e..d8229f017 100644 --- a/ErsatzTV/Controllers/IptvController.cs +++ b/ErsatzTV/Controllers/IptvController.cs @@ -18,20 +18,17 @@ namespace ErsatzTV.Controllers; public class IptvController : ControllerBase { private readonly IFFmpegSegmenterService _ffmpegSegmenterService; - private readonly IHlsPlaylistFilter _hlsPlaylistFilter; private readonly ILogger _logger; private readonly IMediator _mediator; public IptvController( IMediator mediator, ILogger logger, - IFFmpegSegmenterService ffmpegSegmenterService, - IHlsPlaylistFilter hlsPlaylistFilter) + IFFmpegSegmenterService ffmpegSegmenterService) { _mediator = mediator; _logger = logger; _ffmpegSegmenterService = ffmpegSegmenterService; - _hlsPlaylistFilter = hlsPlaylistFilter; } [HttpGet("iptv/channels.m3u")] @@ -52,6 +49,26 @@ public class IptvController : ControllerBase [FromQuery] string mode = null) { + // if mode is "unspecified" - find the configured mode and set it or redirect + if (string.IsNullOrWhiteSpace(mode) || mode == "mixed") + { + Option maybeChannel = await _mediator.Send(new GetChannelByNumber(channelNumber)); + foreach (ChannelViewModel channel in maybeChannel) + { + switch (channel.StreamingMode) + { + case StreamingMode.TransportStream: + mode = "ts-legacy"; + break; + case StreamingMode.TransportStreamHybrid: + mode = "ts"; + break; + default: + return Redirect($"/iptv/channel/{channelNumber}.m3u8"); + } + } + } + FFmpegProcessRequest request = mode switch { "ts-legacy" => new GetConcatProcessByChannelNumber(Request.Scheme, Request.Host.ToString(), channelNumber), @@ -97,6 +114,26 @@ public class IptvController : ControllerBase [FromQuery] string mode = "mixed") { + // if mode is "unspecified" - find the configured mode and set it or redirect + if (string.IsNullOrWhiteSpace(mode) || mode == "mixed") + { + Option maybeChannel = await _mediator.Send(new GetChannelByNumber(channelNumber)); + foreach (ChannelViewModel channel in maybeChannel) + { + switch (channel.StreamingMode) + { + case StreamingMode.HttpLiveStreamingDirect: + mode = "hls-direct"; + break; + case StreamingMode.HttpLiveStreamingSegmenter: + mode = "segmenter"; + break; + default: + return Redirect($"/iptv/channel/{channelNumber}.ts"); + } + } + } + switch (mode) { case "segmenter": diff --git a/ErsatzTV/Services/SchedulerService.cs b/ErsatzTV/Services/SchedulerService.cs index 10f8347db..03ddd7677 100644 --- a/ErsatzTV/Services/SchedulerService.cs +++ b/ErsatzTV/Services/SchedulerService.cs @@ -56,7 +56,7 @@ public class SchedulerService : BackgroundService { await Task.Delay(TimeSpan.FromMinutes(toWait), cancellationToken); } - catch (TaskCanceledException) + catch (Exception ex) when (ex is TaskCanceledException or OperationCanceledException) { // do nothing } @@ -89,10 +89,14 @@ public class SchedulerService : BackgroundService await ScanPlexMediaSources(cancellationToken); await MatchTraktLists(cancellationToken); } + catch (Exception ex) when (ex is TaskCanceledException or OperationCanceledException) + { + // do nothing + } catch (Exception ex) { _logger.LogWarning(ex, "Error during scheduler run"); - + try { using (IServiceScope scope = _serviceScopeFactory.CreateScope())