Video widget updates

This commit is contained in:
Matthew Allum 2005-05-06 17:41:15 +00:00
parent 246e6bdd5d
commit f085407d41
15 changed files with 696 additions and 260 deletions

View File

@ -1,3 +1,32 @@
2005-05-06 mallum,,, <mallum@openedhand.com>
* clutter/cltr-button.c: (cltr_button_new_with_label):
* clutter/cltr-overlay.c:
* clutter/cltr-photo-grid.c: (cltr_photo_grid_cell_new),
(cltr_photo_grid_paint), (cltr_photo_grid_new):
* clutter/cltr-video.c: (cltr_video_print_tag), (got_buffering),
(got_error), (caps_set), (parse_stream_info), (cb_iterate),
(cltr_video_new), (cltr_video_play), (cltr_video_seek),
(cltr_video_seek_time), (cltr_video_stop), (cltr_video_close),
(cltr_video_pause), (cltr_video_can_set_volume),
(cltr_video_set_volume), (cltr_video_get_volume),
(cltr_video_idler), (cltr_video_set_source), (cltr_video_show),
(cltr_video_hide), (cltr_video_handle_xevent), (cltr_video_paint):
* clutter/cltr-video.h:
* clutter/cltr-widget.h:
* clutter/cltr-window.c: (cltr_window_show), (cltr_window_paint),
(cltr_window_handle_xevent), (cltr_window_set_fullscreen),
(cltr_window_focus_widget):
* clutter/cltr-window.h:
* clutter/cltr.h:
* clutter/fonts.c: (get_layout_bitmap), (font_draw),
(font_get_pixel_size):
* configure.ac:
* examples/photos.c: (photo_grid_populate):
* examples/player.c: (handle_xevent), (main):
* examples/scratch.c: (main):
Lots more tweaks, mainly updating video widget.
2005-04-29 mallum,,, <mallum@openedhand.com>
* clutter/cltr-button.c: (cltr_button_new),

View File

