torsdag den 18. juli 2013

Fooling around with gstreamer

So, at work I'm playing with gstreamer, which is a quite powerful, but very confusing thing to use.

Basically you build up a chain of elements, linking your sources to sinks though pads.

gstreamer comes with two handy little command-line tools:

  • gst-launch
    Lets you test your chain (before you write it into your program and compile it, just to see it fail :-/)
  • gst-inspect
    Lets you see the options/parameters of each element.

Two words on gst-inspect:
  1. use gst-inspect without any arguments to see all available elements and gst-inspect to see it's options (capabilities).
  2. You can't always trust the capabilities of source elements, as these may depend on the source (example of untrust worthy source element: v4l2src)
    Your source elements needs to be either paused or playing to see what it offers.

All the elements in your chain have one or more pads, that you can use to link a to other elements, each pad has a set of capabilities are negotiated, to see if they are compatible.

Example just showing a sample videostream on screen:
gst-launch-0.10 videotestsrc ! ximagesink

To specify a width and height, we can pass it through another set of capabilities, forcing the negotiation between the elements to set our desired width and height:
gst-launch-0.10 videotestsrc ! video/x-raw-rgb,width=640,height=480 ! ximagesink

The videotestsrc, as a test source, is very generous of the formats it will output.
ximagesink is not; it only accepts video/x-raw-rgb.

You know this by using gst-inspect:
[urup@c4a012 ~]$ gst-inspect-0.10 ximagesink
Factory Details:
  Long name: Video sink
  Class: Sink/Video
  Description: A standard X based videosink
  Author(s): Julien Moutte
  Rank: secondary (128)

Plugin Details:
  Name: ximagesink
  Description: X11 video output element based on standard Xlib calls
  Filename: /usr/lib/gstreamer-0.10/libgstximagesink.so
  Version: 0.10.36
  License: LGPL
  Source module: gst-plugins-base
  Source release date: 2012-02-20
  Binary package: GStreamer Base Plugins (Archlinux)
  Origin URL: http://www.archlinux.org/

GObject
 +----GstObject
       +----GstElement
             +----GstBaseSink
                   +----GstVideoSink
                         +----GstXImageSink

Implemented Interfaces:
  GstImplementsInterface
  GstNavigation
  GstXOverlay

Pad Templates:
  SINK template: 'sink'
    Availability: Always
    Capabilities:
      video/x-raw-rgb
              framerate: [ 0/1, 2147483647/1 ]
                  width: [ 1, 2147483647 ]
                 height: [ 1, 2147483647 ]


...

And hence we set the video format accordingly to rgb.

One of the more frequently use elements when working with video is the ffmpegcolorspace one. It provides conversion between different formats.

We could therefore write to above as:
gst-launch-0.10 videotestsrc ! video/x-raw-yuv, width=640, height=480 ! ffmpegcolorspace ! ximagesink

It still works, even though the source format is wrong, because ffmpegcolorspace converts it for us.
note: Whenever possible you should make sure your formats match up, instead of converting them. This is especially true if your on a platform with limited capabilities, or you find your playback is lagging.

If you want to know what formats are being used, you can use the -v argument to gst-launch:
[urup@c4a012 ~]$ gst-launch-0.10 -v videotestsrc ! video/x-raw-yuv, width=640, height=480 ! ffmpegcolorspace ! ximagesink
Setting pipeline to PAUSED ...
/GstPipeline:pipeline0/GstVideoTestSrc:videotestsrc0.GstPad:src: caps = video/x-raw-yuv, width=(int)640, height=(int)480, framerate=(fraction)30/1, pixel-aspect-ratio=(fraction)1/1, format=(fourcc)YUY2, color-matrix=(string)sdtv, chroma-site=(string)mpeg2
Pipeline is PREROLLING ...
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:src: caps = video/x-raw-yuv, width=(int)640, height=(int)480, framerate=(fraction)30/1, pixel-aspect-ratio=(fraction)1/1, format=(fourcc)YUY2, color-matrix=(string)sdtv, chroma-site=(string)mpeg2
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:sink: caps = video/x-raw-yuv, width=(int)640, height=(int)480, framerate=(fraction)30/1, pixel-aspect-ratio=(fraction)1/1, format=(fourcc)YUY2, color-matrix=(string)sdtv, chroma-site=(string)mpeg2
/GstPipeline:pipeline0/GstFFMpegCsp:ffmpegcsp0.GstPad:src: caps = video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)640, height=(int)480, framerate=(fraction)30/1, pixel-aspect-ratio=(fraction)1/1
/GstPipeline:pipeline0/GstFFMpegCsp:ffmpegcsp0.GstPad:sink: caps = video/x-raw-yuv, width=(int)640, height=(int)480, framerate=(fraction)30/1, pixel-aspect-ratio=(fraction)1/1, format=(fourcc)YUY2, color-matrix=(string)sdtv, chroma-site=(string)mpeg2
/GstPipeline:pipeline0/GstXImageSink:ximagesink0.GstPad:sink: caps = video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)640, height=(int)480, framerate=(fraction)30/1, pixel-aspect-ratio=(fraction)1/1
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
ERROR: from element /GstPipeline:pipeline0/GstXImageSink:ximagesink0: Output window was closed
...

