A Programmer's Blog

von der XBOX zum HTPC

Dec
14

Medien lassen sich auf viele verschiedene Weise im Wohnzimmer abspielen. Eine brauchbare Möglichkeit ist heute der oftmals im TV eingebaute Media-Player. Es gibt aber auch dedizierte Player, wie beispielsweise die Produkte von Pocorn Hour. Aber gerade ersteres hat meistens ein stark eingeschränktes Interface und spielt meist nur eine Hand voll Formate ab. Für Bastler, zu denen ich mich zähle, war jahrelang die erste XBOX mit XBMC eine gute Wahl. In letzter Zeit wird auch die Kategorie des sog. Home Theater Personal Computer (HTPC) immer interessanter.

Auch ich habe mich dazu entschieden einen HTPC zu bauen. Ausschlaggebend dafür war, dass meine alte XBOX technisch den heutigen Formaten nicht mehr gewachsen ist. Ich wollte eine Lösung, die alles kann: Alle möglichen Film-Formate abspielen und für Musik sollte ich nicht extra den TV einschalten müssen! Ein HTPC, mit der richtigen Software, erfüllt diese Anforderungen.

Media Center PCs (bzw.  HTPCs) hatten lange Zeit gewaltige Nachteile im Bereich Stromverbauch, Wärmeentwicklung und damit auch der Lautstärke. Ende 2008 änderte sich dies, denn hier begann Intel mit dem Vertrieb der Atom-CPUs, welche weniger auf Performance, sondern auf niedrigen Stromverbrauch (~8Watt TDP) ausgelegt sind. Seit 2010 beinhalten diese CPUs gleichzeitig auch eine GPU, so dass theoretisch der Einsatz einer dedizierten Grafikkarte unnötig gemacht wurde. Allerdings hatte diese GPI keine HD-Fähigkeiten und die CPU alleine reicht hierfür schlichtweg nicht aus. Im Jahr 2011 stieg auch AMD in diesen Markt ein und liefert mit ihrer Fusion-Reihe eine CPU mit integrierter Radeon HD GPU, welcher in meinen Augen nun den Durchbruch zum kostengünstigen, stromsparenden HTPC darstellt.

Erst einmal Hardware einkaufen …

Nach einigen Recherchen und Unterstützung von Kollegen, hatte ich meine Wunschkonfiguration gefunden:

    • Gehäuse: Silverstone La Scala LC19B-R (inkl. 120W Netzteil), 140€
      Das Gehäuse hat einfach Style! Ausserdem hat es den Vorteil, dass es bereits mit einem lüfterlosen 120W Netzteil verbaut ist. Mehr Power benötigt so ein HTPC in der Regel nicht. Es ist sehr flach und passt sich damit perfekt in die TV-Landschaft ein. Ein LCD-Display oder eine Fernbedienung fehlt leider – da ich aber die Box sowieso per Android-Phone oder Maus steuere, ist dies für mich kein Negativpunkt.
    • Mainboard (inkl. Atom Fusion 350)Gigabyte GA-E350N-USB3, 93€
      Dieses Board ist sehr günstig, besitzt aber auch keinerlei Schnickschnack wie WLAN oder Bluetooth. Dafür ist es im Vergleich zu anderen Boards sehr energieeffizient.
    • RAM4GB 1066 CL7 , 15 €
      Da das Board kein Dual-Channel unterstützt, braucht man hier nur einen einzigen Riegel kaufen.
    • SSD:  16GB Kinston S100, 41€
      Die SDD dient als reine Systemplatte, damit der HTPC schnell bootet.
    • Optisches Laufwerk: Samsung SN-208BB, 21€
      Für ca. 40 € Aufpreis bekommt man ein Slimeline Blueray Laufwerk. Das habe ich mir gespart, da ich für die Blueray-Wiedergabe noch eine PS3 besitze.

Das macht also summa summarum ca. 310 €. Allerdings fehlt bei der Konfiguration noch eine Daten-Platte sowie TV-Karte. Glücklicherweise hatte ich noch eine 2TB Festplatte herumliegen. Die Festplattenpreise sind derzeit aufgrund der Flutkatastrophe in Thailand nämlich horrend hoch. Auf eine TV-Karte kann ich vorerst verzichten.

