/// <summary>
 /// Erzeugt eine Beschreibung.
 /// </summary>
 /// <param name="job">Ein Auftrag.</param>
 /// <param name="active">Gesetzt, wenn es sich um einen aktiven Auftrag handel.</param>
 /// <returns>Die gewünschte Beschreibung.</returns>
 public static ProfileJobInfo Create( VCRJob job, bool active )
 {
     // Process
     if (active)
         return new ProfileJobInfo { Profile = job.Source.ProfileName, Name = job.Name, JobIdentifier = job.UniqueID.Value.ToString( "N" ).ToLower() };
     else
         return null;
 }
        /// <summary>
        /// Entfernt einen Auftrag.
        /// </summary>
        /// <param name="job">Der betroffene Auftrag.</param>
        public void DeleteJob( VCRJob job )
        {
            // Client is talking to us - do not hibernate after change
            m_PendingHibernation = false;

            // Remove from job manager
            JobManager.Delete( job );

            // Recalculate
            BeginNewPlan();
        }
 /// <summary>
 /// Legt eine neue Information an.
 /// </summary>
 /// <param name="job">Der Auftrag.</param>
 /// <param name="schedule">Die Aufzeichnung.</param>
 /// <param name="guide">Ein Eintrag der Programmzeitschrift.</param>
 /// <param name="profile">Vorgabe für das Geräteprofil.</param>
 /// <returns>Die Information.</returns>
 public static JobScheduleInfo Create( VCRJob job, VCRSchedule schedule, ProgramGuideEntry guide, string profile )
 {
     // Process
     return
         new JobScheduleInfo
         {
             ScheduleIdentifier = (schedule == null) ? null : schedule.UniqueID.Value.ToString( "N" ),
             JobIdentifier = (job == null) ? null : job.UniqueID.Value.ToString( "N" ),
             Schedule = EditSchedule.Create( schedule, job, guide ),
             Job = EditJob.Create( job, guide, profile ),
         };
 }
 /// <summary>
 /// Meldet die Daten zu einer Aufzeichnung.
 /// </summary>
 /// <param name="schedule">Die Aufzeichnung.</param>
 /// <param name="job">Der zugehörige Auftrag.</param>
 /// <returns></returns>
 public static InfoSchedule Create( VCRSchedule schedule, VCRJob job )
 {
     // Create
     return
         new InfoSchedule
         {
             Source = (schedule.Source ?? job.Source).GetUniqueName(),
             WebId = ServerRuntime.GetUniqueWebId( job, schedule ),
             StartTime = schedule.FirstStart,
             RepeatPattern = schedule.Days,
             Duration = schedule.Duration,
             Name = schedule.Name,
         };
 }
Exemple #5
0
 /// <summary>
 /// Erstellt eine neue Beschreibung.
 /// </summary>
 /// <param name="job">Ein Auftrag.</param>
 /// <param name="active">Gesetzt, wenn es sich um einen aktiven Auftrag handelt.</param>
 /// <returns>Die gewünschte Beschreibung.</returns>
 public static InfoJob Create( VCRJob job, bool active )
 {
     // Report
     return
         new InfoJob
         {
             Schedules = job.Schedules.Select( schedule => InfoSchedule.Create( schedule, job ) ).OrderBy( schedule => schedule.Name ?? string.Empty, StringComparer.InvariantCultureIgnoreCase ).ToArray(),
             WebId = ServerRuntime.GetUniqueWebId( job, null ),
             ProfileName = job.Source.ProfileName,
             SourceName = job.Source.DisplayName,
             IsActive = active,
             Name = job.Name,
         };
 }
        /// <summary>
        /// Aktualisiert einen Auftrag oder legt einen neue an.
        /// </summary>
        /// <param name="job">Der betroffene Auftrag.</param>
        /// <param name="scheduleIdentifier">Die eindeutige Kennung der veränderten Aufzeichnung.</param>
        public void UpdateJob( VCRJob job, Guid? scheduleIdentifier )
        {
            // Client is talking to us - do not hibernate after update
            m_PendingHibernation = false;

            // Cleanup
            if (scheduleIdentifier.HasValue)
                foreach (var schedule in job.Schedules)
                    if (schedule.UniqueID.HasValue)
                        if (schedule.UniqueID.Value.Equals( scheduleIdentifier.Value ))
                            schedule.NoStartBefore = null;

            // Add to job manager
            JobManager.Update( job, scheduleIdentifier );

            // Recalculate
            BeginNewPlan();
        }
