Ikke's Blog

Archives for: 2005

Dec 31
Metacity scroll-to-become-invisible

Finished my "scroll on the titlebar to change window opacity" patch today.

Because images say more than words:



(Image is link to original)

Scroll up on the title bar to make the window more opaque, scroll down to make them more transparent, in steps of 4%.
There might be some minor bugs in the code, and the code might be not-really-acceptable (breaking Metacity standards) but hey, it works :-)

You can find a complete "cvs diff" of my current local metacity-cvs-head branch here. It contains both the composite manager changes and the scroll-on-titlebar thingy.
The current composite manager will be dropped in favour of the GL-accelerated one in the spif2 branch. I still couldn't get that one working though :-(

[edit] In Bugzilla now, GNOME bug #325373.

I started working on "Planet UGent" today, just for fun, which should aggregate everyone who is somehow related to UGent: students, teaching staff,...
Templates taken from Planet Gnome and altered thanks to Peter and RealNitro. Still a lot of design work (top banner, CSS) to do though. And obviously, we need more feeds :-)

Dec 28
More composite

In the end I decided to try the patched metacity using the binary nvidia drivers, and I must confess, it works great. Some things (like alt-tab) seem to be broken, but transparency works without any speed issue.

While I was in that second X instance, I decided to give luminocity another try too and guess what... It was working great! I attempted to make a little movie of it with my DSC. The quality is very bad, but you should be able to get an idea of what we might get one day (optional, of course ;-))

Please don't leech the movie too much, it's 23MB... You can find it here (thanks to Zeus for the hosting ;-))

Dec 28
RhythmBox bubbles

A Zeus member (the Gaim Guifications author) complained about the bubbles RhythmBox pops up when a new track starts.
As I'm always willing to help others (right :roll:) I made a little patch to make this behaviour optional.

It's small, ugly and untested, so use with care ;-) Against current RB CVS from cvs.gnome.org. Patch
You got to pass "--disable-bubbles" to ./configure, they're enabled by default.

Alver, let me know whether it works please so I can fix it if necessary :-)

Dec 28
Robin

As seen on #gnome-nl: Robin. Check it out! You do need a Mozilla-based browser (like Firefox) to use this.

Dec 28
Metacity and Xcomposite

I've been playing around a little more with Metacity and XComposite/XRender. I applied the patches from bugs #309152 and #310080 to current Metacity CVS-HEAD, fixed some things which broke the build, and replaced the running instance with the newly compiled one.

Here's the result:


(Image is link to full-size screenshot)

Some things to notice:

  • The terminal in the upper left corner is the one I used to replace the running metacity. It looks like there are some problems taking control of existing windows: I was unable to use the old terminal any longer... It became usable again once I killed the new metacity and the system one took control
  • The terminal in the center of the screen is made transparent using transset. Transset'ing a window removes the drop shadows :-(
  • My sticky notes transparency is working fine! Notes can be moved and resized fine.
  • The "Metacity compositing example" dialog box is generated using zenity. It's broken as I was dragging around the window whilst the screenshot was made, to give an example of how windows become transparent when moving them around.
  • I made my desktop background light to make the window drop shadows more apparent.

Overall all this eye candy is still fairly slow. I'm on an NVidia Geforce2 MX440 GPU, using the open-source drivers. I *think* the binary ones support XComposite, but I won't try it as the binary drivers don't allow me to run 1400x1050. If someone got a spare Ati 92xx GPU around, let me know, I'm looking for one (paid if necessary B-)).

There's still a lot of work to do, but I hope one day we'll get there :-)

If you want to play around with this stuff yourself, get today's metacity cvs head from cvs.gnome.org, and apply this patch. ./configure using "--enable-compositor --enable-render" with --prefix to some directory, make && make install, and run "${prefix}/bin/metacity --replace"

[edit]
Thanks to some xorg.conf tuning (ModeLine) I got the nvidia binary drivers working on the resolution I want them to, so I'm running a GPU accelerated desktop now. Composite is working great... I backported my patch to metacity 2.12.2 and am running the patched version on my whole system now. See Gnome bug #309152 if you want the patch.

Next tasks:

  • allow the user to set window transparency in the window menu, or by using the scrollwheel on the title bar
  • Make drop shadows configurable (both on/off, size, intensity)
  • Make the (ugly!) minimize effect optional
  • Try to enhance the (ugly!) alt-tab behaviour
Dec 26
Stickynotes alpha

As per bug #150493:


This is "true" transparency using XComposite, not blending with the background or a screenshot.

It's fairly buggy, but that's caused by xcompmgr and Metacity's ignorance of Compositing (I think):

  • When xcompmgr is running and you create a new note, it's not transparent although xprop says _NET_WM_WINDOW_OPACITY is set to a correct value. Restarting xcompmgr makes new notes transparent
  • Text of notes can't be changed
  • Notes can't be resized or moved

The "Delete" and "Sticky" buttons work fine though. Really strange.

Metacity really needs a built-in compositing manager, like XFWM's.

Dec 23
Crosswords

Only 67% :-( Guess I'm too young to know about those k* tools ;-) Some questions are a little Debian-specific too, but hey :-)

Ikke • LifePermalink 5 comments
Dec 23
GtkSpell language

I'm sorry Gnome-NL guys, but I must confess I'm running my desktop using the "C" locale (ie. english). There's one major problem with this: when I'm using Gaim with spell checking enabled, I'm always "wrong" as 99% of all time I talk to IM buddies, it's in dutch (nl_BE, or something close to that at least ;-)).
A very annoying issue that could be solved by disabling spell checking (*sigh*), which I don't want (hey, one has to *fix* problems, not go around them).

So I made this little patch (very simple, low profile patch, I know). It's against gtkspell 2.0.11, and as gtkspell seems to be no longer maintained, this is the version you got on your system most propably too.

To set a language to use for (gtkspell based) spell checking, just set the GTKSPELL_LANG environment variable, like this:
echo "export GTKSPELL_LANG=nl >> ~/.profile"
Then log out and log in again so the variable is incorporated in your environment.

Enjoy!

Dec 20
less and HTML

I didn't know about this before:

(that's "less index.html" in the lower terminal)

Cool! The image isn't fake, just try it for yourself.

Ikke • LinuxPermalink 3 comments
Dec 18
Gaim CVS and Bonjour using Avahi

So you want to play around with Gaim 2.0beta1 or CVS, you definately want the Bonjour/RendezVous protocol plugin to be able to IM with your buddies on your local LAN, but you haven't got Howl on your system as you believe Avahi is the way to go (good boy :-))?

Just apply this little patch. It's against current anoncvs from sf.net. You need to build avahi with avahi-compat-howl support.

Dec 16
GTK+ and Cairo is fun!

I've been playing with creating GTK+ widgets using Cairo lately. As I had to write some text for some bloody Word-task (university stuff) I started writing a widget for an "OXO" game, and make a little tutorial on how to make something alike. The task is done (I even had to remove some parts of the text :(), the tutorial isn't finished yet as there are some issues left with the widget.

Anyway, writing 2D drawing code using Cairo is really fun. Sometimes you need some maths to get some tasks done, but it's fun to experiment and the possibilities are almost endless.

Here's a little sample of what I got now, click on the image for a full-scale screenshot:

Some parts of the "logics" inside the widget are still buggy (-> the code to check whether a move is a winning one or not).

I start to get rid of the spammers on my blog. There's still some comment- and trackback-spam, but at least most spambots can't leech several gigabytes of my bandwith anymore. There are still requests done, but they get a 300byte answer, or even less.
One issue left: if I get 2 identical requests (same HTTP_REQUEST, HTTP_REFERER etc), one using HTTP/1.0 and one using HTTP/1.1, my mod_rewrite rules generate another response: 403 (5 bytes) when using HTTP/1.0, 301 (352 bytes) when using HTTP/1.1:

216.195.35.XX - - [16/Dec/2005:14:24:58 +0100] "GET /index.php/all?skin=stockholm HTTP/1.1" 403 5 "http://spamhost/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)"
216.195.35.XX - - [16/Dec/2005:14:25:05 +0100] "GET /index.php/all?skin=stockholm HTTP/1.1" 301 352 "http://spamhost/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)"

Can anyone explain me what causes this?

Thanks to RubenV who helped me out when creating the mod_rewrite rules :)

Dec 13
Linus and Gnome

Sigh. Luckily we got Nat ;-)
I still got my lockups on high IO load, or my mouse starting to go all over the screen and generating random clicks while doing so on high load, after which I get warnings in dmesg the psmouse driver lost ticks. Guess what part of my machine's stack causes that B-)

Dec 13
Some great news

Although I'm not a big Ubuntu lover, this is most certainly a good thing.
Who doesn't know the "Metro"? :-)

[edit] Looks like Peter saw it too ;-)

Ikke • LinuxPermalink 4 comments
Dec 3
More valgrind abuse

After my previous article on Valgrind I started using it more and more, and discovered another nice feature of it. Just check this sample:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define MESSAGE "test"

int main(int argc, char *argv[]) {
        char *t = NULL;

        /* Hey, everyone makes mistakes */
        t = (char *)malloc(strlen("" MESSAGE) * sizeof(char));
        assert(t != NULL);
        strcpy(t, "" MESSAGE);

        printf("%s\n", t);

        free(t);

        return 0;
}

Compiling and running looks ok:

$ gcc -g -Wall -Werror -o test2 test2.c
$ ./test2
test

But luckily there's Valgrind to tell us the code is horribly wrong:

$ valgrind --tool=memcheck ./test2
==13483== Memcheck, a memory error detector for x86-linux.
==13483== Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al.
==13483== Using valgrind-2.2.0, a program supervision framework for x86-linux.
==13483== Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.
==13483== For more details, rerun with: -v
==13483==
==13483== Invalid write of size 1
==13483==    at 0x1B906485: strcpy (mac_replace_strmem.c:199)
==13483==    by 0x80484B2: main (test2.c:14)
==13483==  Address 0x1BA5C02C is 0 bytes after a block of size 4 alloc'd
==13483==    at 0x1B906B82: malloc (vg_replace_malloc.c:131)
==13483==    by 0x8048472: main (test2.c:12)
==13483==
==13483== Invalid read of size 1
==13483==    at 0x1B968B6B: _IO_vfprintf (in /lib/tls/libc-2.3.5.so)
==13483==    by 0x1B96DF36: _IO_printf (in /lib/tls/libc-2.3.5.so)
==13483==    by 0x1B93DF36: __libc_start_main (in /lib/tls/libc-2.3.5.so)
==13483==  Address 0x1BA5C02C is 0 bytes after a block of size 4 alloc'd
==13483==    at 0x1B906B82: malloc (vg_replace_malloc.c:131)
==13483==    by 0x8048472: main (test2.c:12)
test
==13483==
==13483== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 13 from 1)
==13483== malloc/free: in use at exit: 0 bytes in 0 blocks.
==13483== malloc/free: 1 allocs, 1 frees, 4 bytes allocated.
==13483== For a detailed leak analysis,  rerun with: --leak-check=yes
==13483== For counts of detected errors, rerun with: -v

This should be fairly self-explaining... I guess most C programmers forgot to allocate strlen(msg)+1 (the end '\0') at least once in their life...

By the way: hello Planet Grep :-)

Dec 2
gotroot.com mod_security rules update script

Lately I've been working on the new webserver machine for VTK. Today I configured mod_security for Apache2, partially by using the rules one can find on gotroot.com.
On the site a little script is provided to update the rules automagicly (in a cronjob or something alike), but when I started using the script I didn't like it for several reasons.
So I decided to rewrite it to suit my needs. You can find my enhanced version here.

The machine now also runs PHP4 and PHP5 side by side thanks to this great documentation (and the Gentoo PHP herd developers, obviously). PHP4 as an Apache module (because this is the "default", so it must run as efficient as possible), PHP5 using the CGI interface for all .php5 files.
We can't make "the big switch" to a PHP5-only server due to our bloody PhpBB forum which is not PHP5 compatible. And as our forum is one of the biggest PHP consumers on the server, I don't want to run PHP4 as CGI and only run the forum this way.

[edit]
I enhanced the script a little more, here's a diff:

--- update_mod_security_rules.sh        2005-12-02 14:46:02.000000000 +0100
+++ update_rules_v2.sh  2005-12-04 14:34:33.000000000 +0100
@@ -15,6 +15,7 @@
 APACHESTART="/etc/init.d/apache2 restart"
 MODSECPATH="/etc/modsecurity"
 APACHEPID="/var/run/apache2.pid"
+APACHECTL="/usr/sbin/apache2ctl"

 #Modules
 #If you want the "exclude" rules, they should be the first entry in the list
@@ -59,10 +60,21 @@

 echo "Make sure you got \"Include ${MODSECPATH}/all.conf\" somewhere in your Apache config"

+${APACHECTL} configtest > /dev/null 2>&1
+if [ ! "x$?" = "x0" ]; then
+        echo
+        echo "There's something wrong in Apache's configuration:"
+        echo
+        ${APACHECTL} configtest
+        echo
+        echo "Exiting, not restarting Apache"
+        exit 1
+fi
+
 # try restart
 if [ "$UPDATED" -gt "0" ]; then
         echo -n "Restarting apache: "
-        /bin/kill -HUP ${PID} 2>/dev/null
+        ${APACHECTL} graceful
         # did it work?
         if `/bin/kill -CHLD ${PID} >/dev/null 2>&1`; then
                 echo "ok."

The script

Nov 25
Spam attack

This blog is under a massive referer spam attack at the moment by multiple spambots. I'm trying to get rid of them using .htaccess, but it hardly works.
Those spambots already consumed all my monthly bandwith, so I really need them to go away. If someone knows how to do this (I googled around, no usable help), please let me know asap, otherwise I'll be forced to take this blog down for some days I'm afraid... Maybe I should switch to WordPress here too.

My sincere apologies if I broke something in the blog setup, or if some people are unable to reach the site although they're not spammers.

Nov 23
Non-tech people on tech stuff

Read this.

Reminds me on an article on "Web 2.0" in our newspaper some days ago, and a "readers reaction" on it yesterday. Obviously 2 people who don't understand what it's all about. Sadly enough.

Ikke • Life, LinuxPermalink 3 comments
Nov 19
OOo2 on 770

Nice work, RealNitro!

Ikke • DesktopPermalink 5 comments
Nov 19
Small Valgrind introduction

Everyone writing C or C++ code should know what a memory leak is. You allocate some memory, and never free it.
It can be very hard to make your code memleak free, or even just to know whether your code contains any memleaks.
Luckily, in the Free Software world, we got a great tool to check our code for memleaks (or other errors): Valgrind.

As I don't have time to write a lot now, I'll just give a very simple sample of it's usage.

Here's my code (very bad code, obviously, but hey ;-)):

#include <stdio.h>
#include <stdlib.h>

static void function() {
        char *test = (char *)malloc(100 * sizeof(char));
        test[0] = '\0';

        printf("Function\n");

        /* Leaking 100 chars here, 100 bytes */
}

int main(int argc, char *argv[]) {
        int *i = NULL;

        function();
        i = (int *)malloc(50 * sizeof(int));
        printf("Done\n");

        return 0;

        /* Leaking 50 ints here. On x86, this is 50*4=200 bytes */
}

As you can see, we leak memory twice: once 100 bytes, once 200.
Let's compile and run our code:

$ gcc -o test -Wall -g test.c
$ ./test
Function
Done

Great, our code works fine (or at least, it looks like it).

Now we introduce valgrind. First we'll do a simple memory allocation check:

$ valgrind --tool=memcheck ./test ==18819== Memcheck, a memory error detector for x86-linux.
==18819== Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al.
==18819== Using valgrind-2.2.0, a program supervision framework for x86-linux.
==18819== Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.
==18819== For more details, rerun with: -v
==18819==
Function
Done
==18819==
==18819== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 1)
==18819== malloc/free: in use at exit: 300 bytes in 2 blocks.
==18819== malloc/free: 2 allocs, 0 frees, 300 bytes allocated.
==18819== For a detailed leak analysis,  rerun with: --leak-check=yes
==18819== For counts of detected errors, rerun with: -v

Valgrind tells us we leaked 300 bytes, in 2 blocks (one malloc call returns one block, obviously).
It also tells us to re-run the test with the --leak-check=yes flag, which is a good advice:

$ valgrind --tool=memcheck --leak-check=yes ./test
==18826== Memcheck, a memory error detector for x86-linux.
==18826== Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al.
==18826== Using valgrind-2.2.0, a program supervision framework for x86-linux.
==18826== Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.
==18826== For more details, rerun with: -v
==18826==
Function
Done
==18826==
==18826== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 1)
==18826== malloc/free: in use at exit: 300 bytes in 2 blocks.
==18826== malloc/free: 2 allocs, 0 frees, 300 bytes allocated.
==18826== For counts of detected errors, rerun with: -v
==18826== searching for pointers to 2 not-freed blocks.
==18826== checked 1404368 bytes.
==18826==
==18826== 100 bytes in 1 blocks are definitely lost in loss record 1 of 2
==18826==    at 0x1B906B82: malloc (vg_replace_malloc.c:131)
==18826==    by 0x80483B5: function (test.c:5)
==18826==    by 0x80483F4: main (test.c:14)
==18826==
==18826==
==18826== 200 bytes in 1 blocks are definitely lost in loss record 2 of 2
==18826==    at 0x1B906B82: malloc (vg_replace_malloc.c:131)
==18826==    by 0x8048400: main (test.c:15)
==18826==
==18826== LEAK SUMMARY:
==18826==    definitely lost: 300 bytes in 2 blocks.
==18826==    possibly lost:   0 bytes in 0 blocks.
==18826==    still reachable: 0 bytes in 0 blocks.
==18826==         suppressed: 0 bytes in 0 blocks.
==18826== Reachable blocks (those to which a pointer was found) are not shown.
==18826== To see them, rerun with: --show-reachable=yes

Great, here Valgrind tells us exactly what we're doing wrong.
There are 2 blocks where we leak memory:

  • The first one is at code path
    main (test.c:14) -> function (test.c:5) -> malloc (vg_replace_malloc.c:131)
    leaking 100 bytes.
    The vg_replace_malloc.c file isn't ours, it's a valgrind file where the malloc() wrapper (which keeps track of our allocations/free's/...) is located. We're mostly interested in the "function (test.c:5)" part. If we look at line 5, we see this is

    char *test = (char *)malloc(100 * sizeof(char));
    our first allocation. And indeed, if we look further, we never free these 100 chars.
  • Second is at main (test.c:15). Again, we can look at this line:
    i = (int *)malloc(50 * sizeof(int));
    and indeed, we never free these allocated integers again. We allocated 50 ints, and on x86 one int is 32 bits (4 bytes), so we leak 200 bytes (and valgrind was correct once again :-)).

Obviously, valgrind got much more options or checks:

$ valgrind
valgrind: Missing --tool option
Available tools:
        memcheck
        addrcheck
        cachegrind
        corecheck
        helgrind
        massif
        lackey
        none
        callgrind
valgrind: Use --help for more information.

I don't know all of them, actually I only use the memcheck thing, but even when only using one tool, it can be a very useful program.

I got one minor issue with valgrind currently: when it detects memory leaks in some program, it still returns 0 in the end, so it's not easy to integrate valgrind checks in automake's "make check" target. If someone got any pointers how to do this, please let me know!