Putting it all together

Wenn man die Verpackung des Motherboards in die Hand nimmt, fällt einem schon auf wie klein es eigentlich ist. Aber beim Auspacken ist man völlig baff. Der CPU-Lüfter ist gerade einmal 2 Daumen dick!

Das Gehäuse ist sehr gut verarbeitet und bei diesem kleinen Mainboard ist der Platz mehr als ausreichend. Laut Herstellerangaben kann in dem Gehäuse nur eine 2,5 oder 3,5″ HDD verbaut werden, allerdings habe ich mindestens 3 weitere mögliche Orte gefunden, um 2,5″ Laufwerke unter zu bringen.

Die Hardware-Installation lief nahezu reibungslos ab. Einzig das DVD-Rom konnte ich nicht sofort in Betrieb nehmen, da es einen speziellen Mikro-SATA Adapter (ca. 5€) benötigt. Also musste für die Betriebsystem-Installation erstmal das DVD-Laufwerk meines PCs herhalten.

… fehlt noch das Betriebsystem!

Ich bin großer Ubuntu-Linux-Fan: es liefert eine sinnvolle Standardkonfiguration, startet sehr schnell und ist aktuell. Der einzige Haken an der Geschichte ist, dass die ATI Treiber leider die XVMC-Schnittstelle nicht unterstützen, welche benötigt wird um HD-Inhalte in X11 auf der GPU zu rendern. Ob ATI dies jemals nachreichen wird, steht in den Sternen. Es gibt zwar Möglichkeiten den MPlayer hardwarebeschleunigt zum laufen zu bringen, aber das sieht mir derzeit sehr nach einem Gefrickel aus, worauf ich mich jetzt noch nicht einlassen möchte.

Also war sehr schnell klar, dass es eine Windows-Variante werden wird. Vorzugsweise Windows-7, wegen der SSD-TRIM-Funktionalität. Glücklicherweise habe ich eine Windows 7 Lizenz geschenkt bekommen, so dass hier kein weiterer Kostenpunkt entstanden ist. Fairerweise muss an dieser Stelle aber gesagt werden, dass ein kompletter HTPC (inkl. Windows 7, HDD und TV-Karte) unter 400 € eher unrealistisch ist.

16GB für’s Betriebsystem reicht doch locker … nicht?!

Windows 7 auf einer 16 GB Platte zu installieren ist gar nicht mal so einfach. Nach der Grundinstallation von Windows 7 x64 Professional hatte ich noch 1,42GB freien Speicherplatz. Ich hab verschiedene Maßnahmen durchgeführt:

  • Abschalten der Indexierung auf der Systemplatte
  • Systemwiederherstellungspunkte deaktiviert
  • Auslagerungsdatei deaktiviert
  • nahezu alle Windows Funktionen deinstalliert
  • Suspend-To-Disk deaktiviert
  • Große Windows-Ordner auf die andere HDD gelegt

Zwischenzeitlich hatte ich auch bis zu 5GB freien Speicher, aber nach einigen Windows-Updates war das auch wieder ausgeschöpft und irgendwann habe ich aufgegeben, so dass ich mir jetzt ein 32-Bit Image mit vorinstalliertem Service Pack 1 besorgt habe.

Windows-7 auf einer 16GB-Platte zu halten ist mühsam und kann ich niemandem Raten! Hier habe ich eindeutig an der falschen Stelle gespart!

XBMC, i luv u! <3

Eine Sache stand von vornherein fest: Als Media-Player Software kommt XBMC zum Einsatz! Hier bin ich echt schon etwas religiös, aber ich behaupte einfach (ohne es wirklich zu wissen), dass es nichts besseres gibt! Es ist natürlich auch etwas Gewohnheit, da ich XBMC bereits von der XBOX kenne und lieben gelernt habe. Mir ist bisher noch kein Format untergekommen, was der Player nicht abgespielt hat. Es hat eine einfache Bedienung und mit der Remote-App auf Android lässt sich das ganze dann noch einfach per Handy steuern. Dadurch lässt sich dann auch Musik abspielen ohne extra den TV einzuschalten.

