/// <summary> /// Erzeugte eine neue Zugriffsinstanz. /// </summary> /// <param name="profile">Zu verwendende DVB.NET Hardware Abstraktion.</param> /// <param name="main">Zugehörige Anwendung.</param> public DeviceAdpator(Profile profile, IViewerSite main) : base(main) { // Remember Profile = profile; // Attach to the device Device = HardwareManager.OpenHardware(Profile); // Create m_TTXConnector = new TTXStreamConsumer(this); // Load alternate interfaces GeneralInfo = (IGeneralInfo)main; ChannelInfo = (IChannelInfo)main; StreamInfo = (IStreamInfo)main; LocalInfo = (ILocalInfo)main; // Initialize core - DirectShow Graph feed directly from a Transport Stream SetAccessor(new AudioVideoAccessor()); }
/// <summary> /// Führt die eintreffenden Aufträge aus. /// </summary> private void WorkerThread(object reset) { // Always use the configured language UserProfile.ApplyLanguage(); // Use hardware manager using (HardwareManager.Open()) { // Device to use Hardware device; // Try to attach profile try { // Open it device = HardwareManager.OpenHardware(Profile); // Should reset if ((bool)reset) { device.ResetWakeupDevice(); } // Report success ActionDone(null, null); } catch (Exception e) { // Report error ActionDone(e, null); // Did it return; } // Loop for (var lastIdle = DateTime.UtcNow; m_Running;) { // Wait for new item to process m_Trigger.WaitOne(); // Load operation var operation = m_Operation; // Clear m_Operation = null; // Process if (m_Running) { if (operation != null) { try { // Process var result = operation(device); // See if there is at least one active source with a program guide running var withGuide = Streams.Values.FirstOrDefault(stream => stream.IsProgamGuideActive.GetValueOrDefault(false)); // Check for service parser operation if (m_ServiceParser == null) { // Can be activated it at least one source with active program guide if (withGuide != null) { try { // Create m_ServiceParser = new ServiceParser(Profile, withGuide.Manager.Source); } catch { // Ignore any error m_ServiceParser = null; } } } else { // Only allowed if there is at least one source with active program guide if (withGuide == null) { DisableServiceParser(); } } // Done if (!ReferenceEquals(result, DelayedOperationTag)) { ActionDone(null, result); } } catch (Exception e) { // Report ActionDone(e, null); } } } // See if idle processing should be started if (m_Running) { if ((DateTime.UtcNow - lastIdle).TotalSeconds >= 5) { // Run OnIdle(device); // Reset lastIdle = DateTime.UtcNow; } } } // Reset EPG flag EPGProgress = null; // Clear EPG list to preserve memory m_EPGItems.Clear(); // Reset PSI scan flag using (var scanner = m_Scanner) { // Forget all m_ScanProgress = -1; m_Scanner = null; } // Just be safe try { // Final cleanup RemoveAll(); } catch { // Ignore any error } } }
/// <summary> /// Analysiert die aktuelle Konfiguration des Suchlaufs auf Basis /// der DVB <i>Network Information Table (NIT)</i> Informationen. /// </summary> private void AnalyserThread() { // Be safe try { // Configure language UserProfile.ApplyLanguage(); // Uses hardware manager using (HardwareManager.Open()) { // Attach to the hardware itself Hardware device = HardwareManager.OpenHardware(Profile); // Reset counters TotalLocations = m_Locations.Count; CurrentLocation = 0; // Last inversion used SpectrumInversions lastInversion = SpectrumInversions.On; // Process all transponders foreach (GroupLocation location in m_Locations) { // Update counter ++CurrentLocation; // Reset CurrentLocationGroupsPending = 0; CurrentLocationGroup = 0; // Check caller if (!LocationStart(location)) { return; } // Groups found on this location Dictionary <SourceGroup, bool> found = new Dictionary <SourceGroup, bool>(); // Groups with valid network information - only those are considered List <SourceGroup> nitAvailable = new List <SourceGroup>(); // Load counter CurrentLocationGroupsPending = location.Groups.Count; // Process all groups foreach (SourceGroup group in location.Groups) { // Get the expected type Type groupType = group.GetType(); // Clone the group SourceGroup newGroup = SourceGroup.FromString <SourceGroup>(group.ToString()); // Count up --CurrentLocationGroupsPending; ++CurrentLocationGroup; // See if this is already processed if (null != found.Keys.FirstOrDefault(p => p.CompareTo(newGroup, true))) { continue; } // Check for external termination if (null == m_Worker) { return; } // Not supported if (!Profile.SupportsGroup(newGroup) || !device.CanHandle(newGroup)) { // Remember m_UnhandledGroups.Add(newGroup); // Next continue; } // Check caller if (!GroupStart(location, newGroup)) { return; } // Attach to the group if (null != SelectGroup(device, location, newGroup, ref lastInversion)) { // See if we are a cable group CableGroup cableGroup = newGroup as CableGroup; // Attach to the NIT var nit = device.GetLocationInformation(15000); if (null != nit) { // Remember nitAvailable.Add(newGroup); // Process foreach (SourceGroup other in nit.Groups) { if (other.GetType() == groupType) { // See if this is a cable group CableGroup otherCable = other as CableGroup; // Update inversion if (null != otherCable) { // Other must be cable, too if (null == cableGroup) { continue; } // Use same parameters otherCable.SpectrumInversion = cableGroup.SpectrumInversion; otherCable.Bandwidth = cableGroup.Bandwidth; } // Report if (ScannerTraceSwitch.Level >= TraceLevel.Info) { Trace.WriteLine(string.Format(Properties.Resources.Trace_Scanner_NIT, other), ScannerTraceSwitch.DisplayName); } // Mark it found[other] = true; } } } } // Check caller if (!GroupDone(location, newGroup)) { return; } } // Create a brand new scan location ScanLocation scan = location.ToScanLocation(); // Try to update foreach (SourceGroup group in nitAvailable) { // Try to find the full qualified name SourceGroup nitGroup = found.Keys.FirstOrDefault(p => p.CompareTo(group, true)); // Update if (null == nitGroup) { scan.Groups.Add(group); } else { scan.Groups.Add(nitGroup); } } // Just remember m_AnalyseResult[location] = scan; // Check caller if (!LocationDone(location)) { return; } } } } catch (Exception e) { // Remember m_ThreadException = e; } }
/// <summary> /// Führt den eigentlichen Sendersuchlauf aus. /// </summary> private void ScannerThread() { // Be safe try { // Configure language UserProfile.ApplyLanguage(); // Uses hardware manager using (HardwareManager.Open()) { // Attach to the hardware itself var device = HardwareManager.OpenHardware(Profile); // Tell it that we only do a scan device.PrepareSourceScan(); // Start loading location result list foreach (var location in m_Locations) { m_ScanResults.Add(location.Clone()); } // Reset counters TotalLocations = m_Locations.Count; // Last successfull inversion var lastInversion = SpectrumInversions.On; // Process all transponders for (CurrentLocation = 0; CurrentLocation < m_Locations.Count;) { // Get new and old var location = m_Locations[CurrentLocation]; var newLocation = m_ScanResults[CurrentLocation]; // Count ++CurrentLocation; // Reset CurrentLocationGroupsPending = 0; CurrentLocationGroup = 0; // Check caller if (!LocationStart(location)) { return; } // Allow NIT scan on... var enableNIT = new List <SourceGroup>(); var foundInfo = new List <SourceGroup>(); // Startup and load the groups from the configuration foreach (SourceGroup group in location.Groups) { enableNIT.Add(group); } // All we have to process var process = new List <SourceGroup>(enableNIT); // Allowed group type var groupType = (process.Count > 0) ? process[0].GetType() : null; // All we did so far var done = new HashSet <SourceGroup>(); // Process all groups while (process.Count > 0) { // Take the first one var group = process[0]; // Remove it process.RemoveAt(0); // Reset counter CurrentLocationGroupsPending = process.Count; // Count what we did ++CurrentLocationGroup; // Already done if (done.Contains(group)) { continue; } // Found group information on equivalent group if (foundInfo.FirstOrDefault(g => g.CompareTo(group, true)) != null) { continue; } // Mark as done done.Add(group); // Check for external termination if (m_Worker == null) { return; } // Not supported if (!Profile.SupportsGroup(group) || !device.CanHandle(group)) { // Remember m_UnhandledGroups.Add(group); // Next continue; } // Read the configuration var filter = Profile.GetFilter(group); // See if this should be skiped if (filter != null) { if (filter.ExcludeFromScan) { // Remember m_GroupsExcluded.Add(group); // Next continue; } } // Check caller if (!GroupStart(location, group)) { return; } // See if we should process the NIT var checkNIT = enableNIT.Contains(group); // See if we should process if (checkNIT || group.IsComplete) { // Clone the group - may change group = SourceGroup.FromString <SourceGroup>(group.ToString()); // Attach to the group var info = SelectGroup(device, location, group, ref lastInversion); // Mark as done again - group may be updated for DVB-C and if unchanged this is simply a no-operation done.Add(group); // Read the configuration again - actually for DVB-C it may change filter = Profile.GetFilter(group); // See if this should be skiped if (filter != null) { if (filter.ExcludeFromScan) { // Remember m_GroupsExcluded.Add(group); // Next continue; } } // Remember that we found a group information - transponder is not dead if (info != null) { foundInfo.Add(group); } // See if NIT update is allowed if (checkNIT) { if (info != null) { // See if we are a cable group var cableGroup = group as CableGroup; // Try load var nit = device.GetLocationInformation(15000); if (nit != null) { foreach (SourceGroup other in nit.Groups) { if (other.GetType() == groupType) { // See if this is a cable group var otherCable = other as CableGroup; // Disable NIT scan on the group as is enableNIT.RemoveAll(g => g.CompareTo(other, true)); process.RemoveAll(g => g.CompareTo(other, true)); // Set inversion if (otherCable != null) { if (cableGroup != null) { // Use same parameters otherCable.SpectrumInversion = cableGroup.SpectrumInversion; otherCable.Bandwidth = cableGroup.Bandwidth; // Disable NIT scan on the group which may be DVB-C corrected enableNIT.RemoveAll(g => g.CompareTo(otherCable, true)); process.RemoveAll(g => g.CompareTo(otherCable, true)); } } // Report if (ScannerTraceSwitch.Level >= TraceLevel.Info) { Trace.WriteLine(string.Format(Properties.Resources.Trace_Scanner_NIT, other), ScannerTraceSwitch.DisplayName); } // Add for processing process.Insert(0, other); } } } } } // Reset counter - may be updated if a new NIT was processed CurrentLocationGroupsPending = process.Count; // Skip if a legacy template group if (group.IsComplete) { // Merge newLocation.Groups.Add(group); // Process this group if (info == null) { m_Protocol.Add(new ProtocolRecord { Mode = ProtocolRecordMode.EmptyGroup, Location = location, Group = group }); } else { foreach (var source in info.Sources) { // Only stations var station = source as Station; if (station == null) { continue; } // Attach to the filter var modifiers = Profile.GetFilter(source); if (modifiers != null) { if (modifiers.ExcludeFromScan) { continue; } else { modifiers.ApplyTo(station); } } // Remember group.Sources.Add(station); // Get the count int foundOfType; if (!SourcesFound.TryGetValue(station.SourceType, out foundOfType)) { foundOfType = 0; } // Update SourcesFound[station.SourceType] = ++foundOfType; // Ask user if (!StationFound(location, group, station)) { return; } } } } } // Check caller if (!GroupDone(location, group)) { return; } } // Check caller if (!LocationDone(location)) { return; } } } } catch (Exception e) { // Remember m_ThreadException = e; } }