/// <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> /// Bereitet die internen Strukturen für die Konfiguration einer Quellgruppe für den /// Satellitenempfang vor. /// </summary> /// <param name="initializer">Methode zur Übernahme der Parameter der Quellgruppe.</param> /// <returns>Ein neuer Namensraum.</returns> private IDVBTuningSpace2 PrepareSatellite(out Action <ILocator> initializer) { // Get native types var location = GroupLocation as SatelliteLocation; var group = SourceGroup as SatelliteGroup; // Create DiSEqC message if (location != null) { if (group != null) { DiSEqCMessage = StandardDiSEqC.FromSourceGroup(group, location); } } // Create tuning space var space = Activator.CreateInstance(Type.GetTypeFromCLSID(DVBSTuningSpaceClassIdentifier)); try { // Change type var tuningSpace = (IDVBSTuningSpace)space; // Configure tuningSpace.UniqueName = "DVBNET Satellite"; tuningSpace.FriendlyName = "DVB.NET Satellite Tuning Space"; tuningSpace.NetworkType = "{FA4B375A-45B4-4D45-8440-263957B11623}"; tuningSpace.SystemType = DVBSystemType.Satellite; // Configure location if (location != null) { // Configure tuningSpace.LNBSwitch = checked ((int)location.SwitchFrequency); tuningSpace.HighOscillator = checked ((int)location.Frequency2); tuningSpace.LowOscillator = checked ((int)location.Frequency1); tuningSpace.SpectralInversion = SpectralInversion.Automatic; tuningSpace.FrequencyMapping = string.Empty; tuningSpace.InputRange = string.Empty; tuningSpace.NetworkID = -1; } // Create locator var locator = Activator.CreateInstance(Type.GetTypeFromCLSID(DVBSLocatorClassIdentifier)); try { // Configure group if (group == null) { initializer = null; } else { initializer = clone => { // Change type var dvbs = (IDVBSLocator)clone; // Configure dvbs.Modulation = group.UsesS2Modulation ? ModulationType.VSB8 : ModulationType.QPSK; dvbs.SymbolRate = checked ((int)(group.SymbolRate / 1000)); dvbs.CarrierFrequency = checked ((int)group.Frequency); dvbs.InnerFECRate = BinaryConvolutionCodeRate.NotSet; dvbs.OuterFECRate = BinaryConvolutionCodeRate.NotSet; dvbs.SignalPolarisation = Polarisation.NotSet; dvbs.WestPosition = group.IsWestPosition; dvbs.OuterFEC = FECMethod.NotSet; dvbs.InnerFEC = FECMethod.NotSet; dvbs.OrbitalPosition = -1; dvbs.Elevation = -1; dvbs.Azimuth = 0; // Set polarisation switch (group.Polarization) { case Polarizations.Horizontal: dvbs.SignalPolarisation = Polarisation.Horizontal; break; case Polarizations.Vertical: dvbs.SignalPolarisation = Polarisation.Vertical; break; } // Set rate switch (group.InnerFEC) { case InnerForwardErrorCorrectionModes.Conv1_2: dvbs.InnerFEC = FECMethod.Viterbi; dvbs.InnerFECRate = BinaryConvolutionCodeRate.Rate1_2; break; case InnerForwardErrorCorrectionModes.Conv2_3: dvbs.InnerFEC = FECMethod.Viterbi; dvbs.InnerFECRate = BinaryConvolutionCodeRate.Rate2_3; break; case InnerForwardErrorCorrectionModes.Conv3_4: dvbs.InnerFEC = FECMethod.Viterbi; dvbs.InnerFECRate = BinaryConvolutionCodeRate.Rate3_4; break; case InnerForwardErrorCorrectionModes.Conv3_5: dvbs.InnerFEC = FECMethod.Viterbi; dvbs.InnerFECRate = BinaryConvolutionCodeRate.Rate3_5; break; case InnerForwardErrorCorrectionModes.Conv4_5: dvbs.InnerFEC = FECMethod.Viterbi; dvbs.InnerFECRate = BinaryConvolutionCodeRate.Rate4_5; break; case InnerForwardErrorCorrectionModes.Conv5_6: dvbs.InnerFEC = FECMethod.Viterbi; dvbs.InnerFECRate = BinaryConvolutionCodeRate.Rate5_6; break; case InnerForwardErrorCorrectionModes.Conv7_8: dvbs.InnerFEC = FECMethod.Viterbi; dvbs.InnerFECRate = BinaryConvolutionCodeRate.Rate7_8; break; case InnerForwardErrorCorrectionModes.Conv8_9: dvbs.InnerFEC = FECMethod.Viterbi; dvbs.InnerFECRate = BinaryConvolutionCodeRate.Rate8_9; break; case InnerForwardErrorCorrectionModes.Conv9_10: dvbs.InnerFEC = FECMethod.Viterbi; dvbs.InnerFECRate = BinaryConvolutionCodeRate.Rate9_10; break; } } }; // Change type - actually test it tuningSpace.DefaultLocator = (ILocator)locator; } finally { // Cleanup BDAEnvironment.Release(ref locator); } // Report return((IDVBTuningSpace2)tuningSpace); } catch { // Cleanup BDAEnvironment.Release(ref space); // Forward throw; } }
/// <summary> /// Wählt eine Quellgruppe aus. /// </summary> /// <param name="group">Díe Daten der Quellgruppe.</param> /// <param name="location">Die Wahl des Ursprungs, über den die Quellgruppe empfangen werden kann.</param> public void Tune( SourceGroup group, GroupLocation location ) { // May repeat some times for (int retryCount = 3; retryCount-- > 0; Thread.Sleep( 250 )) { // All supported in order of importance if (!Tune( group as SatelliteGroup, location as SatelliteLocation ).HasValue) if (!Tune( group as CableGroup ).HasValue) if (!Tune( group as TerrestrialGroup ).HasValue) throw new DVBException( "Unsupported channel type " + group.GetType().FullName ); // Done if locked if (SignalStatus.Locked) break; // Enforce reset m_lastMessage = null; } }
/// <summary> /// Wählt eine Quellgruppe aus. /// </summary> /// <param name="group">Díe Daten der Quellgruppe.</param> /// <param name="location">Die Wahl des Ursprungs, über den die Quellgruppe empfangen werden kann.</param> /// <returns>Gesetzt, wenn es sich um eine DVB-S Quellgruppe handelt.</returns> private Channel_S? Tune( SatelliteGroup group, SatelliteLocation location ) { // Not us if (location == null) return null; if (group == null) return null; // Validate if (FrontendType != FrontendType.Satellite) throw new DVBException( "Expected " + FrontendType.ToString() + " Channel" ); // Create channel var data = new Channel_S { Mode = group.UsesS2Modulation ? DVBSMode.DVB_S2 : DVBSMode.DVB_S, Inversion = SpectrumInversion.Auto, SymbolRate = group.SymbolRate, Frequency = group.Frequency, }; // Attach to the DiSEqC setting var selector = StandardDiSEqC.FromSourceGroup( group, location ); // See if the message is different from the last one if (!selector.Equals( m_lastMessage )) { // Remember m_lastMessage = selector.Clone(); // As long as necessary for (int nCount = selector.Repeat; nCount-- > 0; Thread.Sleep( 120 )) { // Send it DVBException.ThrowOnError( _SendDiSEqCMsg( m_Class.ClassPointer, selector.Request, (byte) selector.Request.Length, selector.Burst ), "Could not send DiSEqC message" ); // Set repeat flag if (selector.Request.Length > 0) selector.Request[0] |= 1; } } // Calculated items data.b22kHz = (group.Frequency >= location.SwitchFrequency) ? 1 : 0; data.LOF = (0 == data.b22kHz) ? location.Frequency1 : location.Frequency2; // Power modes switch (group.Polarization) { case Polarizations.Horizontal: data.LNBPower = PowerMode.Horizontal; break; case Polarizations.Vertical: data.LNBPower = PowerMode.Vertical; break; case Polarizations.NotDefined: data.LNBPower = PowerMode.Off; break; default: throw new ArgumentException( group.Polarization.ToString(), "Polarization" ); } // Process return data.SetChannel( this, false ); }
/// <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; }
/// <summary> /// Wählt eine Quellgruppe aus. /// </summary> /// <param name="group">Díe Daten der Quellgruppe.</param> /// <param name="location">Die Wahl des Ursprungs, über den die Quellgruppe empfangen werden kann.</param> /// <returns>Gesetzt, wenn es sich um eine DVB-S Quellgruppe handelt.</returns> private bool SendChannel( SatelliteGroup group, SatelliteLocation location ) { // Not us if (location == null) return false; if (group == null) return false; // Validate if (FrontendType != FrontendType.Satellite) throw new DVBException( "Expected " + FrontendType.ToString() + " Channel" ); // Create channel var channel = new Channel_S { Inversion = SpectrumInversion.Auto, SymbolRate = group.SymbolRate, Frequency = group.Frequency, }; // Attach to the DiSEqC setting var selector = StandardDiSEqC.FromSourceGroup( group, location ); // See if the message is different from the last one if (!selector.Equals( m_lastMessage )) { // Remember m_lastMessage = selector.Clone(); // As long as necessary for (int nCount = selector.Repeat; nCount-- > 0; Thread.Sleep( 120 )) { // Send it DVBException.ThrowOnError( CDVBFrontend_SendDiSEqCMsg( m_Class.ClassPointer, selector.Request, (byte) selector.Request.Length, selector.Burst ), "Could not send DiSEqC Message" ); // Set repeat flag if (selector.Request.Length > 0) selector.Request[0] |= 1; } } // Calculated items channel.b22kHz = (group.Frequency >= location.SwitchFrequency) ? 1 : 0; channel.LOF = (0 == channel.b22kHz) ? location.Frequency1 : location.Frequency2; // Power modes switch (group.Polarization) { case Polarizations.Horizontal: channel.LNBPower = PowerMode.Horizontal; break; case Polarizations.Vertical: channel.LNBPower = PowerMode.Vertical; break; case Polarizations.NotDefined: channel.LNBPower = PowerMode.Off; break; default: throw new ArgumentException( group.Polarization.ToString(), "Polarization" ); } // Process CheckChannel( CDVBFrontend_SetChannel( m_Class.ClassPointer, channel, false ) ); // Check up for synchronisation Channel_S val1, val2; // Get channel twice CheckChannel( CDVBFrontend_GetChannel( m_Class.ClassPointer, out val1 ) ); CheckChannel( CDVBFrontend_GetChannel( m_Class.ClassPointer, out val2 ) ); // Did it return true; }
/// <summary> /// Wählt eine Quellgruppe aus. /// </summary> /// <param name="group">Díe Daten der Quellgruppe.</param> /// <param name="location">Die Wahl des Ursprungs, über den die Quellgruppe empfangen werden kann.</param> /// <returns>Gesetzt, wenn es sich um eine DVB-S Quellgruppe handelt.</returns> public void SetChannel( SourceGroup group, GroupLocation location ) { // Stop all filters StopFilters(); // May repeat some times for (int nRetry = 3; nRetry-- > 0; ) { // Supported types in order of importance if (!SendChannel( group as SatelliteGroup, location as SatelliteLocation )) if (!SendChannel( group as CableGroup )) if (!SendChannel( group as TerrestrialGroup )) throw new DVBException( "Unsupported Channel Type " + group.GetType().FullName ); // Wait for the signal for (int n = 10; n-- > 0; Thread.Sleep( 50 )) if (SignalStatus.Locked) return; // Force to resend DiSEqC command m_lastMessage = null; } }
/// <summary> /// Initialize the frontend. /// </summary> /// <remarks> /// When the C++ method invocation reports a hardware error the call is repeated /// up to three times with a <see cref="Thread.Sleep(int)"/>(500) between the calls. /// If the error holds a <see cref="DVBException"/> is thrown. /// <see cref="StopFilters"/> /// </remarks> /// <exception cref="DVBException"> /// Thrown when the C++ method invocation reports some <see cref="DVBError"/>. /// </exception> public void Initialize() { // Time to stop all filters StopFilters(); // Execute DVBError eCode = CDVBFrontend_Init( m_Class.ClassPointer ); // Retry for (int nRetry = 3; (DVBError.Hardware == eCode) && (nRetry-- > 0); ) { // Delay Thread.Sleep( 500 ); // Try again eCode = CDVBFrontend_Init( m_Class.ClassPointer ); } // Validate if (DVBError.None != eCode) throw new DVBException( "Can not initialize Frontend", eCode ); // Reset m_lastMessage = null; }
/// <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; }