Lots, see ChangeLog

This commit is contained in:
Matthew Allum 2005-04-22 18:03:55 +00:00
parent 3b342b81b7
commit 298f878086
23 changed files with 1712 additions and 65 deletions

View File

@ -1,3 +1,41 @@
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> 2005-04-13 mallum,,, <mallum@openedhand.com>
* bootstrap-autotools.sh: * bootstrap-autotools.sh:

View File

@ -1 +1 @@
SUBDIRS=clutter examples SUBDIRS=clutter gst examples

View File

@ -8,6 +8,8 @@ source_h = pixbuf.h util.h fonts.h \
cltr-window.h \ cltr-window.h \
cltr-photo-grid.h \ cltr-photo-grid.h \
cltr-list.h \ cltr-list.h \
cltr-overlay.h \
cltr-button.h \
cltr-scratch.h cltr-scratch.h
source_c = pixbuf.c util.c fonts.c \ source_c = pixbuf.c util.c fonts.c \
@ -19,6 +21,8 @@ source_c = pixbuf.c util.c fonts.c \
cltr-window.c \ cltr-window.c \
cltr-photo-grid.c \ cltr-photo-grid.c \
cltr-list.c \ cltr-list.c \
cltr-overlay.c \
cltr-button.c \
cltr-scratch.c cltr-scratch.c
AM_CFLAGS = @GCC_FLAGS@ @CLTR_CFLAGS@ AM_CFLAGS = @GCC_FLAGS@ @CLTR_CFLAGS@

54
clutter/cltr-button.c Normal file
View File

@ -0,0 +1,54 @@
#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)
{
}

14
clutter/cltr-button.h Normal file
View File

@ -0,0 +1,14 @@
#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

View File

