Zwischenprojekt: KVMPortSwitcher

Meine Entwicklungsstrategie für private Projekte folgt meist einer Stack-Strategie: je älter die Idee, desto tiefer vergraben, ständig kommt neues Zeugs oben drauf, und in seltenen Fällen findet das jüngste Projekt direkt zur Reife. Und so geschah es mit dem jüngsten Spross meines bunten Straußes an Java-Projekten: KVMPortSwitcher. Wer nur den technischen Sermon lesen und den Code sehen will, darf direkt zum Projekt auf GitHub abbiegen.

Um was geht es? Seit einiger Zeit besitze ich einen “TESmart 16-port HDMI KVM Switch” (das exakte Modell gibt es offenbar nicht mehr, aber hier ist der Nachfolger zu finden). TESmart ist der einzige mir bekannte Hersteller, der KVM-Switches mit 8 Ports und mehr zu einigermaßen bezahlbaren Preisen anbietet und trotzdem problemlos funktioniert – meine Anforderungen damals waren “4K, HDMI, 8 Ports oder mehr, keine Spezialkabel”. Dadurch schrumpfte die Zahl der zur Auswahl stehenden Geräte nach ausführlicher Recherche auf “1”.

Nun gehört alles mit 8 Ports und mehr offenbar üblicherweise der Profi-Fraktion an, und so hat dieser Switch zusätzlich einen Ethernet-Anschluss, mit dem man ihn ins LAN integrieren kann, um ihn so über IP steuern zu können. Warum würde man das wollen? Zum einen zwecks Konfiguration des Geräts. Aber vor allem zur Steuerung des ausgewählten Ports. Denn die anderen Wege, den Port zu wechseln, sind mit verschiedenen Problemen und Nicklichkeiten verbunden, die einem ganz schön auf die Nerven gehen können.

Man kann die Knöpfe an der Front des KVM-Switches verwenden. Prinzipiell keine schlechte Idee, aber beim 16-Port-Modell braucht man dabei für die Geräte 10-16 zwei Tastendrücke. Oder sogar drei, denn wenn der Display-Timeout zugeschlagen hat, dient der erste Tastendruck gar nicht dem Umschalten, sondern dem Aktivieren. Also zwei oder drei Tastendrücke, und man muss natürlich die Hand von der Tastatur nehmen.

Wie wäre es mit der IR-Fernbedienung? Anders, aber nicht besser. Wenn man sie denn mal gefunden hat (vorsichtshalber steht nur “Remote Control” drauf, damit man sie ja nicht klar zuordnen kann), kann man zwar die Ports 2-9 durch einen Tastendruck auswählen, die Ports 1 und 10-16 hingegen nicht – was besonders bei “1” sehr dumm ist, da drückt man auf “1” und wundert sich, dass nix passiert, bis dem Gerät klar wird, dass keine Eingabe mehr erfolgt. Wer jetzt denkt, er könne durch zwei Tastendrücke “0” und “1” das Gerät überlisten, sieht sich getäuscht. auch “1” gefolgt von “OK” hilft nicht. Immerhin braucht es den “Aktivierungstastendruck” wie bei den Front-Panel-Buttons nicht.

Wie wäre es mit der eingebauten Möglichkeit, über die Tastatur den Port zu wechseln? Im Prinzip eine gute Idee, aber: es funktioniert nur mit den im Gerät hartcodierten Shortcuts, und die sind eher komisch, aber natürlich so gewählt, dass sie möglichst nicht mit anderen gängigen Tastatursteuerungen kollidieren: zwei Mal Scroll Lock (aka “Rollen”), dann 1-n. Man erkennt direkt das Problem für die 16-Port-Variante: bei Rollen-Rollen-1 gibt es die von der Fernbedienung bekannte Gedenksekunde, bis klar ist, dass man wirklich “1” meint und nicht “10” oder “13” und nur langsam tippt. Und noch ein Haken: das funktioniert natürlich nur, wenn die Tastatur im dafür vorgesehenen spezifischen USB-Port steckt, der diese Logik enthält – dieser Port ist aber nicht kompatibel mit allen Tastaturen dieser Welt, und so muss man manchmal auf den “nackten” USB-Port ausweichen. Und schon ist es Essig mit der Hotkey-Funktionalität.

Insgesamt gibt es also ausreichend Gründe, alternative Möglichkeiten zum Umschalten der Ports zu suchen. Eine davon bietet TESmart selbst an mit einem kleinen Tool, das eine IP-Verbindung aufbauen kann, dadurch den aktiven Port feststellt und dann per Mausclick das Umschalten erlaubt. Schön, aber natürlich eher keine Verbesserung zu den anderen drei Varianten. Tatsächlich dauert es doch recht lange, bis das Tool endlich den “Connect” hergestellt hat – keine Ahnung, warum. Mehrere Sekunden jedenfalls.

Nun muss man TESmart zugutehalten, dass sie das Protokoll über die IP-Schnittstelle zur Ansteuerung der Funktionalität öffentlich dokumentiert haben – leider muss man solche Dinge ja positiv vermerken, da es sich nicht um eine Selbstverständlichkeit handelt. Jedenfalls ist es denkbar einfach: IP-Verbindung herstellen, ein paar Bytes senden, fertig ist die Laube.

Ich hatte also so ein Projekt schon länger im Hinterkopf – meine Brot-und-Butter-Implementierungssprache Java schien da aber ungeeignet, weil man dort keine systemweiten Keyboard-Shortcuts beim Betriebssystem registrieren kann, und eine weitere grafische Oberfläche, wo man per Click den KVM-Switch bedienen kann, wollte ich nun auch nicht bauen. Zufällig bin ich bei meinen Streifzügen durch das Internet dann aber über eine Bibliothek namens JNativeHook gestolpert, die für alle gängigen Betriebssysteme und CPU-Architekturen native code zusammen mit etwas Java-Glue-Code zur Verfügung stellt, um solche globalen Hotkey-Listener zu implementieren. Kurz getestet, tut, also frisch ans Werk.

