+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:
cltr-video.h \
cltr-list.h \
cltr-overlay.h \
+ cltr-label.h \
cltr-button.h \
cltr-scratch.h
cltr-video.c \
cltr-list.c \
cltr-overlay.c \
+ cltr-label.c \
cltr-button.c \
cltr-scratch.c
struct CltrButton
{
CltrWidget widget;
+ char *label;
+ Pixbuf *pixb;
+
};
static void
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)
{
--- /dev/null
+#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();
+ }
+}
--- /dev/null
+#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
#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;
}
}
-#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)
* - multisample ?
*/
+ if (!grid->paint_cell_item)
+ cltr_photo_grid_update_visual_state(grid);
+
glEnable(GL_BLEND);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); /* needed */
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,
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_INT_8_8_8_8,
+ /* GL_UNSIGNED_BYTE, */
pixtmp->data);
CLTR_GLERR();
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)
{
texture->mutex = g_mutex_new();
pixbuf_ref(pixb);
+ cltr_texture_ref(texture);
return texture;
}
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);
{
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;
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;
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) {
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);
}
/* 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)
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);
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;
}
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;
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,
#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"
pango_font_description_free (desc);
+ cltr_font_ref(font);
+
return font;
}
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;
tb2 = a * color->b + 0x80;
pixel.b = ((tb1 + (tb1 >> 8)) >> 8) + ((tb2 + (tb2 >> 8)) >> 8);
+
pixbuf_set_pixel (pixb, i, j, &pixel);
b++;
}
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,
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);
+ }
}
{
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,
int y,
PixbufPixel *p);
+void
+font_get_pixel_size (ClutterFont *font,
+ const char *text,
+ int *width,
+ int *height);
#endif
/* 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
/* ARGB_32 MSB */
- p->r = (*offset >> 24) & 0xff;
+ p->r = (*offset >> 24) & 0xff;
p->g = (*offset >> 16) & 0xff;
p->b = (*offset >> 8) & 0xff;
p->a = *offset & 0xff;
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");
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);
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);
exit (-1);
}
- win = cltr_window_new(800, 600);
+ font = font_new("Sans bold 96");
+
+ win = cltr_window_new(1400, 1050);
- video = cltr_video_new(800, 600);
+ 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);