Video widget updates
authorMatthew Allum <mallum@openedhand.com>
Fri, 6 May 2005 17:41:15 +0000 (17:41 +0000)
committerMatthew Allum <mallum@openedhand.com>
Fri, 6 May 2005 17:41:15 +0000 (17:41 +0000)
15 files changed:
ChangeLog
clutter/cltr-button.c
clutter/cltr-overlay.c
clutter/cltr-photo-grid.c
clutter/cltr-video.c
clutter/cltr-video.h
clutter/cltr-widget.h
clutter/cltr-window.c
clutter/cltr-window.h
clutter/cltr.h
clutter/fonts.c
configure.ac
examples/photos.c
examples/player.c
examples/scratch.c

index d868a7e..4472d82 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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),
index be8ea02..d230195 100644 (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)
 {
index 077a7bd..5865900 100644 (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);
 
 }
index cb836a0..fa6a435 100644 (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,27 +677,47 @@ 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;
 
index 33565ac..c55be0f 100644 (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,150 +79,393 @@ cltr_video_print_tag (const GstTagList *list,
 }
 
 static void
-cltr_video_got_found_tag (GstPlay    *play, 
-                         GstElement *source, 
-                         GstTagList *tag_list,
-                         CltrVideo  *video)
+got_eos (GstPlay* play, CltrVideo *video)
 {
+  CLTR_DBG ("End Of Stream\n");
+
   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);
+
+  signal->signal_id = CLTR_VIDEO_ASYNC_EOS;
 
   g_async_queue_push (video->queue, signal);
 
-  /* gst_tag_list_foreach (tag_list, cltr_video_print_tag, NULL); */
+  gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
 }
 
 static void
-cltr_video_got_time_tick (GstPlay   *play, 
-                         gint64     time_nanos,
-                         CltrVideo *video)
+got_stream_length (GstElement *play, 
+                  gint64      length_nanos,
+                   CltrVideo  *video)
 {
+  video->stream_length = (gint64) length_nanos / GST_MSECOND;
 
+  /* fire off some callback here ? */
 
-  /*
+  CLTR_DBG("length: %i", video->stream_length);
+}
+
+static void
+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);
-  */
 
-  g_print ("time tick %f\n", time_nanos / (float) GST_SECOND); 
+  /* 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
-cltr_video_got_stream_length (GstPlay   *play, 
-                             gint64     length_nanos,
-                             CltrVideo *video)
+got_redirect (GstElement  *play, 
+             const gchar *new_location,
+             CltrVideo   *bvw)
 {
+  CLTR_MARK();
+
   /*
-  CltrVideoSignal *signal;
+  bvw->priv->got_redirect = TRUE;
 
-  signal = g_new0 (CltrVideoSignal, 1);
+  signal = g_new0 (BVWSignal, 1);
+  signal->signal_id = ASYNC_REDIRECT;
+  signal->signal_data.redirect.new_location = g_strdup (new_location);
 
-  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 (bvw->priv->queue, signal);
 
-  g_async_queue_push (video->queue, signal);
+  g_idle_add ((GSourceFunc) bacon_video_widget_signal_idler, bvw);
   */
-  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)
+stream_info_set (GObject    *obj, 
+                GParamSpec *pspec, 
+                CltrVideo  *video)
 {
-  CltrVideoSignal *signal;
 
-  signal = g_new0 (CltrVideoSignal, 1);
+  parse_stream_info (video);
 
-  signal->signal_id = CLTR_VIDEO_ASYNC_VIDEO_SIZE;
-  signal->signal_data.video_size.width = width;
-  signal->signal_data.video_size.height = height;
+  /*
+  signal = g_new0 (BVWSignal, 1);
+  signal->signal_id = ASYNC_NOTIFY_STREAMINFO;
 
-  g_async_queue_push (video->queue, signal);
+  g_async_queue_push (bvw->priv->queue, signal);
+
+  g_idle_add ((GSourceFunc) bacon_video_widget_signal_idler, bvw);
+  */
 }
 
 static void
-cltr_video_got_eos (GstPlay* play, CltrVideo *video)
+got_source (GObject    *play,
+           GParamSpec *pspec,
+           CltrVideo  *video)
 {
-  CLTR_DBG ("End Of Stream\n");
+  GObject      *source = NULL;
+  GObjectClass *klass;
 
-  CltrVideoSignal *signal;
+  CLTR_MARK();
 
-  signal = g_new0 (CltrVideoSignal, 1);
+  /*
+  if (bvw->priv->tagcache) {
+    gst_tag_list_free (bvw->priv->tagcache);
+    bvw->priv->tagcache = NULL;
+  }
 
-  signal->signal_id = CLTR_VIDEO_ASYNC_EOS;
+  if (!bvw->priv->media_device)
+    return;
 
-  g_async_queue_push (video->queue, signal);
+  g_object_get (play, "source", &source, NULL);
+  if (!source)
+    return;
 
-  gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
+  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 gboolean
-cltr_video_seek_timer (GstPlay * play)
+
+static void
+got_buffering (GstElement *play, 
+              gint        percentage,
+              CltrVideo  *video)
 {
-  gst_play_seek_to_time (play, length / 2);
-  return FALSE;
+  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
-caps_set (GObject    *obj,
-         GParamSpec *pspec, 
-         CltrVideo  *video)
+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) 
+    {
+      /* const GValue *par; */
 
-  s = gst_caps_get_structure (GST_PAD_CAPS (pad), 0);
+      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;
+
+      /*
+      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;
+       }
+
+       got_video_size (bvw->priv->play, bvw->priv->video_width,
+       bvw->priv->video_height, bvw);
 
-  if (s) {
+      */
+  }
+}
+
+
+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);
 