Der Code an sich und die UI war natürlich trivial. Kurz noch ein TrayIcon dazugeschraubt (denn für eine Anwendung, die normalerweise im Hintergrund läuft, ist es immer geschickt, noch einen Haken zur Kontrolle derselben zu haben), ausprobiert. Funktionierte – meistens. Denn es gab ein interessantes Phänomen, dass der NativeKey-Event-Dispatcher manchmal, wenn der Port umgeschaltet wurde, munter weiter denselben Event wieder und wieder feuerte. Ich bin dem noch nicht auf den Grund gegangen, aber habe einen klassischen Workaround gefunden: asynchrone Verarbeitung, der Listener löst nicht direkt den Port-Switch aus, sondern scheduled einen extra Thread, der kurz wartet und dann erst umschaltet. Das scheint das Problem zuverlässig gelöst zu haben.

Wer bis hierhin durchgehalten hat, darf jetzt zum GitHub-Projekt abbiegen. Es gibt auch ein runnable jar nebst inkludiertem jnativehook-Jar als Release 0.1.0 zum Download bei GitHub, Java 8 wird zur Ausführung benötigt. Wer also zufällig einen TESmart HDMI-KVM-Switch sein Eigen nennt und ihn in sein Heimnetz integriert (hat), kann direkt loslegen.

Auf der GitHub-Projektseite kann man auch nachlesen, was noch die TODOs sind. Konfigurierbare Port-Namen (bei 16 Ports kann man schon mal den Überblick verlieren), konfigurierbare Keyboard-Shortcuts, i18n (bis jetzt ist alles hartcodiert englisch). Und vielleicht auch noch für die old-school-Generation die Steuermöglichkeit über die serielle Schnittstelle des TESmart-KVM-Switches?

SwingHelpViewer – ein einfacher Online-Hilfe-Viewer

Seit einiger Zeit schraube ich an diversen Anwendungen auf Basis von Java Swing, die wirklich demnächst die Release-Reife erreichen sollten. Die meisten aus der Reihe “für RISC OS, aber nicht unter RISC OS lauffähig” (da Java-basiert, und es unter RISC OS keine kompetente JVM gibt). Hier kann man ein paar wenige Details zu diesen geplanten Anwendungen nachlesen.

Wie dem auch sei, solche klassischen FatClient-Anwendungen brauchen typischerweise eine Online-Hilfe. Allein um dem Benutzer mitzuteilen, welche 3rd-Party-Bibliotheken genutzt werden und unter welcher Lizenz diese stehen.

Standard unter Java ist für solche Zwecke JavaHelp, vor Urzeiten von Sun entwickelt, aber seit fast so langer Zeit auch nicht weiter gepflegt. Diverse ungefixte Bugs, unklare Lizenzsituation (alle Sourcefiles reden von GPLv2, irgendwo steht “GPLv2 with Classpath Exception”, und es gibt auch Hinweise, dass es dual lizenziert ist sowohl unter GPLv2 als auch unter CDDL), merkwürdige indexbasierte Suche die außer Englisch recht wenig versteht, unflexibel in der Integration. Aber durchaus mit coolen Features für die damalige Zeit, inklusive einer JSP-basierten Server-Variante.

Allein die Lizenzsituation bewog mich, schnell mal was Eigenes zu bauen. Mit dem typischen “wie schwer kann das schon sein” auf den Lippen begann ich während eines langweiligen Fußballspiels (es könnte der VfB Stuttgart involviert gewesen sein), schnell mal einen Hilfe-Viewer ähnlich des JavaHelp-Viewers zu bauen. Ungefähr 10 Stunden später hatte ich einen Viewer, der ein JavaHelp-HelpSet (.hs-Datei) parsen und sowohl TOC als auch Index eines solchen HelpSets erfolgreich darstellen. Es war also tatsächlich nicht so schwer, am längsten hat noch das XML-Gefrickel gedauert, weil ich mir in den Kopf gesetzt hatte, ganz ohne 3rd-Party-Dependencies auszukommen, und das DOM-Zeugs in Java SE ist halt sehr mit-der-Hand-am-Arm.

Code aufräumen, Icons malen und jetzt seit neuestem eine einfache Volltextsuche dazuzubauen hat nochmal ein paar Stunden gekostet, alles in allem schätze ich mal 3 PT an Gesamtaufwand. Swing ist wohl doch nicht so schlecht wie viele seit etwa 1999 nicht müde werden zu behaupten.

Das Ergebnis dieser Bemühungen kann man auf GitHub inspizieren. Und damit es wirklich von jedem auf welche Weise auch immer verwendet werden kann, habe ich als Lizenz die “Unlicense” ausgewählt. Ist bestimmt auch wieder inkompatibel mit irgendwas, aber es ist die freieste Lizenz, die ich gefunden habe.

Wird es für den SwingHelpViewer eine Weiterentwicklung geben? Natürlich liegen einige Erweiterungen auf der Hand (indexbasierte Suche z.B. über Apache Lucene, ein Bookmark-System, Unterstützung für weitere JavaHelp-Features wie “merged help sets” und Direkthilfe-Action und Hilfe-Cursor und so, Unterstützung für andere Hilfedaten wie CHM, HLP oder Eclipse Help, Einbindung anderer Anzeigekomponenten die mehr von HTML und CSS verstehen als JEditorPane), aber der jetzige Zustand dürfte für meine Zwecke wohl reichen.

Wer die Herausforderung sucht, könnte z.B. mal schnell eine Java 1.2-kompatible Version des Codes bauen. Im Moment läuft alles ab Java 7, wenn man den Diamond Operator rauswirft müsste Java 5 gehen, wenn man die Generics rauswirft Java 1.4, und wenn man das XML-Parsing anders löst (wer erinnert sich noch an crimson.jar…), dürfte man bei Java 1.2 angekommen sein. Der Code ist sehr “old-school”, und Swing ist ja im Prinzip seit Java 1.2 unverändert.

Was GitHub angeht, ist SwingHelpViewer mein erstes dort publiziertes Projekt. Wenn ich die jetzige Geschwindigkeit beibehalte, werden meine über die Jahre entstandenen programmiertechnischen Ergüsse spätestens bis 2050 komplett auf GitHub gelandet sein.

Apple setzt auf ARM

Auf der WWDC (die jährliche Apple Entwickler-Konferenz) wurde in der Keynote wie schon seit Längerem allgemein erwartet (erste Gerüchte etwa seit 2011) verkündet, dass zukünftige Macs als CPU ein selbstentwickeltes SoC auf ARM-Basis enthalten werden. Höchstwahrscheinlich ein performanceoptimierter Abkömmling der A12Z-und-Nachfolger-Reihe aus dem iPad Pro.