Nov 12
Nano on Maemo

So, you got SSH access to your Nokia 770, but can't edit any files? Try my Nano package...
It doesn't work yet in the xterm application (I didn't try myself yet, RealNitro told me ;-)), looks like there's some issue with that terminal's CTRL-key emulation...
Anyway, it's meant to be used over SSH, not for on-device purposes...

Now I still should be able to get USB networking working somehow :-( Didn't spend any more time on it though...

Nov 5
Maemo and mDNS

Porting Avahi to the Maemo platform seems to be quite hard (if not impossible) because of the DBUS version conflict (Avahi needs DBUS >= 0.34, whilst the Maemo platform is still based on DBUS 0.2x). There's a DBUS 0.3x branch in Maemo's SVN repository, but that's not stable yet, and will only be used in the InternetTablet2006 releases, so I gave up on Avahi for now :oops:.
Instead, I'm trying to create a good package of Howl now (I know, I don't like the Howl API either), then I'll attempt to build a small (Hildon?) application on top of it, just as a test case for "the real thing" ;-)

*edit*
It works inside my scratchbox (i386) :-)
Built an arm deb package too, installed it on my "real" device, the software runs (no ld errors), but I couldnt test it yet as I don't have a wireless network at home, and didn't manage to get USB networking working yet :-(

Nov 3
Using C++ classes in C

Today I had a little chat with Michiel on #gnome-nl regarding the use of C++ classes in C code (he started learning C again ;-)).

I was fascinated (well, sort of) by this, and tried to get something working. Here's the result:

  • First we need a C++ class, using one header file (Test.hh)

    class Test {
            public:
                    void testfunc();
                    Test(int i);
    
            private:
                    int testint;
    };
    

    and one implementation file (Test.cc)

    #include <iostream>
    #include "Test.hh"
    
    using namespace std;
    
    Test::Test(int i) {
            this->testint = i;
    }
    
    void Test::testfunc() {
            cout << "test " << this->testint << endl;
    }

    This is just basic C++ code.

  • Then we need some glue code. This code is something in-between C and C++. Again, we got one header file (TestWrapper.h, just .h as it doesn't contain any C++ code)

    typedef void CTest;
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    CTest * test_new(int i);
    void test_testfunc(const CTest *t);
    void test_delete(CTest *t);
    #ifdef __cplusplus
    }
    #endif
    

    and the function implementations (TestWrapper.cc, .cc as it contains C++ code):

    #include "TestWrapper.h"
    #include "Test.hh"
    
    extern "C" {
    
    CTest * test_new(int i) {
           Test *t = new Test(i);
    
           return (CTest *)t;
    }
    
    void test_testfunc(const CTest *test) {
            Test *t = (Test *)test;
            t->testfunc();
    }
    
    void test_delete(CTest *test) {
            Test *t = (Test *)test;
    
            delete t;
    }
    }
    

    Some things you should notice:

    1. typedef void CTest
      We typedef CTest to void. This way we can use "CTest *" in our C code as if it's a normal C type, whilst we have compile-time type checks (sort of at least :-)), and it's cleaner than always using "void *"

    2. The use of "extern "C" { }" around all functions (both definitions and implementations). We need this so the compiler won't name-mangle the resulting binaries. If you want to see what name-mangling is:

      $ cat test.c
      #include <iostream>
      using namespace std;
      
      void test() {
              cout << "test" << endl;
      }
      
      int main(int argc, char *argv[]) {
              test();
              return 0;
      }
      $ g++ -o nmtest test.c
      $ ./nmtest
      test
      $ nm nmtest
      ***blablabla***
      08048818 t _Z41__static_initialization_and_destruction_0ii
      080487c4 T _Z4testv
               U _ZNKSs4sizeEv@@GLIBCXX_3.4
               U _ZNKSsixEj@@GLIBCXX_3.4
      ***blablabla***

      As you can see, our "test()" function has been renamed to "_Z4testv" by the compiler. This is needed to allow polyphormism in C++, but we don't want this in our C wrapper of course, as we want to know the name of the function we will call!
      This implies we need another function name for every polyphormistic (SP?) class function of our C++ class in the C wrapper.

  • At last, we need some code to test our work (main.c):

    #include <stdio.h>
    #include "TestWrapper.h"
    
    int main() {
            CTest *t = NULL;
    
            t = test_new(5);
            test_testfunc(t);
            test_delete(t);
            t = NULL;
    
            return 0;
    }
    

    This is, once more, braindead simple (C) code, where we use the functions defined in TestWrapper.h.

  • Last but not least, we need to compile everything. I made a basic Makefile to do this (Makefile):

    CFLAGS=-Wall -Werror -g -ansi -pedantic -std=c89
    CCFLAGS=-Wall -Werror -g
    LDFLAGS=-g -Wall -lstdc++
    
    OBJS=Test.o TestWrapper.o main.o
    PROG=test
    
    all: $(PROG)
    default: all
    
    %.o: %.cc
            $(CC) $(CCFLAGS) -c $<
    
    %.o: %.c
            $(CC) $(CFLAGS) -c $<
    
    $(PROG): $(OBJS)
            $(CC) $(OBJS) $(LDFLAGS) -o $@
    
    clean:
            rm -f $(OBJS)
            rm -f $(PROG)
    

Now we can simply call "make" to build the project:

$ make
cc -Wall -Werror -g -c Test.cc
cc -Wall -Werror -g -c TestWrapper.cc
cc -Wall -Werror -g -ansi -pedantic -std=c89 -c main.c
cc Test.o TestWrapper.o main.o -g -Wall -lstdc++ -o test

Finally, we test the resulting binary:

$ ./test
test 5

which is the expected result.

Obviously, writing a wrapper like this by hand can be a boring task. It might be possible to automate/script this, but I don't know whether the result is worth the time one puts into it. Just use plain C, we don't need C++ ;-)

Nov 3
Scratchbox working

Thanks to Bram (and VTK Computer) I got an old 20Gb hard drive, which I needed to be able to install a Scratchbox environment and play around with the Maemo platform.
I managed to install everything by now (although I had one crash again :-(), so I hope I'll be able to start hacking on some apps/libs soon. One of the things I'd love to get working is Avahi, the GPL'ed mDNS stack.

The obligatory shot:

I just followed these steps. They contain one error though: when editing your ~/.bash_profile, you got to add a line containing

export LC_ALL=en_GB

too.

Oct 27
770 and UGent VPN

So, I just got my Nokia 770 connected to the UGent VPN nerwork, which means I can connect to the internet when I'm near one of the access points. It wasn't too easy, and editting long texts on the device is fairly boring, so I'll stop here. More news when I'm near a "real" computer ;-)

Cheers!

Oct 18
Gnome for young children && 770 update

This theme mockup by Andreas Nilsson is actually pretty cool stuff IMHO, when used in an environment where young children/kids use the computer (eg in schools). I think it's pretty attractive, as long as the texts are easily readable.

Next to this, thanks to Philip and (obviously) Nokia itself, I was able to order my personal Nokia 770 from their Developer Program today. It should arrive in 1-3 days, so I'll be pretty stressed when checking the mail next days :-) When I saw (and even touched ;-)) the 770 at LinuxTag I was really impressed, let's hope it'll work well (/me crosses fingers for vpnc support) and bring a lot of pleasure on a development side :-)

Oct 16
Screencasts part III: Victory!

Just found this wiki page which uses some other transcode options. I tried it, converted 2 seconds of a vnc recording to Xvid, and it works, jay :-)

Basicly:

$ emerge tightvnc vncrec transcode
$ vncserver
(enter password if necessary, edit the VNC xinitrc file,...)
$ vncrec -record test.vnc localhost:1
$ transcode -x vnc --use_rgb -i test.vnc -o test.avi -y xvid -k -f 10
$ mplayer test.avi

I'll try connecting to Vino now. Encoding takes a very long time, but well...

/me happy ;-)

Oct 15
Screencasts part II

After digging around a little more, I found vncrec, which works really well. Quality is good, computer doesn't lag while making the movie,... One major problem: the output format. Nobody can play these files, except if he/she got vncrec installed, which is *nix only.
It should be possible to convert .vnc files to some other format (video) using transcode. I tried this, but when playing the ouput file using mplayer (xvid encoded), I only get green and red noise. Not everyone got an xvid codec installed too, so I might want to use mpeg2 here or something alike. If only I would get a real video, and not just noise...
Transcoding a vnc file takes a lot of time too.

I'll keep you guys posted :-)

Oct 14
Screencast

Could anyone please tell me how I can make a screencast in X? Istanbul doesn't work (segfaults and other errors), vnc2swf produces flash files, which I don't like, xvidcap doesn't want to compile,...

I'd really need to be able to create a little movie to convince some people @ university Linux is not all about command line magic like su, sudo, mount -t smbfs -o username=foobar //server/share /mnt/foobar and other 19[89]X commands...

I could use Istanbul's Gstreamer pipelines in some small application, but there's one major problem: ximagesrc's image quality is terrible.

Oct 11
MS Hotmail new Beta interface

Check it out here.

One major question: how well will it work for people exploring the web using a non-IE based browser?

Sep 19
Dislocated wrist, and GIM update

Typing this using one hand, as I was so stupid to dislocate my left wrist last saturday night. At least, I hope it's only dislocated, and not broken. And yes, it does hurt.
I might get a picture later.
Got some GIM design drawings completed lately, but only on paper, I need to dia'ize them (which won't be an easy job now). I hope I'll be able to show some of the work soon.

Sep 10
Software Freedom Day 2005

So, today is Software Freedom Day 2005. Here in Ghent, VTK/WVS organises a little event in co-operation with several companies and organisations. There's a movie in Film Plateau ("Revolution OS"), a little get-together afterwards, and maybe some food. All of this free (as in beer), except the food, obviously.
More information can be found here (in Dutch).

I'm trying to work on the GIM design some more, and working on the new PDC at VTK. More on this later.

Aug 31
Virtual Reality in 2015

What will the Internet look like in 2015? What are giants like Microsoft and Google up to? Who are the other players?

Find the (possible) answer on these and other questions here (requires a Flash player, unfortunately).

Complete nonsense? A bit of truth? Maybe even worse than presented here? Let me know in the comments!

Thanks to Bram ;-)

Aug 7
MS R&B

Don't we just love MS and the great software they offer us? ;-)

Don't take tis too seriously, of course

Ikke • LifePermalink 3 comments
Jul 29
Lack of updates

Hija,

as some of you might now I'm currently employed (just one month) at some nice company called Dedigate, where I'm allowed to do some nice coding stuff etc (ok, also less exciting things ;-)) whilst getting payed. As I'm behind a computer screens >8h/day over there, trying to write some good code, I'm not in a real coding-mood when I get home (don't flame me, I'm just some normal human being). This implies I rarely blog, as I don't like to blog about my "normal" life.

Nothing too fancy happened lately, except the fact I saw Arsenal (not the football club) live at BoomTown (wiiiii :-)), the DConf project was released to the wolves, and I got 20 years old today (07/28) (got a nice little present from my favourite girl, the piano and violin scores of the Brahms piece I blogged about before, thank you!).

I'm quite tired now, guess I need some good sleep to be able to get to work again tomorrow. 2 weeks to go :-)

Ikke • LifePermalink 6 comments
Jul 16
GConf introduction

I played a little with GConf today. Here's some little introduction to it.

We'll be doing 3 very simple things today:

  1. Read out GConf key values

  2. Set key values

  3. Read out values, and register to value changes

Reading out a string from the GConf tree

Reading out a value (in our case a string) is very simple: first of all you need to know which string you want to read. In this sample we'll try to get the value of the default browser. Then you create a GConfClient, a proxy to the GConf system, you query gconfd using the proxy, get the value and do something with it.

Here's the code:

/* GConf test reader
 * Compile using
 *      gcc `pkg-config --libs --cflags gconf-2.0` -o reader reader.c
 */

#include <glib.h>
#include <gconf/gconf-client.h>

/* Path to the key we'll be working with */
#define GCKEY "/desktop/gnome/applications/browser/exec"

gint main(gint argc, gchar *argv[]) {
        /* Our proxy */
        GConfClient *gclient = NULL;
        /* String to store the GCKEY's value in */
        gchar *val = NULL;

        /* Initialize the GConf subsystem */
        gconf_init(argc, argv, NULL);

        g_print("Working with key \"%s\"\n", "" GCKEY);
        
        /* Get the default GConf proxy */
        gclient = gconf_client_get_default();
        g_assert(gclient != NULL);

        /* Get the value of GCKEY */
        val = gconf_client_get_string(gclient, "" GCKEY, NULL);
        if(val == NULL) {
                /* Key was not set before */
                val = g_strdup("<unset>");
        }
        g_assert(val != NULL);

        g_print("Value: \"%s\"\n", val);

        g_free(val);

        return 0;
}

As you can see this is very straight-forward.
Now compile and run the code:

ikke@marslander ~/Projects/gconf $ gcc `pkg-config --libs --cflags gconf-2.0` -o reader reader.c
ikke@marslander ~/Projects/gconf $ ./reader
Working with key "/desktop/gnome/applications/browser/exec"
Value: "mozilla"

Setting a key value

To set a key, once more we just need a GConfClient proxy, and call a function to set the new key value:

/* GConf test writer
 * Compile using
 *      gcc `pkg-config --libs --cflags gconf-2.0` -o setkey setkey.c
 */

#include <glib.h>
#include <gconf/gconf-client.h>

/* Path to the key we'll be working with */
#define GCKEY "/extra/test/key"

gint main(gint argc, gchar *argv[]) {
        /* Our proxy */
        GConfClient *gclient = NULL;
        /* New value */
        gchar *val = NULL;

        /* Initialize the GConf subsystem */
        gconf_init(argc, argv, NULL);

        if(argc > 1) {
                val = g_strdup(argv[1]);
        }
        else {
                val = g_strdup("testval");
        }

        g_print("Working with key \"%s\"\n", "" GCKEY);
        
        /* Get the default GConf proxy */
        gclient = gconf_client_get_default();
        g_assert(gclient != NULL);

        g_assert(val != NULL);
        gconf_client_set_string(gclient, "" GCKEY, val, NULL);

        g_print("Value \"%s\" set\n", val);

        g_free(val);

        return 0;
}

Again, compile the code and play around with it:

ikke@marslander ~/Projects/gconf $ gcc `pkg-config --libs --cflags gconf-2.0` -o setkey setkey.c
ikke@marslander ~/Projects/gconf $ ./setkey
Working with key "/extra/test/key"
Value "testval" set
ikke@marslander ~/Projects/gconf $ ./setkey test2
Working with key "/extra/test/key"
Value "test2" set

Now you might want to alter reader.c and compile it again so it reads out this new key instead of the one we used before.

Using change notifications

At last we'll be using one of the more advanced features of GConf, change notifications. This means we can register a callback to a key change, so when the key's value is changed (in-process or by another process) we'll be notified of this.
One again this is very easy: get a GConfClient proxy, figure out to which key you want to subscribe, find out the container directory, tell gconfd you want to register to that "directory", add a key change event handler, and you're done. This might sound confusing, read the code sample to see how easy it is.

/* GConf test listener
 * Compile using
 *      gcc `pkg-config --libs --cflags gconf-2.0` -o listener listener.c
 */

#include <glib.h>
#include <gconf/gconf-client.h>

/* The GConf PATH we'll want to monitor */
#define GCPATH "/extra/test"
/* Path to the key we'll be working with */
#define GCKEY "/extra/test/key"

/* This is the callback function for GCKEY changes */
void key_changed_cb(GConfClient* client, guint cnxn_id, GConfEntry *entry, gpointer user_data) {
        /* Store the new key value */
        gchar *val = NULL;
        /* A local GConfValue */
        GConfValue *value = NULL;

        /* Get the value from the provided entry */
        value = gconf_entry_get_value(entry);
        
        /* This should not happen, but one never knows */
        if(value == NULL) {
                val = g_strdup("<unset>");
        }
        else {
                /* Check value type, we want a string */
                if(value->type == GCONF_VALUE_STRING) {
                        /* Get the key value
                         * We use g_strdup because we'll g_free(val) later */
                        val = g_strdup(gconf_value_get_string(value));
                }
                else {
                        val = g_strdup("<wrong type>");
                }
        }
        g_assert(val != NULL);

        g_print("Value changed: \"%s\"\n", val);

        g_free(val);
}

gint main(gint argc, gchar *argv[]) {
        /* Our proxy */
        GConfClient *gclient = NULL;
        /* String to store the GCKEY's value in */
        gchar *val = NULL;
        /* A simple mainloop */
        GMainLoop *loop = NULL;

        /* Initialize the GConf subsystem */
        gconf_init(argc, argv, NULL);

        g_print("Working with key \"%s\"\n", "" GCKEY);
        
        /* Get the default GConf proxy */
        gclient = gconf_client_get_default();
        g_assert(gclient != NULL);

        /* Get the value of GCKEY */
        val = gconf_client_get_string(gclient, "" GCKEY, NULL);
        if(val == NULL) {
                /* Key was not set before */
                val = g_strdup("<unset>");
        }
        g_assert(val != NULL);

        g_print("Initial value: \"%s\"\n", val);

        g_free(val);

        /* Watch GCPATH */
        gconf_client_add_dir(gclient, "" GCPATH, GCONF_CLIENT_PRELOAD_NONE, NULL);
        /* And specify a callback function for GCKEY changes */
        gconf_client_notify_add(gclient, "" GCKEY, key_changed_cb, NULL, NULL, NULL);

        /* Create a mainloop and run it */
        loop = g_main_loop_new(NULL, FALSE);
        g_assert(loop != NULL);
        g_main_loop_run(loop);

        return 0;
}

50% of this code is equal to "reader.c". The only "special" things is adding a callback notifier in main(), and the callback function itself.
You should notice GConfValues got a type: in this sample we check whether the key's type equals to "GCONF_VALUE_STRING", otherwise we don't "process" the value.

Once more, compile and run this code:

ikke@marslander ~/Projects/gconf $ gcc `pkg-config --libs --cflags gconf-2.0` -o listener listener.c
ikke@marslander ~/Projects/gconf $ ./listener
Working with key "/extra/test/key"
Initial value: "test2"

At this point, the program just hangs due to our GMainLoop. The key value is the one last set with ./setkey

Now open a new console, go to the directory where setkey is located, and execute it giving some new value. Then watch what's going on at the terminal where "listener" is running:

ikke@marslander ~/Projects/gconf $ ./setkey "a longer test key"
Working with key "/extra/test/key"
Value "a longer test key" set

In the "listener" console, we see this:

Value changed: "a longer test key"

Jay, change notifications working fine :-)

In this sample we only worked with string values, GConf also supports floats, integers, booleans, lists and even more. Check out the API docs for more information.
If you want to read more about GConf, e.g. its internals, you might want to check this tutorial by the GConf author, Havoc Pennington. Notice this is an old document, so the code samples in there won't work anymore, the GConf API has changed quite a lot since then. The ideas explained in the article are still relevant though, so it's worth reading.

Jun 25
LinuxTag day 2

