2015-07-20 11:32:55 -07:00
using MediaBrowser.Common.Events ;
using MediaBrowser.Controller.LiveTv ;
using MediaBrowser.Model.Events ;
using MediaBrowser.Model.Logging ;
using MediaBrowser.Model.Serialization ;
using System ;
using System.Collections.Concurrent ;
2016-01-28 12:10:56 -07:00
using System.Globalization ;
2015-07-20 11:32:55 -07:00
using System.Linq ;
using System.Threading ;
2015-10-03 21:23:11 -07:00
using CommonIO ;
2016-01-21 10:29:14 -07:00
using MediaBrowser.Controller.Power ;
2015-07-20 11:32:55 -07:00
namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
public class TimerManager : ItemDataProvider < TimerInfo >
{
private readonly ConcurrentDictionary < string , Timer > _timers = new ConcurrentDictionary < string , Timer > ( StringComparer . OrdinalIgnoreCase ) ;
2016-01-21 10:29:14 -07:00
private readonly IPowerManagement _powerManagement ;
private readonly ILogger _logger ;
2015-07-20 11:32:55 -07:00
public event EventHandler < GenericEventArgs < TimerInfo > > TimerFired ;
2016-01-21 10:29:14 -07:00
public TimerManager ( IFileSystem fileSystem , IJsonSerializer jsonSerializer , ILogger logger , string dataPath , IPowerManagement powerManagement , ILogger logger1 )
2015-09-13 16:07:54 -07:00
: base ( fileSystem , jsonSerializer , logger , dataPath , ( r1 , r2 ) = > string . Equals ( r1 . Id , r2 . Id , StringComparison . OrdinalIgnoreCase ) )
2015-07-20 11:32:55 -07:00
{
2016-01-21 10:29:14 -07:00
_powerManagement = powerManagement ;
_logger = logger1 ;
2015-07-20 11:32:55 -07:00
}
public void RestartTimers ( )
{
StopTimers ( ) ;
2015-07-28 20:42:03 -07:00
foreach ( var item in GetAll ( ) . ToList ( ) )
{
AddTimer ( item ) ;
}
2015-07-20 11:32:55 -07:00
}
public void StopTimers ( )
{
foreach ( var pair in _timers . ToList ( ) )
{
pair . Value . Dispose ( ) ;
}
_timers . Clear ( ) ;
}
public override void Delete ( TimerInfo item )
{
base . Delete ( item ) ;
2015-08-22 11:29:12 -07:00
StopTimer ( item ) ;
2015-07-20 11:32:55 -07:00
}
public override void Update ( TimerInfo item )
{
base . Update ( item ) ;
Timer timer ;
if ( _timers . TryGetValue ( item . Id , out timer ) )
{
var timespan = RecordingHelper . GetStartTime ( item ) - DateTime . UtcNow ;
timer . Change ( timespan , TimeSpan . Zero ) ;
2016-01-21 10:29:14 -07:00
ScheduleWake ( item ) ;
2015-07-20 11:32:55 -07:00
}
else
{
AddTimer ( item ) ;
}
}
public override void Add ( TimerInfo item )
{
if ( string . IsNullOrWhiteSpace ( item . Id ) )
{
throw new ArgumentException ( "TimerInfo.Id cannot be null or empty." ) ;
}
base . Add ( item ) ;
AddTimer ( item ) ;
2016-01-21 10:29:14 -07:00
ScheduleWake ( item ) ;
2015-07-20 11:32:55 -07:00
}
private void AddTimer ( TimerInfo item )
{
2015-07-28 20:42:03 -07:00
var startDate = RecordingHelper . GetStartTime ( item ) ;
var now = DateTime . UtcNow ;
if ( startDate < now )
{
EventHelper . FireEventIfNotNull ( TimerFired , this , new GenericEventArgs < TimerInfo > { Argument = item } , Logger ) ;
return ;
}
2015-08-22 11:29:12 -07:00
var timerLength = startDate - now ;
StartTimer ( item , timerLength ) ;
}
2015-07-20 11:32:55 -07:00
2016-01-21 10:29:14 -07:00
private void ScheduleWake ( TimerInfo info )
{
var startDate = RecordingHelper . GetStartTime ( info ) . AddMinutes ( - 5 ) ;
try
{
_powerManagement . ScheduleWake ( startDate ) ;
_logger . Info ( "Scheduled system wake timer at {0} (UTC)" , startDate ) ;
}
catch ( NotImplementedException )
{
}
catch ( Exception ex )
{
_logger . ErrorException ( "Error scheduling wake timer" , ex ) ;
}
}
2015-08-22 11:29:12 -07:00
public void StartTimer ( TimerInfo item , TimeSpan length )
{
StopTimer ( item ) ;
2015-11-20 21:55:26 -07:00
2015-08-22 11:29:12 -07:00
var timer = new Timer ( TimerCallback , item . Id , length , TimeSpan . Zero ) ;
2015-07-20 11:32:55 -07:00
2016-01-28 12:10:56 -07:00
if ( _timers . TryAdd ( item . Id , timer ) )
{
2016-01-28 20:43:20 -07:00
_logger . Info ( "Creating recording timer for {0}, {1}. Timer will fire in {2} minutes" , item . Id , item . Name , length . TotalMinutes . ToString ( CultureInfo . InvariantCulture ) ) ;
2016-01-28 12:10:56 -07:00
}
else
2015-07-20 11:32:55 -07:00
{
timer . Dispose ( ) ;
2016-01-28 12:10:56 -07:00
_logger . Warn ( "Timer already exists for item {0}" , item . Id ) ;
2015-07-20 11:32:55 -07:00
}
}
2015-08-22 11:29:12 -07:00
private void StopTimer ( TimerInfo item )
{
Timer timer ;
if ( _timers . TryRemove ( item . Id , out timer ) )
{
timer . Dispose ( ) ;
}
}
2015-07-20 11:32:55 -07:00
private void TimerCallback ( object state )
{
var timerId = ( string ) state ;
var timer = GetAll ( ) . FirstOrDefault ( i = > string . Equals ( i . Id , timerId , StringComparison . OrdinalIgnoreCase ) ) ;
if ( timer ! = null )
{
EventHelper . FireEventIfNotNull ( TimerFired , this , new GenericEventArgs < TimerInfo > { Argument = timer } , Logger ) ;
}
}
}
}