Using Quil in REPL

388 views
Skip to first unread message

Todd Blume

unread,
May 15, 2013, 5:07:01 AM5/15/13
to clojured...@googlegroups.com
I'm just learning Clojure and thought that playing with Quil would be a fun way to do it. I've got a project that has leinigen nature and the Quil dependency set up. When I run from the file everything works, but when I try to use Quil functions in the REPL it fails.

I've done (use 'quil.core) and the Quil namespace seems to be loaded. It shows up in the namespace browser and the symbols seem to be bound to the Quil code. But the dependency on the native Processing package seems to be broken. For example (color 45) throws a NullPointerException. I can see from the trace that the exception is thrown from the Quil color function when it is trying to call the native Processing .color function.

The CCW release note says:

"Of course, when you have an active REPL, and once a namespace from a dependency's jar has been loaded in the REPL, you can open vars from this namespace as usual, via F3, Ctrl/Cmd+Click in the REPL or from the editor, and also by double-clicking on the var from the Namespace Browser.

Native deps are also correctly supported. Meaning you can start hacking with Overtone or Quil and their Sound / OpenGL supports right now!!!"

So how do I get the transitive dependency on the Processing native lib to work in the REPL?
I've tried various forms to get the native lib loaded with no success.

Would some kind soul please share the proper expressions to enter into the REPL so that Quil and the Processing native jar gets loaded?

Thanks for CCW! I love that I can use Clojure in Eclipse.
Using Eclipse Juno on Mac OSX Mountain Lion.

Laurent PETIT

unread,
May 15, 2013, 5:30:11 AM5/15/13
to clojuredev-users
Hello,

Are you using the stable version 0.12.3 of CCW, or the beta version ?

2013/5/15 Todd Blume <t...@tigerisland.com>:
> --
> You received this message because you are subscribed to the Google Groups "counterclockwise-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to clojuredev-use...@googlegroups.com.
> To post to this group, send email to clojured...@googlegroups.com.
> Visit this group at http://groups.google.com/group/clojuredev-users?hl=en.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Niels van Klaveren

unread,
May 15, 2013, 7:15:08 AM5/15/13
to clojured...@googlegroups.com
There's indeed something going wrong with Quil's native dependencies in 0.12.3, see this thread in clj-processing group.

Todd Blume

unread,
May 16, 2013, 4:23:08 PM5/16/13
to clojured...@googlegroups.com
I'm using STABLE001
  Counterclockwise (Clojure plugin for Eclipse) 0.12.3.STABLE001 ccw.feature.feature.group Counterclockwise team

The release note that I quoted implies that native deps are working, and rolled out in the latest stable version. Do I need a newer beta instead? (did I read the wrong note?)

Since it specifically mentions Quil I'd think that somebody has tried it and knows what the magic incantation is...

Laurent PETIT

unread,
May 16, 2013, 4:43:03 PM5/16/13
to clojuredev-users
Hello,

OK, so I tested it against Quil 1.6.0. Please can you check the following:

a) expand the "Leiningen Dependencies" node under your project node.
You should see clojure, org.processing.*, quil jars.
b) if you select e.g. org.processing.core jar in the leiningen
dependencies, invoke the contextual menu, and select the "properties"
menu item, select the "Native" Entry on the left of the Properties
popup: You should see "Location Path :
<your-project-name>/target/native/macosx"
c) then, after potentially doing a project refresh, you should see the
target folder under your project, and the native/macosx subfolders as
well ; and a lot of .jnilib files in them.

If you have problems, then try to force a "leiningen refresh" on the
project : project > contextual menu > Leiningen > "Reset project
configuration", and retry steps a) b) & c).

Note that if you've also got leiningen on the command line, and issued
a "lein clean", then the "target/" folder may well have disappeared.
That's something I don't like in Leiningen, the way native
dependencies are dropped in the target/ folder and may disappear
anytime with a clear, when they are really just another kind of
dependency and belong to a more "stable" location on the filesystem.
Anyway.

Hope this helps,

Looking forward to hearing from your report on all this,

--
Laurent



2013/5/16 Todd Blume <t...@tigerisland.com>:

Todd Blume

