Sunday, 20 April 2014

XBMC and your TV remote can be friends

Installing and deploying an XBMC distribution on a Raspberry Pi (Pi) is pretty easy. Once plugged to a TV, you may also be surprised by the ability to navigate the XBMC menus with your TV remote, out-of-the-box. Or may be not? Then you may want to read further.

How does it work?

All the magic happens thanks to the HDMI CEC feature. CEC stands for Consumer Electronic Control and is is charge of transmitting control signals between devices linked by HDMI wires. 
For the records, it uses the pin #13 of the HDMI standard connector (more details on Wikipedia). Lucky number.



In our case, it makes possible for a TV and Raspberry Pi to send each others control signals, as soon as they are connected together via a HDMI cable and both implement the HDMI CEC features.

From the TV remote to the Pi

More details to understands what happens under the hood

Both the TV and the Pi are CEC enabled, it means they can send and receive CEC signals through the HDMI wire.
The schema above illustrate a very common use case:
  1. One presses a button on the TV remote (e.g. the Play media button). Nothing to do with CEC so far, rather InfraRed in most TV remotes cases.
  2. The TV receives the signal and may decide to forward it to the HDMI connected Pi. It triggers a CEC signal (e.g. a Play media signal) which is sent to the Pi.
  3. The Pi receives the CEC signal and takes action according to the current context (e.g. starts to play the current selected movie)
This explains how you can control XBMC running on your Pi using your TV remote. Essentially, good guys have taken care of implementing the CEC feature in XBMC, while other good guys have done the same in your TV hardware.

However the communication goes both ways so the Pi can also send signals to the TV. This come handy when the Pi changes its state, like getting into energy saving mode or shutting down: it may send a CEC signal to the TV asking it to go stand-by or to shut down as well.

Obviously none of the devices on the HDMI chain can force another one to do anything, it's all up to the way each device constructor/programmer has implemented the CEC routine. It's more like each device can send and receive whatever CEC signals and will act according to their own CEC implementation upon reception of a CEC signal.

Practical case: TV + Remote + XBMC = ?

You can spare yourself the suspens by searching your TV manual for CEC information. Each constructor may have renamed/rebranded it though. Here is a list picked from CEPro:


Brand
CEC Branding
Hitachi Plain old HDMI-CEC
LG Electronics SimpLink
Panasonic Viera Link (originally EZSync)
Philips Easy Link
Samsung Anynet+
Sharp Aquos Link
Sony Bravia Sync
Toshiba Regza Link (formerly CE-Link)

If you're not keen on reading your TV manual, then you may give it a try and see straight away: plug your enabled XBMC Pi (e.g. using Raspbmc) to your TV and turn them on.

CEC TV side should activate automatically when an HDMI device source is selected.
XBMC's CEC drivers on the Pi will kick-in straight away, showing a toast notification.

Just grab your remote and try the buttons, e.g. play with the arrows and see if it switch the menus in XBMC. In case it doesn't work, please note that punching the buttons harder doesn't work better (I've been through that, once) and may damage the remote, possibly yourself too.


Going further with the TV remote

You should now be aware of what to expect from your TV remote with XBMC, either one of those 3 cases:

  • Your TV is CEC compliant and your remote works like a charm, you don't miss any functionality: lucky you, you don't even need to read those lines.
  • Your TV is CEC compliant and your remote has a few buttons recognised by XBMC out-of-the-box, however it misses a few functionalities: bare with me, the next section may be of some help.
  • Your TV is not CEC compliant: forget your TV remote and have a look to this Pi IR receiver. It's cheap and funny to put in place, but out of the scope of this article. You also have the option of WiFi XBMC remotes apps for smartphones. This one for Android rocks.
If you wish to customise your TV remote for XBMC you need to dig a bit further to achieve your goals. Fortunately this won't involve any coding neither compiling, the nice guys behind XBMC have built an easy-to-use XML mapping for all supported remote devices.

Know your buttons

The first step is to identify the buttons triggering CEC signals which are recognised by XBMC on the Pi. Assuming we are logged-in as root onto your Pi's Bash, there are two distinct approaches to this (note they're not exclusive):

The hardcore and straight-forward approach

