VideoText in DVB.NET 3.9 für Entwickler

Da ich für das Service Pack 1 gerade ein bißchen am Code herumspielen musst, hier eine grobe Zusammenfassung der Möglichkeiten, die DVB.NET einem Entwickler zur Auswertung von VideoText bietet.

Kern ist die Klasse TTXParser, deren AddPayload Methode mit dem Rohdatenstrom (ES) beschickt wird. Sobald eine Seite (TTXPage) vollständig bereit steht, wird ein entsprechendes Ereignis ausgelöst (OnPage). Ergänzend bietet DVB.NET mit der Klasse PageManager die Möglichkeit, einmal empfangene Seiten vorzuhalten. Diese können dann gezielt angefordert werden (CurrentPage) und werden dann unmittelbar oder nach Empfang der ersten Version über ein Ereignis gemeldet (OnPageAvailable) – dito bei jeder folgenden Aktualisierung der Seite [unabhängig davon, ob sich der Inhalt verändert hat]. Sollten kein Rohdatenstrom vorliegen (so wie es beim DVB Empfang oft der Fall ist), kann dieser durch Kombination mit einer TTXStream Instanz aus einem PES erzeugt werden.

Im Zentrum der eigentlichen Darstellung stehen Instanzen der TTXPage Klasse. Diese verwaltet eine voranalyiserte Darstellung der Seite, die allerdings für die direkte Auswertung nicht zwingend geeignet ist. Hier sind noch Steuersequenzen für Zeichengröße, Zeichensatz, Vorder- und Hintergrundfarbe etc. eingebettet. Mit einem Aufruf von CreatePage erfolgt die Umsetzung in eine .NET Bitmap Instanz, die direkt zur Anzeige verwendet werden kann. Die Unterstützung des VideoText Standards ist zwar recht rudimentär (international Zeichensätze werden nicht korrekt dargestellt, was etwa ARTE oder BBC etwas komisch aussehen lässt), für die deutschen Sender reicht es aber. Ebenso vorhanden sind transparente Seiten etwa für Untertitel.

Ergänzend zur Bitmap und den Rohdaten bietet CreatePage die Option, eine Information über alle auf der Seite ausgegebenen Ziffern zu erfragen. Diese werden über eine Klasse DigitManager verwaltet. Mit der Methode GetTTXDigitAt kann zu einer relativen Position auf der Seite (in den Koordinaten 0.0 bis 1.0, wobei 0.0 / 0.0 wie gewohnt oben links ist) ermittelt werden, ob dort eine Ziffer ausgegeben wurde. Ist das der Fall, so wird auch der Rahmen des Zeichens in relativen Koordinaten gemeldet. Ergänzend prüft GetPageAt zu einer Position, ob dort eine dreistellige Seitennummer im Bereich 100 bis 899 (jeweils einschließlich) vorhanden ist – dazu wird natürlich GetTTXDigitAt eingesetzt. Bedingung ist eine Sequenz aus genau drei Ziffern gleicher Größe – Höhe und Breite.

Viel Spaß

Jochen

Noch ein kleines Tool: BBC / ITV Programmzeitschrift

Ich habe aus Eigennutz mal ein kleines Tool geschrieben, das die FreeSat Programmzeitschrift in eine Excel fähige Datei auslesen kann. Nix Dolles und sicher noch mit Bugs und Schönheitsfehlern, aber vielleicht nützlich für den den einen oder anderen. Es wird eine funktionsfähige (i.e. mindestens ein Geräteprofil mit durchgeführtem Suchlauf auf Astra 2 / EuroBird) DVB.NET 3.9 Installation vorausgesetzt. Die Quelltexte sind als Beispiel dabei (es ist eine ganz einfache Page basierte WPF Anwendung).

Viel Spaß

Jochen

Zum Beispiel

Lesepause :-)

Ich habe meine freie Zeit mal böswillig nicht genutzt, um etwas an VCR.NET zu tun, sondern vielmehr, um mein Hintergrundwissen im Bereich Betriebssysteme aufzufrischen – im aktuellen Arbeitskontext ist das natürlich Windows. Die dazu verwendete Literatur war die nun fünfte Auflage von Windows Internals – ein oder zwei ältere Versionen hatte ich mir schon vor langer Zeit einmal angetan.