unread,
May 16, 2013, 4:44:07 PM5/16/13
to clojured...@googlegroups.com
The last post in that thread was from Laurent on 2012.6.16 just a week before CCW 0.9.0 Stable was released. It indicates that native deps were fixed in beta, and the 0.9.0 release note that I quoted  says the same and mentions working with Quil. Is there a new regression that breaks native deps in the REPL?  Is there an open issue on 0.12.3? Anybody tried Quil lately?

Would issue 533 have anything to do with this? I don't think switching namespaces is involved.

Todd Blume

unread,
May 16, 2013, 5:05:33 PM5/16/13
to clojured...@googlegroups.com
Thanks Lauren for the quick reply! Still no luck though.


On Thursday, May 16, 2013 10:43:03 AM UTC-10, laurent.petit wrote:
Hello,

OK, so I tested it against Quil 1.6.0. Please can you check the following:

a) expand the "Leiningen Dependencies" node under your project node.
You should see clojure, org.processing.*, quil jars.
b) if you select e.g. org.processing.core jar in the leiningen
dependencies, invoke the contextual menu, and select the "properties"
menu item, select the "Native" Entry on the left of the Properties
popup: You should see "Location Path :
<your-project-name>/target/native/macosx"

This all looked good. Clojure jar, 6 processing jars, and quill jar all there. Native path on processing.core looks good.
 
c) then, after potentially doing a project refresh, you should see the
target folder under your project, and the native/macosx subfolders as
well ; and a lot of .jnilib files in them.


Target folder was missing. Project refresh created it. Targets now have liblugen-rt and libogl* in them.

(color 42) still fails with NullPointerException. I load my file with a sketch to start the REPL (sketch runs). Is this the wrong thing to do?
 
If you have problems, then try to force a "leiningen refresh" on the
project : project > contextual menu > Leiningen > "Reset project
configuration", and retry steps a) b) & c).


This had no effect.
 
Note that if you've also got leiningen on the command line, and issued
a "lein clean", then the "target/" folder may well have disappeared.
That's something I don't like in Leiningen, the way native
dependencies are dropped in the target/ folder and may disappear
anytime with a clear, when they are really just another kind of
dependency and belong to a more "stable" location on the filesystem.
Anyway.


I may have cleaned somewhere along the way following advice in other threads. I'm still new to Leinigen, CCW, and Clojure...

Hope this helps,

It still doesn't work. I assume that it worked when you just tested it. What are you typing into the REPL? Are you giving it any expressions to modify the namespace state?
 

Looking forward to hearing from your report on all this,

--
Laurent

Any further ideas?
Thanks for all of your help!

Aloha,
Todd 

Laurent PETIT

unread,
May 16, 2013, 5:26:13 PM5/16/13
to clojuredev-users
2013/5/16 Todd Blume <t...@tigerisland.com>:
I must confess I didn't try in the REPL. I wanted first to check the
above points.

To make significant progress with test REPLs, it would be better if I
could reproduce the exact steps you are. Is it easy for you to share
your project ? Maybe via Github ? Maybe in a small zip (remove the
target folder first ! :-) ).
And then tell exactly the way you're starting the REPL (as if you
would explain behind my back, telling me to point the mouse at this
control, then type this keyword combination. Assuming I'll fill the
gaps is a recipe for not following the same code paths and thus not
being able to see the same problems appear).

Cheers,

--
Laurent

Todd Blume

unread,
May 16, 2013, 6:15:28 PM5/16/13
to clojured...@googlegroups.com
I understand. There is a time to be terse, and a time to be verbose.
Unfortunately I have to run out now, so I'll have to get you a full test package tomorrow.
The good news is that my test case is an absolutely trivial sketch - it just displays an image from a file:

------------------

(ns quilTest.core (:use quil.core))


(def HEIGHT 200)

(def WIDTH 320)


(defn setup []

  (smooth)                          ;;Turn on anti-aliasing

  (frame-rate 100)                  ;;Set framerate to 1 FPS

  (background 200)                  ;;Set the background colour to a nice shade of grey.

 

  (color-mode :hsb MAX_HUE MAX_SATURATION MAX_BRIGHTNESS MAX_ALPHA)

  

  (set-image 0 0 (load-image "image.png"))

  )                 

                                    

(defn draw []

)

                                    