So, I'm at LinuxTag currently, bloody tired, but well, having quite a good time after all (god I hate qwertz). I wouldn't say it's superb (talks tend not to go deep enough etc), but meeting some guys you've known on IRC for a while already in real life now is just great. Hacking on some things together (too bad I still havent got a laptop, which disables me from doing any real hacking myself, actually, we can only work together on one machine which does give problems from time to time), grabbing a beer (not to much, as beer is not as free as the speech couterpart ;-)), discussing things, just hanging around... Well, pretty much the things everybody does in here :-)
I won't write too much now (waaaaaay too tired), a larger "report" including some pictures might follow later (although that later might become "not within 2 weeks", as the following week I'll hardly be at home).

Fortunately we got some great wheather (although sometimes it tends to be too hot :-/)

Ikke • Life, LinuxPermalink 1 comment
Jun 22
LinuxTag 2005

So, I'll be heading to Germany tomorrow after my last exam, to attend at LinuxTag on Friday and Saturday. Most likely I will be at the Social Event too.
If you're reading this and you're coming as well, let me know, maybe we can meet :-) Leave a comment or send me some email, although I cannot promise I'll be able to check my email/blog comments over there... (I hope there'll be some public terminals)

Ikke • LifePermalink 1 comment
Jun 20
*g*

Check the first comment here. Rodrigo has some good points in his post, gives some hints on how to solve the problem, tries to be constructive.
Anonymous Coward replies.

Ignore, let's move on.

Jun 19
To Philip

Philip:
Don't get too frustrated ;-) Lots of people know about these issues. Lots of them care. But as you mentioned, people need to get together, and come out with real-world solutions for real-world problems.
You're right when you state there's a lot of flaming on xdg. But not on all subjects. Take D-BUS and HAL, two promising technologies that get widely accepted, and are truly desktop-agnostic. Both Gnome and KDE start to make heavy use of it.
I'm not really familiar with the copy-paste issues. But as far as I know there is a clipboard specification on fd.o. If that's not sufficient for new applications, everyone is free to propose extensions for the specification. But why do we need a spec if applications don't use it? Currently Gnome got no real clipboard manager, I heard KDE does though.

Some parts of the desktop should be standardised, and shared between both (or should I say "all"?) Desktop Environments we got in the Free Software world. A normal non-techie desktop user wants to be able to copy-paste between Kmail and Gaim without any problem. And he's right when he wants this.
Low-level non-interfacing libraries like D-BUS and HAL should be shared too. It'd be pointless if both Gnome and KDE would start writing up something like HAL. I've been following HAL development for a logn time already, and it's taking lots of effort and thorough decission-making to develop it (kudo's to the devs, especially David :-)), so duplicating something like it is a wasted effort. We could use the amount of work the devs put in the 2nd implementation elsewhere.
Same goes for D-BUS: we all know the story of CORBA and all it's implementations. Finally, with D-BUS, sending some simple dumb signal becomes a matter of writing 3 lines of code (now don't count, it's just a number), a dev does not have to write up IDL files and whatever more. Some people told me once only the guys that wrote Bonobo know how to use it, and maybe they were right (although I know D-BUS and CORBA/Bonobo aren't 100% the same thing, bleh).

But where is the line? I mean, if both Gnome and KDE should share everything (not only in standards, something they should share, but also in libs) we can as well just start dropping one of them and only developing on the other one. And we all know what happens when someone gets a monopoly ;-)

So (finally, the key matter): DConf. I did follow the lengthy discussions (url is just one of the many threads) when they were on xdg. And I must admit, at that time, sometimes they bored me to that. I also laughed when I read that "Over my dead body" comment. Actually, I used it several times to demonstrate what's going on between Gnome and KDE. Although there's one big thing to note: the comment was made by someone who was, afaik, no KDE developer. Waldo, who is one, did participate in a positive manner IIRC.

Now why do people accept something like HAL, and tend to be against something like DConf? I think it's fairly simple: currently both KDE and Gnome got their configuration infrastructure, KConfig and Gconf. Almost all apps who target one of these environments use the corresponding configuration libraries and standards. This is a large part of all desktop apps, including some of the largest (well, except the Mozilla and OOo stuff).
So I can understand some people are a little reluctant when all at once someone on xdg comes to tell them we need a new, common configuration interface. I'm not saying this is a good thing, just trying to understand how they think:

  • When KConfig or Gconf would be dropped one day in favour of Dconf, lots of code that accesses configuration settings should be rewritten to use the new API's
  • It is possible even the internal logics of this code will need to be rewritten, if they use some special features of the system they use now that won't be included in Dconf
  • "We already got a config system that does what we need, why can't the (fill in other/'rival' DE) guys just use ours?"
  • "Dconf offers this and this, but hell, I don't need all that! It only makes my simple I-administrate-one-desktop life more difficult"

and there could be more than 100 other reasons.

So what's the big difference between, say, HAL and Dconf? HAL is new. Desktop developers can just say "Hey, that's some cool new technology, let's write some application (gvm/ivman/kvm/...) around it, or add some functionality to something we got now (gnome-vfs/kioslaves/...) using it".
Dconf will also be something new. But the functionality it offers won't be. So existing things will have to be adapted or rewritten.

Summary: I agree with you on large parts of your rant. Basic libraries like GStreamer should be adopted by both platforms (as long as the development team does, well, a good job... together), duplicating effort is useless there.
Standards should be written and implemented, so a normal desktop-user shouldn't care whether he's running KDE applications or Gnome apps in some random environment. Copy-paste between two Gnome apps should be as easy/workable as doing it between a Gnome and a KDE app.
But we should not make just one melt pot of both platforms. Some concurrention is a good thing ;-) I hope you're not saying something like "Hey, let's drop GTK+, let's use Qt too, to avoid duplicate efforts".
As for ISV's: it's not a bad thing they should choose between GTK+ or Qt. Both platforms got their strengths, every ISV got it's preferences and knowledge. And both platforms get vendors that use them: GTK eg by VMWare, Qt by Skype. But we should make sure indeed VMWare can run flawlessly on a desktop running KDE, taking care VMWare should not use any special tricks to get that working (eg configuration management). Like this all ISV's can choose their preferred platform, without being forced to ask the client "Hey, what desktop are you running?"

Somewhat unrelated: we, in the FOSS world, should make sure we get more enterprise-ready (and Dconf is one step in the right direction). We are not limited to single-desktop employments. There are some good efforts like Sabayon, or Fedora Stateless, and maybe some non-Gnome-based counterparts I don't know of, but these need much more attention, as they are not completely usable yet (as you can see while reading our experiences with Fedora Stateless). 100-workstation deployments should become fun for the administrator, not a hell as it is now. If we could ever reach that goal, FOSS would get the oportunity to get a strong share in the corporate desktop market, as deploying concurrent desktops in a big environment isn't always a breeze either these days (wink@Jeroen and DICT, if someone'd ever read this).

Bleh, I dislike writing long rants as I'm not good at it so I stop here. By the way, didn't we agree not to blog on Dconf and keep it silent for a while? ;-)

Completely unrelated: I got some email from Nokia saying I'll get a code to get one of their N770's at 99

Jun 19
Windows Picture and Fax preview question, and a little update

I guess most of you saw the Windows Picture and Fax viewer at least once already:

PictureFaxViewerThumb
(click on the tumbnail for a full scale view)

Never mind the screenshot's content, it was the first one I could find on Google Images.

Now what's so special about this? Let's take a closer look:

PictureFaxViewerButtons

"If you want to rotate the picture to the right, please click the button on the left. If you want to rotate left, you need the button on the right"

Is it just me who doesn't get the logics behind this? Guess I won't ever become a good UI-designer...

If anyone got a good explanation for this, please let me know.

Next to that: I haven't been working too much on coding lately, trying to study. I might overhaul the opluginmanager API completely once more, playing around with some idea's to make it more usable from languages other than C, so as long as I didn't decide on the final design (on which I'd still love to get some input) it's stalled a little.

I'll have my last exam on Thursday afternoon, then probably I'll take off to Germany to visit LinuxTag (let me know if you're coming), I'll be at Rock Werchter one day, then the VTK Weekend follows, our annual GAO barbeque,... Busy times to come :-)

Jun 16
Wikipedia Article of the day

Hija,

Today I implemented an idea I had been playing with for some time already: make a daily RSS feed of Wikipedia articles.
Why? If you add this feed to your aggregator, you'll be served a random article every day (or maybe twice a day, still have to decide at which frequency the cronjob should run) to expand your global knowledge, not only regarding tech-stuff ;-)

The blog page is here, you can find links to the RSS/Atom/... feed on the right.

Things could be somewhat buggy for now (there are lots of articles with lots of markups, some of them forbidden by b2evo, so I have to filter them out) but as more articles are aggregated, I'll be able to squash them :-)

I hope you like (and use) the service ;-) Spread the word!

Jun 15
Gnome tip

This must be the greates Gnome tip I ever read (the dragging part at least). Now finally one doesn't need to crawl through one Save and one Open dialog to send a simple screenshot to some buddy. Thanks Karel!!!

Next to that: this is some of the most insane projects ever. A Unix shell written in JavaScript, that can be run from a browser. Check the "Open Shell" link on top of the page. Pretty nifty, didn't look at the code yet, will do that later.

Started working on the "save and restore enabled plugins" functionality today. I decided to use GMarkup instead of libxml2 so I don't add another dependency (next to glib), and the config strings are so easy formatted GMarkup is more than sufficient to parse them. But it made me discover once more how much I hate dreaded SAX parsing. Someone who enjoys writing SAX based parsers must be on a serious crack overdose :crazy:

Jun 14
One more status update

I implemented Python plugin loading this afternoon. It's almost finished, only calling functions does not work yet (thats only like 10 lines or so, but my eyes start to hurt). It's using the Python plugin base class I blogged about yesterday.

The code is far from perfect, it might leak like hell etc, but hey, it's working ;-) You can't debug or clean code that is not working at all :-)

Here's the current output of the test loader I wrote:

** (process:19360): DEBUG: Loading all modules in .libs
** (process:19360): DEBUG: Suffix for .libs/libtestplugin1.so is valid, loading module
** (process:19360): DEBUG: [OPluginManagerPlugin] [test-plugin1] Got an init function
** (process:19360): DEBUG: [test-plugin1] Init with data "test-init-data"
** (process:19360): DEBUG: Module .libs/libtestplugin1.so is valid, adding
** (process:19360): DEBUG: Suffix for .libs/libtestplugin2.so is valid, loading module
** (process:19360): DEBUG: Module .libs/libtestplugin2.so is valid, adding
** (process:19360): DEBUG: Loading all modules in .
** (process:19360): DEBUG: Suffix for ./TestPlugin.py is valid, loading module
Creating new OPluginManagerPythonPlugin instance: PythonTest
** (process:19360): DEBUG: Module ./TestPlugin.py is valid, adding


Found 3 modules
** (process:19360): DEBUG: Dumping module 0:


================================================
Dumping data for: .libs/libtestplugin1.so, type is "native"
=================
* Name: test-plugin1
* Summary: A simple test plugin, full-featured
* Description: This is a sample test plugin, to test the OPluginManager functionality, giving sample usage of all possibilities
* Version: 0.1
* URI: http://www.eikke.com
* Authors:
        ikke
        -----------
                Email: eikke eikke com
                URI: http://www.eikke.com
* Module got an init function
* Module got a data free function
* Module got a configure function
================================================



** (process:19360): DEBUG: Dumping module 1:


================================================
Dumping data for: .libs/libtestplugin2.so, type is "native"
=================
* Name: test-plugin2
* Summary: A simple, small test plugin
* Description: This is a sample test plugin, to test the OPluginManager functionality. It only offers limited functionality
* Version: 0.1
* URI: http://www.eikke.com
* Authors:
        ikke
        -----------
                Email: eikke eikke com
                URI: http://www.eikke.com
        John Doe
        -----------
                Email: foo@bar.com
                URI: http://www.foobar.foo
* Module got no init function
* Module got no data free function
* Module got no configure function
================================================



** (process:19360): DEBUG: Dumping module 2:


================================================
Dumping data for: ./TestPlugin.py, type is "Python"
=================
* Name: PythonTest
* Summary: A little test plugin
* Description: Some longer description of this test plugin
* Version: 0.1
* URI: http://www.eikke.com
* Authors:
        Ikke
        -----------
                Email: eikke eikke com
                URI: http://www.eikke.com
* Module got no init function
* Module got no data free function
* Module got no configure function
================================================



** (process:19360): DEBUG: Deleting 3 modules
** (process:19360): DEBUG: [OPluginManagerPlugin] Freeing "test-plugin1" data
** (process:19360): DEBUG: [OPluginManagerPlugin] Running free function
** (process:19360): DEBUG: [test-plugin1] Freeing data "Test plugin 1 data"
** (process:19360): DEBUG: [OPluginManagerPlugin] Freeing "test-plugin2" data
** (process:19360): DEBUG: [OPluginManagerPlugin] No free function provided

As you can see, it loads 3 modules: 2 native (C) ones in .libs, one fully fledged, one minimal, and loads one Python plugin.
The Python plugin code is very simple, but can still offer almost the same flexibility as the C interface does:

from OPluginManagerPlugin import OPluginManagerPlugin, OPluginManagerPluginAuthor

class TestPlugin(OPluginManagerPlugin):
        def __init__(self):
                tmpauthor = OPluginManagerPluginAuthor("Ikke", "eikke eikke com", "http://www.eikke.com")
                OPluginManagerPlugin.__init__(self, "PythonTest", "A little test plugin", tmpauthor, "Some longer description of this test plugin", "0.1", "http://www.eikke.com", self.Init, self.FreeData, self.Configure)

        def Configure(self):
                print "Configuring"

        def Init(self, init_data):
                print "Initializing with data \"" + init_data + "\""
                return "testplugindata"

        def FreeData(self, data):
                print "Freeing \"" + data + "\""

def OPluginManagerPluginInit():
        return TestPlugin()

I should learn how to work with Python lists etc to be able to implement multi-author functionality etc though.

I updated CVS heavily, so you can find (and checkout) all current code here. Please play around with it and let me know what you think of it (as a comment here or on the live.gnome wiki page), so I know what I should enhance, add,...

Oh, I got one more terrible exam today (part 2 of the one I got yesterday). Life's great :-p

Jun 13
OPluginManager getting it's final forms

I tried to stabilize the OPluginManager interface today, after a terrible exam. Look at the OPluginManager page at live.gnome.org to get a view of the current structure.

I updated the test cases I got here locally (one example is the plugin code I got on that wiki page too). The directory-loader is finished too, almost everything is in place now actually, except the UI part and the "only-load-enabled-modules" feature. These things should be fairly trivial (don't we love that word, NVDB?) to implement.

Here's a sample app:

#include <glib.h>

#include "o-plugin-manager.h"
#include "o-plugin-manager-plugin.h"

gint main(guint argc, gchar *argv[]) {
        gint cnt = 0;
        gchar *dir = NULL, *dir2 = NULL, *modulepath = NULL;
        const OPluginManagerPlugin *plugin = NULL;
        OPluginManager *manager = NULL;

        g_type_init();

        manager = O_PLUGIN_MANAGER(o_plugin_manager_new());
        o_plugin_manager_load_modules(manager, ".libs", "test-init-data", NULL);        

        g_print("\n\nFound %d modules\n", o_plugin_manager_get_num_modules(manager));

        /* Check whether we got a 0'st module, call its configure function */
        if(o_plugin_manager_get_num_modules(manager) > 0) {
                plugin = o_plugin_manager_get_module(manager, 0);
                g_debug("Dumping module 0:\n");
                o_plugin_manager_plugin_dump(plugin);
        }

        g_object_unref(manager);

        return 0;
}

As you can see, this code loads all valid modules in .libs with the string "test-init-data" as init data, then checks whether a 0st plugin is available, and dumps the plugin info.

This is the current output:

** (process:14246): DEBUG: Loading all modules in .libs, suffix is so
** (process:14246): DEBUG: Suffix for .libs/libtestplugin.so is so, loading module
** (process:14246): DEBUG: [OPluginManagerPlugin] [test-plugin] Got an init function
** (process:14246): DEBUG: [test-plugin] Init with data "test-init-data"
** (process:14246): DEBUG: Module .libs/libtestplugin.so is valid, adding


Found 1 modules
** (process:14246): DEBUG: Dumping module 0:


================================================
Dumping data for: .libs/libtestplugin.so
=================
* Name: test-plugin
* Summary: A simple test plugin
* Description: This is a sample test plugin, to test the OPluginManager functionality
* Version: 0.1
* URI: http://www.eikke.com
* Authors:
        ikke
        -----------
                Email: eikke eikke com
                URI: http://www.eikke.com
        John Doe
        -----------
                Email: foo@bar.com
                URI: http://www.foobar.foo
* Module got an init function
* Module got a data free function
* Module got a configure function
================================================

** (process:14246): DEBUG: Deleting 1 modules
** (process:14246): DEBUG: [OPluginManagerPlugin] Freeing "test-plugin" data
** (process:14246): DEBUG: [OPluginManagerPlugin] Running free function
** (process:14246): DEBUG: [test-plugin] Freeing data "Test plugin data"

Here libtestplugin.so is the plugin you can see in the live.gnome wiki.

I also tried to implement a plugin structure in Python, although I'm no Python-expert at all. Current code is available here.
To give a little overview: every Python-based plugin should be a class extending from OPluginManagerPlugin, in this sample PluginTest is an implementation. There should be one fixed-name function in the __main__ module that returns an instance of this plugin class. Like this we just have to call that fixed-name function in our C wrapper, get it's return value in a PyObject *, then check whether it's type descends from OPluginManagerPlugin, and if that's the case start using the object as if it's just an OPluginManagerPlugin, we don't have to care about the details.
The code needs lots of enhancements and cleanups. If you could elaborate on this, please contact me. Especially the function-pointer part (passing (int)0 if no function is given) is ugly: I need to be able to check whether the var is a real function pointer before I call it, not only checking whether it's != 0. Next to this, I should figure out how to do proper error handling. Once that's done, I should be able to write a small wrapper plugin in C so I can start using plugins written in Python from within C.

Jun 12
Using Python objects in Python-C interop

As I wrote in my previous article, I did not know yet how to handle Python objects, and call their member functions.

After getting some help from Adam "adamh" Hooper, it became clear this is actually very easy to do.

Here's some code (I'm not reposting the whole C file, just append this to the end, it should be clear):

g_debug("Calling pytest::test using the helper function");
PyObject_CallMethod(ret, "test", NULL);

Py_XDECREF(ret);
ret = NULL;
        
g_debug("Calling pytest::test, no helper function");
g_debug("Creating a new pytest object");
ret = PyInstance_New(PyDict_GetItemString(dict, "" MODULE_NAME), NULL, NULL);
g_assert(ret != NULL);
PyObject_CallMethod(ret, "test", NULL);
Py_XDECREF(ret);

Watch out: you should not Py_XDECREF(ret) before doing this, of course.

As you can see there are 2 ways to achieve our goal:

  • In the first part of the snipper, we use "ret". This is the return value of the global function called "test", which is a "pytest" instance (the "test" function ends with return pytest()). We just call PyObject_CallMethod(object, name, args) to call the function.
  • In the first "solution" we use some ugly hack to get a pytest instance. In the second part we use a cleaner method, by calling PyInstance_New(type, constructor_args, kw). As you can see, we get "type" in the same way we got the entry point to the global "test" function. Now again we can just call a method on the object as in the first part.

This should be the output now:

** (process:13267): DEBUG: Initializing Python
** (process:13267): DEBUG: Setting PATH
** (process:13267): DEBUG: Trying to import "pytest"
** (process:13267): DEBUG: Success loading global test function
In main test function, argument is "testarg"
Initializing a pytest object
** (process:13267): DEBUG: Calling pytest::test using the helper function
In pytest's test function
** (process:13267): DEBUG: Calling pytest::test, no helper function
** (process:13267): DEBUG: Creating a new pytest object
Initializing a pytest object
In pytest's test function

Looks like Python/C interop is not that hard actually :-) You can find the final code here.

Jun 11
Calling Python from C

As I wrote on the OPluginManager overview page, I'd like to provide functionality to write plugins in Python. To achieve this I need to be able to call Python code from C (as the base OPluginManager framework is C-based). After asking around a little and reading some code samples (mostly in the Epiphany extension loading code) I figured out the basic calls one needs.

Here's what we need to do:
First we need some Python code. Take this as a test (pytest.py):

 class pytest:
        def __init__(self):
                print "Initializing a pytest object"

        def test(self):
                print "In pytest's test function"

def test(a):
        print "In main test function, argument is \"" + a + "\""
        return pytest()

Now we want to call some of this from C (pytest.c):


/* We want Python functionality */
#include <Python.h>
#include <glib.h>

/* To make life easier for us */
#define MODULE_NAME "pytest"

gint main(guint argc, gchar *argv[]) {
        /* The module object */
        PyObject *module = NULL;
        /* Objects we need to get a reference to a function */
        PyObject *dict = NULL, *func = NULL;
        /* Stuff we need to be able to load a module not in PYTHONPATH */
        PyObject *path = NULL, *pwd = NULL;
        /* Args we offer to the called function, and a reference to the return value */
        PyObject *args = NULL, *ret = NULL;

        /* Initialize the Python framework */
        g_debug("Initializing Python");
        Py_Initialize();

        /* "pytest.py" is in ".", so we need to alter the module search path
           "." is not in it by default */
        g_debug("Setting PATH");
        /* Get the current path (this is a list) */
        path = PySys_GetObject("path");
        /* Create a value to add to the list */
        pwd = PyString_FromString(".");
        /* And add it */
        PyList_Insert(path, 0, pwd);
        /* We don't need that string value anymore, so deref it */
        Py_DECREF(pwd);

        /* Load the module */
        g_debug("Trying to import \"%s\"", MODULE_NAME);
        module = PyImport_ImportModule("" MODULE_NAME);
        /* Check whether we succeeded */
        if(module == NULL) {
                /* If not, print the error message and get out of here */
                PyErr_Print();
                PyErr_Clear();
                g_warning("Failed to initialize \"%s\"", MODULE_NAME);
                return 1;
        }

        /* Get a dict from the module
           I should look up the API, but I presume this is something like
           "function_name" => function_entry_point */
        dict = PyModule_GetDict(module);
        /* Get the entry point of our "test" function
           This is -not- the pytest:test function */
        func = PyDict_GetItemString(dict, "test");

        /* Check again whether we succeeded, and whether the function can be called */
        if(func != NULL && PyCallable_Check(func) == TRUE) {
                g_debug("Success loading global test function");
        }
        else {
                /* Something bad occured, print out the Python error and abort */
                g_debug("Failed loading %s", MODULE_NAME);
                if(PyErr_Occurred()) {
                        PyErr_Print();
                        PyErr_Clear();
                }
                return 1;
        }

        /* We want to offer some args to the test(a) function
           These args should go into a tuple */
        /* Create a tuple with one element */
        args = PyTuple_New(1);
        /* Add a new element to the tuple, at position 0, a new string with content "testarg" */
        PyTuple_SetItem(args, 0, PyString_FromString("testarg"));

        /* Call the test function, with the "args" tuple as arguments */
        ret = PyObject_CallObject(func, args);
        /* Something went wrong.
           I must admit I still have to figure out what the return value of CallObject actually is.
           What would ret be if test(a) returns nothing? */
        if(ret == NULL) {
                /* Print error and abort */
                PyErr_Print();
                PyErr_Clear();
                g_warning("Failed to call test function");
                return 1;
        }

        /* Free the returned value, and the args tuple
           We don't really free, we unref the objects.
           I should look up what the difference between XDECREF and DECREF is. DECREF seems to be a standard unref thing */
        Py_XDECREF(ret);
        Py_DECREF(args);

        return 0;

        /* Maybe we should free the module too, and deinitialize Python
           This is not done in the code I read though */
}

Comments inline. This code might look huge, but actually it mostly consists of error checking ;-)

We need a rather "large" line to compile this:

gcc -o pytest -g `pkg-config --cflags --libs glib-2.0` -I/usr/include/python2.3 -lpython2.3 pytest.c

(You should adjust this to match your Python version if necessary)

When we run the program, this is what we get:

** (process:30233): DEBUG: Initializing Python
** (process:30233): DEBUG: Setting PATH
** (process:30233): DEBUG: Trying to import "pytest"
** (process:30233): DEBUG: Success loading global test function
In main test function, argument is "testarg"
Initializing a pytest object

Which is somewhat what we could expect.

In this sample I only use a global method, I don't use any Python object (like "pytest"). I must admit I don't know how to do this yet :oops: but hey, I'm just taking my first steps :-)

Jun 9
Done today
  • Created an initial page on OPluginManager on live.gnome.org.
  • Started writing a longer article on women in the FOSS community, now Gnome-Women was launched (actually, did that yesterday ;-))
  • Sent an email to the author of this article in our local newspaper to explain crackers are no hackers (and the other way around). WikiPedia got some decent information on this issue.
  • Did not study enough :-(

TODO:

  • Continue working on the OPluginManager design, then implement some more of it. Get to learn some more on GObject<->Python/Mono interaction, and Python/Mono<->native calling code (ie how to allow using an OPluginManager object in Python/C#, and how to allow OModuleLoader/OPluginManager to work with Python/C# based plugins).
  • Finish the mentioned article
  • Poke jdub to get some response (even if it's negative) ;-)
  • Write some of my ideas on the Tag based desktop down, decide wether to send it to desktop-devel@gnome or xdg@fdo, and do so accordingly.
  • Study!!!!
Jun 6
Debian Sarge released

I'm not willing to offend any Debian user, but this is just hilareous:
This release includes a number of up-to-date large software packages, such as the K Desktop Environment 3.3 (KDE), the GNOME desktop environment 2.8, the GNUstep desktop, XFree86 4.3.0, GIMP 2.2.6, Mozilla 1.7.8, Galeon 1.3.20, Mozilla Thunderbird 1.0.2, Firefox 1.0.4, PostgreSQL 7.4.7, MySQL 4.0.24 and 4.1.11a, GNU Compiler Collection 3.3.5 (GCC), Linux kernel versions 2.4.27 and 2.6.8, Apache 1.3.33 and 2.0.54, Samba 3.0.14, Python 2.3.5 and 2.4.1, Perl 5.8.4 and much more.

So

  • KDE 3.3
  • Gnome 2.8
  • XFree86 4.3.0
  • GCC 3.3.5
  • Linux kernel 2.6.8

are up-to-date now? Right :roll:

Disclaimer: I guess I could be flamed now as some some stupid Gentoo user thinking he's ultra 1337 etc etc, that's not my intention at all, I just think this is funny

[edit]As just seen on IRC:
17:48 <Em> the debian world must be in an uproar. you know. with gearing up for the next release in 2009
*grin*[/edit]

Jun 2
KEW2005

Just sit back and relax. Enjoy

If you really want to know what it is: Johannes Brahms' "Sonate nr. 3 in d Op. 108", by Yossif Ivanov (BE), 2nd price at the Queen Elisabeth concours last week. A magnificent piece in a superb performance. Partial movie is here, you need the latest WMP codecs to play it when running Linux.

Ikke • LifePermalink 2 comments
Jun 1
10X10


No comment ;-) Let's go for it.

May 29
OPluginManager

I've been working on my OPluginManager lately (not too much, got to study too, and watched the Queen Elisabeth concours of course ;-)).

This is what I got now (it's my first GTK code ever, so I'm quite happy with it):

This is the "plugin" code:

#include "plugins/o-plugin-manager-plugin.h"
#include "plugins/o-plugin-manager-plugin-data.h"

#define TEST_PLUGIN_MSG "[test-plugin] "

static gpointer plugin_init(gpointer d, GError **e) {
        g_debug("" TEST_PLUGIN_MSG "Init");
        return (gpointer) g_strdup("Test plugin data");
}

static void free_data(gpointer d) {
        g_debug("" TEST_PLUGIN_MSG "Freeing data \"%s\"", (gchar *) d);

        g_free(d);
}

static OPluginManagerPluginAuthorData author = {
        O_PLUGIN_MANAGER_PLUGIN_DATA_AUTHOR_MAGIC,
        "ikke",
        "eikke eikke com"
};

static OPluginManagerPluginData plugininfo = {
        O_PLUGIN_MANAGER_PLUGIN_DATA_MAGIC,
        "test-plugin",
        "A simple test plugin",
        "This is a sample test plugin, to test the OPluginManager functionality",
        "0.1",
        "http://www.eikke.com",
        &author,

        NULL,
        plugin_init,
        free_data
};

O_PLUGIN_MANAGER_PLUGIN_REGISTER(plugininfo);

As you can see it's braindead easy to write a plugin :-)

The code is quite a mess at the moment, the UI is just plain ugly and inaccessible, there's no I18N support, but well, as you can see, one day it might work :-)

Lots of guys I know are in Stuttgart right now, visiting GUADEC. I wish I could be there too :-( Have a great time!!!

May 29
GVim

Just had a little chat with Ruben on Vim, where he suggested me to put my .vimrc etc online.

So I did, this is my current GVim setup:


(Thumbnail is link to original image)

And here's my current .vimrc. If you know any other fancy tricks I could use, please let me know :-)

A lot of useful information on configuring your Vim is available here.

May 25
Nokia

Ok, I admit, I also want one. Just check Planet Gnome if you don't know what I'm talking about.

May 24
Gnome stuff

Some new Topaz mockups were created, showing another (more radical IMHO) view on what Gnome3 should become, like these before. If you want to comment on them, desktop-devel is the place to be.

Since today, I got write access to Gnome CVS, mostly thanks to Philip and Ronald. Thank you guys! Just got the documentation building of asyncworker working (I hope at least ;-)), patch submitted (edit: and committed. My first one :-)). I'll import my first work on OPluginManager somewhere later this week.

And I may not forget to send out some emails to find some holiday job. As I'm a lazy bum, I still didn't send them :oops:

May 24
OModuleLoader

It looks like I have to release the current code I got for OModuleLoader/OPluginManager. Well, here it is. Still needs a lot of love, but hey ;-)

May 22
C preprocessor magic

Did you ever run in this situation where you need to #define some string, and use it both as a function name and as a string? As you might have discovered it is not easily possible to do this.

I ran into this problem today, and found out you got to solve it using 2 extra macro's (thanks to this page):

#include <stdio.h>

#define xstr(s) str(s)
#define str(s) #s

#define FOO foobar

void FOO() {
        printf("In %s\n" xstr(FOO));
}

int main() {
        /* This won't work because FOO is no string */
        /* printf("FOO is \"%s\"\n", FOO); */
        printf("FOO is \"%s\"\n", xstr(FOO));
        FOO();
        return 0;
}

which gives the desired result:

FOO is "foobar"
In foobar

and inspecting the output of nm, the function is correctly called "foobar", not "FOO". Jay!

[edit] Once more I just got blown away by what glib offers you. G_STRINGIFY is defined by default when you include glib.h (in glib/gmacros.h more precisely).

May 21
GModuleLoader

After Philip was talking about his GQueueThread/ASyncWorker on #gnome-nl, I was tempted to write some Glib-extension too, and so I did.

You might remember the extra exercise in my article on GModules and vtables, about loading all modules in the current directory and use them. Well, I created a generic object to handle this, because it's a functionality needed quite frequently in plugin-based programs.

I called this "GModuleLoader" ;-)

Here's a sample client application, loading 2 modules:

#include <glib.h>
#include <gmodule.h>

#include "g-module-loader.h"
#include "g-module-loader-module.h"

gint main(gint argc, gchar *argv[]) {
        GModuleLoader *l = NULL;
        guint cnt = 0;
        GPtrArray *modules = NULL;

        g_type_init();

        /* Create a new GModuleLoader */
        l = (GModuleLoader *) g_module_loader_new();
        g_assert(l != NULL);

        /* Load all modules in ".libs", with "simple-test" as data.
         * We do not want any error reporting (yet) */
        g_module_loader_load(l, ".libs", "simple-test", NULL);

        g_print("\n\nLooping through all loaded modules, printing the data\n");
        /* Get the list of all modules */
        modules = g_module_loader_get_modules(l);
        if(modules == NULL) {
                g_object_unref(l);
                g_error("No modules in list, aborting");
                return 1;
        }
        
        /* Loop */
        for(cnt = 0; cnt < modules->len; cnt++) {
                GModuleLoaderModule *m = NULL;
                gchar *data = NULL;
                GModule *mod = NULL;

                /* Get the GModuleLoaderModule */
                m = (GModuleLoaderModule *) g_ptr_array_index(modules, cnt);
                /* Normally we don't ever need the real GModule,
                 * because we use a vtable with all tables we need as returned
                 * data from the init function */
                mod = g_module_loader_module_get_module(m);
                if(m == NULL) {
                        g_error("Module in a GModuleLoaderModule should never be null");
                        return 1;
                }
                /* This is the data returned by the module init function.
                 * Most times this will be a vtable/struct */
                data = g_module_loader_module_get_module_data(m);

                g_print("%s:\t%s\n", g_module_name(mod), data);
        }
        g_print("\n");
        
        /* Clean up */
        g_object_unref(l);
        
        return 0;
}

I hope this is understandable :-)

Here's the code for "module1.c", the source for libmodule1.so. "module2.c" is almost the same: s/M1/M2 and s/module1/module2:

#include <glib.h>
#include <gmodule.h>

/* This is a fixed name, the module init function
 * It takes a pointer (given by the client code)
 * and can return some data (most of the time a vtable/struct, we keep it 
 * simple here) */
G_MODULE_EXPORT gpointer module_get_data(gpointer data) {
        gchar *s = NULL;
        
        s = (gchar *) data;
        if(s != NULL) {
                g_print("\n[M1] Module1 loaded with data \"%s\"\n\n", s);
        }

        return g_strdup("[M1] module1data");
}

/* Same thing, fixed name.
 * This function takes a pointer to the data given by module_get_data
 * and is called when this data should be freed */
G_MODULE_EXPORT void module_free_data(gpointer data) {
        gchar *s = NULL;
        
        s = (gchar *) data;
        if(s != NULL) {
                g_print("\n[M1] Freeing module1 data \"%s\"\n\n", s);
                g_free(data);
        }

        return;
}

As you can see I'm using fixed names in the plugins, I don't think there's any other way to do this kind of things. None of these 2 functions are required though.

Here's the output of the test application:

# ./simple-test
** (process:24094): DEBUG: Loading all modules in .libs, suffix is so
** (process:24094): DEBUG: Suffix for .libs/libmodule1.so is so, loading module
** (process:24094): DEBUG: Loading data for .libs/libmodule1.so

[M1] Module1 loaded with data "simple-test"

** (process:24094): DEBUG: Module .libs/libmodule1.so is valid, adding
** (process:24094): DEBUG: Suffix for .libs/libmodule2.so is so, loading module
** (process:24094): DEBUG: Loading data for .libs/libmodule2.so

[M2] Module2 loaded with data "simple-test"

** (process:24094): DEBUG: Module .libs/libmodule2.so is valid, adding


Looping through all loaded modules, printing the data
.libs/libmodule1.so:    [M1] module1data
.libs/libmodule2.so:    [M2] module2data

** (process:24094): DEBUG: Deleting 2 modules
** (process:24094): DEBUG: Freeing data for .libs/libmodule1.so

[M1] Freeing module1 data "[M1] module1data"

** (process:24094): DEBUG: Closing module .libs/libmodule1.so
** (process:24094): DEBUG: Freeing data for .libs/libmodule2.so

[M2] Freeing module2 data "[M2] module2data"

** (process:24094): DEBUG: Closing module .libs/libmodule2.so

It should be fairly easy to follow all steps, find out the module_get_data and module_free_data calls, etc.

It's working fairly well now, I'll try to enhance it some more, test it better and document it, then maybe I'll send some email to the Glib list ;-)

May 19
GModules and vtables

After the article I posted yesterday on GModules, I just wrote some sample code using a vtable to look up functions, which makes module handling much easier.

I guess we better go straight to the code:

First we need to define some structure that represents our vtable. I did this in a common header file, vtable-common.h:

#ifndef _VTABLE_COMMON_H
#define _VTABLE_COMMON_H

#include <glib.h>

typedef void (* voidvoidfunc) (void);
typedef gint (* intvoidfunc) (void);
typedef void (* voidstringfunc) (gchar *s);
typedef gboolean (* boolpstringfunc) (gchar **ps);
/* This function will demonstrate NULL function pointers */
typedef void (* foofunc) (void);

typedef struct VtableTest {
        voidvoidfunc funcone;
        intvoidfunc functwo;
        voidstringfunc functhree;
        boolpstringfunc funcfour;
        foofunc funcfive;
} VtableTest;

/* Module init function */
typedef VtableTest * (* VtableTestInit) (void);

#endif

First we define typedefs for all function prototypes we want in our vtable, then we define the prototype of a module init function.

This may look a bit strange, let's take a look at the module code (in vtable-module.c) to see what we can do with this:

#include <glib.h>
#include <gmodule.h>

#include "vtable-common.h"

/* Our vtable function implementations */
static void one() {
        g_print("[M] Function 1\n");
}

static gint two() {
        g_print("[M] Function 2\n");
        return 2;
}

static void three(gchar *s) {
        g_print("[M] Function 3: %s\n", s);
}

static gboolean four(gchar **s) {
        g_print("[M] Function 4\n");
        *s = g_strdup("four");
        return TRUE;
}

/* Our function table.
 * As you can see, we put functions in there as if they're normal variables */
static VtableTest table = {
        one,
        two,
        three,
        four,
        /* This module does not implement funcfive */
        NULL
};

/* This is the module init function.
 * It's a "VtableTestInit" function, as defined in vtable-common.h */
G_MODULE_EXPORT VtableTest * vtable_module_init() {
        g_debug("[M] Initializing module");
        /* Of course you can do a lot in this function,
         * we don't need to do anything in this sample */
        /* Return a reference to the function table */
        return &table;
}

The comments in the code should explain every step pretty well.
As you can see we only export one function, vtable_module_init. This function got a fixed name (so we should define this name in our API). It returns a pointer to a vtable of type VtableTest, which includes pointers to all function implementations.

Last but not least is the main code, in vtable-main.c:

#include <glib.h>
#include <gmodule.h>

#include "vtable-common.h"