A quick way to check what TV remote buttons are caught by XBMC looking at its raw logs.
  1. Turn XBMC logs to DEBUG level. To do so, edit the XBMC advanced settings file:
    vi /opt/xbmc-bcm/xbmc-bin/share/xbmc/system/advancedsettings.xml
    If the file is empty (it may not exist already depending on your XBMC distribution), simply fill it with the following:
    <advancedsettings>
      <loglevel hide="false">1</loglevel> 
    </advancedsettings>
    As it is more likely you've got some content already into the config file, simply add a new line with:
    <loglevel hide="false">1</loglevel>
    straight after the line matching
    <advancedsettings>
  2. Monitor XBMC logs live. Enter this command which will refresh and filter the XBMC debug log file live:
    tail -f /home/pi/.xbmc/temp/xbmc.log | grep -iE "onkey" --color=always
    Then leave your console as it is. tail -f is in charge of displaying new lines from the log file /home/pi/.xbmc/temp/xbmc.log, then we pipe this flow to grep to display only the lines containing the pattern "onkey". The option --color=always allows to highlight the characters grep has matched.
  3. Play with your TV remote when XBMC is running so you can see the live log fed with entries showing which of the TV remote buttons you've pressed are actually recognised by XBMC.  You should see something like this on each successful occurrence:
    01:55:38 T:3040153600   DEBUG: OnKey: 168 (a8) pressed, action is Notification(Keypress, right, 1)
    01:55:39 T:3040153600   DEBUG: OnKey: 166 (a6) pressed, action is Notification(Keypress, up, 1)
    01:55:40 T:3040153600   DEBUG: OnKey: 169 (a9) pressed, action is Notification(Keypress, left, 1)
    01:55:41 T:3040153600   DEBUG: OnKey: 167 (a7) pressed, action is Notification(Keypress, down, 1)
    01:55:44 T:3040153600   DEBUG: OnKey: 11 (0b) pressed, action is Notification(Keypress, select, 1)
    
    Where each end of line shows "Notification(Keypress, <button_name>, 1)", <button_name> being the name assigned by XBMC to the button you pressed on your TV remote.
    E.g. at line #1, <button_name> = right, meaning the button you pressed on your TV remote to display that line of log is bound to XBMC remote as the right button.

The soft and visual approach

