[Gtk-sharp-list] Best way to continuously update a Gtk.Image (V4L)

Sebastian scut@nb.in-berlin.de
Sun, 18 Apr 2004 15:35:00 +0800


Hi *,


I hope to have solved all of my problems. Below is a summary for the
archives, as other people might face similar problems :)


On Sat, Apr 17, 2004 at 12:47:37PM +0800, Sebastian wrote:

>  1. Is just overwriting the Pixbuf byte array and queuing a redraw the
>     proper way or may this pointer change somehow?

Seems to work.


>  2. How to call this from the Gtk# main loop? There is no main loop at the
>     moment, and if I try to close the window, I get this message:
> 
> 	(<unknown>:1970): Gtk-CRITICAL **: file gtkmain.c: line 1151
> 		(gtk_main_quit): assertion `main_loops != NULL' failed
> 
>     I do not want the user to have to click a start-button or the like.

I now use one main GTK loop plus Gdk.Threads.Enter/Leave calls.
See http://bobi.ifs.hr/ifs/razno/doc/gtk/gtkfaq-5.html#ss5.2 and
http://www.ijon.de/comp/tutorials/threads/gdkgtk.html (german).


...
using System.Threading;
...

public class V4lGtk
{
	private static Thread capture = null;

	public static void Main (string[] args)
	{
		Gdk.Threads.Init ();
		Application.Init ();

		V4lGtk vg = new V4lGtk ();
		vg.Test ();
	}

	public void Test ()
	{
		Window win = new Window ("V4L GTK# test");
		win.DeleteEvent += new DeleteEventHandler (Window_Delete);

		Video4Linux vl = new Video4Linux ();
		vl.Open ();
		vl.SetCaptureSize (320, 240);
		vl.PrepareCapture ();

		Gdk.Pixbuf pb = new Gdk.Pixbuf (Gdk.Colorspace.Rgb, false,
			8, vl.FrameWidth, vl.FrameHeight);

		Image img = new Image (pb);
		win.Add (img);
		win.ShowAll ();

		CaptureThread cth = new CaptureThread (vl, pb, img);
		ThreadStart captureSt = new ThreadStart (cth.Start);
		capture = new Thread (captureSt);
		capture.Start ();

		Console.WriteLine ("main GTK thread");

		// The main loop, wrapped within .Enter and .Leave
		Gdk.Threads.Enter ();
		Application.Run ();
		Gdk.Threads.Leave ();
	}

	static void Window_Delete (object obj, DeleteEventArgs args)
	{
		capture.Abort ();
		Application.Quit ();
		args.RetVal = true;
	}
}

class CaptureThread
{
	private CaptureThread ()
	{
	}

	Video4Linux vl;
	Gdk.Pixbuf pb;
	Image img;

	public CaptureThread (Video4Linux vl, Gdk.Pixbuf pb, Image img)
	{
		this.vl = vl;
		this.pb = pb;
		this.img = img;
	}

	public void Start ()
	{
		GdkPixbufConverter conv = new GdkPixbufConverter (vl, pb);
		vl.StartCapture ();

		while (true) {
			vl.GetFrame ();
			conv.ConvertCurrentFrame ();

			// Wrapped inside Enter/Leave to not confuse GTK
			Gdk.Threads.Enter ();
			img.QueueDraw ();
			Gdk.Threads.Leave ();

			vl.FreeFrame ();
		}
	}
}

...


Is this the right way (I think so), or did I miss something?


ciao,
Sebastian

-- 
   |\      _,,,--,,_  ,)  scut@nb.in-berlin.de, http://segfault.net/~scut/pgp
   /,`.-'`'   -,  ;-;;'   5453 AC95 1E02 FDA7 50D2 A42D 427E 6DEF 745A 8E07
_ |,4-  ) )-,_ ) /\__________________________________________________________
~'---''(_/--' (_/-'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~