Stream custom live channels using your own media
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
3.6 KiB

using System.Globalization;
using NCalc;
using NCalc.Handlers;
namespace ErsatzTV.Infrastructure.Streaming;
public static class OpacityExpressionHelper
{
public static void EvaluateFunction(string name, FunctionArgs args)
{
switch (name)
{
case "LinearFadePoints":
{
if (args.Parameters.Length != 5)
{
throw new ArgumentException("LinearFadePoints() requires 5 arguments.");
}
double time = Convert.ToDouble(args.Parameters[0].Evaluate(), CultureInfo.CurrentCulture);
double start = Convert.ToDouble(args.Parameters[1].Evaluate(), CultureInfo.CurrentCulture);
double peakStart = Convert.ToDouble(args.Parameters[2].Evaluate(), CultureInfo.CurrentCulture);
double peakEnd = Convert.ToDouble(args.Parameters[3].Evaluate(), CultureInfo.CurrentCulture);
double end = Convert.ToDouble(args.Parameters[4].Evaluate(), CultureInfo.CurrentCulture);
args.Result = LinearFadePoints(time, start, peakStart, peakEnd, end);
break;
}
case "LinearFadeDuration":
{
if (args.Parameters.Length != 4)
{
throw new ArgumentException("LinearFadeDuration() requires 4 arguments.");
}
double time = Convert.ToDouble(args.Parameters[0].Evaluate(), CultureInfo.CurrentCulture);
double start = Convert.ToDouble(args.Parameters[1].Evaluate(), CultureInfo.CurrentCulture);
double fadeSeconds = Convert.ToDouble(args.Parameters[2].Evaluate(), CultureInfo.CurrentCulture);
double peakSeconds = Convert.ToDouble(args.Parameters[3].Evaluate(), CultureInfo.CurrentCulture);
args.Result = LinearFadeDuration(time, start, fadeSeconds, peakSeconds);
break;
}
}
}
private static double LinearFadePoints(double time, double start, double peakStart, double peakEnd, double end)
{
if (time < start || time >= end)
{
return 0;
}
// fade in
if (time < peakStart)
{
return (time - start) / (peakStart - start);
}
// solid
if (time < peakEnd)
{
return 1.0;
}
// fade out
return (end - time) / (end - peakEnd);
}
private static double LinearFadeDuration(double time, double start, double fadeSeconds, double peakSeconds)
{
// edge case with no fade
if (fadeSeconds <= 0)
{
double noFadeEnd = start + peakSeconds;
return (time >= start && time < noFadeEnd) ? 1.0 : 0.0;
}
double peakStart = start + fadeSeconds;
double peakEnd = peakStart + peakSeconds;
double end = peakEnd + fadeSeconds;
return LinearFadePoints(time, start, peakStart, peakEnd, end);
}
public static float GetOpacity(
Expression expression,
TimeSpan timeOfDay,
TimeSpan contentTime,
TimeSpan contentTotalTime,
TimeSpan channelTime)
{
expression.Parameters["content_seconds"] = contentTime.TotalSeconds;
expression.Parameters["content_total_seconds"] = contentTotalTime.TotalSeconds;
expression.Parameters["channel_seconds"] = channelTime.TotalSeconds;
expression.Parameters["time_of_day_seconds"] = timeOfDay.TotalSeconds;
object expressionResult = expression.Evaluate();
return Convert.ToSingle(expressionResult, CultureInfo.InvariantCulture);
}
}