Es gibt viele weitere sinnvolle Features. Ein Beispiel: Es lässt sich eine Verzögerung für der Audiospur einstellen, da bei manchen Filmen ja Audio- und Videospur nicht synchron sind. Das habe ich so in keinem anderen Player wiedergefunden!

Und das beste ist: es ist Open Source!

HTPC vs XBOX

Um zu überprüfen, ob sich der Aufwand gelohnt hat, habe ich ein paar Messungen gemacht. Vorweg sei gesagt, dass sich natürlich alleine wegen der HD-Fähigkeit das Upgrade gelohnt hat. Bei den Strommessungen ist zu beachten, dass diese nicht über einen längeren Zeitraum gemacht wurden, und damit nicht für bare Münze genommen werden sollten. Für Lautstärken-Messungen fehlt mir das entsprechende Equipment, so dass ich das nach meinem perönlichen Empfinden beschreibe.

iXy (xbox)

Die XBOX hat relativ veraltete Hardware, dafür kann sie noch erstaunlich viel wiedergeben (ab 720p ist meistens schluss). Zugriff auf die Daten bekommt man nur per FTP.

Hardware:
  • Intel Mobile Celeron (Coppermine-Kern) mit 733 MHz
  • 64 MB DDR-RAM mit 200 MHz
  • Geforce 3-Kern „NV2A“
  • 300GB 5400 RPM HDD (original sind nur 10GB)
Stromverbrauch:
  • Standby: 1,7W
  • Idle: 52W
  • Last: 60W
Lautstärke:

Trotz tausch des Lüfters ist die XBOX sehr deutlich hörbar und hat zusätzlich zum Lüfterton einen deutlichen Summton. Zu dem waren die Festplatten damals noch deutlich lauter, so dass man jeden Zugriff auf die Festplatte wahrnimmt!

Bauform:

3,9kg leicht aber dafür ist Gehäuse klobig und hässlich.

hatepeze (htpc)

Der HTPC kommt mit allen gängigen Formaten (1080p Videos eingeschlossen) ohne Probleme klar, ausserdem kann ich neben XBMC weitere Programme im Hintergrund ausführen. Neben FTP kann ich beispielsweise über Windows-Shares Daten freigeben.

Hardware:
  • AMD Fusion E-350 2x 1,6 GHz
  • 4GB DDR3-RAM mit 1066 MHz
  • AMD Radeon HD 6310
  • 16 GB SSD und 2TB 7200 RPM HDD
Stromverbrauch:
  • Standby: 2,1W, das liesse sich auf <1W reduzieren, wenn man auf die WAL (wake on lan) Funktion verzichtet.
  • Idle: 33W
  • Last: 40W (ich habe aber teilweise auch > 40W gesehen)
Lautstärke:
Leider ist auch der HTPC wahrnehmbar, allerdings handelt es sich um ein leises und angenehmes Lüftergeräusch. Ich habe ich den verbauten System-Lüfter im Silverstone La Scala LC19 Gehäuse nicht angeschlossen, da dieser von der Lautstärke her fast eine Frechheit ist. Er ist zwar leiser als eine XBOX (was ja keine besondere Leistung ist), aber bei so einem Hersteller wie Silverstone erwartet man eigentlich, dass der Systemlüfter eine entsprechend hohe Qualität hat, vor allem wenn im selben Gehäuse ein lüfterloses Netzteil steckt!
Bauform:

Ist mit 4,9KG deutlich schwerer, dafür aber ein praktisches und wirklich schönes Gehäuse.

Fazit

Mein HTPC steht jetzt seit 5 Tagen in meinem Wohnzimmer und ich möchte ihn nicht mehr missen. Neben den eigentlichen Player-Funktionen kann ich ihn als Download-Knecht verwenden oder einfach mal damit surfen. Früher musste ich verschiedene Formate an verschiedenen Playern ausgeben: Die XBOX funktionierte zwar für Musik; HD-Filme musste ich je nach Format aber auf PS3 (m2ts) oder TV (mkv) wiedergeben, und selbst dann gab es häufig Probleme. Der HTPC spielt alles ohne Zicken ab!