@ -5,10 +5,13 @@ struct CltrButton
{
CltrWidget widget;
CltrLabel *label;
Pixmap *pixb;
CltrTexture *texture;
CltrButtonActivate activate_cb;
void *activate_cb_data;
CltrButtonState state; /* may be better in widget ? */
};
@ -85,6 +88,15 @@ cltr_button_new_with_label(const char *label,
return CLTR_WIDGET(button);
}
CltrWidget*
cltr_button_new_with_pixbuf(Pixbuf *pixb)
{
CltrButton *button = NULL;
button = CLTR_BUTTON(cltr_button_new(-1, -1));
}
static void
cltr_button_show(CltrWidget *widget)
{

View File

@ -3,7 +3,7 @@
struct CltrOverlay
{
CltrWidget widget;
CltrWidget widget;
};
static void
@ -49,6 +49,17 @@ cltr_overlay_handle_xevent (CltrWidget *widget, XEvent *xev)
static void
cltr_overlay_paint(CltrWidget *widget)
{
glEnable(GL_BLEND);
glColor4f(0.5, 0.5, 0.5, 1.0);
cltr_glu_rounded_rect(widget->x,
widget->y,
widget->x + widget->width,
widget->y + widget->height,
widget->width/30,
NULL);
glDisable(GL_BLEND);
}

View File

@ -132,7 +132,6 @@ cltr_photo_grid_cell_new(CltrPhotoGrid *grid,
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));
@ -540,7 +539,6 @@ cltr_photo_grid_paint(CltrWidget *widget)
int x = 0, y = 0, rows = 0, cols = 0, i =0;
GList *cell_item;
CltrWindow *win = CLTR_WINDOW(widget->parent);
CltrPhotoGrid *grid = (CltrPhotoGrid *)widget;
rows = grid->n_rows+1;
@ -551,10 +549,7 @@ cltr_photo_grid_paint(CltrWidget *widget)
if (grid->cells_tail == NULL)
{
/* No pictures to paint yet */
CltrWindow *win = CLTR_WINDOW(grid->widget.parent);
glColor3f(0.6, 0.6, 0.62);
glColor3ub(0xc2, 0xc3, 0xc1);
glRecti(0, 0, widget->width, widget->height);
glPopMatrix();
@ -607,7 +602,7 @@ cltr_photo_grid_paint(CltrWidget *widget)
CltrPhotoGridCell *cell = (CltrPhotoGridCell *)cell_item->data;
Pixbuf *pixb = NULL;
int x1, x2, y1, y2, thumb_w, thumb_h;
int ns_border, ew_border;
int ns_border, ew_border, selected_offset = 0;
pixb = cell->pixb;
@ -636,8 +631,12 @@ cltr_photo_grid_paint(CltrWidget *widget)
cell->anim_step = 0;
}
if (cell_item == grid->cell_active
&& grid->state == CLTR_PHOTO_GRID_STATE_BROWSE)
selected_offset = 2;
ew_border = thumb_w/8;
ns_border = thumb_h/8;
ns_border = (thumb_h/8) + 4;
thumb_w -= (2 * ew_border);
thumb_h -= (2 * ns_border);
@ -662,10 +661,10 @@ cltr_photo_grid_paint(CltrWidget *widget)
g_mutex_lock(grid->mutex);
cltr_texture_render_to_gl_quad(cell->texture,
-(thumb_w/2),
-(thumb_h/2),
(thumb_w/2),
(thumb_h/2));
-(thumb_w/2) - selected_offset,
-(thumb_h/2) - selected_offset,
(thumb_w/2) - selected_offset,
(thumb_h/2) - selected_offset);
g_mutex_unlock(grid->mutex);
@ -678,26 +677,46 @@ cltr_photo_grid_paint(CltrWidget *widget)
else
glColor4f(0.9, 0.95, 0.95, 1.0);
glColor4f(1.0, 1.0, 1.0, 1.0);
/* Draw with origin in center of photo */
/*
glRecti(-(thumb_w/2)-4, -(thumb_h/2)-4,
(thumb_w/2)+4, (thumb_h/2)+ns_border);
*/
glRecti(-(thumb_w/2)-6 - selected_offset,
-(thumb_h/2)-6 - selected_offset,
(thumb_w/2)+6 - selected_offset,
(thumb_h/2)+ns_border - selected_offset);
/*
cltr_glu_rounded_rect(-(thumb_w/2)-4, -(thumb_h/2)-4,
(thumb_w/2)+4, (thumb_h/2)+ns_border,
thumb_w/30,
NULL);
*/
/* Nice colors */
/* glColor4ub(0x3c, 0xbb, 0x15, 0xff); */
/* glColor4ub(0x99, 0x99, 0xff, 0xff); */
/* glColor4ub(0x99, 0x99, 0x99, 0xff); */
/* shadow */
glColor4ub(0x99, 0x99, 0x99, 0xff);
glRecti(-(thumb_w/2)-6+2, -(thumb_h/2)-6+2,
(thumb_w/2)+6+2, (thumb_h/2)+ns_border+2);
/*
glColor4f(0.1, 0.1, 0.1, 0.3);
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);
@ -725,7 +744,9 @@ cltr_photo_grid_paint(CltrWidget *widget)
/* finally paint background */
glDisable(GL_TEXTURE_2D);
glColor3f(0.6, 0.6, 0.62);
glColor3ub(0xc2, 0xc3, 0xc1);
glRecti(0, 0, widget->width, widget->height);
/* reset */
@ -824,7 +845,7 @@ cltr_photo_grid_new(int width,
grid->view_min_y = 0.0;
/* Assmes cols == rows */
grid->zoom_max = /* 1.0 + */ (float) (n_rows * 1.0); // - 0.3;
grid->zoom_max = (float) (n_rows * 1.0);
grid->row_offset = 0;

View File

@ -1,6 +1,8 @@
#include "cltr-video.h"
#include "cltr-private.h"
/* This is all very much based on the totem gst bacon video widget */
struct CltrVideo
{
CltrWidget widget;
@ -9,10 +11,20 @@ struct CltrVideo
GAsyncQueue *queue;
int video_width, video_height;
gint video_width, video_height;
gdouble video_fps;
CltrTexture *frame_texture;
};
gboolean has_video, has_audio;
gint64 stream_length;
gint64 current_time_nanos;
gint64 current_time;
float current_position;
guint update_id;
char *last_error_message;
};
static void
@ -24,6 +36,14 @@ cltr_video_handle_xevent (CltrWidget *widget, XEvent *xev);
static void
cltr_video_paint(CltrWidget *widget);
static void
parse_stream_info (CltrVideo *video);
static gboolean
cb_iterate (CltrVideo *video);
static gboolean
cltr_video_idler (CltrVideo *video);
static gint64 length = 0; /* to go */
@ -59,83 +79,7 @@ cltr_video_print_tag (const GstTagList *list,
}
static void
cltr_video_got_found_tag (GstPlay *play,
GstElement *source,
GstTagList *tag_list,
CltrVideo *video)
{
CltrVideoSignal *signal;
signal = g_new0 (CltrVideoSignal, 1);
signal->signal_id = CLTR_VIDEO_ASYNC_FOUND_TAG;
signal->signal_data.found_tag.source = source;
signal->signal_data.found_tag.tag_list = gst_tag_list_copy (tag_list);
g_async_queue_push (video->queue, signal);
/* gst_tag_list_foreach (tag_list, cltr_video_print_tag, NULL); */
}
static void
cltr_video_got_time_tick (GstPlay *play,
gint64 time_nanos,
CltrVideo *video)
{
/*
CltrVideoSignal *signal;
signal = g_new0 (CltrVideoSignal, 1);
signal->signal_id = CLTR_VIDEO_ASYNC_FOUND_TAG;
signal->signal_data.found_tag.source = source;
signal->signal_data.found_tag.tag_list = gst_tag_list_copy (tag_list);
g_async_queue_push (video->queue, signal);
*/
g_print ("time tick %f\n", time_nanos / (float) GST_SECOND);
}
static void
cltr_video_got_stream_length (GstPlay *play,
gint64 length_nanos,
CltrVideo *video)
{
/*
CltrVideoSignal *signal;
signal = g_new0 (CltrVideoSignal, 1);
signal->signal_id = CLTR_VIDEO_ASYNC_VIDEO_SIZE;
signal->signal_data.video_size.width = width;
signal->signal_data.video_size.height = height;
g_async_queue_push (video->queue, signal);
*/
CLTR_DBG ("got length %" G_GUINT64_FORMAT "\n", length_nanos);
length = length_nanos;
}
static void
cltr_video_got_video_size (GstPlay *play,
gint width,
gint height,
CltrVideo *video)
{
CltrVideoSignal *signal;
signal = g_new0 (CltrVideoSignal, 1);
signal->signal_id = CLTR_VIDEO_ASYNC_VIDEO_SIZE;
signal->signal_data.video_size.width = width;
signal->signal_data.video_size.height = height;
g_async_queue_push (video->queue, signal);
}
static void
cltr_video_got_eos (GstPlay* play, CltrVideo *video)
got_eos (GstPlay* play, CltrVideo *video)
{
CLTR_DBG ("End Of Stream\n");
@ -150,60 +94,379 @@ cltr_video_got_eos (GstPlay* play, CltrVideo *video)
gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
}
static gboolean
cltr_video_seek_timer (GstPlay * play)
static void
got_stream_length (GstElement *play,
gint64 length_nanos,
CltrVideo *video)
{
gst_play_seek_to_time (play, length / 2);
return FALSE;
video->stream_length = (gint64) length_nanos / GST_MSECOND;
/* fire off some callback here ? */
CLTR_DBG("length: %i", video->stream_length);
}
static void
caps_set (GObject *obj,
GParamSpec *pspec,
CltrVideo *video)
got_time_tick (GstElement *play,
gint64 time_nanos,
CltrVideo *video)
{
CLTR_MARK();
video->current_time_nanos = time_nanos;
video->current_time = (gint64) time_nanos / GST_MSECOND;
if (video->stream_length == 0)
video->current_position = 0;
else
{
video->current_position = (float) video->current_time / video->stream_length;
}
/* fire off callback here */
}
static void
got_found_tag (GstPlay *play,
GstElement *source,
GstTagList *tag_list,
CltrVideo *video)
{
CltrVideoSignal *signal;
CLTR_MARK();
signal = g_new0 (CltrVideoSignal, 1);
signal->signal_id = CLTR_VIDEO_ASYNC_FOUND_TAG;
signal->signal_data.found_tag.source = source;
signal->signal_data.found_tag.tag_list = gst_tag_list_copy (tag_list);
g_async_queue_push (video->queue, signal);
/* gst_tag_list_foreach (tag_list, cltr_video_print_tag, NULL); */
}
static void
got_state_change (GstElement *play,
GstElementState old_state,
GstElementState new_state,
CltrVideo *video)
{
if (old_state == GST_STATE_PLAYING)
{
if (video->update_id != 0)
{
g_source_remove (video->update_id);
video->update_id = 0;
}
g_idle_remove_by_data (video);
}
else if (new_state == GST_STATE_PLAYING)
{
if (video->update_id != 0)
g_source_remove (video->update_id);
video->update_id = g_timeout_add (200, (GSourceFunc) cb_iterate, video);
g_idle_add((GSourceFunc) cltr_video_idler, video);
}
if (old_state <= GST_STATE_READY && new_state >= GST_STATE_PAUSED)
{
parse_stream_info (video);
}
else if (new_state <= GST_STATE_READY && old_state >= GST_STATE_PAUSED)
{
video->has_video = FALSE;
video->has_audio = FALSE;
/*
if (bvw->priv->tagcache)
{
gst_tag_list_free (bvw->priv->tagcache);
bvw->priv->tagcache = NULL;
}
*/
video->video_width = 0;
video->video_height = 0;
}
}
static void
got_redirect (GstElement *play,
const gchar *new_location,
CltrVideo *bvw)
{
CLTR_MARK();
/*
bvw->priv->got_redirect = TRUE;
signal = g_new0 (BVWSignal, 1);
signal->signal_id = ASYNC_REDIRECT;
signal->signal_data.redirect.new_location = g_strdup (new_location);
g_async_queue_push (bvw->priv->queue, signal);
g_idle_add ((GSourceFunc) bacon_video_widget_signal_idler, bvw);
*/
}
static void
stream_info_set (GObject *obj,
GParamSpec *pspec,
CltrVideo *video)
{
parse_stream_info (video);
/*
signal = g_new0 (BVWSignal, 1);
signal->signal_id = ASYNC_NOTIFY_STREAMINFO;
g_async_queue_push (bvw->priv->queue, signal);
g_idle_add ((GSourceFunc) bacon_video_widget_signal_idler, bvw);
*/
}
static void
got_source (GObject *play,
GParamSpec *pspec,
CltrVideo *video)
{
GObject *source = NULL;
GObjectClass *klass;
CLTR_MARK();
/*
if (bvw->priv->tagcache) {
gst_tag_list_free (bvw->priv->tagcache);
bvw->priv->tagcache = NULL;
}
if (!bvw->priv->media_device)
return;
g_object_get (play, "source", &source, NULL);
if (!source)
return;
klass = G_OBJECT_GET_CLASS (source);
if (!g_object_class_find_property (klass, "device"))
return;
g_object_set (source, "device", bvw->priv->media_device, NULL);
*/
}
static void
got_buffering (GstElement *play,
gint percentage,
CltrVideo *video)
{
CLTR_DBG("Buffering with %i", percentage);
#if 0
BVWSignal *signal;
g_return_if_fail (bvw != NULL);
g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
signal = g_new0 (BVWSignal, 1);
signal->signal_id = ASYNC_BUFFERING;
signal->signal_data.buffering.percent = percentage;
g_async_queue_push (bvw->priv->queue, signal);
g_idle_add ((GSourceFunc) bacon_video_widget_signal_idler, bvw);
#endif
}
static void
got_error (GstElement *play,
GstElement *orig,
GError *error,
gchar *debug,
CltrVideo *video)
{
/*
XXX TODO cpy the error message to asyc queueu
*/
CLTR_MARK();
#if 0
/* since we're opening, we will never enter the mainloop
* until we return, so setting an idle handler doesn't
* help... Anyway, let's prepare a message. */
if (GST_STATE (play) != GST_STATE_PLAYING) {
g_free (bvw->priv->last_error_message);
bvw->priv->last_error_message = g_strdup (error->message);
return;
}
signal = g_new0 (BVWSignal, 1);
signal->signal_id = ASYNC_ERROR;
signal->signal_data.error.element = orig;
signal->signal_data.error.error = g_error_copy (error);
if (debug)
signal->signal_data.error.debug_message = g_strdup (debug);
g_async_queue_push (bvw->priv->queue, signal);
g_idle_add ((GSourceFunc) bacon_video_widget_signal_idler, bvw);
#endif
}
static void
caps_set (GObject *obj,
GParamSpec *pspec,
CltrVideo *video)
{
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) {
if (s)
{
/* const GValue *par; */
if (!(gst_structure_get_double (s, "framerate", &video->video_fps) &&
gst_structure_get_int (s, "width", &video->video_width) &&
gst_structure_get_int (s, "height", &video->video_height)))
return;
const GValue *par;
/*
if ((par = gst_structure_get_value (s, "pixel-aspect-ratio")))
{
gint num = gst_value_get_fraction_numerator (par),
den = gst_value_get_fraction_denominator (par);
if (!(gst_structure_get_double (s, "framerate", &bvw->priv->video_fps) &&
gst_structure_get_int (s, "width", &bvw->priv->video_width) &&
gst_structure_get_int (s, "height", &bvw->priv->video_height)))
return;
if ((par = gst_structure_get_value (s,
"pixel-aspect-ratio"))) {
gint num = gst_value_get_fraction_numerator (par),
den = gst_value_get_fraction_denominator (par);
if (num > den)
bvw->priv->video_width *= (gfloat) num / den;
else
bvw->priv->video_height *= (gfloat) den / num;
}
if (num > den)
bvw->priv->video_width *= (gfloat) num / den;
else
bvw->priv->video_height *= (gfloat) den / num;
}
got_video_size (bvw->priv->play, bvw->priv->video_width,
bvw->priv->video_height, bvw);
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);
}
static void
parse_stream_info (CltrVideo *video)
{
GList *streaminfo = NULL;
GstPad *videopad = NULL;
g_object_get (G_OBJECT (video->play), "stream-info", &streaminfo, NULL);
streaminfo = g_list_copy (streaminfo);
g_list_foreach (streaminfo, (GFunc) g_object_ref, NULL);
for ( ; streaminfo != NULL; streaminfo = streaminfo->next)
{
GObject *info = streaminfo->data;
gint type;
GParamSpec *pspec;
GEnumValue *val;
if (!info)
continue;
g_object_get (info, "type", &type, NULL);
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (info), "type");
val = g_enum_get_value (G_PARAM_SPEC_ENUM (pspec)->enum_class, type);
if (strstr (val->value_name, "AUDIO"))
{
if (!video->has_audio) {
video->has_audio = TRUE;
/*if (!bvw->priv->media_has_video &&
bvw->priv->show_vfx && bvw->priv->vis_element) {
videopad = gst_element_get_pad (bvw->priv->vis_element, "src");
}*/
}
}
else if (strstr (val->value_name, "VIDEO"))
{
video->has_video = TRUE;
if (!videopad)
g_object_get (info, "object", &videopad, NULL);
}
}
if (videopad)
{
GstPad *real = (GstPad *) GST_PAD_REALIZE (videopad);
/* handle explicit caps as well - they're set later */
if (((GstRealPad *) real)->link != NULL && GST_PAD_CAPS (real))
caps_set (G_OBJECT (real), NULL, video);
g_signal_connect (real, "notify::caps", G_CALLBACK (caps_set), video);
}
/*
else if (bvw->priv->show_vfx && bvw->priv->vis_element)
{
fixate_visualization (NULL, NULL, bvw);
}
*/
g_list_foreach (streaminfo, (GFunc) g_object_unref, NULL);
g_list_free (streaminfo);
}
static gboolean
cb_iterate (CltrVideo *video)
{
GstFormat fmt = GST_FORMAT_TIME;
gint64 value;
/* check length/pos of stream */
if (gst_element_query (GST_ELEMENT (video->play),
GST_QUERY_TOTAL, &fmt, &value)
&& GST_CLOCK_TIME_IS_VALID (value)
&& value / GST_MSECOND != video->stream_length)
{
got_stream_length (GST_ELEMENT (video->play), value, video);
}
if (gst_element_query (GST_ELEMENT (video->play),
GST_QUERY_POSITION, &fmt, &value))
{
got_time_tick (GST_ELEMENT (video->play), value, video);
}
return TRUE;
}
CltrWidget*
cltr_video_new(int width, int height)
{
@ -274,15 +537,14 @@ cltr_video_new(int width, int height)
#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_CALLBACK (got_eos), (gpointer) video);
g_signal_connect (G_OBJECT (video->play), "state-change",
G_CALLBACK (got_state_change), (gpointer) video);
g_signal_connect (G_OBJECT (video->play), "found_tag",
G_CALLBACK (got_found_tag), (gpointer) video);
/*
g_signal_connect (G_OBJECT (video->play), "error",
G_CALLBACK (got_error), (gpointer) video);
@ -291,13 +553,18 @@ cltr_video_new(int width, int height)
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);
/* what does this do ?
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 ();
@ -305,76 +572,114 @@ cltr_video_new(int width, int height)
return CLTR_WIDGET(video);
}
#if 0
video->play = gst_play_new (&error);
gboolean
cltr_video_play ( CltrVideo *video, GError ** error)
{
gboolean ret;
if (error)
if (video->last_error_message)
{
g_print ("Error: could not create play object:\n%s\n", error->message);
g_error_free (error);
return NULL;
g_free (video->last_error_message);
video->last_error_message = NULL;
}
/* Getting default audio and video plugins from GConf */
video->vis_element = gst_element_factory_make ("goom", "vis_element");
video->data_src = gst_element_factory_make ("gnomevfssrc", "source");
ret = (gst_element_set_state (GST_ELEMENT (video->play),
GST_STATE_PLAYING) == GST_STATE_SUCCESS);
if (!ret)
{
g_set_error (error, 0, 0, "%s", video->last_error_message ?
video->last_error_message : "Failed to play; reason unknown");
}
video->audio_sink = gst_gconf_get_default_audio_sink ();
return ret;
}
if (!GST_IS_ELEMENT (video->audio_sink))
g_error ("Could not get default audio sink from GConf");
gboolean
cltr_video_seek (CltrVideo *video, float position, GError **gerror)
{
gint64 seek_time, length_nanos;
video->video_sink = gst_element_factory_make ("cltrimagesink", "cltr-output");
/* Resetting last_error_message to NULL */
if (video->last_error_message)
{
g_free (video->last_error_message);
video->last_error_message = NULL;
}
if (!GST_IS_ELEMENT (video->video_sink))
g_error ("Could not get clutter video sink");
length_nanos = (gint64) (video->stream_length * GST_MSECOND);
seek_time = (gint64) (length_nanos * position);
video->queue = g_async_queue_new ();
gst_element_seek (video->play, GST_SEEK_METHOD_SET |
GST_SEEK_FLAG_FLUSH | GST_FORMAT_TIME,
seek_time);
gst_element_set(video->video_sink, "queue", video->queue, NULL);
return TRUE;
}
/* Let's send them to GstPlay object */
gboolean
cltr_video_seek_time (CltrVideo *video, gint64 time, GError **gerror)
{
if (video->last_error_message)
{
g_free (video->last_error_message);
video->last_error_message = NULL;
}
if (!gst_play_set_audio_sink (video->play, video->audio_sink))
g_warning ("Could not set audio sink");
if (!gst_play_set_video_sink (video->play, video->video_sink))
g_warning ("Could not set video sink");
if (!gst_play_set_data_src (video->play, video->data_src))
g_warning ("Could not set data src");
if (!gst_play_set_visualization (video->play, video->vis_element))
g_warning ("Could not set visualisation");
gst_element_seek (video->play, GST_SEEK_METHOD_SET |
GST_SEEK_FLAG_FLUSH | GST_FORMAT_TIME,
time * GST_MSECOND);
/* Setting location we want to play */
return TRUE;
}
/* Uncomment that line to get an XML dump of the pipeline */
/* gst_xml_write_file (GST_ELEMENT (play), stdout); */
void
cltr_video_stop ( CltrVideo *video)
{
gst_element_set_state (GST_ELEMENT (video->play), GST_STATE_READY);
}
g_signal_connect (G_OBJECT (video->play), "time_tick",
G_CALLBACK (cltr_video_got_time_tick), video);
g_signal_connect (G_OBJECT (video->play), "stream_length",
G_CALLBACK (cltr_video_got_stream_length), video);
g_signal_connect (G_OBJECT (video->play), "have_video_size",
G_CALLBACK (cltr_video_got_video_size), video);
g_signal_connect (G_OBJECT (video->play), "found_tag",
G_CALLBACK (cltr_video_got_found_tag), video);
g_signal_connect (G_OBJECT (video->play), "error",
G_CALLBACK (gst_element_default_error), NULL);
g_signal_connect (G_OBJECT (video->play),
"eos", G_CALLBACK (cltr_video_got_eos), video);
void
cltr_video_close ( CltrVideo *video)
{
gst_element_set_state (GST_ELEMENT (video->play), GST_STATE_READY);
g_signal_connect (G_OBJECT (video->video_sink), "notify::caps",
G_CALLBACK (caps_set), video);
/* XX close callback here */
}
#endif
/*
g_object_set (G_OBJECT (video->play), "volume",
(gdouble) (1. * 0 / 100), NULL);
*/
void
cltr_video_pause ( CltrVideo *video)
{
gst_element_set_state (GST_ELEMENT (video->play), GST_STATE_PAUSED);
}
/* gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY); */
return CLTR_WIDGET(video);
gboolean
cltr_video_can_set_volume ( CltrVideo *video )
{
return TRUE;
}
void
cltr_video_set_volume ( CltrVideo *video, int volume)
{
if (cltr_video_can_set_volume (video) != FALSE)
{
volume = CLAMP (volume, 0, 100);
g_object_set (G_OBJECT (video->play), "volume",
(gdouble) (1. * volume / 100), NULL);
}
}
int
cltr_video_get_volume ( CltrVideo *video)
{
gdouble vol;
g_object_get (G_OBJECT (video->play), "volume", &vol, NULL);
return (gint) (vol * 100 + 0.5);
}
@ -434,24 +739,6 @@ cltr_video_set_source(CltrVideo *video, char *location)
return TRUE;
}
void
cltr_video_play(CltrVideo *video)
{
/* Change state to PLAYING */
if (gst_element_set_state (GST_ELEMENT (video->play),
GST_STATE_PLAYING) == GST_STATE_FAILURE)
g_error ("Could not set state to PLAYING");
g_timeout_add(FPS_TO_TIMEOUT(30), (GSourceFunc) cltr_video_idler, video);
}
void
cltr_video_pause(CltrVideo *video)
{
if (gst_element_set_state (GST_ELEMENT (video->play),
GST_STATE_PAUSED) == GST_STATE_FAILURE)
g_error ("Could not set state to PAUSED");
}
static void
@ -482,23 +769,10 @@ 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;
}
int dis_x = 0, dis_y = 0, dis_height = 0, dis_width = 0;
if (video->video_width > video->video_height)
{
@ -509,12 +783,13 @@ cltr_video_paint(CltrWidget *widget)
dis_x = 0;
}
glEnable(GL_BLEND);
glColor4f(1.0, 1.0, 1.0, 1.0);
glEnable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
cltr_texture_lock(video->frame_texture);
@ -528,6 +803,10 @@ cltr_video_paint(CltrWidget *widget)
cltr_texture_unlock(video->frame_texture);
glDisable(GL_TEXTURE_2D);
glColor4f(1.0, 1.0, 1.0, 0.5);
// glRecti(100, 100, 600, 600);
}
glPopMatrix();

