December 20, 2005

Glade, GTK, Ruby & uClibC




GTK Widgets


Originally uploaded by crafterm.

Following my previous post regarding building a uClibC based Linux system, we'll now look at building a graphical environment suitable for constructing applications that interact with the user.

Quite often no interactivity other than services or web applications are required for embedded devices (eg. DSL boxes and the like), but this is not always the case (eg. when deploying to real computers or constructing live CD's, etc).

For this, I've been experimenting with getting GTK+ running under DirectFB. This has been the approach of the Debian Installer crew over the past few years who have been working on a graphical installer for the Debian project.

DirectFB can run on any VESA compliant video card. There's also some accelerated drivers for particular video cards as well that utilise video hardware for rendering, etc. Since DirectFB runs directly by interfacing with the kernel and doesn't have a networking protocol like X11 amongst other things it can be quite fast.

The Debian installer crew have been using GTK+ 2.0.9 as their toolkit, with some GDK DirectFB patches to allow rendering of widgets onto the framebuffer device. The advantage of this is that there's no need to pack an X11 server (or a need to configure) along with the resultant root filesystem.

There's been some recent activity surrounding getting GTK+ 2.8.3 (ie. the latest GTK+ version) up and running on DirectFB, and this has been the version I've been experimenting with. The image above shows the gtk-demo program running under VMware from a ramdisk that has GTK+ 2.8.3 rendering on a frame buffer.

There's some instructions about how to build GTK+ 2.8.3 in a DirectFB environment available from the DirectFB Wiki. It also includes information about the dependencies that are required such as glib, pkg-config, pango, cairo (with dfb patches), gtk+ (with dfb patches), etc.

The great thing about GTK+ is that it's also themeable with different rendering engines so you can make it look like many different windowing system or give it it's own look and feel.

Also, there's a lot of nice tool support surrounding it.

For example, Glade, the Gnome User Interface Builder, allows you to build GUI's graphically which can then be integrated into your application via generated C/C++ code, or via libglade, which can interpret a Glade definition file (XML) at runtime and create the resultant GUI.

To make things easier, there's even bindings for most popular scripting languages so that you don't have to enter the world of C/C++ to do the dirty work of UI coding. The Debian team have been using the python bindings, but I've been experimenting with the Ruby GTK+ and Glade bindings, which let you script the GUI using Ruby'ism such as blocks, etc.

eg. a simple Ruby script to display a Glade generated GUI:

#/usr/bin/env ruby
require 'libglade2'
def gtk_main_quit puts "Quitting Application" Gtk.main_quit end
Gtk.init
GladeXML.new("mygladeUI.glade") { |handler| method(handler) }
Gtk.main

This simply shows the GUI created within Glade, saved as XML, and handles the gtk_main_quit signal which in my example was a handler name connected to the action of a button.

All in all, all of these tools work fine with uClibC and buildroot, and Glade/GTK/etc provide a very easy way to prototype and use GUI's from C/C++ or your favourite scripting language.

Awesome tools! :)

Posted by crafterm at 01:46 PM | Comments (0) | TrackBack

December 19, 2005

uClibC linux buildroot!




uClibC Configuration


Originally uploaded by crafterm.



Recently I've been building a small Linux distribution based on the uClibC buildroot environment.



uClibC is a C library implementation, designed for embedded and/or small systems that have low resource footprint. uClibC buildroot is a build environment surrounding uClibC for constructing a fully deployable Linux installation to such devices, including the construction of a cross compiling toolchain (so you can build arm, i386, mips, etc binaries from your desktop machine), the skeleton root filesystem with all of the usual paths /bin, /dev, /usr, /var, /tmp, etc, and a package build infrastructure for building applications to run under this environment (eg. networking services or end user applications).



The whole buildroot environment comes with a configuration package similar to the Linux kernel's 'make menuconfig' environment where you can select the toolchain you'd like to use (eg. gcc/binutils/gdb versions, etc), and the packages you'd like built (eg. openssh, tinyx, etc). See the above screen capture for an example.