A user-friendly way to check what TV remote buttons are caught by XBMC looking at the on-screen toast notifications.
  1. Edit the XBMC remote key mapping, remote.xml, so each action taken on one of the TV remote button recognised by XBMC triggers an on-screen toast notification instead of the initial action it was intended to. We first back the config file up:
    cp /opt/xbmc-bcm/xbmc-bin/share/xbmc/system/keymaps/remote.xml /opt/xbmc-bcm/xbmc-bin/share/xbmc/system/keymaps/remote.xml.backup
  2. Now we can edit the remote.xml file:
    vi /opt/xbmc-bcm/xbmc-bin/share/xbmc/system/keymaps/remote.xml
  3. Replace its whole content with the following:
    <!-- Mapping all the supported remote buttons to a toast notification presenting the button name -->
    <keymap>
      <global>
        <remote>
          <left>Notification(Keypress, left, 1)</left>
          <right>Notification(Keypress, right, 1)</right>
          <up>Notification(Keypress, up, 1)</up>
          <down>Notification(Keypress, down, 1)</down>
          <select>Notification(Keypress, select, 1)</select>
          <back>Notification(Keypress, back, 1)</back>
          <menu>Notification(Keypress, menu, 1)</menu>
          <info>Notification(Keypress, info, 1)</info>
          <display>Notification(Keypress, display, 1)</display>
          <title>Notification(Keypress, title, 1)</title>
          <play>Notification(Keypress, play, 1)</play>
          <pause>Notification(Keypress, pause, 1)</pause>
          <reverse>Notification(Keypress, reverse, 1)</reverse>
          <forward>Notification(Keypress, forward, 1)</forward>
          <skipplus>Notification(Keypress, skipplus, 1)</skipplus>
          <skipminus>Notification(Keypress, skipminus, 1)</skipminus>
          <stop>Notification(Keypress, stop, 1)</stop>
          <zero>Notification(Keypress, zero, 1)</zero>
          <one>Notification(Keypress, one, 1)</one>
          <two>Notification(Keypress, two, 1)</two>
          <three>Notification(Keypress, three, 1)</three>
          <four>Notification(Keypress, four, 1)</four>
          <five>Notification(Keypress, five, 1)</five>
          <six>Notification(Keypress, six, 1)</six>
          <seven>Notification(Keypress, seven, 1)</seven>
          <eight>Notification(Keypress, eight, 1)</eight>
          <nine>Notification(Keypress, nine, 1)</nine>
          <!-- additional keys from the media center extender for xbox remote -->
          <power>Notification(Keypress, power, 1)</power>
          <mytv>Notification(Keypress, mytv, 1)</mytv>
          <mymusic>Notification(Keypress, mymusic, 1)</mymusic>
          <mypictures>Notification(Keypress, mypictures, 1)</mypictures>
          <myvideo>Notification(Keypress, myvideo, 1)</myvideo>
          <record>Notification(Keypress, record, 1)</record>
          <start>Notification(Keypress, start, 1)</start>
          <volumeplus>Notification(Keypress, volumeplus, 1)</volumeplus>
          <volumeminus>Notification(Keypress, volumeminus, 1)</volumeminus>
          <channelplus>Notification(Keypress, channelplus, 1)</channelplus>
          <channelminus>Notification(Keypress, channelminus, 1)</channelminus>
          <pageplus>Notification(Keypress, pageplus, 1)</pageplus>
          <pageminus>Notification(Keypress, pageminus, 1)</pageminus>
          <mute>Notification(Keypress, mute, 1)</mute>
          <recordedtv>Notification(Keypress, recordedtv, 1)</recordedtv>
          <guide>Notification(Keypress, guide, 1)</guide>
          <livetv>Notification(Keypress, livetv, 1)</livetv>
          <liveradio>Notification(Keypress, liveradio, 1)</liveradio>
          <epgsearch>Notification(Keypress, epgsearch, 1)</epgsearch>
          <star>Notification(Keypress, star, 1)</star>
          <hash>Notification(Keypress, hash, 1)</hash>
          <clear>Notification(Keypress, clear, 1)</clear>
          <enter>Notification(Keypress, enter, 1)</enter>
          <xbox>Notification(Keypress, xbox, 1)</xbox>
          <playlist>Notification(Keypress, playlist, 1)</playlist>
          <guide>Notification(Keypress, guide, 1)</guide>
          <teletext>Notification(Keypress, teletext, 1)</teletext>
          <red>Notification(Keypress, red, 1)</red>
          <green>Notification(Keypress, green, 1)</green>
          <yellow>Notification(Keypress, yellow, 1)</yellow>
          <blue>Notification(Keypress, blue, 1)</blue>
          <subtitle>Notification(Keypress, subtitle, 1)</subtitle>
          <language>Notification(Keypress, language, 1)</language>
        </remote>
      </global>
    </keymap>
    
    I've made this file up using an exhaustive list of the buttons recognised by XBMC as per its code (see the TranslateRemoteString method)
  4. Restart XBMC (or simply turn the Pi off and on again)
  5. Play with your TV remote when XBMC is running so you can see the on-screen notifications showing the actual button name bound with your TV remote button.

    Below is an example of how it should look like when the select button of the TV remote is pressed (corresponding to the line #9 of the XML listing above):


If a button doesn't give a notification, then it means your TV doesn't forward it as an XBMC supported CEC signal. There is no much to do in that case, unfortunately.

Customize your TV remote buttons with XBMC

Now you know how each of your TV remote button is recognised by XBMC, it's time to make your own mapping.

To take a practical example, I had only the basic buttons of my LG TV remote recognised by XBMC, and I was missing some features like switching the subtitles or the audio track during a video playback.

As the navigation arrows on my remote were already taking care of skipping scenes back and forward, I decided to map the subtitle and audio functions respectively to the skip back () and skip forward () buttons of my TV remote.

To achieve such a remapping, you need to map your TV remote buttons as recognised by XBMC to the available XBMC actions. Their wiki give an exhaustive list of the available actions.

The default remote.xml file comes with several sections. The full structure is explained here, however I'll stick with two things for this example: mapping the TV remote buttons to an action in a context. By context I mean a specific window under XBMC, e.g. the general menus windows or the fullscreen playback window. By action I mean, well, an action like move left in a menu or play a video.

If I go back to my example, I want to make the following changes:
  1. When in the general menus, I want the  and  buttons to map respectively to the XBMC.ActivateWindow(Home) and ContextMenu XBMC actions.
    The former takes XBMC back to the Home window, while the latter shows a contextual menu, when available (the one you get with a mouse secondary-click)
  2. When on a fullscreen movie playback, I want the  and  buttons to map respectively to the NextSubtitle and AudioNextLanguage XBMC actions.
    The former rolls through the available subtitles (if any) and no subtitles, while the latter rolls through the available audio tracks, if any other than the main one.

The points above translate into the following remote.xml file configuration:
<keymap>
  <global>
    <remote>
      ...
      <skipplus>ContextMenu</skipplus>
      <skipminus>XBMC.ActivateWindow(Home)</skipminus>
      ...
    </remote>
  </global>
  ...
  <FullscreenVideo>
    <remote>
      ...
      <skipplus>NextSubtitle</skipplus>
      <skipminus>AudioNextLanguage</skipminus>    
      ...
    </remote>
  </FullscreenVideo>    
  ...
</keymap>
Where the line #5, #6, #14 and #15 show the following structure:
<button_name>xbmc_action_name</button_name>
(Note the "..." must not be included, they're just here to figure the rest of the XML file content)

All the XBMC action are fully documented on their very good wiki.

You now have all your button names and action names to map together into the various contexts XBMC offers.

When done with your customisations, take care to save your changes in another location than /opt/xbmc-bcm/xbmc-bin/share/xbmc/system/keymaps/ (e.g. your home folder) as any automated update will revert all the XBMC config files.

Conclusion

Now you should be able to adapt your TV remote to your exact needs. The only issue is if you don't have enough recognised buttons to map all the actions you want.
In that case you may want to fall back on a generic TV remote which should be fully recognised and offer all the mappings capabilities you're dreaming about.

That's all folks!

Sunday, 23 March 2014

Formatting a Hard Drive with Linux, for Linux

I never thought I would struggle that much with an external Hard Drive (HD) formatting operation under Linux.
But I did, so here is this article, describing step-by-step what one shall do to smoothly format a HD under Linux, using the console only (it means no UI, neither a mouse. sigh)

However don't get too excited, the context of this article is quite narrow.

First of all it sticks to Linux Ext formats, Ext4 in the current use-case. Furthermore the Linux distrib is a light Raspbian (the one used by Raspbmc) on a Raspberry Pi. Finally this focuses on a single partition scheme only. I may explain partitionning  more into details in a further post if needed.

Before we start make sure you've got:
  • A system running Linux (a Pi in this example)
  • Basic knowledge in Linux bash command lines
  • A USB HD that can be safely erased
First of all, open a bash prompt onto the machine which will be in charge of formatting the target HD, e.g. a remote ssh session, a command prompt from the Linux Graphical User Interface (GUI) such as X, or directly the command prompt given by your system like Arch Linux would do.

We'll assume we are logged as root. If you think it's bad practice, then simply prefix the following bash commands with sudo.

Plug your HD in and see how your system sees it:
fdisk -l
This should give you an output like:
root@raspbmc:~# fdisk -l
Disk /dev/mmcblk0: 15.9 GB, 15931539456 bytes
255 heads, 63 sectors/track, 1936 cylinders, total 31116288 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0006e204
        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1               1      143360       71680    b  W95 FAT32
/dev/mmcblk0p2          151552    31115263    15481856   83  Linux

A few explanations about this output:
  • The whole chunk between lines 2 and 10 would repeat for each disk detected by your system.
  • Line 2 shows the actual Linux device against which your HD has been bound: it is know as mmcblk0. That's what we were looking for actually. We can also see the size of the device, which is almost 16 GB in this example. In this case, it is an SD card (already formatted).
    Let's call this device <myDevice> as a generic placeholder for the name you will find for your own device. However my output sample will still show mmcblk0 for the sake of the example.
  • Lines 9 and 10 show the partitions that already exist, if any. Each of them has been bound to its own Linux device, respectively mmcblk0p1 and mmcblk0p2. It may happen if the disk you're using has been pre-formatted already.
We can now run the fdisk utility in interactive mode, i.e. the prompt now belongs to fdisk until you exit it (so no more need to prefix anything with sudo in this section):

fdisk /dev/<myDevice>

You should see something like this:
root@raspbmc:~# fdisk /dev/mmcblk0
Command (m for help):
As you can see, the prompt is not the bash one anymore, but the fdisk one.

Out of curiosity, have a look to the available commands:
m
You should see something like this:
Command (m for help): m
Command action
   a   toggle a bootable flag
   b   edit bsd disklabel
   c   toggle the dos compatibility flag
   d   delete a partition
   l   list known partition types
   m   print this menu
   n   add a new partition
   o   create a new empty DOS partition table
   p   print the partition table
   q   quit without saving changes
   s   create a new empty Sun disklabel
   t   change a partition’s system id
   u   change display/entry units
   v   verify the partition table
   w   write table to disk and exit
   x   extra functionality (experts only)
As we simply want to wipe out all the data on this HD, let's check if any partition exists already so we can get rid of it:
p
You should see something like this:
Command (m for help): p

Disk /dev/mmcblk0: 15.9 GB, 15931539456 bytes
255 heads, 63 sectors/track, 1936 cylinders, total 31116288 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0006e204

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1               1      143360       71680    b  W95 FAT32
/dev/mmcblk0p2          151552    31115263    15481856   83  Linux
Which is exactly the output we had earlier, when running fdisk in non-interactive mode.
Delete existing partitions if needed:
d
You should see something like this:
Command (m for help): d
Partition number (1-4): 

Simply enter the number corresponding to the line of the partition you want to delete and hit enter. Make sure no partition remains (if needed) by printing the partition list again using the 'p' command.
Now we've wiped out the existing partitions (if any), let's create a new one:
n
You should see something like this:
Command (m for help): n
Partition type:
   p   primary (2 primary, 0 extended, 2 free)
   e   extended

We'll create a primary partition by default. Very roughly, we can only create 4 partitions, that's a hard limit. To work that around without breaking everything, some clever guys introduced the extended ones, which can be used to nest as many logical partitions as needed. This forum post gives a bit more details about this.
Once a partition type has been selected, simply follow the instructions to build your partition. Each prompt comes with a default value which all drive to a partition covering the whole disk space.

Now we've got our new partition, it will be automatically bound to a new device within your /dev folder. Let's see what device has been created (we'll name it <myDevicePartition>) by using the 'p' command again.
It is very important as from now on we are going to deal with the partition we've just created within the HD, not the HD itself. E.g. in this example case, /dev/mmcblk0 points to the HD, while /dev/mmcblk0p1 and /dev/mmcblk0p2 point to the respective existing partitions within the HD.

If you are happy with your work, ask fdisk to write changes and exit:
w
In case you've done rubbish, simply use the 'q' command so you don't save any changes on exit.

We are halfway from having a usable HD now. The disk is partitioned, meaning it has an internal structure able to host a file system (a single one in this example).
Let's format our partition:
mkfs.ext4 /dev/<myDevicePartition> 

In order to access our freshly formatted HD, we have to mount it, i.e. build an access point into the existing file system (the one hosting the bash you have used to partition your HD).

This access point is a simple directory. We'll create it into the /media directory for the sake of Linux good practices (assuming it does exist as it could also be named /mnt or /mount), but it could be any other really:
mkdir /media/<myMountPoint>
Where <myMountPoint> is a name of your choice.

We can now mount the device (which is the -only- partition of your HD)
mount -t ext4 /dev/<myFormatedDevice> /media/<myMountPoint>

Some systems automatically mount the HD they detect either at startup or on-the-fly. In case your system is not that clever, you can manually make this mount permanent.
You need to edit your /etc/fstab configuration file and add the following line:
/dev/<myFormatedDevice> /media/<myMountPoint> ext4 defaults 0 0


Other sources used for this article: http://superuser.com/a/643797 and fdisk help.

That's all folks!


Saturday, 22 March 2014

Which SD cards for a Raspberry Pi?

Many types of Secure Digital (SD) cards exist to fit many different purposes. This article aims to help one spotting the differences and the way they are advertised to finally pick the SD card that will fit a given device (more specifically a Raspberry Pi).

Basics of SD cards

SD cards exist in various formats, namely regular, mini and micro.

From top to bottom: regular, mini and micro sizes
The format doesn't mean anything in terms of capacity (how much it can hold) and speed (how fast it reads and writes data).

Checking the capacity is trivial, the size is most of the time given in GB and may vary from a few GB to hundreds (and so does the price).

The trickier part is about speed: it is actually not precise enough, we should rather talk about:

  • Reading speed
    How much data per second an SD card can read
  • Writing speed
    How much data per second an SD card can write
  • Read access latency
    How much time it takes an SD card before it can read data
  • Write access latency
    How much time it takes an SD card before it can write data

Reading and writing speeds can be spotted via the following properties: 
  1. Speed class
    It is simply the minimum writing speed an SD card can perform. The higher the faster, knowing it is expressed in MB, e.g. a class 6 SD card will never write non-fragmented data slower than 6 MB per second. This may change if the data written is fragmented, e.g. being many small files instead of a single one.
  2. "x" rating
    Quoting wikipedia
  3. The “×” rating, made obsolete by speed classes, is a multiple of the standard CD-ROM drive speed of 150 KB/s (approximately 1.23 Mbit/s) 
    It is to be read carefully though: there is no rule regarding what it refers to, e.g. from a vendor to another it could be an average reading speed, the best reading speed, the best writing speed, or any combination of the above.
    As most of the times (not to say always), a card will read data faster than it writes, it is safer to assume the "x" rating refers to the average reading speed rather than anything else.  

Read and write access latencies however cannot be spotted that easily, and you'll have to dig into the vendor documentation to check those details, if provided.
That's very unfortunate though, because this is what we need to pick the right SD card for our Pi, which leads to the next section.

Which SD card for my Pi?

Most of us would think "I'll take the fastest one" (commonly class 10 on the paper) to get the best results.

If you've read and understood the previous section then you may think this could be wrong:  the class (and in a certain way the "x" rating as well) gives an I/O rate, i.e. how fast the card is to read or write data.

However, before getting into this I/O you need to access the card and this takes a certain amount of time, and this time is not represented by the class neither the x speed.

This might not be big deal when it comes to read or write big chunks of data: the access latency would be negligible compared to the time it takes to write the data. However this latency would add up for each access the cards makes, so when it comes to access very small files, it may take ages even if the SD card is class 10.

Let's take a simple example with a class 10 SD card which would have a 1 second write access latency.
Class 10 means it can write 10 MB/s, i.e. it can write 10 GB (=10240 MB) of data in 10240/10=1024 s.
1 s latency means it will take the card 1 s each times it will begin to write a single file.
Write access latency adds up as follow:

  • In the case of a single file (let's say a HD video), it is just a one off write access, so only 1 s latency added up to the write operation.
    It makes it 1024+1 seconds to write this 10 GB file, which is roughly half an hour.
  • In the case of 10,240 files, each one 1 MB big , we still have 10 GB worth of data in total, but fragmented into 10,240 single files.
    Hence we would still have the same writing time, 1024 sec, but the added latency remains 1 s per file, i.e. 10,240 seconds.
    Total time for the 10GB write operations is now 1024+10240=11264 s, which is roughly more that 3 hours.


Conclusion: when it comes to manipulate small files, like Linux does, or like your MP3 collection is, the shorter the access latencies are, the better, regardless of the SD card class or "x" rating.

This very interesting article shows numbers for many different SD cards brands and classes. It also highlights the fact the highest class SD cards may not have the best latencies...

Regarding the Pi, it seems that a class 6 SD card is sufficient most of the times, according to the Pi capabilities. You may not need a higher class unless you're manipulating large files directly on the SD card instead of on an external HD for instance.

As a concrete example, this 8 GB class 6 SD card is fairly cheap and delivers good performances for most of the usages I've got for my Pi, e.g. media-center and games emulation.


-That's all folks!