video improvements + other tweaks

This commit is contained in:
Matthew Allum 2005-04-27 22:17:45 +00:00
parent 26decbdb97
commit 64355c0e48
15 changed files with 433 additions and 128 deletions

View File

@ -1,3 +1,28 @@
2005-04-27 mallum,,, <mallum@openedhand.com>
* clutter/Makefile.am:
* clutter/cltr-button.c: (cltr_button_new):
* clutter/cltr-label.c:
* clutter/cltr-label.h:
* clutter/cltr-photo-grid.c: (cltr_photo_grid_paint):
* clutter/cltr-texture.c: (cltr_texture_realize),
(cltr_texture_new), (cltr_texture_unref),
(cltr_texture_no_tile_new):
* clutter/cltr-texture.h:
* clutter/cltr-video.c: (cltr_video_got_time_tick), (caps_set),
(cltr_video_new), (cltr_video_idler), (cltr_video_set_source),
(cltr_video_play), (cltr_video_pause), (cltr_video_show),
(cltr_video_hide), (cltr_video_handle_xevent), (cltr_video_paint):
* clutter/cltr.h:
* clutter/fonts.c: (font_new), (draw_layout_on_pixbuf),
(font_draw):
* clutter/fonts.h:
* clutter/pixbuf.c: (pixbuf_set_pixel), (pixbuf_get_pixel):
* examples/photos.c: (photo_grid_populate), (main):
* examples/player.c: (main):
Improve video widget, use playbin rather than gst_play
Lots of misc tweaks.
2005-04-26 mallum,,, <mallum@openedhand.com>
* clutter/Makefile.am:

View File

@ -10,6 +10,7 @@ source_h = pixbuf.h util.h fonts.h \
cltr-video.h \
cltr-list.h \
cltr-overlay.h \
cltr-label.h \
cltr-button.h \
cltr-scratch.h
@ -24,6 +25,7 @@ source_c = pixbuf.c util.c fonts.c \
cltr-video.c \
cltr-list.c \
cltr-overlay.c \
cltr-label.c \
cltr-button.c \
cltr-scratch.c

View File