The build infrastructure then downloads and compiles your toolchain first (ie. cross compiling compiler, linker, assembler, debugger, etc) directly from gnu.org. It then downloads each package that you've selected (adhering to dependencies) from it's remote download area (eg. sourceforge, or the projects home site) and builds it using your cross compiling toolchain, and installs it into a root filesystem area which is later compressed via cramfs, ext3fs, or another format, to be used as your root Linux filesystem with a kernel image.



In our case I'm targeting i386 systems so I also have the added advantage of being able to chroot into the target filesystem before it's compressed and perform extra builds inside of the target as if it was running on the real device, and this has been a real saviour as things like libtool and pkg-config can cause issues with cross compiling environments and linking.



Once you've got your root filesystem built, you can download the Linux kernel sources and create a kernel image using the Linux 'make bzImage' target. Then using a bootloader like Grub - you're all set to boot your kernel and mount your image as the kernel's root filesystem.

Posted by crafterm at 03:55 PM | Comments (0) | TrackBack

December 16, 2005

/proc/cmdline

Ever wanted to see what the command line was passed to the Linux kernel upon boot:

$> cat /proc/cmdline
root=/dev/hdb1 ro spash=silent $>

Cool :)

Posted by crafterm at 04:05 PM | Comments (0) | TrackBack

December 15, 2005

Changing GTK+ settings when in a non Gnome environment

From the FreeBSD Gnome FAQ:

How do I use GTK+ 2 resource settings for GTK+ 2 applications when not in a GNOME environment?

GNOME 2 applications get their GTK+ 2 resources from themes and the corresponding theme engine. If you would rather run your GTK+ 2 applications in a non-GNOME environment then you will need to create a file named ~/.gtkrc-2.0.

To use the widgets from a GTK+ 2 theme when in a non-GNOME environment, simply include the theme's gtk-2.0/gtkrc in your ~/.gtkrc-2.0. For example:

include "/usr/X11R6/share/themes/Crux/gtk-2.0/gtkrc"

If you prefer, you can use the same GTK+ 1.2 theme for both GTK+ 1.2 and GTK+ 2 applications, which will give your GTK+ programs a consistent look. For the most part, you can transfer your settings from your ~/.gtkrc file (used for GTK+ 1.2) with a couple of caveats.

If you have any theme engine references, you will have to make sure there is a corresponding GTK+ 2 theme engine. Otherwise, remove the engine entries.

The default font specification should be outside of any style blocks and should be specified with the gtk-font-name keyword. For example:

gtk-font-name = "Verdana 11"

Note that while a GTK+ 1.2 gtkrc file will work in a GTK+ 2 gtkrc-2.0 file, the opposite is not true: the contents of a GTK+ 2 gtkrc-2.0 file will not work inside a GTK+ 1.2 gtkrc file.

For simply switching GTK+ themes without needing to edit your ~/.gtkrc files, you can use the x11/gtk-theme-switch and x11/gtk2-theme-switch ports.

Posted by crafterm at 06:04 PM | Comments (0) | TrackBack

December 12, 2005

Converting BINS metadata to iPhoto

Before I used a Mac and photo management software like iPhoto, I simply had all of my images in hierarchy layout of directories in my /home/crafterm/images path, and used a great package like BINS to render my images to a website that I could upload to a server.

Bins-Site

BINS did a really good job and had some nice theming abilities, but since the rendering was done on my workstation, the site that was created was static and didn't have any interactive features like comments, view counts, favourites, etc.

One of the things I liked most about BINS was that it used XML to store all of it's meta data about each image (including extracted EXIF data as a backup), and there was a graphical tool for editing everything. I always thought, if I ever needed to get the data out of BINS, at least XML was going to let me do it.

Fast forward a few years, and this is exactly what happened. I ended up getting a Mac as my primary work machine, and this whole world of new multimedia applications opened up to me, particularly the free and bundled iLife suite of iPhoto, iTunes, iMovie, iDVD, Garageband, etc.

