@ -11,7 +11,11 @@ using Newtonsoft.Json;
@@ -11,7 +11,11 @@ using Newtonsoft.Json;
namespace ErsatzTV.Core.Scheduling.Engine ;
public class SchedulingEngine ( IMediaCollectionRepository mediaCollectionRepository , ILogger < SchedulingEngine > logger )
public class SchedulingEngine (
IMediaCollectionRepository mediaCollectionRepository ,
IGraphicsElementRepository graphicsElementRepository ,
IChannelRepository channelRepository ,
ILogger < SchedulingEngine > logger )
: ISchedulingEngine
{
private static readonly JsonSerializerSettings JsonSettings = new ( )
@ -19,6 +23,8 @@ public class SchedulingEngine(IMediaCollectionRepository mediaCollectionReposito
@@ -19,6 +23,8 @@ public class SchedulingEngine(IMediaCollectionRepository mediaCollectionReposito
NullValueHandling = NullValueHandling . Ignore
} ;
private readonly Dictionary < string , Option < GraphicsElement > > _ graphicsElementCache = new ( ) ;
private readonly Dictionary < string , Option < ChannelWatermark > > _ watermarkCache = new ( ) ;
private readonly Dictionary < string , EnumeratorDetails > _ enumerators = new ( ) ;
private readonly SchedulingEngineState _ state = new ( 0 ) ;
private PlayoutReferenceData _ referenceData ;
@ -394,26 +400,26 @@ public class SchedulingEngine(IMediaCollectionRepository mediaCollectionReposito
@@ -394,26 +400,26 @@ public class SchedulingEngine(IMediaCollectionRepository mediaCollectionReposito
PlayoutItemGraphicsElements = [ ]
} ;
// foreach (int watermarkId in context.GetChannelWatermarkIds())
// {
// playoutItem.PlayoutItemWatermarks.Add(
// new PlayoutItemWatermark
// {
// PlayoutItem = playoutItem,
// WatermarkId = watermarkId
// });
// }
//
// foreach ((int graphicsElementId, string variablesJson) in context.GetGraphicsElements())
// {
// playoutItem.PlayoutItemGraphicsElements.Add(
// new PlayoutItemGraphicsElement
// {
// PlayoutItem = playoutItem,
// GraphicsElementId = graphicsElementId,
// Variables = variablesJson
// });
// }
foreach ( int watermarkId in _ state . GetChannelWatermarkIds ( ) )
{
playoutItem . PlayoutItemWatermarks . Add (
new PlayoutItemWatermark
{
PlayoutItem = playoutItem ,
WatermarkId = watermarkId
} ) ;
}
foreach ( ( int graphicsElementId , string variablesJson ) in _ state . GetGraphicsElements ( ) )
{
playoutItem . PlayoutItemGraphicsElements . Add (
new PlayoutItemGraphicsElement
{
PlayoutItem = playoutItem ,
GraphicsElementId = graphicsElementId ,
Variables = variablesJson
} ) ;
}
//await AddItemAndMidRoll(context, playoutItem, mediaItem, executeSequence);
@ -444,6 +450,133 @@ public class SchedulingEngine(IMediaCollectionRepository mediaCollectionReposito
@@ -444,6 +450,133 @@ public class SchedulingEngine(IMediaCollectionRepository mediaCollectionReposito
return result ;
}
public void LockGuideGroup ( bool advance )
{
_ state . LockGuideGroup ( advance ) ;
}
public void UnlockGuideGroup ( )
{
_ state . UnlockGuideGroup ( ) ;
}
public async Task GraphicsOn ( List < string > graphicsElements , Dictionary < string , string > variables )
{
string variablesJson = null ;
if ( variables . Count > 0 )
{
variablesJson = JsonConvert . SerializeObject ( variables , JsonSettings ) ;
}
foreach ( string element in graphicsElements . Where ( e = > ! string . IsNullOrWhiteSpace ( e ) ) )
{
foreach ( GraphicsElement ge in await GetGraphicsElementByPath ( element ) )
{
_ state . SetGraphicsElement ( ge . Id , variablesJson ) ;
}
}
}
public async Task GraphicsOff ( List < string > graphicsElements )
{
if ( graphicsElements . Count = = 0 )
{
_ state . ClearGraphicsElements ( ) ;
}
else
{
foreach ( string element in graphicsElements . Where ( e = > ! string . IsNullOrWhiteSpace ( e ) ) )
{
foreach ( GraphicsElement ge in await GetGraphicsElementByPath ( element ) )
{
_ state . RemoveGraphicsElement ( ge . Id ) ;
}
}
}
}
public async Task WatermarkOn ( List < string > watermarks )
{
foreach ( string watermark in watermarks . Where ( e = > ! string . IsNullOrWhiteSpace ( e ) ) )
{
foreach ( ChannelWatermark wm in await GetChannelWatermarkByName ( watermark ) )
{
_ state . SetChannelWatermarkId ( wm . Id ) ;
}
}
}
public async Task WatermarkOff ( List < string > watermarks )
{
if ( watermarks . Count = = 0 )
{
_ state . ClearChannelWatermarkIds ( ) ;
}
else
{
foreach ( string watermark in watermarks . Where ( e = > ! string . IsNullOrWhiteSpace ( e ) ) )
{
foreach ( ChannelWatermark wm in await GetChannelWatermarkByName ( watermark ) )
{
_ state . RemoveChannelWatermarkId ( wm . Id ) ;
}
}
}
}
public void SkipItems ( string content , int count )
{
if ( ! _ enumerators . TryGetValue ( content , out EnumeratorDetails enumeratorDetails ) )
{
logger . LogWarning ( "Unable to skip items for invalid content {Key}" , content ) ;
return ;
}
for ( var i = 0 ; i < count ; i + + )
{
enumeratorDetails . Enumerator . MoveNext ( ) ;
}
}
public void SkipToItem ( string content , int season , int episode )
{
if ( ! _ enumerators . TryGetValue ( content , out EnumeratorDetails enumeratorDetails ) )
{
logger . LogWarning ( "Unable to skip items for invalid content {Key}" , content ) ;
return ;
}
if ( season < 0 | | episode < 1 )
{
logger . LogWarning ( "Unable to skip to invalid season/episode: {Season}/{Episode}" , season , episode ) ;
return ;
}
var done = false ;
for ( var index = 0 ; index < enumeratorDetails . Enumerator . Count ; index + + )
{
if ( done )
{
break ;
}
foreach ( MediaItem mediaItem in enumeratorDetails . Enumerator . Current )
{
if ( mediaItem is Episode e )
{
if ( e . Season ? . SeasonNumber = = season & &
e . EpisodeMetadata . HeadOrNone ( ) . Map ( em = > em . EpisodeNumber ) = = episode )
{
done = true ;
break ;
}
}
enumeratorDetails . Enumerator . MoveNext ( ) ;
}
}
}
public ISchedulingEngine WaitUntil ( TimeOnly waitUntil , bool tomorrow , bool rewindOnReset )
{
var currentTime = _ state . CurrentTime ;
@ -763,6 +896,51 @@ public class SchedulingEngine(IMediaCollectionRepository mediaCollectionReposito
@@ -763,6 +896,51 @@ public class SchedulingEngine(IMediaCollectionRepository mediaCollectionReposito
return FillerKind . None ;
}
private async Task < Option < GraphicsElement > > GetGraphicsElementByPath ( string path )
{
if ( _ graphicsElementCache . TryGetValue ( path , out Option < GraphicsElement > cachedGraphicsElement ) )
{
foreach ( GraphicsElement graphicsElement in cachedGraphicsElement )
{
return graphicsElement ;
}
}
else
{
Option < GraphicsElement > maybeGraphicsElement =
await graphicsElementRepository . GetGraphicsElementByPath ( path ) ;
_ graphicsElementCache . Add ( path , maybeGraphicsElement ) ;
foreach ( GraphicsElement graphicsElement in maybeGraphicsElement )
{
return graphicsElement ;
}
}
return Option < GraphicsElement > . None ;
}
private async Task < Option < ChannelWatermark > > GetChannelWatermarkByName ( string name )
{
if ( _ watermarkCache . TryGetValue ( name , out Option < ChannelWatermark > cachedWatermark ) )
{
foreach ( ChannelWatermark channelWatermark in cachedWatermark )
{
return channelWatermark ;
}
}
else
{
Option < ChannelWatermark > maybeWatermark = await channelRepository . GetWatermarkByName ( name ) ;
_ watermarkCache . Add ( name , maybeWatermark ) ;
foreach ( ChannelWatermark channelWatermark in maybeWatermark )
{
return channelWatermark ;
}
}
return Option < ChannelWatermark > . None ;
}
public record SerializedState (
int? GuideGroup ,
bool? GuideGroupLocked ) ;
@ -771,6 +949,8 @@ public class SchedulingEngine(IMediaCollectionRepository mediaCollectionReposito
@@ -771,6 +949,8 @@ public class SchedulingEngine(IMediaCollectionRepository mediaCollectionReposito
{
private int _ guideGroup = guideGroup ;
private bool _ guideGroupLocked ;
private readonly Dictionary < int , string > _ graphicsElements = [ ] ;
private readonly System . Collections . Generic . HashSet < int > _ channelWatermarkIds = [ ] ;
// state
public int PlayoutId { get ; set ; }
@ -823,6 +1003,16 @@ public class SchedulingEngine(IMediaCollectionRepository mediaCollectionReposito
@@ -823,6 +1003,16 @@ public class SchedulingEngine(IMediaCollectionRepository mediaCollectionReposito
public void UnlockGuideGroup ( ) = > _ guideGroupLocked = false ;
public void SetGraphicsElement ( int id , string variablesJson ) = > _ graphicsElements . Add ( id , variablesJson ) ;
public void RemoveGraphicsElement ( int id ) = > _ graphicsElements . Remove ( id ) ;
public void ClearGraphicsElements ( ) = > _ graphicsElements . Clear ( ) ;
public Dictionary < int , string > GetGraphicsElements ( ) = > _ graphicsElements ;
public void SetChannelWatermarkId ( int id ) = > _ channelWatermarkIds . Add ( id ) ;
public void RemoveChannelWatermarkId ( int id ) = > _ channelWatermarkIds . Remove ( id ) ;
public void ClearChannelWatermarkIds ( ) = > _ channelWatermarkIds . Clear ( ) ;
public List < int > GetChannelWatermarkIds ( ) = > _ channelWatermarkIds . ToList ( ) ;
// result
public Option < DateTimeOffset > RemoveBefore { get ; set ; }
public bool ClearItems { get ; set ; }