@ -4,6 +4,9 @@
struct CltrButton
{
CltrWidget widget;
char *label;
Pixbuf *pixb;
};
static void
@ -34,6 +37,23 @@ cltr_button_new(int width, int height)
return CLTR_WIDGET(button);
}
CltrWidget*
cltr_button_new_with_label(const char *label,
CltrFont *font,
PixbufPixel *col)
{
CltrButton *button = NULL;
int label_width, label_height;
if (font == NULL)
{
/* XXXX grab default font */
}
return CLTR_WIDGET(button);
}
static void
cltr_button_show(CltrWidget *widget)
{

133
clutter/cltr-label.c Normal file
View File

@ -0,0 +1,133 @@
#include "cltr-label.h"
#include "cltr-private.h"
struct CltrLabel
{
CltrWidget widget;
char *text;
Pixbuf *pixb;
PixbufPixel *col;
CltrFont *font;
CltrTexture *texture;
};
static void
cltr_label_show(CltrWidget *widget);
static gboolean
cltr_label_handle_xevent (CltrWidget *widget, XEvent *xev);
static void
cltr_label_paint(CltrWidget *widget);
CltrWidget*
cltr_label_new(const char *text,
CltrFont *font,
PixbufPixel *col)
{
CltrLabel *label;
int width,height;
label = g_malloc0(sizeof(CltrLabel));
font_get_pixel_size (font, text, &width, &height);
if (width && height)
{
PixbufPixel bg = { 0xff, 0x0, 0x0, 0xff };
label->text = strdup(text);
label->pixb = pixbuf_new(width, height);
pixbuf_fill_rect(label->pixb, 0, 0, -1, -1, &bg);
/*
font_draw(font,
label->pixb,
label->text,
0,
0,
col);
*/
label->texture = cltr_texture_new(label->pixb);
}
label->font = font; /* XXX Ref The font XXX*/
label->col = col; /* XXX Ref The Col XXX*/
label->widget.width = width;
label->widget.height = height;
label->widget.show = cltr_label_show;
label->widget.paint = cltr_label_paint;
label->widget.xevent_handler = cltr_label_handle_xevent;
return CLTR_WIDGET(label);
}
void
cltr_label_set_text(CltrLabel *label)
{
if (label->texture)
cltr_texture_unref(label->texture);
if (label->pixb)
cltr_texture_unref(label->pixb);
if (label->text)
free(label->text);
/* XXX TODO */
}
const char*
cltr_label_get_text(CltrLabel *label)
{
return label->text;
}
static void
cltr_label_show(CltrWidget *widget)
{
;
}
static gboolean
cltr_label_handle_xevent (CltrWidget *widget, XEvent *xev)
{
;
}
static void
cltr_label_paint(CltrWidget *widget)
{
CltrLabel *label = CLTR_LABEL(widget);
if (label->text)
{
glPushMatrix();
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
/* glColor4ub(100, 200, 50, 100); */
cltr_texture_render_to_gl_quad(label->texture,
widget->x,
widget->y,
widget->x + widget->width ,
widget->y + widget->height);
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glPopMatrix();
}
}

16
clutter/cltr-label.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef _HAVE_CLTR_LABEL_H
#define _HAVE_CLTR_LABEL_H
#include "cltr.h"
typedef struct CltrLabel CltrLabel;
#define CLTR_LABEL(w) ((CltrLabel*)(w))
CltrWidget*
cltr_label_new(const char *text,
CltrFont *font,
PixbufPixel *col);
#endif

View File

@ -1,29 +1,6 @@
#include "cltr-photo-grid.h"
#include "cltr-private.h"
/*
TODO
- image cache !!
- change idle_cb to timeouts, reduce tearing + inc interactivity on
image load
- Split events into seperate file ( break up ctrl.c )
- offset zoom a little to give border around picture grid
- figure out highlighting selected cell
- tape on pictures ?
- tidy this code here + document !
- fix threads, lower priority ?
*/
struct CltrPhotoGridCell
{
Pixbuf *pixb;
@ -432,88 +409,6 @@ cltr_photo_grid_activate_cell(CltrPhotoGrid *grid)
}
}
#if 0
gpointer
cltr_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 (grid->img_path, 0, &error)) == NULL)
{
/* handle this much better */
fprintf(stderr, "failed to open '%s'\n", grid->img_path);
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++;
}
CLTR_DBG("estamited %i pixb's\n", n_pixb);
g_dir_rewind (dir);
while ((entry = g_dir_read_name (dir)) != NULL)
{
Pixbuf *pixb = NULL;
fullpath = g_strconcat(grid->img_path, "/", 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, cell->pixb, buf, 10, 10, &font_col);
g_mutex_lock(Mutex_GRID);
cell->texture = cltr_texture_new(cell->pixb);
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_free(fullpath);
}
g_dir_close (dir);
g_mutex_lock(Mutex_GRID);
grid->is_populated = TRUE;
g_mutex_unlock(Mutex_GRID);
cltr_widget_queue_paint(CLTR_WIDGET(grid));
return NULL;
}
#endif
static void
cltr_photo_grid_update_visual_state(CltrPhotoGrid *grid)
@ -679,6 +574,9 @@ cltr_photo_grid_paint(CltrWidget *widget)
* - multisample ?
*/
if (!grid->paint_cell_item)
cltr_photo_grid_update_visual_state(grid);
glEnable(GL_BLEND);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); /* needed */

View File

@ -292,7 +292,7 @@ cltr_texture_realize(CltrTexture *texture)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexImage2D(GL_TEXTURE_2D, 0, /*GL_COMPRESSED_RGBA_ARB*/ GL_RGBA,
texture->width,
@ -360,13 +360,17 @@ cltr_texture_realize(CltrTexture *texture)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
/* glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_); */
/* glPixelStorei (GL_UNPACK_ALIGNMENT, 4); */
/* glPixelStorei (GL_UNPACK_ROW_LENGTH, texture->tile_x_size[x]); */
glTexImage2D(GL_TEXTURE_2D, 0, /*GL_COMPRESSED_RGBA_ARB*/ GL_RGBA,
pixtmp->width,
pixtmp->height,
0, GL_RGBA,
GL_UNSIGNED_INT_8_8_8_8,
/* GL_UNSIGNED_BYTE, */
pixtmp->data);
CLTR_GLERR();
@ -402,13 +406,32 @@ cltr_texture_new(Pixbuf *pixb)
pixbuf_ref(pixb);
init_tiles (texture);
cltr_texture_ref(texture);
return texture;
}
void
cltr_texture_ref(CltrTexture *texture)
{
texture->refcnt++;
}
void
cltr_texture_unref(CltrTexture *texture)
{
texture->refcnt--;
if (texture->refcnt <= 0)
{
cltr_texture_unrealize(texture);
g_free(texture);
pixbuf_unref(texture->pixb);
}
}
CltrTexture*
cltr_texture_no_tile_new(Pixbuf *pixb)
{
@ -432,6 +455,7 @@ cltr_texture_no_tile_new(Pixbuf *pixb)
texture->mutex = g_mutex_new();
pixbuf_ref(pixb);
cltr_texture_ref(texture);
return texture;
}

