/// <summary>
        /// Erzeugt eine neue Planung.
        /// </summary>
        /// <param name="resource">Das zugehörige Gerät.</param>
        /// <param name="schedulePlan">Die zugehörige Gesamtplanung.</param>
        /// <param name="decryptionCounter">Die Zähler für die Entschlüsselung.</param>
        /// <param name="allocations">Optional alle bereits vorgenommenen Zuordnungen.</param>
        /// <param name="planTime">Der aktuelle Planungsbeginn, sofern bekannt.</param>
        /// <exception cref="ArgumentNullException">Es wurde kein Gerät angegeben.</exception>
        public ResourcePlan(IScheduleResource resource, SchedulePlan schedulePlan, HashSet <Guid> decryptionCounter = null, AllocationMap allocations = null, DateTime?planTime = null)
        {
            // Remember
            SchedulePlan = schedulePlan;
            Resource     = resource;

            // Register a single decryption counter
            DecryptionCounters = decryptionCounter ?? new HashSet <Guid> {
                schedulePlan.RegisterDecryption(Resource.Decryption.MaximumParallelSources)
            };

            // Check for allocation
            if (allocations != null)
            {
                // Just clone
                Allocations = allocations.Clone(planTime);
            }
            else
            {
                // Number of sources we may use
                var sourceLimit = resource.SourceLimit;
                if (sourceLimit < 1)
                {
                    sourceLimit = int.MaxValue;
                }

                // Create brand new
                Allocations = new AllocationMap(sourceLimit, CheckForSourceGroupMatch);
            }
        }
Example #2
0
 /// <summary>
 /// Erzeugt eine neue Beschreibung.
 /// </summary>
 /// <param name="definition">Die ursprüngliche Beschreibung der Aufzeichnung.</param>
 /// <param name="resource">Das zu verwendende Gerät.</param>
 /// <param name="time">Die tatsächliche Ausführungszeit.</param>
 /// <param name="late">Gesetzt, wenn die Ausführung verspätet beginnt.</param>
 internal ScheduleInfo( IScheduleDefinition definition, IScheduleResource resource, PlannedTime time, bool late )
 {
     // Remember
     Definition = definition;
     Resource = resource;
     StartsLate = late;
     Time = time;
 }
Example #3
0
 /// <summary>
 /// Erzeugt eine neue Beschreibung.
 /// </summary>
 /// <param name="definition">Die ursprüngliche Beschreibung der Aufzeichnung.</param>
 /// <param name="resource">Das zu verwendende Gerät.</param>
 /// <param name="time">Die tatsächliche Ausführungszeit.</param>
 /// <param name="late">Gesetzt, wenn die Ausführung verspätet beginnt.</param>
 internal ScheduleInfo(IScheduleDefinition definition, IScheduleResource resource, PlannedTime time, bool late)
 {
     // Remember
     Definition = definition;
     Resource   = resource;
     StartsLate = late;
     Time       = time;
 }
Example #4
0
            /// <summary>
            /// Ergänzt ein Gerät.
            /// </summary>
            /// <param name="resource">Das gewünschte Gerät.</param>
            public void Add(IScheduleResource resource)
            {
                // Not allowed
                if (m_CurrentPlan != null)
                {
                    throw new NotSupportedException("Add");
                }

                // Forward
                m_Resources.Add(resource);
            }