Also, Flickr captured a lot of the online photo publishing community with it's social, and interactive nature. So, like many others, I ended up getting a Flickr pro account, and started uploading using the Flickr export plugin from Connected Flow

The problem was essentially that after importing all of my images into iPhoto, all of the descriptions that I'd entered into BINS were missing. The data was there in the BINS XML files alongside each image, but as expected it wasn't in iPhoto.

So, I started prodding around with AppleScript and found out via the iPhoto AppleScript dictionary that it's possible to select an image inside the iPhoto library by filename, and assign a comment (amongst other things) to it.

I whacked together a script to do this:

-- Sets the comment of a particular image in iPhoto
-- Expects image title as first argument, and comment as second

on run argv
	set myTitle to item 1 of argv
	set myComment to item 2 of argv
	
	tell application "iPhoto"
		set comment of photos whose image filename is myTitle to myComment as text
	end tell
end run

This script must be invoked from the command line and it accepts two arguments, the first being the filename of the image, and the second being the comment you wish to set that image to.

You can invoke the script as follows:

$> osascript iPhotoCommentScript IMG_1234.JPG "My new fancy comment"

With this script, all that was needed now was the ability to iterate over the BINS XML files, extracting the image filename, and attributes such as the description, location (and perhaps other things later like people, and the other custom tags BINS let's you specify).

To do this I wrote a simple Ruby script:

#!/usr/bin/env ruby
#
# Given a directory of BINS image description files, read the description and location of
# each image, and pass this data on to iPhoto as the comment for that image.
#
# Currently reads all xml files in the current directory, skipping album.xml.

require "rexml/document"

files = Dir["*.xml"]

files.each { |file|
    next if file == "album.xml" # skip this since it's not an image
    
    xmlDoc = REXML::Document.new File.new(file)
    location = xmlDoc.root.elements["/image/description/field[@name='location']"]
    description = xmlDoc.root.elements["/image/description/field[@name='description']"]
    imagename = file.sub(/\.xml$/, "")

    location = location == nil ? "" : location.text.strip
    description = description == nil ? "" : description.text.strip

    comment = description

    if (location != "") 
      if (description == "")
        comment = location
      else
        comment += ", " + location
      end
    end
    
    system "osascript ~/Desktop/iPhotoSetComment.scpt #{imagename} \"#{comment}\""    
    puts "Updated description/location for image #{imagename}"
}

And that's it. All I needed to do was simply run the Ruby script in each directory of my BINS photo library hierarchy, to update each photo's corresponding comment in my iPhoto library.

Since BINS allows you to set extra meta data fields such as image location, (and others such as the names of people who were there, etc) the Ruby script combines the description and location into a single string. It's best to review the resultant string for grammar, etc if you'd ended your description with an exclamation mark or something. You might want to extend the Ruby script to extract the other fields and combine it into a more complete description string.

Also, even if you don't use BINS, the AppleScript script itself might be useful for merging data from other photo library formats.

Next step is to take the comment fields from iPhoto and write them into the EXIF tag of the files themselves so that they stay with the images where-ever they go. Once I find a Ruby library that lets you write EXIF meta-data I'll take a look into this as well.

Technorati Tags: , , , , ,

Posted by crafterm at 02:24 PM | Comments (0) | TrackBack

December 11, 2005

GNU C compiler and #define's

Ever wanted to know what hidden system #define variables have been set by the GNU C compiler every time a compile is done.

Try this:

$> cpp -E -dM /dev/null

On my OS X machine this results in:

#define __DBL_MIN_EXP__ (-1021)
#define __FLT_MIN__ 1.17549435e-38F
#define __CHAR_BIT__ 8
#define __WCHAR_MAX__ 2147483647
#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
#define __FLT_EVAL_METHOD__ 0
#define __DBL_MIN_10_EXP__ (-307)
#define __FINITE_MATH_ONLY__ 0
#define __GNUC_PATCHLEVEL__ 1
#define __SHRT_MAX__ 32767
#define __LDBL_MAX__ 1.79769313486231580793728971405301e+308L
#define __APPLE_CC__ 5247
#define __UINTMAX_TYPE__ long long unsigned int
#define __LDBL_MAX_EXP__ 1024
#define __SCHAR_MAX__ 127
#define __USER_LABEL_PREFIX__ _
#define __STDC_HOSTED__ 1
#define __LDBL_HAS_INFINITY__ 1
#define __DBL_DIG__ 15
#define __FLT_EPSILON__ 1.19209290e-7F
#define __LDBL_MIN__ 2.00416836000897277799610805135016e-292L
#define __ppc__ 1
#define __strong
#define __APPLE__ 1
#define __DECIMAL_DIG__ 33
#define __LDBL_HAS_QUIET_NAN__ 1
#define __DYNAMIC__ 1
#define __GNUC__ 4
#define __DBL_MAX__ 1.7976931348623157e+308
#define __weak
#define __DBL_MAX_EXP__ 1024
#define __LONG_LONG_MAX__ 9223372036854775807LL
#define __GXX_ABI_VERSION 1002
#define __FLT_MIN_EXP__ (-125)
#define __DBL_MIN__ 2.2250738585072014e-308
#define __DBL_HAS_QUIET_NAN__ 1
#define __REGISTER_PREFIX__
#define __NO_INLINE__ 1
#define _ARCH_PPC 1
#define __FLT_MANT_DIG__ 24
#define __VERSION__ "4.0.1 (Apple Computer, Inc. build 5247)"
#define __BIG_ENDIAN__ 1
#define __SIZE_TYPE__ long unsigned int
#define __FLT_RADIX__ 2
#define __LDBL_EPSILON__ 4.94065645841246544176568792868221e-324L
#define __NATURAL_ALIGNMENT__ 1
#define __FLT_HAS_QUIET_NAN__ 1
#define __FLT_MAX_10_EXP__ 38
#define __LONG_MAX__ 2147483647L
#define __FLT_HAS_INFINITY__ 1
#define _BIG_ENDIAN 1
#define __LDBL_MANT_DIG__ 106
#define __WCHAR_TYPE__ int
#define __FLT_DIG__ 6
#define __INT_MAX__ 2147483647
#define __LONG_DOUBLE_128__ 1
#define __FLT_MAX_EXP__ 128
#define __DBL_MANT_DIG__ 53
#define __WINT_TYPE__ int
#define __LDBL_MIN_EXP__ (-968)
#define __MACH__ 1
#define __LDBL_MAX_10_EXP__ 308
#define __DBL_EPSILON__ 2.2204460492503131e-16
#define __INTMAX_MAX__ 9223372036854775807LL
#define __FLT_DENORM_MIN__ 1.40129846e-45F
#define __PIC__ 1
#define __FLT_MAX__ 3.40282347e+38F
#define __FLT_MIN_10_EXP__ (-37)
#define __INTMAX_TYPE__ long long int
#define __GNUC_MINOR__ 0
#define __DBL_MAX_10_EXP__ 308
#define __LDBL_DENORM_MIN__ 4.94065645841246544176568792868221e-324L
#define __PTRDIFF_TYPE__ int
#define __LDBL_MIN_10_EXP__ (-291)
#define __LDBL_DIG__ 31
#define __POWERPC__ 1

Interesting :)

Technorati Tags: , , , , ,

Posted by crafterm at 05:50 PM | Comments (0) | TrackBack

Christmas is in the Air!

Leon Garcias

Originally uploaded by crafterm.

Christmas is fast approaching, and around Frankfurt lots of shops, houses, and apartment buildings are starting to get jazzed up with all sorts of decorations.

For example this shot is taken from a restaurant just around the corner from where I live, Leon Garcias. Certainly in the cold winter the lights make it look even more warm and inviting :)

Technorati Tags: ,

Posted by crafterm at 05:40 PM | Comments (0) | TrackBack