aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2016-09-27 01:13:56 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2016-09-27 01:13:56 -0400
commit64d63c1b4b1f5088cff899541b71c782e26a0a24 (patch)
tree843ac39a71bc5182ad5d780bba4c0bb0ed539df3
parentadb39f40904947917a14e260579098cbc0d9829d (diff)
implement keep up to
-rw-r--r--MediaBrowser.Controller/LiveTv/TimerInfo.cs3
-rw-r--r--MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs1
-rw-r--r--MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs1
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs138
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs1
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs5
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs2
7 files changed, 130 insertions, 21 deletions
diff --git a/MediaBrowser.Controller/LiveTv/TimerInfo.cs b/MediaBrowser.Controller/LiveTv/TimerInfo.cs
index ea21ba46e..42c3480ce 100644
--- a/MediaBrowser.Controller/LiveTv/TimerInfo.cs
+++ b/MediaBrowser.Controller/LiveTv/TimerInfo.cs
@@ -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; }
}
}
diff --git a/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs b/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs
index 4d863c6eb..0ceed70c0 100644
--- a/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs
+++ b/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs
@@ -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; }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs b/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs
index 77b915a75..ce65cc7bf 100644
--- a/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs
+++ b/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs
@@ -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].
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index 7cdb623f3..6ea3fbc5e 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -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();
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
index 67356da2f..f9c04abc5 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
@@ -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;
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs
index 28cec34f4..bddce0420 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs
@@ -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));
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
index 462bb2721..348bcd97b 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
@@ -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,