Auch wenn das Buch in der Gesamtheit einen etwas gemischten Eindruck hinterläßt, halte ich es für die angesprochene Zielgruppe für unbedingt empfehlenswert. Die meisten Kapitel sind didaktisch gut aufgebaut, logisch und meiner Ansicht nach genau in der richtigen Tiefe. Es geht nicht in die absoluten Details (elendige Diskussionen aller Felder von Kernel Strukturen sind extremst selten), sondern vermittelt vielmehr Hintergründe, Zusammenhänge und zum Teil auch Designentscheidungen. Wer wirklich direkt anfangen will, einen Treiber zu schreiben, wird sicher mehr brauchen – aber das war auch nicht meine Erwartungshaltung. Bei mir hinterläßt es zumindest das Gefühl, einige Grundprinzipien verstanden zu haben – und es hat mich zu einigen Experimenten mit Vista rund um UAC und VSS motiviert, bei denen diese Prinzipen auch für den Endanwender fühlbar werden.

Allerdings gibt es auch einige (zwei oder so) Kapitel, die eher verwirrend waren – vielleicht, weil das nicht wirklich mein Thema war, vielleicht, weil der Umfang der zu vermittelnden Daten einfach den Rahmen sprengte. Die Netzwerkarchitektur scheint mir eher ein ‚alles mal erwähnen‘ zu sein als sich an der angenehmen Tiefe des Rest zu orientieren – wie gesagt, kann auch an mir liegen.

Auch vielleicht nicht ganz ohne Schuld auf meiner Seite habe ich das Gefühl, dass zwischen den (zweifellos berechtigten) Querreferenzen nach vorne und hinten doch mal etwas auf der Strecke blieb. So meine ich das eine oder andere mal ein ‚wie bereits in Kapitel X ausführlich beschrieben‘ bei Nachschlagen auf einen Absatz mit zwei Sätzen reduziert gesehen zu haben. Da ich aber keine Zeit hatte, alles mehrfach zu lesen und nachzuschlagen (immerhin 1150 Seiten), kann ich das nicht für alle Stellen oder gar für Vorwärtsreferenzen bestätigen.

Alles in Allem meine ich, das Buch ist mit der richtigen Erwartungshaltung unbedingt sein Geld wert (Tipp: mal bei Amazon UK statt hier nachzuschauen, das kann sich je nach Situation trotz Porto lohnen).

Nun versuche ich etwas braver mit meiner Zeit umzugehen und mal nach dem DVB.NET / VCR.NET 3.9 Service Pack 1 zu schauen.

Viel Spaß

Jochen

WPF Evaluation: Ressourcen

Ich stelle mir XAML Ressourcen als eine Art statische Felder vor, die beim Starten der Anwendung automatisch initialisiert werden. Natürlich ist dieses Bild etwas vereinfacht, da es Konzepte wie die hierarchische Sichtbarkeit nicht wirklich wiedergeben kann, aber für einen Einstieg in die Thematik sollte es reichen.

Eine der wohl üblichsten Verwendungsarten von in XAML definierten Ressourcen sind sicherlich Abbildungsvorschriften von Daten auf Oberflächenelementen (e.g. <DataTemplate x:Key=“ShortDescription“>) und Styles (e.g. <Style x:Key=“DescriptionHeader“>), ich fand es im Bereich der Oberflächengestaltung auch recht praktisch, beliebige Strukturen vordefinieren zu können (e.g. <StackPanel x:Key=“LongDescription“>).

Genauso nützlich ist es, globale Instanzen einmalig definieren zu können (e.g. <app:ProgramGuide x:Key=“TheGuide“ />), wobei diese sich oft (wenn die Reihenfolge der Definition es erlaubt) auch gegenseitige referenzieren können (e.g. <app:Filter x:Key=“GuideFilter“ /> und <app:ProgramGuideView x:Key=“GuideView“ GuideFilter=“{StaticResource GuideFilter}“ Source=“{Binding Source={StaticResource TheGuide}, Path=Events, IsAsync=true, Mode=OneTime}“ />).

In der Beispielanwendung werden Ressourcen auch für Zeichenketten wie Formate (e.g <system:String x:Key=“DateTimeFormat“>dd.MM.yyyy HH:mm</system:String>) verwendet, wobei allerdings meiner persönlichen Ansicht nach hier die Grauzone zum Aspekt der Lokalisierung auf die gute alte WinForms Art (.resx) berührt wird. Auch wenn WPF anderen Ideen zur allgemeinen Lokalisierung mit sich bringt, könnte es für diese Fälle (Zeichenketten, die lokalisierbar sein sollten, aber nicht direkt in der Oberfläche erscheinen) eleganter sein, auf RESX und die StaticResource Markup Erweiterung zu setzen.