Viel wurde schon geschrieben über Apples erneuten Pferdewechsel bei der CPU für seine Desktoprechnerlinien – MOS 6502 im Apple I und II, Motorola 68xxx im Mac der ersten Generation, Motorola/IBM PowerPC in den PowerMacs ab Mitte der 90er, und schließlich Intel x86/x64 seit Mitte der Nullerjahre. Und jetzt also ARM. Für alle historisch interessierten schließt sich damit der Kreis, der mit der Ausgründung von ARM Ltd. aus Acorn als Joint Venture mit Acorn und VLSI Anfang der 90er begann, und Apple den ARM610 als CPU im Newton PDA einsetzte – damals mit mageren 20 MHz getaktet, der finale Newton hatte dann einen schnellen StrongARM intus.

Meine Einlassung hier soll auch nicht als Expertenmeinung im MacOS-Universum eingestuft werden – ich habe wenig Plan von und Einblick in MacOS und der derzeit dort so eingesetzten Software. Der Presse entnehme ich, dass im Prinzip ausschließlich mit den MacBooks der Gewinn eingefahren wird und der Rest eher so nebenher läuft. Das traditionelle Profilager der Kreativen, von DTP über Illustrationen bis Bitmap-Bearbeitung scheint im großen Spiel der Dinge inzwischen eher nachrangig. Photoshop, Final Cut Pro, InDesign, Illustrator, QuarkXPress, Premiere Pro, Finale…sowieso allesamt auch unter Windows erhältlich und wohl nicht mehr der entscheidende Faktor bei der Useranzahl und damit auch dem Umsatz. Die Lifestyle-Kundschaft, die einfach alles aus dem Apple-Universum kauft was nicht bei drei auf dem Baum ist – von MacBook über iMac, Apple Watch, HomeKit, iPhone bis iPad und Apple TV – ist der Umsatztreiber.

Was treibt also Apple zu diesem Wechsel, der ja nicht ohne Risiko ist? Ich kann da einige Gründe ausmachen. Wie man die jeweils gewichtet, liegt im Auge des Betrachters. Wir werden erst hinterher schlauer sein.

Zunächst ganz schnöde: der Wechsel spart vermutlich einen Haufen Geld. Intel-CPUs sind ja doch eher teuer, und Apple musste immer Chipsätze und Zusatzchips drumrum entwickeln oder zukaufen. Die ARM-Entwicklung erfolgt ja sowieso aufgrund von iPhone und iPad, warum dann nicht etwas nach oben skalieren. In Zeiten von “viele Cores helfen viel” ist ein ARM-Core da sicher keine unbedingt schlechte Basis. Es heißt ja, dass die letzte Inkarnation des iPad Pro CPU- und GPU-technisch mit den mobilen Core i-CPUs locker mithalten kann.

Wichtig erscheint mir auch, dass Intel in den letzten Jahren seinen ehemaligen Vorsprung bei der Prozesstechnik eingebüßt hat. Die Auftragsfertiger wie TSMC oder Samsung haben Intel mindestens eingeholt, eher überholt. Angeblich hat TSMC den 3nm-FinFET-Prozess 2022 produktionsreif. Allerdings ist das nicht ohne Risiko, denn andere große Auftragsfertiger haben beim großen Technologierennen schon abreißen lassen müssen – Globalfoundries dürfte der bekannteste Fall sein, früher ganz vorne dabei als Ausgründung von AMD, aber inzwischen nur noch Massenfertiger ohne Spitzenfertigungstechnologie. Jedenfalls ist die Verfügbarkeit von Auftragsfertigern mit topaktueller Prozesstechnologie eine Voraussetzung für den Erfolg von “fabless CPU designers” wie ARM, Qualcomm, Apple oder AMD. Dass dieses Pendel mal wieder in Richtung Intel zurückschwingt ist jetzt nicht völlig ausgeschlossen.

Viel wird über die Vereinheitlichung der Plattformen iOS und macOS geschrieben. Aus meiner Sicht ist das ein schwaches Argument, denn wo genau ist denn hier die zugrundeliegende CPU-Architektur entscheidend? Entscheidend ist doch hier vielmehr, ob sich die Benutzeroberflächen angleichen und das Software-Ökosystem aus Bibliotheken und Frameworks möglichst identisch ist. Ob dann am Ende der Compiler x86-Code oder ARM-Code draus macht, ist doch weitgehend irrelevant. Vielleicht werden die allermeisten Programme bis in 10 Jahren sowieso alle im Browser laufen und in JavaScript und WebAssembly geschrieben sein, dann haben sich solche Details eh erübrigt.

Ein aus meiner Sicht wichtigeres Argument ist, dass sich Apple der einfachen Vergleichbarkeit – besonders was den Preis angeht – seiner Hardwareplattform entzieht. Heutzutage ist komplett transparent, dass Apple gegenüber der x86-Welt für seine MacBooks einen nicht unerheblichen Aufpreis nimmt, der sich nicht in erhöhter CPU- oder GPU-Leistung niederschlägt. Der Wechsel zu ARM nützt hier zweifach: zum einen kann Apple sehr einfach Coprozessoren aller Art im SoC unterbringen, die speziell auf die neueste Modeerscheinung der IT hingedengelt wurde – sei es Spracherkennung, Bildverarbeitung, Video-Encoding oder irgendwas-mit-KI. Zum anderen kann Apple zukünftige Herausforderungen durch einen cleveren Mix aus Software und Hardware erschlagen, ohne dass jemand genau abgrenzen kann, ob jetzt die geniale Programmierung oder die geniale Hardware letztlich verantwortlich ist.