Example #5
0
            /// <summary>
            /// Aktiviert eine Aufzeichnung auf einem Gerät.
            /// </summary>
            /// <param name="resource">Eines der verwalteten Geräte.</param>
            /// <param name="source">Optional eine Quelle, die auf dem Gerät angesteuert werden kann.</param>
            /// <param name="scheduleIdentifier">Die eindeutige Kennung der Aufzeichnung.</param>
            /// <param name="scheduleName">Der Anzeigename der Aufzeichnung.</param>
            /// <param name="plannedStart">Der ursprüngliche Start der Aufzeichnung in UTC / GMT Notation.</param>
            /// <param name="currentEnd">Das aktuelle Ende der Aufzeichnung in UTC / GMT Notation.</param>
            /// <returns>Gesetzt, wenn die Aufzeichnung auf dem gewünschten Gerät aktiviert werden kann.</returns>
            /// <exception cref="ArgumentNullException">Es wurde kein Gerät angegeben.</exception>
            /// <exception cref="ArgumentException">Das Gerät ist nicht bekannt oder kann die Quelle nicht empfangen.</exception>
            /// <exception cref="ArgumentOutOfRangeException">Die Laufzeit der Aufzeichnung ist nicht positiv.</exception>
            public bool Start(IScheduleResource resource, IScheduleSource source, Guid scheduleIdentifier, string scheduleName, DateTime plannedStart, DateTime currentEnd)
            {
                // Validate
                if (resource == null)
                {
                    throw new ArgumentNullException("resource");
                }
                if (!m_Resources.Contains(resource))
                {
                    throw new ArgumentException(resource.Name, "resource");
                }
                if (plannedStart >= currentEnd)
                {
                    throw new ArgumentOutOfRangeException("currentEnd");
                }
                if (m_Recordings.Any(r => r.UniqueIdentifier == scheduleIdentifier))
                {
                    throw new ArgumentException("resource");
                }

                // Create helper entry
                m_Recordings.Add(new ResourceAllocationInformation(resource, source, scheduleIdentifier, scheduleName, plannedStart, currentEnd - plannedStart));

                // May require cleanup
                try
                {
                    // Create the new plan
                    var plan = CreateSchedulePlan();

                    // Did it
                    if (plan != null)
                    {
                        // Remember as current
                        m_CurrentPlan = plan;

                        // Report
                        return(true);
                    }
                }
                catch
                {
                    // Cleanup
                    m_Recordings.RemoveAt(m_Recordings.Count - 1);

                    // Report
                    throw;
                }

                // Cleanup
                m_Recordings.RemoveAt(m_Recordings.Count - 1);

                // Add to list
                return(false);
            }
 /// <summary>
 /// Erstellt einen periodischen Auftrag für die Aktualisierung der Liste der Quellen.
 /// </summary>
 /// <param name="resource">Die zu verwendende Ressource.</param>
 /// <param name="profile">Das zugehörige Geräteprofil.</param>
 /// <returns>Der gewünschte Auftrag.</returns>
 PeriodicScheduler IRecordingPlannerSite.CreateSourceScanTask(IScheduleResource resource, Profile profile)
 {
     // Protect against misuse
     if (m_profiles.TryGetValue(profile.Name, out ProfileState state))
     {
         return(new SourceListTask(resource, state));
     }
     else
     {
         return(null);
     }
 }
        /// <summary>
        /// Erzeugt eine neue Beschreibung.
        /// </summary>
        /// <param name="resource">Das zugehörige Gerät.</param>
        /// <param name="source">Optional die zu verwendende Quelle.</param>
        /// <param name="identifier">Die eindeutige Kennung der zugehörigen Aufzeichnung oder Aufgabe.</param>
        /// <param name="name">Der Name der Aufzeichnung.</param>
        /// <param name="start">Der Startzeitpunkt.</param>
        /// <param name="duration">Die Dauer der Aufzeichnung.</param>
        /// <exception cref="ArgumentOutOfRangeException">Die Dauer der Aufzeichnung ist negativ.</exception>
        public ResourceAllocationInformation( IScheduleResource resource, IScheduleSource source, Guid identifier, string name, DateTime start, TimeSpan duration )
        {
            // Validate
            if (duration.TotalSeconds <= 0)
                throw new ArgumentOutOfRangeException( "duration" );

            // Remember all
            Time = new PlannedTime { Start = start, Duration = duration };
            Resources = new[] { resource };
            UniqueIdentifier = identifier;
            Source = source;
            Name = name;
        }
        /// <summary>
        /// Erstellt einen periodischen Auftrag für die Aktualisierung der Programmzeitschrift.
        /// </summary>
        /// <param name="resource">Die zu verwendende Ressource.</param>
        /// <param name="profile">Das zugehörige Geräteprofil.</param>
        /// <returns>Der gewünschte Auftrag.</returns>
        PeriodicScheduler IRecordingPlannerSite.CreateProgramGuideTask(IScheduleResource resource, Profile profile)
        {
            // Protect against misuse
            ProfileState state;

            if (m_profiles.TryGetValue(profile.Name, out state))
            {
                return(new ProgramGuideTask(resource, state));
            }
            else
            {
                return(null);
            }
        }
        /// <summary>
        /// Default constructor for <see cref="FeedingManager"/>
        /// </summary>
        /// <param name="schedulingEngine"></param>
        public DefaultFeedingManager(IOptions <FeedingManagerOptions> options, ILogger <DefaultFeedingManager> logger, ISchedulingEngine schedulingEngine, IThingsResource thingsResource, IScheduleResource scheduleResource)
        {
            _schedulingEngine = schedulingEngine;
            _logger           = logger;
            _scheduleResource = scheduleResource;
            Slots             = new List <FeedingSlot>();

            if (options.Value?.FeedingSlots?.Any() == true)
            {
                foreach (var slotConfig in options.Value.FeedingSlots)
                {
                    Slots.Add(new FeedingSlot(slotConfig, Slots, thingsResource));
                }
            }
        }
        /// <summary>
        /// Erzeugt eine neue Verwaltung.
        /// </summary>
        /// <param name="forResource">Das Geräteprofil, auf dem der Lauf erfolgen soll.</param>
        /// <param name="profile">Das zugehörige Geräteprofil.</param>
        /// <param name="lastUpdate">Methode zur Ermittelung des letzten Aktualisierungszeitpunktes.</param>
        /// <exception cref="ArgumentNullException">Der letzte Aktualisierungszeitpunkt ist nicht gesetzt.</exception>
        private SourceListTask( IScheduleResource forResource, ProfileState profile, Func<DateTime?> lastUpdate )
            : base( "Sendersuchlauf", Guid.NewGuid() )
        {
            // Validate
            if (forResource == null)
                throw new ArgumentNullException( nameof( forResource ) );
            if (lastUpdate == null)
                throw new ArgumentNullException( nameof( lastUpdate ) );

            // Remember
            m_Resources = new[] { forResource };
            m_LastUpdate = lastUpdate;

            // Set the job directory
            if (profile != null)
                CollectorDirectory = profile.Server.JobManager.CollectorDirectory;
        }