View File

@ -66,8 +66,32 @@ cltr_video_new(int width, int height);
gboolean
cltr_video_set_source(CltrVideo *video, char *location);
gboolean
cltr_video_play ( CltrVideo *video, GError ** Error);
gboolean
cltr_video_seek (CltrVideo *video, float position, GError **gerror);
gboolean
cltr_video_seek_time (CltrVideo *video, gint64 time, GError **gerror);
void
cltr_video_play(CltrVideo *video);
cltr_video_stop ( CltrVideo *video);
void
cltr_video_close ( CltrVideo *video);
void
cltr_video_pause ( CltrVideo *video);
gboolean
cltr_video_can_set_volume ( CltrVideo *video );
void
cltr_video_set_volume ( CltrVideo *video, int volume);
int
cltr_video_get_volume ( CltrVideo *video);
#endif

View File

@ -1,8 +1,6 @@
#ifndef _HAVE_CLTR_WIDGET_H
#define _HAVE_CLTR_WIDGET_H
typedef struct CltrWidget CltrWidget;
#include "cltr.h"
#define CLTR_WIDGET(w) ((CltrWidget*)(w))

View File

@ -12,9 +12,15 @@ cltr_window_paint(CltrWidget *widget);
struct CltrWindow
{
CltrWidget widget;
Window xwin;
CltrWidget *focused_child;
CltrWidget widget;
Window xwin;
CltrWidget *focused_child;
CltrCallback *pre_paint_hook, *post_paint_hook;
CltrXEventCallback xevent_cb;
void *xevent_cb_data;
};
void
@ -86,6 +92,10 @@ static void
cltr_window_paint(CltrWidget *widget)
{
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glClearColor( 0.0, 0.0, 0.0, 0.0 ); /* needed for saturate to work */
}
@ -93,7 +103,6 @@ cltr_window_paint(CltrWidget *widget)
static void
cltr_window_handle_xconfigure(CltrWindow *win, XConfigureEvent *cxev)
{
/*
widget.width = cxev->width;
widget.height = cxev->height;
@ -120,7 +129,10 @@ cltr_window_handle_xevent (CltrWidget *widget, XEvent *xev)
/* XXX Very basic - assumes we are only interested in mouse clicks */
if (win->focused_child)
return cltr_widget_handle_xevent(win->focused_child, xev);
cltr_widget_handle_xevent(win->focused_child, xev);
if (win->xevent_cb)
(win->xevent_cb)(widget, xev, win->xevent_cb_data);
return FALSE;
}
@ -157,12 +169,12 @@ cltr_window_set_fullscreen(CltrWindow *win)
}
Window
void
cltr_window_focus_widget(CltrWindow *win, CltrWidget *widget)
{
/* XXX Should check widget is an actual child of the window */
ClutterMainContext *ctx = CLTR_CONTEXT();
/* ClutterMainContext *ctx = CLTR_CONTEXT(); */
if (win->focused_child)
cltr_widget_unfocus(win->focused_child);
@ -172,4 +184,13 @@ cltr_window_focus_widget(CltrWindow *win, CltrWidget *widget)
win->focused_child = widget;
}
void
cltr_window_on_xevent(CltrWindow *win,
CltrXEventCallback callback,
void *userdata)
{
win->xevent_cb = callback;
win->xevent_cb_data = userdata;
}