Dadurch, dass Apple von ARM eine Architektur-Lizenz hat, also völlig eigenständige Cores entwickelt und nicht auf die fertigen Cortex-Axx- oder Neoverse-Cores zurückgreifen muss, können die CPUs für MacOS und den muss-nicht-unbedingt-allzu-stromsparend-sein-Anwendungsfall maßgeschneidert werden. Das ist bei iOS ja auch passiert – während die Android-Fraktion eher auf viele Core gesetzt hat, hat Apple eher die Single-Core-Leistung in den Vordergrund gestellt. Welche Reserven die Architektur hat, wenn man die TDP in Richtung Intel Core i9 erhöhen kann, bleibt abzuwarten. Der A12Z mit 8 Cores in big.LITTLE-Konfiguration, je 128 KiB 1st level instruction und data cache und 8 MiB 2nd level cache ist ja noch eher auf Sparsamkeit und lüfterloses Design ausgelegt. Bechmarks sahen den A12Z ja ungefähr auf Augenhöhe eines Mobile-i5 mit integrierter Intel-Grafik. Technisch ist das der Stand von 2018, da der A12Z nur ein leicht erweiterter A12X ist. Mal sehen, mit was Apple um die Ecke kommt, wenn es ernst wird mit dem ersten MacBook-on-ARM.

Apple hat in der Vergangenheit durch das Backen ganz eigener Brötchen ja große Erfolge gefeiert und ein immer geschlosseneres Ökosystem geschaffen. iOS, Objective-C, Swift, Metal, Apple Store, iTunes, Apple TV, HomeKit – solange die Nutzeranzahl eine kritische Masse überschreitet und das Ökosystem technisch und aus Anwendersicht plausibel bleibt, ist es eine clevere Art von “Vendor Lock-In”.

Ein Risiko der Apple-Strategie steckt natürlich in dem, was in der Industrie unter “zu große Fertigungstiefe” läuft. Apple muss alles selbst entwickeln, vom Betriebssystem (iOS und MacOS) über CPU, GPU und Zusatzprozessoren bis hin zu Compilern (Objective-C, Swift) und natürlich der Hardware selbst. Das birgt eine irre Komplexität und hohen Aufwand in sich, um in jedem einzelnen Bereich Spitze oder zumindest nahe dran zu sein. Firmen, die das früher mal versucht haben, waren dauerhaft nicht erfolgreich (Sun, SGI, Acorn, mit Abstrichen auch die klassischen Heimcomputerhersteller wie Commodore und Atari).

Eine gewisse Ironie steckt im Zeitpunkt des jetzt angekündigten Wechsels. Gerade hat – dank AMD – die x86-Welt wieder deutlich an Schwung gewonnen nach fast einem Jahrzehnt gefühlter Stagnation. Ein wenig vergleichbar mit dem damaligen Wechsel von PowerPC zu Intel, als kurze Zeit später IBM ein wahres Feuerwerk an High-Performance-PowerPCs abbrannte. Aber wie wird es sich längerfristig entwickeln? Apple hat auf jeden Fall genügend finanzielle Ressourcen, um seine ARM-SoCs auf Augenhöhe mit den x86-CPUs von Intel und AMD weiterzuentwickeln. Aber das alleine ist keine Garantie, wie man gerade an Intel sieht, die trotz gigantischer finanzieller Ressourcen eher alt gegen AMD aussehen. Kopf schlägt Kapital, zumindest manchmal – oder wie jeder Fußballfan weiß: “Geld schießt keine Tore”, und trotzdem heißt der Deutsche Meister auch 2020 wieder Bayern München. Und andererseits ist Freiburg auf einem einstelligen Tabellenplatz in der Bundesliga, während der Hamburger SV, der VfB Stuttgart und Hannover 96 in der zweiten Liga spielen. Es bleibt also spannend.

Stümpern mit Niveau

Ab und zu – die Frequenz ist uneinheitlich, die Rahmenbedingungen unbekannt – neige ich dazu, irgendein IT-Thema mal genauer zu betrachten und ein paar Experimente durchzuführen. Quasi um immer wieder das “innere Komplexitätsgefühl” neu zu justieren. Ich stelle eine gewisse Häufung beim Thema “Protokolle” fest, vielleicht die masochistische Ader die mich schon zur Implementierung einer CD-/DVD-/BluRay-Brenner-Software gebracht hat. Ziel ist immer, bei einer Sache von Quasi-Null-Wissen auf mindestens 3 zusätzliche Seiten im persönlichen Handbuch des nutzlosen Wissens zu kommen. Quasi qualifiziertes Halbwissen, das jede Fachdiskussion unter einer Stunde locker überlebt.

Diesmal das Thema: IPP, das “Internet Printing Protocol”, das im Rahmen einer Diskussion im Kontext meines Lieblingsbetriebssystems RISC OS eher zufällig aufgekommen ist. Früher dachte ich, IPP sei quasi nur “Druckdatenstrom per HTTP an den Drucker übermitteln”. Sowas wie “JetDirect über HTTP”. Oh Mann, lag ich falsch. Oder besser: es ist eine sehr simplifizierte Beschreibung der Wirklichkeit, und qualifizierte mich damit als “Quasi-Null-Wissenden”.

In Wahrheit hat IPP interessantes Potenzial für die RISC OS-Welt, nämlich “driverless printing”. Man kann per standardisierten Requests den Drucker zu seinen Eigenschaften befragen (Papierzufuhroptionen, Nachbearbeitungsoptionen, Duplex oder nicht und wenn ja wie), zu seinem Status (Tonerstand/Tintenstand, Papierstau etc.) und es gibt ein plattformübergreifendes Rasterformat (“PWG Raster Format” – PWG ist die “Printer Working Group”, die hinter IPP steht), das zum Druck verwendet wird. Zusätzlich vermelden netzwerkverbundene Drucker ihre Anwesenheit über das Bonjour-Protokoll, aber auch direkt verbundene USB-Drucker werden unterstützt. Das Gesamtkunstwerk nennt sich IPP Everywhere. Also die Lösung aller Probleme der Art “klar gibt es da diesen Drucker XYZ, aber für Betriebssystem ABC gibt es leider keine Treiber” – heute behilft man sich da (zumindest im RISC OS-Markt) mit der oberen Preisklasse der PostScript- und PDF-fähigen Drucker, muss aber immer noch tricksen um mit speziellen Druckerfeatures arbeiten zu können.

Die IT wäre nicht die IT, wenn nicht zwei konkurrierende andere Lösungen gleichzeitig um die Gunst des Anwenders (interessiert den das eigentlich?) buhlen würden: AirPrint (von Apples Gnaden) und Wi-Fi Direct Print. So weit, so ärgerlich. Zurück zu IPP. Dessen Charme ist die Verfügbarkeit eines gut dokumentierten Standards, bei den beiden Konkurrenten sieht es da nicht ganz so gut aus, dafür waren diese früher am Markt und sind (deshalb?) deutlich weiter verbreitet – IPP Everywhere wird heute eigentlich nur von einer Reihe von HP-Druckern unterstützt.