Here you see the source element (videotestsrc) delivers video in yuv format.
The ffmpegcolorspace elements receives video in yuv format (sink), but sends it out in rgb format (src).

Ok, simple enough (once you gets the hang of it).
Now to the point of this whole blogspost...

How to tell what formats (capabilities) are supported of any given source element:

Ok, so gstreamer is a powerful thing, and it's error messages are actually understandable, so you know where go and fix it when it breaks.

First up, as stated before, it needs to be connected and running before you actually know this!

gst-launch-0.10 v4l2src device=/dev/video0 ! video/x-raw-yuv,width=640,height=480,format=\(fourcc\)I420 ! appsink

I'm using a webcam (uvcvideo), that is connected as /dev/video0.

Set the environment variable GST_DEBUG:
export GST_DEBUG=v4l2src:5

You should ofcource replace v4l2src with the element name of your source!

Next, make your terminal windows BIG, and run your pipeline as above.
If you're connected to another device slow a slow line (like serial), I suggest piping the output to a file using "2>".

Now, I'm not going to show your the entire output of this, but somewhere in there, there's this (and alot more like it):
...
0:00:00.137710333 [334m30105 [00m  0x8c05120 [36mDEBUG   [00m [00m             v4l2src gstv4l2src.c:450:gst_v4l2src_negotiate: [00m thiscaps: video/x-raw-yuv, format=(fourcc)YUY2, width=(int)1600, height=(int)1200, interlaced=(boolean)false, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 6/1 }; video/x-raw-yuv, format=(fourcc)YUY2, width=(int)1280, height=(int)960, interlaced=(boolean)false, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 8/1 }; video/x-raw-yuv, format=(fourcc)YUY2, width=(int)1024, height=(int)768, interlaced=(boolean)false, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 30/1 }; video/x-raw-yuv, format=(fourcc)YUY2, width=(int)800, height=(int)600, interlaced=(boolean)false, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 20/1 }; video/x-raw-yuv, format=(fourcc)YUY2, width=(int)640, height=(int)480, interlaced=(boolean)false, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 30/1 }; video/x-raw-yuv, format=(fourcc)YUY2, width=(int)352, height=(int)288, interlaced=(boolean)false, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 30/1 };
...

These are the actual supported formats from the camera!
Note: That before this it may print all the capabilities it think it supports (which is nothing worth really)!

You can also read what formats are used from this log, just look a little lower in the log.

There's also the official gstreamer documentation, which is worth reading:
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/gst-running.html

tirsdag den 2. oktober 2012

downloading video's from dr.dk

Intro

Some time ago I was contacted by my sister, who lives in Canada, with a request.
She would like to show her kids some danish cartoons.
Quite a lot of these can actually be streamed for free in Denmark  because they are made by Danmarks Radio (DR), and are paid for by TV-tax/media-license in Denmark that nearly everyone has to pay.

