TEDx Montréal Quartier Latin: Lending an (un)helping hand

Check out my TEDx talk done in October 2010 in Montréal, QC! I am always closing my eyes in photographs and this could not be the exception.

Jorge Silva argues that when designing assistive devices biomedical engineers should seek to “scratch where it itches.” By adopting alternative business models such as open source systems, users of assistive devices are revolutionizing design and production processes, creating technologies that fit the needs of a larger population.

J-Doc got Sparked

Pretty cool piece by Nora Young and the rest of the CBC Spark team about some of the work we have been doing over at the Adaptive Technology Resource Centre.

Check out the podcast here:
http://www.cbc.ca/spark/2009/06/episode-82-june-17-20-2009/

and the video clip Nora mentioned here:

Hi-Res Duke Nukem 3D on Linux

Screenshot of Duke Nukem 3D with eDuke32

Screenshot of Duke Nukem 3D on Linux with eDuke32

A long, long time ago in a country far, far away, I used to spend hours playing one of the first 3D first person shooter games that allowed me to do just about anything I wanted. It was so cool to be able to turn lights on and off, look at your own reflection in the mirrors (even if the reflection was carrying the wrong gun) and, yes of course, pee, if you felt like it. All of this was possible in the wonderful world of Duke Nukem 3D. So you can imagine my surprise when I discovered I could turn back the clock to my teenage years and enjoy, once again, the full agency of my virtual presence in post-apocalyptic Hollywood, thanks, of course, to the magic of Linux.

The code that will make this happen for you is located on the eDuke32 wiki page. eDuke32 is an open source port of the original engine and it works like a charm. This is how you make it work:

  1. Download and extract the most recent source package. It should be named something like:
    eduke32_src_YYYYMMDD.zip

    , where YYYYMMDD is the release date.

  2. It is also a good idea to download the most recent patch, which will be named
    eduke32_src_YYYYMMDD.diff

    , into the same directory where you extracted the source code.

  3. To apply the patch, do:
    $ patch -p3 < eduke32_src_YYYYMMDD.diff

    from the directory where you extracted the source code.

  4. Make sure you have the required dependencies:
    $ sudo aptitude install libsdl1.2-all libsdl1.2-dev libsdl-mixer1.2-dev libsdl-sound1.2-dev nasm
  5. Now
    cd

    into the
    eduke32_src_YYYYMMDD

    directory and type
    make

    like this:

    $ cd eduke32_src_YYYYMMDD/
    $ make
  6. More detailed information is available on the eDuke32 site, the eDuke32 wiki and the high resolution pack site. Enjoy!

Make compiz-fusion work with xscreensaver (the quick & dirty way)

The beautiful desktop experience provided by compiz-fusion represents a significant aesthetic contribution to the pleasure of using Linux. Besides, it makes it really easy to impress even the most committed Apple disciple. The same is true for the cool gl screensavers written for xscreensavers. Unfortunately, these two don’t really work together (my computer freezes everytime xscreensaver comes up while running compiz-fusion) and although the screensaver plugin for compiz-fusion shows great potential, the gl collection for xscreensaver is still a bit ahead and has a lot more variety, so I really wanted to make them work together.

