Today i played around with Net::DBus and the screen on my Logitech G19 keyboard.

For Linux, there is the Gnome15 software that allows plugins to access the keyboards screen. Works quite nicely. I've been using it to display a resource monitor for a year now. But being a typical PerlMonk, i wanted more. So just take a plugin, modify it and off we go...

In a classic "Do'h!" moment, i discovered everything is written in Python. But wait, the Gnome15 daemon talks DBus, which is supposed to be so easy to use, isn't it. And there is even a usable documentation of the Gnome15 DBus API online, so how hard can it be?

Uhm, pretty hard actually, if you have never worked with DBus before. And, when you finally understand how that stuff works, it still feels, well, less like an API and more like flying a plane at night through the Alps without any navigation instruments. (So, in effect, it feels exactly like trying to fix MakeMaker *smile*).

Ok, that's probably enough ranting. And i'm glad there is the DBus API, otherwise i would have no easy way to communicate to the display. So, off with the rant, on with the code!

I'm currently having a little problem displaying text, which is most likely related to a PEBCAC ("Problem Exists Between Chair And Computer"). So, instead, i'm presenting a "hyptnotic eye meditator" which will drive you crazy if you stare long enough.

Here's the code. Note, for clarity and code length, i left out all the checks.

#!/usr/bin/perl # G19 screen demo use strict; use warnings; # Load in the Net::DBus core module. use Net::DBus; use Data::Dumper; use Time::HiRes qw[sleep]; # Get the session object my $bus=Net::DBus->session(); # Connect to the service my $service=$bus->get_service("org.gnome15.Gnome15"); #Get the service object my $g19=$service->get_object("/org/gnome15/Service", "org.gnome15.Serv +ice"); # Just dump some server information my @xresult; @xresult=$g19->GetServerInformation(); print "ServerInformation: " . join('|', @xresult) . "\n"; # Try to connect to the first available screen (and hope it's a G19) @xresult=$g19->GetScreens(); my $g19screenname = $xresult[0]->[0]; print "Using screen $g19screenname\n"; my $g19screen = $service->get_object($g19screenname, "org.gnome15.Scre +en"); # Now, create a page and get its handle my $pagename = $g19screen->CreatePage('Perltest', 'Perl test!', 50); my $page = $service->get_object($pagename, "org.gnome15.Page"); sleep(1); my $linesize = 30; # Create a drawing surface $page->NewSurface(); for(my $i = 0; $i < 500; $i++) { # limit number of loops for(my $l = 0; $l < (240 / ($linesize + 2)); $l++) { my $offs = $l * ($linesize + 2); # Paint alternate color "table" lines if(($l+$i) %2 == 0) { $page->Foreground(40,40,40,255); } else { $page->Foreground(0,0,0,255); } $page->Rectangle(0, $offs, 320, $linesize + 2, 1); } # paint the "hypnotic eye for(my $l = 0; $l < 100; $l+=20) { my $radius = 120 - $l; # paint from large to small my $grey = 255 - int((($i * 5) + $l) % 255); $page->Foreground($grey,0,0,255); $page->Circle(160, 120, $radius, 0); } # Update screen $page->DrawSurface(); $page->Redraw(); sleep(0.1); } # Cleanup (delete the page) $page->Delete(); exit 0;

In line 14, we get the a new session object. In lines 17 through 31, we haggle along different objects until we finally the the screen object.

In line 34, we create a page object on that screen which we retrieve in line 35. We're still not quite ready to draw anything, NewSurface() on line 42 finally gets us a drawing surface.

The outer one (line 44) is basically the timing (each loop draw one screen).

The first inner loop (starting line 45) paints alternate colored lines (modified by the outer loop for a flimmering effect).

The second inner loop (starting line 58) paints the "hyptonic eye", which is essential for meditation/getting mad (whatever you prefer). This also depends on the outer loop for shifting colors.

The lines 66 and 67 actually update the screen.

When we're finished meditating, we delete the page we created (line 73).

That's it. It's not really a nice piece of code, but it gets the job done (and without writing a single line of Python, i might add). I think it's a simple enough demonstration how to work with Net::DBus and how to use Gnome15 supported displays from Perl.

What do you think?

BREW /very/strong/coffee HTTP/1.1
Host: goodmorning.example.com

418 I'm a teapot

Replies are listed 'Best First'.
Re: Net::DBus/Logitech G19 Meditator
by tanktarta (Initiate) on Jan 12, 2012 at 01:46 UTC

    I'm the author of Gnome15, and was just doing some vanity searching and came across this post.

    Love the hypno-effect, I think I have a headache now though. And the text problem probably isn't PEBCAC ;) There is a bug with that call, mainly when you supply a width/height. This is fixed in 0.8.2 which is building now. To draw some text, you would do something like :-

    $page->Text("Hypnotoad - Our Lord And Master", 50, 0, 220, 240, "center,center,wrapword");

    That would draw text in a 220x240 box located at x=50,y=0, with the text wrapped at word boundaries, vertically and horizontally centered.

    You can also change the font :-

    $page->SetFont("24", "Sans", "normal", "normal");

    It's great to see someone else using the API and if you've got any other suggestions to improve it, please feel free :)

    Brett

      Thanks for your reply.

      After thinking long and hard about it, the API itself isn't that bad (it works and when understood is quite locigal). But the documentation of it could use some updates.

      Here are some recommendations and questions:

      • How is the relationship between the different interfaces? A simple tree graph or similar could really clear that up.
      • Show some (pseudo-code?) examples on how to actually use it.
      • What happens if the client crashes? Thus Gnome15 clean everything up? What do i have to do for a clean shutdown?
      • The drawing commands feel quite slow. Any way to batch process them?
      • The Image() page function rocks. I was able to play high FPS movies. But what formats are supported?
      • Gnome15 also controls the keyboard backlight and the G-Key mapping, right? Could i use the API to control that?

      After writing my "list of demands", i like to really thank you for a very nice software. It actually is more fun to use the G19 on Linux than on Windows (with the possible exception of playing DNF)!

      "Believe me, Mike, I calculated the odds of this succeeding against the odds I was doing something incredibly stupid… and I went ahead anyway." (Crow in "MST3K The Movie")

        And thank you :)

        I'll certainly look into implementing your suggestions regarding the documentation. To answer your other questions :-

        "Client Crashes" - Currently Gnome15 will clean up any resources opened by the DBUS client when it closes. It didn't used to do this, allowing bash scripts and the command line DBUS tools to be used to create pages. But this was slow, and there was no way of knowing when to clean up if it went wrong.

        "The drawing commands feel quite slow" - This may be just DBUS, the drawing itself should be pretty quick. I think it's possible to make DBUS calls without waiting for a reply, which might speed things up a bit - no idea how though or what any side effects might be. Another alternative is to design the screen in SVG and use the SetThemeSVG() or LoadTheme() calls which will mean only 1 call. You can then draw other shapes or text over the top of that.

        "The Image() page function rocks" - Interesting use of that function! It should support anything that GTK does. Can you find out by runnng :-

        $ python import gtk gtk.gdk.pixbuf_get_formats()

        Brett