It's not really the topic of the entry to explain it, but it shot it goes a little like this:
  • Do you own a tv (does not matter if it's connected)? if yes: PAY
  • Do you own a cellphone with WAP (or a smartphone)? if yes: PAY
  • Do you have access to the internet? if yes: PAY
  • Do you live in a cave, with no friends, no real life? if so: You don't have to pay
    • Exception(s):
      • Do you own a radio? if yes: PAY
Ok, I'm being mean here, and I am actually gladly paying 2200 dkr. pr year (thats 380$ or 295€), because they make some good commercial free TV and radio programs.

You talked about downloading tv-shows, and now you're talking about fee's and taxes?
Yes, sorry.

The thing is that DR is forced, like many others, to only display their content to citizens in Denmark.
Since I live in Denmark I thought I'd just download those shows, and share them with her. Problem solved.

And here is (finally) how I did it.

How DR streams it's media

First up, the link to DR's TV-library is here: http://dr.dk/tv

If you are outside of DK, you might not see all the content.
They too, are using Geo IP'ing - if you want to overcome this, use VPN, or get the direct link to the media-content (or do both for best performance - at least I sometimes have problems streaming netflix movies from the US over VPN (Overplay)).
On a side-note: Yeah. netflix is FINALLY coming to Denmark in October, THANK YOU (and only days after that HBO said they would offer something for the european nordic market as well). Suddenly thay all seem to want to catch up. I just hope it's not overpriced, and a subset of the US version (which I sadly kinda know it will be already).

DR finally uses a flash player (before they used a crappy Windows mediaplayer plugin), so now everyone (windows, mac and linux) can join in and see what they paid for. Sadly this also makes it a little more troublesome to get the direct link.

I've found a show that needs downloding (another request):
and clicking on the show, brings up the player:
and it is indeed flash.


Getting the media link(s)

I've tried several of the downloadhelpers / youtube downloaders but none of them seem to be able to find the links for the media.
Luckily there are other ways.

Using info the the player

The player has a built-in console, you can start by pressing ctrl-k.
It should look something like this:

You need to be very fast on the keys, because it only prints the information in the beginning, and the flash element needs to have focus first (if one could introduce a delay between the page loading and the media starting it would be very helpful).
On the above screenshot, I only got the last lines, but it's enough.

Strike that. Each time it buffers, it prints the info again (see the timestamp):

You'll need the info, so keep it open.

Using the source-code

If you can't get to the console, you can read the info from the site source code + javescript codes sent back and fourth.

You need yourself a proper browser (firefox with firebug, or chrome). Because we need to see what the javascripts are sending back and forth.
Turn on firebug in firefox, or developer tools in chrome to start.
Now open/reload the media link.

In the source code, look for a "rtmp://" link: rtmp://vod-prio2.gss.dr.dk:

In the botton pane, go to Network.
I found the request in there somewhere; can't remember how exactly anymore (and maybe they changed it :-/)

Update: Just search for it

A commenter just noted that you can just search for it, from dr.dk's serach box.
Just include "rtmp" as a search keyword.

This finds a ressourceId page in the search results, with all the relevant information.
Here an example (http://www.dr.dk/handlers/GetResource.ashx?id=1320340):
{"resourceId":1320340,"name":"Forbrydelsen III (9:10) Synstolkning","mediaType":"Video","restrictedToDenmark":false,"downloadable":false,"geofilterId":0,"publish":null,"expire":null,"links":[{"qualityId":3416809,"uri":"rtmp:\/\/vod.dr.dk\/cms\/mp4:CMS\/Resources\/dr.dk\/NETTV\/DR1\/2012\/11\/12642391-87bf-4dee-b35d-5fec187a3cdd\/Forbrydelsen-III--9-10--Synsto_5c68a152fa1b441eb23c932307e9f943.mp4?ID=1320340","linkType":"Streaming","fileType":"mp4","bitrateKbps":1127,"width":854,"height":480},{"qualityId":3416810,"uri":"rtmp:\/\/vod.dr.dk\/cms\/mp4:CMS\/Resources\/dr.dk\/NETTV\/DR1\/2012\/11\/12642391-87bf-4dee-b35d-5fec187a3cdd\/Forbrydelsen-III--9-10--Synsto_5c68a152fa1b441eb23c932307e9f943_1.mp4?ID=1320340","linkType":"Streaming","fileType":"mp4","bitrateKbps":562,"width":640,"height":360},{"qualityId":3416811,"uri":"rtmp:\/\/vod.dr.dk\/cms\/mp4:CMS\/Resources\/dr.dk\/NETTV\/DR1\/2012\/11\/12642391-87bf-4dee-b35d-5fec187a3cdd\/Forbrydelsen-III--9-10--Synsto_5c68a152fa1b441eb23c932307e9f943_2.mp4?ID=1320340","linkType":"Streaming","fileType":"mp4","bitrateKbps":248,"width":416,"height":234},{"qualityId":3416812,"uri":"rtmp:\/\/vod.dr.dk\/cms\/mp4:CMS\/Resources\/dr.dk\/NETTV\/DR1\/2012\/11\/12642391-87bf-4dee-b35d-5fec187a3cdd\/Forbrydelsen-III--9-10--Synsto_5c68a152fa1b441eb23c932307e9f943_3.mp4?ID=1320340","linkType":"Streaming","fileType":"mp4","bitrateKbps":122,"width":416,"height":234}],"chapters":[],"productionNumber":null,"postingGuid":"{b4fa025e-b022-44f2-8df7-03624df6f889}","images":[],"durationInMilliseconds":3525000,"site":null,"broadcastType":"Program","runningOrder":null,"postingTitle":null,"postingTeaser":null}
This shows all the needed info.
Thanks for the update. It is much easier then the ways I found.
Hopefully. they'll keep indexing these GetResource pages :-)

Downloading the video


Using linux/rtmpdump


Next we need a linux machine, or at least rtmpdump:


I've already installed rtmpdump, so in the above, I just run it.
The parameters are:
  • -r  rtmp://vod-prio2.gss.dr.dk/cms
    • This is the server address or url
  • -y mp4:CMS/Resources/dr.dk/NETTV/DR2/2012/09/44dbf1d8-4af3-42f4-8b08-92932922e4c7/aa7a95ca4dc641dcae6be4cd63817ed2_564.mp4?ID=1237625
    • this is the actual stream
  • -o test.mp4
    • This is the desired output filename, in this case test.mp4. Select wantever you want.
  • -V
    • this is optional, and gives you debugging output. Very useful, if it dosen't work.
In the console output above, the -r and -y options are mashed together, but from my example you should be able to see where to spilt it.


It's then start downloading the media...
Once done, it will return you to the prompt again, saying "download complete".

Using windows/vlc

Sorry. I can't find a way to set the playpath in vlc.

What the hell happend to blogspot?

Hmm... long time no see, and I see that blogspot has gotten a new name, design and even decided to rename the address of my blog.

Thanks for doing something I did not ask for, or want :-(

Well to be fair, the old address still works, but it now redirects.
The new design is ok, and who am I to stand in the way of progress (after all I don't use it very often)?
The new name is perhaps the worst of the three. blogger.... what was wrong with blogspot? I liked it.

Ok, I sound like an old man, which I am not, so I', just going to shut up, and move on to what I really needed/wanted to do here.... write something useful for other people, and my own reference.


torsdag den 26. maj 2011

Visual Studio (2008) windows forms - c++ - tab order

So, since I've changed jobs I'm now stuck in VS2008.

And let me clarify something:
I HATE IT!

It is worlds from eclipse which I used before, and in most respects I mean this in a bad way.
The UI is littered with menu/options that don't work, in one view or another.
The dialog boxes (even though they are named the same) change function wether you're running an application or not, or if you've open a specific view/explorer.

To make matters worse, I'm tasked with maintaining an application written in C++ and winforms.
Don't get me wrong here; I like C++, and have worked with it for over 5 years, building linux apps and Qt GUI's.

Take the simple task of defining the tab order in a form; its a complete pain.
I googled the topic, because (as usual) I could not find a option for it in VS.
I found this on msdn: How to: Set the Tab Order on Windows Forms
But surprise, surprise, IT DOES NOT WORK!
I don't have the options/views; Absolutely nowhere can I find "Tab Order".
Designer view? Nope stuck in code view as well, but that's another story.

All hope is not lost though.
Open a file browser, navigate to the .rc file that contains your dialog, or other gui element, and open it using notepad++ or some other editor.

Here's the interresting piece of code from the file I'm working:

/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_SIGNIN DIALOG  0, 0, 210, 122
STYLE DS_SETFONT | WS_POPUP | WS_BORDER | WS_SYSMENU
FONT 10, "Microsoft Sans Serif"
BEGIN
    LTEXT           "Indtast Medarbejdernummer",IDC_LBL_LOGINNUMBER,68,18,135,13
    EDITTEXT        IDC_EDB_LOGINNUMBER,68,35,113,12,ES_AUTOHSCROLL | ES_NUMBER
    LTEXT           "Indtast Loginkode",IDC_LBL_LOGINCODE,67,53,136,13
    EDITTEXT        IDC_EDB_LOGINCODE,67,70,113,12,ES_PASSWORD | ES_AUTOHSCROLL | ES_NUMBER
END

There are two Labels (LTEXT), and two Editable text input boxes (EDITTEXT).
Tab order is determined by the order they are listed, so if I wanted to change it, I would simply change the order in which they are listed.
Just note that elements that does not take focus will be skipped, so the two labels does not affect the tab order.
Default focus is the first element in the list that takes focus.

Now save the file, and you're done.

Oh, and watch what happens to VS when it gets focus again.
It says the file has changed, and if you wish to reload it.
If you press "yes" here VS will stop working and get restarted by windows.



How to: Set the Tab Order on Windows Forms

søndag den 6. marts 2011

Linux: Running a command/script after resuming from sleep

I've got myself a Asus Eee Top 1602, which I really want to run linux (gentoo) on.

I've got most of the stuff on it working, both the touchscreen, audio and wifi.

There are two issues left:
 * The volume keys on the front don't work, and
 * after I resume from suspend, the display is dimmed to something like 50%.

Previous issues have been:
 * Getting the wifi to work, and
 * Getting the wifi to work after resume.

Things I haven't looked at yet:
 * Memory card reader

Let me just give the some info to the eee top 1602:
 # lspci
00:00.0 Host bridge: Intel Corporation Mobile 945GME Express Memory Controller Hub (rev 03)
00:02.0 VGA compatible controller: Intel Corporation Mobile 945GME Express Integrated Graphics Controller (rev 03)
00:02.1 Display controller: Intel Corporation Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller (rev 03)
00:1b.0 Audio device: Intel Corporation 82801G (ICH7 Family) High Definition Audio Controller (rev 02)
00:1c.0 PCI bridge: Intel Corporation 82801G (ICH7 Family) PCI Express Port 1 (rev 02)
00:1c.1 PCI bridge: Intel Corporation 82801G (ICH7 Family) PCI Express Port 2 (rev 02)
00:1c.3 PCI bridge: Intel Corporation 82801G (ICH7 Family) PCI Express Port 4 (rev 02)
00:1d.0 USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI Controller #1 (rev 02)
00:1d.1 USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI Controller #2 (rev 02)
00:1d.2 USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI Controller #3 (rev 02)
00:1d.3 USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI Controller #4 (rev 02)
00:1d.7 USB Controller: Intel Corporation 82801G (ICH7 Family) USB2 EHCI Controller (rev 02)
00:1e.0 PCI bridge: Intel Corporation 82801 Mobile PCI Bridge (rev e2)
00:1f.0 ISA bridge: Intel Corporation 82801GBM (ICH7-M) LPC Interface Bridge (rev 02)
00:1f.2 IDE interface: Intel Corporation 82801GBM/GHM (ICH7 Family) SATA IDE Controller (rev 02)
00:1f.3 SMBus: Intel Corporation 82801G (ICH7 Family) SMBus Controller (rev 02)
01:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller (rev 02)
02:00.0 Network controller: RaLink RT2860
# lsusb
Bus 001 Device 005: ID 0bda:0158 Realtek Semiconductor Corp. Mass Storage Device
Bus 001 Device 006: ID 0458:7063 KYE Systems Corp. (Mouse Systems)
Bus 001 Device 003: ID 05e3:0608 Genesys Logic, Inc. USB-2.0 4-Port HUB
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 005 Device 002: ID 1bfd:1688 TouchPack Resistive Touch Screen
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 002: ID 04f2:0402 Chicony Electronics Co., Ltd
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub


Getting wifi to work
I'm using the staging driver in the kernel.
It's under: Device Drivers -> Staging drivers ->  Ralink 2860/3090 wireless support
You can compile it as a module or built it into the kernel, it dosen't matter.
What matters, is that you go go Ralink's website, and download the firmware file rt2860.bin, otherwise you'll just get something like this in dmesg when you "up" the wifi:
eeeTop kernel: [ 1321.424360] rt2860 0000:02:00.0: firmware file rt2860.bin request failed (-2)
eeeTop kernel: [ 1321.424378] ERROR! NICLoadFirmware failed, Status[=0x00000001]
eeeTop kernel: [ 1321.424397] rt28xx Initialized fail!

You'll find that here: http://www.ralinktech.com/support.php?s=2 and you'll need to get the PCI firmware of course.
Download that, extract, and place it under /lib/firmware (you might have to create the directory).

After this, I just emerged wpa_supplicant, and I'm able to connect to my wifi (WPA2 protected).

Getting wifi to work after resume
I found out that after the machine has been put in suspend, and reawaken, the wifi does work reconnect.
wpa_supplicant still reports the wifi as connected (with an IP adress and all that, but there's no connection).
I've read some people have some success by disabling some kernel options (specifically wireless extensions), but that  did not work for me.
Instead 'm just restarting the wifi after the machine resumes.
First I thought of using acpid, but I could not find see that that reports any suspend/resume events.
Anyway acpi is old, and maybe deprecated, now with hal (which is also deprecated) and policykit/consolekit, the last one being the future.
I've moved the system completely over to consolekit/policykit, and it work 100% now. (power management, shutdown, suspend, hibernate). But how to migrate was not that well documented, but thats a different story.

I found the solution to be pm-utils.
Even though it is written for HAL, it seems to work for consolekit as well.
Best of all, it is very easy to setup.
Under /etc/pm/ you'll find the configuration.

Under /etc/pm/sleep.d/ I just made a new file 50wifi, and put this in it:
#!/bin/bash
case $1 in
   hibernate)
       echo "Hibernating"
       ;;
   suspend)
       echo "Suspending"
       ;;
   thaw)
       echo "Returning from hibernation"
       /etc/init.d/net.wlan0 restart
       ;;
   resume)
       echo "Returning from suspend"
       /etc/init.d/net.wlan0 restart
       ;;
esac

Next, just make the file executable:
# chmod +x /etc/pm/sleep.d/50wifi

And thats it.
Now, every time the computer comes back from suspend or hibernation it restarts my wireless, and my connection is back within seconds.

I might update the blog, once I the re two remaining issues resolved.
I can live without the volume keys, but the dimmed display really needs to be fixed.

tirsdag den 15. februar 2011

Mini-itx cases, why is it so hard to find one that fits your needs?

Ok, so I've bought myself a new computer, this is going to be my "master" computer (which includes some gaming), and since I'm a little nuts I've decided that it should be as small as possible.
This means mini-itx!

However, it's not much fun having a high performance pc, and use on-board graphics, since these chips are usually only good for 2D and very light 3D.
So I also need room for a PCI-e graphics card and hence a somewhat powerful power-supply.

Lets just look at the PSU for a moment.
I'm using a Intel core i5-2500K and a Intel DH67CF motherbaord, spec'ed with 8 gb of kingston ram, with this I'm using a Consair P128 SSD.
This means a power draw between 35 and 130 watts.

None of the cases I've seen comes with a PSU thats near powerful enough (typically they're around 60W), but bying a picoPSU-150-XT would do the trick.