Exemple #7
0
        /// <summary>
        /// Erstellt eine neue Beschreibung.
        /// </summary>
        /// <param name="job">Der konkrete Auftag.</param>
        /// <param name="guide">Ein Eintrag der Programmzeitschrift.</param>
        /// <param name="profile">Vorgabe für das Geräteprofil.</param>
        /// <returns>Die zugehörige Beschreibung.</returns>
        public static EditJob Create( VCRJob job, ProgramGuideEntry guide, string profile )
        {
            // Process
            if (job == null)
            {
                // No hope
                if (guide == null)
                    return null;

                // Create from program guide            
                return
                    new EditJob
                    {
                        Source = ServerRuntime.VCRServer.GetUniqueName( new SourceSelection { ProfileName = profile, Source = guide.Source } ),
                        DVBSubtitles = UserProfileSettings.UseSubTitles,
                        DolbyDigital = UserProfileSettings.UseAC3,
                        AllLanguages = UserProfileSettings.UseMP2,
                        Videotext = UserProfileSettings.UseTTX,
                        UseProfileForRecording = false,
                        Name = guide.Name.MakeValid(),
                        Profile = profile,
                    };
            }

            // Optionen ermitteln
            var streams = job.Streams;
            var sourceName = ServerRuntime.VCRServer.GetUniqueName( job.Source );

            // Report            
            return
                new EditJob
                {
                    UseProfileForRecording = !job.AutomaticResourceSelection,
                    DolbyDigital = streams.GetUsesDolbyAudio(),
                    AllLanguages = streams.GetUsesAllAudio(),
                    DVBSubtitles = streams.GetUsesSubtitles(),
                    Videotext = streams.GetUsesVideotext(),
                    RecordingDirectory = job.Directory,
                    Profile = job.Source.ProfileName,
                    Source = sourceName,
                    Name = job.Name,
                };
        }
        /// <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>
        /// Prüft, ob die Daten zur Aufzeichnung zulässig sind.
        /// </summary>
        /// <param name="job">Der zugehörige Auftrag.</param>
        /// <exception cref="InvalidJobDataException">Es wurde keine eindeutige Kennung angegeben.</exception>
        /// <exception cref="InvalidJobDataException">Die Daten der Aufzeichnung sind fehlerhaft.</exception>
        public void Validate(VCRJob job)
        {
            // Identifier
            if (!UniqueID.HasValue)
            {
                throw new InvalidJobDataException(Properties.Resources.BadUniqueID);
            }

            // Check for termination date
            if (LastDay.HasValue)
            {
                // Must be a date
                if (LastDay.Value != LastDay.Value.Date)
                {
                    throw new InvalidJobDataException(Properties.Resources.LastDayNotDate);
                }
                if (FirstStart.Date > LastDay.Value.Date)
                {
                    throw new InvalidJobDataException(Properties.Resources.EndsBeforeStart);
                }
            }

            // Duration
            if ((Duration < 1) || (Duration > 9999))
            {
                throw new InvalidJobDataException(Properties.Resources.BadDuration);
            }

            // Repetition
            if (Days.HasValue)
            {
                if (0 != (~0x7f & (int)Days.Value))
                {
                    throw new InvalidJobDataException(Properties.Resources.BadRepeat);
                }
            }

            // Test the station
            if (Source != null)
            {
                // Match profile
                if (job != null)
                {
                    if (job.Source != null)
                    {
                        if (!string.Equals(job.Source.ProfileName, Source.ProfileName, StringComparison.InvariantCultureIgnoreCase))
                        {
                            throw new InvalidJobDataException(Properties.Resources.BadTVStation);
                        }
                    }
                }

                // Source
                if (!Source.Validate())
                {
                    throw new InvalidJobDataException(Properties.Resources.BadTVStation);
                }

                // Streams
                if (!Streams.Validate())
                {
                    throw new InvalidJobDataException(Properties.Resources.BadStreams);
                }
            }
            else if (Streams != null)
            {
                throw new InvalidJobDataException(Properties.Resources.BadStreams);
            }

            // Station
            if (!job.HasSource)
            {
                if (Source == null)
                {
                    throw new InvalidJobDataException(Properties.Resources.NoTVStation);
                }
            }

            // Name
            if (!Name.IsValidName())
            {
                throw new InvalidJobDataException(Properties.Resources.BadName);
            }
        }
        /// <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>
        /// Prüft, ob die Daten zur Aufzeichnung zulässig sind.
        /// </summary>
        /// <param name="job">Der zugehörige Auftrag.</param>
        /// <exception cref="InvalidJobDataException">Es wurde keine eindeutige Kennung angegeben.</exception>
        /// <exception cref="InvalidJobDataException">Die Daten der Aufzeichnung sind fehlerhaft.</exception>
        public void Validate( VCRJob job )
        {
            // Identifier
            if (!UniqueID.HasValue)
                throw new InvalidJobDataException( Properties.Resources.BadUniqueID );

            // Check for termination date
            if (LastDay.HasValue)
            {
                // Must be a date
                if (LastDay.Value != LastDay.Value.Date)
                    throw new InvalidJobDataException( Properties.Resources.LastDayNotDate );
                if (FirstStart.Date > LastDay.Value.Date)
                    throw new InvalidJobDataException( Properties.Resources.EndsBeforeStart );
            }

            // Duration
            if ((Duration < 1) || (Duration > 9999))
                throw new InvalidJobDataException( Properties.Resources.BadDuration );

            // Repetition
            if (Days.HasValue)
                if (0 != (~0x7f & (int) Days.Value))
                    throw new InvalidJobDataException( Properties.Resources.BadRepeat );

            // Test the station
            if (Source != null)
            {
                // Match profile
                if (job != null)
                    if (job.Source != null)
                        if (!string.Equals( job.Source.ProfileName, Source.ProfileName, StringComparison.InvariantCultureIgnoreCase ))
                            throw new InvalidJobDataException( Properties.Resources.BadTVStation );

                // Source
                if (!Source.Validate())
                    throw new InvalidJobDataException( Properties.Resources.BadTVStation );

                // Streams
                if (!Streams.Validate())
                    throw new InvalidJobDataException( Properties.Resources.BadStreams );
            }
            else if (Streams != null)
                throw new InvalidJobDataException( Properties.Resources.BadStreams );

            // Station
            if (!job.HasSource)
                if (Source == null)
                    throw new InvalidJobDataException( Properties.Resources.NoTVStation );

            // Name
            if (!Name.IsValidName())
                throw new InvalidJobDataException( Properties.Resources.BadName );
        }
 /// <summary>
 /// Ermittelt eine Referenz für eine bestimmte Aufzeichung in einem Auftrag, so dass diese
 /// auch in einer URL verwendet werden kann.
 /// </summary>
 /// <param name="job">Ein Auftrag.</param>
 /// <param name="schedule">Eine Aufzeichnung.</param>
 /// <returns>Die eindeutige Referenz.</returns>
 public static string GetUniqueWebId( VCRJob job, VCRSchedule schedule )
 {
     // Forward
     if (job == null)
         return "*";
     else if (schedule == null)
         return string.Format( "*{0:N}", job.UniqueID.Value );
     else
         return GetUniqueWebId( job.UniqueID.Value, schedule.UniqueID.Value );
 }
        /// <summary>
        /// Aktualisiert einen Auftrag oder legt einen Auftrag neu an.
        /// </summary>
        /// <param name="job">Der neue oder veränderte Auftrag.</param>
        /// <param name="scheduleIdentifier">Die eindeutige Kennung der veränderten Aufzeichnung.</param>
        public void Update( VCRJob job, Guid? scheduleIdentifier )
        {
            // Report
            if (job != null)
                Tools.ExtendedLogging( "Updating Job {0}", job.UniqueID );

            // Load default profile name
            job.SetProfile();

            // Validate
            job.Validate( scheduleIdentifier );

            // Cleanup schedules
            job.CleanupExceptions();

            // Remove from archive - if job has been recovered
            job.Delete( ArchiveDirectory );

            // Try to store to disk - actually this is inside the lock because the directory virtually is part of our map
            lock (m_Jobs)
                if (job.Save( JobDirectory ).GetValueOrDefault())
                    m_Jobs[job.UniqueID.Value] = job;
                else
                    throw new ArgumentException( string.Format( Properties.Resources.SaveJobFailed, job.UniqueID ), "job" );
        }
        /// <summary>
        /// Löscht einen aktiven oder archivierten Auftrag.
        /// </summary>
        /// <param name="job">Der zu löschende Auftrag.</param>
        public void Delete( VCRJob job )
        {
            // Check unique identifier
            if (!job.UniqueID.HasValue)
                throw new InvalidJobDataException( Properties.Resources.BadUniqueID );

            // Report
            Tools.ExtendedLogging( "Deleting Job {0}", job.UniqueID );

            // Must synchronize
            lock (m_Jobs)
            {
                // Load from the map
                var internalJob = this[job.UniqueID.Value];

                // See if this is active
                if (internalJob != null)
                {
                    // Delete it
                    internalJob.Delete( JobDirectory );

                    // Remove from map
                    m_Jobs.Remove( internalJob.UniqueID.Value );

                    // Save to file
                    internalJob.Save( ArchiveDirectory );
                }
                else
                {
                    // Report
                    Tools.ExtendedLogging( "Job not found in Active Directory - trying Archive" );

                    // Must be archived               
                    job.Delete( ArchiveDirectory );
                }
            }
        }
        /// <summary>
        /// Rekonstruiert einen Auftrag und eine Aufzeichnung aus einer Textdarstellung.
        /// </summary>
        /// <param name="id">Die Textdarstellung.</param>
        /// <param name="job">Der ermittelte Auftrag.</param>
        /// <returns>Die zugehörige Aufzeichnung im Auftrag.</returns>
        public static VCRSchedule ParseUniqueWebId( string id, out VCRJob job )
        {
            // Read all
            Guid jobID, scheduleID;
            ParseUniqueWebId( id, out jobID, out scheduleID );

            // Find the job
            job = VCRServer.FindJob( jobID );

            // Report schedule if job exists
            if (job == null)
                return null;
            else
                return job[scheduleID];
        }
