CL-Growl Slides April 23rd, 2010
Patrick Stein

On Monday, I am giving a lightning talk at the TC Lispers meeting about my Common Lisp Growl client library.

Here are the slides with presenter notes and the accompanying sample code.

GUI Discussion — TC Lispers November Meeting December 9th, 2009
Patrick Stein

Cross-posted from TCLispers.org:

Lisp GUI Discussion on Vimeo.

Robert Goldman, Paul Krueger, and Patrick Stein gave short presentations on different approaches to Graphical User Interfaces with Common Lisp.

Cross-Platform Development November 25th, 2009
Patrick Stein

In preparation for the upcoming TC Lispers meeting, I was testing my Sheeple-based CL-OpenGL GUI code on all of the different systems that I use. This was important because part of my goal in starting from bare-bones OpenGL was to make something that was pretty easy to port. The OpenGL libraries are the only non-Lisp dependencies, and they are pretty standard.

I run Mac OS X 10.6.2 as my primary development machine. I knew everything I had so far worked there under SBCL 1.0.30 and CMU-CL 20a. It took a little tweaking to get Sheeple built under Allegro CL 8.1 (Trial Edition), but after that I was five-by-five under Allegro, too. Unfortunately, I cannot get CL-OpenGL to run under Clozure 1.3-r11936 on Mac OS X. Also, ECL 9.10.2 doesn’t support weak key hashtables which Sheeple needs. And, my install of clisp broke somewhere along the lines, so I haven’t tried it.

I have an Ubuntu Linux box. There, I am using SBCL 1.0.11.debian (eeps). Everything ran perfectly over there (even displaying through X Windows back to my Mac).

I also run Windows Vista under VMWare Fusion on my Mac. I hadn’t done any development on it for months and months. Fortunately, in Google-ing to find out how to fix it, I stumbled upon what I had written about how I got things set up originally. Over the last two hours, I got SBCL upgraded to 1.0.29 under Vista. I got ASDF-Install set up with a bunch of help from this article. And, from there, I got CFFI and cl-opengl and ZPB-TTF and Sheeple installed.

ZPB-TTF and Sheeple both used some tar format options that archive_0.7.0 didn’t like. For those, I had to jump through some hoops to untar and retar them to get them to install.

Here was my final /Users/Patrick/.sbclrc file:

(require :asdf)
 