Wie auch immer, ich fasste ein Ziel ins Auge: mit meinem IPP-fähigen (aber natürlich nicht IPP Everywhere-kompatiblen, weil Baujahr 2011) Oki C530 ein PDF zu drucken, indem über IPP der PDF-Datenstrom an den Drucker geschickt wird.

Wie anfangen? Der IPP-Guide erzählt von 40 Spezifikationen mit insgesamt fast 2000 Seiten, das schien jetzt etwas ambitioniert. Aber es gibt JIPP, eine Java-Implementierung von IPP von HP, verfügbar auf GitHub. Unter der guten MIT-Lizenz. Da waren Beispiele dabei. Wie schwer kann es also sein?

Erste Hürde: das Github-Projekt hostet nur Source-Releases. Kein Problem, man kann ja selber bauen. Stellt sich raus: ist Kotlin-Code, gebaut mit Gradle. Hm. Bin ich jetzt für beide Dinge nicht so der Experte, vielleicht ein Experiment für ein anderes Mal. Google führt mich zu einer sinnvollen Paketierung des Codes inklusive aller seiner Abhängigkeiten (wie der Kotlin-Runtime – auch nicht gerade schmal das Dingens). Also schnell ein IDE-Projekt aufgesetzt und los geht’s. Ich arbeite mit Version 0.6.16 – nur falls jemand ein paar Jahre später über diesen Artikel stolpert und bis hierher durchgehalten hat.