@ -4,20 +4,38 @@
int int
cltr_init(int *argc, char ***argv) cltr_init(int *argc, char ***argv)
{ {
#define GLX_SAMPLE_BUFFERS_ARB 100000
#define GLX_SAMPLES_ARB 100001
int gl_attributes[] = int gl_attributes[] =
{ {
GLX_RGBA, GLX_RGBA,
GLX_DOUBLEBUFFER, GLX_DOUBLEBUFFER,
GLX_STENCIL_SIZE, 1,
GLX_DEPTH_SIZE, 24,
/*
GLX_SAMPLE_BUFFERS_ARB, 1,
GLX_SAMPLES_ARB, 0,
*/
/*
GLX_RED_SIZE, 1, GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1, GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1, GLX_BLUE_SIZE, 1,
*/
0 0
}; };
XVisualInfo *vinfo; XVisualInfo *vinfo;
if (!g_thread_supported ())
g_thread_init (NULL); g_thread_init (NULL);
// XInitThreads (); // XInitThreads ();
if ((CltrCntx.xdpy = XOpenDisplay(getenv("DISPLAY"))) == NULL) if ((CltrCntx.xdpy = XOpenDisplay(getenv("DISPLAY"))) == NULL)
@ -28,6 +46,10 @@ cltr_init(int *argc, char ***argv)
CltrCntx.xscreen = DefaultScreen(CltrCntx.xdpy); CltrCntx.xscreen = DefaultScreen(CltrCntx.xdpy);
CltrCntx.xwin_root = RootWindow(CltrCntx.xdpy, CltrCntx.xscreen); CltrCntx.xwin_root = RootWindow(CltrCntx.xdpy, CltrCntx.xscreen);
CLTR_DBG("EXT : %s", glXQueryExtensionsString( CltrCntx.xdpy,
CltrCntx.xscreen));
if ((vinfo = glXChooseVisual(CltrCntx.xdpy, if ((vinfo = glXChooseVisual(CltrCntx.xdpy,
CltrCntx.xscreen, CltrCntx.xscreen,
gl_attributes)) == NULL) gl_attributes)) == NULL)

54
clutter/cltr-overlay.c Normal file
View File

@ -0,0 +1,54 @@
#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)
{
}

14
clutter/cltr-overlay.h Normal file
View File

@ -0,0 +1,14 @@
#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

View File

@ -22,7 +22,6 @@
*/ */
#define ANIM_FPS 60
#define FPS_TO_TIMEOUT(t) (1000/(t)) #define FPS_TO_TIMEOUT(t) (1000/(t))
struct CltrPhotoGridCell struct CltrPhotoGridCell
@ -51,10 +50,12 @@ struct CltrPhotoGrid
GList *cells_tail; GList *cells_tail;
GList *cell_active; GList *cell_active;
gboolean is_populated;
/* animation / zoom etc stuff */ /* animation / zoom etc stuff */
/* current anim frame position */ /* current anim frame position */
int anim_n_steps, anim_step; int anim_fps, anim_n_steps, anim_step;
/* start / end points for animations */ /* start / end points for animations */
float zoom_min, zoom_max, zoom_step; float zoom_min, zoom_max, zoom_step;
@ -64,9 +65,10 @@ struct CltrPhotoGrid
/* Values calucated from above for setting up the GL tranforms and 'view' */ /* Values calucated from above for setting up the GL tranforms and 'view' */
float paint_trans_x, paint_trans_y, paint_zoom; float paint_trans_x, paint_trans_y, paint_zoom;
int paint_start_y; int paint_start_y;
GList *paint_cell_item; GList *paint_cell_item;
GMutex *mutex;
CltrPhotoGridState state; CltrPhotoGridState state;
}; };
@ -84,9 +86,17 @@ static void
cltr_photo_grid_update_visual_state(CltrPhotoGrid *grid); cltr_photo_grid_update_visual_state(CltrPhotoGrid *grid);
/* this likely shouldn'y go here */ GMutex*
static GMutex *Mutex_GRID = NULL; 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 static void
cltr_photo_grid_handle_xkeyevent(CltrPhotoGrid *grid, XKeyEvent *xkeyev) cltr_photo_grid_handle_xkeyevent(CltrPhotoGrid *grid, XKeyEvent *xkeyev)
@ -140,12 +150,12 @@ cltr_photo_grid_handle_xevent (CltrWidget *widget, XEvent *xev)
CltrPhotoGridCell* CltrPhotoGridCell*
cltr_photo_grid_cell_new(CltrPhotoGrid *grid, cltr_photo_grid_cell_new(CltrPhotoGrid *grid,
Pixbuf *pixb, Pixbuf *pixb)
const gchar *filename)
{ {
CltrPhotoGridCell *cell = NULL; CltrPhotoGridCell *cell = NULL;
int maxw = grid->widget.width, maxh = grid->widget.height; int maxw = grid->widget.width, maxh = grid->widget.height;
int neww = 0, newh = 0; int neww = 0, newh = 0;
Pixbuf *tmp_pixb = NULL;
cell = g_malloc0(sizeof(CltrPhotoGridCell)); cell = g_malloc0(sizeof(CltrPhotoGridCell));
@ -173,7 +183,7 @@ cltr_photo_grid_cell_new(CltrPhotoGrid *grid,
} }
else cell->pixb = pixb; 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); cell->angle = 6.0 - (rand()%12);
@ -183,6 +193,44 @@ cltr_photo_grid_cell_new(CltrPhotoGrid *grid,
return cell; 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 void
cltr_photo_grid_append_cell(CltrPhotoGrid *grid, cltr_photo_grid_append_cell(CltrPhotoGrid *grid,
CltrPhotoGridCell *cell) CltrPhotoGridCell *cell)
@ -258,10 +306,11 @@ cltr_photo_grid_idle_cb(gpointer data)
cltr_widget_queue_paint(CLTR_WIDGET(grid)); cltr_widget_queue_paint(CLTR_WIDGET(grid));
if (!grid->is_populated)
return TRUE;
switch(grid->state) 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_IN:
case CLTR_PHOTO_GRID_STATE_ZOOM_OUT: case CLTR_PHOTO_GRID_STATE_ZOOM_OUT:
case CLTR_PHOTO_GRID_STATE_ZOOMED_MOVE: case CLTR_PHOTO_GRID_STATE_ZOOMED_MOVE:
@ -330,7 +379,7 @@ cltr_photo_grid_navigate(CltrPhotoGrid *grid,
} }
if (grid->state != CLTR_PHOTO_GRID_STATE_ZOOMED) 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); cltr_photo_grid_idle_cb, grid);
} }
@ -343,7 +392,7 @@ cltr_photo_grid_navigate(CltrPhotoGrid *grid,
grid->anim_step = 0; grid->anim_step = 0;
zoom = grid->zoom_max; 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); cltr_photo_grid_idle_cb, grid);
} }
@ -367,7 +416,7 @@ cltr_photo_grid_activate_cell(CltrPhotoGrid *grid)
grid->state = CLTR_PHOTO_GRID_STATE_ZOOM_IN; 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); cltr_photo_grid_idle_cb, grid);
} }
else if (grid->state == CLTR_PHOTO_GRID_STATE_ZOOMED) else if (grid->state == CLTR_PHOTO_GRID_STATE_ZOOMED)
@ -378,11 +427,12 @@ cltr_photo_grid_activate_cell(CltrPhotoGrid *grid)
grid->view_min_x = 0.0; grid->view_min_x = 0.0;
grid->view_min_y = 0.0; /*- (grid->row_offset * grid->cell_height);*/ 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); cltr_photo_grid_idle_cb, grid);
} }
} }
#if 0
gpointer gpointer
cltr_photo_grid_populate(gpointer data) cltr_photo_grid_populate(gpointer data)
{ {
@ -426,9 +476,10 @@ cltr_photo_grid_populate(gpointer data)
if (pixb) if (pixb)
{ {
CltrPhotoGridCell *cell; 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); g_snprintf(&buf[0], 24, "%i", i);
font_draw(font, cell->pixb, buf, 10, 10, &font_col); font_draw(font, cell->pixb, buf, 10, 10, &font_col);
@ -437,10 +488,13 @@ cltr_photo_grid_populate(gpointer data)
cell->texture = cltr_texture_new(cell->pixb); 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); cltr_photo_grid_append_cell(grid, cell);
g_mutex_unlock(Mutex_GRID);
i++; i++;
} }
@ -451,9 +505,7 @@ cltr_photo_grid_populate(gpointer data)
g_mutex_lock(Mutex_GRID); g_mutex_lock(Mutex_GRID);
grid->cell_active = g_list_first(grid->cells_tail); grid->is_populated = TRUE;
grid->state = CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE;
g_mutex_unlock(Mutex_GRID); g_mutex_unlock(Mutex_GRID);
@ -461,6 +513,7 @@ cltr_photo_grid_populate(gpointer data)
return NULL; return NULL;
} }
#endif
static void static void
cltr_photo_grid_update_visual_state(CltrPhotoGrid *grid) cltr_photo_grid_update_visual_state(CltrPhotoGrid *grid)
@ -478,9 +531,7 @@ cltr_photo_grid_update_visual_state(CltrPhotoGrid *grid)
grid->paint_cell_item = g_list_nth(grid->cells_tail, grid->paint_cell_item = g_list_nth(grid->cells_tail,
grid->n_cols * grid->row_offset); grid->n_cols * grid->row_offset);
if (grid->state != CLTR_PHOTO_GRID_STATE_BROWSE if (grid->state != CLTR_PHOTO_GRID_STATE_BROWSE)
&& grid->state != CLTR_PHOTO_GRID_STATE_LOADING
&& grid->state != CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE)
{ {
float scroll_min_y_offset = (float)(row_offset_h); float scroll_min_y_offset = (float)(row_offset_h);
@ -710,7 +761,7 @@ cltr_photo_grid_paint(CltrWidget *widget)
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
g_mutex_lock(Mutex_GRID); g_mutex_lock(grid->mutex);
cltr_texture_render_to_gl_quad(cell->texture, cltr_texture_render_to_gl_quad(cell->texture,
-(thumb_w/2), -(thumb_w/2),
@ -718,7 +769,7 @@ cltr_photo_grid_paint(CltrWidget *widget)
(thumb_w/2), (thumb_w/2),
(thumb_h/2)); (thumb_h/2));
g_mutex_unlock(Mutex_GRID); g_mutex_unlock(grid->mutex);
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
@ -738,16 +789,19 @@ cltr_photo_grid_paint(CltrWidget *widget)
cltr_glu_rounded_rect(-(thumb_w/2)-4, -(thumb_h/2)-4, cltr_glu_rounded_rect(-(thumb_w/2)-4, -(thumb_h/2)-4,
(thumb_w/2)+4, (thumb_h/2)+ns_border, (thumb_w/2)+4, (thumb_h/2)+ns_border,
thumb_w/40, thumb_w/30,
NULL); NULL);
glColor4f(0.1, 0.1, 0.1, 0.5); /* shadow */
cltr_glu_rounded_rect(-(thumb_w/2)-4, -(thumb_h/2)-4+1, glColor4f(0.1, 0.1, 0.1, 0.3);
(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); NULL);
glColor4f(1.0, 1.0, 1.0, 1.0); glColor4f(1.0, 1.0, 1.0, 1.0);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
@ -776,14 +830,6 @@ cltr_photo_grid_paint(CltrWidget *widget)
glColor3f(0.6, 0.6, 0.62); glColor3f(0.6, 0.6, 0.62);
glRecti(0, 0, widget->width, widget->height); 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 */ /* reset */
glDisable(GL_POLYGON_SMOOTH); glDisable(GL_POLYGON_SMOOTH);
@ -795,21 +841,51 @@ static void
cltr_photo_grid_show(CltrWidget *widget) cltr_photo_grid_show(CltrWidget *widget)
{ {
CltrPhotoGrid *grid = CLTR_PHOTO_GRID(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, loader_thread = g_thread_create (cltr_photo_grid_populate,
(gpointer)grid, (gpointer)grid,
TRUE, TRUE,
NULL); NULL);
*/
g_timeout_add(FPS_TO_TIMEOUT(20), grid->state = CLTR_PHOTO_GRID_STATE_BROWSE;
cltr_photo_grid_idle_cb, grid);
if (!grid->is_populated)
g_timeout_add(FPS_TO_TIMEOUT(20),
cltr_photo_grid_idle_cb, grid);
cltr_widget_queue_paint(widget); 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* CltrWidget*
cltr_photo_grid_new(int width, cltr_photo_grid_new(int width,
int height, int height,
@ -836,9 +912,12 @@ cltr_photo_grid_new(int width,
grid->cell_width = grid->widget.width / n_cols; grid->cell_width = grid->widget.width / n_cols;
grid->cell_height = grid->widget.height / n_rows; 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_n_steps = 20; /* value needs to be calced dep on rows */ grid->anim_fps = 50;
grid->anim_n_steps = 10; /* value needs to be calced dep on rows */
grid->anim_step = 0; grid->anim_step = 0;
/* Default 'browse view' */ /* Default 'browse view' */
@ -851,7 +930,7 @@ cltr_photo_grid_new(int width,
grid->row_offset = 0; grid->row_offset = 0;
Mutex_GRID = g_mutex_new(); grid->mutex = g_mutex_new();
return CLTR_WIDGET(grid); return CLTR_WIDGET(grid);
} }

View File

@ -11,8 +11,6 @@ typedef struct CltrPhotoGridCell CltrPhotoGridCell;
typedef enum CltrPhotoGridState typedef enum CltrPhotoGridState
{ {
CLTR_PHOTO_GRID_STATE_LOADING ,
CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE ,
CLTR_PHOTO_GRID_STATE_BROWSE , CLTR_PHOTO_GRID_STATE_BROWSE ,
CLTR_PHOTO_GRID_STATE_ZOOM_IN , CLTR_PHOTO_GRID_STATE_ZOOM_IN ,
CLTR_PHOTO_GRID_STATE_ZOOMED , CLTR_PHOTO_GRID_STATE_ZOOMED ,
@ -29,11 +27,28 @@ typedef enum CltrPhotoGridCellState
} }
CltrPhotoGridCellState; CltrPhotoGridCellState;
GMutex*
cltr_photo_grid_mutex(CltrPhotoGrid *grid);
void
cltr_photo_grid_set_populated(CltrPhotoGrid *grid, gboolean populated);
CltrPhotoGridCell* CltrPhotoGridCell*
cltr_photo_grid_cell_new(CltrPhotoGrid *grid, cltr_photo_grid_cell_new(CltrPhotoGrid *grid,
Pixbuf *pixb, Pixbuf *pixb);
const gchar *filename);
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 void
cltr_photo_grid_append_cell(CltrPhotoGrid *grid, cltr_photo_grid_append_cell(CltrPhotoGrid *grid,

View File

@ -259,7 +259,7 @@ cltr_texture_realize(CltrTexture *texture)
Pixbuf *pixtmp; Pixbuf *pixtmp;
int src_h, src_w; 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_w = texture->tile_x_size[x];
src_h = texture->tile_y_size[y]; src_h = texture->tile_y_size[y];
@ -276,13 +276,21 @@ cltr_texture_realize(CltrTexture *texture)
texture->tile_y_waste[y]); texture->tile_y_waste[y]);
*/ */
pixbuf_copy(texture->pixb, /* Only break the pixbuf up if we have multiple tiles */
pixtmp, if (texture->n_x_tiles > 1 && texture->n_y_tiles >1)
texture->tile_x_position[x], {
texture->tile_y_position[y], pixtmp = pixbuf_new(texture->tile_x_size[x],
texture->tile_x_size[x], texture->tile_y_size[y]);
texture->tile_y_size[y],
0,0); 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]); glBindTexture(GL_TEXTURE_2D, texture->tiles[i]);
@ -303,7 +311,8 @@ cltr_texture_realize(CltrTexture *texture)
CLTR_GLERR(); CLTR_GLERR();
pixbuf_unref(pixtmp); if (pixtmp != texture->pixb)
pixbuf_unref(pixtmp);
i++; i++;
@ -332,3 +341,15 @@ cltr_texture_new(Pixbuf *pixb)
return texture; return texture;
} }
Pixbuf*
cltr_texture_get_pixbuf(CltrTexture* texture)
{
return texture->pixb;
}
void
cltr_texture_resync_pixbuf(CltrTexture* texture)
{
cltr_texture_unrealize(texture);
}

View File

@ -37,4 +37,11 @@ cltr_texture_render_to_gl_quad(CltrTexture *texture,
int x2, int x2,
int y2); int y2);
Pixbuf*
cltr_texture_get_pixbuf(CltrTexture* texture);
void
cltr_texture_resync_pixbuf(CltrTexture* texture);
#endif #endif

View File

@ -149,6 +149,11 @@ cltr_window_set_fullscreen(CltrWindow *win)
atom_WINDOW_STATE, XA_ATOM, 32, atom_WINDOW_STATE, XA_ATOM, 32,
PropModeReplace, PropModeReplace,
(unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1); (unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1);
/*
XF86VidModeSwitchToMode (GLWin.dpy, GLWin.screen, &GLWin.deskMode);
XF86VidModeSetViewPort (GLWin.dpy, GLWin.screen, 0, 0);
*/
} }

