private async Task <Either <BaseError, string> > GetPlaylist(
            GetHlsPlaylistByChannelNumber request,
            Channel channel)
        {
            DateTimeOffset       now = DateTimeOffset.Now;
            Option <PlayoutItem> maybePlayoutItem = await _playoutRepository.GetPlayoutItem(channel.Id, now);

            return(maybePlayoutItem.Match <Either <BaseError, string> >(
                       playoutItem =>
            {
                double timeRemaining = Math.Abs((playoutItem.Finish - now).TotalSeconds);
                return $@"#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:18000
#EXTINF:{timeRemaining:F2},
{request.Scheme}://{request.Host}/ffmpeg/stream/{request.ChannelNumber}
";
            },
                       () =>
            {
                // TODO: playlist for error stream
                Log.Logger.Error("Unable to locate playout item for m3u8");
                return BaseError.New($"Unable to locate playout item for channel {channel.Number}");
            }));
        }
Esempio n. 2
0
    public async Task <Either <BaseError, string> > Handle(
        GetHlsPlaylistByChannelNumber request,
        CancellationToken cancellationToken)
    {
        await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);

        DateTimeOffset now = DateTimeOffset.Now;
        Validation <BaseError, Parameters> validation = await Validate(dbContext, request, now);

        return(await LanguageExtensions.Apply(
                   validation,
                   parameters => GetPlaylist(dbContext, request, parameters, now)));
    }
Esempio n. 3
0
    private Task <string> GetPlaylist(
        TvContext dbContext,
        GetHlsPlaylistByChannelNumber request,
        Parameters parameters,
        DateTimeOffset now)
    {
        string mode = string.IsNullOrWhiteSpace(request.Mode)
            ? string.Empty
            : $"&mode={request.Mode}";

        long   index         = GetIndexForChannel(parameters.Channel, parameters.PlayoutItem);
        double timeRemaining = Math.Abs((parameters.PlayoutItem.FinishOffset - now).TotalSeconds);

        return($@"#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:{index}
#EXT-X-DISCONTINUITY
#EXTINF:{timeRemaining:F2},
{request.Scheme}://{request.Host}/ffmpeg/stream/{request.ChannelNumber}?index={index}{mode}
".AsTask());
    }
 private async Task <Validation <BaseError, Channel> > ChannelMustExist(GetHlsPlaylistByChannelNumber request) =>
 (await _channelRepository.GetByNumber(request.ChannelNumber))
 .ToValidation <BaseError>($"Channel number {request.ChannelNumber} does not exist.");
 public Task <Either <BaseError, string> > Handle(
     GetHlsPlaylistByChannelNumber request,
     CancellationToken cancellationToken) =>
 ChannelMustExist(request)
 .Map(v => v.ToEither <Channel>())
 .BindT(channel => GetPlaylist(request, channel));
Esempio n. 6
0
 private static Task <Validation <BaseError, Channel> > ChannelMustExist(
     TvContext dbContext,
     GetHlsPlaylistByChannelNumber request) =>
 dbContext.Channels
 .SelectOneAsync(c => c.Number, c => c.Number == request.ChannelNumber)
 .Map(o => o.ToValidation <BaseError>($"Channel number {request.ChannelNumber} does not exist."));
Esempio n. 7
0
 private Task <Validation <BaseError, Parameters> > Validate(
     TvContext dbContext,
     GetHlsPlaylistByChannelNumber request,
     DateTimeOffset now) =>
 ChannelMustExist(dbContext, request)
 .BindT(channel => PlayoutItemMustExist(dbContext, channel, now));