View File

@ -10,9 +10,6 @@ typedef struct CltrWindow CltrWindow;
CltrWidget*
cltr_window_new(int width, int height);
void
cltr_window_paint(CltrWidget *widget);
void
cltr_window_add_widget(CltrWindow *win, CltrWidget *widget, int x, int y);
@ -24,8 +21,13 @@ cltr_window_xwin(CltrWindow *win);
void
cltr_window_set_fullscreen(CltrWindow *win);
Window
void
cltr_window_focus_widget(CltrWindow *win, CltrWidget *widget);
void
cltr_window_on_xevent(CltrWindow *win,
CltrXEventCallback callback,
void *userdata);
#endif

View File

@ -21,7 +21,6 @@
#include "pixbuf.h"
#include "fonts.h"
typedef enum CltrDirection
{
CLTR_NORTH,
@ -44,6 +43,17 @@ typedef struct CltrTexture CltrTexture;
#define cltr_rect_x2(r) ((r).x + (r).width)
#define cltr_rect_y2(r) ((r).y + (r).height)
typedef struct CltrWidget CltrWidget;
typedef void (*CltrCallback) (CltrWidget *widget, void *userdata) ;
typedef void (*CltrXEventCallback) (CltrWidget *widget,
XEvent *xev,
void *userdata) ;
/* texture stuff */
/* ******************* */

View File

@ -56,6 +56,8 @@ get_layout_bitmap (PangoLayout *layout,
pango_layout_get_extents (layout, &ink_rect, NULL);
printf("%s() gave width:%i, height %i\n", __func__, ink->width, ink->height);
/* XXX why the >> 10 */
ink->x = ink_rect.x >> 10;
ink->width = ((ink_rect.x + ink_rect.width + 1023) >> 10) - ink->x;
@ -170,14 +172,10 @@ 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,
&layout_width, &layout_height);
/* cant rely on just clip - need to set layout width too */
/* cant rely on just clip - need to set layout width too ? */
/* pango_layout_set_width(layout, (pixb->width - x) << 10); */
draw_layout_on_pixbuf (layout, pixb, p, x, y,
x,
@ -202,7 +200,7 @@ font_get_pixel_size (ClutterFont *font,
pango_layout_get_pixel_size (layout, width, height);
printf("gave width:%i, height %i\n", *width, *height);
printf("%s() gave width:%i, height %i\n", __func__, *width, *height);
g_object_unref(G_OBJECT(layout));
}

View File

@ -61,8 +61,8 @@ fi
dnl ----- Pango, glib etc ---------------------------------------------------
pkg_modules="pangoft2 pango glib-2.0 gthread-2.0"
PKG_CHECK_MODULES(CLTR, pangoft2 pango glib-2.0 gthread-2.0)
pkg_modules="pangoft2 glib-2.0 gthread-2.0"
PKG_CHECK_MODULES(CLTR, pangoft2 glib-2.0 gthread-2.0)
dnl ----- Gstreamer ---------------------------------------------------------

View File

@ -55,10 +55,11 @@ photo_grid_populate(gpointer data)
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))