Als letztes finde ich im Rahmen der Beispielanwendung erwähnenswert, dass auch Felder als XAML Ressourcen angelegt werden können (e.g. <x:Array Type=“system:DateTime“ x:Key=“TimeSelections“> und darin <system:DateTime>00:00</system:DateTime> et al).

Happy Coding

Jochen

WPF Evaluation: Filter und View

Eine Frage ist natrürlich, was (welcher Ausschnitt der gesamten Programmzeitschrift) dem Anwender wie (etwa die Sortierung) angezeigt werden soll. Für das Beispiel habe mich mich entschieden, dass die Anzeige sortiert nach dem Startzeitpunkt und gruppiert erst nach Datum und dann nach der vollen Stunde erfolgen soll. Für die Evaluation sind diese Entscheidungen auch festgelegt, produktiv muss man da natürlich freier sein. Tatsächlich ist die vorhandene Implementierung bei Anzeige der gesamten Programmzeitschrift (mit einigen Tausend Einträgen) auch zu langsam, aber das macht für das Beispiel erst einmal nichts – zudem wie gleich beschrieben oft eine Filterung aktiv sein wird.

Ich habe mich entschieden, die Art der Anzeige in einer eigene Klasse zu implementieren. Diese wird dann an die Liste via XAML angehängt (ItemsSource=“{Binding Source={StaticResource GuideView}}“) – die Anzeigeklasse ist wieder einmal eine globale Ressource. Interessant ist im Beispiel das Zusammenspiel mit der Filterbedingung.

Zur Auswahl von Teilen der Programmzeitschrift gibt es eine Filterklasse, in der die üblichen Parameter gesetzt werden können. Ich habe diese auf der untersten WPF Ebene implementiert, die sowohl dynamische Eigenschaften (DependencyProperty mit Bindungen) als auch Ereignisse (RoutedEvent) erlaubt: dem FrameworkElement. Eine Instanz der Klasse wird als globale Ressource angeboten. Dazu noch ein paar weitere Details, der Filter selbst ist trivial und nicht wirklich der Rede wert.

Die eindeutige Filterinstanz wird nun auf zweierlei Art verwendet. Zum Einen binden sich verschiedene Oberflächenelemente direkt an die relvanten Filtereigenschaften – etwa das Eingabefeld mit dem Freitextsuchfeld. Interessant ist dabei, dass bei den Bindungen (Text=“{Binding Source={StaticResource GuideFilter}, Path=TextFilter, Mode=OneWayToSource}“) alternierend OneWayToSource und TwoWay (SelectedItem=“{Binding Source={StaticResource GuideFilter}, Path=Time, Mode=TwoWay}“) verwendet wird: im Allgemeinen wäre OneWayToSource die korrekte Wahl, ich möchte aber einige (wenige) Auswahlelement direkt mit den Voreinstellungen belegen, die nur der Filter selbst kennen muss.

Zur Reaktion auf Änderungen der Filterbedingun bindet sich der CollectionSourceView an die Ereignisse, die bei Veränderungen von der Filterinstanz aufgerufen werden – die Verbindung erfolgt aus Basis der globalen Ressourcen (<app:ProgramGuideView x:Key=“GuideView“ GuideFilter=“{StaticResource GuideFilter}“ Source=“{Binding Source={StaticResource TheGuide}, Path=Events, IsAsync=true, Mode=OneTime}“ />). Die Sicht auf die Programmzeitschrift aktualisiert sich dann selbst, gefolgt von der entsprechenden Aktualisierung in der Benutzeroberfläche. Tatsächlich habe ich es nicht so richtig hinbekommen, der Sicht zu sagen, sie solle sich einfach erneuern. Daher im Code der kleine Trick mit dem NullFilterEvent und dem m_Changing Flag, die dafür sorgen, dass die Filter Eigenschaft des Views verändert wird, ohne dass dabei eine mehrfache Auswertung stattfindt – was stark auf die Laufzeit geht.

Soweit dazu

Jochen

full.jpg