;; from Zach Beane
(defmethod asdf:perform :around ((o asdf:load-op)
                                (c asdf:cl-source-file))
  (handler-case (call-next-method o c)
    (#+sbcl sb-ext:invalid-fasl
     #+allegro excl::file-incompatible-fasl-error
     #+lispworks conditions:fasl-error
     #+cmu ext:invalid-fasl
     #-(or sbcl allegor lispworks cmu) error ()
     (asdf:perform (make-instance 'asdf:compile-op) c)
     (call-next-method))))
 
(dolist (pkg  '("alexandria/"
                "archive_0.7.0/"
                "asdf-install/asdf-install/"
                "babel_0.3.0/"
                "cffi_0.10.5/"
                "cl-opengl/"
                "flexi-streams-1.0.7/"
                "gzip-stream_0.2.8/"
                "salza2-2.0.7/"
                "sykopomp-sheeple-ceab213/"
                "trivial-features_0.6/"
                "trivial-gray-streams-2008-11-02/"
                "woolly/"
                "zpb-ttf-1.0/") )
  (pushnew (merge-pathnames pkg
                            (merge-pathnames "ASDF-Systems/"
                                             (user-homedir-pathname)))
           asdf:*central-registry*))
 
(asdf:oos 'asdf:load-op 'asdf-install)
 
;; for my sanity
(setf asdf-install:*locations*
      (list (list (merge-pathnames "ASDF-Systems/" (user-homedir-pathname))
                  (merge-pathnames "ASDF-Systems/" (user-homedir-pathname))
                  "My install spot")))
 
;; via http://sean-ross.blogspot.com/2007/05/asdf-install-windows.html
#+win32
(asdf:oos 'asdf:load-op 'gzip-stream)
 
#+win32
(asdf:oos 'asdf:load-op 'archive)
 
#+win32
(defun asdf-install-extractor (to-dir tarball)
  (let ((name nil))
    (gzip-stream:with-open-gzip-file (ins tarball)
      (archive:with-open-archive (archive ins)
	(let ((*default-pathname-defaults* (pathname to-dir)))
	  (archive:do-archive-entries (entry archive name)
	    (archive:extract-entry archive entry)
	    (unless name (setf name (archive:name entry)))))))
    (string name)))
 
#+win32
(push 'asdf-install-extractor asdf-install:*tar-extractors*)

The list of packages in the middle were about half installed manually to get the archive extraction code working and half installed through ASDF-Install. If I recall correctly, I had to manually install: archive_0.7.0, flexi-streams-1.0.7, gzip-stream_0.2.8, salza2-2.0.7, trivial-gray-streams-2008-11-02, and a fresh copy of asdf-install. I also had to download a compiled version of freeglut.dll and tuck it into my Windows\system32 directory.

Getting SBCL to use the fresh copy of asdf-install was annoying. I ended up starting up a Command Prompt as Administrator (right click on the “command.exe” icon or menu-item and select “Run as Administrator”). Then, I went to the SBCL directory (“C:\Program Files\Steel Bank Common Lisp\1.0.29\”) and did the following:

% rename asdf-install asdf-install.old
% mklink /d asdf-install "C:\Users\Patrick\ASDF-Systems\asdf-install\asdf-install\"

I had extracted the tar-ball from the ASDF-Install distribution into my ASDF-Systems directory.

Then, I went back and made my GUI code use double-buffered OpenGL windows because running Lisp to OpenGL to Windows Vista to VMWare to Quartz had some wicked flickering going on.

Two hours is a long time for something that’s supposed to be easily portable. But, I would have spent at least 95% of that time even if I were using an all-Lisp solution. And, this is far less time than I ever spent porting anything else to Windows.

Playing with Sheeple-based GUI atop CL-OpenGL November 19th, 2009
Patrick Stein

Inspired by the previous TC Lispers meeting and spurred on by the probable topic of the next TC Lispers meeting, I have spent the little bit of coding time I’ve had over the past two weeks on making a GUI layer using Sheeple atop CL-OpenGL and employing ZPB-TTF for font-loading.

I have dubbed this project Woolly (because it’s made from Sheeple and because Woolly sounds sorta like GUI).

woolly-peekI spent about half of my coding time so far getting the basic framework in place (proven through clickable buttons with labels). I am trying to keep it cleanly separated between generic GUI stuff and the CL-OpenGL specifics in the event that someone would like to port it to some other I/O spec.

The other half of my coding time was spent getting the font-rendering to be anti-aliased. I promise to write more about how I accomplished the font-rendering in a future post so that if you’re ever stuck rendering fonts in OpenGL, you won’t be stuck with pixelated blockiness or resorting to rendering to a texture-map and letting the mipmapper figure it out.

For this post, however, I’ll just show you the code that sets up the interface depicted here.

(require :asdf)
(asdf:operate 'asdf:load-op 'woolly-gl :verbose nil)
 
;; make it easier to change renderer/controller later
(rename-package 'woolly-gl 'toolkit)
 
(defun test ()
  (let ((font (sheeple:object :parents toolkit:=font=
                              :em-size 48
                              :pathname "okolaks/okolaksRegular.ttf")))
    (let ((app (sheeple:object :parents toolkit:=app=))
          (win (sheeple:object :parents toolkit:=window=
                               :title "Woolly Window 1"
                               :width 640
                               :height 480))
          (but (sheeple:object :parents toolkit:=button=
                               :offset-x 40
                               :offset-y 40
                               :width 300
                               :height 100
                               :font font
                               :label "Button")))
      (woolly:display-window win)
      (woolly:add win but)
      (woolly:main-loop app)
      (woolly:destroy-window win))))

Next up on my agenda is to make the background and button prettier. It should be easy enough to do with GL_LIGHTING and some vertex-coloring for gradations. After that, it’s on to more controls like labels, panels, checkboxes, drop-downs, borders, and (my dread) text input boxes. Then, it’s on to a layout manager.

woolly-peekEdit: Here’s the same GUI a day later. I’m using a simple lighting scheme and rendering the button in 3D. I haven’t yet hooked in the bit to render it depressed when the button is pressed. I’ve tested the code that draws it the other way, but I haven’t hooked it into the mouse handlers yet.

Edit #2: Actually, it only took a few minutes for me to hook in the rendering it pressed vs. unpressed. When I did it though, it looked like the label was sliding around because the effect of the contrast between the light and dark edges of the button was so great that you perceive the whole button sliding when it’s pressed. So, I added a little bit in there to actually slide the text by an amount close to what is perceived. So, now… it looks pretty spiffy.

ScreenFlow: Review August 21st, 2009
Patrick Stein

I downloaded the trial version of ScreenFlow in early July. I performed a few simple tests with it, liked what I saw, and bought a license. Since purchasing the license, I have used it to record and publish six presentations. Overall, it is a wonderful program that more than lives up to the license price.

How I’ve Been Using It

I have a 2.4GHz MacBook Pro, a FireWire webcam, a stand-alone video camera, a tabletop tripod, and a BlueTooth headset. I brought all of this equipment to the TC Lispers meeting in July.

I failed to record the first presentation. The BlueTooth headset, of course, has a rather opaque user interface. It has an on-off switch. It is unclear which position is on and which is off. It has two buttons for volume control. It has one button that does everything else depending on the current state and whether you click, double-click, or triple-click. I did something wrong. This resulted in a recording failure that I didn’t notice until after the presentation. Most of this was the headset (and me). ScreenFlow could have done better at alerting me (more on that below).

For the other three presentations that evening, I recorded audio through the built-in microphone on the MacBook. This worked famously, and I used it to record the August presentations, too.

Because of the projector we are using, I record the screen at 1024×768. That resolution is plenty, in my opinion. For the July presentations, I recorded some video directly with ScreenFlow from the FireWire webcam. I recorded additional video with the stand-alone video camera. I used the video from the stand-alone camera in two of the final presentations in place of the webcam video because the contrast was better. I didn’t use the stand-alone camera video in the other presentations because I had to change tapes in the middle of one presentation and ran out of batteries in the other.

I forgot to bring my FireWire adapter to the August meeting, so I recorded all of that video with the stand-alone video camera.

After each presentation, I stopped recording and saved (more on this below). The next day, I prepared the final video. I resized the whole thing to 1024×640 to get a more dramatic aspect ratio and to give me a little room to put the screencast and video side-by-side. I added in a couple images (a TC Lispers logo and a Creative Commons logo) and a line of text.

For those presentations where I used the stand-alone video camera’s video, I imported that into ScreenFlow in the comfort of my own home. The audio from my stand-alone camera doesn’t import into ScreenFlow very well. As such, I ended up toying with the video until I got it synced with the audio I had recorded from the built-in microphone (more on this below). I think I’m going to use a clap board next time.

I positioned all of my pieces, added some shadows, added some reflections, and added some Video Actions to transition where the screencast and video sat in space.

Then, I exported the clips and uploaded them to Vimeo. I’m quite pleased with the results.

What It Does Wonderfully

If you can have ScreenFlow record your screen, audio, and video all at the same time, then most everything you’ll want out of this software is a dream.

You’ll have your screencast and video already there. You can add in text and stills. You can add in additional audio or video sources. You can position, scale, and tilt your visual elements. You can give them drop-shadows and reflections. You can adjust the volume of your audio or add audio effects to it.

You have a great deal of control over the text. You can change the font, the alignment, the fill color, the outline color, the background color, and the margin and corner-rounding on the text background. For those color adjustments, you can even adjust the opacity.

For shadows, you have control over the angle, color, offset, opacity, and blur-size. For reflections, you have control over the opacity.

You can add video or audio actions to any clip. You can select multiple clips at once to add an action to so that all of the actions happen at the same time. The actions aren’t so much actions as transitions. You can set the parameters: (opacity, scale, position, orientation, reflection, shadow, etc.) before and after the action. The action will transition from one to the other.

The actions take a little getting used to. When I first started, I had a tendency to try to set the position of a clip before and after an action. The tricky bit is that when you set a parameter before the action, that parameter has effect the whole way back to the last action (or the beginning when there are no prior actions). I surprised myself accidentally several times forgetting to put in an action at the place I want to transition. My workflow now is to get everything in its starting state, go through to where I want the first action, put in the action, and only change the parameters after the action. ScreenFlow inserts the action to finish at your current position in the timeline so this method is the natural way they envisioned, I believe.

Once I have all of my video imported and synced, it only takes me about fifteen minutes to place the logos, other text, get all of the parameters set the way I like (shadows on everything, reflections on screencast and video), add all of the actions that I want, and start exporting. Exporting at high quality takes hours and hours, but that it mostly a function of the multipass compression, not of ScreenFlow itself. You can export at low quality a good deal faster. My big concern though is to be sure you can read the slides and live-typing even after it comes through Vimeo though. As such, I let it export overnight.

What I Wish It Did Better

When you start a recording with ScreenFlow, it gives you a countdown to start recording. I put my Keynote presentation in Fullscreen mode before the countdown completed. It wasn’t until I closed my Keynote presentation that I saw that ScreenFlow had bailed because it could not get input from the microphone. Maybe ScreenFlow can’t bring up a dialog in front of a Fullscreen application, I don’t know. But, it could have told me audibly that it was having issues.

When I did test recordings, I didn’t do anything over five minutes. When I (successfully) recorded the first hour-long presentation, I hit Save. I got the spinning beach ball for a very long time. I was concerned that the application was hung. I am thinking that it was just recoding the video it had pulled in from the webcam. For the August meeting, I wasn’t recording video with ScreenCast during the presentation. Saving at the end of the presentation took no time at all. While I was watching the beach ball spin, I was starting to worry that I had paid a whole bunch for a license that wasn’t going to work for my purposes. The beach ball finished after about eight or nine minutes… just in time for the next presentation. Everything saved perfectly. I could have used a progress bar instead of a beach ball though.

ScreenFlow does not do well importing the audio from my stand-alone video camera. I can pull this audio into iMovie just fine. I might be able to pull it in with iMovie and add it into my ScreenFlow presentation. I don’t know. When I pull it directly into ScreenFlow though, the audio has terrible digital distortion like they made the wrong guess about signed or unsigned samples. You can still follow along enough to help synchronize it with the audio recorded from the built-in microphone, but you’d never want it in your final movie.

Synchronizing an independent video or audio source that wasn’t being pulled into ScreenFlow during the presentation is annoying. I think I can mitigate most of it by using a clap board before things get underway. Trying to do this retroactively was annoying. I had to move the screencast and the built-in audio clips away from time zero. Then, I had to find an area where there was a distinctive sound. I then had to play with moving the newly imported video clip back and forth in time until things were close enough. Fortunately, the human brain is very forgiving about badly synchronized audio and video.

Once I got the clips aligned, I had to move the scrubber back to the beginning of the built-in microphone recording, trim all of the clips from the front to the scrubber, and then move all of the clips back to time zero.

I tried using the markers feature to help me synchronize clips. Unfortunately, the markers are locked to the timeline and I couldn’t see a way to clamp a particular part of a clip to the marker.

I used the Show Audio Waveforms feature to help me synchronize the audio. This was a bit awkward because of the digital distortion in the video camera import. It was also a pain because the timeline is impossible to work with when it is trying to display the waveforms. You can’t have an hour long clip with a waveform and use the magnification slider on the timeline. You end up getting a beach ball part way through your drag. You have no idea where it will think you let go of things when the beach ball finally pops. You can’t move around the timeline or move things within the timeline with the waveforms displayed either for these lengthy clips. I turn off the waveforms as soon as I can. They don’t add much to my process, and they really get in the way.

The program has a feature to add Callouts. These can either highlight the mouse position or the foreground window. In my case, I wanted to retroactively add in Callouts. During the presentation, the presenter was pointing at the projected image with his hand. The callouts were locked to where the mouse was. It would have been fabulous if it would have let me position a callout during edit time instead of being stuck with where the mouse was during the presentation.

The Upshot

It has some frustrations, but it does most things very smoothly. Turn off the Show Audio Waveforms, use a clap board, and enjoy. The output is unmatched, and the interface is very easy to fall into.

Updates In Email

Email:

l