(defsketch example                  ;;Define a new sketch named example

  :title "Wu Xing"                  ;;Set the title of the sketch

  :setup setup                      ;;Specify the setup fn

  :draw draw                        ;;Specify the draw fn

  :size [WIDTH HEIGHT]              ;;You struggle to beat the golden ratio

)     

---------------

That's it.


Test case:

Setup - Clojure project with Leinigen nature and Quil 1.6.0 dependency.

1. Have source file open in the editor.

2. Click "Clojure->Load File In REPL. Note that image opens in an app window.

3. Move focus to REPL by clicking in REPL pane.

4. Type (use 'quil.core) <enter>

5. Type (color 42) <enter>


NullPointerException   quil.core/color (core.clj:787)


View source of quil core.clj at line 787.
Note that the Quil color function is calling the native Processing .color function.

I understand that one probably cannot interact with a running Processing instance, but I'd hoped that one could at least use Processing defined data structures like color in the REPL. Is this a bad assumption?

Aloha,
Todd


Laurent PETIT

unread,
May 16, 2013, 6:47:26 PM5/16/13
to clojuredev-users
Hello,

I've got an unrelated error preventing me to reproduce yours:

CompilerException java.lang.RuntimeException: Unable to resolve
symbol: MAX_HUE in this context, compiling:(quilTest/core.clj:11:3)

Anyway, by looking at the metadata set on the quil.core/color var, I
spot an interesting one: :requires-bindings true

and indeed your line with a null pointer exception contains a call to
(current-applet) which is a ThreadLocal value ... so maybe it is not
set, and then calling a java method on this null value causes the
exception.

Also, I don't think those methods are supposed to be called outside
the draw function in quil.

Rather, you would just re-evaluate the draw definition again and
again. The fact that it is embedded in a loop ensures that you will
see the results of your changes instantly.

Oh, and I don't think we have a native libs (aka system libs) problem
here, because I don't think usage of native libs is the default config
in Quil, and the sketch definition does not explicitly specify a
native (opengl) renderer. See the documentation for the
quil.core/sketch (as opposed to quil.core/defsketch) var.

HTH,

--
Laurent


2013/5/17 Todd Blume <t...@tigerisland.com>:

Todd Blume

unread,
May 17, 2013, 2:45:56 AM5/17/13
to clojured...@googlegroups.com
Hi Laurent,

Sorry about the compile error. In my haste to trim some deadwood for a shorter example I missed deleting that color-mode call.

Thanks for tracking down the ThreadLocal issue. That is the heart of the problem. As you pointed out the processing calls need to be made in the context of the draw call (or at least the same thread). My apologies for my bad assumption that it was a native lib issue. I'm too new to all of this to isolate it well. I assumed that other people were using Quil in the REPL and that I just needed help with some include syntax or something to get it to work.

The bigger question was how do people use Quil in the REPL. I guess now that most don't. I found this good thread on the topic:
It includes a nice workaround to allow one to issue expressions in the REPL and have them evaluated in the draw function. Doing this makes Processing interactive in the REPL. The idea is to enqueue expressions in promises which are then evaluated in draw, and the results delivered through the promise. Here is my implementation of the idea based on code in that thread:

(def function-queue (atom []))


(defn append-function

  "Append a function to the function queue"

  [function]

  (swap! function-queue #(conj %1 function))

  )


(defn eval-functions

  "Evaluate all functions in the function-queue and empty it"

  []

  (let [pending-functions @function-queue]

    (reset! function-queue [])

    (doseq [function pending-functions]

      (function))))


(defn invoke-now 

  "Add a function to the function-queue and block until it returns"

  [function]

  (let [p (promise)]

     (append-function #(deliver p (function)))

     @p))


In the sketch file use only eval-functions:

(defn draw []

  (eval-functions)

  )


In the REPL use invoke-now to execute Processing expressions as though they are in the draw function:

(def my-pixels (invoke-now #(pixels)))

Executes the pixels function in the context of the Processing draw call and returns the results where you can continue to work with them in the REPL.

Sweet!

I'm a rookie at Clojure, so I'm sure that there is a better way to do this. Tims Gardner (from the thread above and who's code I copied) apparently has a whole framework for Quil REPL work.

Aloha,
Todd
Reply all
Reply to author
Forward
0 new messages