This is the mail archive of the
guile@sourceware.cygnus.com
mailing list for the Guile project.
Re: select+read on socket in guile,guile-gtk
- To: Guile-GTK List <guile-gtk at sourceware dot cygnus dot com>, Guile Mailing List <guile at sourceware dot cygnus dot com>
- Subject: Re: select+read on socket in guile,guile-gtk
- From: Steve Tell <tell at telltronics dot org>
- Date: Thu, 22 Jun 2000 00:50:12 -0400 (EDT)
While mulling over the comments from Chris C. and Gary H. (thanks!), and
poking about the source code preparing to write some guile port
extensions, I found a couple of read-made ways to accomplish what I need
for now.
On Wed, 21 Jun 2000, I wrote:
> if guile's cooperative threads play nice with guile-gtk -
> Can I create and maniuplate Gtk+ GUIs from any thread?
Turns out that with a little fiddling, this works after a fashion;
example program attached.
> On Mon, 19 Jun 2000, I wrote:
> > Does guile-gtk provide a way to hook (file descriptors from) guile ports
> > into the Gtk+ select loop? Glib's GIOChannel's perhaps?
Turns out that Gtk+ has such a facility, and guile-gtk already exposes it:
gtk-input-add
> > What I'm ultimately trying to do is arrange for a procedure to get called
> > with complete lines read from a connected TCP socket, so that information
> > recieved from the server at the other end can be used to update
> > items in a guile-gtk interface.
Two short example programs in this direction are attached, tested with a
freshly-compiled guile-1.4 and guile-gtk-0.18 (with Greg Badros' patch for
smob creation)
The first one coaxes guile cooperative threads and guile-gtk into running
together. It ends up burning a lot of CPU time; probably both gtk and
guile are doing nonblocking reads and yielding back and forth.
The second uses gtk-input-add.
Along the way, both illustrate creating a simple TCP client.
Steve
#!/tmp/ggtest/bin/guile-gtk -s
!#
;
; Test 3 using guile to write a simple network client
; that displays results in a Gtk+ window.
; This one uses guile cooperative threads.
;
(use-modules (ice-9 threads))
(use-modules (gtk gtk))
(read-set! keywords 'prefix)
(define (print-to-port port . l)
(for-each (lambda (elem) (display elem port)) l))
(define (print . l)
(apply print-to-port (cons (current-output-port) l)))
; Use any TCP server that periodicly spits back lines of text.
(define IRMP3_PORT 9232)
(define IRMP3_HOST "localhost")
(define mysock (socket AF_INET SOCK_STREAM 0))
(connect mysock AF_INET (car (hostent:addr-list
(gethostbyname IRMP3_HOST)))
IRMP3_PORT)
(define (process-lines p lab) ; loop forever reading and processing lines
(do ((line (read-line mysock) (read-line mysock)))
(#f)
(print "line=\"" line "\"\n")
(gtk-label-set-text lab line)))
(define (make-button parent txt func)
(let* ((btn (gtk-button-new-with-label txt)))
(gtk-container-add parent btn)
(gtk-widget-show btn)
(gtk-signal-connect btn "clicked" func)))
(define (make-label parent txt)
(let* ((lab (gtk-label-new txt)))
(gtk-container-add parent lab)
(gtk-widget-show lab)
lab))
(let* ((window (gtk-widget-new 'GtkWindow
:type 'toplevel
:title "hello world"
:GtkContainer::border_width 10))
(vbox (gtk-vbox-new #f 10))
(statlabel (make-label vbox "(no status yet)")))
(make-button vbox "test me" (lambda () (display "tested.") (newline)))
(make-button vbox "quit" (lambda () (gtk-widget-destroy window)))
(gtk-container-add window vbox)
(gtk-widget-show vbox)
(gtk-widget-show window)
(call-with-new-thread (lambda ()
(print "thread started\n")
(process-lines mysock statlabel)
(print "process-lines returns\n")
(close-port mysock))
(lambda (e) (print "thread error " e "\n")))
; Unless we call guile's thread-yield in the gtk idle loop,
; our thread doesn't run. And unless we call (gtk-update) inside the
; idle procedure, the gtk stuff never gets drawn properly.
; Somthing tells me this isn't the way things are supposed to work...
(gtk-idle-add (lambda ()
(yield)
(gtk-update)
))
(gtk-standalone-main window))
; end of net3g.scm
#!/tmp/ggtest/bin/guile-gtk -s
!#
;
; Test 4 using guile to write a simple network client
; that displays results in a Gtk+ window
; This one uses gtk-input-add
;
(use-modules (gtk gtk))
(use-modules (gtk gdk))
(read-set! keywords 'prefix)
; Use any TCP server that periodicly spits back lines of text.
(define IRMP3_PORT 9232)
(define IRMP3_HOST "localhost")
(define mysock (socket AF_INET SOCK_STREAM 0))
(connect mysock AF_INET (car (hostent:addr-list
(gethostbyname IRMP3_HOST)))
IRMP3_PORT)
(define (read-process-line p lab) ; process single line recieved over socket
(let ((line (read-line p)))
(gtk-label-set-text lab line)
))
(define (make-button parent txt func) ; gtk helpers
(let* ((btn (gtk-button-new-with-label txt)))
(gtk-container-add parent btn)
(gtk-widget-show btn)
(gtk-signal-connect btn "clicked" func)))
(define (make-label parent txt)
(let* ((lab (gtk-label-new txt)))
(gtk-container-add parent lab)
(gtk-widget-show lab)
lab))
(let* ((window (gtk-widget-new 'GtkWindow
:type 'toplevel
:title "hello world"
:GtkContainer::border_width 10))
(vbox (gtk-vbox-new #f 10))
(statlabel (make-label vbox "(no status yet)")))
(make-button vbox "test me" (lambda () (display "tested.") (newline)))
(make-button vbox "quit" (lambda () (gtk-widget-destroy window)))
(gtk-container-add window vbox)
(gtk-widget-show vbox)
(gtk-widget-show window)
(gtk-input-add mysock
1 ; should be 'read (for GDK_INPUT_READ)
; but that causes errors
(lambda (source condition)
(read-process-line mysock statlabel)
))
(gtk-standalone-main window))
; end of net4g.scm