gint main(gint argc, gchar *argv[]) {
        /* Same handles as yesterday */
        GModule *module = NULL;
        VtableTest *moduletable = NULL;
        gchar *modulepath = NULL, *dir = NULL;
        VtableTestInit moduleinitfunc = NULL;
        /* Function value */
        gint two = 0;
        gboolean fourb = FALSE;
        gchar *fours = NULL;
        
        /* Same stuff as yesterday */
        if(g_module_supported() == FALSE)
                g_error("No module support");

        dir = g_get_current_dir();
        modulepath = g_module_build_path((const gchar *) dir, "vtabletestmodule");
        g_debug("Module path: %s", modulepath);
        module = g_module_open(modulepath, G_MODULE_BIND_LAZY);
        g_free(dir);
        g_free(modulepath);
        if(module == NULL)
                g_error("Unable to load module");

        /* We need to lookup one function, which inits our vtable */
        if(g_module_symbol(module, "vtable_module_init", (gpointer *) &moduleinitfunc) == FALSE) {
                g_error("Unable to get reference to the module init function: %s", g_module_error());
        }

        /* Get a reference to the module function table */
        moduletable = moduleinitfunc();

        /* Run all our functions, providing parameters or fetching return
         * values where necessary */
        if(moduletable->funcone != NULL) {
                g_debug("Running module funcone");
                moduletable->funcone();
        }
        else {
                g_warning("Funcone is NULL");
        }

        if(moduletable->functwo != NULL) {
                g_debug("Running module functwo");
                two = moduletable->functwo();
                g_debug("functwo returned %d", two);
        }
        else {
                g_warning("Functwo is NULL");
        }

        if(moduletable->functhree != NULL) {
                g_debug("Running module functhree");
                moduletable->functhree("vtable-module-test");
        }
        else {
                g_warning("Functhree is NULL");
        }

        if(moduletable->funcfour != NULL) {
                g_debug("Running module funcfour");
                fourb = moduletable->funcfour(&fours);
                g_debug("funcfour returned \"%s\", string value is \"%s\"", fourb == TRUE? "true" : "false", fours);
        }
        else {
                g_warning("Funcfour is NULL");
        }

        if(moduletable->funcfive != NULL) {
                g_debug("Running module funcfive");
                moduletable->funcfive();
        }
        else {
                g_warning("Funcfive is NULL");
        }

        /* As yesterday, close the module */
        if(g_module_close(module) == FALSE) {
                g_error("Unable to close module: %s", g_module_error());
        }

        return 0;
}

These are the steps we take:

  • Load the module (see the previous article for more information on this)
  • Look up one symbol, "vtable_init_module". As mentioned before, this is the fixed name symbol that should be exported from our module.
  • run "vtable_module_init", so we get a reference to the module's vtable
  • Now we can use all functions refered to in the vtable. Make sure you always check for NULL pointers, or your application will crash. Even if your API/documentation states a module author must implement all vtable functions, checks don't hurt :-) Notice we call the functions using moduletable->foofunc(), so the vtable members are really normal function pointers, nothing fancy here.
  • We clean up by closing the module

You can compile everything with this simple Makefile (yes I know it's a bad one):

default: main libvtabletestmodule.so
all: default

main: vtable-main.c vtable-common.h
	gcc -o main -g `pkg-config --cflags --libs glib-2.0 gmodule-2.0` vtable-main.c

libvtabletestmodule.so: vtable-module.c vtable-common.h
	gcc -o libvtabletestmodule.so -g -shared `pkg-config --cflags --libs glib-2.0 gmodule-2.0` vtable-module.c

or execute the commands by hand, of course.

Here's the output:

** (process:16338): DEBUG: Module path: /home/foo/bar/vtable/libvtabletestmodule.so
** (process:16338): DEBUG: [M] Initializing module
** (process:16338): DEBUG: Running module funcone
[M] Function 1
** (process:16338): DEBUG: Running module functwo
[M] Function 2
** (process:16338): DEBUG: functwo returned 2
** (process:16338): DEBUG: Running module functhree
[M] Function 3: vtable-module-test
** (process:16338): DEBUG: Running module funcfour
[M] Function 4
** (process:16338): DEBUG: funcfour returned "true", string value is "four"

** (process:16338): WARNING **: Funcfive is NULL

As you can see, all this is quite logical and easy to write once you figure out how to. The provided functionality can be very useful though.
Notice thanks to glib, the code presented here should compile and run under Linux, Solaris and all other supported platforms (yes, even on Windows using DLL's) without any code change.

A little exercise for the reader: currently we got the module name "vtabletestmodule" hardcoded in vtable-main.c. What to do if we have several VtableTest implementations, e.g. vtabletestmodule1 and vtabletestmodule2? We could loop through all files in ".", find out whether they're a valid module (ie try to load them), if they're a valid module, try to figure out whether it exports "vtable_module_init", if that's the case, get a reference to the module's vtable, and use it. This is eg the way Gaim loads all it's plugins (although the module files aren't stored in "." of course). It's not too difficult to implement this, but the result is quite impressive too, so give it a try :-)

May 18
GModules are fun

Glib's GModules are fun :-) These functions provide a braindead interface to modular (think "plug-in based") programming. I wrote some testing code today (read the API a year ago or so but never played with it), here's a short introduction.

When writing module based applications there are mainly 2 parts: the modules, and the application using them. So we'll have to write these 2 things.

Getting started with the module is the easiest part:

#include <glib.h>
#include <gmodule.h>

G_MODULE_EXPORT void m_helloworld() {
        g_print("Hello modular world!\n");
}

This code is pretty straight-forward. The only "strange" thing is G_MODULE_EXPORT, a platform-independent macro telling the compiler/linker to export the function.

Then comes the "client" application, a little more difficult. Comments inline:

#include <glib.h>
#include <gmodule.h>

/* A prototype of the function pointer we'll use */
/* void function(void) */
typedef void (*HelloWorldFunc) (void);

gint main(gint argc, gchar *argv[]) {
        /* We need:
         * - A handle to our module
         * - A pointer to the function we'll import
         * - Some helper strings */
        GModule *module = NULL;
        HelloWorldFunc hello = NULL;
        gchar *module_path = NULL, *curr = NULL;

        /* Check whether glib is compiled with module support */
        if(g_module_supported() == FALSE) {
                g_error("Modules not supported :(");
                return 1;
        }
        
        /* We need to figure out the path to our module. In our test case, this
         * is ".", so we want the current dir. */
        curr = g_get_current_dir();
        /* Create the path to the module. This function does quite a lot of
         * of things, check the GModule API. */
        module_path = g_module_build_path((const gchar *) curr, "module");
        /* Don't we love debugging? */
        g_debug("Module path: %s", module_path);

        /* Finally we're able to open the module. We want lazy symbol resolving.
         * This means we only want a symbol to be resolved if we request it.
         * Once more, see the API for more information. */
        module = g_module_open(module_path, G_MODULE_BIND_LAZY);

        /* Get rid of those helper strings */
        g_free(module_path);
        g_free(curr);

        /* Check whether the module was loaded successfully */
        if(module == NULL) {
                g_error("Unable to load module");
                return 1;
        }

        /* Load the symbol and assign it to our function pointer. 
         * Check for errors */
        if(g_module_symbol(module, "m_helloworld", (gpointer *) &hello) == FALSE) {
                g_error("Unable to get function reference: %s", g_module_error());
                return 1;
        }

        /* Now we can call our funtion.
         * As you can see, we can call it as if it's a normal function.
         * Don't we love function pointers? */
        hello();

        /* We're nice citizens and close all references when we leave */
        if(g_module_close(module) == FALSE) {
                g_error("Unable to close module: %s", g_module_error());
                return 1;
        }

        return 0;
}

(this looks like a lot of code (well...) but if you strip all comments and debugging stuff/checks, you'll only have 10 lines or so)

Should be quite easy to understand too.

Now it's compile time. Of course, in a real-world situation, we'd use autotools to compile our libraries, we'd have a libtoolized library etc etc etc. Here we'll do it in the quick-and-dirty way:

# gcc -o libmodule.so -shared `pkg-config --libs --cflags glib-2.0 gmodule-2.0` module.c
# gcc -o main `pkg-config --libs --cflags glib-2.0 gmodule-2.0` main.c
# ls
libmodule.so  main  main.c  module.c
# ./main
** (process:26533): DEBUG: Module path: /home/foo/bar/libmodule.so
Hello modular world!

Loading all these symbols by hand is a boring task, so most of the time you'll create some API using vtables to make your life easier. More on this later (got to study now ;-) :|)

May 18
Portage on Windows

Maybe one day we'll be able to get lots of *nix software running under Windows using Gentoo's Portage. Read this.

Ikke • LifePermalink 7 comments
May 17
Sysstats.sh

I wrote a little Bash script this morning, which gives a quick overview of your system.
As mentioned in the help text, this can be very usefull for server administrators, eg allowing you to let an overview be sent to your mailbox every 24h using a cronjob.

This is a sample of the current output:

================================================================
* System statistics for:        foo.baar.be
* Generated on:                 Tue May 17 15:00:49 CEST 2005
* Running as:                   root

=================== Uptime =====================================
* Uptime:                       4 days, 04:37:29
* High score:                   151 days, 19:15:18
* Load average:                 0.32 0.24 0.22

=================== Users ======================================
* Active users:                 2
* User information
        USER     TTY        LOGIN@   IDLE   JCPU   PCPU WHAT
        someone pts/0     12:15    2.00s  0.62s  0.05s sshd: ntrangez [priv]
        someone pts/1     13:30    5:19   1.17s  0.05s sshd: ntrangez [priv]

=================== Tasks ======================================
* Number of running tasks:      62
* Running programs:
agetty          events/0        kjournald       lockd           portmap         sh
aio/0           fcron           kseriod         mysqld          ps              sshd
apache2         init            ksoftirqd/0     mysqld_safe     rpc.mountd      su
bash            kblockd/0       kswapd0         nfsd            rpc.statd       syslog-ng
boa             khelper         kthread         pdflush         rpciod/0        uptimed

* CPU load:                     2%
* Process state:
        Running:                1
        Sleeping:               60
        Zombie:                 0
        Stopped:                0

=================== Networking ================================
* Routing table:
        Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
        192.168.2.0     wifi.vtk.ugent. 255.255.255.0   UG    0      0        0 eth0
        192.168.1.0     *               255.255.255.0   U     0      0        0 eth0
        loopback        webvtk.vtk.ugen 255.0.0.0       UG    0      0        0 lo
        default         fire.vtk.ugent. 0.0.0.0         UG    0      0        0 eth0

=================== Hard Disc =================================
* Disk Information:
        Filesystem            Size  Used Avail Use% Mounted on
        /dev/hdc4             4.5G  3.2G  1.1G  75% /
        /dev/hdc5              14G   11G  2.4G  82% /var/www

* Mounts:
        /dev/hdc4 on / type ext3 (rw,noatime)
        none on /proc type proc (rw)
        none on /sys type sysfs (rw)
        none on /dev type ramfs (rw)
        none on /dev/pts type devpts (rw)
        /dev/hdc5 on /var/www type ext3 (rw,noexec,nosuid,nodev,noatime,acl)
        none on /dev/shm type tmpfs (rw)
        nfsd on /proc/fs/nfs type nfsd (rw)

=================== MD5Sum Check ==============================
* Checking MD5 Sums
        /etc/passwd:                            [OK]
        /etc/shadow:                            [OK]
        /etc/group:                             [OK]

===============================================================
* Brought to you by Ikke - http://www.eikke.com

A TODO is included in the script source.

I made the script available here (enscript version here). If you use it, please let me know something :-) Or even better, if you add more support, please send me a patch so everyone can make use of it :-)

It has no special dependencies, next to Bash and some standard utilities like wc, bc, tail, md5sum, awk and grep.
The "record uptime" is only displayed if you got uprecords (/usr/bin/uprecords) installed.
Make sure you check the md5sum part, can be very usefull :-)

May 16
Anjuta 2

A 2.x alpha release of Anjuta, the GTK/Gnome-oriented IDE, has been released.
I must admit the screenshots and features look nice: integrated debugger (GDB based), glade3 support, GObject class building wizard, member completion,...

Maybe time to give it another test drive. Although I doubt it can beat gVim :-) What do you think, Realnitro?

May 15
ContactFS working


(Thumbnail is link to original image)

Needs no comment I guess :-)

Still some problems left:

  • Files with spaces in the filename (ie almost every file in this case) don't work :-( This shouldn't be too hard to solve though (edit: fixed)
  • Read-only
  • No VCard as output. This can be easily solved though (edit: fixed)
  • The init func creating a Node tree from your contacts is blocking, which is bad
  • The Icon issue. Looks like vcards can contain picture information, so I could just write a vcard-thumbnailer and add it to Nautilus.

Now guess what the problem was... Not my code, but the fact I use autotools to compile the thing. Autotools seems to add some fancy compiler flags which made the module crashy as hell, just using "gcc -Wall $(pkg-config --cflags --libs gnome-vfs-module-2.0 libebook-1.2) -shared -fPIC ContactFS.c -o libContactFS.so" worked fine. Guess I'll have to tweak my Makefile.am somehow. (edit: this wasn't autotools fault, but (of course) mine. I added some flags to Makefile.am I got from an official GnomeVFS module's Makefile.am, looks like those weren't nice)

Huge thanks to "gicmo" for all the help.

Oh, and XNest rocks :-)

[update]

May 15
ContactFS progress

Screenshot shows some progress I made with ContactFS. If I "browse" to contact:/, I get 2 "directories", Personal and Test, which are my 2 Evolution address books. I can "cd" into "Test", "ls" all "files" (contacts) in there, and if I try to "cat" one of them, I get some information on that contact (just plaintext for now, this should become a FOAF or VCard formatted string).

In GnomeVFS' test-shell application the module works fine, but if I try to open contact: in Nautilus, it crashes. Maybe I should send an email to Alex to beg for a little help here ;-)
I'll also need his help on how to set file thumbnails once it works in Nautilus (the actual file is just plain text, but I'd like to have the contact's picture as icon in Nautilus, or if no picture is set, /usr/share/pixmaps/nobody.png).

Moving "files" between "directories" would be nice too, but I don't know whether EDS allows writing, need to figure that out.

May 13
ContactFS

I got the insane (well, not really ;-)) idea today to write a GnomeVFS module that allows you to browse your Evolution EDS contacts using any GnomeVFS-capable application, like Nautilus, as a Proof Of Concept. This is the first GnomeVFS module I write.

Started working on it, and I got a basic module working. It does not get any information from EDS yet, only contains one "file" named JohnDoe, can be very instable,... but well ;-)

Here's a little screenshot:

Currently the "contact files" only have "test" as content, this should become a VCard string, or maybe a FOAF document.

Other things to do:

  • assign a proper MIME type, so I can take advantage of Evo's "Picture" contact-property (so you see the picture as "icon" of the "file", if this is possible at all).
  • assign a proper handler to the "open" action (e.g. open a Mailto: window)
  • Fetch real information from Evo, of course
  • Make it stable (the current tree contains dead pointers, I need to learn using GNode's) and thread-safe
  • ...

Maybe this won't be really usefull, but someone suggested to have some VFS module for Soylent too, so I'm gaining some experience here :-)

May 13
Regarding Microsoft

Although I'm hardly using any Microsoft software anymore, I still admit they got some great things, like their .Net framework and the corresponding IDE, VS.Net (don't hate me now).
This could be some great proof of concept/research technology too.

On the other hand: what did they smoke?

May 12
FeedMerge mostly done

JAY!!!! :-D

As I blogged before I've been working on a PlanetPlanet implementation in C. I got a basic RSS2 parser working before, but that code was plain ugly.

Now I refactored all code using GObjects (learnt a lot whilst doing this), and it works :-D
Currently it can parse RSS2 feeds (as many as your memory allows you to ;-)) and combine them into one RSS2 feed. Adding more feed types should be fairly easy.

This is a sample result, and here you can see a FeedValidator validation result. Never mind the encoding issue, that's related to the server settings of the machine I'm hosted on (and I'm no administrator :-().

This is the code I used to generate the feed:

#include <glib.h>
#include <libxml/tree.h>

#include "src/feedmerge-feed.h"
#include "src/feedmerge-merge.h"

gint main(gint argc, gchar *argv[]) {
        FeedMergeFeed *feed1 = NULL, *feed2 = NULL;
        GSList *feeds = NULL;
        xmlDoc *doc = NULL;

        g_type_init();

        feed1 = (FeedMergeFeed *) feedmerge_feed_new();
        feed2 = (FeedMergeFeed *) feedmerge_feed_new();

        feedmerge_feed_fetch_feed(feed1, "http://blog.eikke.com/xmlsrv/rss2.php?blog=1");
        feedmerge_feed_fetch_feed(feed2, "http://blog.eikke.com/xmlsrv/rss2.php?blog=7");

        feedmerge_feed_parse_document(feed1);
        feedmerge_feed_parse_document(feed2);

        /* feedmerge_feed_dump(feed2); */
        feeds = g_slist_append(feeds, feed1);
        feeds = g_slist_append(feeds, feed2);

        /* output type, GSList containing the feeds, feed title, URI and description */
        doc = feedmerge_merge_merge(FEEDMERGE_FEED_TYPE_RSS_200, feeds,
            "Test feed", "http://blog.eikke.com/ikke", "This is a test merged feed");

        g_assert(doc != NULL);

        /* output to stdout */
        xmlSaveFormatFileEnc("-", doc, "UTF-8", 1);

        xmlFreeDoc(doc);

        g_object_unref(feed1);
        g_object_unref(feed2);
        g_slist_free(feeds);
}

Using gob2 again to write my objects, it's just a pleasure to play with :-) Strong type checking is automagically added etc, just great. I'm eager to see some GObject introspection samples.

Of course what I got now can be further abstracted to something like this:

xmlDoc *doc = feedmerge_vamerge("http://a.b/feed1.xml", "file:///tmp/feed2.xml",
    "scp://somehost:/test.xml", "Title", "http://www.eikke.com", "This is a nifty combined feed");

i.e. using varargs.

Thanks to GnomeVFS I don't have to care where the feed comes from, which is just great.

I had to handle some nasty and stupid bugs while coding this (in my own code, of course) and propably I leak memory at several places too, but well... ;-) We got valgrind :-) And thanks to the GCC people for blessing us with the "-Werror" flag, I love that feature.
I won't publish the code yet, but maybe it'll get into Soylent (who knows?) so then it'll be in some CVS/SVN/whatever repository.

Regarding Soylent: we're looking for a new name. Please help us out, I can't wait to start doing some real work.

That's it for now.

May 7
MSN Webcam functionality part II and minor coding

Why didn't I hear about this any earlier, and why isn't it integrated into Gaim?

Oh, for Soylent, I started working on blog feed reading. Currently I got some code that can read an XML feed from any GnomeVFS source, and create a libxml2 xmlDoc out of it. Although maybe I should use SAX to merge different feeds...
Using an XSLT sheet to merge feeds would be really cool and clean, but I think it's the hardest way too ;-)
I tried to document the code well again, it's available here. Can be a nice introduction to GnomeVFS coding :-) (this was my first code using it too ;-))

TODO: add a check to see whether what we pull in is an RSS feed, before loading the whole document, to save bandwidth and memory.

May 6
First EDS code

I started looking into evolution-data-server today, to look what we could use in Project Soylent (actually, I shouldn't blog on it because we don't want any noise on it yet :-)). The result is some code that can dump all your address books, or only dump some of the contacts using a filter string.