Example #11
0
        /// <summary>
        /// Erzeugt eine neue Verwaltung.
        /// </summary>
        /// <param name="forResource">Das Geräteprofil, auf dem der Lauf erfolgen soll.</param>
        /// <param name="profile">Das zugehörige Geräteprofil.</param>
        /// <param name="lastUpdate">Methode zur Ermittelung des letzten Aktualisierungszeitpunktes.</param>
        /// <exception cref="ArgumentNullException">Der letzte Aktualisierungszeitpunkt ist nicht gesetzt.</exception>
        private SourceListTask(IScheduleResource forResource, ProfileState profile, Func <DateTime?> lastUpdate)
            : base("Sendersuchlauf", Guid.NewGuid())
        {
            // Validate
            if (forResource == null)
            {
                throw new ArgumentNullException(nameof(forResource));
            }
            if (lastUpdate == null)
            {
                throw new ArgumentNullException(nameof(lastUpdate));
            }

            // Remember
            m_Resources  = new[] { forResource };
            m_LastUpdate = lastUpdate;

            // Set the job directory
            if (profile != null)
            {
                CollectorDirectory = profile.Server.JobManager.CollectorDirectory;
            }
        }
Example #12
0
 /// <summary>
 /// Erstellt eine periodische Aufgabe zum Aktualisieren der Quellen.
 /// </summary>
 /// <param name="resource">Die zugehörige Ressource.</param>
 /// <param name="profile">Die vollen Informationen zum Geräteprofil.</param>
 /// <returns>Die Beschreibung der Aufgabe oder <i>null</i>.</returns>
 public PeriodicScheduler CreateSourceScanTask(IScheduleResource resource, Profile profile)
 {
     // Forward
     return(new SourceListTask(resource, () => m_lastRunScan[resource.Name]));
 }