Das jprint-Beispiel (inzwischen übrigens – ohne meinen Input und erst vor wenigen Stunden! – signifikant verbessert, an einigen der Stolperfallen) erst mal als Basis genommen. Ein PDF an die bekannte IPP-URL des Druckers geschickt. Eine dubiose Exception war das Ergebnis (aus dem HTTP-OutputStream: java.io.IOException: Error writing request body to server) – wies darauf hin, das irgendwas mit der URL nicht stimmte. OK. Ein paar Varianten durchprobiert (offenbar gibt es typische Implementierungen der Form ipp://irgendneip/ipp und ipp://irgendneip/ipp/lp und http://irgendeineip/ipp und http://irgendeineip:631/ipp – an dieser Stelle die Nebenerkenntnis, dass IPP schlicht HTTP-mit-631-als-Default-Port ist). Manchmal den gleichen Fehler, manchmal einen anderen Fehler (java.net.SocketException: Software caused connection abort: recv failed). Dubios. Weiter rumprobiert. Stellt sich raus: auch bei derselben URL kommt manchmal die eine Exception, manchmal die andere. Aha. Dann doch kein Connection-/URL-Problem? Mal den Code genauer anschauen. Als Transportmechanismus wird eine Klasse namens “IppPacket” verwendet. Da gibt es einen alternativen Konstruktor, der auch eine “ippVersion” (ein int wie es sich gehört) entgegen nimmt. Könnte es sein, dass mein Drucker (aus der Zeit von IPP v1.1) mit dem Default von JIPP (IPP v2.x) einfach nicht klarkommt? Mehrfaches Ausführen des Codes mit stets derselben URL führt tatsächlich manchmal zu einer Exception-losen Verarbeitung des Kommandos mit der Fehler-Rückmeldung “server-error-version-not-supported”, was den Verdacht erhärtet.

Etwas später ist klar: dummerweise erlaubt der Konstruktor von IppPacket, der eine explizite Versionsangabe erlaubt, nicht dieselben Typen an Restparametern, insbesondere nicht den “Operation”-Enum, sondern auch nur einen int. OK, ein paar RFCs zum IPP gelesen und herausgefunden, dass das Kommando getPrinterAttributes 0x0B ist und printJob 0x02. Minuten später sehe ich, dass der Enum innen drin die ints eh auch definiert hat. Grmpf. Ist bestimmt so ein Kotlin-Automatismus. Bleibt die Frage: wie spezifiziert man jetzt in einem int eigentlich “1.1” als Version? Na per 8+8 Bit natürlich. Also 0x0101 für meine Zwecke. Prima. Erstmal getPrinterAttributes probieren statt gleich das PDF zu schicken. Das Kommando wird jetzt zuverlässig verschickt, aber JIPP kann das Resultat nicht unfallfrei parsen – ob das eine Schwäche von JIPP ist oder eine Abweichung von der Spezifikation seitens meines Druckers ist noch ungeklärt, aber Gott sei Dank hat der JIPP-Programmierer bei solchen Parse-Fehlern daran gedacht, die Rohdaten des Replys, der nicht parsebar waren, herauszudumpen. Also konnte ich einfach inspizieren, was mein Drucker so als Fähigkeiten zurückmeldet.

Nachdem das Kommando-Schicken nun völlig problemlos funktionierte, machte ich mich an die eigentliche Aufgabe, den Druck eines PDFs – der Oki unterstützt sowohl direktes Drucken per PostScript als auch per PDF, und PDFs finden sich auf der Platte entschieden leichter. Ein einseitiges Dokument identifiziert und per offiziellem PDF-MIME-Type “application/pdf” zum Drucker geschickt. Kommt zurück: “client-error-attributes-or-values-not-supported”. Eine sprechende Fehlermeldung! Sehr schön. Inspektion der bei getPrinterAttributes zurückgemeldeten Fähigkeiten zeigt: “application/pdf” wird auch gar nicht akzeptiert, nur “application/octet-stream”, “application/vnd.hp-PCL” oder “application/postscript”. Einfach mal “application/octet-stream” geraten, und siehe da: es wird gedruckt.

Na das war ja einfach.

Zu klärende offene Fragen: 1. Nützt mir das jetzt was für IPP unter RISC OS? 2. Wie erzeuge ich möglichst einfach das PWG-Raster-Format aus einem beliebigen Quellformat? 3. Warum drucke ich nicht einfach PDF über einen CUPS-Druckerserver, der ja auch IPP out-of-the-box kann?

Antworten: 1. Noch nicht. 2. Sieht nicht so schwierig aus, auch keine ultrakomplexe Kompression, sondern simples PackedBits-Format und anständig dokumentiert. 2a. Aber auch JPEG wird als Format im Standard zwingend vorausgesetzt – noch einfacher! 3. Weil das ja jeder kann.

Interessanter Beifang: AppImage als Paketiervariante für Linux-Anwendungen. Spannend, kannte ich noch nicht.

Bits frickeln mit Java

Gerade bin ich dabei – zum besseren Kennenlernen von Filecore-basierten Dateisystemen (man muss den Feind kennen) – in Java ein kleines Tool zu entwickeln, das Disc-Images im Filecore-Format versteht und Dateien und Verzeichnisse daraus extrahieren kann. Nur lesend, um weitere Komplexitäten erst mal zu vermeiden.

Etwas Hintergrund: Filecore ist das native Dateisystem unter RISC OS. Oft wird es auch als “ADFS” bezeichnet, weil das “Advanced Disc Filing System” quasi die erste Implementierung von Filecore war (damals, Floppy-Zeit, zur Archimedes-Ära 800 KiB auf einer 3,5″-DD-Diskette), bevor es abstrahiert und generalisiert als Basis für Disketten- und Festplattenformate in RISC OS Einzug hielt. Es gab über die Jahre reichlich Varianten, um die diversen Einschränkungen und Limits in den besser nutzbaren Bereich zu schieben – das E-Format ist das Übliche für DD-Disketten (800 KiB) und man findet es heute in den Weiten des Internets als .adf-Disc-Images der klassischen Archimedes-Software. Später kam das F-Format für die HD-Floppies (1600 KiB). Schließlich wurde mit RISC OS 4 das E+/F+-Format eingeführt (“Big Map”), um die lächerlich niedrige Grenze solcher Dinge wie “maximale Anzahl von Einträgen in einem Verzeichnis” auf ein halbwegs erträgliches Niveau zu heben.

Wie auch immer – beim Hantieren mit Emulatoren und natürlich dem MIST(er) hat man häufig mit diesen .adf- (Floppy-Images) und .hdf- (Harddisc-Images) Dateien zu tun. Oftmals will man “nur kurz” einen Blick reinwerfen und dazu nicht gleich den Emulator hochfahren. Zumal die Emulatoren auch nicht alle so richtig nutzerfreundlich sind was das “Mounten” des Images angeht.

Also: ein Tool muss her. Systemunabhängig und natürlich mit anständigem UI. Also Java. Das Problem: Filecore wurde von echten Bitfuchsern entwickelt. Da wimmelt es nur so von Bitleisten, unsigned values mit allem zwischen 8 und 64 bit und sonstigem, was unter Java nicht so richtig “nativ” unterstützt wird. Übrigens gibt es Spezialisten, die es auch noch gut finden, dass Java keine “unsigned types” hat – für mich ist dieser Artikel ein Beispiel dafür, wie eine limitierte Erfahrung auf nur wenige Programmiersprachen den Blick aufs wesentliche vernebeln kann, denn die allermeisten der genannten Probleme sind nur inhärent im Java- und C-Typsystem, aber in vernünftigen Sprachen wie Ada elegant gelöst. Dumm, dass die Java-Erfinder vermutlich einen genauso eingeschränkten Blickwinkel hatten – C, C++, Smalltalk, Ende der Geschichte. Aber ich schweife ab.

Jedenfalls habe ich nach Bibliotheken gesucht, die unter Java die Bitfrickelei und unsigned types im Handling etwas angenehmer machen. Leider bin ich bis auf Lukas Eders jOOU-Bibliothek auf nix gescheites gestoßen. Klar, im Apache-Commons-Universum gibt es ein paar Dinge, in Guava ebenso, und sogar Oracle hat das Licht gesehen und ein paar nützliche Dinge in Java 8 nachgerüstet. Also: selbst ist der Mann. “Not invented here” ist schließlich eine der grundsätzlichen Triebfedern der IT.

Es sei denn, jemand hat einen Hinweis auf eine vernünftige, umfassende Bibliothek um meine Bedürfnisse zu erfüllen. Unter ebenso vernünftiger Open-Source-Lizenz natürlich. UAwg! Nebenbei: die eigentliche Implementierung ist nun nicht das große Problem, das Finden geeigneter Doku und fehlerarme Interpretation derselben nebst Erkennen gewünschter und unerwünschter Abweichungen davon in der Praxis hingegen schon. Hat man das Problem erst mal in einer Sprache geknackt, sollte eine Portierung in andere Sprachen kein großes Problem sein. Es wäre eine interessante Fallstudie, den Ada-Code neben dem Java-Code zu sehen.

Und falls jemand ein anständiges (nicht jedoch komplexes!) Dateisystem kennt mit einer simplen Implementierung in einer freien Lizenz – mail me. Filecore hat einen Nachfolger schon seit etwa 30 Jahren verdient.

Wo sind die guten E-Mail-Clients?

Im Moment bin ich auf der Suche nach einem anständigen E-Mail-Client unter Windows. Ich bin mit Thunderbird noch nie warm geworden und halte ihn für überladen, instabil, unintuitiv und unzuverlässig. Outlook 2013 kostet mich gerade den letzten Nerv beim Support eines weitgehend unerfahrenen Computernutzers. Quasi unbedienbar, dazu ein Ressourcenfresser sondergleichen. Wenn man eine Einstellung sucht, vergeht mal gern eine Stunde. Die Suchfunktion kann sich nicht entscheiden, ob sie was findet oder nicht – und diese Entscheidung dauert lang.

Und dann stößt man beim googeln auf Beiträge wie diesen – erster Satz: “Microsofts Outlook gilt als das beste E-Mail-Programm.” Äh – bei wem? Bei denen, die nur Lotus Notes (heißt jetzt IBM Notes, sieht aber kein Stück besser aus) als Alternative kennen? Und dann werden dort doch tatsächlich Windows Live Mail und Windows Mail als Alternative genannt. Und natürlich Thunderbird. Ansonsten: nix. Wenn man schon keinen Bock auf Recherche hat, sollte man sich doch solche Artikel gleich sparen.

Jetzt könnte man sagen – tja, was liest Du auch IT-Artikel in der WELT? Ich Dummerchen. Mal bei den Experten von CHIP stattdessen nachlesen. Großartig, diese Top 5. Wenigstens bei heise Downloads gibt es in der E-Mail-Rubrik ein paar Kandidaten.

Aber was sind denn nun die Alternativen? Pegasus Mail, das ich schon unter Windows 3.11 nicht leiden mochte? Opera Mail? Foxmail? Mailbird? eM Client, der in der freien Variante ganze zwei E-Mail-Accounts verwalten kann? Columba – immerhin in Java programmiert und Open Source, d.h. ich könnte realistischerweise eigene Anpassungen vornehmen – dessen letztes Release aus 2007 stammt? Ich ertappe mich kurz beim Gedanken, mutt oder elm unter Cygwin zu installieren. Wenn schon Retro, dann richtig.

Oder was anderes Radikales – mein aus RISC OS-Zeiten liebgewonnenes Messenger Pro in der Windows-Variante kaufen? Hatte ich schon mal in 2002, als Mark Sawle intellegit gründete und Gemini als Messenger Pro-Portierung auf Windows veröffentlichte. Bin ich unter Windows nie mit warm geworden, warum weiß ich eigentlich nicht. Inzwischen ist R-Comp auch der Vertrieb für die Windows-Version, und damit ist es traditionell fast unmöglich, Näheres über die Software herauszufinden, ohne direkt Kontakt aufzunehmen oder die Software einfach zu kaufen. Einfach kaufen? Tja, die R-Comp-Shopseite ist legendär…man kommt über den “Order now!”-Knopf auf eine selten hässliche Zwischenseite, wo einem erklärt wird, dass man doch besser die !Shop-Applikation verwenden soll. Gilt natürlich nur für RISC OS, und der arme Windows-Nutzer clickt vor lauter Verwirrung auf den “secure ordering site”-Link. Ist man clever genug, findet man hier raus, dass es offenbar eine “basic”-Version und eine “full”-Version gibt. Was mag wohl der Unterschied zwischen beiden sein? Auch konsequent: Preise nur in UKP.

Immerhin: für drei Screenshots und ein paar warme Worte hat es gereicht. Liebe Freunde von der Insel: das wird dieser Software (höchstwahrscheinlich) nicht gerecht. Der arme Mark. Nur wer die Original-Intellegit-Seite kennt, kann das Handbuch studieren oder eine etwas ausführlichere Featurebeschreibung lesen. Man kann auch eine Trial-Version herunterl…nein, man kann nur seine E-Mail-Adresse in ein Formularfeld eingeben und eine Trial-Version anfordern. Die 90er feiern ihr Revival.

Wer den ultimativen E-Mail-Client für Windows kennt, immer her mit den Infos. Am besten per E-Mail.

Beknackte Oberflächen – heute: WinZip

Nein, es soll nicht darum gehen, dass der einzig wahre Weg, Archive zu behandeln, die Idee des “Image Filing System” unter RISC OS ist, und nach wie vor SparkFS von David Pilling die ultimative Implementierung dieser Idee ist. Warum unter Windows bis heute nichts annähernd vergleichbares existiert, ist eines der großen Mysterien der Weltgeschichte. Naja, dort hält man ja teilweise auch den Explorer noch für eine gute Idee.

Also, was nervt mich heute darüber hinaus an WinZip? Das unglaublich schlechte Fehlerhandling. Ich archiviere ein Verzeichnis mit ein paar tausend Dateien. Am Ende des Vorgangs informiert mich WinZip mit folgender alarmierender Meldung: “Es sind Fehler aufgetreten. Möchten Sie die WinZip-Protokolldatei aufrufen?” Fehler? Natürlich will man wissen, was schiefgegangen ist. Also die Protokolldatei öffnen (keine Ahnung, welcher Schwachspieler hier “aufrufen” übersetzt hat). Aber was bekommt man zu sehen? Nicht etwa eine Liste der aufgetretenen Fehler. Nein, eine Liste aller Vorgänge. Wie das Hinzufügen einer Datei zum Archiv. Und wie findet man jetzt die Fehler? Leider gibt es überhaupt keinen Hinweis, durch welchen Text so ein Fehler benannt werden könnte. Doch es kommt noch besser: oft sind gar keine Fehler im Protokoll zu finden, sondern lediglich Warnungen.

Fassen wir zusammen: Irreführende Fehlermeldung, gut versteckte Informationen – ein würdiger Kandidat für den Preis der “Beknackten Oberfläche”. Ergonomiewertung: 0%.

In meinem Falle ist der Grund für Warnungen übrigens meistens, das Dateien mit Datestamps früher als dem 1.1.1980 (das früheste Datum, das im ZIP-Format darstellbar ist) archiviert werden. Da fragt man sich doch direkt, was sich Phil Katz damals gedacht hat. Leider können wir ihn nicht mehr fragen.

Artikelserie vom MiST-Meister in der c’t

Das MiST-Mastermind Till Harbaum hat in der aktuellen, morgen am Kiosk erscheinenden c’t (Ausgabe 21/2015) den ersten Teil einer bisher auf (mindestens?) drei Teile geplanten Artikelserie publiziert. Darin geht es um die Basics rund um die FPGA-Programmierung, und natürlich dient das MiST-Board als Basis für diese Experimente.

Wer schon immer wissen wollte, wie das mit der “Magic” der MiST-Cores so funktioniert, könnte dümmeres tun, als sich die neueste c’t zu holen. Auch wenn das einzige Ergebnis des ersten Teils ist, die gelbe LED des MiST-Boards blinken zu lassen.

Für den zweiten Teil der Serie ist ein Pong-Klon angekündigt, sprich man erfährt wie die Videoausgabe funktioniert und wie man auf Eingaben des Benutzers reagiert. Im dritten Teil geht es dann ans Eingemachte: eine Z80-Implementierung nebst Speicher und Videocontroller kommen zum Einsatz – als alter Z80-Hase freue ich mich darauf besonders.

Neben der bloßen Verwendung vorgefertigter Cores wird dem MiST-Projekt also eine weitere, interessante Facette hinzugefügt.

Beknackte Oberflächen – heute: Outlook 2010 EMail-Export

Ich fürchte, die heute begonnene Serie “Beknackte Oberflächen” könnte ein Dauerbrenner werden. Es gibt weniges, was mich so nervt wie beknackte, unintuitive Benutzungsoberflächen. Es nervt deutlich mehr als hässliche, aber wenigstens funktionale Oberflächen.

Microsoft musste ja viel Kritik einstecken für die Einführung des “Ribbon”-Konzepts. Und das völlig zu Recht. Heute noch frage ich mich, was denn der große Vorteil dieses Konzepts sein soll, und warum es nicht wenigstens möglich war, beide Konzepte parallel zu integrieren – denn letztlich wird ja auch jede Ribbon-Aktion entweder direkt ausgeführt (so wie bei der guten alten Toolbar) oder öffnet irgendwann denselben schäbigen Dialog wie früher.

Es geht ja das Gerücht, dass Microsoft Legionen an UI-Experten beschäftigt und ständig Versuchspersonen befragt zur Benutzbarkeit ihrer Oberflächen. Keine Ahnung, wo diese Experten waren, als ein Programmierer die Aufgabe bekam, in Outlook 2010 die Funktionalität “EMail exportieren” einzubauen.

Die Ausgangssituation: ich hatte diverse zu exportierende EMails in einer Folder-Struktur gesammelt und wollte nun diesen Folder exportieren und war schon gespannt, welche Formate mir wohl Outlook anbieten würde – Microsoft ist ja auch bekannt dafür, Industriestandards – wenn sie nicht von Microsoft selbst erfunden wurden – entweder nicht oder unvollständig oder fehlerhaft zu unterstützen.

Es stellte sich aber heraus, dass das Export-Format gar nicht das Problem ist, denn die Frage war zunächst: wie funktioniert der Export denn überhaupt? Intuitiv wäre gewesen, den Export über das Kontextmenü erreichbar zu machen – aber da geht nur, über “Eigenschaften” über den Reiter “AutoArchivierung” zu archivieren – aber ich wollte ja jetzt exportieren und nicht irgendwann archivieren. Vielleicht direktes Drag&Drop des Folders ins Dateisystem? Nein, da empfängt mich das Verbotsschild. Also mal im “Datei”-Ribbon nachgeschaut, ob es da “Export” oder “Speichern” oder sowas gibt. Gibt es nicht. Jetzt war ich doch einigermaßen ratlos und bin die anderen Ribbons durchgegangen. Nix zu sehen. Die Symbolleiste für den Schnellzugriff inspiziert. Geschaut, ob es dort in den “Weiteren Befehlen” vielleicht irgendeine Export-Aktion gibt. Wieder nix.

OK, dann mal in den “Optionen” nachschauen, ob man dort irgendwo was aktivieren kann. Dann die Überraschung: Unter “Erweitert” gibt es tatsächlich einen Bereich “Exportieren” nebst zugehörigem Button. Drückt man diesen, gibt es noch eine Überraschung: ein Dialog öffnet sich, der eine Auswahl von 9 Aktionen anbietet. 9 Export-Aktionen? Nein, natürlich nicht. 7 davon sind Import-Aktionen. Ah ja. Immerhin: die anderen Dinge unter “Optionen -> Erweitert” scheinen wirklich Optionen zu sein und keine gut versteckte Funktionalität. Es ist also noch nicht alles verloren.

XYplorer – ein Dateimanager für Windows

Die meiste Zeit benutze ich Rechner, die unter Windows laufen. Momentan Windows 7 in der Mehrzahl der Fälle. Ganz freiwillig ist das nicht. Am liebsten würde ich RISC OS nutzen, aber das hat inzwischen nur noch wenig Software verfügbar, die ich für die tägliche Arbeit brauche – Java, eine IDE, ein Browser, alles Mangelware unter RISC OS. Linux nutze ich nur für Spezialaufgaben (aktuell ps3mediaserver, CVS-Server, git-Server, NFS-Server).

Egal welches Betriebssystem man nutzt – eine zentrale Aufgabe ist immer die Navigation im und die Organisation des Dateisystems. Erstaunlich, dass Windows dort seit Version 3.0 mit ziemlich schlechter Software ausgerüstet ist. Der Dateimanager machte den Anfang, später dann der Explorer. Bis heute nicht gerade die Spitze was Leistungsfähigkeit und Ergonomie angeht. Die Änderungen zwischen XP und 7 sind auch eher Verschlimmbesserungen.

Ich habe diverse “Commander-ähnliche” Dateimanager ausprobiert, vom TotalCommander bis zum muCommander. Ich konnte mich nie daran gewöhnen. Eventuell ist das meiner RISC OS-Vergangenheit geschuldet – den RISC OS-Filer halte ich bis heute für das ergonomischste Werkzeug für Dateisystemoperationen. Der Filer ist von derartig eleganter Schlichtheit, dass man den Erfindern täglich auf Knien huldigen will. Unter Linux gibt es den ROX-Filer, entwickelt von einem ehemaligen RISC OS-Benutzer – trotzdem fühlt er sich nicht wie das Original an. Komisch, soll aber nicht das Thema sein.

Letztlich habe ich unter Windows immer mit dem normalen Explorer gearbeitet, in Ermangelung an (mir bekannten) Alternativen. Die Wende kam heute: ich las mal wieder einen der berühmten “die x wichtigsten Freeware-Tools”-Artikel, diesmal in der Geschmacksrichtung “The Register”. Wie so oft waren die Kommentare interessanter als der Artikel, und einer der Kommentatoren nannte ein Tool namens XYplorer als unverzichtbares Werkzeug. Heruntergeladen, auf die Platte extrahiert (ja, es gibt eine “mobile”-Version, die nicht installiert werden muss), gestartet – und sofort gesehen, dass dieses Tool genau das richtige für mich ist.

Highlight-Features aus meiner Sicht – neben der Basisidee der multiplen Tabs – sind der Mini Tree und die “Mouse Down Blow Up”-Funktion. Das lässt sich mit Worten ganz schwer beschreiben, das muss man selbst ausprobieren, oder hier nachlesen. Auch die Such- und Filterfunktionen sehen sehr vielversprechend aus.

Schwächen? Die Internationalisierung scheint nicht vollständig, die deutschen Texte sind immer mal wieder von englischen Einsprengseln unterbrochen, vor allem in den Menüs.

Also: die kostenlose Version herunterladen und ausgiebig testen. Bin gespannt, wie lange meine Euphorie anhält.