Because libebook is very poor documented (unfortunately, even the API docs aren't complete) I tried to document the code as good as possible. Please review it, let me know when some things are not well documented, or I just make dumb mistakes in the code :-D
The last version I made is here.

Compile it using
gcc -o evo-addressbooks-test2 `pkg-config --cflags --libs libbonobo-2.0 libebook-1.2` evo-addressbooks-test2.c
Dump your address books using
./evo-addressbook-test2
or use a filter string as first argument. Beware: you should Bash-escape the argument!!!
A sample of this:
./evo-addressbooks-test2 "(contains \"full_name\" \"John Doe\")"
will list some properties of the entry which has "John Doe" as it's full name.

I hope I'll be able to hack on this some more, and also hope we'll get a good view of what Soylent should become soon :-)
It'll be a great oportunity to learn some more aspects of Gnome coding, like GTK/Glade, Bonobo (|-|) and others.

May 6
New blog engine and Soylent

As I mentioned before, I'd like to start using another blogging engine as soon as possible. Plog looked nice, but after giving it a test drive I got into some little annoying problems.
Now the b2evolution guys seem to prepare a maintainance version, so development hasn't completely stalled.

Currently, the blogs (mine and the others I host) run fine I think, and migrating would be quite a lot of work (existing users and posts, not to mention changes of URI's towards aggregators), so I guess I'll wait some longer, unless someone knows a very good engine I could start using, actively maintained.
The main "issue" I got is the fact I host multiple blogs. Most engines don't support this...

Project Soylent is getting started, jay :-) Just read something on using Evolution's libebook API and FOAF, this will be some fun project to work on B-)

Oh, and please everyone vote for davyvandenbremt.be on may1reboot.com.

May 4
Southpark Character


Do what others do

Maybe I should just use this as my hackergotchi, I'd scare people by using a "real" one ;-)
(PNG version now :-))

Ikke • LifePermalink 4 comments
May 2
Why

Karel, why oh why did you this? People seem not to understand I'm not intending to run MSN7 as my default Messenger at all, just trying to solve some little annoyance? Do they actually read what I wrote?

Just tried amsn-cvs. It crashed when I tried to start a normal conversation with someone, then worked fine. I did not try videochat support yet though, none of my contacts owning a webcam came online untill now.

May 1
MSN7 under Linux


(thumbnail is link to full size screenshot)

I want MSN Video Chat (receipt) working. Under Linux. As soon as possible. So I tried getting MSN Messenger working under Wine.

As you can see, it works. But only a little. This is the bloated version 7 of the official client, and Wine seems to be unable to handle it properly. It's using non-standard windows (actually, it are clipped standard windows) etc. I did not try the webcam feature either.

Has anyone got an installer for MSN Messenger 6.x for Windows 98/Me? I'd like to try that one too, but only "beta" version 7 is available on the official website. A commercial software vendor only offering beta versions of it's software to the users... :roll:

Maybe I should just run a stripped Windows session under that great version 5 of VMWare Workstation as RubenV just suggested, and take the easy way ;-) Or try aMsn which should get videochat support soon (it's already in CVS I heard, Scapor?), but I hate that Tcl/Tk interface :-(

Apr 30
Kolab

I just installed Kolab on my desktop machine, just to play around with it, and I must say I'm impressed. This is the most integrated groupware-like suite I've ever worked with.
Based on existing open source solutions like

  • Postfix
  • Cyrus Sasl
  • SpamAssassin
  • Amavis
  • Apache
  • Cyrus IMAP
  • Mysql
  • OpenLdap
  • Sieve
  • PHP

and others, you get a completely integrated mailserver, userbase, calendars,... with a nice webinterface for administration purposes.

I installed Horde as user frontend, which took some time, but now it's working almost well. Using Horde the user gets a well-integrated web interface to his email, calendars, address books, Sieve mail filters, notes and tasks etc.

This is definately something we should look into at VTK. When using Horde as user interface, we could even allow our users to access their Eduserv email from the same interface etc, which would be really nice. The implementation could easily be done in a multiple steps: first get all email stuff working, then addressbooks, then calendars,...
I wonder whether it could be possible to extend the "standard" Kolab "User" LDAP object so it can also be used for Samba3 LDAP authentication? If that'd be possible, this is definately the application to use on our new server :-)

Screenshots might follow later ;-)

Apr 28
Evince, new vinyl and more

Evince
(click on the image to enlarge it)

I got Evince working :-) I had some troubles with it (wrong library naming: shell/Makefile.am adds -lt1lib when compiled with t1lib support, where t1lib only installs libt1.so on my system (default Gentoo t1lib build), resulting in a linker error. A symlink could have solved this, but that's an ugly solution, so now I patch shell/Makefile.am in the ebuild. I could even use sed, actually, because it's a one-line patch) but now everything works fine, including the popplet, dvi en djvu backend.

PDF font anti-aliasing works fine, but I couldn't get previewing (i.e. the feature enabling you to put a PDF file on your desktop, displaying not the icon assigned to PDF files, but the content of the file, as if it were an image or a plain text file) working yet :-( Guess I'll have to dig around some more, or is this a -cvs only feature? I got evince-thumbnailer installed, and it seems to be working fine though...

I bought the vinyl of Shameboy's first release, "Re-choque". The track has been hyped on Studio Brussel, a Flemish radio station, for a long time now. Shameboy is a project around Jimmy Dewit aka "DJ Bobby Ewing" (of Dicobar Galaxy fame), Luuk Cox (Budcemi's drummer) and a mysterious guy called "Mr. Morceau". Some phat beats blended with 80's electro synths and some great producers provide all ingredients for a great dance track. Guess that's the reason why this track is #1 on the Belgian dance charts for several weeks already :-)


If you want to hear some part of the track, check this.

I'm thinking of replacing my current b2evolution install with some other engine. b2evolution's development seems to have stalled completely, and some other products look very appealing. Some of the features I certainly need:

  • Multiple blogs hosted by one engine
  • Multi-user capabilities, with access controls (who can write to which blog?)
  • Themes (and preferably lots of themes available on the net ;-))

The main issue I'm facing is converting all current posts we got here to the new system...
If someone got a good suggestion, let me know :-)

Last but not least: we're making progress with the FedoraStateless@University project :-D Finally... :oops:

Apr 26
Software highlights of the day

Now VMWare Workstation 5 for Linux is being packaged (and will be released soon, if I'm not mistaken) Christian "ChipX86" Hammond (who's working for the VMWare Corporation, must be an interesting job) released some screenshots.
As I blogged before this release is based on GTK+2, so it integrates nicely into your Gnome desktop (although the software seems not to be 100% HIG compliant?).

On the "free" side of FOSS desktop applications, Evince seems to make great progress. Now the "all-in-one-viewer" proposition has been shot on desktop-devel-list@gnome, all work seems to get into document viewing (duh, nothing else to do ;-)).

This is what's possible in evince-cvs for now:

I guess I should get Evince on my system, maybe not -cvs but at least some released version. This should need 2 ebuilds: one for Poppler, and one for Evince. Maybe they're in b.g.o already, who knows?

Oh, and I forgot: Hi to Planet Gnome-NL! I'll create a hackergotchi ASAP, but taking a decent picture of me is a hell of a job ;-)

Apr 24
Screenshots in gallery

So, finally I added a "screenshots" album to my gallery. Currently only some desktop screenshots have been imported, more to follow soon (I hope).

This is my current one:

People in #gnome-nl@GimpNet seem to be very nice, jay :)

Apr 22
Other blogs

I was unable to read all other blogs I read normally for several days, and read most of them by now.

These are some things you must check out:

  • A movie demonstrating Soft Bodies in Blender. It's quite long, but it's worth your time.
  • We got Windows binary DLL codec support for GStreamer, which means every movie you're able to watch in WMP9 will be viewable in Totem or another GStreamer based application too, even if no free codecs are available.
  • Spyderous got great insight in some of the shortcomings in Computer Science subjects in education

Did I mention our concert yesterday was quite ok?

I forgot this one:

  • Never trust lawyers. Mind the name of the person writing this. If you don't know Greg KH: he's the author of udev, the Linux USB subsystem maintainer (one of Linux' trustees) and coder of lots of other kernel parts.

I hate blog comment spammers. Guys, get a live.

Apr 22
The future of X

This German article (bad BableFish translation) gives a great overview of what's currently possible using X11, on the field of eye candy. Some of the presented technologies are just technology previews, still nice to see though.

It's some sort of bundle about thingsI blogged about before:
- Xrender and Xdamage (alpha blending)
- Xgl (X server based on OpenGL)
- Luminocity (the wobbling windows, you know...)
- E17

Make sure you check the provided screenshots and demo movies.

Apr 16
Gnome 3 mockups

I really like this (don't just look at the screenshot, make sure you read the whole article, it's not too long).


Thumbnail is link to original image

Apr 15
Vim TNG


Imagine...

Apr 13
DSP coding and groupware troubles

Yesterday I did some DSP-related code again after several years (those AtomixMP3 days...). Read Stephan M. Bernsee's "The DFT a Pied" to "get" the DFT/FFT again, and then started to concentrate on beat detection of acoustic signals. Read Eric D. Scheirer's paper on acoustical beat detection, which is kinda heavy and theoretical (although very interesting at the same time :-)), and then found this article originating from this fantastic website. The article builds up things very well, it's very easy to understand everything as long as you got some very basic math knowledge. The author starts with some very simple energy based algorithm, then builds it up to more complex analyse methods.
I implemented algorithm #2 from that article together with some simple wave file reader/player in C yesterday, it needs some more tweaking, but the basics do work. Once I get it working fine I'll implement it as a GStreamer plugin. Lots of thanks to the people at #gstreamer@freenode.net for helping me out at coding the thing, I really need to learn some more about primitive data types and their size ;-)

Next task: use my current code to implement #3, enhance the visual beat tap, and make the code better (it's not optimized at all right now). Then I can put it into a GST plugin (after I read the GStreamer Plugins Writers Guide).

I've been testing several free groupware applications at VTK lately, none of them do everything I want untill now :-( egroupware comes close thanks to it's integration with LDAP, but it's buggy as hell (on our system at least): I can't even add a simple event to my calendar, and some of the "applications" just generate PHP errors and die. If anyone got experience with FOSS groupware applications (especially if they got support for LDAP as account and/or addressbook backend, or even Evolution and/or MS Outlook support) please let me know which apps I should try.

Apr 7
Gentoo and fdo standards

Sven just made me feel good. If Gentoo devs will stick to freedesktop.org standards and maybe even actively contribute to them, it'd be of great value for Gentoo Linux as a desktop distribution.

Apr 7
Call for votes

Hija,

I just received this email from Jono Bacon:

Hi all,

Right, my band Seraphidian (www.seraphidian.com) is
involved in a competition to play the Download
festival. We have been finalised as one of the top 10
bands, and I really need your help to push us forward.
This is a huge deal for us.

Please could you go to the following URL and click on
the red VOTE link to vote for the band:

http://www.snickersunsigned.co.uk/snickersunsigned/voting/votedetail.asp?bandid=952&startat=0

Also, if you run a website or weblog, could you
*please* write an entry encouraging you to vote. You
will know how important music is to me, and we really
want to push through to win this!

Also, could you please *not* write a script to bombard
the site with votes or they may accuse the band of
cheating, which we really don't want to do.

The vote closes on monday, so time is of the essence!!

Thanks a lot folks!

  Jono

Maybe some of you know him, read articles by him, whetever. I met him IRL at FOSDEM, he's a great guy (who doesn't know the hilarious LugRadio webcasts?), so if this can help him forward, I urge you to click the link and vote for his band (even if you don't like the music ;-))

CP: Fatboy Slim - Going out of my head

Ikke • LifePermalink 6 comments
Apr 6
Fun @ desktop-devel-list@gnome

Methinks this is funny :-) Make sure you check the preceding message too, so you know what this is all about.

CP: Gotan Project - Joy

Apr 5
Back

So, I'm back, but will leave again on friday ;-)

Napoli was quite nice, lots of Roman things of course ([url=http://en.wikipedia.org/wiki/Pompei]Pompe

Ikke • LifePermalink 2 comments
Mar 28
Bleh

Very long time ago, once more...

I've been very busy lately, lots of projects, some of them ICT-related, others not, but not too much time to do all those things I want to do.

I'm not going to flood my beloved readers with all boring (well... ;-)) things I've been doing lately, let me just say I'm having a pretty good time :>>

Currently I'm playing around with GStreamer some more. Some stupid problems I'm opposed too, very simple things that should work but don't etc, but well...

I hope I'll be able to report on something more exciting soon, write something, whatever, but I can't promise it'll come :oops:

Will be visiting Napoli from wednesday 'till monday, maybe I'll be able to write something about that trip when I get back.

By the way: happy easter @ all :-)

Oh, something else: we reached 2245 unique visitors on blog.eikke.com now, where a unique visitor is unique in 24 hours. An absolute record 88|

Mar 10
Database Regression

Once more, my sites moved from one server to another, which resulted into a minor database regression. Looks like some comments posted went missing, I'm very sorry for this inconvenience.

Mar 1
FOSDEM

Had a great time. No time to give an overview at the moment, but I will report on it as soon as possible.

@RealNitro: the only way to learn things is by coding a lot :-)

Ikke • LifePermalink 1 comment
Feb 25
Gnome Settings Manager

Just thought of this:
Imagine a program that allows you to tar up settings etc. You run it, it takes a snapshot of your Gconf settings, your Gnome application settings in .gnome2, your current GTK+ theme, your Metacity theme, your icon theme,... i.e. all possible settings related to your Gnome desktop, and maybe even more things (as a plugin) like Mozilla Firefox preferences, Openoffice settings,... It takes all this, and makes a nice tarball out of it which you can take to some other machine, run some tool, feed it with the tarball, and all at once you got the exactly same environment as on the first machine...

I've been thinking of this 'caus I installed Ubuntu Linux at VTK the other day on one workstation, and I hated it to be forced to reconfigure every application the way I want them. Just grabbing the settings of my workstation here and applying them there would be so cool.

I know I could just tar -cjvf ~/.somedirectoriesandfiles, but that's no "nice" solution, and could (next to other things) corrupt the existing Gconf keys, Firefox profiles etc.

I just launched the idea on #gnome@GIMPNet, one possible problem that's been mentioned is hard-coded paths (e.g. in Gconf keys). The settings application should be smart enough to find these things, and check if the specified file exists. If not, the key should not be created, and the application using the kay should create it or get it from the Gconf defaults (that's just the way applications should work with Gconf. If they don't, they're not 100% Gconf-enabled/valid).

This is not easy to write, although when coding step by step, one should be able to get it working.

RealNitro: wouldn't this be some nice Python project? File handling, string parsing, Gconf bindings, even using PyGTK one day... If you'd like to take a look at this, I'd be glad to join and learn some more Python at the same time :-)

FOSDEM tomorrow and Sunday. I hope I'll get there (on Sunday preferably).

Feb 25
Vim and SCP/SFTP

Maybe usefull for some people reading this: if you want to edit remote files using Vim or gVim over SCP, no need to use Gnome-VFS, shfs, lufs or whatever more.

:e scp://username@host/a/file/in/your/homedir

will do the job.

When using a decent .ssh/config or when you got the same username on both machines, you can omit the username part.
You should use DSA/RSA keys so you don't have to enter your password on every open/save action :-)

AFAIK tab completion is not available, which is a pitty.

Ikke • LifePermalink 1 comment
Feb 23
Ugent WebAuth using PHP

As mentioned before I wrote some PHP class to allow people writing PHP applications to (ab)use the authentication method UGent and DICT offer easily.
This is the documentation of it, rendered using PhpDocumenter. The code of the class can be found inside the docs (can't give a link here, b2evo bug :-/), a working demo is here.

The code uses 2 mechanisms to decrypt the RSA encrypted key we get from the authentication server: it tries to use PHP's internal openssl_* set of functions, if support for them is compiled in the PHP interpreter. Otherwise it falls back to shell_exec to call OpenSSL in a shell, which gives a lot of overhead, unfortunately.
Unlike the provided samples, I'm not using temporary files anywhere.

Just installed Evince. It got some more features than Gpdf already, let's hope it continues to grow :-)

Feb 23
X Development

There's been a lot of talking lately regarding the future of X, things that should become possible,... Just take a look at Planet Gnome, especially Havoc and Seth have been active in this field.
A week ago or so there was the XDevConf, a conference for, guess what, X developers. There's been blogged about this summit quite a lot too, both on Planet Gnome and Planet Freedesktop.

I just read an article by Rasterman, an Enlightenment developer and X wizard. I did look at E17 and EFL some months ago already, but was pointed to them again because of the article. It explains what is possible already nowadays, including some videos. Make sure you watch them.

I'm a Gnome user, I love the Gnome Desktop and development. Some things you can see in the sample movies are great though, and cannot be used inside Gnome at this moment.
I don't like E17. I dislike the looks of the Windows Manager. Some of the things these guys are able to achieve at this only moment look incredible though, and even usefull ;-) If the X.org developers at freedektop.org could keep enhancing their X server (and especially the drivers), imagine how cool it would be if GTK could make use of some of the things these Enlightenment libraries provide. Not only to provide eye-candy, also "functionality" (think of *real* terminal transparency, no only copying the lowest X buffer, or transparent Gaim buddy lists as I wrote before). The possibilities are endless. And some people would die to get Linux on their desktop :-)

Lennert got a good idea too yesterday: get the Gaim buddy list out of a window, and put it on the desktop (if wanted, of course). Like a "Gaim GDesklet" (if you don't know what desklets are, check this screenshot, upper right corner). Would be very cool IMHO B-)

Feb 22
News from me

Long time ago once more ;-)

I got lots of things to do lately, so I rarely find time to update this blog. Next to this, I got sick about a week ago, so I had to stay in bed for a while too.

Some thing's I've been doing lately:

  1. Installed Xgl, dropped it because I got no hardware acceleration

  2. New desktop (screenshot, slightly changed now: the line under my top panel is smaller)

  3. Installed Hula some minutes ago.



    It is nice, but still needs some work IMHO.

  4. Wrote some mass-mailing-with-attachment Python script. It's not 100% done, if you want it give me a call

  5. At Ghent University there's a new system to allow web application developers to authenticate users against the universities student database. Whilst all sample code in the docs is written in Perl, usign a bunch of temporary files to decode/decrypt keys etc (I'm not getting into the implementation details here), I wrote some PHP class to achieve the same goals. Not using any temporary files (which is better, think of multithreaded webservers...), but still using a shell_exec call to openssl to decrypt a PKI string using some public key. TODO: use PHP's openssl functions, or shell_exec as a fallback when OpenSSL support hasn't been compiled into PHP. I think I'll send the class to the UGent admins once it's done, so others can make use of it too.

  6. Just showed Nat it's easy to generate PDF files from MediaWiki pages using this software. He was looking for a tool like this to create PDF's out of the Hula Wiki pages (hey, I even pointed him at MediaWiki in a lengty mail I sent him upon his request describing all wiki implementations I got some experience with :-))

  7. Installed PhpAdsNew2 today at VTK. It's not implemented yet (still need to give a demo to the admins), I hope it'll allow us to deploy a better, easier and more manageable ad management, including decent statistics. Hey, we need to know our market value, isn't it?

