Yes — that's perfect, thank you! And it also gives me a better sense of how 
racket/gui is implemented for macOS. This snippet of code is now included in my 
library, and I wonder if there's benefit to having this be available in 
racket/gui for cross-platform usage?

Now that I understand this a bit, I tried solving the second use-case I wrote 
about, using the glimagesink. My understanding of this code is that it creates 
a subview with a CAOpenGLLayer, and then enqueues a `setNeedsDisplay`:

When I run equivalent code outside of racket (e.g. through the gst-launch 
tool), I see that I continuously see calls to draw 
 Those calls are not being made when run from Racket.

I realize we're venturing outside of the Realm of Racket (intentional pun)  and 
closer to Cocoa, but I'd like to have a better sense of how to dequeue these 
drawing actions. Based on your previous code, I thought that I could yield to 
the main thread by calling `run` or `runUntilDate` on the main NSRunLoop, but 
that didn't seem to accomplish this goal.

Any ideas of how to "yield" to whatever queue or thread GStreamer has running?

Thank you so much for your help!

On Wed, Jan 10, 2018, at 3:37 PM, Matthew Flatt wrote:
> At Wed, 10 Jan 2018 11:17:14 -0800 (PST), Mark Wunsch wrote:
> > The main question I have is: How does racket/gui set up and interact with 
> > the NSApplication's main thread?
> > [...]
> > My sense of this crash is that there's something inside the racket/gui 
> > internals [....]
> > that works around a "typical" NSApplication start-up sequence that makes 
> > the osxvideosink code believe that it's running outside of the main NSApp 
> > thread. "Typical" is in quotes because I honestly have no idea what I'm 
> > talking about.
> It's true that `racket/gui` avoids the usual run loop, so I expect that
> "osxvideosink.m" will think that it needs its own. Specifically,
> `[[NSRunLoop mainRunLoop] currentMode]` will return nil. And if
> `gst_osx_videosink_check_main_run_loop` runs in the main OS thread via
> a foreign call, then no events will be dispatched while it waits to
> check in teh backup way, because the Racket-level thread that pulses
> the main run loop will be blocked until the foreign call returns.
> Finally, if "osxvideosink.m" sets up its own run loop and hacks
> `isThread`, that would interact badly with `racket/gui` and could
> explain the crash.
> Does it help to wrap the `broadcast` call with
>  (call-atomically-in-run-loop
>   (lambda ()
>     ....))
> using the implementation of `call-atomically-in-run-loop` below?
> ----------------------------------------
> #lang racket/base
> (require racket/gui/base
>          ffi/unsafe
>          ffi/unsafe/objc
>          ffi/unsafe/nsalloc)
> (provide call-atomically-in-run-loop)
> (import-class NSObject NSArray NSRunLoop)
> (define NSDefaultRunLoopMode (get-ffi-obj 'NSDefaultRunLoopMode #f _id))
> (define-objc-class CallerContainer NSObject
>   [proc]
>   (-a _void (call) (proc)))
> (define (call-atomically-in-run-loop proc)
>   (define result #f)
>   (define s (make-semaphore))
>   (call-with-autorelease
>    (lambda ()
>      (define obj (tell CallerContainer alloc))
>      (set-ivar! obj proc (lambda () (set! result (proc)) (semaphore-post s)))
>      (tellv (tell NSRunLoop mainRunLoop)
>             performSelector: #:type _SEL (selector call)
>             target: obj
>             argument: #f
>             order: #:type _uint 0
>             modes: (tell (tell NSArray alloc)
>                          initWithObject: NSDefaultRunLoopMode))))
>   (yield s)
>   result)
> ;; Example, gets a non-#f result:
> #;
> (call-atomically-in-run-loop
>   (lambda ()
>     (tell (tell NSRunLoop mainRunLoop) currentMode)))

You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
For more options, visit

Reply via email to