Example #13
0
 /// <summary>
 /// Erstellt eine periodische Aufgabe zum Aktualisieren der Programmzeitschrift.
 /// </summary>
 /// <param name="resource">Die zugehörige Ressource.</param>
 /// <param name="profile">Die vollen Informationen zum Geräteprofil.</param>
 /// <returns>Die Beschreibung der Aufgabe oder <i>null</i>.</returns>
 public PeriodicScheduler CreateProgramGuideTask(IScheduleResource resource, Profile profile)
 {
     // Forward
     return(new ProgramGuideTask(resource, () => m_lastRunGuide[resource.Name]));
 }
Example #14
0
 /// <summary>
 /// Erzeugt eine neue Simulation.
 /// </summary>
 /// <param name="resource">Das zu verwendende Gerät.</param>
 public _TaskMock( IScheduleResource resource )
     : base( "task", Guid.NewGuid() )
 {
     // Remember
     m_Resources = new[] { resource };
 }
 public SystemController(IThingsResource thingsResource, IScheduleResource scheduleResource, IFeedingManager feedingManager)
 {
     _thingsResource   = thingsResource;
     _scheduleResource = scheduleResource;
     _feedingManager   = feedingManager;
 }
Example #16
0
 /// <summary>
 /// Erzeugt eine neue Simulation.
 /// </summary>
 /// <param name="resource">Das zu verwendende Gerät.</param>
 public _TaskMock(IScheduleResource resource)
     : base("task", Guid.NewGuid())
 {
     // Remember
     m_Resources = new[] { resource };
 }
Example #17
0
 /// <summary>
 /// Erzeugt eine neue Verwaltung.
 /// </summary>
 /// <param name="forResource">Das Geräteprofil, auf dem der Lauf erfolgen soll.</param>
 /// <param name="profile">Das zugehörige Geräteprofil.</param>
 public SourceListTask(IScheduleResource forResource, ProfileState profile)
     : this(forResource, profile, () => profile.LastSourceUpdateTime)
 {
 }
