UPDATE! Ladies and Gentlemen we HAVE static!!!
I tried a new plan of attack...copy and paste the pixbuf.c, modify it to be self-sufficient and input the stuff I need into it. (Kind of cheating I know, but I have my group waiting on this). It turns out the main error was I shouldn't have had the NUM_ITERATIONS loop, it was causing a blank screen, for some reason. Now I'm going to try to put a semaphore thread where the timeout will just read from a buffer that put_pixels creates...should be interesting.
I have been looking at this problem for almost 2 weeks. I am an experienced C programmer but a beginner GTK programmer. I feel I am near a solution, but the documentation for animations in GTK is sparse, fragmentary, and seemingly contradictory it remains out of reach.
The intent is to create a graphical representation of a MPI based cellular automata. My partners (programming the message passing code) are sending me characters to render in a pixbuf, which then gets displayed.
So far so good, I can get a single pixbuf image, but trying to make it continually refresh with new data (just trying to animate random noise at this point) has proven vexatious.
I need help, I need to make a flickering little screen. Once that happens, I should be able to easily take in the data I need.
Here is the code:
First, the main display class, this is where the problems reside.
It was based on the answer of this thread
http://www.gtkforums.com/viewtopic.php?f=3&t=55828&p=72828&hilit=cairo+drawing+area#p72828 I gave up on GTK builder because I have no idea how it works and it was creating errors. But still I'm having a very difficult time making use of the drawing area, since it always initializes to a widget.
Code:
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <cairo.h>
#include <glib.h>
#include <stdlib.h>
#include "pixbuf.c"
GtkWidget *canvas;
GdkPixbuf *panel;
guchar *row;
#define NUM_ITERATIONS 100
#define FRAME_DELAY 50
/*
* the "draw" signal.
*
*/
gboolean
cb_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
{
cr = gdk_cairo_create(widget->window);
gdk_cairo_set_source_pixbuf(cr, panel, 0, 0);
return TRUE;
}
/*
* Timeout call back.
* tell GTK to re-draw the drawing area
*/
gboolean
cb_timeout(gpointer user_data)
{
GdkWindow *win;
int i, j, n;
if (row == NULL);
row = malloc(X_RES * sizeof(guchar));
for (n = 0; n < NUM_ITERATIONS; n++) {
for (i = 0; i < Y_RES; i++) {
for (j = 0; j < X_RES; j++) {
row[j] = rand() % 256;
}
put_pixels(panel, i, row);
}
}
win = gtk_widget_get_window(canvas);
if (win) {
GtkAllocation allocation;
gtk_widget_get_allocation(GTK_WIDGET(canvas), &allocation);
gdk_window_invalidate_rect(win, &allocation, FALSE);
}
return TRUE;
}
/* Create our window and connect the signals */
static GtkWidget*
create_window(void)
{
GtkWidget *window;
canvas = gtk_drawing_area_new();
g_signal_connect(canvas, "draw", G_CALLBACK(cb_draw), NULL);
g_timeout_add(FRAME_DELAY, cb_timeout, &canvas);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_window_set_default_size(GTK_WINDOW (window), X_RES, Y_RES);
gtk_container_add(GTK_CONTAINER (window), canvas);
return window;
}
int
main(int argc, char *argv[])
{
GtkWidget *window;
gtk_init(&argc, &argv);
panel = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
FALSE,
BITS_PER_SAMPLE,
X_RES, Y_RES);
window = create_window();
gtk_widget_show_all(GTK_WIDGET(window));
gtk_main();
return 0;
}
This is the pixel buffer code, there should be no problems since it is much more straight forward.
Code:
#include <gdk-pixbuf/gdk-pixbuf.h>
#define X_RES 200
#define Y_RES 200
#define BITS_PER_SAMPLE 8
static void put_pixels (GdkPixbuf *pixbuf, int y, guchar* blue)
{
int x, rowstride, n_channels;
guchar *pixels, *p;
n_channels = gdk_pixbuf_get_n_channels (pixbuf);
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
pixels = gdk_pixbuf_get_pixels (pixbuf);
g_assert (gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
g_assert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
g_assert (n_channels == 3);
for (x = 0; x < X_RES; x++) {
g_assert (x >= 0 && x < X_RES);
g_assert (y >= 0 && y < Y_RES);
p = pixels + y * rowstride + x * n_channels;
p[0] = 0;
p[1] = 0;
p[2] = blue[x];
}
}
Also, on a final note. I feel the GTK loop will be tricky for a blocking MPI read message so I am planning to have the gtk loop running in a pthread and the MPI interface reading from the other. The MPI thread will read data into a global array of pixbufs and have global counter at where it is at. Since the gtk pthread will only read from the global buffer and only be reading from a semaphore (which is written from the mpi pthread). I don't think there should be any thread safe issues. Do any of you forsee any problems there?
Thanks
Jason