Party in der WG-Küche

Nachdem die AirPort express meines Mitbewohners als WLAN-Hotspot herhalten musste, da mein billo TP-Link Router irgendwie seeehr unzuverlaessig WLAN macht war es in unsrer Küche teilweise sehr still.
Ein zu kurzes Klinkenkabel hatte zur Folge, dass man nicht sehr gern sein Handy anstecken wollte um Musik zu machen und es im Regal liegen zu lassen (wir Informatiker lassen ja unsere Geräte nur ungern irgendwo rum liegen).

Ein zwei Meter Klinke-Erweiterungskabel des AirPort-Besitzers half da zwar effektiv, da man nun sogar auf dem Klo noch Musik für die Küche machen konnte (lol, jk). Aber da das Kabel eigentlich in Gebrauch war, sollte nur eine temporäre Lösung sein, bis ein anderes Kabel gekauft wird.

Eine Mischung aus "Wir müssen mal wieder was bei Amazon bestellen" und "Hier liegt ja noch der ungenutzte Raspberry Pi herum" brachte mich dann auf die Idee doch einfach einen WLAN-Stick zu bestellen und einen AirPlay Reciever zu basteln.

Also hab ich kurz meine alten Notizen zu zuverlässigen WLAN-Sticks die man auf dem Pi benutzen kann rausgekramt, die ich vor kurzer Zeit mal gemacht hatte und nochmal überprüft ob es mittlerweile was besseres für weniger Geld gibt. Da ich bei verschiedenen Alternativen die mehr Durchsatz versprachen von neuen Revisionen las, die dann doch nicht mehr o-o-b unter Linux liefen, entschied ich mich dann für das Modell: Edimax Nano 150Mbps (EW-7811Un). Ich las, dass der verwendete Chip unter Raspbian, das ich benutzen wollte, ohne zusätzliches Treiber-Gefrickel lief. Also das Teil bestellt und es kam auch sehr schnell an, wie man das ja mittlerweile gewohnt ist.

Weil ich mittlerweile nicht mehr so ganz so viel Gefallen daran habe dauernd Linuxe aufzusetzen, mich mit dem neusten init shit auseinander zu setzen und nicht soo optimale Erfahrung mit shairport gemacht hatte (nach ein paar Tagen hat der Daemon schon ganz gern mal seinen Dienst verweigert und man musste den Pi rebooten), wollte ich mal schauen, was es als Alternativen zu Raspbian+shairport denn mittlerweile so gibt.

Und siehe da! Ein wildes volumio erscheint! Die Distro unterstützt außer dem RaspberryPi noch andere Boards und man kann auch allerhand Audio-Kram anschließen, wenn einem der onboard-Sound nicht ausreichen sollte.

Die Webseite muss nicht viel Anleitung geben.

  • Downloaden
  • Flashen
  • Vorbereiten (SD-Karte, WLAN-Stick, DAC, usw. anstecken)
  • Web-Oberfläche aufrufen und Musik aufdrehen

Unter Windows und Mac OS kommt man ganz ohne Konsole aus! Das hat mich ziemlich beeindruckt. Man kann es aber natürlich auch ganz normal mit dd machen, wie unter Linux.

Sollte volumio.local nicht aufgelöst werden, kann man entweder auf der Router Web-Oberfläche nachgucken oder das Netzwerk nach IPs oder Bonjour-Diensten (wie AirPlay) scannen, volumio hat da den ein oder anderen am Laufen.

Als ich dann die IP rausgefunden hatte, konnte ich volumio konfigurieren: ins WLAN eingeloggt, LAN-Kabel ab, Klinke-Kabel dran, Spotify konfiguriert, Musik-Share vom lokalen Fileserver gemountet und das erst beste Musikstück abgespielt. Für den ungehinderten Musikgenuss sollte man noch sicher gehen, dass die Lautstärke sowohl in volumio, als auch an den Boxen aufgedreht ist. Sonst ist nämlich Stille.

Das ganze ging mir persönlich sogar ein bisschen zu einfach, ich hatte mich mental schon auf ein bisschen gefrickel, das mir ja ab und an Spaß macht, eingestellt. Teuer war das ganze auch nicht, da ich bis auf den WLAN-Stick ja schon alles rumliegen hatte. Wenn man alles neu kaufen muss, kommt man so bei 55 Euro raus und spart damit gegenüber einer AirPort express rund 30 Euro.

