/// <summary>
        /// Meldet alle Aufzeichnungen ab einem bestimmten Zeitpunkt.
        /// </summary>
        /// <param name="minTime">Alle Aufzeichnungen, die vor diesem Zeitpunkt enden, werden
        /// nicht berücksichtigt. Die Angabe erfolgt in UTC / GMT Notation.</param>
        /// <returns>Alle Aufzeichnungen.</returns>
        private IEnumerable<ScheduleInfo> GetSchedulesForRecordings( DateTime minTime )
        {
            // All items to process
            var items = new _ScheduleList( m_PlanItems.Where( r => !m_ForbiddenDefinitions.Contains( r.Definition.UniqueIdentifier ) ), minTime );

            // Create the plans to extend
            var plans = new List<SchedulePlan> { m_PlanCreator() };
            var steps = 0;

            // As long as necessary
            while (items.MoveNext())
            {
                // Load the item
                var candidate = items.Current;
                var candiateTime = candidate.Current;
                var planned = candiateTime.Planned;

#if !SILVERLIGHT
                // Report
                if (SchedulerTrace.TraceVerbose)
                    Trace.TraceInformation( Properties.SchedulerResources.Trace_Candidate, candidate.Definition.Source, planned.Start, planned.Duration );
#endif

                // Get the current end of plans and see if we can dump the state - this may increase performance
                var planStart = plans.SelectMany( p => p.Resources ).Min( r => (DateTime?) r.PlanStart );
                var planEnd = plans.SelectMany( p => p.Resources ).Max( r => (DateTime?) r.PlanEnd );
                var canEndPlan = planEnd.HasValue && (planEnd.Value != DateTime.MinValue) && (planned.Start >= planEnd.Value);
                var mustEndPlan = planStart.HasValue && (planStart.Value != DateTime.MaxValue) && planEnd.HasValue && (planEnd.Value != DateTime.MinValue) && ((planEnd.Value - planStart.Value).TotalDays > 2);

                // Count this effort
                if ((++steps > MaximumRecordingsInPlan) || canEndPlan || mustEndPlan || (plans.Count > MaximumAlternativesInPlan))
                {
                    // Find best plan
                    var best = SchedulePlan.FindBest( plans, m_comparer );

                    // Report
                    foreach (var info in Dump( best ))
                        yield return info;

                    // Reset
                    plans.Clear();
                    plans.Add( best.Restart( planned.Start ) );

                    // Reset
                    steps = 1;
                }

#if !SILVERLIGHT
                // Report
                if (SchedulerTrace.TraceVerbose)
                    Trace.TraceInformation( Properties.SchedulerResources.Trace_PlanCount, plans.Count );
#endif

                // All plans to extend
                var allPlans = plans.ToArray();

                // Discard list
                plans.Clear();

                // Iterate over all plans and try to add the current candidate - in worst case this will multiply possible plans by the number of resources available
                foreach (var plan in allPlans)
                    for (int i = plan.Resources.Length; i-- > 0; )
                    {
                        // Clone of plan must be recreated for each resource because test is allowed to modify it
                        var clone = plan.Clone();

                        // Remember the time we tried - implicit cast is important, do NOT use var
                        SuggestedPlannedTime plannedTime = planned;

                        // See if resource can handle this
                        if (clone.Resources[i].Add( candidate.Definition, plannedTime, minTime ))
                            plans.Add( clone );
                    }

                // Must reset if the recording could not be scheduled at all
                if (plans.Count < 1)
                {
                    // Report
                    yield return new ScheduleInfo( candidate.Definition, null, planned, false );

                    // Restore the original plans since we did nothing at all
                    plans.AddRange( allPlans );
                }
            }

            // Send all we found 
            foreach (var info in Dump( SchedulePlan.FindBest( plans, m_comparer ) ))
                yield return info;
        }
        /// <summary>
        /// Meldet alle Aufzeichnungen ab einem bestimmten Zeitpunkt.
        /// </summary>
        /// <param name="minTime">Alle Aufzeichnungen, die vor diesem Zeitpunkt enden, werden
        /// nicht berücksichtigt. Die Angabe erfolgt in UTC / GMT Notation.</param>
        /// <returns>Alle Aufzeichnungen.</returns>
        private IEnumerable <ScheduleInfo> GetSchedulesForRecordings(DateTime minTime)
        {
            // All items to process
            var items = new _ScheduleList(m_PlanItems.Where(r => !m_ForbiddenDefinitions.Contains(r.Definition.UniqueIdentifier)), minTime);

            // Create the plans to extend
            var plans = new List <SchedulePlan> {
                m_PlanCreator()
            };
            var steps = 0;

            // As long as necessary
            while (items.MoveNext())
            {
                // Load the item
                var candidate    = items.Current;
                var candiateTime = candidate.Current;
                var planned      = candiateTime.Planned;

#if !SILVERLIGHT
                // Report
                if (SchedulerTrace.TraceVerbose)
                {
                    Trace.TraceInformation(Properties.SchedulerResources.Trace_Candidate, candidate.Definition.Source, planned.Start, planned.Duration);
                }
#endif

                // Get the current end of plans and see if we can dump the state - this may increase performance
                var planStart   = plans.SelectMany(p => p.Resources).Min(r => (DateTime?)r.PlanStart);
                var planEnd     = plans.SelectMany(p => p.Resources).Max(r => (DateTime?)r.PlanEnd);
                var canEndPlan  = planEnd.HasValue && (planEnd.Value != DateTime.MinValue) && (planned.Start >= planEnd.Value);
                var mustEndPlan = planStart.HasValue && (planStart.Value != DateTime.MaxValue) && planEnd.HasValue && (planEnd.Value != DateTime.MinValue) && ((planEnd.Value - planStart.Value).TotalDays > 2);

                // Count this effort
                if ((++steps > MaximumRecordingsInPlan) || canEndPlan || mustEndPlan || (plans.Count > MaximumAlternativesInPlan))
                {
                    // Find best plan
                    var best = SchedulePlan.FindBest(plans, m_comparer);

                    // Report
                    foreach (var info in Dump(best))
                    {
                        yield return(info);
                    }

                    // Reset
                    plans.Clear();
                    plans.Add(best.Restart(planned.Start));

                    // Reset
                    steps = 1;
                }

#if !SILVERLIGHT
                // Report
                if (SchedulerTrace.TraceVerbose)
                {
                    Trace.TraceInformation(Properties.SchedulerResources.Trace_PlanCount, plans.Count);
                }
#endif

                // All plans to extend
                var allPlans = plans.ToArray();

                // Discard list
                plans.Clear();

                // Iterate over all plans and try to add the current candidate - in worst case this will multiply possible plans by the number of resources available
                foreach (var plan in allPlans)
                {
                    for (int i = plan.Resources.Length; i-- > 0;)
                    {
                        // Clone of plan must be recreated for each resource because test is allowed to modify it
                        var clone = plan.Clone();

                        // Remember the time we tried - implicit cast is important, do NOT use var
                        SuggestedPlannedTime plannedTime = planned;

                        // See if resource can handle this
                        if (clone.Resources[i].Add(candidate.Definition, plannedTime, minTime))
                        {
                            plans.Add(clone);
                        }
                    }
                }

                // Must reset if the recording could not be scheduled at all
                if (plans.Count < 1)
                {
                    // Report
                    yield return(new ScheduleInfo(candidate.Definition, null, planned, false));

                    // Restore the original plans since we did nothing at all
                    plans.AddRange(allPlans);
                }
            }

            // Send all we found
            foreach (var info in Dump(SchedulePlan.FindBest(plans, m_comparer)))
            {
                yield return(info);
            }
        }