implement keep up to

This commit is contained in:
Luke Pulverenti 2016-09-27 01:13:56 -04:00
parent adb39f4090
commit 64d63c1b4b
7 changed files with 130 additions and 21 deletions

View File

@ -9,6 +9,7 @@ namespace MediaBrowser.Controller.LiveTv
public TimerInfo()
{
Genres = new List<string>();
KeepUntil = KeepUntil.UntilDeleted;
}
/// <summary>
@ -109,5 +110,7 @@ namespace MediaBrowser.Controller.LiveTv
public string ShortOverview { get; set; }
public string OfficialRating { get; set; }
public List<string> Genres { get; set; }
public string RecordingPath { get; set; }
public KeepUntil KeepUntil { get; set; }
}
}

View File

@ -105,5 +105,6 @@ namespace MediaBrowser.Model.LiveTv
/// </summary>
/// <value><c>true</c> if this instance is post padding required; otherwise, <c>false</c>.</value>
public bool IsPostPaddingRequired { get; set; }
public KeepUntil KeepUntil { get; set; }
}
}

View File

@ -27,7 +27,6 @@ namespace MediaBrowser.Model.LiveTv
public bool RecordAnyChannel { get; set; }
public int KeepUpTo { get; set; }
public KeepUntil KeepUntil { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [record new only].

View File

@ -442,7 +442,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
private void CancelTimerInternal(string timerId, bool isSeriesCancelled)
{
var timer = _timerProvider.GetAll().FirstOrDefault(r => string.Equals(r.Id, timerId, StringComparison.OrdinalIgnoreCase));
var timer = _timerProvider.GetTimer(timerId);
if (timer != null)
{
if (string.IsNullOrWhiteSpace(timer.SeriesTimerId) || isSeriesCancelled)
@ -474,10 +474,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
return Task.FromResult(true);
}
public Task CreateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<string> CreateTimer(TimerInfo timer, CancellationToken cancellationToken)
{
var existingTimer = _timerProvider.GetAll()
.FirstOrDefault(i => string.Equals(info.ProgramId, i.ProgramId, StringComparison.OrdinalIgnoreCase));
.FirstOrDefault(i => string.Equals(timer.ProgramId, i.ProgramId, StringComparison.OrdinalIgnoreCase));
if (existingTimer != null)
{
@ -485,6 +495,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
existingTimer.Status = RecordingStatus.New;
_timerProvider.Update(existingTimer);
return Task.FromResult(existingTimer.Id);
}
else
{
@ -492,16 +503,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
}
}
return CreateTimer(info, cancellationToken);
}
public Task CreateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken)
{
return CreateSeriesTimer(info, cancellationToken);
}
public Task<string> CreateTimer(TimerInfo timer, CancellationToken cancellationToken)
{
timer.Id = Guid.NewGuid().ToString("N");
ProgramInfo programInfo = null;
@ -601,9 +602,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public Task UpdateTimerAsync(TimerInfo updatedTimer, CancellationToken cancellationToken)
{
var existingTimer = _timerProvider
.GetAll()
.FirstOrDefault(i => string.Equals(i.Id, updatedTimer.Id, StringComparison.OrdinalIgnoreCase));
var existingTimer = _timerProvider.GetTimer(updatedTimer.Id);
if (existingTimer == null)
{
@ -1137,6 +1136,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
_timerProvider.AddOrUpdate(timer, false);
SaveNfo(timer, recordPath, seriesPath);
EnforceKeepUpTo(timer);
};
var pathWithDuration = tunerHost.ApplyDuration(mediaStreamInfo.Path, duration);
@ -1148,8 +1148,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
mediaStreamInfo.RunTimeTicks = duration.Ticks;
}
await
recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken)
await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken)
.ConfigureAwait(false);
recordingStatus = RecordingStatus.Completed;
@ -1195,6 +1194,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
}
else if (File.Exists(recordPath))
{
timer.RecordingPath = recordPath;
timer.Status = RecordingStatus.Completed;
_timerProvider.AddOrUpdate(timer, false);
OnSuccessfulRecording(timer, recordPath);
@ -1205,6 +1205,102 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
}
}
private async void EnforceKeepUpTo(TimerInfo timer)
{
if (string.IsNullOrWhiteSpace(timer.SeriesTimerId))
{
return;
}
var seriesTimerId = timer.SeriesTimerId;
var seriesTimer = _seriesTimerProvider.GetAll().FirstOrDefault(i => string.Equals(i.Id, seriesTimerId, StringComparison.OrdinalIgnoreCase));
if (seriesTimer == null || seriesTimer.KeepUpTo <= 1)
{
return;
}
if (_disposed)
{
return;
}
await _recordingDeleteSemaphore.WaitAsync().ConfigureAwait(false);
try
{
if (_disposed)
{
return;
}
var timersToDelete = _timerProvider.GetAll()
.Where(i => i.Status == RecordingStatus.Completed && !string.IsNullOrWhiteSpace(i.RecordingPath))
.Where(i => string.Equals(i.SeriesTimerId, seriesTimerId, StringComparison.OrdinalIgnoreCase))
.OrderByDescending(i => i.EndDate)
.Where(i => File.Exists(i.RecordingPath))
.Skip(seriesTimer.KeepUpTo - 1)
.ToList();
await DeleteLibraryItemsForTimers(timersToDelete).ConfigureAwait(false);
}
finally
{
_recordingDeleteSemaphore.Release();
}
}
private readonly SemaphoreSlim _recordingDeleteSemaphore = new SemaphoreSlim(1,1);
private async Task DeleteLibraryItemsForTimers(List<TimerInfo> timers)
{
foreach (var timer in timers)
{
if (_disposed)
{
return;
}
try
{
await DeleteLibraryItemForTimer(timer).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.ErrorException("Error deleting recording", ex);
}
}
}
private async Task DeleteLibraryItemForTimer(TimerInfo timer)
{
var libraryItem = _libraryManager.FindByPath(timer.RecordingPath, false);
if (libraryItem != null)
{
await _libraryManager.DeleteItem(libraryItem, new DeleteOptions
{
DeleteFileLocation = true
});
}
else
{
try
{
File.Delete(timer.RecordingPath);
}
catch (DirectoryNotFoundException)
{
}
catch (FileNotFoundException)
{
}
}
_timerProvider.Delete(timer);
}
private string EnsureFileUnique(string path, string timerId)
{
var originalPath = path;
@ -1460,9 +1556,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
foreach (var timer in allTimers)
{
var existingTimer = _timerProvider
.GetAll()
.FirstOrDefault(i => string.Equals(i.Id, timer.Id, StringComparison.OrdinalIgnoreCase));
var existingTimer = _timerProvider.GetTimer(timer.Id);
if (existingTimer == null)
{
@ -1484,6 +1578,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
existingTimer.Status = RecordingStatus.Cancelled;
}
existingTimer.SeriesTimerId = seriesTimer.Id;
_timerProvider.Update(existingTimer);
}
}
@ -1649,8 +1745,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
return channelIds.SelectMany(GetEpgDataForChannel).ToList();
}
private bool _disposed;
public void Dispose()
{
_disposed = true;
foreach (var pair in _activeRecordings.ToList())
{
pair.Value.CancellationTokenSource.Cancel();

View File

@ -25,6 +25,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
timer.PostPaddingSeconds = series.PostPaddingSeconds;
timer.IsPostPaddingRequired = series.IsPostPaddingRequired;
timer.IsPrePaddingRequired = series.IsPrePaddingRequired;
timer.KeepUntil = series.KeepUntil;
timer.Priority = series.Priority;
timer.Name = parent.Name;
timer.Overview = parent.Overview;

View File

@ -156,5 +156,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
EventHelper.FireEventIfNotNull(TimerFired, this, new GenericEventArgs<TimerInfo> { Argument = timer }, Logger);
}
}
public TimerInfo GetTimer(string id)
{
return GetAll().FirstOrDefault(r => string.Equals(r.Id, id, StringComparison.OrdinalIgnoreCase));
}
}
}

View File

@ -52,6 +52,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
PostPaddingSeconds = info.PostPaddingSeconds,
IsPostPaddingRequired = info.IsPostPaddingRequired,
IsPrePaddingRequired = info.IsPrePaddingRequired,
KeepUntil = info.KeepUntil,
ExternalChannelId = info.ChannelId,
ExternalSeriesTimerId = info.SeriesTimerId,
ServiceName = service.Name,
@ -247,6 +248,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
PostPaddingSeconds = dto.PostPaddingSeconds,
IsPostPaddingRequired = dto.IsPostPaddingRequired,
IsPrePaddingRequired = dto.IsPrePaddingRequired,
KeepUntil = dto.KeepUntil,
Priority = dto.Priority,
SeriesTimerId = dto.ExternalSeriesTimerId,
ProgramId = dto.ExternalProgramId,