View File

@ -19,6 +19,34 @@
#include <clutter/cltr.h>
int Paused = 0;
void
handle_xevent(CltrWidget *win, XEvent *xev, void *cookie)
{
KeySym kc;
CltrVideo *video = CLTR_VIDEO(cookie);
if (xev->type == KeyPress)
{
XKeyEvent *xkeyev = &xev->xkey;
kc = XKeycodeToKeysym(xkeyev->display, xkeyev->keycode, 0);
switch (kc)
{
case XK_Return:
if (Paused)
cltr_video_play (video, NULL);
else
cltr_video_pause (video);
Paused ^= 1;
break;
}
}
}
int
main (int argc, char *argv[])
{
@ -26,7 +54,7 @@ main (int argc, char *argv[])
CltrFont *font;
PixbufPixel col = { 0xff, 0xff, 0xff, 0x66 };
pixel_set_vals(&col, 0xff, 0x00, 0x00, 0xff);
pixel_set_vals(&col, 0x00, 0x00, 0x00, 0x99);
cltr_init (&argc, &argv);
@ -45,13 +73,15 @@ main (int argc, char *argv[])
cltr_widget_add_child(win, video, 0, 0);
label = cltr_label_new("hello world", font, &col);
// label = cltr_label_new("hello world", font, &col);
cltr_widget_add_child(win, label, 100, 100);
// cltr_widget_add_child(win, label, 100, 300);
cltr_window_on_xevent(CLTR_WINDOW(win), handle_xevent, video);
cltr_widget_show_all(win);
cltr_video_play(CLTR_VIDEO(video));
cltr_video_play(CLTR_VIDEO(video), NULL);
cltr_main_loop();

View File

@ -11,7 +11,7 @@ int
main(int argc, char **argv)
{
int i;
CltrWidget *win = NULL, *grid = NULL, *test = NULL, *test2 = NULL;
CltrWidget *win = NULL, *grid = NULL, *test = NULL, *test2 = NULL, *list;
CltrFont *font = NULL;
PixbufPixel col = { 0xff, 0, 0, 0xff };
@ -53,24 +53,23 @@ main(int argc, char **argv)
if (want_fullscreen)
cltr_window_set_fullscreen(CLTR_WINDOW(win));
font = font_new("Sans 20");
font = font_new("Sans Bold 11");
test = cltr_button_new_with_label("ButtonBoooo\ndsfdsfdsf sss\nsjhsjhsjhs", font, &col);
test = cltr_button_new_with_label("ButtonBoooo\nd sfdsfdsfsss\nsjhsjhsjhs", font, &col);
test2 = cltr_button_new_with_label("Button", font, &col);
test2 = cltr_button_new_with_label("One Two", font, &col);
cltr_widget_add_child(win, test, 300, 100);
cltr_widget_add_child(win, test2, 100, 100);
cltr_window_focus_widget(CLTR_WINDOW(win), test);
cltr_window_focus_widget(CLTR_WINDOW(win), test2);
cltr_widget_set_focus_next(test, test2, CLTR_EAST);
cltr_widget_set_focus_next(test, test2, CLTR_WEST);
cltr_widget_set_focus_next(test2, test, CLTR_EAST);
cltr_widget_set_focus_next(test2, test, CLTR_WEST);
/*
test = cltr_scratch_new(300, 100);
test2 = cltr_scratch_new(150, 150);
@ -83,12 +82,13 @@ main(int argc, char **argv)
/*
cltr_widget_add_child(win, test, 320, 240);
cltr_widget_add_child(win, test2, 400, 300);
*/
list = cltr_list_new(640,480,640, 160);
cltr_widget_add_child(win, list, 0, 0);
*/
cltr_window_focus_widget(CLTR_WINDOW(win), list);
cltr_widget_show_all(win);