Restart schedule from bottom active item
This commit is contained in:
@@ -26,6 +26,7 @@ public sealed class ChannelScheduleEngine
|
|||||||
private TaskCompletionSource<bool>? _advanceSignal;
|
private TaskCompletionSource<bool>? _advanceSignal;
|
||||||
private Guid? _lastPlaybackItemId;
|
private Guid? _lastPlaybackItemId;
|
||||||
private Guid? _skipCurrentItemId;
|
private Guid? _skipCurrentItemId;
|
||||||
|
private Guid? _restartFromTopAfterItemId;
|
||||||
private ChannelScheduleItem? _directPlaybackItem;
|
private ChannelScheduleItem? _directPlaybackItem;
|
||||||
private PreparedCutFrame? _preparedCutFrame;
|
private PreparedCutFrame? _preparedCutFrame;
|
||||||
|
|
||||||
@@ -77,6 +78,12 @@ public sealed class ChannelScheduleEngine
|
|||||||
{
|
{
|
||||||
if (IsRunning)
|
if (IsRunning)
|
||||||
{
|
{
|
||||||
|
if (GetNextPlayableItem() is null)
|
||||||
|
{
|
||||||
|
await RestartFromTopAsync().ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await AdvanceToNextAsync().ConfigureAwait(false);
|
await AdvanceToNextAsync().ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -87,7 +94,10 @@ public sealed class ChannelScheduleEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
_lastPlaybackItemId = null;
|
_lastPlaybackItemId = null;
|
||||||
|
_skipCurrentItemId = null;
|
||||||
|
_restartFromTopAfterItemId = null;
|
||||||
ResetDataUnavailableItems();
|
ResetDataUnavailableItems();
|
||||||
|
ClearStalePlaybackStatesBeforeStart();
|
||||||
_playbackCts = new CancellationTokenSource();
|
_playbackCts = new CancellationTokenSource();
|
||||||
IsRunning = true;
|
IsRunning = true;
|
||||||
RefreshQueueMarkers();
|
RefreshQueueMarkers();
|
||||||
@@ -112,6 +122,7 @@ public sealed class ChannelScheduleEngine
|
|||||||
ClearPreparedFrame(resetState: true);
|
ClearPreparedFrame(resetState: true);
|
||||||
_lastPlaybackItemId = null;
|
_lastPlaybackItemId = null;
|
||||||
_skipCurrentItemId = null;
|
_skipCurrentItemId = null;
|
||||||
|
_restartFromTopAfterItemId = null;
|
||||||
RefreshQueueMarkers();
|
RefreshQueueMarkers();
|
||||||
QueueChanged?.Invoke(this, EventArgs.Empty);
|
QueueChanged?.Invoke(this, EventArgs.Empty);
|
||||||
return;
|
return;
|
||||||
@@ -135,6 +146,7 @@ public sealed class ChannelScheduleEngine
|
|||||||
|
|
||||||
_lastPlaybackItemId = null;
|
_lastPlaybackItemId = null;
|
||||||
_skipCurrentItemId = null;
|
_skipCurrentItemId = null;
|
||||||
|
_restartFromTopAfterItemId = null;
|
||||||
ClearPreparedFrame(resetState: false);
|
ClearPreparedFrame(resetState: false);
|
||||||
IsRunning = false;
|
IsRunning = false;
|
||||||
RefreshQueueMarkers();
|
RefreshQueueMarkers();
|
||||||
@@ -152,6 +164,8 @@ public sealed class ChannelScheduleEngine
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_lastPlaybackItemId = null;
|
_lastPlaybackItemId = null;
|
||||||
|
_skipCurrentItemId = null;
|
||||||
|
_restartFromTopAfterItemId = null;
|
||||||
ResetDataUnavailableItems();
|
ResetDataUnavailableItems();
|
||||||
ClearPreparedFrame(resetState: true);
|
ClearPreparedFrame(resetState: true);
|
||||||
RefreshQueueMarkers();
|
RefreshQueueMarkers();
|
||||||
@@ -260,6 +274,8 @@ public sealed class ChannelScheduleEngine
|
|||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
_lastPlaybackItemId = null;
|
_lastPlaybackItemId = null;
|
||||||
|
_skipCurrentItemId = null;
|
||||||
|
_restartFromTopAfterItemId = null;
|
||||||
ClearPreparedFrame(resetState: false);
|
ClearPreparedFrame(resetState: false);
|
||||||
foreach (var item in Queue)
|
foreach (var item in Queue)
|
||||||
{
|
{
|
||||||
@@ -327,6 +343,37 @@ public sealed class ChannelScheduleEngine
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Task RestartFromTopAsync()
|
||||||
|
{
|
||||||
|
if (!IsRunning)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
var activeItem = Queue.FirstOrDefault(item => item.State is ScheduleQueueItemState.OnAir or ScheduleQueueItemState.Sending);
|
||||||
|
if (activeItem is not null)
|
||||||
|
{
|
||||||
|
_skipCurrentItemId = activeItem.Id;
|
||||||
|
_restartFromTopAfterItemId = activeItem.Id;
|
||||||
|
_lastPlaybackItemId = null;
|
||||||
|
activeItem.State = ScheduleQueueItemState.Queued;
|
||||||
|
activeItem.LastError = string.Empty;
|
||||||
|
activeItem.CurrentRegionLabel = string.Empty;
|
||||||
|
activeItem.ClearInternalNextPreview();
|
||||||
|
activeItem.ClearPlaybackCountdown();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_lastPlaybackItemId = null;
|
||||||
|
_restartFromTopAfterItemId = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefreshQueueMarkers();
|
||||||
|
QueueChanged?.Invoke(this, EventArgs.Empty);
|
||||||
|
_advanceSignal?.TrySetResult(true);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
public bool Remove(ChannelScheduleItem? item)
|
public bool Remove(ChannelScheduleItem? item)
|
||||||
{
|
{
|
||||||
if (item is null || !item.CanDelete)
|
if (item is null || !item.CanDelete)
|
||||||
@@ -547,7 +594,7 @@ public sealed class ChannelScheduleEngine
|
|||||||
|
|
||||||
if (regionTargets.Count == 0)
|
if (regionTargets.Count == 0)
|
||||||
{
|
{
|
||||||
_lastPlaybackItemId = queueItem.Id;
|
MarkLastPlaybackItem(queueItem);
|
||||||
MarkDataUnavailable(queueItem, "선택한 지역 조건에 송출 가능한 데이터가 없습니다.");
|
MarkDataUnavailable(queueItem, "선택한 지역 조건에 송출 가능한 데이터가 없습니다.");
|
||||||
RefreshQueueMarkers();
|
RefreshQueueMarkers();
|
||||||
return;
|
return;
|
||||||
@@ -637,7 +684,7 @@ public sealed class ChannelScheduleEngine
|
|||||||
queueItem.CurrentRegionLabel = string.Empty;
|
queueItem.CurrentRegionLabel = string.Empty;
|
||||||
queueItem.ClearInternalNextPreview();
|
queueItem.ClearInternalNextPreview();
|
||||||
queueItem.ClearPlaybackCountdown();
|
queueItem.ClearPlaybackCountdown();
|
||||||
_lastPlaybackItemId = queueItem.Id;
|
MarkLastPlaybackItem(queueItem);
|
||||||
if (playedAny)
|
if (playedAny)
|
||||||
{
|
{
|
||||||
queueItem.State = ScheduleQueueItemState.Queued;
|
queueItem.State = ScheduleQueueItemState.Queued;
|
||||||
@@ -737,7 +784,7 @@ public sealed class ChannelScheduleEngine
|
|||||||
queueItem.CurrentRegionLabel = string.Empty;
|
queueItem.CurrentRegionLabel = string.Empty;
|
||||||
queueItem.ClearInternalNextPreview();
|
queueItem.ClearInternalNextPreview();
|
||||||
queueItem.ClearPlaybackCountdown();
|
queueItem.ClearPlaybackCountdown();
|
||||||
_lastPlaybackItemId = queueItem.Id;
|
MarkLastPlaybackItem(queueItem);
|
||||||
if (playedAny)
|
if (playedAny)
|
||||||
{
|
{
|
||||||
queueItem.State = ScheduleQueueItemState.Queued;
|
queueItem.State = ScheduleQueueItemState.Queued;
|
||||||
@@ -1770,6 +1817,36 @@ public sealed class ChannelScheduleEngine
|
|||||||
return item.State is ScheduleQueueItemState.Queued or ScheduleQueueItemState.Next or ScheduleQueueItemState.Completed;
|
return item.State is ScheduleQueueItemState.Queued or ScheduleQueueItemState.Next or ScheduleQueueItemState.Completed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MarkLastPlaybackItem(ChannelScheduleItem queueItem)
|
||||||
|
{
|
||||||
|
if (_restartFromTopAfterItemId == queueItem.Id)
|
||||||
|
{
|
||||||
|
_lastPlaybackItemId = null;
|
||||||
|
_restartFromTopAfterItemId = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastPlaybackItemId = queueItem.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearStalePlaybackStatesBeforeStart()
|
||||||
|
{
|
||||||
|
foreach (var item in Queue.Where(item => item.State is ScheduleQueueItemState.OnAir or ScheduleQueueItemState.Sending))
|
||||||
|
{
|
||||||
|
if (_preparedCutFrame?.Item.Id == item.Id)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.State = ScheduleQueueItemState.Queued;
|
||||||
|
item.LastError = string.Empty;
|
||||||
|
item.CurrentRegionLabel = string.Empty;
|
||||||
|
item.ClearRenderedPreview();
|
||||||
|
item.ClearInternalNextPreview();
|
||||||
|
item.ClearPlaybackCountdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ResetDataUnavailableItems()
|
private void ResetDataUnavailableItems()
|
||||||
{
|
{
|
||||||
foreach (var item in Queue.Where(item => item.State == ScheduleQueueItemState.DataUnavailable))
|
foreach (var item in Queue.Where(item => item.State == ScheduleQueueItemState.DataUnavailable))
|
||||||
|
|||||||
Reference in New Issue
Block a user