[Xfce4-commits] [apps/parole] 01/02: Separate clutter into its own source

noreply at xfce.org noreply at xfce.org
Wed Jun 18 06:37:35 CEST 2014


This is an automated email from the git hooks/post-receive script.

bluesabre pushed a commit to branch master
in repository apps/parole.

commit 8072b2c8c042fc4d7c47c83b203f2c14d013ae0a
Author: Sean Davis <smd.seandavis at gmail.com>
Date:   Tue Jun 17 23:32:31 2014 -0400

    Separate clutter into its own source
---
 src/Makefile.am      |    2 +
 src/gst/parole-gst.c |   20 +--
 src/parole-clutter.c |  359 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/parole-clutter.h |   47 +++++++
 src/parole-player.c  |   59 +++------
 5 files changed, 434 insertions(+), 53 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index d9646bb..a0955f7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -52,6 +52,8 @@ parole_SOURCES =				\
 	parole-medialist.h			\
 	parole-mediachooser.c			\
 	parole-mediachooser.h			\
+	parole-clutter.c			\
+	parole-clutter.h			\
 	parole-conf.c				\
 	parole-conf.h				\
 	parole-conf-dialog.c			\
diff --git a/src/gst/parole-gst.c b/src/gst/parole-gst.c
index 08d94db..bcea70b 100644
--- a/src/gst/parole-gst.c
+++ b/src/gst/parole-gst.c
@@ -2218,6 +2218,7 @@ parole_gst_constructed (GObject *object)
     ParoleGst *gst;
 
     gchar *videosink = NULL;
+    gchar *playbin = NULL;
 
     gst = PAROLE_GST (object);
 
@@ -2226,29 +2227,29 @@ parole_gst_constructed (GObject *object)
                   NULL);
 
 #if GST_CHECK_VERSION(1, 0, 0)
-    gst->priv->playbin = gst_element_factory_make ("playbin", "player");
+    playbin = g_strdup("playbin");
 #else
-    gst->priv->playbin = gst_element_factory_make ("playbin2", "player");
+    playbin = g_strdup("playbin2");
 #endif
 
+    /* Configure the playbin */
+    gst->priv->playbin = gst_element_factory_make (playbin, "player");
     if ( G_UNLIKELY (gst->priv->playbin == NULL) )
     {
         GError *error;
 
         error = g_error_new (1, 0, _("Unable to load \"%s\" plugin"
                                      ", check your GStreamer installation."),
-#if GST_CHECK_VERSION(1, 0, 0)
-                                     "playbin");
-#else
-                                     "playbin2");
-#endif
+                                     playbin);
 
         parole_gst_show_error (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (gst))),
                                 error);
         g_error_free (error);
         g_error ("playbin load failed");
     }
+    g_free(playbin);
 
+    /* Configure the audio sink */
     gst->priv->audio_sink = gst_element_factory_make ("autoaudiosink", "audio");
     if ( G_UNLIKELY (gst->priv->audio_sink == NULL) )
     {
@@ -2261,16 +2262,17 @@ parole_gst_constructed (GObject *object)
         g_error ("autoaudiosink load failed");
     }
 
+    /* Configure the video sink */
     if (g_strcmp0(videosink, "xvimagesink") == 0)
     {
-        gst->priv->video_sink = gst_element_factory_make ("xvimagesink", "video");
         gst->priv->image_sink = XVIMAGESINK;
+        gst->priv->video_sink = gst_element_factory_make ("xvimagesink", "video");
     }
 
     if (g_strcmp0(videosink, "cluttersink") == 0)
     {
-        gst->priv->video_sink = gst_element_factory_make ("cluttersink", "video");
         gst->priv->image_sink = CLUTTERSINK;
+        gst->priv->video_sink = gst_element_factory_make ("cluttersink", "video");
     }
 
     if ( G_UNLIKELY (gst->priv->video_sink == NULL) )
