From mboxrd@z Thu Jan 1 00:00:00 1970 From: Steve Tell To: Guile-GTK List , Guile Mailing List Subject: Re: select+read on socket in guile,guile-gtk Date: Wed, 21 Jun 2000 21:50:00 -0000 Message-id: References: X-SW-Source: 2000-q2/msg00066.html 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