/// <summary>
        /// Erzeugt eine neue Beschreibung.
        /// </summary>
        /// <param name="uniqueIdentifier">Die eindeutige Kennung dieses Datenstroms.</param>
        /// <param name="manager">Die Verwaltung des Empfangs.</param>
        /// <param name="targetPath">Ein optionaler Dateiname zur Ablage der empfangenen Daten.</param>
        /// <param name="originalSelection">Die ursprünglich angeforderte Konfiguration der Aufzeichnung.</param>
        /// <exception cref="ArgumentNullException">Es wurde keine Verwaltung angegeben</exception>
        public ActiveStream( Guid uniqueIdentifier, SourceStreamsManager manager, StreamSelection originalSelection, string targetPath )
        {
            // Validate
            if (manager == null)
                throw new ArgumentNullException( "manager" );

            // Remember
            SourceKey = new SourceIdenfierWithKey( uniqueIdentifier, manager.Source );
            RequestedStreams = originalSelection.Clone();
            TargetPath = targetPath;
            Manager = manager;
        }
        /// <summary>
        /// Ermittelt eine aktive Quelle.
        /// </summary>
        /// <param name="source">Die eindeutige Kennung der Quelle.</param>
        /// <returns>Der 0-basierte laufende Index der Quelle oder <i>-1</i>,
        /// wenn diese nicht in Benutzung ist.</returns>
        public ActiveStream FindSource(SourceIdenfierWithKey source)
        {
            // Find the source
            ActiveStream stream;

            if (Streams.TryGetValue(source, out stream))
            {
                return(stream);
            }
            else
            {
                return(null);
            }
        }
        /// <summary>
        /// Erzeugt eine neue Beschreibung.
        /// </summary>
        /// <param name="uniqueIdentifier">Die eindeutige Kennung dieses Datenstroms.</param>
        /// <param name="manager">Die Verwaltung des Empfangs.</param>
        /// <param name="targetPath">Ein optionaler Dateiname zur Ablage der empfangenen Daten.</param>
        /// <param name="originalSelection">Die ursprünglich angeforderte Konfiguration der Aufzeichnung.</param>
        /// <exception cref="ArgumentNullException">Es wurde keine Verwaltung angegeben</exception>
        public ActiveStream(Guid uniqueIdentifier, SourceStreamsManager manager, StreamSelection originalSelection, string targetPath)
        {
            // Validate
            if (manager == null)
            {
                throw new ArgumentNullException("manager");
            }

            // Remember
            SourceKey        = new SourceIdenfierWithKey(uniqueIdentifier, manager.Source);
            RequestedStreams = originalSelection.Clone();
            TargetPath       = targetPath;
            Manager          = manager;
        }
        /// <summary>
        /// Aktiviert den Empfang einer Quelle.
        /// </summary>
        /// <param name="sources">Informationen zu den zu aktivierenden Quellen.</param>
        protected override void OnAddSources(ReceiveInformation[] sources)
        {
            // Prepare operation
            Start(device =>
            {
                // Check mode
                if (EPGProgress.HasValue)
                {
                    CardServerException.Throw(new EPGActiveFault());
                }
                if (m_ScanProgress >= 0)
                {
                    CardServerException.Throw(new SourceUpdateActiveFault());
                }

                // Force reload of group information to be current
                device.ResetInformationReaders();

                // Create optimizer
                var optimizer = new StreamSelectionOptimizer();

                // Source backmap
                var infos = new Dictionary <SourceIdenfierWithKey, ReceiveInformation>();

                // Pre-Test
                foreach (var info in sources)
                {
                    // It's not allowed to activate a source twice
                    var key = new SourceIdenfierWithKey(info.UniqueIdentifier, info.Selection.Source);
                    if (FindSource(key) != null)
                    {
                        CardServerException.Throw(new SourceInUseFault(info.Selection.Source));
                    }

                    // Remember
                    infos.Add(key, info);

                    // Prepare to optimize
                    optimizer.Add(info.Selection, info.Streams);
                }

                // See how many we are allowed to start
                var allowed = optimizer.Optimize();

                // Streams to activate
                var newStreams = new List <ActiveStream>();
                try
                {
                    // Process all
                    for (int i = 0; i < allowed; ++i)
                    {
                        // Attach to the source
                        var current = sources[i];
                        var source  = current.Selection;
                        var key     = new SourceIdenfierWithKey(current.UniqueIdentifier, source.Source);

                        // Create the stream manager
                        var manager = source.Open(optimizer.GetStreams(i));

                        // Attach file size mapper
                        manager.FileBufferSizeChooser = infos[key].GetFileBufferSize;

                        // Create
                        var stream = new ActiveStream(key.UniqueIdentifier, manager, current.Streams, current.RecordingPath);

                        // Remember
                        newStreams.Add(stream);

                        // See if we have to connect an optimizer for restarts
                        if (device.HasConsumerRestriction)
                        {
                            stream.EnableOptimizer(source);
                        }

                        // Try to start
                        stream.Refresh(m_RetestWatchDogInterval);
                    }

                    // Loaded all
                    newStreams.ForEach(stream => Streams.Add(stream.SourceKey, stream));

                    // Generate response
                    try
                    {
                        // Create all
                        return(newStreams.Select(stream => stream.CreateInformation()).ToArray());
                    }
                    finally
                    {
                        // No need to clean up
                        newStreams.Clear();
                    }
                }
                finally
                {
                    // Cleanup
                    newStreams.ForEach(stream => stream.Dispose());
                }
            });
        }