Tuesday, September 30, 2014

Ubuntu Upgrade Woes

I tried to upgrade to the newest LTS release last week. Let's get this out of the way, relevant XKCD. It took three solid, long days, which is more than anybody should ever be expected to spend installing an operating system for a desktop system (though I must admit that I spent a full week working through Linux From Scratch in my off time). All said and done, I was left with a (almost) fully functional Ubuntu installation, so I am pretty happy.

To put this in context, I have a whole bunch of rants about how much Ubuntu sucks filed away on my computer, but this will probably be the first one that will actually see the light of day. The only reason I bring it up is that it seems that I, sort of, figured out why this was causing me problems and how to fix it. However, I don't really know of a place to put this. I know what worked for me, but I really don't understand it fully and I really don't think I am in the position to give technical advice to anybody.

So, I'll get to the short of it with the hopes that anybody in my same shoes that is frantically Googling about might land on this page. If you:

  1. Are running Ubuntu (or probably any other GNU/Linux that supports EFI boot) on a MacBook Pro (at least the 6,2 model, but perhaps others that use hybrid video technology).
  2. Are having a tough time getting the Nvidia drivers to work (the install but you end up with a blank screen on the next boot).

You might be suffering from the same issue I had; you need to ensure that you are booting in emulated BIOS mode rather than using Apple's EFI. For me, this means that I need to hold the "Option Key" on boot and hand select the Ubuntu drive, but Google says that there are other ways to do this.

It actually solves one of the big mysteries I've had since starting to use Ubuntu on the Apple computers: the poor battery life in Ubuntu versus OS X (in my and my friend's experience this basically cuts the idle lifetime by a factor of two to three). At least one of the reasons for this poor battery life (and perhaps the major contributor) is that the video card is stuck in the discrete Nvidia GPU mode and never switches to the integrated i915 card.

This caught me by surprise as I wasn't aware that booting using different methods would leave the hardware in different states (i.e. boot one way and the system is stable and usable, boot another way and you will get crappy performance at best and very likely an install that will crash every time it tries to start Xorg). It is a shame that Ubuntu picks the unstable EFI way to set up the booting process… however…

You really can't blame Ubuntu for their decision. Apple used a non-standard EFI method for (at least) this series of MacBook Pros. They also used a non-standard hybrid video technology based on Optimus but sufficiently different that none of the bumblebee stuff works, yet. I think people are working on it and Youtube shows some videos with working proof-of-concept graphics switching, but it is a pretty old laptop so I'm not holding my breath.

As a side note, while the whole installation debacle should have soured me on 14.04, I have to say that it is extremely well polished compared to 12.04. Of course it could be better, but I absolutely love how Unity looks once you install a few themes and fiddle with Unity Tweak Tool to bend it to your taste.

Also, I know many people that would ask, "was it worth it?" Is it worth it to work for three days to get a GNU/Linux installation up and running? Absolutely. I am vastly more productive when working within GNU/Linux. Should it have taken less time? Absolutely, and that is the real question to ask. Would another distribution provide similar features for much less investment?

Tuesday, April 1, 2014

Some Emacs hacks for GDB and other stuff

I am fighting with GDB in Emacs today. Thought I would share a few hacks that make things more livable. These get hackier as you go, so… be warned.

First, GDB in many windows mode makes a bunch of dedicated windows. This can be pretty annoying. In fact, dedicated windows in general can be pretty annoying. If I want to change the buffer of a window, don't you dare stop me. Emacs Wiki has some advice code that allows you to disable the setting of dedicated windows in GDB startup (bottom of the page). But to be clear, this is a problem with the Emacs interface, not the GDB interface. The GDB interface has a good reason to not want those buffers to change, and it is annoying to use it if they do change. The problem is when I know that I really do want these to change but Emacs makes me jump through hoops to do it. So, let's fix the underlying problem. Here is a bit of code to add to your init files that will allow you to change buffers even if they are dedicated.

(defun undedicate-window (&optional window)
  (interactive)
  (set-window-dedicated-p (or window (get-buffer-window)) nil))