-    const GValue *par;
+  g_list_foreach (streaminfo, (GFunc) g_object_ref, NULL);
 
-    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);
+  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");
 
-      if (num > den)
-        bvw->priv->video_width *= (gfloat) num / den;
-      else
-        bvw->priv->video_height *= (gfloat) den / num;
+      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);
+
+      }
     }
 
-    got_video_size (bvw->priv->play, bvw->priv->video_width,
-                   bvw->priv->video_height, bvw);
+  if (videopad) 
+    {
+      GstPad *real = (GstPad *) GST_PAD_REALIZE (videopad);
 
-  }
-#endif
-  
-  /* and disable ourselves */
-  //g_signal_handlers_disconnect_by_func (pad, caps_set, bvw);
+      /* 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_CALLBACK (got_eos), (gpointer) video);
+
   g_signal_connect (G_OBJECT (video->play), "state-change",
-                   G_CALLBACK (state_change), (gpointer) video);
-  */
+                   G_CALLBACK (got_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_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;
+}
+
+void
+cltr_video_stop ( CltrVideo *video)
+{
+  gst_element_set_state (GST_ELEMENT (video->play), GST_STATE_READY);
+}
 
-  /* Uncomment that line to get an XML dump of the pipeline */
-  /* gst_xml_write_file (GST_ELEMENT (play), stdout);  */
+void
+cltr_video_close ( CltrVideo *video)
+{
+  gst_element_set_state (GST_ELEMENT (video->play), GST_STATE_READY);
+  
+  /* XX close callback here */
+}
 
-  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_pause ( CltrVideo *video)
+{
+  gst_element_set_state (GST_ELEMENT (video->play), GST_STATE_PAUSED);
+}
 
-  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_can_set_volume ( CltrVideo *video )
+{
+  return TRUE;
+}
 
-  /* gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY); */
+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);
+  }
+}
 
-  return CLTR_WIDGET(video);
+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();
index c5da08e..165af52 100644 (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_stop ( CltrVideo *video);
+
 void
-cltr_video_play(CltrVideo *video);
+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
index 87e7856..c7bb377 100644 (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))
index 27036cf..38667f9 100644 (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;
+}
+
 
index d3ff82a..46c16b7 100644 (file)
@@ -11,9 +11,6 @@ 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);
 
 /* win only methods */
@@ -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
index bc872a7..5ba2955 100644 (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 */
 
 /* ******************* */
index 8806955..f3b265f 100644 (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));
 }
index e1e6742..c6688f3 100644 (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 ---------------------------------------------------------
 
index f088a8f..261cb21 100644 (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))
index 77f6a15..0c6b62f 100644 (file)
 
 #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, 300);  
 
-  cltr_widget_add_child(win, label, 100, 100);  
+  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();
 
index d89111d..49606ba 100644 (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);