View File

@ -49,7 +49,8 @@ CltrRect;
#include "cltr-events.h" #include "cltr-events.h"
#include "cltr-widget.h" #include "cltr-widget.h"
#include "cltr-window.h" #include "cltr-window.h"
#include "cltr-overlay.h"
#include "cltr-button.h"
#include "cltr-photo-grid.h" #include "cltr-photo-grid.h"
#endif #endif

View File

@ -19,6 +19,8 @@
#include "pixbuf.h" #include "pixbuf.h"
#include "util.h" #include "util.h"
#define CLTR_CLAMP(x, y) ((x) > (y)) ? (y) : (x);
static int* static int*
load_png_file( const char *file, load_png_file( const char *file,
int *width, int *width,
@ -672,6 +674,100 @@ pixbuf_scale_down(Pixbuf *pixb,
return pixb_scaled; 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 #if 0
/* /*
@ -927,4 +1023,89 @@ MagickExport Image *GaussianBlurImage(Image *image,const double radius,
return(blur_image); 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 #endif

View File

@ -86,4 +86,20 @@ pixbuf_scale_down(Pixbuf *pixb,
int new_width, int new_width,
int new_height); 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 #endif

View File

@ -66,9 +66,13 @@ PKG_CHECK_MODULES(CLTR, pangoft2 pango glib-2.0 gthread-2.0)
dnl ----- Gstreamer --------------------------------------------------------- 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]) 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 --------------------------------------------------- dnl ------ Check for PNG ---------------------------------------------------
AC_MSG_CHECKING(for libpng12) AC_MSG_CHECKING(for libpng12)
@ -110,14 +114,17 @@ AC_SUBST(GCC_FLAGS)
AC_SUBST(GST_CFLAGS) AC_SUBST(GST_CFLAGS)
AC_SUBST(GST_LIBS) AC_SUBST(GST_LIBS)
AC_SUBST(GCONF_CFLAGS)
AC_SUBST(GCONF_LIBS)
CLTR_CFLAGS="$GLX_CLAGS $CLTR_CFLAGS" CLTR_CFLAGS="$GLX_CLAGS $CLTR_CFLAGS"
CLTR_LIBS="$GLX_LIBS $PNG_LIBS $JPEG_LIBS $CLTR_LIBS" CLTR_LIBS="$GLX_LIBS $PNG_LIBS $JPEG_LIBS $CLTR_LIBS"
AC_SUBST(CLTR_CFLAGS) AC_SUBST(CLTR_CFLAGS)
AC_SUBST(CLTR_LIBS) AC_SUBST(CLTR_LIBS)
AC_OUTPUT([Makefile AC_OUTPUT([Makefile
clutter/Makefile clutter/Makefile
examples/Makefile examples/Makefile
gst/Makefile
]) ])

View File

@ -1,7 +1,23 @@
noinst_PROGRAMS = scratch noinst_PROGRAMS = scratch photos player
scratch_SOURCES = scratch.c scratch_SOURCES = scratch.c
scratch_CFLAGS = $(CLTR_CFLAGS) scratch_CFLAGS = $(CLTR_CFLAGS)
scratch_LDFLAGS = \ scratch_LDFLAGS = \
$(CLTR_LIBS) \ $(CLTR_LIBS) \
$(top_builddir)/clutter/libclutter.la $(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

157
examples/photos.c Normal file
View File

@ -0,0 +1,157 @@
#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;
}

196
examples/player.c Normal file
View File

@ -0,0 +1,196 @@
/* 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);
}

20
gst/Makefile.am Normal file
View File

@ -0,0 +1,20 @@
# 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

669
gst/cltrimagesink.c Normal file
View File

@ -0,0 +1,669 @@
/* 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)

57
gst/cltrimagesink.h Normal file
View File

@ -0,0 +1,57 @@
#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__ */