View File

@ -28,6 +28,12 @@ struct CltrTexture
CltrTexture*
cltr_texture_new(Pixbuf *pixb);
void
cltr_texture_ref(CltrTexture *texture);
void
cltr_texture_unref(CltrTexture *texture);
CltrTexture*
cltr_texture_no_tile_new(Pixbuf *pixb);

View File

@ -5,8 +5,7 @@ struct CltrVideo
{
CltrWidget widget;
GstPlay *play;
GstElement *data_src, *video_sink, *audio_sink, *vis_element;
GstElement *play, *data_src, *video_sink, *audio_sink, *vis_element;
GAsyncQueue *queue;
@ -82,9 +81,11 @@ cltr_video_got_time_tick (GstPlay *play,
gint64 time_nanos,
CltrVideo *video)
{
CltrVideoSignal *signal;
/*
CltrVideoSignal *signal;
signal = g_new0 (CltrVideoSignal, 1);
signal->signal_id = CLTR_VIDEO_ASYNC_FOUND_TAG;
signal->signal_data.found_tag.source = source;
@ -161,12 +162,15 @@ caps_set (GObject *obj,
GParamSpec *pspec,
CltrVideo *video)
{
#if 0
GstPad *pad = GST_PAD (obj);
GstStructure *s;
if (!GST_PAD_CAPS (pad))
return;
s = gst_caps_get_structure (GST_PAD_CAPS (pad), 0);
if (s) {
@ -191,8 +195,10 @@ caps_set (GObject *obj,
got_video_size (bvw->priv->play, bvw->priv->video_width,
bvw->priv->video_height, bvw);
}
*/
#endif
/* and disable ourselves */
//g_signal_handlers_disconnect_by_func (pad, caps_set, bvw);
}
@ -216,6 +222,91 @@ cltr_video_new(int width, int height)
/* Creating the GstPlay object */
video->play = gst_element_factory_make ("playbin", "play");
if (!video->play) {
g_error ("Could not make playbin element");
/* XXX Error */
return NULL;
}
video->audio_sink = gst_gconf_get_default_audio_sink ();
if (!GST_IS_ELEMENT (video->audio_sink))
g_error ("Could not get default audio sink from GConf");
video->video_sink = gst_element_factory_make ("cltrimagesink", "cltr-output");
if (!GST_IS_ELEMENT (video->video_sink))
g_error ("Could not get clutter video sink");
#if 0
sig1 = g_signal_connect (video_sink, "error", G_CALLBACK (out_error), err);
sig2 = g_signal_connect (audio_sink, "error", G_CALLBACK (out_error), err);
if (gst_element_set_state (video_sink,
GST_STATE_READY) != GST_STATE_SUCCESS ||
gst_element_set_state (audio_sink,
GST_STATE_READY) != GST_STATE_SUCCESS) {
if (err && !*err) {
g_set_error (err, 0, 0,
"Failed to intialize %s output; check your configuration",
GST_STATE (video_sink) == GST_STATE_NULL ?
"video" : "audio");
}
gst_object_unref (GST_OBJECT (video_sink));
gst_object_unref (GST_OBJECT (audio_sink));
g_object_unref (G_OBJECT (bvw));
return NULL;
}
/* somehow, alsa hangs? */
gst_element_set_state (video->audio_sink, GST_STATE_NULL);
g_signal_handler_disconnect (video->video_sink, sig1);
g_signal_handler_disconnect (video->audio_sink, sig2);
#endif
g_object_set (G_OBJECT (video->play), "video-sink",
video->video_sink, NULL);
g_object_set (G_OBJECT (video->play), "audio-sink",
video->audio_sink, NULL);
/* Needed ? */
#if 0
g_signal_connect (GST_PAD_REALIZE (gst_element_get_pad (audio_sink, "sink")),
"fixate", G_CALLBACK (cb_audio_fixate), (gpointer) bvw);
#endif
g_signal_connect (G_OBJECT (video->play), "eos",
G_CALLBACK (cltr_video_got_eos), (gpointer) video);
/*
g_signal_connect (G_OBJECT (video->play), "state-change",
G_CALLBACK (state_change), (gpointer) video);
*/
g_signal_connect (G_OBJECT (video->play), "found_tag",
G_CALLBACK (cltr_video_got_found_tag), (gpointer) video);
/*
g_signal_connect (G_OBJECT (video->play), "error",
G_CALLBACK (got_error), (gpointer) video);
g_signal_connect (G_OBJECT (video->play), "buffering",
G_CALLBACK (got_buffering), (gpointer) video);
g_signal_connect (G_OBJECT (video->play), "notify::source",
G_CALLBACK (got_source), (gpointer) video);
g_signal_connect (G_OBJECT (video->play), "notify::stream-info",
G_CALLBACK (stream_info_set), (gpointer) video);
g_signal_connect (G_OBJECT (video->play), "group-switch",
G_CALLBACK (group_switch), (gpointer) video);
g_signal_connect (G_OBJECT (video->play), "got-redirect",
G_CALLBACK (got_redirect), (gpointer) video);
*/
video->queue = g_async_queue_new ();
gst_element_set(video->video_sink, "queue", video->queue, NULL);
return CLTR_WIDGET(video);
#if 0
video->play = gst_play_new (&error);
if (error)
@ -275,7 +366,7 @@ cltr_video_new(int width, int height)
g_signal_connect (G_OBJECT (video->video_sink), "notify::caps",
G_CALLBACK (caps_set), video);
#endif
/*
g_object_set (G_OBJECT (video->play), "volume",
(gdouble) (1. * 0 / 100), NULL);
@ -336,8 +427,9 @@ cltr_video_idler (CltrVideo *video)
gboolean
cltr_video_set_source(CltrVideo *video, char *location)
{
if (!gst_play_set_location (video->play, location))
return FALSE;
/* if (!gst_play_set_location (video->play, location)) */
g_object_set (G_OBJECT (video->play), "uri", location, NULL);
return TRUE;
}
@ -390,11 +482,24 @@ cltr_video_paint(CltrWidget *widget)
glPushMatrix();
if (video->frame_texture
/*
&& video->video_height
&& video->video_width)
&& video->video_width
*/)
{
int dis_x, dis_y, dis_height, dis_width;
/* Hack */
if (!video->video_height || !video->video_width )
{
Pixbuf *pixb = cltr_texture_get_pixbuf(video->frame_texture);
video->video_height = pixb->height;
video->video_width = pixb->width;
}
if (video->video_width > video->video_height)
{
dis_width = widget->width;
@ -408,6 +513,10 @@ cltr_video_paint(CltrWidget *widget)
glEnable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
cltr_texture_lock(video->frame_texture);
cltr_texture_render_to_gl_quad(video->frame_texture,

View File

@ -54,6 +54,7 @@ typedef struct CltrTexture CltrTexture;
#include "cltr-widget.h"
#include "cltr-window.h"
#include "cltr-overlay.h"
#include "cltr-label.h"
#include "cltr-button.h"
#include "cltr-photo-grid.h"
#include "cltr-video.h"

View File

@ -22,6 +22,8 @@ font_new (const char *face)
pango_font_description_free (desc);
cltr_font_ref(font);
return font;
}
@ -116,6 +118,11 @@ draw_layout_on_pixbuf (PangoLayout *layout,
int tr1, tg1, tb1, tr2, tg2, tb2;
int a = (*b * color->a + 0x80) >> 8;
/*
if (!a)
{ b++; continue; }
*/
pixbuf_get_pixel (pixb, i, j, &pixel);
tr1 = (255 - a) * pixel.r + 0x80;
@ -128,6 +135,7 @@ draw_layout_on_pixbuf (PangoLayout *layout,
tb2 = a * color->b + 0x80;
pixel.b = ((tb1 + (tb1 >> 8)) >> 8) + ((tb2 + (tb2 >> 8)) >> 8);
pixbuf_set_pixel (pixb, i, j, &pixel);
b++;
}
@ -154,6 +162,8 @@ font_draw(ClutterFont *font,
layout = pango_layout_new (font->context);
pango_layout_set_width(layout, pixb->width - x );
pango_layout_set_text (layout, text, -1);
pango_layout_get_pixel_size (layout,
@ -166,4 +176,41 @@ font_draw(ClutterFont *font,
y,
pixb->width - x,
pixb->height - y);
g_object_unref(G_OBJECT(layout));
}
void
font_get_pixel_size (ClutterFont *font,
const char *text,
int *width,
int *height)
{
PangoLayout *layout;
layout = pango_layout_new (font->context);
pango_layout_set_text (layout, text, -1);
pango_layout_get_pixel_size (layout, width, height);
g_object_unref(G_OBJECT(layout));
}
void
cltr_font_ref(CltrFont *font)
{
font->refcnt++;
}
void
cltr_font_unref(CltrFont *font)
{
font->refcnt--;
if (font->refcnt <= 0)
{
/* XXX free up pango stuff */
g_free(font);
}
}

View File

@ -14,11 +14,19 @@ struct ClutterFont
{
PangoFontMap *font_map;
PangoContext *context;
int refcnt;
};
typedef ClutterFont CltrFont ; /* Tsk Tsk .. */
ClutterFont*
font_new (const char *face);
void
cltr_font_ref(CltrFont *font);
void
cltr_font_unref(CltrFont *font);
void
font_draw(ClutterFont *font,
@ -28,5 +36,10 @@ font_draw(ClutterFont *font,
int y,
PixbufPixel *p);
void
font_get_pixel_size (ClutterFont *font,
const char *text,
int *width,
int *height);
#endif

View File

@ -519,7 +519,12 @@ pixbuf_set_pixel(Pixbuf *pixb, int x, int y, PixbufPixel *p)
/* ARGB_32 MSB */
// *offset = (p->r << 0) | (p->g << 8) | (p->b << 16) | (p->a << 24);
*offset = (p->r << 24) | (p->g << 16) | (p->b << 8) | (p->a);
*offset = ( (p->r << 24) | (p->g << 16) | (p->b << 8) | (p->a) );
/*
printf("set %i,%i,%i,%i\n", p->r, p->g, p->b, p->a);
printf("Looks like %i %x\n", *offset, *offset);
*/
}
void

View File

@ -19,7 +19,7 @@ photo_grid_populate(gpointer data)
gchar *fullpath = NULL;
int n_pixb = 0, i =0;
ClutterFont *font = NULL;
PixbufPixel font_col = { 255, 255, 255, 255 };
PixbufPixel font_col = { 255, 0, 0, 255 };
font = font_new("Sans Bold 96");
@ -130,12 +130,12 @@ main(int argc, char **argv)
usage(argv[0]);
}
win = cltr_window_new(800, 600);
win = cltr_window_new(640, 480);
if (want_fullscreen)
cltr_window_set_fullscreen(CLTR_WINDOW(win));
grid = cltr_photo_grid_new(800, 600, cols, cols, ImgPath);
grid = cltr_photo_grid_new(640, 480, cols, cols, ImgPath);
cltr_window_focus_widget(CLTR_WINDOW(win), grid);

View File

@ -22,7 +22,11 @@
int
main (int argc, char *argv[])
{
CltrWidget *win, *video, *test;
CltrWidget *win, *video, *label;
CltrFont *font;
PixbufPixel col = { 0xff, 0xff, 0xff, 0x66 };
pixel_set_vals(&col, 0xff, 0x00, 0x00, 0xff);
cltr_init (&argc, &argv);
@ -31,17 +35,19 @@ main (int argc, char *argv[])
exit (-1);
}
win = cltr_window_new(800, 600);
font = font_new("Sans bold 96");
video = cltr_video_new(800, 600);
win = cltr_window_new(1400, 1050);
video = cltr_video_new(1400, 1050);
cltr_video_set_source(CLTR_VIDEO(video), argv[1]);
cltr_widget_add_child(win, video, 0, 0);
test = cltr_scratch_new(300, 300);
label = cltr_label_new("hello world", font, &col);
cltr_widget_add_child(win, test, 100, 100);
cltr_widget_add_child(win, label, 100, 100);
cltr_widget_show_all(win);