/// <summary> /// Fordert zum Beenden einer Aufzeichnung oder Aufgabe aus. /// </summary> /// <param name="item">Alle notwendigen Informationen zur Aufzeichnung.</param> /// <param name="planner">Die zugehörige Aufzeichnungsplanung.</param> public void Stop(IScheduleInformation item, RecordingPlanner planner) { // Report Debug.WriteLine(string.Format("{0} stop {1}", m_planTime.ToLocalTime(), item.Definition.Name)); // Readout var definition = item.Definition; var resource = item.Resource; // Forward planner.Stop(definition.UniqueIdentifier); // Check mode if (definition is ProgramGuideTask) { m_lastRunGuide[resource.Name] = m_planTime; } else if (definition is SourceListTask) { m_lastRunScan[resource.Name] = m_planTime; } else { VCRConfiguration.Current.HasRecordedSomething = true; } }
/// <summary> /// Erzeugt eine neue Verwaltungsinstanz. /// </summary> /// <param name="server">Die primäre VCR.NET Instanz.</param> internal ProfileStateCollection(VCRServer server) { // Remember Server = server; // Profiles to use var profileNames = VCRProfiles.ProfileNames.ToArray(); var nameReport = string.Join(", ", profileNames); // Log VCRServer.Log(LoggingLevel.Full, Properties.Resources.LoadProfiles, nameReport); // Report Tools.ExtendedLogging("Loading Profile Collection: {0}", nameReport); // Load current profiles m_profiles = profileNames.ToDictionary(profileName => profileName, profileName => new ProfileState(this, profileName), ProfileManager.ProfileNameComparer); // Now we can create the planner m_planner = RecordingPlanner.Create(this); m_planThread = new Thread(PlanThread) { Name = "Recording Planner", IsBackground = true }; // Configure timer m_timer.OnTimerExpired += BeginNewPlan; // Start planner m_planThread.Start(); }
/// <summary> /// Fordert zum Starten einer Aufzeichnung oder Aufgabe auf. /// </summary> /// <param name="item">Die Beschreibung der Aufgabe.</param> /// <param name="planner">Die zugehörige Aufzeichnungsplanung.</param> /// <param name="context">Zusatzinformationen zur Aufzeichnungsplanung.</param> public void Start(IScheduleInformation item, RecordingPlanner planner, PlanContext context) { // Report Debug.WriteLine(string.Format("{0} start{3} on {1}: {2}", m_planTime.ToLocalTime(), item.Resource, item.Definition.Name, item.StartsLate ? " late" : string.Empty)); // Forward planner.Start(item); }
public void FullValidation() { // Create component under Test using (var cfg = TestConfigurationProvider.Create(Properties.Resources.AllSchedulers)) using (var cut = RecordingPlanner.Create(this)) for (int i = 250; i-- > 0;) { cut.DispatchNextActivity(m_planTime); } }
/// <summary> /// Meldet, dass eine Aufzeichnung nun beendet werden kann. /// </summary> /// <param name="item">Die betroffene Aufzeichnung.</param> /// <param name="planner">Die Planungsinstanz.</param> void IRecordingPlannerSite.Stop(IScheduleInformation item, RecordingPlanner planner) { // Report VCRServer.Log(LoggingLevel.Schedules, "Done recording '{0}'", item.Definition.Name); // Locate the profile - if we don't find it we are in big trouble! if (!m_profiles.TryGetValue(item.Resource.Name, out ProfileState profile)) { return; } // Mark as pending m_pendingSchedule = item; m_pendingStart = false; // Forward request to profile manager m_pendingActions += () => profile.EndRecording(item.Definition.UniqueIdentifier); }
public void ShowPlan() { // Create component under Test using (var cfg = TestConfigurationProvider.Create(Properties.Resources.AllSchedulers)) using (var cut = RecordingPlanner.Create(this)) foreach (var plan in cut.GetPlan(m_now).Take(250)) { Debug.WriteLine(string.Format ( "{0:dd.MM.yyyy HH:mm}-{5:HH:mm}{1} on {2} [{3}] {4}", plan.Time.LocalStart, plan.StartsLate ? " [late]" : string.Empty, (plan.Resource == null) ? string.Format("[{0}]", string.Join(", ", plan.Definition.Resources.Select(r => r.Name))) : (object)plan.Resource, plan.Definition.UniqueIdentifier, plan.Definition.Name, plan.Time.LocalEnd )); } }
/// <summary> /// Meldet, dass eine Aufzeichnung nun beginnen sollte. /// </summary> /// <param name="item">Die zu startende Aufzeichnung.</param> /// <param name="planner">Die Planungsinstanz.</param> /// <param name="context">Zusatzinformationen zur Aufzeichnungsplanung.</param> void IRecordingPlannerSite.Start(IScheduleInformation item, RecordingPlanner planner, PlanContext context) { // We are no longer active - simulate start and do nothing if (!m_plannerActive) { // Make planner believe we did it planner.Start(item); // Make sure that we wake up after the grace period if (PowerManager.IsSuspended && VCRConfiguration.Current.SuppressDelayAfterForcedHibernation) { Tools.ExtendedLogging("Hibernation Delay is disabled and can not be enforced"); } else { m_timer.SecondsToWait = VCRConfiguration.Current.DelayAfterForcedHibernation.TotalSeconds; } // Done return; } // Report VCRServer.Log(LoggingLevel.Schedules, "Start recording '{0}'", item.Definition.Name); // Locate the profile - if we don't find it we are in big trouble! ProfileState profile; if (!m_profiles.TryGetValue(item.Resource.Name, out profile)) { return; } // Mark as pending m_pendingSchedule = item; m_pendingStart = true; // Create the recording var recording = VCRRecordingInfo.Create(item, context); // Check for EPG var guideUpdate = item.Definition as ProgramGuideTask; if (guideUpdate != null) { // Start a new guide collector m_pendingActions += ProgramGuideProxy.Create(profile, recording).Start; } else { // Check for PSI var sourceUpdate = item.Definition as SourceListTask; if (sourceUpdate != null) { // Start a new update m_pendingActions += SourceScanProxy.Create(profile, recording).Start; } else { // Start a regular recording - profile will decide if to join an existing recording m_pendingActions += () => profile.StartRecording(recording); } } }
/// <summary> /// Ergänzt alle bekannten Aufzeichnungen zu einer Planungsinstzanz. /// </summary> /// <param name="scheduler">Die Verwaltung der Aufzeichnungen.</param> /// <param name="disabled">Alle nicht zu verwendenden Aufzeichnungen.</param> /// <param name="planner">Die Gesamtplanung.</param> /// <param name="context">Zusätzliche Informationen zur aktuellen Planung.</param> void IRecordingPlannerSite.AddRegularJobs(RecordingScheduler scheduler, Func <Guid, bool> disabled, RecordingPlanner planner, PlanContext context) { // Retrieve all jobs related to this profile foreach (var job in Server.JobManager.GetActiveJobs()) { foreach (var schedule in job.Schedules) { // No longer in use if (!schedule.IsActive) { continue; } // Resolve source var source = schedule.Source ?? job.Source; if (source == null) { continue; } // Resolve profile var resource = planner.GetResourceForProfile(source.ProfileName); if (resource == null) { continue; } // Register single item schedule.AddToScheduler(scheduler, job, new[] { resource }, VCRProfiles.FindSource, disabled, context); // Remember - even if we skipped it context.RegisterSchedule(schedule, job); } } }
/// <summary> /// Überträgt alle Aufträge in einen Ablaufplanung. /// </summary> /// <param name="scheduler">Die zu befüllende Ablaufplanung.</param> /// <param name="disabled">Alle deaktivierten Aufträge.</param> /// <param name="planner">Die zugehörige Aufzeichnungsplanung.</param> /// <param name="context">Detailinformationen zur Planung.</param> public void AddRegularJobs(RecordingScheduler scheduler, Func <Guid, bool> disabled, RecordingPlanner planner, PlanContext context) { // Retrieve all jobs related to this profile foreach (var job in m_jobs.Values) { foreach (var schedule in job.Schedules) { // No longer in use if (!schedule.IsActive) { continue; } // Resolve source var source = schedule.Source ?? job.Source; if (source == null) { continue; } // Resolve profile var resource = planner.GetResourceForProfile(source.ProfileName); if (resource == null) { continue; } // Register schedule.AddToScheduler(scheduler, job, new[] { resource }, FindSource, disabled, context); // Connect context.RegisterSchedule(schedule, job); } } }