Exemple #16
0
        /// <summary>
        /// Erstellt einen passenden Auftrag für die persistente Ablage.
        /// </summary>
        /// <param name="jobIdentifier">Die eindeutige Kennung des Auftrags.</param>
        /// <returns>Der zugehörige Auftrag.</returns>
        public VCRJob CreateJob( Guid jobIdentifier )
        {
            // Create core
            var job =
                new VCRJob
                    {
                        AutomaticResourceSelection = !UseProfileForRecording,
                        Directory = RecordingDirectory,
                        UniqueID = jobIdentifier,
                        Name = Name,
                    };

            // Check source
            var profile = Profile;
            if (string.IsNullOrEmpty( profile ))
                return job;

            // Get the name of the source
            var sourceName = Source;
            if (string.IsNullOrEmpty( sourceName ))
            {
                // Create profile reference
                job.Source = new SourceSelection { ProfileName = profile };

                // Done
                return job;
            }

            // Locate the source
            job.Source = ServerRuntime.VCRServer.FindSource( profile, sourceName );
            if (job.Source == null)
                return job;

            // Configure streams
            job.Streams = new StreamSelection();

            // Set all - oder of audio settings is relevant, dolby MUST come last
            job.Streams.SetUsesAllAudio( AllLanguages );
            job.Streams.SetUsesDolbyAudio( DolbyDigital );
            job.Streams.SetUsesSubtitles( DVBSubtitles );
            job.Streams.SetUsesVideotext( Videotext );
            job.Streams.ProgramGuide = true;

            // Report
            return job;
        }
        /// <summary>
        /// Erstellt die Beschreibung der Aufzeichnung für die persistente Ablage.
        /// </summary>
        /// <param name="scheduleIdentifier">Die eindeutige Kennung der Aufzeichnung.</param>
        /// <param name="job">Der zugehörige Auftrag.</param>
        /// <returns>Die gewünschte Beschreibung.</returns>
        public VCRSchedule CreateSchedule( Guid scheduleIdentifier, VCRJob job )
        {
            // Create
            var schedule =
                new VCRSchedule
                {
                    UniqueID = scheduleIdentifier,
                    FirstStart = FirstStart,
                    Days = RepeatPattern,
                    Duration = Duration,
                    LastDay = LastDay,
                    Name = Name,
                };

            // See if we have a source
            var sourceName = Source;
            if (string.IsNullOrEmpty( sourceName ))
                return schedule;

            // See if there is a profile
            var jobSource = job.Source;
            if (jobSource == null)
                return schedule;

            // Locate the source
            schedule.Source = ServerRuntime.VCRServer.FindSource( jobSource.ProfileName, sourceName );
            if (schedule.Source == null)
                return schedule;

            // Configure streams
            schedule.Streams = new StreamSelection();

            // Set all - oder of audio settings is relevant, dolby MUST come last
            schedule.Streams.SetUsesAllAudio( AllLanguages );
            schedule.Streams.SetUsesDolbyAudio( DolbyDigital );
            schedule.Streams.SetUsesSubtitles( DVBSubtitles );
            schedule.Streams.SetUsesVideotext( Videotext );
            schedule.Streams.ProgramGuide = true;

            // Report
            return schedule;
        }
 /// <summary>
 /// Erstellt die Beschreibung der Aufzeichnung für die persistente Ablage.
 /// </summary>
 /// <param name="job">Der zugehörige Auftrag.</param>
 /// <returns>Die gewünschte Beschreibung.</returns>
 public VCRSchedule CreateSchedule( VCRJob job )
 {
     // Forward
     return CreateSchedule( Guid.NewGuid(), job );
 }
        /// <summary>
        /// Erstellt eine Beschreibung zu dieser Aufzeichnung.
        /// </summary>
        /// <param name="schedule">Eine Aufzeichnung.</param>
        /// <param name="job">Der bereits vorhandene Auftrag.</param>
        /// <param name="guide">Ein Eintrag aus der Programmzeitschrift.</param>
        /// <returns>Die gewünschte Beschreibung.</returns>
        public static EditSchedule Create( VCRSchedule schedule, VCRJob job, ProgramGuideEntry guide )
        {
            // None
            if (schedule == null)
            {
                // No hope
                if (guide == null)
                    return null;

                // Calculate
                var start = guide.StartTime - TimeSpan.FromMinutes( UserProfileSettings.EPGPreTime );
                var duration = checked( (int) (UserProfileSettings.EPGPreTime + (guide.Duration / 60) + UserProfileSettings.EPGPostTime) );

                // Partial - we have a brand new job which is pre-initialized with the source
                if (job == null)
                    return new EditSchedule { FirstStart = start, Duration = duration };

                // Full monty - we have to overwrite the jobs settings since we are not the first schedule
                return
                    new EditSchedule
                    {
                        Source = ServerRuntime.VCRServer.GetUniqueName( new SourceSelection { ProfileName = job.Source.ProfileName, Source = guide.Source } ),
                        DVBSubtitles = UserProfileSettings.UseSubTitles,
                        DolbyDigital = UserProfileSettings.UseAC3,
                        AllLanguages = UserProfileSettings.UseMP2,
                        Videotext = UserProfileSettings.UseTTX,
                        Name = guide.Name.MakeValid(),
                        Duration = duration,
                        FirstStart = start,
                    };
            }

            // Consolidate exceptions
            schedule.CleanupExceptions();

            // Optionen ermitteln
            var streams = schedule.Streams;
            var sourceName = ServerRuntime.VCRServer.GetUniqueName( schedule.Source );

            // Create
            return
                new EditSchedule
                {
                    Exceptions = schedule.Exceptions.Select( exception => PlanException.Create( exception, schedule ) ).ToArray(),
                    LastDay = schedule.LastDay.GetValueOrDefault( VCRSchedule.MaxMovableDay ),
                    DolbyDigital = streams.GetUsesDolbyAudio(),
                    DVBSubtitles = streams.GetUsesSubtitles(),
                    AllLanguages = streams.GetUsesAllAudio(),
                    Videotext = streams.GetUsesVideotext(),
                    FirstStart = schedule.FirstStart,
                    RepeatPattern = schedule.Days,
                    Duration = schedule.Duration,
                    Name = schedule.Name,
                    Source = sourceName,
                };
        }