+2005-04-22 mallum,,, <mallum@openedhand.com>
+
+ * clutter/Makefile.am:
+ * clutter/cltr-button.c:
+ * clutter/cltr-button.h:
+ * clutter/cltr-core.c: (cltr_init):
+ * clutter/cltr-overlay.c:
+ * clutter/cltr-overlay.h:
+ * clutter/cltr-photo-grid.c: (cltr_photo_grid_handle_xevent),
+ (cltr_photo_grid_cell_new), (ctrl_photo_grid_get_zoomed_coords),
+ (cell_is_offscreen), (cltr_photo_grid_idle_cb),
+ (cltr_photo_grid_navigate), (cltr_photo_grid_activate_cell),
+ (cltr_photo_grid_populate), (cltr_photo_grid_update_visual_state),
+ (cltr_photo_grid_paint), (cltr_photo_grid_show),
+ (cltr_photo_grid_set_fps), (cltr_photo_grid_get_fps),
+ (cltr_photo_grid_set_anim_steps), (cltr_photo_grid_get_anim_steps),
+ (cltr_photo_grid_new):
+ Fix up grid so external prog can load images.
+ * clutter/cltr-photo-grid.h:
+ * clutter/cltr-texture.c: (cltr_texture_realize),
+ (cltr_texture_new):
+ * clutter/cltr-texture.h:
+ * clutter/cltr-window.c: (cltr_window_set_fullscreen):
+ * clutter/cltr.h:
+ * clutter/pixbuf.c: (pixbuf_scale_down), (ConvolveImage),
+ (GaussianBlurImage):
+ * clutter/pixbuf.h:
+ New experimental Methods
+ * configure.ac:
+ * examples/Makefile.am:
+ * examples/photos.c:
+ * examples/player.c:
+ Add new examples
+ * gst/Makefile.am:
+ * gst/cltrimagesink.c:
+ * gst/cltrimagesink.h:
+ Add initial crusty ( broken ) gst stuff
+
2005-04-13 mallum,,, <mallum@openedhand.com>
* bootstrap-autotools.sh:
-SUBDIRS=clutter examples
\ No newline at end of file
+SUBDIRS=clutter gst examples
\ No newline at end of file
cltr-window.h \
cltr-photo-grid.h \
cltr-list.h \
+ cltr-overlay.h \
+ cltr-button.h \
cltr-scratch.h
source_c = pixbuf.c util.c fonts.c \
cltr-window.c \
cltr-photo-grid.c \
cltr-list.c \
+ cltr-overlay.c \
+ cltr-button.c \
cltr-scratch.c
AM_CFLAGS = @GCC_FLAGS@ @CLTR_CFLAGS@
--- /dev/null
+#include "cltr-button.h"
+#include "cltr-private.h"
+
+struct CltrButton
+{
+ CltrWidget widget;
+};
+
+static void
+cltr_button_show(CltrWidget *widget);
+
+static gboolean
+cltr_button_handle_xevent (CltrWidget *widget, XEvent *xev);
+
+static void
+cltr_button_paint(CltrWidget *widget);
+
+
+CltrWidget*
+cltr_button_new(int width, int height)
+{
+ CltrButton *button;
+
+ button = g_malloc0(sizeof(CltrButton));
+
+ button->widget.width = width;
+ button->widget.height = height;
+
+ button->widget.show = cltr_button_show;
+ button->widget.paint = cltr_button_paint;
+
+ button->widget.xevent_handler = cltr_button_handle_xevent;
+
+ return CLTR_WIDGET(button);
+}
+
+static void
+cltr_button_show(CltrWidget *widget)
+{
+
+}
+
+static gboolean
+cltr_button_handle_xevent (CltrWidget *widget, XEvent *xev)
+{
+
+}
+
+static void
+cltr_button_paint(CltrWidget *widget)
+{
+
+
+}
--- /dev/null
+#ifndef _HAVE_CLTR_BUTTON_H
+#define _HAVE_CLTR_BUTTON_H
+
+#include "cltr.h"
+
+typedef struct CltrButton CltrButton;
+
+#define CLTR_BUTTON(w) ((CltrButton*)(w))
+
+CltrWidget*
+cltr_button_new(int width, int height);
+
+
+#endif
int
cltr_init(int *argc, char ***argv)
{
+
+#define GLX_SAMPLE_BUFFERS_ARB 100000
+#define GLX_SAMPLES_ARB 100001
+
+
int gl_attributes[] =
{
GLX_RGBA,
GLX_DOUBLEBUFFER,
+ GLX_STENCIL_SIZE, 1,
+ GLX_DEPTH_SIZE, 24,
+
+ /*
+ GLX_SAMPLE_BUFFERS_ARB, 1,
+ GLX_SAMPLES_ARB, 0,
+
+ */
+ /*
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
+
+
+
+ */
0
};
XVisualInfo *vinfo;
-
- g_thread_init (NULL);
+ if (!g_thread_supported ())
+ g_thread_init (NULL);
// XInitThreads ();
if ((CltrCntx.xdpy = XOpenDisplay(getenv("DISPLAY"))) == NULL)
CltrCntx.xscreen = DefaultScreen(CltrCntx.xdpy);
CltrCntx.xwin_root = RootWindow(CltrCntx.xdpy, CltrCntx.xscreen);
+ CLTR_DBG("EXT : %s", glXQueryExtensionsString( CltrCntx.xdpy,
+ CltrCntx.xscreen));
+
+
if ((vinfo = glXChooseVisual(CltrCntx.xdpy,
CltrCntx.xscreen,
gl_attributes)) == NULL)
--- /dev/null
+#include "cltr-overlay.h"
+#include "cltr-private.h"
+
+struct CltrOverlay
+{
+ CltrWidget widget;
+};
+
+static void
+cltr_overlay_show(CltrWidget *widget);
+
+static gboolean
+cltr_overlay_handle_xevent (CltrWidget *widget, XEvent *xev);
+
+static void
+cltr_overlay_paint(CltrWidget *widget);
+
+
+CltrWidget*
+cltr_overlay_new(int width, int height)
+{
+ CltrOverlay *overlay;
+
+ overlay = g_malloc0(sizeof(CltrOverlay));
+
+ overlay->widget.width = width;
+ overlay->widget.height = height;
+
+ overlay->widget.show = cltr_overlay_show;
+ overlay->widget.paint = cltr_overlay_paint;
+
+ overlay->widget.xevent_handler = cltr_overlay_handle_xevent;
+
+ return CLTR_WIDGET(overlay);
+}
+
+static void
+cltr_overlay_show(CltrWidget *widget)
+{
+
+}
+
+static gboolean
+cltr_overlay_handle_xevent (CltrWidget *widget, XEvent *xev)
+{
+
+}
+
+static void
+cltr_overlay_paint(CltrWidget *widget)
+{
+
+
+}
--- /dev/null
+#ifndef _HAVE_CLTR_OVERLAY_H
+#define _HAVE_CLTR_OVERLAY_H
+
+#include "cltr.h"
+
+typedef struct CltrOverlay CltrOverlay;
+
+#define CLTR_OVERLAY(w) ((CltrOverlay*)(w))
+
+CltrWidget*
+cltr_overlay_new(int width, int height);
+
+
+#endif
*/
-#define ANIM_FPS 60
#define FPS_TO_TIMEOUT(t) (1000/(t))
struct CltrPhotoGridCell
GList *cells_tail;
GList *cell_active;
+ gboolean is_populated;
+
/* animation / zoom etc stuff */
/* current anim frame position */
- int anim_n_steps, anim_step;
+ int anim_fps, anim_n_steps, anim_step;
/* start / end points for animations */
float zoom_min, zoom_max, zoom_step;
/* Values calucated from above for setting up the GL tranforms and 'view' */
float paint_trans_x, paint_trans_y, paint_zoom;
int paint_start_y;
- GList *paint_cell_item;
+ GList *paint_cell_item;
+ GMutex *mutex;
CltrPhotoGridState state;
};
cltr_photo_grid_update_visual_state(CltrPhotoGrid *grid);
-/* this likely shouldn'y go here */
-static GMutex *Mutex_GRID = NULL;
+GMutex*
+cltr_photo_grid_mutex(CltrPhotoGrid *grid)
+{
+ return grid->mutex;
+}
+void
+cltr_photo_grid_set_populated(CltrPhotoGrid *grid, gboolean populated)
+{
+ grid->is_populated = populated;
+}
static void
cltr_photo_grid_handle_xkeyevent(CltrPhotoGrid *grid, XKeyEvent *xkeyev)
CltrPhotoGridCell*
cltr_photo_grid_cell_new(CltrPhotoGrid *grid,
- Pixbuf *pixb,
- const gchar *filename)
+ Pixbuf *pixb)
{
CltrPhotoGridCell *cell = NULL;
int maxw = grid->widget.width, maxh = grid->widget.height;
int neww = 0, newh = 0;
+ Pixbuf *tmp_pixb = NULL;
cell = g_malloc0(sizeof(CltrPhotoGridCell));
}
else cell->pixb = pixb;
- CLTR_DBG ("loaded %s at %ix%i", filename, neww, newh);
+ cell->texture = cltr_texture_new(cell->pixb);
cell->angle = 6.0 - (rand()%12);
return cell;
}
+Pixbuf*
+cltr_photo_grid_cell_pixbuf(CltrPhotoGridCell *cell)
+{
+ return cell->pixb;
+}
+
+CltrPhotoGridCell*
+cltr_photo_grid_get_active_cell(CltrPhotoGrid *grid)
+{
+ if (grid->cell_active)
+ return grid->cell_active->data;
+ else
+ return NULL;
+}
+
+void
+cltr_photo_grid_set_active_cell(CltrPhotoGrid *grid, CltrPhotoGridCell *cell)
+{
+ GList *cell_item = NULL;
+
+ cell_item = g_list_find(g_list_first(grid->cells_tail), (gconstpointer)cell);
+
+ if (cell_item)
+ grid->cell_active = cell_item;
+}
+
+CltrPhotoGridCell*
+cltr_photo_grid_get_first_cell(CltrPhotoGrid *grid)
+{
+ GList *cell_item = NULL;
+
+ cell_item = g_list_first(grid->cells_tail);
+
+ if (cell_item)
+ return cell_item->data;
+ return NULL;
+}
+
void
cltr_photo_grid_append_cell(CltrPhotoGrid *grid,
CltrPhotoGridCell *cell)
cltr_widget_queue_paint(CLTR_WIDGET(grid));
+ if (!grid->is_populated)
+ return TRUE;
+
switch(grid->state)
{
- case CLTR_PHOTO_GRID_STATE_LOADING:
- case CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE:
case CLTR_PHOTO_GRID_STATE_ZOOM_IN:
case CLTR_PHOTO_GRID_STATE_ZOOM_OUT:
case CLTR_PHOTO_GRID_STATE_ZOOMED_MOVE:
}
if (grid->state != CLTR_PHOTO_GRID_STATE_ZOOMED)
- g_timeout_add(FPS_TO_TIMEOUT(ANIM_FPS),
+ g_timeout_add(FPS_TO_TIMEOUT(grid->anim_fps),
cltr_photo_grid_idle_cb, grid);
}
grid->anim_step = 0;
zoom = grid->zoom_max;
- g_timeout_add(FPS_TO_TIMEOUT(ANIM_FPS),
+ g_timeout_add(FPS_TO_TIMEOUT(grid->anim_fps),
cltr_photo_grid_idle_cb, grid);
}
grid->state = CLTR_PHOTO_GRID_STATE_ZOOM_IN;
- g_timeout_add(FPS_TO_TIMEOUT(ANIM_FPS),
+ g_timeout_add(FPS_TO_TIMEOUT(grid->anim_fps),
cltr_photo_grid_idle_cb, grid);
}
else if (grid->state == CLTR_PHOTO_GRID_STATE_ZOOMED)
grid->view_min_x = 0.0;
grid->view_min_y = 0.0; /*- (grid->row_offset * grid->cell_height);*/
- g_timeout_add(FPS_TO_TIMEOUT(ANIM_FPS),
+ g_timeout_add(FPS_TO_TIMEOUT(grid->anim_fps),
cltr_photo_grid_idle_cb, grid);
}
}
+#if 0
gpointer
cltr_photo_grid_populate(gpointer data)
{
if (pixb)
{
CltrPhotoGridCell *cell;
- gchar buf[24];
+ gchar buf[24];
+ Pixbuf *tmp_pixb;
- cell = cltr_photo_grid_cell_new(grid, pixb, entry);
+ cell = cltr_photo_grid_cell_new(grid, pixb);
g_snprintf(&buf[0], 24, "%i", i);
font_draw(font, cell->pixb, buf, 10, 10, &font_col);
cell->texture = cltr_texture_new(cell->pixb);
- g_mutex_unlock(Mutex_GRID);
+ if (!grid->cell_active)
+ grid->cell_active = g_list_first(grid->cells_tail);
cltr_photo_grid_append_cell(grid, cell);
+ g_mutex_unlock(Mutex_GRID);
+
i++;
}
g_mutex_lock(Mutex_GRID);
- grid->cell_active = g_list_first(grid->cells_tail);
-
- grid->state = CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE;
+ grid->is_populated = TRUE;
g_mutex_unlock(Mutex_GRID);
return NULL;
}
+#endif
static void
cltr_photo_grid_update_visual_state(CltrPhotoGrid *grid)
grid->paint_cell_item = g_list_nth(grid->cells_tail,
grid->n_cols * grid->row_offset);
- if (grid->state != CLTR_PHOTO_GRID_STATE_BROWSE
- && grid->state != CLTR_PHOTO_GRID_STATE_LOADING
- && grid->state != CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE)
+ if (grid->state != CLTR_PHOTO_GRID_STATE_BROWSE)
{
float scroll_min_y_offset = (float)(row_offset_h);
glEnable(GL_TEXTURE_2D);
- g_mutex_lock(Mutex_GRID);
+ g_mutex_lock(grid->mutex);
cltr_texture_render_to_gl_quad(cell->texture,
-(thumb_w/2),
(thumb_w/2),
(thumb_h/2));
- g_mutex_unlock(Mutex_GRID);
+ g_mutex_unlock(grid->mutex);
glDisable(GL_TEXTURE_2D);
cltr_glu_rounded_rect(-(thumb_w/2)-4, -(thumb_h/2)-4,
(thumb_w/2)+4, (thumb_h/2)+ns_border,
- thumb_w/40,
+ thumb_w/30,
NULL);
- glColor4f(0.1, 0.1, 0.1, 0.5);
+ /* shadow */
+
+ glColor4f(0.1, 0.1, 0.1, 0.3);
- cltr_glu_rounded_rect(-(thumb_w/2)-4, -(thumb_h/2)-4+1,
- (thumb_w/2)+4, (thumb_h/2)+ns_border+1,
- thumb_w/40,
+ cltr_glu_rounded_rect(-(thumb_w/2)-4 + 1, -(thumb_h/2)-4 + 1,
+ (thumb_w/2)+4 + 1, (thumb_h/2)+ns_border +1,
+ thumb_w/30,
NULL);
+
glColor4f(1.0, 1.0, 1.0, 1.0);
glEnable(GL_TEXTURE_2D);
glColor3f(0.6, 0.6, 0.62);
glRecti(0, 0, widget->width, widget->height);
- g_mutex_lock(Mutex_GRID);
-
- /* Hack, so final item get painted via threaded load */
- if (grid->state == CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE)
- grid->state = CLTR_PHOTO_GRID_STATE_BROWSE;
-
- g_mutex_unlock(Mutex_GRID);
-
/* reset */
glDisable(GL_POLYGON_SMOOTH);
cltr_photo_grid_show(CltrWidget *widget)
{
CltrPhotoGrid *grid = CLTR_PHOTO_GRID(widget);
- GThread *loader_thread;
- grid->state = CLTR_PHOTO_GRID_STATE_LOADING;
+ /*
+ GThread *loader_thread;
loader_thread = g_thread_create (cltr_photo_grid_populate,
(gpointer)grid,
TRUE,
NULL);
+ */
- g_timeout_add(FPS_TO_TIMEOUT(20),
- cltr_photo_grid_idle_cb, grid);
+ grid->state = CLTR_PHOTO_GRID_STATE_BROWSE;
+
+ if (!grid->is_populated)
+ g_timeout_add(FPS_TO_TIMEOUT(20),
+ cltr_photo_grid_idle_cb, grid);
cltr_widget_queue_paint(widget);
}
+void
+cltr_photo_grid_set_fps(CltrPhotoGrid *grid, int fps)
+{
+ grid->anim_fps = fps;
+}
+
+int
+cltr_photo_grid_get_fps(CltrPhotoGrid *grid)
+{
+ return grid->anim_fps;
+}
+
+void
+cltr_photo_grid_set_anim_steps(CltrPhotoGrid *grid, int steps)
+{
+ grid->anim_n_steps = steps;
+}
+
+int
+cltr_photo_grid_get_anim_steps(CltrPhotoGrid *grid)
+{
+ return grid->anim_n_steps;
+}
+
+
+
CltrWidget*
cltr_photo_grid_new(int width,
int height,
grid->cell_width = grid->widget.width / n_cols;
grid->cell_height = grid->widget.height / n_rows;
- grid->state = CLTR_PHOTO_GRID_STATE_LOADING;
+ grid->state = CLTR_PHOTO_GRID_STATE_BROWSE;
+ grid->is_populated = FALSE;
+
+ grid->anim_fps = 50;
- grid->anim_n_steps = 20; /* value needs to be calced dep on rows */
+ grid->anim_n_steps = 10; /* value needs to be calced dep on rows */
grid->anim_step = 0;
/* Default 'browse view' */
grid->row_offset = 0;
- Mutex_GRID = g_mutex_new();
+ grid->mutex = g_mutex_new();
return CLTR_WIDGET(grid);
}
typedef enum CltrPhotoGridState
{
- CLTR_PHOTO_GRID_STATE_LOADING ,
- CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE ,
CLTR_PHOTO_GRID_STATE_BROWSE ,
CLTR_PHOTO_GRID_STATE_ZOOM_IN ,
CLTR_PHOTO_GRID_STATE_ZOOMED ,
}
CltrPhotoGridCellState;
+GMutex*
+cltr_photo_grid_mutex(CltrPhotoGrid *grid);
+
+void
+cltr_photo_grid_set_populated(CltrPhotoGrid *grid, gboolean populated);
CltrPhotoGridCell*
cltr_photo_grid_cell_new(CltrPhotoGrid *grid,
- Pixbuf *pixb,
- const gchar *filename);
+ Pixbuf *pixb);
+
+Pixbuf*
+cltr_photo_grid_cell_pixbuf(CltrPhotoGridCell *cell);
+
+CltrPhotoGridCell*
+cltr_photo_grid_get_active_cell(CltrPhotoGrid *grid);
+
+void
+cltr_photo_grid_set_active_cell(CltrPhotoGrid *grid, CltrPhotoGridCell *cell);
+
+CltrPhotoGridCell*
+cltr_photo_grid_get_first_cell(CltrPhotoGrid *grid);
+
void
cltr_photo_grid_append_cell(CltrPhotoGrid *grid,
Pixbuf *pixtmp;
int src_h, src_w;
- pixtmp = pixbuf_new(texture->tile_x_size[x], texture->tile_y_size[y]);
+
src_w = texture->tile_x_size[x];
src_h = texture->tile_y_size[y];
texture->tile_y_waste[y]);
*/
- pixbuf_copy(texture->pixb,
- pixtmp,
- texture->tile_x_position[x],
- texture->tile_y_position[y],
- texture->tile_x_size[x],
- texture->tile_y_size[y],
- 0,0);
+ /* Only break the pixbuf up if we have multiple tiles */
+ if (texture->n_x_tiles > 1 && texture->n_y_tiles >1)
+ {
+ pixtmp = pixbuf_new(texture->tile_x_size[x],
+ texture->tile_y_size[y]);
+
+ pixbuf_copy(texture->pixb,
+ pixtmp,
+ texture->tile_x_position[x],
+ texture->tile_y_position[y],
+ texture->tile_x_size[x],
+ texture->tile_y_size[y],
+ 0,0);
+ }
+ else pixtmp = texture->pixb;
glBindTexture(GL_TEXTURE_2D, texture->tiles[i]);
CLTR_GLERR();
- pixbuf_unref(pixtmp);
+ if (pixtmp != texture->pixb)
+ pixbuf_unref(pixtmp);
i++;
return texture;
}
+
+Pixbuf*
+cltr_texture_get_pixbuf(CltrTexture* texture)
+{
+ return texture->pixb;
+}
+
+void
+cltr_texture_resync_pixbuf(CltrTexture* texture)
+{
+ cltr_texture_unrealize(texture);
+}
int x2,
int y2);
+Pixbuf*
+cltr_texture_get_pixbuf(CltrTexture* texture);
+
+void
+cltr_texture_resync_pixbuf(CltrTexture* texture);
+
+
#endif
atom_WINDOW_STATE, XA_ATOM, 32,
PropModeReplace,
(unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1);
+
+ /*
+ XF86VidModeSwitchToMode (GLWin.dpy, GLWin.screen, &GLWin.deskMode);
+ XF86VidModeSetViewPort (GLWin.dpy, GLWin.screen, 0, 0);
+ */
}
#include "cltr-events.h"
#include "cltr-widget.h"
#include "cltr-window.h"
-
+#include "cltr-overlay.h"
+#include "cltr-button.h"
#include "cltr-photo-grid.h"
#endif
#include "pixbuf.h"
#include "util.h"
+#define CLTR_CLAMP(x, y) ((x) > (y)) ? (y) : (x);
+
static int*
load_png_file( const char *file,
int *width,
return pixb_scaled;
}
+Pixbuf*
+pixbuf_clone(Pixbuf *pixb)
+{
+ Pixbuf *clone;
+
+ clone = util_malloc0(sizeof(Pixbuf));
+
+ clone->width = pixb->width;
+ clone->height = pixb->height;
+ clone->bytes_per_pixel = pixb->bytes_per_pixel;
+ clone->channels = pixb->channels;
+ clone->bytes_per_line = pixb->bytes_per_line;
+ clone->data = malloc(pixb->bytes_per_line * pixb->height);
+
+ memcpy(clone->data, pixb->data, pixb->bytes_per_line * pixb->height);
+
+ return clone;
+}
+
+Pixbuf*
+pixbuf_convolve(Pixbuf *pixb,
+ int *kernel,
+ int kernel_size,
+ int kernel_divisor)
+{
+ int padding, x, y, r, g, b, a, l, k;
+ PixbufPixel pixel;
+ Pixbuf *clone_pixb;
+
+ padding = ( kernel_size - 1 ) / 2;
+ clone_pixb = pixbuf_clone(pixb);
+
+ for( y = padding; y < pixb->height - padding; y++ )
+ {
+ for( x = padding; x < pixb->width - padding; x++ )
+ {
+ r = b = g = a = 0;
+
+ for( l = 0; l < kernel_size; l++ )
+ {
+ for( k = 0; k < kernel_size; k++ )
+ {
+ pixbuf_get_pixel(pixb, (x+k-padding), (y+l-padding), &pixel);
+
+ r += pixel.r * kernel[k + l * kernel_size];
+ g += pixel.g * kernel[k + l * kernel_size];
+ b += pixel.b * kernel[k + l * kernel_size];
+ a += pixel.a * kernel[k + l * kernel_size];
+ }
+ }
+
+ r = CLTR_CLAMP( r / kernel_divisor, 0xff);
+ g = CLTR_CLAMP( g / kernel_divisor, 0xff);
+ b = CLTR_CLAMP( b / kernel_divisor, 0xff);
+ a = CLTR_CLAMP( a / kernel_divisor, 0xff);
+
+ pixel_set_vals(&pixel, r, g, b, a);
+
+ pixbuf_set_pixel(clone_pixb, x, y, &pixel);
+
+ }
+ }
+
+ return clone_pixb;
+}
+
+Pixbuf*
+pixbuf_blur(Pixbuf *pixb)
+{
+ /*
+ int kernel[] = { 1, 1, 1,
+ 1, 0, 1,
+ 1, 1, 1 };
+ */
+
+ int kernel[] = { 1, 1, 1,
+ 1, 1, 1,
+ 1, 1, 1 };
+
+
+ return pixbuf_convolve( pixb, kernel, 3, 9 );
+}
+
+Pixbuf*
+pixbuf_sharpen(Pixbuf *pixb)
+{
+ int kernel[] = {-1, -1, -1,
+ -1, 9, -1,
+ -1, -1, -1 };
+
+ return pixbuf_convolve( pixb, kernel, 3, 1 );
+}
+
+
#if 0
/*
return(blur_image);
}
+/* GPE-gallery convolve code */
+
+static void
+image_convolve( GdkPixbuf *pixbuf,
+ int *mask,
+ int mask_size,
+ int mask_divisor ) {
+
+ int x, y, k, l, b, rowstride, width, height, channels, padding, new_value;
+ int* temp_pixel;
+ guchar *temp_image, *image;
+
+ rowstride = gdk_pixbuf_get_rowstride( GDK_PIXBUF( pixbuf ) );
+ channels = gdk_pixbuf_get_n_channels( GDK_PIXBUF( pixbuf ) );
+
+ width = gdk_pixbuf_get_width( GDK_PIXBUF( pixbuf ) );
+ height = gdk_pixbuf_get_height( GDK_PIXBUF( pixbuf ) );
+
+ // fprintf( stderr, "Rowstride: %d, width: %d, height: %d, channels: %d\n", rowstride, width, height, channels );
+
+
+ padding = ( mask_size - 1 ) / 2;
+
+ image = gdk_pixbuf_get_pixels( GDK_PIXBUF( pixbuf ) );
+ temp_image = (guchar*) malloc( width * height * channels * sizeof( guchar ) );
+ memcpy( temp_image, image, width * height * channels * sizeof( guchar ) );
+ temp_pixel =(int*) malloc( channels * sizeof( int ) );
+ for( y = padding; y < height - padding; y++ ) {
+
+ for( x = padding; x < width - padding; x++ ) {
+
+ for( b = 0; b < channels; b++ )
+ temp_pixel[b] = 0;
+
+ for( l = 0; l < mask_size; l++ ) {
+
+ for( k = 0; k < mask_size; k++ ) {
+
+ for( b = 0; b < channels; b++ )
+ temp_pixel[b] += temp_image[ ( y + l - padding ) * rowstride
+ + ( x + k - padding ) * channels + b ] * mask[ k + l *
+ mask_size ];
+
+ }
+
+ }
+
+ for( b = 0; b < channels; b++ ) {
+
+ new_value = temp_pixel[b] / mask_divisor;
+ image[ y * rowstride + x * channels + b ] = ( new_value > 255 ? 255
+ : new_value < 0 ? 0 : new_value );
+
+ }
+
+ }
+
+ }
+
+
+ free( temp_image );
+ free( temp_pixel );
+
+}
+
+void image_tools_blur( GdkPixbuf* pixbuf ) {
+
+ int mask[] = { 1, 1, 1,
+ 1, 1, 1,
+ 1, 1, 1 };
+
+ image_convolve( pixbuf, mask, 3, 9 );
+
+}
+
+void image_tools_sharpen( GdkPixbuf* pixbuf ) {
+
+ int mask[] = {-1, -1, -1,
+ -1, 9, -1,
+ -1, -1, -1 };
+
+ image_convolve( pixbuf, mask, 3, 1 );
+
+}
+
#endif
int new_width,
int new_height);
+Pixbuf*
+pixbuf_clone(Pixbuf *pixb);
+
+Pixbuf*
+pixbuf_convolve(Pixbuf *pixb,
+ int *kernel,
+ int kernel_size,
+ int kernel_divisor) ;
+
+Pixbuf*
+pixbuf_blur(Pixbuf *pixb);
+
+Pixbuf*
+pixbuf_sharpen(Pixbuf *pixb);
+
+
#endif
dnl ----- Gstreamer ---------------------------------------------------------
-pkg_modules="gstreamer-0.8 gstreamer-interfaces-0.8 gthread-2.0"
+pkg_modules="gstreamer-0.8 gstreamer-interfaces-0.8 gthread-2.0 gstreamer-play-0.8 gstreamer-gconf-0.8"
PKG_CHECK_MODULES(GST, [$pkg_modules])
+dnl ----- Gconf -------------------------------------------------------------
+
+PKG_CHECK_MODULES(GCONF, gconf-2.0, HAVE_GCONF="yes", HAVE_GCONF="no")
+
dnl ------ Check for PNG ---------------------------------------------------
AC_MSG_CHECKING(for libpng12)
AC_SUBST(GST_CFLAGS)
AC_SUBST(GST_LIBS)
+AC_SUBST(GCONF_CFLAGS)
+AC_SUBST(GCONF_LIBS)
+
CLTR_CFLAGS="$GLX_CLAGS $CLTR_CFLAGS"
CLTR_LIBS="$GLX_LIBS $PNG_LIBS $JPEG_LIBS $CLTR_LIBS"
AC_SUBST(CLTR_CFLAGS)
AC_SUBST(CLTR_LIBS)
-
AC_OUTPUT([Makefile
clutter/Makefile
examples/Makefile
+gst/Makefile
])
-noinst_PROGRAMS = scratch
+noinst_PROGRAMS = scratch photos player
scratch_SOURCES = scratch.c
scratch_CFLAGS = $(CLTR_CFLAGS)
scratch_LDFLAGS = \
$(CLTR_LIBS) \
$(top_builddir)/clutter/libclutter.la
+
+photos_SOURCES = photos.c
+photos_CFLAGS = $(CLTR_CFLAGS)
+photos_LDFLAGS = \
+ $(CLTR_LIBS) \
+ $(top_builddir)/clutter/libclutter.la
+
+player_SOURCES = player.c
+player_CFLAGS = $(CLTR_CFLAGS) $(GST_CFLAGS) $(GCONF_CFLAGS)
+player_LDFLAGS = \
+ $(CLTR_LIBS) \
+ $(GST_LIBS) \
+ $(GCONF_LIBS) \
+ $(top_builddir)/clutter/libclutter.la
+
+
--- /dev/null
+#include <clutter/cltr.h>
+
+gchar *ImgPath = NULL;
+
+int
+usage(char *progname)
+{
+ fprintf(stderr, "Usage ... check source for now\n");
+ exit(-1);
+}
+
+gpointer
+photo_grid_populate(gpointer data)
+{
+ CltrPhotoGrid *grid = (CltrPhotoGrid *)data;
+ GDir *dir;
+ GError *error;
+ const gchar *entry = NULL;
+ gchar *fullpath = NULL;
+ int n_pixb = 0, i =0;
+ ClutterFont *font = NULL;
+ PixbufPixel font_col = { 255, 255, 255, 255 };
+
+ font = font_new("Sans Bold 96");
+
+ if ((dir = g_dir_open (ImgPath, 0, &error)) == NULL)
+ {
+ /* handle this much better */
+ fprintf(stderr, "failed to open '%s'\n", ImgPath);
+ return NULL;
+ }
+
+ while ((entry = g_dir_read_name (dir)) != NULL)
+ {
+ if (!strcasecmp(&entry[strlen(entry)-4], ".png")
+ || !strcasecmp(&entry[strlen(entry)-4], ".jpg")
+ || !strcasecmp(&entry[strlen(entry)-5], ".jpeg"))
+ n_pixb++;
+ }
+
+ g_dir_rewind (dir);
+
+ while ((entry = g_dir_read_name (dir)) != NULL)
+ {
+ Pixbuf *pixb = NULL;
+ fullpath = g_strconcat(ImgPath, "/", entry, NULL);
+
+ pixb = pixbuf_new_from_file(fullpath);
+
+ if (pixb)
+ {
+ CltrPhotoGridCell *cell;
+ gchar buf[24];
+ Pixbuf *tmp_pixb;
+
+ cell = cltr_photo_grid_cell_new(grid, pixb);
+
+ g_snprintf(&buf[0], 24, "%i", i);
+ font_draw(font, cltr_photo_grid_cell_pixbuf(cell),
+ buf, 10, 10, &font_col);
+
+ g_mutex_lock(cltr_photo_grid_mutex(grid));
+
+ if (!cltr_photo_grid_get_active_cell(grid))
+ cltr_photo_grid_set_active_cell(grid,
+ cltr_photo_grid_get_first_cell(grid));
+
+ cltr_photo_grid_append_cell(grid, cell);
+
+ g_mutex_unlock(cltr_photo_grid_mutex(grid));
+
+ i++;
+ }
+
+ g_free(fullpath);
+ }
+
+ g_dir_close (dir);
+
+ g_mutex_lock(cltr_photo_grid_mutex(grid));
+
+ cltr_photo_grid_set_populated(grid, TRUE);
+
+ g_mutex_unlock(cltr_photo_grid_mutex(grid));
+
+ cltr_widget_queue_paint(CLTR_WIDGET(grid));
+
+ return NULL;
+}
+
+int
+main(int argc, char **argv)
+{
+ CltrWidget *win = NULL, *grid = NULL;
+ gchar *img_path = NULL;
+ gboolean want_fullscreen = FALSE;
+ gint i, cols = 3;
+
+ GThread *loader_thread;
+
+ cltr_init(&argc, &argv);
+
+ if (argc < 2)
+ usage(argv[0]);
+
+ for (i = 1; i < argc; i++)
+ {
+ if (!strcmp ("--image-path", argv[i]) || !strcmp ("-i", argv[i]))
+ {
+ if (++i>=argc) usage (argv[0]);
+ ImgPath = argv[i];
+ continue;
+ }
+ if (!strcmp ("--cols", argv[i]) || !strcmp ("-c", argv[i]))
+ {
+ if (++i>=argc) usage (argv[0]);
+ cols = atoi(argv[i]);
+ continue;
+ }
+ if (!strcmp ("-fs", argv[i]) || !strcmp ("--fullscreen", argv[i]))
+ {
+ want_fullscreen = TRUE;
+ continue;
+ }
+ if (!strcmp("--help", argv[i]) || !strcmp("-h", argv[i]))
+ {
+ usage(argv[0]);
+ }
+
+ usage(argv[0]);
+ }
+
+ win = cltr_window_new(800, 600);
+
+ if (want_fullscreen)
+ cltr_window_set_fullscreen(CLTR_WINDOW(win));
+
+ grid = cltr_photo_grid_new(800, 600, cols, cols, ImgPath);
+
+ cltr_window_focus_widget(CLTR_WINDOW(win), grid);
+
+ cltr_widget_add_child(win, grid, 0, 0);
+
+ cltr_widget_show_all(win);
+
+ /* grid->state = CLTR_PHOTO_GRID_STATE_BROWSE; */
+
+ loader_thread = g_thread_create (photo_grid_populate,
+ (gpointer)grid,
+ TRUE,
+ NULL);
+
+
+ cltr_main_loop();
+
+ return 0;
+}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2003 Julien Moutte <julien@moutte.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <clutter/cltr.h>
+
+#include <gst/play/play.h>
+#include <gst/gconf/gconf.h>
+
+static GMainLoop *loop = NULL;
+static gint64 length = 0;
+
+static void
+print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
+{
+ gint i, count;
+
+ count = gst_tag_list_get_tag_size (list, tag);
+
+ for (i = 0; i < count; i++) {
+ gchar *str;
+
+ if (gst_tag_get_type (tag) == G_TYPE_STRING) {
+ if (!gst_tag_list_get_string_index (list, tag, i, &str))
+ g_assert_not_reached ();
+ } else {
+ str =
+ g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
+ }
+
+ if (i == 0) {
+ g_print ("%15s: %s\n", gst_tag_get_nick (tag), str);
+ } else {
+ g_print (" : %s\n", str);
+ }
+
+ g_free (str);
+ }
+}
+
+static void
+got_found_tag (GstPlay * play, GstElement * source, GstTagList * tag_list)
+{
+ gst_tag_list_foreach (tag_list, print_tag, NULL);
+}
+
+static void
+got_time_tick (GstPlay * play, gint64 time_nanos)
+{
+ g_print ("time tick %f\n", time_nanos / (float) GST_SECOND);
+}
+
+static void
+got_stream_length (GstPlay * play, gint64 length_nanos)
+{
+ g_print ("got length %" G_GUINT64_FORMAT "\n", length_nanos);
+ length = length_nanos;
+}
+
+static void
+got_video_size (GstPlay * play, gint width, gint height)
+{
+ g_print ("got video size %d, %d\n", width, height);
+}
+
+static void
+got_eos (GstPlay * play)
+{
+ g_print ("End Of Stream\n");
+ g_main_loop_quit (loop);
+}
+
+static gboolean
+seek_timer (GstPlay * play)
+{
+ gst_play_seek_to_time (play, length / 2);
+ return FALSE;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GstPlay *play;
+ GstElement *data_src, *video_sink, *audio_sink, *vis_element;
+ GError *error = NULL;
+
+ CltrWidget *win;
+
+ /* Initing GStreamer library */
+ gst_init (&argc, &argv);
+ cltr_init (&argc, &argv);
+
+ if (argc != 2) {
+ g_print ("usage: %s <video filename>\n", argv[0]);
+ exit (-1);
+ }
+
+ win = cltr_window_new(800, 600);
+ cltr_widget_show_all(win);
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ /* Creating the GstPlay object */
+ play = gst_play_new (&error);
+ if (error) {
+ g_print ("Error: could not create play object:\n%s\n", error->message);
+ g_error_free (error);
+ return 1;
+ }
+
+ /* Getting default audio and video plugins from GConf */
+ vis_element = gst_element_factory_make ("goom", "vis_element");
+ data_src = gst_element_factory_make ("gnomevfssrc", "source");
+
+ audio_sink = gst_gconf_get_default_audio_sink ();
+ if (!GST_IS_ELEMENT (audio_sink))
+ g_error ("Could not get default audio sink from GConf");
+
+ /*
+ video_sink = gst_gconf_get_default_video_sink ();
+ if (!GST_IS_ELEMENT (video_sink))
+ g_error ("Could not get default video sink from GConf");
+ */
+
+ video_sink = gst_element_factory_make ("cltrimagesink", "cltr-output");
+
+ gst_element_set(video_sink, "widget", win, NULL);
+
+ if (video_sink == NULL)
+ g_printf("sink NULL\n");
+
+ /* Let's send them to GstPlay object */
+ if (!gst_play_set_audio_sink (play, audio_sink))
+ g_warning ("Could not set audio sink");
+ if (!gst_play_set_video_sink (play, video_sink))
+ g_warning ("Could not set video sink");
+ if (!gst_play_set_data_src (play, data_src))
+ g_warning ("Could not set data src");
+ if (!gst_play_set_visualization (play, vis_element))
+ g_warning ("Could not set visualisation");
+
+ /* Setting location we want to play */
+ if (!gst_play_set_location (play, argv[1]))
+ g_warning ("Could not set location");
+
+ /* Uncomment that line to get an XML dump of the pipeline */
+ gst_xml_write_file (GST_ELEMENT (play), stdout);
+
+ g_signal_connect (G_OBJECT (play), "time_tick",
+ G_CALLBACK (got_time_tick), NULL);
+ g_signal_connect (G_OBJECT (play), "stream_length",
+ G_CALLBACK (got_stream_length), NULL);
+ g_signal_connect (G_OBJECT (play), "have_video_size",
+ G_CALLBACK (got_video_size), NULL);
+ g_signal_connect (G_OBJECT (play), "found_tag",
+ G_CALLBACK (got_found_tag), NULL);
+ g_signal_connect (G_OBJECT (play), "error",
+ G_CALLBACK (gst_element_default_error), NULL);
+ g_signal_connect (G_OBJECT (play), "eos", G_CALLBACK (got_eos), NULL);
+
+ /* Change state to PLAYING */
+ if (gst_element_set_state (GST_ELEMENT (play),
+ GST_STATE_PLAYING) == GST_STATE_FAILURE)
+ g_error ("Could not set state to PLAYING");
+
+ g_timeout_add (20000, (GSourceFunc) seek_timer, play);
+
+
+
+ cltr_main_loop();
+ // g_main_loop_run (loop);
+
+ g_print ("setting pipeline to ready\n");
+
+ gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
+
+ /* unref
+ gst_object_unref (GST_OBJECT (play)); */
+
+ exit (0);
+}
--- /dev/null
+# see http://cvs.sourceforge.net/viewcvs.py/wechselspieler/wechselspieler/plugins/Makefile.am?rev=1.6&view=auto
+
+lib_LTLIBRARIES = libcltrimagesink.la
+
+# HACK HACK HACK HACK for now
+libdir= /usr/lib/gstreamer-0.8/
+
+INCLUDES=@GST_CFLAGS@ $(CLTR_CFLAGS)
+
+LIBS=@GST_LIBS@
+
+
+libcltrimagesink_la_SOURCES = cltrimagesink.c
+libcltrimagesink_la_INCLUDES = $(CLTR_CFLAGS)
+libcltrimagesink_LIBDIR = ${libdir}/gst
+libcltrimagesink_la_LIBADD = @CLTR_LIBS@
+libcltrimagesink_la_LDFLAGS = -module -avoid-version
+
+noinst_HEADERS = \
+ cltrimagesink.h
\ No newline at end of file
--- /dev/null
+/* GStreamer
+ * Copyright (C) <2003> Julien Moutte <julien@moutte.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define DBG(x, a...) \
+ g_printerr ( __FILE__ ":%d,%s() " x "\n", __LINE__, __func__, ##a)
+
+/* Object header */
+#include "cltrimagesink.h"
+
+/* Debugging category */
+#include <gst/gstinfo.h>
+
+GST_DEBUG_CATEGORY_STATIC (gst_debug_cltrimagesink);
+
+#define GST_CAT_DEFAULT gst_debug_cltrimagesink
+
+/* ElementFactory information */
+static GstElementDetails gst_cltrimagesink_details =
+GST_ELEMENT_DETAILS ("Video sink",
+ "Sink/Video",
+ "An Clutter based videosink",
+ "Matthew Allum <mallum@o-hand.com>");
+
+/* Default template - initiated with class struct to allow gst-register to work
+ without X running */
+static GstStaticPadTemplate gst_cltrimagesink_sink_template_factory =
+GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-raw-rgb, "
+ "framerate = (double) [ 1.0, 100.0 ], "
+ "width = (int) [ 1, MAX ], "
+ "height = (int) [ 1, MAX ]; "
+ "video/x-raw-yuv, "
+ "framerate = (double) [ 1.0, 100.0 ], "
+ "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
+ );
+
+/* CltrimageSink signals and args */
+enum
+{
+ SIGNAL_HANDOFF,
+ SIGNAL_BUFALLOC,
+ LAST_SIGNAL
+ /* FILL ME */
+ };
+
+static guint gst_cltrimagesink_signals[LAST_SIGNAL] = { 0 };
+
+enum
+{
+ ARG_0,
+ ARG_WIDGET,
+ ARG_SYNCHRONOUS,
+ ARG_SIGNAL_HANDOFFS
+ /* FILL ME */
+};
+
+static GstVideoSinkClass *parent_class = NULL;
+
+#define GLERR() \
+ { \
+ GLenum err = glGetError (); /* Roundtrip */ \
+ if (err != GL_NO_ERROR) \
+ { \
+ g_printerr (__FILE__ ": GL Error: %x [at %s:%d]\n", \
+ err, __func__, __LINE__); \
+ } \
+ }
+
+
+/* ============================================================= */
+/* */
+/* Private Methods */
+/* */
+/* ============================================================= */
+
+
+
+/*
+=================
+Element stuff
+=================
+*/
+
+static GstCaps *
+gst_cltrimagesink_fixate (GstPad *pad,
+ const GstCaps *caps)
+{
+ GstStructure *structure;
+ GstCaps *newcaps;
+
+ DBG("mark");
+
+ if (gst_caps_get_size (caps) > 1)
+ return NULL;
+
+ newcaps = gst_caps_copy (caps);
+ structure = gst_caps_get_structure (newcaps, 0);
+
+ if (gst_caps_structure_fixate_field_nearest_int (structure, "width", 320))
+ {
+ return newcaps;
+ }
+
+ if (gst_caps_structure_fixate_field_nearest_int (structure, "height", 240))
+ {
+ return newcaps;
+ }
+
+ if (gst_caps_structure_fixate_field_nearest_double (structure,
+ "framerate",
+ 30.0))
+ {
+ return newcaps;
+ }
+
+ gst_caps_free (newcaps);
+ return NULL;
+}
+
+static GstCaps *
+gst_cltrimagesink_getcaps (GstPad * pad)
+{
+ GstCltrimageSink *cltrimagesink;
+
+ cltrimagesink = GST_CLTRIMAGESINK (gst_pad_get_parent (pad));
+
+ if (!cltrimagesink->caps)
+ cltrimagesink->caps
+ = gst_caps_new_simple (
+ "video/x-raw-rgb",
+ "bpp", G_TYPE_INT, 24,
+ "depth", G_TYPE_INT, 24,
+ "endianness", G_TYPE_INT, G_BIG_ENDIAN,
+ "red_mask", G_TYPE_INT, 0xff0000,
+ "green_mask", G_TYPE_INT, 0x00ff00,
+ "blue_mask", G_TYPE_INT, 0xff,
+ "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
+ "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
+ "framerate", GST_TYPE_DOUBLE_RANGE, 1.0, 100.0, NULL);
+
+ return gst_caps_copy (cltrimagesink->caps);
+
+}
+
+static GstPadLinkReturn
+gst_cltrimagesink_sink_link (GstPad * pad, const GstCaps * caps)
+{
+ GstCltrimageSink *cltrimagesink;
+ gboolean ret;
+ GstStructure *structure;
+ Pixbuf *pixb = NULL;
+
+ DBG("mark");
+
+ cltrimagesink = GST_CLTRIMAGESINK (gst_pad_get_parent (pad));
+
+ /*
+ if (!cltrimagesink->texture)
+ return GST_PAD_LINK_DELAYED;
+ */
+
+ structure = gst_caps_get_structure (caps, 0);
+
+ ret = gst_structure_get_int (structure, "width",
+ &(GST_VIDEOSINK_WIDTH (cltrimagesink)));
+
+ ret &= gst_structure_get_int (structure, "height",
+ &(GST_VIDEOSINK_HEIGHT (cltrimagesink)));
+
+ ret &= gst_structure_get_double (structure,
+ "framerate", &cltrimagesink->framerate);
+ if (!ret)
+ {
+ DBG("!ret returning GST_PAD_LINK_REFUSED");
+ return GST_PAD_LINK_REFUSED;
+ }
+
+ cltrimagesink->pixel_width = 1;
+
+ gst_structure_get_int (structure, "pixel_width",
+ &cltrimagesink->pixel_width);
+
+ cltrimagesink->pixel_height = 1;
+
+ gst_structure_get_int (structure, "pixel_height",
+ &cltrimagesink->pixel_height);
+
+ DBG("returning GST_PAD_LINK_OK, with %ix%i or %ix%i",
+ cltrimagesink->pixel_width,
+ cltrimagesink->pixel_height,
+ GST_VIDEOSINK_WIDTH (cltrimagesink),
+ GST_VIDEOSINK_HEIGHT (cltrimagesink));
+
+ pixb = pixbuf_new(GST_VIDEOSINK_WIDTH (cltrimagesink),
+ GST_VIDEOSINK_HEIGHT (cltrimagesink));
+
+ DBG("pixbuf new at %ix%i", GST_VIDEOSINK_WIDTH (cltrimagesink),
+ GST_VIDEOSINK_HEIGHT (cltrimagesink));
+
+ /* Is this the right place ? */
+ cltrimagesink->texture = cltr_texture_new(pixb);
+
+ pixbuf_unref(pixb);
+
+ return GST_PAD_LINK_OK;
+}
+
+static GstElementStateReturn
+gst_cltrimagesink_change_state (GstElement * element)
+{
+ GstCltrimageSink *cltrimagesink;
+
+ DBG("mark");
+
+ cltrimagesink = GST_CLTRIMAGESINK (element);
+
+ switch (GST_STATE_TRANSITION (element))
+ {
+ case GST_STATE_NULL_TO_READY:
+ /* Initializing the Context */
+ /*
+ if (!cltrimagesink->texture)
+ {
+ DBG("setting state to failure");
+ return GST_STATE_FAILURE;
+ }
+ */
+ break;
+ case GST_STATE_READY_TO_PAUSED:
+ printf ("ready to paused\n");
+ cltrimagesink->time = 0;
+ break;
+ case GST_STATE_PAUSED_TO_PLAYING:
+ break;
+ case GST_STATE_PLAYING_TO_PAUSED:
+ break;
+ case GST_STATE_PAUSED_TO_READY:
+ cltrimagesink->framerate = 0;
+ GST_VIDEOSINK_WIDTH (cltrimagesink) = 0;
+ GST_VIDEOSINK_HEIGHT (cltrimagesink) = 0;
+ break;
+ case GST_STATE_READY_TO_NULL:
+ if (cltrimagesink->texture)
+ cltr_texture_unref(cltrimagesink->texture);
+
+ break;
+ }
+
+ if (GST_ELEMENT_CLASS (parent_class)->change_state)
+ return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+
+ return GST_STATE_SUCCESS;
+}
+
+static void
+gst_cltrimagesink_chain (GstPad * pad, GstData * data)
+{
+ GstBuffer *buf = GST_BUFFER (data);
+ GstCltrimageSink *cltrimagesink;
+
+ g_return_if_fail (GST_IS_PAD (pad));
+ g_return_if_fail (buf != NULL);
+
+ DBG("mark");
+
+ cltrimagesink = GST_CLTRIMAGESINK (gst_pad_get_parent (pad));
+
+ if (GST_IS_EVENT (data))
+ {
+ gst_pad_event_default (pad, GST_EVENT (data));
+ DBG("GST_IS_EVENT, returning");
+ return;
+ }
+
+ buf = GST_BUFFER (data);
+
+ /* update time */
+ if (GST_BUFFER_TIMESTAMP_IS_VALID (buf))
+ cltrimagesink->time = GST_BUFFER_TIMESTAMP (buf);
+
+ /* If this buffer has been allocated using our buffer management we
+ * simply put the ximage which is in the PRIVATE pointer */
+
+ DBG("time is is %li", cltrimagesink->time);
+
+#if 0
+ if (GST_BUFFER_FREE_DATA_FUNC (buf) == gst_cltrimagesink_buffer_free)
+ {
+ /*
+ gst_cltrimagesink_ximage_put (cltrimagesink, GST_BUFFER_PRIVATE (buf));
+ */
+ }
+ else
+#endif
+ { /* Else we have to copy the data into our private image, */
+ /* if we have one... */
+
+
+ if (cltrimagesink->texture)
+ {
+ /* need to copy the data into out pixbuf here */
+ Pixbuf *pixb = NULL;
+
+ pixb = cltr_texture_get_pixbuf(cltrimagesink->texture);
+
+ if (pixb)
+ memcpy (pixb->data,
+ GST_BUFFER_DATA (buf),
+ MIN (GST_BUFFER_SIZE (buf),
+ pixb->bytes_per_line * pixb->width));
+
+ cltr_texture_resync_pixbuf(cltrimagesink->texture);
+
+ /*
+ cltr_texture_render_to_gl_quad(cltrimagesink->texture,
+ 0, 0, 320, 240);
+ */
+
+
+#if 0
+ memcpy (cltrimagesink->cltrimage->data,
+ GST_BUFFER_DATA (buf),
+ MIN (GST_BUFFER_SIZE (buf),
+ cltrimagesink->cltrimage->size));
+
+ gst_cltrimagesink_ximage_put (cltrimagesink,
+ cltrimagesink->cltrimage);
+#endif
+ }
+ else
+ {
+ /* No image available. Something went wrong during capsnego ! */
+
+ DBG("MARK, texture == NULL");
+
+ gst_buffer_unref (buf);
+ GST_ELEMENT_ERROR (cltrimagesink, CORE, NEGOTIATION, (NULL),
+ ("no format defined before chain function"));
+ return;
+ }
+ }
+
+ /* swap buffer here ? */
+
+ GST_DEBUG ("clock wait: %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (cltrimagesink->time));
+
+ /* ah, BTW, I think the gst_element_wait should happen _before_
+ the ximage is shown */
+
+ if (GST_VIDEOSINK_CLOCK (cltrimagesink))
+ gst_element_wait (GST_ELEMENT (cltrimagesink), cltrimagesink->time);
+
+ /* set correct time for next buffer */
+ if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf) && cltrimagesink->framerate > 0)
+ cltrimagesink->time += GST_SECOND / cltrimagesink->framerate;
+
+ gst_buffer_unref (buf);
+
+ /*
+ if (!cltrimagesink->signal_handoffs)
+ gst_cltrimagesink_handle_xevents (cltrimagesink, pad);
+ */
+}
+
+
+/* =========================================== */
+/* */
+/* Init & Class init */
+/* */
+/* =========================================== */
+
+static void
+gst_cltrimagesink_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GstCltrimageSink *cltrimagesink;
+
+ g_return_if_fail (GST_IS_CLTRIMAGESINK (object));
+
+ cltrimagesink = GST_CLTRIMAGESINK (object);
+
+ switch (prop_id)
+ {
+ case ARG_WIDGET:
+ cltrimagesink->widget = g_value_get_pointer (value);
+ break;
+ /*
+ case ARG_SIGNAL_HANDOFFS:
+ cltrimagesink->signal_handoffs = g_value_get_boolean (value);
+ */
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_cltrimagesink_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GstCltrimageSink *cltrimagesink;
+
+ g_return_if_fail (GST_IS_CLTRIMAGESINK (object));
+
+ cltrimagesink = GST_CLTRIMAGESINK (object);
+
+ switch (prop_id)
+ {
+ case ARG_WIDGET:
+ g_value_set_pointer (value, cltrimagesink->widget);
+ break;
+ /*
+ case ARG_SIGNAL_HANDOFFS:
+ g_value_set_boolean (value, cltrimagesink->signal_handoffs);
+ break;
+ */
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_cltrimagesink_finalize (GObject *object)
+{
+ GstCltrimageSink *cltrimagesink;
+
+ cltrimagesink = GST_CLTRIMAGESINK (object);
+
+ /*
+ if (cltrimagesink->display_name)
+ {
+ g_free (cltrimagesink->display_name);
+ cltrimagesink->display_name = NULL;
+ }
+ */
+
+ g_mutex_free (cltrimagesink->x_lock);
+ g_mutex_free (cltrimagesink->pool_lock);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_cltrimagesink_init (GstCltrimageSink * cltrimagesink)
+{
+ DBG("mark");
+
+ GST_VIDEOSINK_PAD (cltrimagesink)
+ = gst_pad_new_from_template ( gst_static_pad_template_get(&gst_cltrimagesink_sink_template_factory), "sink");
+
+ gst_element_add_pad (GST_ELEMENT (cltrimagesink),
+ GST_VIDEOSINK_PAD (cltrimagesink));
+
+ gst_pad_set_chain_function (GST_VIDEOSINK_PAD (cltrimagesink),
+ gst_cltrimagesink_chain);
+
+ gst_pad_set_link_function (GST_VIDEOSINK_PAD (cltrimagesink),
+ gst_cltrimagesink_sink_link);
+
+ gst_pad_set_getcaps_function (GST_VIDEOSINK_PAD (cltrimagesink),
+ gst_cltrimagesink_getcaps);
+
+ gst_pad_set_fixate_function (GST_VIDEOSINK_PAD (cltrimagesink),
+ gst_cltrimagesink_fixate);
+
+ /*
+ gst_pad_set_bufferalloc_function (GST_VIDEOSINK_PAD (cltrimagesink),
+ gst_cltrimagesink_buffer_alloc);
+ */
+
+ cltrimagesink->framerate = 0;
+
+ cltrimagesink->x_lock = g_mutex_new ();
+
+ cltrimagesink->pixel_width = cltrimagesink->pixel_height = 1;
+
+ cltrimagesink->image_pool = NULL;
+ cltrimagesink->pool_lock = g_mutex_new ();
+
+ cltrimagesink->texture = NULL;
+
+ GST_FLAG_SET (cltrimagesink, GST_ELEMENT_THREAD_SUGGESTED);
+ GST_FLAG_SET (cltrimagesink, GST_ELEMENT_EVENT_AWARE);
+}
+
+static void
+gst_cltrimagesink_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_set_details (element_class, &gst_cltrimagesink_details);
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_cltrimagesink_sink_template_factory));
+}
+
+static void
+gst_cltrimagesink_class_init (GstCltrimageSinkClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+
+ gobject_class = (GObjectClass*) klass;
+ gstelement_class = (GstElementClass*) klass;
+
+ parent_class = g_type_class_ref (GST_TYPE_VIDEOSINK);
+
+ /* TOGO */
+ g_object_class_install_property (gobject_class,
+ ARG_WIDGET,
+ g_param_spec_pointer ("widget",
+ "Widget",
+ "Cltr drawable widget",
+ G_PARAM_READWRITE));
+
+ /* TOGO */
+ g_object_class_install_property (gobject_class,
+ ARG_SYNCHRONOUS,
+ g_param_spec_boolean ("synchronous",
+ "Synchronous",
+ "When enabled, runs "
+ "the X display in synchronous mode. (used only for debugging)",
+ FALSE,
+ G_PARAM_READWRITE));
+ /* TOGO */
+ g_object_class_install_property (gobject_class,
+ ARG_SIGNAL_HANDOFFS,
+ g_param_spec_boolean ("signal-handoffs",
+ "Signal handoffs",
+ "Send a signal before unreffing the buffer, forces YUV, no GL output",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ gst_cltrimagesink_signals[SIGNAL_HANDOFF]
+ = g_signal_new ("handoff",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GstCltrimageSinkClass, handoff),
+ NULL,
+ NULL,
+ gst_marshal_VOID__POINTER_OBJECT,
+ G_TYPE_NONE,
+ 2,
+ GST_TYPE_BUFFER,
+ GST_TYPE_PAD);
+
+ gst_cltrimagesink_signals[SIGNAL_BUFALLOC] =
+ g_signal_new ("bufferalloc",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GstCltrimageSinkClass, bufferalloc),
+ NULL,
+ NULL,
+ gst_marshal_VOID__POINTER_OBJECT,
+ G_TYPE_NONE, 2,
+ GST_TYPE_BUFFER, GST_TYPE_PAD);
+
+ gobject_class->finalize = gst_cltrimagesink_finalize;
+ gobject_class->set_property = gst_cltrimagesink_set_property;
+ gobject_class->get_property = gst_cltrimagesink_get_property;
+
+ gstelement_class->change_state = gst_cltrimagesink_change_state;
+}
+
+/* ============================================================= */
+/* */
+/* Public Methods */
+/* */
+/* ============================================================= */
+
+/* =========================================== */
+/* */
+/* Object typing & Creation */
+/* */
+/* =========================================== */
+
+GType
+gst_cltrimagesink_get_type (void)
+{
+ static GType cltrimagesink_type = 0;
+
+ if (!cltrimagesink_type)
+ {
+ static const GTypeInfo cltrimagesink_info =
+ {
+ sizeof (GstCltrimageSinkClass),
+ gst_cltrimagesink_base_init,
+ NULL,
+ (GClassInitFunc) gst_cltrimagesink_class_init,
+ NULL,
+ NULL,
+ sizeof (GstCltrimageSink),
+ 0,
+ (GInstanceInitFunc) gst_cltrimagesink_init,
+ };
+
+
+ cltrimagesink_type
+ = g_type_register_static (GST_TYPE_VIDEOSINK,
+ "GstCltrimageSink",
+ &cltrimagesink_info,
+ 0);
+ }
+
+ return cltrimagesink_type;
+}
+
+static gboolean
+plugin_init (GstPlugin *plugin)
+{
+ /* Loading the library containing GstVideoSink, our parent object */
+ if (!gst_library_load ("gstvideo"))
+ return FALSE;
+
+ if (!gst_element_register (plugin,
+ "cltrimagesink",
+ GST_RANK_SECONDARY,
+ GST_TYPE_CLTRIMAGESINK))
+ return FALSE;
+
+ GST_DEBUG_CATEGORY_INIT (gst_debug_cltrimagesink,
+ "cltrimagesink",
+ 0,
+ "cltrimagesink element");
+ return TRUE;
+}
+
+#define GST_LICENSE "LGPL"
+#define GST_PACKAGE "GStreamer"
+#define GST_ORIGIN "http://o-hand.com"
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "cltrimagesink",
+ "Clutter video output plugin based on OpenGL 1.2 calls",
+ plugin_init,
+ VERSION,
+ GST_LICENSE,
+ GST_PACKAGE,
+ GST_ORIGIN)
--- /dev/null
+#ifndef __GST_CLTRIMAGESINK_H__
+#define __GST_CLTRIMAGESINK_H__
+
+#include <gst/video/videosink.h>
+#include <clutter/cltr.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_CLTRIMAGESINK \
+ (gst_cltrimagesink_get_type())
+#define GST_CLTRIMAGESINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_CLTRIMAGESINK, GstCltrimageSink))
+#define GST_CLTRIMAGESINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_CLTRIMAGESINK, GstCltrimageSink))
+#define GST_IS_CLTRIMAGESINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_CLTRIMAGESINK))
+#define GST_IS_CLTRIMAGESINK_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_CLTRIMAGESINK))
+
+typedef struct _GstCltrimageSink GstCltrimageSink;
+typedef struct _GstCltrimageSinkClass GstCltrimageSinkClass;
+
+struct _GstCltrimageSink
+{
+ /* Our element stuff */
+ GstVideoSink videosink;
+
+ CltrTexture *texture;
+
+ int pixel_width, pixel_height;
+
+ gdouble framerate;
+ GMutex *x_lock;
+
+ GstClockTime time;
+
+ GMutex *pool_lock;
+ GSList *image_pool;
+
+ GstCaps *caps;
+
+ CltrWidget *widget;
+};
+
+struct _GstCltrimageSinkClass {
+ GstVideoSinkClass parent_class;
+
+ /* signals */
+ void (*handoff) (GstElement *element, GstBuffer *buf, GstPad *pad);
+ void (*bufferalloc) (GstElement *element, GstBuffer *buf, GstPad *pad);
+};
+
+GType gst_cltrimagesink_get_type(void); /* XXX needed ? */
+
+G_END_DECLS
+
+#endif /* __GST_CLTRIMAGESINK_H__ */