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}"); })); }
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))); }
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));
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."));
private Task <Validation <BaseError, Parameters> > Validate( TvContext dbContext, GetHlsPlaylistByChannelNumber request, DateTimeOffset now) => ChannelMustExist(dbContext, request) .BindT(channel => PlayoutItemMustExist(dbContext, channel, now));