changeset 7680:a0ec02774303

Use popen2 for communication with gnuplot
author David Bateman <dbateman@free.fr>
date Wed, 02 Apr 2008 13:29:19 -0400
parents 3c16e2414564
children b1c1133641ee
files scripts/ChangeLog scripts/plot/__gnuplot_ginput__.m scripts/plot/gnuplot_drawnow.m src/ChangeLog src/graphics.cc
diffstat 5 files changed, 100 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ChangeLog	Tue Apr 01 16:35:48 2008 -0400
+++ b/scripts/ChangeLog	Wed Apr 02 13:29:19 2008 -0400
@@ -1,3 +1,10 @@
+2008-04-02  David Bateman  <dbateman@free.fr>
+
+	* plot/__gnuplot_ginput__.m: Use the gnuplot stream itself for
+	communication rather than a chat file if mkfifo is not available.
+	* plot/gnuplot_drawnow.m: Open stream with popen2 to allow two way
+	communication with the gnuplot process.
+
 2008-04-01  Richard Bovey  <Richard.Bovey@baesystems.com>
 
 	* general/sortrows.m: Handle negative column arguments.
--- a/scripts/plot/__gnuplot_ginput__.m	Tue Apr 01 16:35:48 2008 -0400
+++ b/scripts/plot/__gnuplot_ginput__.m	Wed Apr 02 13:29:19 2008 -0400
@@ -31,9 +31,20 @@
 
 function [x, y, button] = __gnuplot_ginput__ (f, n)
 
-  persistent have_mkfifo = ! ispc ();
-
-  stream = get (f, "__plot_stream__");
+  ostream = get (f, "__plot_stream__");
+  if (numel (ostream) < 1)
+    error ("ginput: stream to gnuplot not open");
+  elseif (ispc ())
+    if (numel (ostream) == 1)
+      error ("ginput: Need mkfifo that is not implemented under Windows");
+    endif
+    use_mkfifo = false;
+    istream = ostream(2);
+    ostream = ostream(1);
+  else
+    use_mkfifo = true;
+    ostream = ostream(1);
+  endif
 
   if (compare_versions (__gnuplot_version__ (), "4.0", "<="))
     error ("ginput: version %s of gnuplot not supported", gnuplot_version ());
@@ -49,11 +60,11 @@
     button = zeros (n, 1);
   endif
 
-  gpin_name = tmpnam ();
+  if (use_mkfifo)
+    gpin_name = tmpnam ();
 
-  if (have_mkfifo)
-    ## Use pipes if not on Windows. Mode: 6*8*8 ==  0600
-    [err, msg] = mkfifo(gpin_name, 6*8*8);
+    ##Mode: 6*8*8 ==  0600
+    [err, msg] = mkfifo (gpin_name, 6*8*8);
 
     if (err != 0)
       error ("ginput: Can not open fifo (%s)", msg);
@@ -65,47 +76,47 @@
     k = 0;
     while (true)
       k++;
-      fprintf (stream, "set print \"%s\";\n", gpin_name);
-      fflush (stream);
-      if (have_mkfifo)
-	[gpin, err] = fopen (gpin_name, "r");
-	if (err != 0)
-	  error ("ginput: Can not open fifo (%s)", msg);
-	endif
-      endif
-      fputs (stream, "pause mouse any;\n\n");
 
       ## Notes: MOUSE_* can be undefined if user closes gnuplot by "q"
       ## or Alt-F4. Further, this abrupt close also requires the leading
       ## "\n" on the next line.
-      fputs (stream, "\nif (exists(\"MOUSE_KEY\") && exists(\"MOUSE_X\")) print MOUSE_X, MOUSE_Y, MOUSE_KEY; else print \"0 0 -1\"\n");
-
-      ## Close output file, otherwise all blocks (why?!).
-      fputs (stream, "set print;\n");
-      fflush (stream);
-
-      if (! have_mkfifo)
-	while (exist (gpin_name, "file") == 0)
-	endwhile
-	[gpin, msg] = fopen (gpin_name, "r");
+      if (use_mkfifo)
+	fprintf (ostream, "set print \"%s\";\n", gpin_name);
+	fflush (ostream);
+	[gpin, err] = fopen (gpin_name, "r");
+	if (err != 0)
+	  error ("ginput: Can not open fifo (%s)", msg);
+	endif
+	fputs (ostream, "pause mouse any;\n\n");
+	fputs (ostream, "\nif (exists(\"MOUSE_KEY\") && exists(\"MOUSE_X\")) print MOUSE_X, MOUSE_Y, MOUSE_KEY; else print \"0 0 -1\"\n");
 
-	if (gpin < 0)
-	  error ("ginput: Can not open file (%s)", msg);
-	endif
+	## Close output file, to force it to be flushed
+	fputs (ostream, "set print;\n");
+	fflush (ostream);
 
-	## Now read from file
-	count = 0;
-	while (count == 0)
-	  [xk, yk, buttonk, count] = fscanf (gpin, "%f %f %d", "C");
-	endwhile
-	x(k) = xk;
-	y(k) = yk;
-	button (k) = buttonk;
-      else
 	## Now read from fifo.
 	[x(k), y(k), button(k), count] = fscanf (gpin, "%f %f %d", "C");