Immerhin kann man jetzt in der WG-Küche wieder Musik abspielen: Vom Handy über AirPlay, vom Fileserver oder USB-Stick auf dem Gerät oder von Spotify. Und so UPNP und DLNA Kram ist auch noch dabei, da muss ich aber erst mal rausfinden, was damit so geht.

Und das Schwein ist auch glücklich:
VolumioPi im Regal

If you really want your values in the correct range

Update: Made the statement look more intuitive. Also corrected a rogue closing parenthesis...

The other day I noticed a subtle bug in one of my Java visualization prototypes. I somehow got NaNs everywhere, where there should absolutely be none of them.
The math I am using is correct, so I had to find the place where the NaN was produced.
I would really like it if the whole application just blows up into my face when it tries to calculate something with NaN instead of a usable value, but anyway, I had to trace the NaNs to its origin and after some debugging I found it.

Turns out Math.acos (which I was using) has the following in its javadoc:

If the argument is NaN or its absolute value is greater than 1, then the result is NaN.

Duh. Better if I had read the javadoc before blindly throwing my values at the function, because, it turns out, I was passing a 1.000000000002 at some time, for which I got rewarded with NaN.

So, for a quick fix, I decided to ensure that my values are in the correct range of -1.0 to 1.0.

Instead of writing something horrible like

if (val > 1.0)  
      return 1.0;
  if (val < -1.0)  
      return -1.0;
  

Leo gave me a much simpler and nicer looking solution:

return Math.max(-1.0, Math.min(value, 1.0));  
  

These kind of floating-point errors are really nasty and I should probably take the time for reading "What Every Computer Scientist Should Know About Floating-Point Arithmetic" (Goldberg, 1991), finally.



I am writing these a-programmers-diary posts, for several reasons (at leats these are the ones to bring me starting this with this post).
The first one is, that I want to use this blog more for some kind of diary while programming. So do not assume that this will always be the best solution I am posting. Normally this is just the one I found working and seemed to me not as a crime against humanity.
Another reason is, that I sometimes think 'Oh, I had this problem before, how do I solve this'. So I can use these posts for some kind of reference.
The third reasons is that maybe someone reads this and finds a better solution or spots any mistakes I am making. If you do so feel free to correct me, I really like to learn. Just contact me via mail or twitter and I will add your suggestions as an update to the post, so it stays with the text of the post and does not get lost like outsourced comments like to do.

Location-aware Functional Keys

The problem

The problem with the Apple Media Keys is that they hide the standard function keys. This is great for media consumption, as I can adjust the display brightness or sound volume with just one hand.
However in Eclipse, the current IDE I spend most of my working hours in, the F-keys are mapped to often used actions, such as debug stepping and running code. This is great, as I can debug my code step by step with just a few keys with my eyes staying on the display.

The solution

OS X provides a setting for either one of the two modes directly accessible without touching the Fn key, but this is tedious doing it everytime I switch from home to work or vice versa.

Enter ControlPlane. This app lets you do Actions based on your Context. For instance, most of my Contexts are activated, when my MacBook is connected to a certain monitor or sees a certain WiFi network, but other Evidence Sources are also possible.

The missing link between the automatically detected environment (work or home) and the correct setting (media keys or function keys) is the often neglected, because miserably documented, AppleScript.

I found a script for toggling the setting in a forum post. I took it and created two separate scripts, one for activating the setting (at work) and one for deactivating (at home).

Next I created a Shell Execution Action for each of the scripts (osascript path/to/script), one when entering the work Context, and one when leaving.

But wait! We are not done yet.

Mavericks introduced fine-granular settings for Accessibility. Each Accessibility feature has to be enabled for specific apps, when Apps request those features. But ControlPlane does not request the feature to script UI elements, so it does not get added to the list, thus our AppleScript execution fails. Giving the AppleScript Editor the rights is not enough, because when ControlPlane is executing the script the AppleScript Editor is no longer the executing app.

So, how to get the some executing app listed there?

The trick is to wrap both scripts in an Automator app; and so I wrapped both scripts and told ControlPlane to execute both apps and hide them (just to be sure I do not see them executing).

I put the code and the basic instructions into a gist: