mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-09-06 13:57:14 -04:00
update recording scheduler
This commit is contained in:
parent
a83d6322e1
commit
4d7f983618
@ -17,6 +17,12 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <value>The series timer identifier.</value>
|
/// <value>The series timer identifier.</value>
|
||||||
public string SeriesTimerId { get; set; }
|
public string SeriesTimerId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the timer identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The timer identifier.</value>
|
||||||
|
public string TimerId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ChannelId of the recording.
|
/// ChannelId of the recording.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -12,7 +12,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.Channels
|
namespace MediaBrowser.Server.Implementations.Channels
|
||||||
{
|
{
|
||||||
public class ChannelPostScanTask : ILibraryPostScanTask
|
public class ChannelPostScanTask
|
||||||
{
|
{
|
||||||
private readonly IChannelManager _channelManager;
|
private readonly IChannelManager _channelManager;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using MediaBrowser.Common.ScheduledTasks;
|
using MediaBrowser.Common.ScheduledTasks;
|
||||||
using MediaBrowser.Controller.Channels;
|
using MediaBrowser.Controller.Channels;
|
||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -9,11 +10,15 @@ namespace MediaBrowser.Server.Implementations.Channels
|
|||||||
{
|
{
|
||||||
class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask
|
class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask
|
||||||
{
|
{
|
||||||
private readonly IChannelManager _manager;
|
private readonly IChannelManager _channelManager;
|
||||||
|
private readonly IUserManager _userManager;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public RefreshChannelsScheduledTask(IChannelManager manager)
|
public RefreshChannelsScheduledTask(IChannelManager channelManager, IUserManager userManager, ILogger logger)
|
||||||
{
|
{
|
||||||
_manager = manager;
|
_channelManager = channelManager;
|
||||||
|
_userManager = userManager;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
@ -31,11 +36,14 @@ namespace MediaBrowser.Server.Implementations.Channels
|
|||||||
get { return "Channels"; }
|
get { return "Channels"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Execute(System.Threading.CancellationToken cancellationToken, IProgress<double> progress)
|
public async Task Execute(System.Threading.CancellationToken cancellationToken, IProgress<double> progress)
|
||||||
{
|
{
|
||||||
var manager = (ChannelManager)_manager;
|
var manager = (ChannelManager)_channelManager;
|
||||||
|
|
||||||
return manager.RefreshChannels(progress, cancellationToken);
|
await manager.RefreshChannels(new Progress<double>(), cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await new ChannelPostScanTask(_channelManager, _userManager, _logger).Run(progress, cancellationToken)
|
||||||
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<ITaskTrigger> GetDefaultTriggers()
|
public IEnumerable<ITaskTrigger> GetDefaultTriggers()
|
||||||
@ -48,7 +56,7 @@ namespace MediaBrowser.Server.Implementations.Channels
|
|||||||
|
|
||||||
public bool IsHidden
|
public bool IsHidden
|
||||||
{
|
{
|
||||||
get { return true; }
|
get { return false; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsEnabled
|
public bool IsEnabled
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System.ComponentModel;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Common.IO;
|
|
||||||
using MediaBrowser.Common.ScheduledTasks;
|
using MediaBrowser.Common.ScheduledTasks;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
@ -372,15 +371,12 @@ namespace MediaBrowser.Server.Implementations.IO
|
|||||||
|
|
||||||
DisposeWatcher(dw);
|
DisposeWatcher(dw);
|
||||||
|
|
||||||
if (ex is Win32Exception)
|
if (ConfigurationManager.Configuration.EnableLibraryMonitor == AutoOnOff.Auto)
|
||||||
{
|
{
|
||||||
Logger.Info("Disabling realtime monitor to prevent future instability");
|
Logger.Info("Disabling realtime monitor to prevent future instability");
|
||||||
|
|
||||||
if (ConfigurationManager.Configuration.EnableLibraryMonitor == AutoOnOff.Auto)
|
ConfigurationManager.Configuration.EnableLibraryMonitor = AutoOnOff.Disabled;
|
||||||
{
|
Stop();
|
||||||
ConfigurationManager.Configuration.EnableLibraryMonitor = AutoOnOff.Disabled;
|
|
||||||
Stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,8 +33,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||||||
|
|
||||||
private readonly LiveTvManager _liveTvManager;
|
private readonly LiveTvManager _liveTvManager;
|
||||||
|
|
||||||
|
public static EmbyTV Current;
|
||||||
|
|
||||||
public EmbyTV(IApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IConfigurationManager config, ILiveTvManager liveTvManager)
|
public EmbyTV(IApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IConfigurationManager config, ILiveTvManager liveTvManager)
|
||||||
{
|
{
|
||||||
|
Current = this;
|
||||||
|
|
||||||
_appHpst = appHost;
|
_appHpst = appHost;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
@ -48,6 +52,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||||||
_timerProvider.TimerFired += _timerProvider_TimerFired;
|
_timerProvider.TimerFired += _timerProvider_TimerFired;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
_timerProvider.RestartTimers();
|
||||||
|
}
|
||||||
|
|
||||||
public event EventHandler DataSourceChanged;
|
public event EventHandler DataSourceChanged;
|
||||||
|
|
||||||
public event EventHandler<RecordingStatusChangedEventArgs> RecordingStatusChanged;
|
public event EventHandler<RecordingStatusChangedEventArgs> RecordingStatusChanged;
|
||||||
@ -147,7 +156,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||||||
|
|
||||||
public Task CancelSeriesTimerAsync(string timerId, CancellationToken cancellationToken)
|
public Task CancelSeriesTimerAsync(string timerId, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var remove = _seriesTimerProvider.GetAll().SingleOrDefault(r => r.Id == timerId);
|
var remove = _seriesTimerProvider.GetAll().FirstOrDefault(r => string.Equals(r.Id, timerId, StringComparison.OrdinalIgnoreCase));
|
||||||
if (remove != null)
|
if (remove != null)
|
||||||
{
|
{
|
||||||
_seriesTimerProvider.Delete(remove);
|
_seriesTimerProvider.Delete(remove);
|
||||||
@ -157,7 +166,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||||||
|
|
||||||
private void CancelTimerInternal(string timerId)
|
private void CancelTimerInternal(string timerId)
|
||||||
{
|
{
|
||||||
var remove = _timerProvider.GetAll().SingleOrDefault(r => r.Id == timerId);
|
var remove = _timerProvider.GetAll().FirstOrDefault(r => string.Equals(r.Id, timerId, StringComparison.OrdinalIgnoreCase));
|
||||||
if (remove != null)
|
if (remove != null)
|
||||||
{
|
{
|
||||||
_timerProvider.Delete(remove);
|
_timerProvider.Delete(remove);
|
||||||
@ -176,11 +185,24 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task DeleteRecordingAsync(string recordingId, CancellationToken cancellationToken)
|
public async Task DeleteRecordingAsync(string recordingId, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var remove = _recordingProvider.GetAll().FirstOrDefault(i => string.Equals(i.Id, recordingId, StringComparison.OrdinalIgnoreCase));
|
var remove = _recordingProvider.GetAll().FirstOrDefault(i => string.Equals(i.Id, recordingId, StringComparison.OrdinalIgnoreCase));
|
||||||
if (remove != null)
|
if (remove != null)
|
||||||
{
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(remove.TimerId))
|
||||||
|
{
|
||||||
|
var enableDelay = _activeRecordings.ContainsKey(remove.TimerId);
|
||||||
|
|
||||||
|
CancelTimerInternal(remove.TimerId);
|
||||||
|
|
||||||
|
if (enableDelay)
|
||||||
|
{
|
||||||
|
// A hack yes, but need to make sure the file is closed before attempting to delete it
|
||||||
|
await Task.Delay(3000).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File.Delete(remove.Path);
|
File.Delete(remove.Path);
|
||||||
@ -195,7 +217,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||||||
}
|
}
|
||||||
_recordingProvider.Delete(remove);
|
_recordingProvider.Delete(remove);
|
||||||
}
|
}
|
||||||
return Task.FromResult(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken)
|
public Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken)
|
||||||
@ -293,6 +314,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||||||
|
|
||||||
if (list.Count > 0)
|
if (list.Count > 0)
|
||||||
{
|
{
|
||||||
|
SaveEpgDataForChannel(channelId, list);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -430,7 +453,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||||||
}
|
}
|
||||||
|
|
||||||
var mediaStreamInfo = await GetChannelStream(timer.ChannelId, null, CancellationToken.None);
|
var mediaStreamInfo = await GetChannelStream(timer.ChannelId, null, CancellationToken.None);
|
||||||
var duration = (timer.EndDate - RecordingHelper.GetStartTime(timer)).TotalSeconds + timer.PrePaddingSeconds;
|
var duration = (timer.EndDate - DateTime.UtcNow).TotalSeconds + timer.PostPaddingSeconds;
|
||||||
|
|
||||||
HttpRequestOptions httpRequestOptions = new HttpRequestOptions()
|
HttpRequestOptions httpRequestOptions = new HttpRequestOptions()
|
||||||
{
|
{
|
||||||
@ -451,14 +474,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||||||
recordPath = Path.Combine(recordPath, RecordingHelper.GetRecordingName(timer, info));
|
recordPath = Path.Combine(recordPath, RecordingHelper.GetRecordingName(timer, info));
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(recordPath));
|
Directory.CreateDirectory(Path.GetDirectoryName(recordPath));
|
||||||
|
|
||||||
var recording = _recordingProvider.GetAll().FirstOrDefault(x => string.Equals(x.Id, info.Id, StringComparison.OrdinalIgnoreCase));
|
var recording = _recordingProvider.GetAll().FirstOrDefault(x => string.Equals(x.ProgramId, info.Id, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
if (recording == null)
|
if (recording == null)
|
||||||
{
|
{
|
||||||
recording = new RecordingInfo()
|
recording = new RecordingInfo()
|
||||||
{
|
{
|
||||||
ChannelId = info.ChannelId,
|
ChannelId = info.ChannelId,
|
||||||
Id = info.Id,
|
Id = Guid.NewGuid().ToString("N"),
|
||||||
StartDate = info.StartDate,
|
StartDate = info.StartDate,
|
||||||
EndDate = info.EndDate,
|
EndDate = info.EndDate,
|
||||||
Genres = info.Genres ?? null,
|
Genres = info.Genres ?? null,
|
||||||
@ -480,7 +503,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||||||
OriginalAirDate = info.OriginalAirDate,
|
OriginalAirDate = info.OriginalAirDate,
|
||||||
Status = RecordingStatus.Scheduled,
|
Status = RecordingStatus.Scheduled,
|
||||||
Overview = info.Overview,
|
Overview = info.Overview,
|
||||||
SeriesTimerId = info.Id.Substring(0, 10)
|
SeriesTimerId = info.Id.Substring(0, 10),
|
||||||
|
TimerId = timer.Id
|
||||||
};
|
};
|
||||||
_recordingProvider.Add(recording);
|
_recordingProvider.Add(recording);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
using MediaBrowser.Controller.Plugins;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
||||||
|
{
|
||||||
|
public class EntryPoint : IServerEntryPoint
|
||||||
|
{
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
EmbyTV.Current.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,10 @@
|
|||||||
using System.Text;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.Extensions;
|
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Model.Extensions;
|
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
||||||
{
|
{
|
||||||
@ -49,10 +48,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||||||
|
|
||||||
public static DateTime GetStartTime(TimerInfo timer)
|
public static DateTime GetStartTime(TimerInfo timer)
|
||||||
{
|
{
|
||||||
if (timer.StartDate.AddSeconds(-timer.PrePaddingSeconds + 1) < DateTime.UtcNow)
|
|
||||||
{
|
|
||||||
return DateTime.UtcNow.AddSeconds(1);
|
|
||||||
}
|
|
||||||
return timer.StartDate.AddSeconds(-timer.PrePaddingSeconds);
|
return timer.StartDate.AddSeconds(-timer.PrePaddingSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||||||
public void RestartTimers()
|
public void RestartTimers()
|
||||||
{
|
{
|
||||||
StopTimers();
|
StopTimers();
|
||||||
|
|
||||||
|
foreach (var item in GetAll().ToList())
|
||||||
|
{
|
||||||
|
AddTimer(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopTimers()
|
public void StopTimers()
|
||||||
@ -90,7 +95,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||||||
|
|
||||||
private void AddTimer(TimerInfo item)
|
private void AddTimer(TimerInfo item)
|
||||||
{
|
{
|
||||||
var timespan = RecordingHelper.GetStartTime(item) - DateTime.UtcNow;
|
var startDate = RecordingHelper.GetStartTime(item);
|
||||||
|
var now = DateTime.UtcNow;
|
||||||
|
|
||||||
|
if (startDate < now)
|
||||||
|
{
|
||||||
|
EventHelper.FireEventIfNotNull(TimerFired, this, new GenericEventArgs<TimerInfo> { Argument = item }, Logger);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var timespan = startDate - now;
|
||||||
|
|
||||||
var timer = new Timer(TimerCallback, item.Id, timespan, TimeSpan.Zero);
|
var timer = new Timer(TimerCallback, item.Id, timespan, TimeSpan.Zero);
|
||||||
|
|
||||||
|
@ -217,6 +217,7 @@
|
|||||||
<Compile Include="Library\Validators\YearsPostScanTask.cs" />
|
<Compile Include="Library\Validators\YearsPostScanTask.cs" />
|
||||||
<Compile Include="LiveTv\ChannelImageProvider.cs" />
|
<Compile Include="LiveTv\ChannelImageProvider.cs" />
|
||||||
<Compile Include="LiveTv\EmbyTV\EmbyTV.cs" />
|
<Compile Include="LiveTv\EmbyTV\EmbyTV.cs" />
|
||||||
|
<Compile Include="LiveTv\EmbyTV\EntryPoint.cs" />
|
||||||
<Compile Include="LiveTv\EmbyTV\ItemDataProvider.cs" />
|
<Compile Include="LiveTv\EmbyTV\ItemDataProvider.cs" />
|
||||||
<Compile Include="LiveTv\EmbyTV\RecordingHelper.cs" />
|
<Compile Include="LiveTv\EmbyTV\RecordingHelper.cs" />
|
||||||
<Compile Include="LiveTv\EmbyTV\SeriesTimerManager.cs" />
|
<Compile Include="LiveTv\EmbyTV\SeriesTimerManager.cs" />
|
||||||
|
@ -37,7 +37,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
|
|||||||
|
|
||||||
new StartupTrigger(),
|
new StartupTrigger(),
|
||||||
|
|
||||||
new IntervalTrigger{ Interval = TimeSpan.FromHours(6)}
|
new IntervalTrigger{ Interval = TimeSpan.FromHours(8)}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -742,9 +742,6 @@
|
|||||||
<Content Include="dashboard-ui\livetvnewrecording.html">
|
<Content Include="dashboard-ui\livetvnewrecording.html">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="dashboard-ui\livetvprogram.html">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="dashboard-ui\livetvrecording.html">
|
<Content Include="dashboard-ui\livetvrecording.html">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
@ -1006,9 +1003,6 @@
|
|||||||
<Content Include="dashboard-ui\scripts\livetvnewrecording.js">
|
<Content Include="dashboard-ui\scripts\livetvnewrecording.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="dashboard-ui\scripts\livetvprogram.js">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="dashboard-ui\scripts\livetvrecording.js">
|
<Content Include="dashboard-ui\scripts\livetvrecording.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
Loading…
Reference in New Issue
Block a user