+	fclose (gpin);
+      else
+	fprintf (ostream, "set print \"-\";\n");
+	fflush (ostream);
+	fputs (ostream, "pause mouse any;\n\n");
+	fputs (ostream, "\nif (exists(\"MOUSE_KEY\") && exists(\"MOUSE_X\")) print \"OCTAVE: \", MOUSE_X, MOUSE_Y, MOUSE_KEY; else print \"0 0 -1\"\n");
+
+	## Close output file, to force it to be flushed
+	fputs (ostream, "set print;\n");
+	fflush (ostream);
+
+	str = {};
+	while (isempty (str))
+	  str = char (fread (istream)');
+	  if (! isempty (str))
+	    str = regexp (str, 'OCTAVE:\s+[\d.\+-]+\s+[\d.\+-]+\s+\d*', 'match');
+	  endif
+	  fclear (istream);
+	endwhile
+        [x(k), y(k), button(k), count] = sscanf (str{end}(8:end), "%f %f %d", "C");
       endif
-      fclose (gpin);
 
       if ([x(k), y(k), button(k)] == [0, 0, -1])
 	## Mousing not active (no plot yet).
@@ -132,7 +143,9 @@
     endwhile
 
   unwind_protect_cleanup
-    unlink (gpin_name);
+    if (use_mkfifo)
+      unlink (gpin_name);
+    endif
   end_unwind_protect
 
 endfunction
--- a/scripts/plot/gnuplot_drawnow.m	Tue Apr 01 16:35:48 2008 -0400
+++ b/scripts/plot/gnuplot_drawnow.m	Wed Apr 02 13:29:19 2008 -0400
@@ -38,7 +38,7 @@
     plot_stream = [];
     fid = [];
     unwind_protect
-      [plot_stream, enhanced] = open_gnuplot_stream ([], term, file);
+      [plot_stream, enhanced] = open_gnuplot_stream (1, [], term, file);
       __go_draw_figure__ (f, plot_stream, enhanced, mono);
       if (nargin == 5)
         fid = fopen (debug_file, "wb");
@@ -57,35 +57,40 @@
     f = __get__ (h);
     plot_stream = f.__plot_stream__;
     if (isempty (plot_stream))
-      [plot_stream, enhanced] = open_gnuplot_stream (h);
+      [plot_stream, enhanced] = open_gnuplot_stream (2, h);
       set (h, "__enhanced__", enhanced);
     else
       enhanced = f.__enhanced__;
     endif
-    __go_draw_figure__ (f, plot_stream, enhanced, mono);
+    __go_draw_figure__ (f, plot_stream (1), enhanced, mono);
+    fflush (plot_stream (1));
   else
     print_usage ();
   endif
 
 endfunction
 
-function [plot_stream, enhanced] = open_gnuplot_stream (h, varargin)
+function [plot_stream, enhanced] = open_gnuplot_stream (npipes, h, varargin)
 
   cmd = gnuplot_binary ();
 
-  plot_stream = popen (cmd, "w");
-
-  if (plot_stream < 0)
-    error ("drawnow: failed to open connection to gnuplot");
+  if (npipes > 1)
+    [plot_stream(1), plot_stream(2), pid] = popen2 (cmd);
+    if (pid < 0)
+      error ("drawnow: failed to open connection to gnuplot");
+    endif
   else
+    plot_stream = popen (cmd, "w");
+    if (plot_stream < 0)
+      error ("drawnow: failed to open connection to gnuplot");
+    endif
+  endif
 
-    if (! isempty (h))
-      set (h, "__plot_stream__", plot_stream);
-    endif
+  if (! isempty (h))
+    set (h, "__plot_stream__", plot_stream);
+  endif
 
-    enhanced = init_plot_stream (plot_stream, h, varargin{:});
-
-  endif
+  enhanced = init_plot_stream (plot_stream (1), h, varargin{:});
 
 endfunction
 
--- a/src/ChangeLog	Tue Apr 01 16:35:48 2008 -0400
+++ b/src/ChangeLog	Wed Apr 02 13:29:19 2008 -0400
@@ -4,6 +4,11 @@
 	(do_lookup (tree_argument_list *, const string_vector&,
 	octave_value_list&, bool&)): Call MAYBE_DO_BREAKPOINT here.
 
+2008-04-02  David Bateman  <dbateman@free.fr>
+
+	* graphics.cc (void gnuplot_backend::close_figure (const
+	octave_value&) const): Allow for an input and output stream.
+
 2008-03-28  Jaroslav Hajek  <highegg@gmail.com>
 
 	* DLD-FUNCTIONS/lookup.cc: New file.
--- a/src/graphics.cc	Tue Apr 01 16:35:48 2008 -0400
+++ b/src/graphics.cc	Wed Apr 02 13:29:19 2008 -0400
@@ -1291,12 +1291,22 @@
       if (! pstream.is_empty())
 	{
 	  octave_value_list args;
-	  args(1) = "\nquit;\n";
-	  args(0) = pstream;
-	  feval ("fputs", args);
-	  args.resize (1);
-	  feval ("fflush", args);
-	  feval ("pclose", args);
+	  Matrix fids = pstream.matrix_value ();
+
+	  if (! error_state)
+	    {
+	      args(1) = "\nquit;\n";
+	      args(0) = octave_value (fids (0));
+	      feval ("fputs", args);
+	      args.resize (1);
+	      feval ("fflush", args);
+	      feval ("pclose", args);
+	      if (fids.numel () > 1)
+		{
+		  args(0) = octave_value (fids (1));
+		  feval ("pclose", args);
+		}
+	    }
 	}
     }