Here is what I did:

  1. You can use
    xscreensaver-command -watch

    to monitor xscreensaver events, so you can actually run a program when xscreensaver is activated (for example, to disable compiz-fusion), and another one when it is deactivated (to bring compiz-fusion back). I modified the following script available from the xscreensaver man pages and saved it as
    ~/bin/fixscreensaver

    :

    #!/usr/bin/perl
    
    # Fixes xscreensaver when compiz is running
    
    my $blanked = 0;
    open (IN, "xscreensaver-command -watch |");
    while () {
      if (m/^(BLANK|LOCK)/) {
        if (!$blanked) {
          system "usemetacity";
          $blanked = 1;
        }
      } elsif (m/^UNBLANK/) {
        system "usecompiz";
        $blanked = 0;
      }
    }
  2. As you can see, the script above calls
    usemetacity

    when xscreensaver is activated and
    usecompiz

    when it is deactivated. Save the following script as
    ~/bin/usemetacity

    :

    #!/bin/bash
    
    #killall gkrellm
    metacity --replace &
    #sleep 1
    #gkrellm &
  3. Now save this one as
    ~/bin/usecompiz

    :

    #!/bin/bash
    
    #killall gkrellm
    compiz --replace &
    #sleep 2
    #gkrellm &
    #windowranger
  4. Add
    ~/bin/fixscreensaver

    to the list of startup applications (System > Preferences > Sessions > Startup programs) and also make sure that
    ~/bin/

    is in your $PATH environment variable.

  5. Optional: If you use gkrellm, you should uncomment the corresponding lines in the scripts above. Those lines will prevent metacity (the default gnome window manager) and compiz-fusion from changing the position of the gkrellm window, which happens everytime you switch between the two because these window managers use different ways to describe desktop geometry.
  6. Optional: You can also use the
    usecompiz

    and
    usemetacity

    scripts to manage any other application that misbehaves when metacity or compiz-fusion take over your desktop. In fact, I use the
    windowranger

    script below to automatically put windows back into their corresponding viewports since everything gets shoved into the first viewport once you go back into compiz from metacity (thanks for pointing it out darken). You will need
    wmctrl

    for this to work properly:

    #!/usr/bin/python
    
    import os, time, wnck, sys
    
    def dec2hex(n):
      #"""return the hexadecimal string representation of integer n"""#
      return "%X" % n
    
    def hex2dec(s):
      #"""return the integer value of a hexadecimal string s"""#
      return int(s, 16)
    
    def MoveWindow(wID, wtitle, xpos, ypos):
    
        time.sleep(0.2)
        os.system('wmctrl -i -r ' + wID + ' -e 0,'+str(xpos)+','+str(ypos)+',-1,-1')
        #time.sleep(0.4)
        #os.system('wmctrl -i -a ' + wID)
        if DEBUG: print "Moved to", xpos, ypos, 'n'
    
    def Place(x, y, wID, wclass, wtitle):
    
      fin,dout = os.popen4('wmctrl -d')   # output desktop geometry
      for line in dout:
        line = line[line.find('VP: ') + 4:len(line)]  # get current viewport offset
        line = line[0:line.find(' ')]
        offset = line.split(',')      # split in x,y viewport offset coordinates
        vpxpos = int(offset[0])       # convert into integer
        vpypos = int(offset[1])       # convert into integer
        absxpos = vpxpos+x            # absolute window position (x)
        absypos = vpypos+y            # absolute window position (y)
        wxpos = absxpos
        wypos = absypos
        while wxpos >= width:
          wxpos = wxpos - width       # relative window position (x)
        while wypos >= height:
          wypos = wypos - height      # relative window position (y)
        if (wxpos >= 0)&(wxpos <= 2): wxpos = 0
        if (wypos >= 0)&(wypos <= 2): wypos = 0
    
      dout.close()                    # close command output
      if DEBUG: print 'Position:', absxpos, 'x', absypos
    
      #Send Firefox to viewport 1
      if wclass.find('Firefox') != -1:
        # Flash fullscreen windows are titled 'Firefox' so we need to ignore them...
        if wtitle != 'Firefox':
          MoveWindow(wID, wtitle, wxpos - vpxpos + vpx1, wypos - vpypos + vpy1)
    
      #Send GYachI to viewport 2
      elif wclass.find('GYachI') != -1:
        MoveWindow(wID, wtitle, wxpos - vpxpos + vpx2, wypos - vpypos + vpy2)
    
      #Send VirtualBox to viewport 5
      elif wclass.find('VirtualBox') != -1:
        MoveWindow(wID, wtitle, wxpos - vpxpos + vpx5, wypos - vpypos + vpy5)
    
      #Send Amarok to viewport 6
      elif wclass.find('Amarokapp') != -1:
        MoveWindow(wID, wtitle, wxpos - vpxpos + vpx6, wypos - vpypos + vpy6)
    
      #Send Azureus to viewport 6
      elif wclass.find('SWT') != -1:
        MoveWindow(wID, wtitle, wxpos - vpxpos + vpx6, wypos - vpypos + vpy6)
    
      #Send Qbittorrent to viewport 6
      elif wclass.find('Qbittorrent') != -1:
        MoveWindow(wID, wtitle, wxpos - vpxpos + vpx6, wypos - vpypos + vpy6)
    
      #Send Pidgin to viewport 7
      elif wclass.find('Pidgin') != -1:
        MoveWindow(wID, wtitle, wxpos - vpxpos + vpx7, wypos - vpypos + vpy7)
    
      #Send Skype to viewport 7
      elif wclass.find('Skype') != -1:
        MoveWindow(wID, wtitle, wxpos - vpxpos + vpx7, wypos - vpypos + vpy7)
    
      #Send Thunderbird to viewport 8
      elif wclass.find('Thunderbird-bin') != -1:
        MoveWindow(wID, wtitle, wxpos - vpxpos + vpx8, wypos - vpypos + vpy8)
    
      #Send all other windows in viewport 1 to viewport 2
      elif (wclass.find('Gnome-panel')==-1)&(wtitle != 'Desktop')&(wclass.find('Gkrellm')==-1)&(wclass.find('Launcher')==-1)&(absxpos < width)&(absypos <= height):
        MoveWindow(wID, wtitle, wxpos - vpxpos + vpx2, wypos - vpypos + vpy2)
    
      else:
        if DEBUG: print 'Ignoredn'
    
    #---------------------------- MAIN -------------------------------------
    s = wnck.screen_get_default()
    width = s.get_width()
    height = s.get_height()
    vpx1 = (width * 0);vpy1 = (height * 0)
    vpx2 = (width * 1);vpy2 = (height * 0)
    vpx3 = (width * 2);vpy3 = (height * 0)
    vpx4 = (width * 3);vpy4 = (height * 0)
    vpx5 = (width * 0);vpy5 = (height * 1)
    vpx6 = (width * 1);vpy6 = (height * 1)
    vpx7 = (width * 2);vpy7 = (height * 1)
    vpx8 = (width * 3);vpy8 = (height * 1)
    DEBUG = False;
    
    for arg in sys.argv:
      if arg=='--debug':
        DEBUG=True;
    
    if DEBUG: print 'Viewport geometry:', width, 'x', height, 'n'
    
    fin,wout = os.popen4('wmctrl -lGx')
    for line in wout:
      wID = line[0:line.find(' ')]                      # get the window ID
      line = line[line.find(' '):len(line)]
      line = line.lstrip()
      wdesk = line[0:line.find(' ')]                    # get the window desktop
      line = line[line.find(' '):len(line)]
      line = line.lstrip()
      wxoffset = line[0:line.find(' ')]                 # get the window x offset
      wxoffset = (int(wxoffset) / 2)
      line = line[line.find(' '):len(line)]
      line = line.lstrip()
      wyoffset = line[0:line.find(' ')]                 # get the window y offset
      wyoffset = (int(wyoffset) / 2) - 24
      line = line[line.find(' '):len(line)]
      line = line.lstrip()
      wwidth = line[0:line.find(' ')]                   # get the window width
      line = line[line.find(' '):len(line)]
      line = line.lstrip()
      wheight = line[0:line.find(' ')]                  # get the window height
      line = line[line.find(' '):len(line)]
      line = line.lstrip()
      wclass = line[0:line.find(' jsilva')]             # get the window class
      line = line[line.find(' jsilva'):len(line)]
      line = line.lstrip()
      whost = line[0:line.find(' ')]                    # get the window host
      line = line[line.find(' '):len(line)]
      line = line.lstrip()
      wtitle = line[0:len(line) - 1]                    # get the window title
      if DEBUG:
        print 'Class:', wclass
        print 'Host:', whost
        print 'Title:', wtitle
      Place(wxoffset,wyoffset,wID,wclass,wtitle)  # place window
    wout.close()
  7. Enjoy!