TODO:

  1. Get a new harddrive (8.4Gb is too small on a modern desktop/development system)

  2. Get NVidia Binary drivers working, play around with Xgl once more, and try hardware accelerated composition

  3. Get semi-transparant Gaim chat windows and buddy list working

  4. Play around with Galago

  5. Get a Subversion repository somehow, somewhere

  6. Find out how to get to FOSDEM, or I won't go once more

  7. Finish reading the GStreamer development handbook (60 pages to go)

  8. Get some new girlfriend?

  9. Lots more, not willing to think about it at the moment.

Oh I almost forgot. We sold our first Dell computers today. Let's hope the ecommerce site will be up soon.

Feb 13
New article: GOptions

Wrote a new article today, on command line options parsing using Glib 2.6's GOptions.

Once more, it's listed on my articles page, direct link here.

Next one will be on moving your project dir into a local or remote Subversion repository, or GStreamer basics, still have to make up my mind.

Feb 12
Use id's

Hint #cantremember: Use ID's where-ever you're allowed to

This makes crossreferencing later on (using XRef or whatsoever) easier, and references are very nice and usefull (look at WikiPedia and others).

Ikke • DocbookPermalink 1 comment
Feb 12
"Introduction to Makefiles and Autotools" published

I finally finished the Docbook-translation of my article on Makefiles and Autotools. The result is listed on my articles page, direct link here.

Feb 10
CV

Just wrote some initial version of my CV, still needs some work, and PDF conversion :-)

I might ask some people for some advise on it too.

Feb 10
Get a reference sheet

Hint: Use a Docbook element reference sheet

Simple :-)
I use this, this is somewhat bigger.

Feb 9
#3

Hint 3: Write directly in DocBook format

As you might know I first wrote my first 2 articles in this blog. I docbook'ized the first one, which went quite well, now in progress doing the second one, which is a real PITA.

So, little hint: don't write plaintext files first, write DocBook code/tags directly.

Ikke • DocbookPermalink 1 comment
Feb 8
Use Yelp to preview your documents

Simple one for now, got not much time, but don't want to break the chain either:

Tip 2: Use Yelp to preview your documents

You can use Yelp to preview the Docbook documents you wrote, so you don't need to xsltproc/xmlto the file everytime (which takes a while).

Just open the like this:

yelp mydocument.dbk

Ikke • DocbookPermalink 1 comment
Feb 7
Article list generation script

I wrote the articles/index.html generation script, using Bash and some sed magic.

This is a sample input file:

Using Glib Signals with GOB_gob-signals
Introducing the Glib Mainloop_glib-mainloop

which outputs the current index.html.

You can find the script here, it's called genindex.sh. The index.html.in file I use as a boilerplate in the end is here, very easy to figure out what's done.

Bash is a really powerful thing, the more scripts I try to write using it, the more I learn.
Of course you could do something like this using PHP, Python or something else, but Bash is much cleaner IMHO (i.e.: you don't need a fully fledged PHP installation to do stuff like this).

Feb 7
New articles page

Just finished (well, almost) the articles section on my website.
As you can see, the articles are available as PDF now too, although the PDFs aren't formatted very well sometimes (links aren't rendered as real links :-(), need to look into this.
I also need an info page with an explanation of the license, and some copyright information.
The article titles should get the same look as the section links on my homepage, but I cant get them to behave correctly :'(

I'm going to write a PHP script that generates the HTML code you see there from an XML file listing all available articles, too. Will make things much easier for me :-)

I've read some of the GStreamer API docs today, it's a wonderful framework. Prepare for some tutorial ;-)
Next one should be about local (UNIX Domain) sockets, but I think I'll Docbookize the Makefiles tutorial first.

Feb 7
A Docbook tip a day keeps MS Word away

Last night I decided to create a new blog category, where I'll try to give one Docbook-related tip every day, so others can get used to this great format too and start writing documentation or articles using it :-)

I will concentrate on writing "article" files, not "books" or some of the other Docbook classes.

First tip: The standard Docbook Article boilerplate

A Docbook document is an SGML or XML file. Writing SGML can be a tedious task, so most users write their documents in XML.
This is the standard boilerplate for a Docbook XML article:

<?xml version="1.0"?>
<!DOCTYPE article PUBLIC "-//OASIS/DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
<article id="sometitle" lang="en">

Document goes here

</article>
Ikke • DocbookPermalink 1 comment
Feb 6
New article: The Glib Mainloop

I decided to write new articles in docbook directly, not posting them into this blog.

As promised I wrote an article on the Glib Mainloop. It is available here. I still need to add hyperlinks to the quoted references (API's,...), but I'll do that later.

I start to like DocBook, actually. The generated documents may look ugly, but some CSS work could fix it.
The good thing is you got a consistent interface, and the XML you write really describes what you're writing about, if you use the correct tags.
The documents I write may not be 100% correct (missing tags on some places etc), but I'm learning ;-)

I hope you like the article, please comment on it if thing's aren't correct, not obvious enough,...

I should try to write up some CV too next days. Hell of a job.

Feb 4
Articles

Converted my first article, the one about GObject Signals, into the Docbook format.
The resulting HTML is here, the Docbook XML source here.
The CSS stylesheet needs some more polishing, I know.
Also try viewing the article in Yelp: download the source, and run "yelp gob-signals.dbk".
I updated my homepage so there's a new link to the articles section now.

I'll convert the article on Makefiles later, it's a tedious job.

Started working on the "Glib Mainloop" one, won't be finished too soon (not easy to know what to write about ;-))

Feb 3
Gnome 2.10.0 beta 1 released

Just got the notification on IRC. Jay, finally :-)

Musical hint: check out the "Cello Concerto in a" by Camille Saint-Sa

Feb 1
Writing Makefiles the manual way, and using autotools

As promised, the article on writing Makefiles. As an extra, I also include how to build a basic/simple autotools project.

Writing Makefiles, the manual way

Let's get started.
First of all, you need all files used in my previous article, i.e. test-signal.gob and test-signal-test.c

There are some rules of thumb you can use when writing a Makefile manally:

  1. Find out what programs you need to process your source files

  2. Find out what packages you need: which headers, and which libraries

  3. Make a list of all source files, and find out which ones are dependent on others

Let's get through these step by step:

  1. What programs do we need? We need gob2 of course, to process our gob file. Next to this, we need the stuff you need most of the time when creating a Makefile: a compiler and a linker. And guess what, GCC can do both things.

  2. What packages do we need? Remember the command line thing you had to use when compiling the test-signal executable?

    gcc -Wall `pkg-config --libs --cflags gobject-2.0 glib-2.0` -o testsignal test-signal-test.c test-signal.c

    We don't even need this line to figure out what we need: we're building a gobject, so we need all libs and headers provided by the gobject package, version 2.x in our case, same thing for glib.
    How can we find out where these things are located? Well, the smart people at freedesktop.org made a nifty tool called pkg-config. When a library is installed, it can install a pkg-config resource file, which lists the directories where it's stuff is installed. For some samples of these files, check /usr/lib/pkg-config. The pkg-config command line utility can parse these files and give you the information you need.

  3. What source files have we got, and which one needs which? We got 2 files, test-signal.gob and test-signal-test.c. In the end we want to generate an executable called test-signal, which needs test-signal.c (the GObject implementation file) and test-signal-test.c.
    We will work in 2 stages here: first we'll compile all necessary .c files to an object file (.o), then in the end link all object files together in a nice executable.
    Here's what should happen: test-signal.gob should be parsed by gob to create our test-signal.c and test-signal.h file, test-signal.c must be compiled, test-signal-test.c must be compiled, and finaly test-signal.o and test-signal-test.o should be linked into test-signal.

First a little intermezzo. You might be asking "If I need to make all these lists, what's the use? Can't I just write some Bash script which executes the gcc command all at once?". Well, no. Make does more than just executing some commands. It also checks whether it *should* do something. Imagine you got 100 source files. You got all of them compiled, linked into some executable, run that one, and find some bug. You fix it by editing some lines in one file, and re-execute your huge gcc command. Gcc would recompile all 100 files, which will take some time.
If you use a Makefile make will find out only one file has been altered since the last build, it'll let gcc recompile only that file, then relink all object files together, which will take less time. Next to this: once using autotools, everything becomes much simpeler ;-)

Ok, now we got all prerequisites. Let's get started writing our Makefile.
I always tend to use the same format when writing one (although I dont write many of them, I use autotools ;-)). I start with defining the executables:

GOB2=gob2
CC=gcc
LD=gcc

This is not necessary, but can be usefull sometimes. Now we can use these variables later on. If we want to change the linker, we only have to edit the Makefile in one place.

Next comes the definition of the CFLAGS, the flags given to the compiler (CC) when compiling a sourcefile into an object file:

CFLAGS=`pkg-config --cflags glib-2.0`
CFLAGS+=`pkg-config --cflags gobject-2.0`
CFLAGS+=-Wall -g

As you can see, we request the CFLAGS necessary for glib-2.0 and gobject-2.0 (2.x, actually) by querying pkg-config. In the end we add 2 compiler flags: -Wall, which tells gcc to show all possible warnings, and -g, which tells gcc to include debugging information. This can result in a somewhat bigger executable, but it is very usefull if we want to debug the program using GDB.

Now we define the LDFLAGS, the flags given to the linker:

LDFLAGS=`pkg-config --libs glib-2.0`
LDFLAGS+=`pkg-config --libs gobject-2.0`

This should be fairly self-explaining.

This project only consists of one executable, so I define an "OBJS" variable including all the object files needed to build our executable:

OBJS=test-signal.o test-signal-test.o

Now comes the name of the executable we want to create:

PROG=test-signal

Now the magic starts. Until now we only defined some variables for later use. We were not forced to do so, it's just more convenient later on. Actually, when building small things, we can just use re-use this Makefile, and only have to change the variable definitions (OBJS, PROG, maybe some CFLAGS and LDFLAGS).

Now some rules follow, which tell make how to handle files:

%.c %.h %-private.h: %.gob
        $(GOB2) $<

This rule tells make: "When a foo.c, foo.h or foo-private.h is needed, and not existant, it should be made from foo.gob, by executing "$(GOB2) $<" which gets expanded as "gob2 foo.gob"". Indeed, % represent "a string", $(GOB2) is the variable we defined at the beginning and gets expanded as "gob2", and $< gets expanded as the first item on the right of the semicolon (":").
One big thing to watch out for: Makefiles are indenting-sensitive but you may not use spaces. So in the last Makefile fragment there's a [tab] before $(GOB2).
The format of a rule is very simple:

filenametobuild: dependenciestobuilditfrom
[tab]what to do first[enter]
[tab]what to do next if necessary[enter]

etc.

Next we define how to link our $(PROG):

$(PROG): $(OBJS)
        $(CC) $(LDFLAGS) $(OBJS) -o $(PROG)

$(PROG) is built out of $(OBJS) by issuing "$(CC) $(LDFLAGS) $(OBJS) -o $(PROG)", expanded to "gcc `pkg-config --libs gobject-2.0` `pkg-config --libs glib-2.0` test-signal.o test-signal-test.o -o test-signal"

We still have to tell make how to create object files out of source files:

%.o: %.c
        $(CC) $(CFLAGS) -c $<

You should be able to figure out what this does by yourself.

Now we add some convenience targets:

all: $(PROG)

default: $(PROG)

clean:
        rm -f $(OBJS) $(PROG)
        rm -f test-signal.[ch]
        rm -f test-signal-private.h

This enables us to just type "make", which will start building the "default" target, or "make all", which will build the "all" target, or "make clean" to "build" the "clean" target.
Notice a target

  1. is not forced to "do" something ("all" and "default"). You can just say "it depends on "foo" and/or "bar", which will be built then, and

  2. the dependencies of a target may be empty ("clean")

Let's end with the complete Makefile:

GOB2=gob2
CC=gcc
LD=gcc

CFLAGS=`pkg-config --cflags glib-2.0`
CFLAGS+=`pkg-config --cflags gobject-2.0`
CFLAGS+=-Wall -g

LDFLAGS=`pkg-config --libs glib-2.0`
LDFLAGS+=`pkg-config --libs gobject-2.0`

OBJS=test-signal.o test-signal-test.o

PROG=test-signal

%.c %.h %-private.h: %.gob
        $(GOB2) $<

$(PROG): $(OBJS)
        $(CC) $(LDFLAGS) $(OBJS) -o $(PROG)

%.o: %.c
        $(CC) $(CFLAGS) -c $<

all: $(PROG)

default: $(PROG)

clean:
        rm -f $(OBJS) $(PROG)
        rm -f test-signal.[ch]
        rm -f test-signal-private.h

Save this file as a file called "Makefile" in your source directory, and type "make". This should be the result:

gob2 test-signal.gob
gcc `pkg-config --cflags glib-2.0` `pkg-config --cflags gobject-2.0` -Wall -g -c test-signal.c
test-signal.c: In function `test_signal_testsignal':
test-signal.c:141: warning: implicit declaration of function `memset'
gcc `pkg-config --cflags glib-2.0` `pkg-config --cflags gobject-2.0` -Wall -g -c test-signal-test.c
gcc `pkg-config --libs glib-2.0` `pkg-config --libs gobject-2.0` test-signal.o test-signal-test.o -o test-signal
rm test-signal.c

Notice the "rm test-signal.c": make removes the files it generated itself, so when you update test-signal.gob, it will tell gob to reconstruct the c file, otherwise the c file wouldnt get updated.

Now you should be able to execute ./test-signal.

Ok, we got a nice Makefile now, but it took some time to write it, isn't it? And we don't have a "normal" FOSS install method like ./configure, make, make install...

Well, that's what we are going to do now. The following stuff is much easier than writing Makefiles by hand (you know, FOSS devs are lazy people ;-)), but it is useful to know how Makefiles are formatted, and how they work, though.

Ok, time for some really 1337 (couldn't stop it) stuff: introducing GNU Autotools.

Using the GNU Autotools to build your project

Didn't you ever want to be able to write such a neat ./configure script yourself? Here's how to do it with our sample project :-)

Autotools consist of a bunch of utilities, most of them starting with "auto" (duh). There's autoconf to generate a "configure" script from a file you provide, there's the automake script that creates Makefile's for you (actually, it does not create Makefiles. Read on), and many more.

This is how it works: the configure script will look up a bunch of stuff for you (or you provide it using --with-foo=... etc), it will do some tests to figure out whether the project should compile and run cleanly on your system, and in the end it will generate some files.
A boilerplate for these generated files should be provided by you, called "thefile.in". The generated file will be "thefile" then. Inside "thefile.in", you can use variables like these: "@FOO@", which will be substituted by the configure script.
That's the system automake uses: you write a simple Makefile.am file (read on on how to do this), automake generates a long and difficult Makefile.in file, which gets processed by configure to create the final Makefile.

GNU Autotools have some strict rules (although it is possible, but not advisable, to get around them). Source files should be in the src/ subdirectory, and some files are required in the root directory of the project. We'll find out which ones these are later on.

Let's get started by creating our initial project directory layout:

#Go into an empty directory
mkdir src
cd src
cp /foo/bar/test-signal.gob ./
cp /foo/bar/test-signal-test.c ./
cd ..

Initial task: once more, figure out what the required dependencies are. As mentioned in the first part, we need gobject-2.0 and glib-2.0. Next to this, we need a working C compiler.

We can start writing a configure.in file now, in the root dir of our project, which will be processed by autoconf to generate out ./configure script. Here's what it could look like, comments (starting with "dnl") inline:

dnl Register ourselves to autoconf, giving the main source file
AC_INIT(src/test-signal-test.c)

dnl Init Automake, giving the program name and version. More parameters (author and author's email) are optional
AM_INIT_AUTOMAKE(TestSignal, 0.1)
dnl Enable maintainer mode (debugging flags etc)
AM_MAINTAINER_MODE

dnl Check whether we got a good C compiler. Variable "CC" will be defined and expanded in the .in files
AC_PROG_CC

dnl GOB2 macro, to check whether gob version >=x.y.z (here >=2.0.0) is found. Variable "GOB2" will be substituted/expanded
GOB2_CHECK([2.0.0])

dnl Use built-in macro's to query pkg-config. First parameter is a variable name we'll use later on, second is the package to check for (with optional minimal version), third is the thing to do if the package is found, fourth if not
PKG_CHECK_MODULES(GLIB, glib-2.0, have_glib=true, have_glib=false)
if test "x${have_glib}" = "xfalse" ; then
        AC_MSG_ERROR([No Glib package information found])
fi
dnl So glib-2.0 is found. Remember the first parameter in the previous command, GLIB? Well, GLIB_CFLAGS now contains the output of `pkg-config --cflags glib-2.0`, same thing for GLIB_LIBS with --libs instead of --cflags
dnl AC_SUBST tells configure to substitute the given value in the provided .in files
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)

dnl Same thing for gobject-2.0
PKG_CHECK_MODULES(GOBJECT, gobject-2.0, have_gobject=true, have_gobject=false)
if test "x${have_gobject}" = "xfalse" ; then
        AC_MSG_ERROR([No GObject package information found])
fi
AC_SUBST(GOBJECT_CFLAGS)
AC_SUBST(GOBJECT_LIBS)

dnl Here we tell the configure script which files to *create*, so we leave out the .in part
AC_OUTPUT([
        Makefile        \
        src/Makefile
])

Currently Makefile.in and src/Makefile.in don't exist yet, they will be created by automake later on.

This file is a very simple one, it can be a tedious job to create complex configure.in files :-/

Next thing: Makefile.am files, which will be processed by automake to create the Makefile.in's.
In the project root dir, this file can be very simple:

SUBDIRS = src

We just define the subdir(s) of the current dir.
src/Makefile.am is a little more complex:

INCLUDES = $(GLIB_CFLAGS) $(GOBJECT_CFLAGS)

bin_PROGRAMS = test-signal

test_signal_SOURCES = test-signal.c test-signal-test.c

test_signal_LDADD = $(GLIB_LIBS) $(GOBJECT_LIBS)

%.c %.h %-private.h: %.gob
        @GOB2@ $<

Some explanation:

  • "INCLUDES" is a variable that will be given to every compile call to "$(CC)", here we only need the glib and gobject includes. Remember these values will be setted by the configure script.
  • "bin_PROGRAMS" is a variable defining the names of all targets we want to be installed as an executable in the bin directory (/usr/local/bin if no prefix is given to ./configure)
  • "test_signal_SOURCES" is a variable defining which files are needed to make the target "test-signal". Notice "-" being replaced with "_" here, which is a common thing in automake files.
  • "test_signal_LDADD" defines which parameters to offer to the linker when linking the input object files to the "test-signal" executable. We could have used a global "LDADD" variable here, like "INCLUDES", or have made "INCLUDES" non-global by using "test_signal_INCLUDES". In large projects this can make a big difference.
  • The last part is the one we also used in our hand-written Makefile. It will be put like this in the resulting Makefile.in by automake, so make will know how to build .c and .h files from a .gob file.
    Automake puts all non-automake-specific stuff that's in Makefile.am in the resulting Makefile.in.

Now everything is done. At least, almost ;-) We still need to call out autotool scripts.
It's easy to do this from a shell script. Most projects call this script "autogen.sh", so will we. This script can be fairly complex, ours will be braindead easy:

#!/bin/bash
aclocal
autoconf
automake -a

As you can see, we first call aclocal (part of the automake package), then autoconf, then automake with the -a flag.
Why "aclocal"? Autoconf, which creates a configure script out of a configure.in file, uses M4, a complex macro system, to do this. aclocal copies the necessary macro definitions for your system to the right place.