Example #18
0
 /// <summary>
 /// Erzeugt eine neue Verwaltung.
 /// </summary>
 /// <param name="forResource">Das Geräteprofil, auf dem der Lauf erfolgen soll.</param>
 /// <param name="lastUpdate">Methode zur Ermittelung des letzten Aktualisierungszeitpunktes.</param>
 public SourceListTask(IScheduleResource forResource, Func <DateTime?> lastUpdate)
     : this(forResource, null, lastUpdate)
 {
 }
 /// <summary>
 /// Erstellt eine periodische Aufgabe zum Aktualisieren der Programmzeitschrift.
 /// </summary>
 /// <param name="resource">Die zugehörige Ressource.</param>
 /// <param name="profile">Die vollen Informationen zum Geräteprofil.</param>
 /// <returns>Die Beschreibung der Aufgabe oder <i>null</i>.</returns>
 public PeriodicScheduler CreateProgramGuideTask( IScheduleResource resource, Profile profile )
 {
     // Forward
     return new ProgramGuideTask( resource, () => m_lastRunGuide[resource.Name] );
 }
 /// <summary>
 /// Meldet ein Gerät zur Verwendung an.
 /// </summary>
 /// <param name="resource">Das gewünschte Gerät.</param>
 public void Add(IScheduleResource resource)
 {
     // Blind forward
     Resources.Add(resource);
 }
        /// <summary>
        /// Diese Methode verteilt Aufgaben an Geräte, die eine Zeitlang nicht in Benutzung sind.
        /// </summary>
        /// <param name="resource">Das zu verwendende Gerät.</param>
        /// <param name="startFree">Der Anfang des unbenutzten Bereiches.</param>
        /// <param name="endFree">Das Ende des unbenutzten Bereiches.</param>
        /// <param name="tasks">Die Liste der Aufgaben.</param>
        /// <returns>Alle Aufgaben, die dem Gerät in der unbenutzten Zeit zugeordnet wurden.</returns>
        private IEnumerable <ScheduleInfo> DispatchTasksForResource(IScheduleResource resource, DateTime startFree, DateTime endFree, List <_Task> tasks)
        {
            // See if there is room left to run a task
            while ((tasks.Count > 0) && (endFree > startFree))
            {
                // Load duration
                var duration = endFree - startFree;

                // Best task
                var tiBest = -1;

                // From all tasks fitting choose the one which starts first
                for (var ti = 0; ti < tasks.Count; ti++)
                {
                    // See if resource could be used
                    var task = tasks[ti];
                    if (!task.AllowedResources.Contains(resource, ReferenceComparer <IScheduleResource> .Default))
                    {
                        continue;
                    }

                    // Not enough time - skip
                    var planned = task.Current.Planned;
                    if (planned.Duration.Ticks <= 0)
                    {
                        continue;
                    }
                    if (planned.Duration > duration)
                    {
                        continue;
                    }

                    // Will not end before resource is reused
                    if (planned.End > endFree)
                    {
                        continue;
                    }

                    // Check for best
                    if (tiBest < 0)
                    {
                        tiBest = ti;
                    }
                    else if (planned.Start < tasks[tiBest].Current.Planned.Start)
                    {
                        tiBest = ti;
                    }
                }

                // Found nothing
                if (tiBest < 0)
                {
                    break;
                }

                // Reload
                var bestTask = tasks[tiBest];
                var bestPlan = bestTask.Current;

                // Check mode
                var startsLate = bestPlan.Planned.Start < startFree;
                if (startsLate)
                {
                    bestPlan.Planned.Start = startFree;
                }

                // Set the new free area
                startFree = bestPlan.Planned.End;

#if !SILVERLIGHT
                // Trace
                if (SchedulerTrace.TraceInfo)
                {
                    Trace.TraceInformation
                    (
                        startsLate ? Properties.SchedulerResources.Trace_LateTask : Properties.SchedulerResources.Trace_NormalTask,
                        resource,
                        bestPlan.Planned.Start,
                        bestPlan.Planned.Duration
                    );
                }
#endif

                // Report
                yield return(new ScheduleInfo(bestTask.Definition, resource, bestPlan.Planned, startsLate));

                // Advance
                bestTask.MoveNext();

                // Get rid of it
                if (bestTask.Current == null)
                {
                    tasks.RemoveAt(tiBest);
                }
            }
        }
        /// <summary>
        /// Diese Methode verteilt Aufgaben an Geräte, die eine Zeitlang nicht in Benutzung sind.
        /// </summary>
        /// <param name="resource">Das zu verwendende Gerät.</param>
        /// <param name="startFree">Der Anfang des unbenutzten Bereiches.</param>
        /// <param name="endFree">Das Ende des unbenutzten Bereiches.</param>
        /// <param name="tasks">Die Liste der Aufgaben.</param>
        /// <returns>Alle Aufgaben, die dem Gerät in der unbenutzten Zeit zugeordnet wurden.</returns>
        private IEnumerable<ScheduleInfo> DispatchTasksForResource( IScheduleResource resource, DateTime startFree, DateTime endFree, List<_Task> tasks )
        {
            // See if there is room left to run a task
            while ((tasks.Count > 0) && (endFree > startFree))
            {
                // Load duration
                var duration = endFree - startFree;

                // Best task
                var tiBest = -1;

                // From all tasks fitting choose the one which starts first
                for (var ti = 0; ti < tasks.Count; ti++)
                {
                    // See if resource could be used
                    var task = tasks[ti];
                    if (!task.AllowedResources.Contains( resource, ReferenceComparer<IScheduleResource>.Default ))
                        continue;

                    // Not enough time - skip
                    var planned = task.Current.Planned;
                    if (planned.Duration.Ticks <= 0)
                        continue;
                    if (planned.Duration > duration)
                        continue;

                    // Will not end before resource is reused
                    if (planned.End > endFree)
                        continue;

                    // Check for best
                    if (tiBest < 0)
                        tiBest = ti;
                    else if (planned.Start < tasks[tiBest].Current.Planned.Start)
                        tiBest = ti;
                }

                // Found nothing
                if (tiBest < 0)
                    break;

                // Reload
                var bestTask = tasks[tiBest];
                var bestPlan = bestTask.Current;

                // Check mode
                var startsLate = bestPlan.Planned.Start < startFree;
                if (startsLate)
                    bestPlan.Planned.Start = startFree;

                // Set the new free area
                startFree = bestPlan.Planned.End;

#if !SILVERLIGHT
                // Trace
                if (SchedulerTrace.TraceInfo)
                    Trace.TraceInformation
                        (
                            startsLate ? Properties.SchedulerResources.Trace_LateTask : Properties.SchedulerResources.Trace_NormalTask,
                            resource,
                            bestPlan.Planned.Start,
                            bestPlan.Planned.Duration
                        );
#endif

                // Report
                yield return new ScheduleInfo( bestTask.Definition, resource, bestPlan.Planned, startsLate );

                // Advance
                bestTask.MoveNext();

                // Get rid of it
                if (bestTask.Current == null)
                    tasks.RemoveAt( tiBest );
            }
        }
 /// <summary>
 /// Erzeugt eine neue Verwaltung.
 /// </summary>
 /// <param name="forResource">Das Geräteprofil, auf dem der Lauf erfolgen soll.</param>
 /// <param name="profile">Das zugehörige Geräteprofil.</param>
 public SourceListTask( IScheduleResource forResource, ProfileState profile )
     : this( forResource, profile, () => profile.LastSourceUpdateTime )
 {
 }
 /// <summary>
 /// Erzeugt eine neue Verwaltung.
 /// </summary>
 /// <param name="forResource">Das Geräteprofil, auf dem der Lauf erfolgen soll.</param>
 /// <param name="lastUpdate">Methode zur Ermittelung des letzten Aktualisierungszeitpunktes.</param>
 public SourceListTask( IScheduleResource forResource, Func<DateTime?> lastUpdate )
     : this( forResource, null, lastUpdate )
 {
 }
 /// <summary>
 /// Erzeugt eine neue Verwaltung.
 /// </summary>
 /// <param name="forResource">Das Gerät, für das die Sammlung erfolgt.</param>
 /// <param name="lastUpdate">Methode zur Ermittelung des letzten Aktualisierungszeitpunktes.</param>
 public ProgramGuideTask(IScheduleResource forResource, Func <DateTime?> lastUpdate)
     : this(forResource, null, lastUpdate)
 {
 }
 /// <summary>
 /// Default constructor for <see cref="SchedulingEngine"/>
 /// </summary>
 /// <param name="scheduleResource"></param>
 public SchedulingEngine(IScheduleResource scheduleResource)
 {
     _scheduleResource = scheduleResource;
 }
 /// <summary>
 /// Erzeugt eine neue Verwaltung.
 /// </summary>
 /// <param name="forResource">Das Gerät, für das die Sammlung erfolgt.</param>
 /// <param name="profile">Das zugehörige Geräteprofil.</param>
 public ProgramGuideTask( IScheduleResource forResource, ProfileState profile )
     : this( forResource, profile, () => profile.ProgramGuide.LastUpdateTime )
 {
 }
 /// <summary>
 /// Erstellt eine periodische Aufgabe zum Aktualisieren der Quellen.
 /// </summary>
 /// <param name="resource">Die zugehörige Ressource.</param>
 /// <param name="profile">Die vollen Informationen zum Geräteprofil.</param>
 /// <returns>Die Beschreibung der Aufgabe oder <i>null</i>.</returns>
 public PeriodicScheduler CreateSourceScanTask( IScheduleResource resource, Profile profile )
 {
     // Forward
     return new SourceListTask( resource, () => m_lastRunScan[resource.Name] );
 }
 /// <summary>
 /// Erzeugt eine neue Verwaltung.
 /// </summary>
 /// <param name="forResource">Das Gerät, für das die Sammlung erfolgt.</param>
 /// <param name="lastUpdate">Methode zur Ermittelung des letzten Aktualisierungszeitpunktes.</param>
 public ProgramGuideTask( IScheduleResource forResource, Func<DateTime?> lastUpdate )
     : this( forResource, null, lastUpdate )
 {
 }
            /// <summary>
            /// Ergänzt ein Gerät.
            /// </summary>
            /// <param name="resource">Das gewünschte Gerät.</param>
            public void Add( IScheduleResource resource )
            {
                // Not allowed
                if (m_CurrentPlan != null)
                    throw new NotSupportedException( "Add" );

                // Forward
                m_Resources.Add( resource );
            }
            /// <summary>
            /// Aktiviert eine Aufzeichnung auf einem Gerät.
            /// </summary>
            /// <param name="resource">Eines der verwalteten Geräte.</param>
            /// <param name="source">Optional eine Quelle, die auf dem Gerät angesteuert werden kann.</param>
            /// <param name="scheduleIdentifier">Die eindeutige Kennung der Aufzeichnung.</param>
            /// <param name="scheduleName">Der Anzeigename der Aufzeichnung.</param>
            /// <param name="plannedStart">Der ursprüngliche Start der Aufzeichnung in UTC / GMT Notation.</param>
            /// <param name="currentEnd">Das aktuelle Ende der Aufzeichnung in UTC / GMT Notation.</param>
            /// <returns>Gesetzt, wenn die Aufzeichnung auf dem gewünschten Gerät aktiviert werden kann.</returns>
            /// <exception cref="ArgumentNullException">Es wurde kein Gerät angegeben.</exception>
            /// <exception cref="ArgumentException">Das Gerät ist nicht bekannt oder kann die Quelle nicht empfangen.</exception>
            /// <exception cref="ArgumentOutOfRangeException">Die Laufzeit der Aufzeichnung ist nicht positiv.</exception>
            public bool Start( IScheduleResource resource, IScheduleSource source, Guid scheduleIdentifier, string scheduleName, DateTime plannedStart, DateTime currentEnd )
            {
                // Validate
                if (resource == null)
                    throw new ArgumentNullException( "resource" );
                if (!m_Resources.Contains( resource ))
                    throw new ArgumentException( resource.Name, "resource" );
                if (plannedStart >= currentEnd)
                    throw new ArgumentOutOfRangeException( "currentEnd" );
                if (m_Recordings.Any( r => r.UniqueIdentifier == scheduleIdentifier ))
                    throw new ArgumentException( "resource" );

                // Create helper entry
                m_Recordings.Add( new ResourceAllocationInformation( resource, source, scheduleIdentifier, scheduleName, plannedStart, currentEnd - plannedStart ) );

                // May require cleanup
                try
                {
                    // Create the new plan
                    var plan = CreateSchedulePlan();

                    // Did it
                    if (plan != null)
                    {
                        // Remember as current
                        m_CurrentPlan = plan;

                        // Report
                        return true;
                    }
                }
                catch
                {
                    // Cleanup
                    m_Recordings.RemoveAt( m_Recordings.Count - 1 );

                    // Report
                    throw;
                }

                // Cleanup
                m_Recordings.RemoveAt( m_Recordings.Count - 1 );

                // Add to list
                return false;
            }
