/// <summary> /// Startet eine Überwachung. /// </summary> /// <param name="graph">Die zugehörige Empfangsinstanz.</param> /// <param name="services">Die Liste der Dienste.</param> /// <param name="processor">Der Verarbeitungsalgorithmus.</param> public static void Start(DataGraph graph, SourceIdentifier[] services, Func <PMT, bool, bool> processor) { // Validate if (graph == null) { throw new ArgumentNullException("graph"); } if (processor == null) { throw new ArgumentNullException("processor"); } // Nothing to do if (services == null) { return; } // Create scope and process var sequencer = new PMTSequencer(graph, services, processor); // Nothing to do if (sequencer.m_services.Length < 1) { return; } // Install watch dog sequencer.ProcessNext(null); }
/// <summary> /// Entschlüsselt eine einzelne Quelle. /// </summary> /// <param name="service">Die Informationen zur Quelle.</param> /// <param name="graph">Der zu verwendende Graph.</param> public void Decrypt( ushort service, DataGraph graph ) { // Check COM interface var controlPtr = ComIdentity.QueryInterface( graph.AdditionalFilters[m_filterIndex].Interface, typeof( KsControl.Interface ) ); if (controlPtr != IntPtr.Zero) using (var control = new KsControl( controlPtr )) control.SetServices( service ); }
/// <summary> /// Startet eine Überwachung. /// </summary> /// <param name="graph">Die zugehörige Empfangsinstanz.</param> /// <param name="services">Die Liste der Dienste.</param> /// <param name="processor">Der Verarbeitungsalgorithmus.</param> private PMTSequencer( DataGraph graph, SourceIdentifier[] services, Func<PMT, bool, bool> processor ) { // Remember m_services = services.Where( s => s != null ).ToArray(); m_lastTable = m_services.ToDictionary( s => s.Service, s => default( PMT ) ); m_processor = processor; m_graph = graph; }
/// <summary> /// Startet eine Überwachung. /// </summary> /// <param name="graph">Die zugehörige Empfangsinstanz.</param> /// <param name="services">Die Liste der Dienste.</param> /// <param name="processor">Der Verarbeitungsalgorithmus.</param> private PMTSequencer(DataGraph graph, SourceIdentifier[] services, Func <PMT, bool, bool> processor) { // Remember m_services = services.Where(s => s != null).ToArray(); m_lastTable = m_services.ToDictionary(s => s.Service, s => default(PMT)); m_processor = processor; m_graph = graph; }
/// <summary> /// Führt die DiSEqC Steuerung aus. /// </summary> /// <param name="token">Die Informationen zur aktuellen Wahl der Quellgruppe.</param> /// <returns>Das Ergebnis der Operation.</returns> private PipelineResult ApplyDiSEqC( DataGraph.TuneToken token ) { // See if we are fully active var message = (token == null) ? null : token.DiSEqCMessage; if (message == null) { // Shutdown connection Close(); // Reset m_LastDiSEqC = null; // Next return PipelineResult.Continue; } // Attach to tuner var tuner = token.Pipeline.Graph.TunerFilter; if (tuner == null) return PipelineResult.Continue; // Verify that grpah is created if (token.Pipeline.Graph.TransportStreamAnalyser == null) return PipelineResult.Continue; // Already did it if (message.Equals( m_LastDiSEqC )) return PipelineResult.Continue; // Open the device Open( tuner ); try { // Process var data = (byte[]) message.Request.Clone(); var error = bdaapiSetDiSEqCMsg( Device, data, (byte) data.Length, (byte) message.Repeat, message.Burst, Polarisation.NotSet ); if (error == APIErrorCodes.Success) m_LastDiSEqC = message.Clone(); else throw new DVBException( error.ToString() ); } catch (Exception e) { // Report EventLog.WriteEntry( "DVB.NET", string.Format( "TechnoTrend BDA API DiSEqC: {0}", e ), EventLogEntryType.Error ); // Force recalibrate on next call m_LastDiSEqC = null; } // Next one, please return PipelineResult.Continue; }
/// <summary> /// Aktualisiert die Aktionslisten des DVB Empfangs. /// </summary> /// <param name="graph">Der DirectShow Graph für den DVB Empfang.</param> /// <param name="profile">Das verwendete Geräteprofil.</param> /// <param name="types">Die gewünschte Aktivierung.</param> void IPipelineExtension.Install( DataGraph graph, Profile profile, PipelineTypes types ) { // Validate if (graph == null) throw new ArgumentNullException( "graph" ); if (profile == null) throw new ArgumentNullException( "profile" ); // Check supported types if ((types & PipelineTypes.DVBS2) != 0) graph.TunePipeline.AddPreProcessing( ActivateS2 ); }
/// <summary> /// Aktualisiert die Aktionslisten des DVB Empfangs. /// </summary> /// <param name="graph">Der DirectShow Graph für den DVB Empfang.</param> /// <param name="profile">Das verwendete Geräteprofil.</param> /// <param name="types">Die gewünschte Aktivierung.</param> void IPipelineExtension.Install( DataGraph graph, Profile profile, PipelineTypes types ) { // Validate if (graph == null) throw new ArgumentNullException( "graph" ); if (profile == null) throw new ArgumentNullException( "profile" ); // Check supported types if ((types & PipelineTypes.SignalInformation) != 0) graph.SignalPipeline.AddPostProcessing( TransformSignal ); }
/// <summary> /// Erzeugt neue Einstellungen. /// </summary> /// <param name="graph">Der zugehörige Graph.</param> /// <exception cref="ArgumentNullException">Es wurde kein Graph angegeben.</exception> internal GraphConfiguration( DataGraph graph ) { // Validate if (graph == null) throw new ArgumentNullException( "graph" ); // Remember Graph = graph; // Finish MinimumPATCountWaitTime = 50; MinimumPATCount = 5; }
/// <summary> /// Erzeugt neue Einstellungen. /// </summary> /// <param name="graph">Der zugehörige Graph.</param> /// <exception cref="ArgumentNullException">Es wurde kein Graph angegeben.</exception> internal GraphConfiguration(DataGraph graph) { // Validate if (graph == null) { throw new ArgumentNullException("graph"); } // Remember Graph = graph; // Finish MinimumPATCountWaitTime = 50; MinimumPATCount = 5; }
/// <summary> /// Führt die DiSEqC Steuerung aus. /// </summary> /// <param name="token">Die aktuellen Informationen zum Wechsel der Quellgruppe.</param> /// <returns>Meldet, wie die weitere Abarbeitung zu erfolgen hat.</returns> private static PipelineResult ApplyDiSEqC( DataGraph.TuneToken token ) { // Check mode var location = (token == null) ? null : token.GroupLocation as SatelliteLocation; if (location == null) return PipelineResult.Continue; // Load tuner var tuner = token.Pipeline.Graph.TunerFilter; if (tuner == null) return PipelineResult.Continue; // Verify that grpah is created if (token.Pipeline.Graph.TransportStreamAnalyser == null) return PipelineResult.Continue; // Check support var diseqc = tuner.GetOutputControlNode<IBDADiseqCommand>( 0 ); if (diseqc == null) return PipelineResult.Continue; // Requires cleanup try { // Enable diseqc.Enable = true; // Set mode switch (location.LNB) { case DiSEqCLocations.BurstOff: diseqc.UseToneBurst = false; break; case DiSEqCLocations.BurstOn: diseqc.UseToneBurst = true; break; case DiSEqCLocations.DiSEqC1: diseqc.LNBSource = 1; break; case DiSEqCLocations.DiSEqC2: diseqc.LNBSource = 2; break; case DiSEqCLocations.DiSEqC3: diseqc.LNBSource = 3; break; case DiSEqCLocations.DiSEqC4: diseqc.LNBSource = 4; break; case DiSEqCLocations.None: diseqc.Enable = false; break; } } finally { // Cleanup BDAEnvironment.Release( ref diseqc ); } // Next return PipelineResult.Continue; }
/// <summary> /// Berechnet die Signalstärke. /// </summary> /// <param name="token">Der aktuelle Zustand der Berechnung.</param> /// <returns>Informationen zur Fortführung der Operation.</returns> private static PipelineResult TransformSignal( DataGraph.SignalToken token ) { // Shutdown call - ignore if (token == null) return PipelineResult.Continue; // Nothing we can do if (!token.SignalInformation.Strength.HasValue) return PipelineResult.Continue; // Make sure that bounds are respected token.SignalInformation.Strength = Math.Max( 0, Math.Min( 15, token.SignalInformation.Strength.Value ) ); // Next return PipelineResult.Continue; }
/// <summary> /// Berechnet die Signalstärke. /// </summary> /// <param name="token">Der aktuelle Zustand der Berechnung.</param> /// <returns>Informationen zur Fortführung der Operation.</returns> private static PipelineResult TransformSignal( DataGraph.SignalToken token ) { // Shutdown call - ignore if (token == null) return PipelineResult.Continue; // Nothing we can do if (!token.SignalInformation.Strength.HasValue) return PipelineResult.Continue; // Translate var dBGuess = Math.Round( 10.25 - token.SignalInformation.Strength.Value / 960.0, 1 ); // Save in bounds token.SignalInformation.Strength = Math.Max( 0, Math.Min( 15, dBGuess ) ); // Next return PipelineResult.Continue; }
/// <summary> /// Aktiviert die Entschlüsselung einer Quelle. /// </summary> /// <param name="token">Informationen zur gewählten Quelle.</param> private PipelineResult Decrypt( DataGraph.DecryptToken token ) { // Load graph if (token != null) m_DataGraph = token.Pipeline.Graph; // Get unique call identifier var callIdentifier = Interlocked.Increment( ref m_ChangeCounter ); // Check mode of operation var sources = (token == null) ? null : token.Sources; var noSources = (sources == null) || (sources.Length < 1); if (noSources) { // Shutdown all if (m_DataGraph != null) if (m_DataGraph.TunerFilter != null) lock (m_deviceAccess) Decrypt( null, (token == null) || (sources == null) ); // Next return PipelineResult.Continue; } // Start processor token.WaitForPMTs( ( pmt, first ) => { // See if we are still allowed to process and do so lock (m_deviceAccess) if (Thread.VolatileRead( ref m_ChangeCounter ) == callIdentifier) Decrypt( pmt, false ); else return false; // Next return true; }, sources ); // Next return PipelineResult.Continue; }
/// <summary> /// Startet eine Überwachung. /// </summary> /// <param name="graph">Die zugehörige Empfangsinstanz.</param> /// <param name="services">Die Liste der Dienste.</param> /// <param name="processor">Der Verarbeitungsalgorithmus.</param> public static void Start( DataGraph graph, SourceIdentifier[] services, Func<PMT, bool, bool> processor ) { // Validate if (graph == null) throw new ArgumentNullException( "graph" ); if (processor == null) throw new ArgumentNullException( "processor" ); // Nothing to do if (services == null) return; // Create scope and process var sequencer = new PMTSequencer( graph, services, processor ); // Nothing to do if (sequencer.m_services.Length < 1) return; // Install watch dog sequencer.ProcessNext( null ); }
/// <summary> /// Berechnet die Signalstärke. /// </summary> /// <param name="token">Der aktuelle Zustand der Berechnung.</param> /// <returns>Informationen zur Fortführung der Operation.</returns> private static PipelineResult TransformSignal( DataGraph.SignalToken token ) { // Shutdown call - ignore if (token == null) return PipelineResult.Continue; // See if strength information from network provider is available var strength = token.SignalStrength; if (!strength.HasValue) return PipelineResult.Continue; // Get the raw value var bias = (double) (short) -(strength + 1); // Translate var dBGuess = Math.Round( 8.175 - bias / 1368.0, 1 ); // Save in bounds token.SignalInformation.Strength = Math.Max( 0, Math.Min( 15, dBGuess ) ); // Next return PipelineResult.Continue; }
/// <summary> /// Aktualisiert die Aktionslisten des DVB Empfangs. /// </summary> /// <param name="graph">Der DirectShow Graph für den DVB Empfang.</param> /// <param name="profile">Das verwendete Geräteprofil.</param> /// <param name="types">Die gewünschte Aktivierung.</param> void IPipelineExtension.Install( DataGraph graph, Profile profile, PipelineTypes types ) { // Validate if (graph == null) throw new ArgumentNullException( "graph" ); if (profile == null) throw new ArgumentNullException( "profile" ); // Check supported types if ((types & PipelineTypes.CICAM) != 0) { // Load static settings m_suppress = AdditionalFilterSelector.GetSuppression( PipelineTypes.CICAM, profile.Parameters ); m_hasBeenReset = (m_suppress != SuppressionMode.None); // Analyse settings if (!bool.TryParse( profile.Parameters.GetParameter( PipelineTypes.CICAM, AdditionalFilterSelector.CancelEncryptionOnChangedStream ), out m_disableOnChange )) m_disableOnChange = false; if (!int.TryParse( profile.Parameters.GetParameter( PipelineTypes.CICAM, AdditionalFilterSelector.DelayOnChangedStream ), out m_changeDelay )) m_changeDelay = 0; // Register in pipeline graph.DecryptionPipeline.AddPostProcessing( Decrypt ); // Check for additional filter var filterDisplayName = profile.Parameters.GetParameter( PipelineTypes.CICAM, AdditionalFilterSelector.FilterName ); if (!string.IsNullOrEmpty( filterDisplayName )) { // Load moniker - if available var filterMoniker = profile.Parameters.GetParameter( PipelineTypes.CICAM, AdditionalFilterSelector.FilterMoniker ); // Remember position of our extension m_filterIndex = graph.AdditionalFilterInformations.Count; // Register in graph graph.AdditionalFilterInformations.Add( DeviceAndFilterInformations.Cache.AllFilters.FindFilter( filterDisplayName, filterMoniker ) ); } } }
/// <summary> /// Aktiviert die Entschlüsselung einer Quelle. /// </summary> /// <param name="token">Informationen zur gewählten Quelle.</param> /// <exception cref="NotSupportedException">Aktuell kann immer nur eine Quelle entschlüsselt werden.</exception> private PipelineResult Decrypt( DataGraph.DecryptToken token ) { // Load graph if (token != null) m_DataGraph = token.Pipeline.Graph; // Get unique call identifier var callIdentifier = Interlocked.Increment( ref m_ChangeCounter ); // Check mode of operation var sources = (token == null) ? null : token.Sources; if ((sources == null) || (sources.Length < 1)) { // Shutdown if (sources == null) lock (m_deviceAccess) Close(); // Next return PipelineResult.Continue; } // Check request if (sources.Length != 1) throw new NotSupportedException( Properties.Resources.Exception_DecryptSingle ); // Wait for PMT token.WaitForPMTs( ( pmt, first ) => { // See if we are still allowed to process and do so lock (m_deviceAccess) if (Thread.VolatileRead( ref m_ChangeCounter ) == callIdentifier) Decrypt( pmt ); else return false; // Next return true; }, sources ); // Next return PipelineResult.Continue; }
/// <summary> /// Führt die DiSEqC Steuerung aus. /// </summary> /// <param name="token">Die aktuellen Informationen zum Wechsel der Quellgruppe.</param> /// <returns>Meldet, wie die weitere Abarbeitung zu erfolgen hat.</returns> private PipelineResult ApplyDiSEqC( DataGraph.TuneToken token ) { // Not active var diseqc = (token == null) ? null : token.DiSEqCMessage; if (diseqc == null) { // Reset request - or first call at all m_LastDiSEqC = null; // Next return PipelineResult.Continue; } // Attach to tuner var tuner = token.Pipeline.Graph.TunerFilter; if (tuner == null) return PipelineResult.Continue; // Verify that grpah is created if (token.Pipeline.Graph.TransportStreamAnalyser == null) return PipelineResult.Continue; // Request the message to send if (diseqc.Equals( m_LastDiSEqC )) return PipelineResult.Continue; // Attach to the one input pin of the tuner using (var input = tuner.GetSinglePin( PinDirection.Input )) using (var propertySet = KsPropertySet.Create<DiSEqCMessage>( input.Interface )) if (propertySet != null) { // Create the identifier of the property to use var nodeReference = KsPNode.Create( TunerExtensionPropertiesS2, TunerExtensionProperties.DiSEqC, 0 ); // Check for support of the property if (!propertySet.DoesSupport( nodeReference, PropertySetSupportedTypes.Set )) return PipelineResult.Continue; // Create structures var message = new DiSEqCMessage(); // Create a copy var command = (byte[]) diseqc.Request.Clone(); // As long as necessary try { // Prepare the message message.Request = new byte[151]; // Fill the message command.CopyTo( message.Request, 0 ); // Configure message.RequestLength = (byte) command.Length; message.LastMessage = true; message.Power = 0; // Send the message propertySet.Set( nodeReference, message ); } catch { // Reset m_LastDiSEqC = null; // Forward throw; } // Remember m_LastDiSEqC = diseqc.Clone(); } // Next return PipelineResult.Continue; }
/// <summary> /// Setzt die DVB-S2 Empfangsparameter. /// </summary> /// <param name="tune">Informationen zur aktuellen Auswahl der Quellgruppe.</param> /// <returns>Beschreibt, wie weiter vorzugehen ist.</returns> private static PipelineResult TuneDVBS2( DataGraph.TuneToken tune ) { // Graph is starting or resetting var group = (tune == null) ? null : tune.SourceGroup as SatelliteGroup; if (group == null) return PipelineResult.Continue; // Attach to tuner var tuner = tune.Pipeline.Graph.TunerFilter; if (tuner == null) return PipelineResult.Continue; // Verify that grpah is created if (tune.Pipeline.Graph.TransportStreamAnalyser == null) return PipelineResult.Continue; // Not DVB-S2 if (!group.UsesS2Modulation) return PipelineResult.Continue; // Attach to the BDA interface var config = tuner.GetDigitalDemodulator(); if (config == null) return PipelineResult.Continue; // Requires cleanup try { // Change interface var config2 = config as IBDADigitalDemodulator2; if (config2 == null) return PipelineResult.Continue; // Pilot to use var pilot = PilotMode.NotSet; // Roll-Off to use var rollOff = RollOff.NotDefined; switch (group.RollOff) { case S2RollOffs.Alpha20: rollOff = RollOff.Twenty; break; case S2RollOffs.Alpha25: rollOff = RollOff.TwentyFive; break; case S2RollOffs.Alpha35: rollOff = RollOff.ThirtyFive; break; default: rollOff = RollOff.NotSet; break; } // Modulation to use var modulation = ModulationType.NotDefined; switch (group.Modulation) { case SatelliteModulations.QPSK: modulation = ModulationType.NBCQPSK; break; case SatelliteModulations.PSK8: modulation = ModulationType.NBC8PSK; break; case SatelliteModulations.QAM16: modulation = ModulationType.QAM16; break; } // Update conditionally if (modulation != ModulationType.NotDefined) config2.SetModulation( ref modulation ); // Update unconditionally config2.SetRollOff( ref rollOff ); config2.SetPilot( ref pilot ); } finally { // Back to COM BDAEnvironment.Release( ref config ); } // Normal return PipelineResult.Continue; }
/// <summary> /// Aktiviert die Auswahl einer DVB-S2 Quellgruppe. /// </summary> /// <param name="tune">Der aktuelle Auswahlvorgang.</param> /// <returns>Beschreibt, wie die Bearbeitung weiter fortgeführt werden soll.</returns> private static PipelineResult ActivateS2( DataGraph.TuneToken tune ) { // Graph is starting or resetting var group = (tune == null) ? null : tune.SourceGroup as SatelliteGroup; if (group == null) return PipelineResult.Continue; // Attach to tuner var tuner = tune.Pipeline.Graph.TunerFilter; if (tuner == null) return PipelineResult.Continue; // Verify that grpah is created if (tune.Pipeline.Graph.TransportStreamAnalyser == null) return PipelineResult.Continue; // Not DVB-S2 if (!group.UsesS2Modulation) return PipelineResult.Continue; // Attach to the locator of the tune request var locator = tune.TuneRequest.Locator; try { // Apply modulation switch (group.Modulation) { case SatelliteModulations.QPSK: locator.Modulation = (ModulationType) (ModulationType.AnalogFrequency + 5); break; case SatelliteModulations.PSK8: locator.Modulation = (ModulationType) (ModulationType.AnalogFrequency + 6); break; case SatelliteModulations.QAM16: locator.Modulation = ModulationType.QAM16; break; } // Store back tune.TuneRequest.Locator = locator; } finally { // Cleanup properly BDAEnvironment.Release( ref locator ); } // Attach to the one input pin of the tuner using (var input = tuner.GetSinglePin( PinDirection.Input )) { // Start with roll-off using (var propertySet = KsPropertySet.Create<RollOff>( input.Interface )) if (propertySet != null) { // Get the property and node to use var roNode = KsPNode.Create( BdaTunerExtensionProperties, BDATunerExtensions.RollOff, BDANodes.Tuner ); // Update if (propertySet.DoesSupport( roNode, PropertySetSupportedTypes.Set )) switch (group.RollOff) { case S2RollOffs.Alpha35: propertySet.Set( roNode, RollOff.Offset35 ); break; case S2RollOffs.Alpha25: propertySet.Set( roNode, RollOff.Offset25 ); break; case S2RollOffs.Alpha20: propertySet.Set( roNode, RollOff.Offset20 ); break; default: propertySet.Set( roNode, RollOff.NotSet ); break; } } // Continue with pilot using (var propertySet = KsPropertySet.Create<Pilot>( input.Interface )) if (propertySet != null) { // Get the property and node to use var piNode = KsPNode.Create( BdaTunerExtensionProperties, BDATunerExtensions.Pilot, BDANodes.Tuner ); // Update if (propertySet.DoesSupport( piNode, PropertySetSupportedTypes.Set )) propertySet.Set( piNode, Pilot.NotSet ); } } // Normal return PipelineResult.Continue; }
/// <summary> /// Führt die DiSEqC Steuerung aus. /// </summary> /// <param name="token">Die aktuellen Informationen zum Wechsel der Quellgruppe.</param> /// <returns>Meldet, wie die weitere Abarbeitung zu erfolgen hat.</returns> private static PipelineResult ApplyDiSEqC( DataGraph.TuneToken token ) { // Check mode var location = (token == null) ? null : token.GroupLocation as SatelliteLocation; if (location == null) return PipelineResult.Continue; // Attach to capture var capture = token.Pipeline.Graph.CaptureFilter; if (capture == null) return PipelineResult.Continue; // Verify that grpah is created if (token.Pipeline.Graph.TransportStreamAnalyser == null) return PipelineResult.Continue; // Initial uint positionOption; switch (location.LNB) { case DiSEqCLocations.DiSEqC1: positionOption = 0x0000; break; case DiSEqCLocations.DiSEqC2: positionOption = 0x0001; break; case DiSEqCLocations.DiSEqC3: positionOption = 0x0100; break; case DiSEqCLocations.DiSEqC4: positionOption = 0x0101; break; default: positionOption = uint.MaxValue; break; } // Request interface var filter = capture.GetFrequencyFilter(); if (filter != null) { // Do it the more or less modern way try { // Load filter.Range = positionOption; } finally { // Cleanup BDAEnvironment.Release( ref filter ); } } else { // Attach to the tuning space var space = token.TuneRequest.TuningSpace; try { // Store ((IDVBSTuningSpace) space).InputRange = positionOption.ToString(); } finally { // Cleanup BDAEnvironment.Release( ref space ); } } // Next return PipelineResult.Continue; }
/// <summary> /// Aktualisiert die Aktionslisten des DVB Empfangs. /// </summary> /// <param name="graph">Der DirectShow Graph für den DVB Empfang.</param> /// <param name="profile">Das verwendete Geräteprofil.</param> /// <param name="types">Die gewünschte Aktivierung.</param> void IPipelineExtension.Install( DataGraph graph, Profile profile, PipelineTypes types ) { // Validate if (graph == null) throw new ArgumentNullException( "graph" ); if (profile == null) throw new ArgumentNullException( "profile" ); // Check supported types if ((types & PipelineTypes.CICAM) != 0) graph.DecryptionPipeline.AddPostProcessing( Decrypt ); }
/// <summary> /// Aktiviert die Entschlüsselung einer Quelle. /// </summary> /// <param name="token">Informationen zur gewählten Quelle.</param> public PipelineResult Decrypt( DataGraph.DecryptToken token ) { // Load graph if (token != null) m_dataGraph = token.Pipeline.Graph; // Get unique call identifier var callIdentifier = Interlocked.Increment( ref m_changeCounter ); // See if we can do anything if (m_dataGraph == null) return PipelineResult.Continue; if (m_filterIndex < 0) return PipelineResult.Continue; if (m_filterIndex >= m_dataGraph.AdditionalFilters.Count) return PipelineResult.Continue; // Deactivate if CAM reset is forbidden var sources = (token == null) ? null : token.Sources; var noSources = (sources == null) || (sources.Length < 1); if ((noSources && (m_suppress != SuppressionMode.Complete)) || !m_hasBeenReset) lock (m_deviceAccess) { // Check COM interface var controlPtr = ComIdentity.QueryInterface( m_dataGraph.AdditionalFilters[m_filterIndex].Interface, typeof( KsControl.Interface ) ); if (controlPtr == IntPtr.Zero) return PipelineResult.Continue; // Process using (var control = new KsControl( controlPtr )) { // Report if (BDASettings.BDATraceSwitch.Enabled) Trace.WriteLine( Properties.Resources.Trace_ResetCAM, BDASettings.BDATraceSwitch.DisplayName ); // Reset the CAM control.Reset(); // We did it once m_hasBeenReset = true; } } // Start processor token.WaitForPMTs( ( pmt, first ) => { // See if we are still allowed to process and do so lock (m_deviceAccess) { // No longer current if (Thread.VolatileRead( ref m_changeCounter ) != callIdentifier) return false; // Try reset if (!first) if (m_disableOnChange) Decrypt( 0, m_dataGraph ); // Wait for it if (m_changeDelay > 0) Thread.Sleep( m_changeDelay ); // Regular Decrypt( pmt.ProgramNumber, m_dataGraph ); } // Next return true; }, sources ); // Next return PipelineResult.Continue; }
/// <summary> /// Übernimmt die Ansteuerung einer Antenne. /// </summary> /// <param name="tune">Der aktuelle Änderungswunsch.</param> /// <returns>Beschreibt, wie weiter fortzufahren ist.</returns> private PipelineResult ApplyDiSEqC( DataGraph.TuneToken tune ) { // Not active var diseqc = (tune == null) ? null : tune.DiSEqCMessage; if (diseqc == null) { // Reset request - or first call at all m_LastDiSEqC = null; // Next return PipelineResult.Continue; } // Attach to tuner var tuner = tune.Pipeline.Graph.TunerFilter; if (tuner == null) return PipelineResult.Continue; // Verify that grpah is created if (tune.Pipeline.Graph.TransportStreamAnalyser == null) return PipelineResult.Continue; // Request the message to send if (diseqc.Equals( m_LastDiSEqC )) return PipelineResult.Continue; // Attach to the one input pin of the tuner using (var input = tuner.GetSinglePin( PinDirection.Input )) using (var propertySet = KsPropertySet.Create<NovaDiSEqCMessage>( input.Interface )) if (propertySet != null) { // Create the identifier of the property to use var nodeReference = KsPNode.Create( BdaTunerExtensionProperties, BDATunerExtensions.DiSEqC, BDANodes.Tuner ); // Check for support of the property if (!propertySet.DoesSupport( nodeReference, PropertySetSupportedTypes.Set )) return PipelineResult.Continue; // Create structures var message = new NovaDiSEqCMessage(); // Create a copy var command = (byte[]) diseqc.Request.Clone(); // As long as necessary for (int nCount = diseqc.Repeat; nCount-- > 0; Thread.Sleep( 120 )) try { // Prepare the message message.Request = new byte[151]; message.Response = new byte[9]; // Fill the message command.CopyTo( message.Request, 0 ); // Set the lengths message.RequestLength = (uint) command.Length; message.ResponseLength = 0; // Configure message.ToneBurstModulation = (ToneBurstModulationModes) diseqc.Burst; message.ResponseMode = DiSEqCReceiveModes.NoReply; message.DiSEqCVersion = DiSEqCVersions.Version1; message.AmplitudeAttenuation = 3; message.LastMessage = true; // Send the message propertySet.Set( nodeReference, message ); // Set repeat flag if (command.Length > 0) command[0] |= 1; } catch { // Reset m_LastDiSEqC = null; // Forward throw; } // Remember m_LastDiSEqC = diseqc.Clone(); } // Done return PipelineResult.Continue; }