diff --git a/src/parole-clutter.c b/src/parole-clutter.c
new file mode 100644
index 0000000..6e6416f
--- /dev/null
+++ b/src/parole-clutter.c
@@ -0,0 +1,359 @@
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <gdk/gdkx.h>
+
+#include <clutter/clutter.h>
+#include <clutter-gtk/clutter-gtk.h>
+
+#include <gst/video/video.h>
+
+#include <libxfce4util/libxfce4util.h>
+
+#include "gst/gst-enum-types.h"
+#include "parole-gst.h"
+#include "parole-clutter.h"
+
+#define PAROLE_CLUTTER_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_CLUTTER, ParoleClutterPrivate))
+
+struct ParoleClutterPrivate
+{
+    GtkWidget          *embed;
+
+    ClutterActor       *stage;
+    ClutterActor       *texture;
+
+    ParoleAspectRatio   aspect_ratio;
+
+    gpointer            conf;
+
+    gint                video_w;
+    gint                video_h;
+};
+
+enum
+{
+    PROP_0,
+    PROP_CONF_OBJ
+};
+
+static gpointer parole_clutter_object = NULL;
+
+G_DEFINE_TYPE (ParoleClutter, parole_clutter, GTK_TYPE_WIDGET)
+
+static void
+parole_clutter_finalize (GObject *object)
+{
+    //ParoleClutter *clutter;
+
+    //clutter = PAROLE_CLUTTER (object);
+
+    TRACE ("start");
+
+    G_OBJECT_CLASS (parole_clutter_parent_class)->finalize (object);
+}
+
+static void
+parole_clutter_show (GtkWidget *widget)
+{
+    if ( gtk_widget_get_window(widget) )
+        gdk_window_show (gtk_widget_get_window(widget));
+
+    if ( GTK_WIDGET_CLASS (parole_clutter_parent_class)->show )
+        GTK_WIDGET_CLASS (parole_clutter_parent_class)->show (widget);
+}
+
+static void
+parole_clutter_constructed (GObject *object)
+{
+    //ParoleClutter *clutter;
+
+    //clutter = PAROLE_CLUTTER (object);
+}
+
+static void
+parole_clutter_get_video_output_size (ParoleClutter *clutter, gint *ret_w, gint *ret_h)
+{
+    guint video_w, video_h;
+    guint video_par_n, video_par_d;
+    guint dar_n, dar_d;
+    guint disp_par_n, disp_par_d;
+    /*
+     * TODO: FIX Aspect Ratios following change
+     */
+    GtkAllocation *allocation = g_new0 (GtkAllocation, 1);
+    gtk_widget_get_allocation(GTK_WIDGET(clutter->priv->embed), allocation);
+    *ret_w = allocation->width;
+    *ret_h = allocation->height;
+    g_free(allocation);
+
+    disp_par_n = 1;
+    disp_par_d = 1;
+
+    video_w = clutter->priv->video_w;
+    video_h = clutter->priv->video_h;
+
+    if ( video_w != 0 && video_h != 0 )
+    {
+        switch ( clutter->priv->aspect_ratio )
+        {
+            case PAROLE_ASPECT_RATIO_NONE:
+                return;
+            case PAROLE_ASPECT_RATIO_AUTO:
+                *ret_w = video_w;
+                *ret_h = video_h;
+                return;
+            case PAROLE_ASPECT_RATIO_SQUARE:
+                video_par_n = 1;
+                video_par_d = 1;
+                break;
+            case PAROLE_ASPECT_RATIO_16_9:
+                video_par_n = 16 * video_h;
+                video_par_d = 9 * video_w;
+                break;
+            case PAROLE_ASPECT_RATIO_4_3:
+                video_par_n = 4 * video_h;
+                video_par_d = 3 * video_w;
+                break;
+            case PAROLE_ASPECT_RATIO_DVB:
+                video_par_n = 20 * video_h;
+                video_par_d = 9 * video_w;
+                break;
+            default:
+                return;
+        }
+
+        if ( gst_video_calculate_display_ratio (&dar_n, &dar_d,
+                                                video_w, video_h,
+                                                video_par_n, video_par_d,
+                                                disp_par_n, disp_par_d) )
+        {
+            if (video_w % dar_n == 0)
+            {
+                *ret_w = video_w;
+                *ret_h = (guint) gst_util_uint64_scale (video_w, dar_d, dar_n);
+            }
+            else
+            {
+                *ret_w = (guint) gst_util_uint64_scale (video_h, dar_n, dar_d);
+                *ret_h = video_h;
+            }
+            TRACE ("Got best video size %dx%d fraction, %d/%d\n", *ret_w, *ret_h, disp_par_n, disp_par_d);
+        }
+    }
+}
+
+static void
+parole_clutter_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
+{
+    ParoleClutter *clutter;
+
+    g_return_if_fail (allocation != NULL);
+
+    gtk_widget_set_allocation(widget, allocation);
+
+    if ( gtk_widget_get_realized (widget) )
+    {
+        gint w, h;
+        gdouble ratio, width, height;
+
+        clutter = PAROLE_CLUTTER(parole_clutter_get());
+
+        w = allocation->width;
+        h = allocation->height;
+
+        clutter_actor_set_size (clutter->priv->stage, w, h);
+
+        parole_clutter_get_video_output_size (clutter, &w, &h);
+
+        width = w;
+        height = h;
+
+        if ( (gdouble) allocation->width / width > allocation->height / height)
+            ratio = (gdouble) allocation->height / height;
+        else
+            ratio = (gdouble) allocation->width / width;
+
+        width *= ratio;
+        height *= ratio;
+
+        clutter_actor_set_size (clutter->priv->texture, width, height);
+        clutter_actor_set_x (clutter->priv->texture, (allocation->width - width)/2);
+        clutter_actor_set_y (clutter->priv->texture, (allocation->height - height)/2);
+
+        gtk_widget_queue_draw (widget);
+    }
+}
+
+static void
+parole_clutter_conf_notify_cb (GObject *object, GParamSpec *spec, ParoleClutter *clutter)
+{
+    GtkAllocation *allocation = g_new0 (GtkAllocation, 1);
+    if ( !g_strcmp0 ("aspect-ratio", spec->name) )
+    {
+        g_object_get (G_OBJECT (clutter->priv->conf),
+                      "aspect-ratio", &clutter->priv->aspect_ratio,
+                      NULL);
+
+        gtk_widget_get_allocation( GTK_WIDGET (clutter), allocation );
+        parole_clutter_size_allocate (GTK_WIDGET (clutter->priv->embed), allocation);
+        g_free(allocation);
+    }
+}
+
+static void parole_clutter_get_property    (GObject *object,
+                                        guint prop_id,
+                                        GValue *value,
+                                        GParamSpec *pspec)
+{
+    ParoleClutter *clutter;
+    clutter = PAROLE_CLUTTER (object);
+
+    switch (prop_id)
+    {
+        case PROP_CONF_OBJ:
+            g_value_set_pointer (value, clutter->priv->conf);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void parole_clutter_set_property    (GObject *object,
+                                            guint prop_id,
+                                            const GValue *value,
+                                            GParamSpec *pspec)
+{
+    ParoleClutter *clutter;
+    clutter = PAROLE_CLUTTER (object);
+
+    switch (prop_id)
+    {
+        case PROP_CONF_OBJ:
+            clutter->priv->conf = g_value_get_pointer (value);
+
+            if (clutter->priv->conf)
+            {
+                g_object_get (G_OBJECT (clutter->priv->conf),
+                              "aspect-ratio", &clutter->priv->aspect_ratio,
+                              NULL);
+
+                g_signal_connect (G_OBJECT (clutter->priv->conf), "notify",
+                G_CALLBACK (parole_clutter_conf_notify_cb), clutter);
+            }
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+parole_clutter_class_init (ParoleClutterClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+    object_class->finalize = parole_clutter_finalize;
+    object_class->constructed = parole_clutter_constructed;
+
+    object_class->set_property = parole_clutter_set_property;
+    object_class->get_property = parole_clutter_get_property;
+
+    widget_class->show = parole_clutter_show;
+    
+    g_object_class_install_property    (object_class,
+                                        PROP_CONF_OBJ,
+                                        g_param_spec_pointer ("conf-object",
+                                        NULL, NULL,
+                                        G_PARAM_CONSTRUCT_ONLY|
+                                        G_PARAM_READWRITE));
+
+    g_type_class_add_private (klass, sizeof (ParoleClutterPrivate));
+}
+
+static void
+parole_clutter_init (ParoleClutter *clutter)
+{
+    ClutterColor *black;
+    GValue value = {0};
+
+    clutter->priv = PAROLE_CLUTTER_GET_PRIVATE (clutter);
+
+    g_value_init(&value, G_TYPE_BOOLEAN);
+    g_value_set_boolean(&value, TRUE);
+
+    black = clutter_color_new(0,0,0,255);
+
+    clutter->priv->embed = gtk_clutter_embed_new();
+    g_signal_connect (G_OBJECT(clutter->priv->embed), "size-allocate",
+                      G_CALLBACK(parole_clutter_size_allocate), NULL);
+
+    /* Configure the Stage */
+    clutter->priv->stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (clutter->priv->embed));
+    clutter_actor_set_background_color(clutter->priv->stage, black);
+
+    /* Configure the Texture */
+    clutter->priv->texture = CLUTTER_ACTOR (g_object_new (CLUTTER_TYPE_TEXTURE, "disable-slicing", TRUE, NULL));
+    clutter_actor_set_x_align(clutter->priv->texture, CLUTTER_ACTOR_ALIGN_CENTER);
+    clutter_actor_set_y_align(clutter->priv->texture, CLUTTER_ACTOR_ALIGN_CENTER);
+    g_object_set_property (G_OBJECT(clutter->priv->texture), "keep-aspect-ratio", &value);
+    clutter_actor_add_child (clutter->priv->stage, clutter->priv->texture);
+
+    gtk_widget_set_can_focus (GTK_WIDGET (clutter), TRUE);
+
+    /*
+     * Disable double buffering on the video output to avoid
+     * flickering when resizing the window.
+     */
+    gtk_widget_set_double_buffered (GTK_WIDGET (clutter), FALSE);
+}
+
+GtkWidget *
+parole_clutter_new (gpointer conf_obj)
+{
+    parole_clutter_object = g_object_new (PAROLE_TYPE_CLUTTER,
+                                          "conf-object", conf_obj,
+                                          NULL);
+
+    g_object_add_weak_pointer (parole_clutter_object, &parole_clutter_object);
+
+    return GTK_WIDGET (parole_clutter_object);
+}
+
+GtkWidget *parole_clutter_get (void)
+{
+    if ( G_LIKELY (parole_clutter_object != NULL ) )
+    {
+    /*
+     * Don't increase the reference count of this object as
+     * we need it to be destroyed immediately when the main
+     * window is destroyed.
+     */
+    }
+    else
+    {
+        parole_clutter_object = g_object_new (PAROLE_TYPE_CLUTTER, NULL);
+        g_object_add_weak_pointer (parole_clutter_object, &parole_clutter_object);
+    }
+
+    return GTK_WIDGET (parole_clutter_object);
+
+}
+
+void parole_clutter_set_video_dimensions (ParoleClutter *clutter, gint w, gint h)
+{
+    clutter->priv->video_w = w;
+    clutter->priv->video_h = h;
+}
+
+ClutterActor *parole_clutter_get_texture (ParoleClutter *clutter)
+{
+    return clutter->priv->texture;
+}
+
+GtkWidget *parole_clutter_get_embed_widget (ParoleClutter *clutter)
+{
+    return clutter->priv->embed;
+}
diff --git a/src/parole-clutter.h b/src/parole-clutter.h
new file mode 100644
index 0000000..b15fbc4
--- /dev/null
+++ b/src/parole-clutter.h
@@ -0,0 +1,47 @@
+
+#ifndef __PAROLE_CLUTTER_H
+#define __PAROLE_CLUTTER_H
+
+#include <glib-object.h>
+#include <gst/gst.h>
+#include <gtk/gtk.h>
+
+#include <clutter/clutter.h>
+#include <clutter-gtk/clutter-gtk.h>
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_CLUTTER        (parole_clutter_get_type () )
+#define PAROLE_CLUTTER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_CLUTTER, ParoleClutter))
+#define PAROLE_IS_CLUTTER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_CLUTTER))
+
+typedef struct ParoleClutterPrivate ParoleClutterPrivate;
+
+typedef struct
+{
+    GtkWidget               parent;
+    ParoleClutterPrivate   *priv;
+
+} ParoleClutter;
+
+typedef struct
+{
+    GtkWidgetClass  parent_class;
+
+} ParoleClutterClass;
+
+GType         parole_clutter_get_type         (void) G_GNUC_CONST;
+GtkWidget    *parole_clutter_new              (gpointer conf_obj);
+GtkWidget    *parole_clutter_get              (void);
+GtkWidget    *parole_clutter_get_embed_widget (ParoleClutter *clutter);
+
+ClutterActor *parole_clutter_get_texture      (ParoleClutter *clutter);
+
+void
+parole_clutter_set_video_dimensions           (ParoleClutter *clutter,
+                                               gint w,
+                                               gint h);
+
+G_END_DECLS
+
+#endif /* __PAROLE_CLUTTER_H */
diff --git a/src/parole-player.c b/src/parole-player.c
index 1e42918..22fd430 100644
--- a/src/parole-player.c
+++ b/src/parole-player.c
@@ -70,6 +70,7 @@
 #include "parole-button.h"
 #include "enum-gtypes.h"
 #include "parole-debug.h"
+#include "parole-clutter.h"
 
 #include "gst/gst-enum-types.h"
 
@@ -437,8 +438,7 @@ struct ParolePlayerPrivate
     gboolean            buffering;
     gboolean            wait_for_gst_disc_info;
 
-    ClutterActor       *stage;
-    ClutterActor       *texture;
+    GtkWidget          *clutter;
 
     /* Actions */
     GSimpleAction      *media_next_action;
@@ -1382,6 +1382,7 @@ parole_player_playing (ParolePlayer *player, const ParoleStream *stream)
     gint64 duration;
     gboolean seekable;
     gboolean live;
+    gint height, width;
 
     int hide_controls_timeout;
 
@@ -1390,9 +1391,13 @@ parole_player_playing (ParolePlayer *player, const ParoleStream *stream)
     g_object_get (G_OBJECT (stream),
                   "seekable", &seekable,
                   "duration", &duration,
+                  "video-width", &width,
+                  "video-height", &height,
                   "live", &live,
                   NULL);
 
+    parole_clutter_set_video_dimensions (PAROLE_CLUTTER(player->priv->clutter), width, height);
+
     if (player->priv->wait_for_gst_disc_info == TRUE)
     {
         parole_media_list_add_cdda_tracks(player->priv->list, parole_gst_get_num_tracks(PAROLE_GST (player->priv->gst)));
@@ -2924,8 +2929,6 @@ gboolean
 parole_player_configure_event_cb (GtkWidget *widget, GdkEventConfigure *ev, ParolePlayer *player)
 {
     gint old_w, old_h, new_w, new_h;
-    gfloat clutter_width, clutter_height, x, y;
-    GtkAllocation *alloc = g_new(GtkAllocation, 1);
 
     /* Get the current window size */
     gtk_window_get_size (GTK_WINDOW (widget), &new_w, &new_h);
@@ -2950,32 +2953,6 @@ parole_player_configure_event_cb (GtkWidget *widget, GdkEventConfigure *ev, Paro
         }
     }
 
-    gtk_widget_get_allocation(player->priv->videobox, alloc);
-    clutter_actor_set_size (player->priv->stage, alloc->width, alloc->height);
-
-    parole_gst_get_video_output_size_from_dimensions (PAROLE_GST(player->priv->gst), alloc->width, alloc->height, &new_w, &new_h);
-
-    x = 0.0;
-    y = 0.0;
-
-    if ( ((gdouble)alloc->width / (gdouble)new_w) * (gdouble)new_h <= (gdouble)alloc->height )
-    {
-        clutter_height = ((gdouble)alloc->width / (gdouble)new_w) * (gdouble)new_h;
-        clutter_width = alloc->width;
-        y = (alloc->height - clutter_height) / 2.0;
-    }
-
-    else
-    {
-        clutter_width = (((gdouble)alloc->height / (gdouble)new_h) * (gdouble)new_w);
-        clutter_height = alloc->height;
-        x = (alloc->width - clutter_width) / 2.0;
-    }
-
-    clutter_actor_set_size (player->priv->texture, clutter_width, clutter_height);
-    clutter_actor_set_x(player->priv->texture, x);
-    clutter_actor_set_y(player->priv->texture, y);
-
     return FALSE;
 }
 
@@ -3574,26 +3551,20 @@ parole_player_init (ParolePlayer *player)
     {
         GtkWidget *clutterbox;
         GstElement *video_sink;
-        ClutterColor *color = clutter_color_new(0,0,0,255);
-        GValue value = {0};
-        g_value_init(&value, G_TYPE_BOOLEAN);
-        g_value_set_boolean(&value, TRUE);
+        ClutterActor *texture;
+
+        player->priv->clutter = parole_clutter_new(player->priv->conf);
+        clutterbox = parole_clutter_get_embed_widget(PAROLE_CLUTTER(player->priv->clutter));
+        texture = parole_clutter_get_texture (PAROLE_CLUTTER(player->priv->clutter));
 
-        clutterbox = gtk_clutter_embed_new();
         gtk_box_pack_start (GTK_BOX (player->priv->videobox),
                                      clutterbox,
                                      TRUE, TRUE, 0);
-        player->priv->stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (clutterbox));
-        clutter_actor_set_background_color(player->priv->stage, color);
-        player->priv->texture = CLUTTER_ACTOR (g_object_new (CLUTTER_TYPE_TEXTURE, "disable-slicing", TRUE, NULL));
-        clutter_actor_set_x_align(player->priv->texture, CLUTTER_ACTOR_ALIGN_CENTER);
-        clutter_actor_set_y_align(player->priv->texture, CLUTTER_ACTOR_ALIGN_CENTER);
-        g_object_set_property (G_OBJECT(player->priv->texture), "keep-aspect-ratio", &value);
+
         video_sink = parole_gst_video_sink (PAROLE_GST(player->priv->gst));
-        g_object_set (video_sink, "texture", player->priv->texture, NULL);
-        clutter_actor_add_child (player->priv->stage, player->priv->texture);
+        g_object_set (video_sink, "texture", texture, NULL);
+
         gtk_widget_show (clutterbox);
-        g_object_set_property (G_OBJECT(player->priv->texture), "keep-aspect-ratio", &value);
     }
     else
     {

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list