Example #32
0
        /// <summary>
        /// Registriert diese Aufzeichnung in einer Planungsinstanz.
        /// </summary>
        /// <param name="scheduler">Die zu verwendende Planungsinstanz.</param>
        /// <param name="job">Der zugehörige Auftrag.</param>
        /// <param name="devices">Die Liste der Geräte, auf denen die Aufzeichnung ausgeführt werden darf.</param>
        /// <param name="findSource">Dient zum Prüfen einer Quelle.</param>
        /// <param name="disabled">Alle deaktivierten Aufträge.</param>
        /// <param name="context">Die aktuelle Planungsumgebung.</param>
        /// <exception cref="ArgumentNullException">Es wurden nicht alle Parameter angegeben.</exception>
        public void AddToScheduler( RecordingScheduler scheduler, VCRJob job, IScheduleResource[] devices, Func<SourceSelection, SourceSelection> findSource, Func<Guid, bool> disabled, PlanContext context )
        {
            // Validate
            if (scheduler == null)
                throw new ArgumentNullException( nameof( scheduler ) );
            if (job == null)
                throw new ArgumentNullException( nameof( job ) );
            if (findSource == null)
                throw new ArgumentNullException( nameof( findSource ) );

            // Let VCR.NET choose a profile to do the work
            if (job.AutomaticResourceSelection)
                devices = null;

            // Create the source selection
            var persistedSource = Source ?? job.Source;
            var selection = findSource( persistedSource );

            // Station no longer available
            if (selection == null)
                if (persistedSource != null)
                    selection =
                        new SourceSelection
                        {
                            DisplayName = persistedSource.DisplayName,
                            ProfileName = persistedSource.ProfileName,
                            Location = persistedSource.Location,
                            Group = persistedSource.Group,
                            Source =
                                new Station
                                {
                                    TransportStream = persistedSource.Source?.TransportStream ?? 0,
                                    Network = persistedSource.Source?.Network ?? 0,
                                    Service = persistedSource.Source?.Service ?? 0,
                                    Name = persistedSource.DisplayName,
                                },
                        };

            // See if we are allowed to process
            var identifier = UniqueID.Value;
            if (disabled != null)
                if (disabled( identifier ))
                    return;

            // Load all
            var name = string.IsNullOrEmpty( Name ) ? job.Name : $"{job.Name} ({Name})";
            var source = ProfileScheduleResource.CreateSource( selection );
            var duration = TimeSpan.FromMinutes( Duration );
            var noStartBefore = NoStartBefore;
            var start = FirstStart;

            // Check repetition
            var repeat = CreateRepeatPattern();
            if (repeat == null)
            {
                // Only if not being recorded
                if (!noStartBefore.HasValue)
                    scheduler.Add( RecordingDefinition.Create( this, name, identifier, devices, source, start, duration ) );
            }
            else
            {
                // See if we have to adjust the start day
                if (noStartBefore.HasValue)
                {
                    // Attach to the limit - actually we shift it a bit further assuming that we did have no large exception towards the past and the duration is moderate
                    var startAfter = noStartBefore.Value.AddHours( 12 );
                    var startAfterDay = startAfter.ToLocalTime().Date;

                    // Localize the start time
                    var startTime = start.ToLocalTime().TimeOfDay;

                    // First adjust
                    start = (startAfterDay + startTime).ToUniversalTime();

                    // One more day
                    if (start < startAfter)
                        start = (startAfterDay.AddDays( 1 ) + startTime).ToUniversalTime();
                }

                // Read the rest
                var exceptions = Exceptions.Select( e => e.ToPlanException( duration ) ).ToArray();
                var endDay = LastDay.GetValueOrDefault( MaxMovableDay );

                // A bit more complex
                if (start.Date <= endDay.Date)
                    scheduler.Add( RecordingDefinition.Create( this, name, identifier, devices, source, start, duration, endDay, repeat ), exceptions );
            }
        }
 /// <summary>
 /// Erzeugt eine neue Verwaltung.
 /// </summary>
 /// <param name="forResource">Das Gerät, für das die Sammlung erfolgt.</param>
 /// <param name="profile">Das zugehörige Geräteprofil.</param>
 public ProgramGuideTask(IScheduleResource forResource, ProfileState profile)
     : this(forResource, profile, () => profile.ProgramGuide.LastUpdateTime)
 {
 }