Nachtrag:

Bei der Datenerhebung habe ich vergessen die Startzeit zu messen, allerdings hat hier bei einem Kaltstart trotz der SSD im HTPC, eindeutig die XBOX die Nase vorn. Einen Standby-Modus gibt es bei der XBOX so nicht, daher würde hier wieder der HTPC gewinnen.

Und Thanks Richie, Bruty und Jia für die vielen Tipps zur Hardware; danke Moggebert für die Windows-7 Lizenz.

neo4j + scala = fun

Jul
10

I had a great time at the LCGTUG Hackaton yesterday.

We played around with Neo4J and Scala. The result is pretty useless: a shortest-path calculator using the Dijsktra algorithm. But I think everyone learned something new about Neo4j, Scala or Dijsktra 🙂

Thank you LCGTUG for organizing the event.

Do It Yourself!

Jul
06

In the current project I am working on, we have about 50 external JAR-Dependencies. About one of ten bugs in our software is caused by one of these dependencies. They are not only hard to find, but hard to fix either. And even if you get it fixed within the source-code and create a patch, there is no guarantee that the fix will ever make it in the next version. Many open-source-projects are not very active or the maintainers are just too lazy to implement patches.

So, if you want to keep your dependencies update-able, it often results in ugly workarounds. I remember my time as a flash-developer, where we had to subclass nearly every component in the Flex-SDK and do really dirty hacks to get everything working as suspected.

The way of introducing a new dependency often looks like this: We need to implement a new feature, and the first thing we do is to research about stuff already done. During the research we maybe find a library which solves exactly that problem, and the initial effort to implement the feature using that library may not very high. But problems arise with time, when the software is being tested in real world situations, with real data and conditions. This may be months after the library has been introduced. Some of these problems become really time-consuming, and some of them cannot be solved in an acceptable amount of time.

I believe we should spend much more time before adding new external dependencies to our project. We should not only care about how fast we can implement our features with them, but also how good they are maintained, how easily patches can be committed and also if it wouldn’t be more efficient to just implement it by ourselves!

Scala and the Observer Pattern

Jun
17

I just started coding my first scala snippets. I played a bit around with lwjgl library to create some random graphic stuff.

The first problem I faced was to find a generic implementation to dispatch events such as render- or input-events from one place and handle them in another place. In OO-Languages this problem is usually solved using the observer pattern.

After studying some existing scala solutions,  I did not find the one that fits my coding style. Since I come from the Flash-world, I would really appreciate a solution where observers are just callback-functions instead of implementations of traits. I also don’t like to have my observables cluttered with code for dispatching the events to the observers.

My Solution consists of a single generic class, the “Event”:

class Event[T] {
 private var listeners: List[T] = List();

 def apply(listener: T): Unit = register(listener);
 def register(listener : T) : Unit = listeners ::= listener;
 def unregisterAll() : Unit = listeners = List();
 def fire(f : (T) => Unit) = {
   for(l <- listeners) {
     f(l)
   }
 }
}

All an observable has to do now is to create one field for each event-type they offer and to call fire() on them. The following example defines one event that gets fired as soon as the position of a DisplayObject changes. The callback-method takes the coordinates as paramters containing the new values.

class DisplayObject {

 val onPositionChangeEvent = new Event[(Int, Int) => Unit];

 private var x:Int = 0;
 private var y:Int = 0;

 def changePosition(x:Int, y:Int) = {
   this.x = x;
   this.y = y;
   onPositionChangeEvent.fire(_(x, y));
 }
}

Now we can register a callback-function directly at the onPositionChangeEvent-field. In the following example we print the new value to the console.

var observable = new DisplayObject();
observable.onPositionChangeEvent((x, y) => println(x + ":" + y));
observable.changePosition(10, 15);

One problem I faced is that I could not find any possibility to reliably unregister from an event. So I decided to implement an unsubscribeAll method.

observable.onPositionChangeEvent.unregisterAll();

If someone has an idea how this could be improved, please leave me a comment.