Now, what happens when I add a graphics card?
Ouch!
Here, no small PSU can be of any help :-(

This is especially true, when the card I'm going to use (for the moment) is a nVidia 8800GTS, which usesalot of power in idle, and much more when under load.
I really don't want to add ~100 watts to this system, since:
  1. It'll add another fan with all the noise thats brings.
  2. More heat, and I really don't want this in a small case.
  3. My energy bill will be much higher.

Well, for me, only one solution comes to mind. Plug in the graphics card when I want to do serious gaming, and leave it disconnected for my everyday computer-use.

I don't game that much. I do some programming, and gimp'ing, but the built-in Intel HD3000 graphics can handle this just fine.

Offtopic: Taking of power, did you know that most power-supplies are most effective at around 80% load?

So a picoPSU-150-XT for everyday use, and something else for gaming, or maybe just use a silverstone ST45SF PSU for it all.

If these where my only requirements for a case I would be fine, because there are lots of (mostly square) boxes that uses SFX PSU's and has room for a dual PCI-e card.

The problem is, that I really want a slim desktop case that sits under my monitor.
Now, by slim I mean less then 70mm!

I started my search at mini-itx.com/store, but found no cases that were up to the task.
So what candidates have I found?

Gigabyte
Gigabyte makes a series thats called MIB, I like the MIB T5142. Here are some images:

Now, I didn't notice this at first, but look at the last picture (of the back). Look how the motherboard is placed. Where is the PCI-e connector placed?
Thats right, all the way to the right, right next to the case edge (and no riser card/extension calbe I've found can reach).
Ok, there's no slot for the graphics card either, but I own a dremel, so thats no problem. I've cut these kinds of holes before.

I like the design, and the idea that the monitor is a part of it.
There is also ample room inside for a bigger power supply, harddrive and cdrom.
These cases are (WxDxH): 445 x 250 x 65  mm

Unfortunately, the MIB T5142 is not sold in eurupe, only the T5140:

But I don't like the front.
If I wanted this, I would move the motherboard to the left so a normal angled riser card would do the trick.

Then I found the Jetway JC-110-B:


I don't think it is as pretty, but it has the motherboard in the right place, and it's much smaller.
In fact, it's only (WxDxH): 300 x 273 x 65  mm
Jetway also makes two other models with the same sizes, but different fronts.
The jetway cases comes with a set of brackets to mount the case under your table or on the wall, which I think is a plus, because the case is too small for my monitor stand to fit on top of it.
On the down side, there's no audio port the the front/sides.

Silverstone cases:
There's the LC09:

It's 346 mm (W) x 55 mm (H) x 310 mm (D).
It has audio/usb in the side, and the motherboard in the right place, but I don't like the how the top plate looks. Why does it have to stick out over the rest of the case like that?
Also, given it's only 55mm high, I might not be able to fit the SFX PSU in there...
Oh, and lastly, the expansion port is only 1, which might not work with the dual design of the 8800GTS I have.

Then, there's the LC05:
Which is 346 mm (W) x 55 mm (H) x 300 mm (D).
But there's no expansion port(s), and the motherboard is placed wrong, like the MIB T5140/2.

Lastly there's the LC19:
It is 390 mm (W) x 68 mm (H) x 348 mm (D), and also available in black.
It's so large it can take a microATX motherboard.
There's audio, usb and card reader in the front (under the cover).
My only problem with this is, that it's deep. Almost 35 cm!

G-Atlantic
The GA620iBK-P4:

(with wall mount)


There are 3 different fronts for the case, the above in model A, which I quite like.
It's 300 (W) x 65 (H) x 273 (D) and comes with a 120W PSU (so I might not need the picoPSU)

There's also the GA630iBK-P4, which as far as I can are the same, but with a curved front:

or if you don't need the expansion ports, but want a smaller case, go with the GA688iBK-P4:

at only 220 (W)  x 65 (H) x 305 (D) mm


Casetronic
There's the c137:

 and the c158:

For info, see the chart below.
I think the finish is nice, but very industrial.
The c158 is just 54mm high, which might be a problem.

Here all info in a nice chart:

manufacture model h w d psu (w) cdrom exp fa fu cr type tag
gigabyte mib t5142 65 445 250 65 normal 0 y y n Mini-itx -eu
gigabyte mib t5140 65 445 250 65 normal 0 y y n Mini-itx
jetway  JC-110-B 65 300 273 100 slim 2 n y n Mini-itx
silverstone lc19 68 390 348 120 slim 1 y y y Micro-atx
silverstone lc05 55 346 300 60 normal 0 y y n Mini-itx
silverstone lc09 55 346 310 60 slim 1 y y n Mini-itx
Morex  2799 p4 64 295 288 150 slim 2 y y n Mini-itx ugly
Coolermaster Elite 100  70 262 318 150 slim 0 y y n Micro-atx
Casetronic c137 69 323 254 120 slim 2 n n n Mini-itx
Casetronic c158 54 305 279 120 slim 2 y y cf Mini-itx
G-alantic GA620iBK-P4 65 300 273 120 slim 2 n y n Mini-itx
h = height (mm)
w = width (mm)
d = depth (mm)
exp = full height expansion ports/brackets
fa = front audio jacket
fu = front usb port(s)
cr = card reader

The table became a little less readable because blogspot cropped the last text, so I had to shorten the whole table.


There are many others, but some simply look too flimsy, or are to high.
Search ebay for "mini-itx cases" and be inspired :-)

Other manufactures that makes products that almost fit my needs:
Evercase
Morex
Thermaltake
InWin
Chenbro


So, as it turns out, it isn't hard at all, your just need to know where to look.

I going with a G-Alantic GA6?0iBK-P4 or one of the casetronic's, as they look nice, has the size I'm going for, has a decent power supply I can use for everyday use, has the expansion port(s) I need.

Good hunting.

lørdag den 29. maj 2010

Getting your multimedia keys/remote control to work under X11 - by hacking your kernel

Right, so I have a media center (who doesn`t these days), and ofcourse a remote control for it.
My problem is, that I`ve got a Logitech ultraX media remote.
It is a nice remote, but only some of of the keys on the remote works out of the box
Heres the story of how I got all of my keys working.


The underlying problem
The underlying problem to all of this is that X11 does not support more then 255 different keys.
This is fine for most purposes, but not many media keys are included in these 255 keys.
Meny (if not all) common keys are mapped with a low keycode (range 0 to 200 (like letters and numbers), but many specialized meida keys are mapped much higher.

Testing to see if your keys really are dead in X
The first thing I did when trying to get the keys working, was running xev, which tells me if X recieves the input (key press in my case), and what that input is mapped to.
The problem was, that xev didn`t recieve any input from the buttons that did not work.
If your key press is detected in xev, this guide is NOT for you!
This guide is for getting your keys to register in X (xev)!

Solutions/Remedies for the problem?
After googling a bit I quickly found a MultimediaKeys guide on the gentoo-wiki.com site, which suggested running "showkey" from a real console (to open a real console hit alt-ctrl-f1).
When doing so, it registered my input, and showed a corrosponding keycode, but no scancode.
Output from showkey, when pressing some of the non-working keys in X (subtitle, language, dvd, music and repeat keys on the remote were pressed here):
showkey
kb mode was UNICODE
[ if you are trying this under X, it might not work
since the X server is also reading /dev/console ]

press any key (program terminates 10s after last keypress)...
keycode 28 release
keycode 370 press
keycode 370 release
keycode 368 press
keycode 368 release
keycode 389 press
keycode 389 release
keycode 391 press
keycode 391 release
keycode 129 press
keycode 129 release
The first line above (keycode 28 release) is the enter key being released (after executing the command).

I didn`t note it at the time, but the buttons that worked had keycodes lower then 255, and those that did not had keycodes higher then 255.
TAKE NOTE OF THIS, IT IS IMPORTANT!

So, first I thought it was because the input did not generate any scancodes (showkey -s shows generated scancodes, and showkey -k shows generated keycodes) - (but none of the keys do, and some of them work), so that wasn`t it.
So I hacked around a bit to generate some fake scancodes, but this was/is a dead end, and is not needed.

Using keytouch
The gentoo wiki guide suggested using a application called "keytouch" to get the keys working.
The keytouch application is used as a system service, and translates keycodes higher then 255 to lower keycodes, or it can map key presses directly to program commands.
I`ve tried keytouch; When starting the service (you can only do this after you`ve selected a keyboard/remote or created your own), I get this output (which means it does not work):
* Service keytouch starting
keytouch-init: Failed to set keycode:
keycode 148 to scancode -57260 (0xffff2054)
keytouch-init: Failed to set keycode:
keycode 149 to scancode -57260 (0xffff2054)
keytouch-init: Failed to set keycode:
keycode 202 to scancode -57260 (0xffff2054)
keytouch-init: Failed to set keycode:
keycode 203 to scancode -57260 (0xffff2054)
keytouch-init: Failed to set keycode:
keycode 227 to scancode -57260 (0xffff2054)
keytouch-init: Failed to set keycode:
keycode 141 to scancode -57260 (0xffff2054)
keytouch-init: Failed to set keycode:
keycode 225 to scancode 786 (0x312)
keytouch-init: Failed to set keycode:
keycode 224 to scancode 786 (0x312)
keytouch-init: Failed to set keycode:
keycode 231 to scancode -57260 (0xffff2054)
keytouch-init: Failed to set keycode:
keycode 124 to scancode -57260 (0xffff2054)
keytouch-init: Failed to set keycode:
keycode 235 to scancode -57260 (0xffff2054)
keytouch-init: Failed to set keycode:
keycode 219 to scancode 786 (0x312)
keytouch-init: Failed to set keycode:
keycode 147 to scancode -57260 (0xffff2054)
keytouch-init: Failed to set keycode:
keycode 129 to scancode -57260 (0xffff2054)
* Service keytouch started
So, no luck there :-(

Alternate solution - hacking the kernel
I figured the easiest way would then be to just change the mapping of the non-working keys to a lower keycode, this way I also don`t need yet another system service running, and I really want as few of those as possible (both to reduce system boot time, and to conserve system ressources).
The next step requires compiling your own kernel.
If you don`t know how, read the documentation for your distro (it's not covered here).
I`m running gentoo linux on all of my systems, so I`m quite comfortable compiling my own kernel, so heres what you need to do, once you know how (and has otherwise configured your kernel correctly for your own system).

Determine what keycodes needs to be remapped
Run showkey from a real console (as described above), and write down all the keycodes for the keys that does not work.
Note: showkey shows the keycodes in decimal form, and later you`ll need them in hex, so you may want to convert the numbers as you write them down.
For instance, take the Subtitle key from the showkey output above, it has a keycode of 370 in decimal, and thus becomes 0x172 in hex.

Remap the keys
Now edit /usr/src/linux/include/linux/input.h
In this file you will find all the defines for the keycodes that the linux kernel can generate.
Now, search for the keycodes you`ve noted down (remember to search for the converted hex numbers).
Once you have found a #define match, change the value to something lower then 248 (Range 248 - 255 is reserved for special needs of AT keyboard driver acording to a comment in input.h) - (you don`t have to write the value down in hex, you can write it in decimal if you want).
You`ll be remapping your keys to a keycode that most likely is already used, and the system won`t know the difference between these, so think about how you remap!

For the subtitle example, here the relevant part of input.h (lines 472 to 477):
#define KEY_LANGUAGE 0x170
#define KEY_TITLE 0x171
#define KEY_SUBTITLE 0x172
#define KEY_ANGLE 0x173
#define KEY_ZOOM 0x174
#define KEY_MODE 0x175
I`v changed the value of KEY_SUBTITLE to 183.
This means that the susbtitle button will ack like the F13 key (because it has a keycode value of 183) - (which I don`t have on my keyboard, and don`t use - since I have never heard of it).
You can also remap them directly to something else, like the arrow keys, if you know how you are going to use them.
For instance if you are going to use them in mythtv, or some other application where you`ll need s, m or any other key, this might be simpler, however it does not give you as much control over your keys as they will always ack like and s or a m.

I`ve remapped every key on the remote having a higher keycode then 255, to something else f14,f15...f24 and others.

Save, recompile and reboot
Once done, save input.h, and recompile your kernel (do a make clean first, to ensure the new values are used).
Now install your new kernel and reboot.

Testing if it works
Once rebooted, start X, fire up xev, and viola, all your keys now work (as whatever you remapped them to).


Why the 255 limit?
Q: So why does X only allow for 255 keys?
A: I don`t know!
The X11 protocol was released in 1985, and they properly didn`t think it was an issue.
The problem shound be fixed in X12, but no-one really knows when this is comming out.

Are there any drawbacks?
Yep, sure:
  • One drawback to this is that you can`t use one key to create keycombo`s.
  • Every time you update to a new kernel, you`ll have to patch it with your own remapped values.

Any suggestions?
I suggest remapping to the f13...f24 keys, and then let mythtv, xbmc or xmodmap remap the keys from there, as it gives you more control, and the abillity to make key combinations (keycombo`s).

References