Run this script, or enter the commands by hand. aclocal can give a lot of warnings, don't bother about these.
If this is the first time you run the script, you will see some automake errors in the end, and the script execution will fail:

Makefile.am: required file `./NEWS' not found
Makefile.am: required file `./README' not found
Makefile.am: required file `./AUTHORS' not found
Makefile.am: required file `./ChangeLog' not found

These are the required files I mentioned earlier. We'll just touch them for now so they "exist", although contain no usefull information:

touch NEWS README AUTHORS ChangeLog

Now restart the autogen.sh script, everything should pass now.

If you take a look now, you'll see a couple of Makefile.in files are created now (who will be converted into Makefiles by configure, remember?), and the configure script.

Let's take our work to the test, and run ./configure. You'll see the usual output, and everything should pass fine (we don't have a lot of prerequisites :-))

Now let's try if our project builds fine:

make

Jay, lot of compiler commands, no errors. Fun :-)

To finish, test whether the executable works:

cd src
./test-signal

The same output as before appears, we're member of the Autotools User Group now ;-)

That's it for now, more stuff should follow: "The Glib mainloop", "Debugging using GDB", and a from-scratch "program" we'll create. I only lack the time to write everything ;-)

I'd like to convert these articles to some format so they can be used outside this blog (converted to PDF, HTML,...). Docbook seems to be a good format to do this, I need to get used to it first, though. If someone knows a good Docbook editor (next to Conglomerate), please let me know.

Feb 1
I'm amazed

I just found this article on distrowatch.com, and I'm amazed. This is *so* unreal :crazy:
If you're too lazy to read it, or just want to know why you should: it looks like CCux Linux included Ivman in their latest development release, by default XX(
Quoting the Release Notes:

(But) This Version has some nice new Features too. Supermount doesn't handle the automatically Device mounting. In Fact, this is now handled from dbus 0.23, hal 0.4.7 and ivman 0.5. This Combination does this Job much better when mounting CD/DVD Drives or USB Sticks, Kameras or other Things. Therefore it doesn't need anymore User Interaction to get all Drives running.

88| :-P :-) :-D :-p B-) |-| :>>

This is some great new, isn't it? Mostly thanks to Rohan lately I guess :-) YOU ROCK

Next to this: as promised in my GObject Signal handling article, I wrote a makefile for it, and even did the autotools stuff. I'll write an article on that stuff this evening, or tomorrow, if possible.

PS. Good news: exam was fairly good, I think. Let's hope for the best tomorrow.

Feb 1
New category

Just made a new blogging category, "Coding Corner". I've got some ideas related to a serie of articles on Gnome/Glib coding, building on GObjects like in the article of yesterday, but also introducing some basic GTK+ coding, daemonizing, autotools (autoconf/automake/autoheader) and some more. It will be a little "Hello world" program, which can *normally* be done in like 10 lines of code, but a little more sophisticated here. I hope I'll be able to start writing the first article (about the Glib mainloop) tomorrow afternoon.
I'm looking for some format to write the articles in, so maybe I'll be able to generate PDF documents of them later on, etc. Maybe I should take a look at Docbook? LaTeX isn't really suited here.
Of course the CUPS PDF Writer could do it's job too ;-)

Got an exam at 14:00 and tomorrow morning, wish me luck, I need it.

Jan 31
GOB signals walkthrough

I mentioned the "GOB" utility a couple of times already, but the more I use it, the more I start to love it.

I'd like to take you on a little "Glib/GObject Signals" tour today.

First of all, what are Signals? The GObject Signal API states:

Signals

Jan 30
Python for Dummies, and update

Jono Bacon wrote an article on Python coding for beginners, using PyGtk and Glade to create GUI's.
The article was inspired by his work on an application handling iRiver devices. It is (AFAIK) using HAL too.
Guess it's time for me to (re)start doing some Python coding too... Get some more skills ;-)

I fixed some (mail handling) bugs in Beagle yesterday, got the "Open IM" functionality of Best working locally (again using a patched Gaim). Mail patch should be applied soon.

[edit]Patch has been applied: link (and other updated files)[/edit]

Trying to get some GObject's for CDIS working using GOB now. GOB really rocks, it's so easy to write code once you read the complete manpage :-)

Plea"se note Ivman got a new Wiki, thanks to Rohan.

Jan 24
Beagle installed

Got beagle-cvs installed properly, started hacking on an Irssi log backend already. It rocks :-)
And so do the guys in #dashboard@GIMPNet ;-)

I'll report on how to install it (on Gentoo, of course) later.

Jan 24
Snow

Seems to be a very "cool" (;-)) thing lately to show some pictures with snow in your area in your blog. So here are mine (link won't stay valid).



Some more in my gallery.

Not as impressive as the pictures by Garret LeSage, John "J5" Palmieri, Tim Ney, John Trowbridge, Nat Friedman, Joe Shaw, Luis Villa and many more, but well...

Going to write a Beagle-cvs ebuild now :-)

Jan 24
Beagle

Beagle is so damn impressive. Check these demo's.

Jan 23
Gnome coding, and presenting CDIS

I started looking into Gnome coding last days, by reading some of the great tutorials in the Developer section of the Gnome site. Currently I'm reading the stuff on GObjects, which is very interesting. I first read the article on IBM DeveloperWorks regarding "Wrapping GObjects in Python", which is a neat way to use C code in Python. It's also written by Ross Burton, as you might remember the author of the Contact Lookup Applet.
Regarding that applet: Ross is not willing to incorporate my Gaim patch, because it is too much bound to Gaim, and requires a patched version of Gaim. Too bad, Cdis should provide a solution for this.

Now what is Cdis? It's the new name for what I previously called DAL. Cdis stands for "Common Desktop Integration Standard", a name proposed by John "J5" Palmieri. Some information regarding it I sent to the Xdg list at freedesktop.org is available here. Beware, the thread got corrupted somewhere and is attached to the pkgconfig2 thread, so it continues here

I had some talkings on IRC with JakobS, the KDE maintainer of the MulticastDNS features coming in KDE 3.4, regarding automatic code generation. It will be fun to get this working (XML2C, XML2GObject, XML2KObject,...). It should be possible to do this without writing real code, just using XML and XSLT, which generates the necessary code for various platforms, based on a CdisInterface description file.

For the GObject creation, which is a very tedious task, I've been looking into Gob, the GObject builder. It just rocks. This is a sample Gob file:

requires 2.0.0

%{
//This should not be necessary, but well...
#include <stdio.h>
%}

class Ikke:GobTestOne from G:Object
{
        private int test=1;
        property INT test
                (nick = "test",
                 blurb = "Testje",
                 export,
                 link);

        public void
        printtest (self)
        {
                g_printf("%d\n", self->_priv->test);
        }

        public GObject *
        new (void)
        {
                return (GObject *) GET_NEW;
        }
}

As you can see, a very simple format.
If I process this file using gob, this is what I get:

$gob2 gobtest1.gob
$ ls
gobtest1.gob ikke-gobtestone-private.h ikke-gobtestone.h
ikke-gobtestone.c
$ wc -l ikke-gobtestone*
22 ikke-gobtestone-private.h
276 ikke-gobtestone.c
75 ikke-gobtestone.h
373 total

which is rather impressive. The generated code is also very usefull.

A "bigger" Gob file (just a sample) can be seen here, whilst this is a sample C file "using" the object. Impressive, huh?

Gnome 2.10.0 beta1 tarball creation tomorrow, launch on wednesday. Jay! I got the webcal in my Evolution Calendar ;-)

That's it for now, maybe I'll have some usefull stuff to say soon ;-)

Jan 20
Contact-lookup-applet with Gaim integration

Long time ago.

I've been working on a lot of things lately, hope I'll be able to report on them later, now something I did today.

I integrated Ross Burtonini's Contact Lookup Applet with Gaim.

This is the thing "in action":


The standard contact view


New button



Conversation opened

Actually this was my first Glade/GTK+ code ever, although not that much ;-) And it rocks :-) Also the Gnome devs on #gnome@GimpNet and the Gaim guys on #gaim@Freenode were a great help when needed. Thanks a lot!!!

If there's already a conversation running, that window will be focused, and if Gaim-Remote isn't running, there'll be a small error dialog box.

Gaim also needs a patch for now, but the necessary features should be standard in upcoming versions.
Make sure you got the "Remote Command" plugin enabled too.
If you're not using a patched version of Gaim (actually not Gaim, but Gaim-Remote) the "Start IM" button will also be displayed, but when pressing it, nothing will happen (no crashes or so, just nothing).

Current CLA and Gaim patches are available here.

I'll send an email to Ross, maybe this stuff can get into CVS?

I hope you like it :-)

Jan 15
Movie - Oceans12

Saw Oceans 12 yesterday evening. Never saw Oceans 11, so I can't compare, but it made me think of "The Italian Job" and "Catch me if you can".
Not a bad movie, if you're willing to turn off your brain for a while.
The trick with Julia Robberts is nice :-p But I won't say more about that B-) ;-)
By the way: funny comment on IMDB. It reveals the Robberts trick though :-(

Oceans12

Ikke • LifePermalink 1 comment
Jan 15
Done today

Not much DAL work, next to some arguments on the mailing list. I'll code some more stuff tomorrow. First need to work some things out.

Worked a bit on the frontpage. It's pure XHTML/CSS again now, SEO-optimized (simple html, headings, good meta tags,...). It even looks good in links :-)
Also did some mod_rewrite work for this blog (http://blog.eikke.com/ikke works now :-) others should follow), and error page handling (404's are redirected to / now).

I'm quite tired, need some sleep, first exam on tuesday. Bloody chemistry.

Jan 13
DAL redefined

After quite a lot of (positive) replies on both desktop-devel@gnome and xdg@freedesktop, I wrote some little summary of current state.
This stuff is quite different from the initial implementation proposition, but well :-)

Thanks to RealNitro and WindowLicker I got my frontpage pure XHTML-Strict/CSS now. Thanks guys :-p

Jan 13
New frontpage and mailings

Check it here :-) Needs some more cleaning of HTML code, but well. Thanks to RubenV for the base template.

Sent an RFC to freedesktop.org's XDG list, and one to Gnome's desktop-devel. Let's hope I'll get some responses...

Jan 12
Review and comments asked

Please review this and tell me what you think.

Is it worth the effort? Has it got any use? Is there already some project like this? Enhancements?...

Thanks, Ikke

Jan 12
Gaim plugin... working

No proof/evidence for now, some people "enjoyed" the working state already ;-) I'm set on "away" state now when the screensaver listener detects a running screensaver, and I'm online when the screensaver is stopped.

Needs a lot of cleanups...

And I'm thinking of a new project, which (next to other things) incorporates this thing. Similar to HAL, but at desktop level -> DAL. I'll write more about it later.

Ikke • LifePermalink 16 comments
Jan 11
GaimDbus

A picture says 100x more than words...

GaimDbus sample 1 (thumb)
(thumbnail is link to original picture)

This makes me feel good :-)

The picture shows how I started and stopped xscreensaver a few times (by issuing "xscreensaver-command -activate" on a console), in the bottom left corner you can see the desktop-event-notification executable running (I did not daemonize it yet), and last but not least the Gaim debug window where my Gaim plugin shows it's received some DBUS messages sent by the server.

There is on major bug: XScreensaverStarted isnt always catched by the listener, nor by "xscreensaver-demo -watch". I will have to contact the xescreensaver maintainer I guess.

Next to this: the actual "set me away" isnt done yet. This shouldn't be too hard now, calling some functions when a DBUS message is received.

I included all necessary autotools stuff too, so it's as easy as sh autogen.sh && ./configure && make && make install.

I hope I'll be able to code the other parts tomorrow. Sleep now.

Big thanks to everyone hacking on DBUS, the guys at #gaim@freenode, and Google ;-)

Jan 11
Session Bus working, Gentoo GDM patch and Xscreensaver jay'ness

signal interface=com.eikke.DesktopEventNotification; member=XScreensaverEvent; sender=:1.58
string:ScreensaverStarted
signal interface=com.eikke.DesktopEventNotification; member=XScreensaverEvent; sender=:1.58
string:ScreensaverStopped

Next to this, I got my session bus working thanks to the nice guys on the DBUS mailing list, Ross' IBM article and some custom hacking.

Now my session bus is started when I log in, patch for GDM's Xsession file submitted into the Gentoo Bugzilla

Next task: simple DBUS listener to test the Xscreensaver notification stuff, and write the Gaim plugin.

[edit]
DBUS test listener is done:

./dbus-watch-test
Event received: ScreensaverStarted
Event received: ScreensaverStopped

TODO:
- Gaim plugin (get DBUS inside Gaim's Glib mainloop)
- Daemonize the event submitter

Jan 10
DBUS troubles, stupid HAL patch, and gaim-xscreensaver start

Still haven't got the DBUS session bus working :-(

Made a patch for HAL-CVS so it broadcasts kobject-uevents to DBUS. It's of no use. Will give it some usefullness (SP?) tomorrow :-)
Current patch is here.

Started working on the xscreensaver <-> DBUS link. Some testing code is here, not indented. It's buggy, so don't look at it too closely.
sGapor gave a good hint about another possible use of this daemon: pause your media player when your screensaver is started.
Creating the Gaim plugin to idle you when the screensaver is started shouldn't be too difficult now I looked at the sources of gaim-remote.

Anyone's got the name of a music group that plays Turkish traditional music?

[edit] Just got an email from Havoc with some pointers on how to try to get the system bus working. Tomorrow...

Ikke • LifePermalink 2 comments
Jan 9
New subdomain UI, me on dbus@lists.fgo, and XScreensaver security considerations

I got a (IMHO) nice UI on code.eikke.com, using AutoIndex. It still needs some hacking: I want to get some mod_rewrite working, so I can use links like http://code.eikke.com/adir/foofile, which will then be interpreted as http://code.eikke.com/index.php?dir=adir&file=foofile. AutoIndex should generate similar code too then. This way, Google (which doesn't like GET arguments) will index my pages too.
Oh, and I want a GNOME iconset. I had to choose between WinXP and KDE...

Started a discussion on kobject-uevents and DBUS on the mailing list today (link). I've been thinking about it last hours, and my proposition is stupid. Kernel events shouldn't be sent out by the DBUS daemon itself. This should be done by some separate daemon.

If only I could get my session bus working :-(

Normally I should be allowed to create a Subversion repository on my domain once more. Jay :-)

After my blog post about xscreensaver and DBUS, jwz, the xscreensaver developer, posted a comment. I mailed him regarding this issue, check "More" for a digest of our discussion.

Had a performance with my orchestra today. We played the first part of the "New World Symphony" by Dvorak, and the Ouverture from "The Barber of Seville" by Rosinni. Some minor mistakes, but it was pretty good. The public was enthousiastic.
Next performance: April 23, Conservatorium Ghent, Belgium.

=> Read more!

Jan 8
DBUS'ified XScreensaver

Didn't have much time to code today, had to visit some family. Had a good meal ;-)

I hacked some DBUS support into XScreensaver today. Xscreensaver *should* send out a signal on the session bus now when the screensaver starts, or when it stops. Now guess what: it doesn't work (for now). Some security thing which disables me from sending events on my session bus :-(

Patch is here.

When this works, I will write a plugin for Gaim, which listens to the session bus. If it catches a screensaver event, it'll set your status to "Away" when the screensaver is started, and make you "Available" when the screensaver is stopped, if you were so when it started.

I created a new subdomain, http://code.eikke.com, where coding stuff will be hosted. I'd need some fancy "index" script, because Apache indexing doesn't work :-( I'd also need a decent Subversion repository. Maybe I should ask the guys who are so kind to host me (you know who you are).

Got some other new DBUS-based idea too, I'll discuss it on the dbus and gnome-desktop mailing lists when I get time.

Sent the mail to the dbus list regarding the kernel events stuff. Now it looks like I wasn't subscribed on that list anymore, and I need moderation... Hope they'll read and allow it soon.

Jan 8
Dbus kernel events part 2

I got the appended strings working, thanks to the patch to udev-ize CUPS (here).

No screenshot for now, this is some of the result (from dbus-monitor):

signal interface=org.kernel.KobjectUevent; member=KobjectUevent; sender=:1.20
string:ACTION=remove
string:DEVPATH=/module/ext2
string:SUBSYSTEM=module
string:SEQNUM=1061
signal interface=org.kernel.KobjectUevent; member=KobjectUevent; sender=:1.20
string:ACTION=add
string:DEVPATH=/module/ext2
string:SUBSYSTEM=module
string:SEQNUM=1062

Some more code-cleanups, and its done :-)

Next thing TODO: get on the DBUS mailing list, ask whether it's usefull to write a patch which incorporates this into DBUS itself (optionally), so one more daemon isn't necessary.

Current code is here. Watch out: it's not completely finished!!!

Jan 7
Kernel Events to DBUS

After my posting on LKML and the following answers and hints, I started hacking a bit.
This ended up in a utility that listens to kernel kobject_uevent events, and sends these to the DBUS System bus, so other applications can listen to DBUS to get kernel messages.

Evidence:

Dbus kernel events
(thumbnail is link to original image)

One problem for now: extra strings I pass with the DBUS message aren't sent. Got to look into this later... I wish there was more DBUS coding documentation, and more samples.

Ikke • LinuxPermalink 1 comment
Jan 7
Gnome, kernel work and Gaim

Currently busy catching up woth new Gnome improvements. Gnome 2.10 (dev 2.9) looks promising once again :-)
I've been on GimpNet (irc.gnome.org) for a while too now, just met scapor who owns this blog. Great source for new Linux-desktop users, and even advanced users can learn new stuff :-) Keep going!

Kernel events were merged into the Linux kernel, which should simplify kernel<->userland interaction a lot. There's a small utility called kdbusd which shows a prototype of listening to these kernel messages, and sends them to the DBus System Daemon. kdbusd could be broken now tough: I didn't test it yet, but it looks like the 2.6.10 uevent implementation is somewhat different than the one Arjan Van Der Ven, Robert M. Love and Kay Sievers wrote.
I started hacking more uevent calls into the vanilla kernel...

One nifty feature in Gaim I wanted to blog about some time ago is the "Expand" feature. I was too lazy to make screenshots in that time tough ;-)
Now I found a nice screenie and explanation of it in the GnomeTux blog I mentioned at the beginnning of this post. Check it here. This is the screenshot:

Stuff on my TODO list:
- Gphoto2 Gnome-VFS provider, so I can browse my Canon Ixus 500 files in Nautilus. The camera does not support usb-storage, so it can't be mounted. Gphoto2 supports it perfectly tough. But I dislike Gthumb...
- Work on Gaim - Evolution links.
- Make some program/plugin/... that enables syncing my new Nokia 3100's Agenda to Evolution's Calendar. There is a lib called Gammu that is capable of extracting data out of this phone, but there is no Evolution link. I'd need to test Gammu first tough (anyone got a DKU5 datacable?).
- Some more stuff I forgot now.

Got to study some more now, bloody chemistry.

Jan 5
Official statement

WE'RE UP AGAIN :-D:-D:-D:-D:-D

I'll explain the downtime later ;-)

Ikke • LifePermalink 1 comment

Categories

Who's Online?

  • Guest Users: 451

Misc

XML Feeds

What is RSS?