;; Removing annoying dedicated buffer nonsense
(defun switch-to-buffer! (buffer-or-name &optional norecord force-same-window)
  "Like switch-to-buffer but works for dedicated buffers \(though
it will ask first)."
  (interactive
   (list (read-buffer-to-switch "Switch to buffer: ") nil 'force-same-window))
  (when (and (window-dedicated-p (get-buffer-window))
             (yes-or-no-p "This window is dedicated, undedicate it? "))
    (undedicate-window))
  (switch-to-buffer buffer-or-name norecord force-same-window))

I just set a global key binding of (kbd "C-x b") to switch-to-buffer! (actually I use a global minor mode to keep track of all of my keybindings, but the result is the same). This will now act exactly like switch-to-buffer unless the window is dedicated, in which case it will ask if you want to "undedicate" the window first. Now Emacs wont reuse these buffers willy nilly, but you can still do what you think is best.

Second, dedicated windows are so convenient (now that they are convenient to undedicate) that you might find that you want to start setting the dedicated flag on random windows that you don't want Emacs to change. So here is a function for that. If you want a dedicated completion window, well, just set it on that window and you won't have to worry about it getting taken over by some other Emacs pop-up.

(defun toggle-window-dedication (&optional window)
  (interactive)
  (let ((window (or window (get-buffer-window))))
    (set-window-dedicated-p window (not (window-dedicated-p window)))))

(global-set-key (kbd "C-x d") 'toggle-window-dedication)

Third, I really hate that performing any act in GUD tends to make the source buffer you are working with jump back to the execution point. This is a problem if you are setting several breakpoints, or printing out several values from the source file. Thus I came up with this hack (and this really is a hack) to make this problem go away.

(defun nice-gud-print (arg)
  (interactive "p")
  (save-excursion
   (gud-print arg)
   (sleep-for .1)))
(global-set-key (kbd "C-x C-a C-p") 'nice-gud-print)
(defun nice-gud-break (arg)
  (interactive "p")
  (save-excursion
   (gud-break arg)
   (sleep-for .1)))
(global-set-key (kbd "C-x C-a C-b") 'nice-gud-break)
(defun nice-gud-tbreak (arg)
  (interactive "p")
  (save-excursion
   (gud-tbreak arg)
   (sleep-for .1)))
(global-set-key (kbd "C-x C-a C-t") 'nice-gud-tbreak)

The sleep-for call is necessary to make save-excursion actually work. My guess here is that GUD queues requests and then executes them later. So without the sleep, my call to GUD returns, and with it the save-excursion environment exits, long before GUD processes the command and then resets the view to the execution point. Not pretty, but it works for me at least.

Lastly, I find that it is helpful to have a key binding for gdb-restore-windows. This way you can easily jump to a particular window, make the buffer full screen, and then return to the debugger view later. However, if you like to use a vertically split screen like I do (i.e. you like 80 column width programs), it is often even better to have a toggle between just the two center windows and the full debugger view. So, here is a function to do that:

(defun gdb-windows-toggle (&optional full-restore)
  (interactive "P")
  (let ((window-tree (first (window-tree))))
    (cond (full-restore
           (gdb-restore-windows))
          ((and (listp window-tree)
                (= (length window-tree) 5))
           (let ((buffers (if (listp (fourth window-tree))
                              (mapcar 'window-buffer
                                      (rest (rest (fourth window-tree))))
                              (list (window-buffer (fourth window-tree)))))
                 (first-selected (or (windowp (fourth window-tree))
                                     (eql (first (window-list))
                                          (third (fourth window-tree))))))
             (delete-other-windows)
             (when (> (length buffers) 1)
               (split-window-horizontally))
             (cl-loop for buffer in buffers
                      for window in (window-list)
                      do (progn (undedicate-window window)
                                (set-window-buffer window buffer)))
             (unless first-selected
               (select-window (second (window-list))))))
          ((or (windowp window-tree)
               (and (= (length window-tree) 4)
                    ;; horizontal split
                    (not (first window-tree))
                    ;; No further splits
                    (windowp (third window-tree))
                    (windowp (fourth window-tree))))
           (let ((current-buffers
                   (if (windowp window-tree)
                       (list (window-buffer window-tree))
                       (mapcar 'window-buffer (rest (rest window-tree)))))
                 (first-selected (or (windowp window-tree)
                                     (eql (first (window-list))
                                          (third window-tree)))))
             (gdb-restore-windows)
             (let ((windows (rest (rest (fourth (first (window-tree)))))))
               (when (= (length current-buffers) 1)
                 (delete-window (second windows)))
               (cl-loop for buffer in current-buffers
                        for window in windows
                        do (progn (undedicate-window window)
                                  (set-window-buffer window buffer)))
               (if first-selected
                   (select-window (first windows))
                   (select-window (second windows))))))
          (t ;; If all else fails, just restore the windows
           (gdb-restore-windows)))))

(global-set-key (kbd "C-c g") 'gdb-windows-toggle)

That is long and ugly, and probably could be made much simpler, but it does the trick and does it pretty well. Maybe if these really work out I can get someone involved with Emacs to include some of these little hacks (cleaned up of course). It would be nice to deal with the fact that GDB is fundamentally broken for me right now, but… we'll see where those bug reports go.

Monday, January 13, 2014

Visualization of the Game of Life

Working with visualization a bit today and needed a system to visualize, so I did the Game of Life and it turned out pretty, so I decided I should share.


The game is played in the XY plane. Older generations are moved down in Z and their color is darkened by 20%. Each system is started with random live and dead cells. The first runs are with free boundary conditions while after around 2:50 I switch to a toroidal system of size 20 in X and Y. You can clearly see gliders at several places in the video, for instance there is one at the 2:00 mark.

If you care, the simulation and visualization were all done from inside a Lisp session and takes around 90 lines of code (including blank ones) to get this effect.  The stuttering frame rate is due to the screen capturing software, RecordMyDesktop.  I'm not sure how to do this better other than grabbing the frames from the OpenGL display buffer, writing them to a bitmap file, and making my own video with FFMPEG (which is what I do for presentations).

I need to figure out how to make this a live wallpaper for my phone...