[byzanz] Add API for automatic encoder selection and use it



commit d67fef4789e98480269e785fdfe28e3a47449175
Author: Benjamin Otte <otte gnome org>
Date:   Thu Aug 27 15:32:29 2009 +0200

    Add API for automatic encoder selection and use it
    
    There's no encoder implemented yet, but who cares!

 src/byzanzapplet.c     |   34 ++++++++-
 src/byzanzencoder.c    |  195 ++++++++++++++++++++++++++++++++++++++++++++++--
 src/byzanzencoder.h    |   15 ++++-
 src/byzanzencodergif.c |    9 ++-
 src/byzanzsession.c    |   23 +++++-
 src/byzanzsession.h    |    2 +
 src/record.c           |    4 +-
 7 files changed, 263 insertions(+), 19 deletions(-)
---
diff --git a/src/byzanzapplet.c b/src/byzanzapplet.c
index 3979b7b..1206f3e 100644
--- a/src/byzanzapplet.c
+++ b/src/byzanzapplet.c
@@ -27,12 +27,14 @@
 #include <gio/gio.h>
 #include <glib/gstdio.h>
 #include <panel-applet-gconf.h>
-#include "byzanzsession.h"
-#include "byzanzselect.h"
 #include "paneltogglebutton.h"
 #include "paneldropdown.h"
 #include <glib/gi18n.h>
 
+#include "byzanzencoder.h"
+#include "byzanzselect.h"
+#include "byzanzsession.h"
+
 static GQuark index_quark = 0;
 
 typedef struct {
@@ -158,6 +160,8 @@ panel_applet_start_response (GtkWidget *dialog, int response, AppletPrivate *pri
   guint i;
   GdkWindow *window;
   GdkRectangle area;
+  GType encoder_type;
+  GtkFileFilter *filter;
 
   file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
   if (file == NULL)
@@ -175,6 +179,14 @@ panel_applet_start_response (GtkWidget *dialog, int response, AppletPrivate *pri
   if (i >= byzanz_select_get_method_count ())
     goto out;
 
+  filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (priv->dialog));
+  if (filter && gtk_file_filter_get_needed (filter) != 0) {
+    encoder_type = byzanz_encoder_get_type_from_filter (filter);
+  } else {
+    /* It's the "All files" filter */
+    encoder_type = byzanz_encoder_get_type_from_file (file);
+  }
+
   gtk_widget_destroy (dialog);
   priv->dialog = NULL;
   byzanz_applet_update (priv);
@@ -183,7 +195,7 @@ panel_applet_start_response (GtkWidget *dialog, int response, AppletPrivate *pri
   if (window == NULL)
     goto out2;
 
-  priv->rec = byzanz_session_new (file, window, &area, TRUE);
+  priv->rec = byzanz_session_new (file, encoder_type, window, &area, TRUE);
   g_signal_connect_swapped (priv->rec, "notify", G_CALLBACK (byzanz_applet_session_notify), priv);
   
   byzanz_session_start (priv->rec);
@@ -212,6 +224,9 @@ byzanz_applet_start_recording (AppletPrivate *priv)
   if (priv->dialog == NULL) {
     char *uri;
     guint i;
+    GType type;
+    ByzanzEncoderIter iter;
+    GtkFileFilter *filter;
 
     priv->dialog = gtk_file_chooser_dialog_new (_("Record your desktop"),
         GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (priv->applet))),
@@ -222,6 +237,19 @@ byzanz_applet_start_recording (AppletPrivate *priv)
       gtk_dialog_add_button (GTK_DIALOG (priv->dialog),
           byzanz_select_method_get_mnemonic (i), method_response_codes[i]);
     }
+    filter = gtk_file_filter_new ();
+    gtk_file_filter_set_name (filter, _("All files"));
+    gtk_file_filter_add_custom (filter, 0, (GtkFileFilterFunc) gtk_true, NULL, NULL);
+    gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (priv->dialog), filter);
+    for (type = byzanz_encoder_type_iter_init (&iter);
+         type != G_TYPE_NONE;
+         type = byzanz_encoder_type_iter_next (&iter)) {
+      filter = byzanz_encoder_type_get_filter (type);
+      if (filter) {
+        gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (priv->dialog), filter);
+        g_object_unref (filter);
+      }
+    }
     gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (priv->dialog), FALSE);
     uri = panel_applet_gconf_get_string (priv->applet, "save_filename", NULL);
     if (!uri || uri[0] == '\0' ||
diff --git a/src/byzanzencoder.c b/src/byzanzencoder.c
index a25036d..91a7d5b 100644
--- a/src/byzanzencoder.c
+++ b/src/byzanzencoder.c
@@ -23,9 +23,6 @@
 
 #include "byzanzencoder.h"
 
-/* all the encoders */
-#include "byzanzencodergif.h"
-
 typedef struct _ByzanzEncoderJob ByzanzEncoderJob;
 struct _ByzanzEncoderJob {
   GTimeVal		tv;		/* time this job was enqueued */
@@ -114,7 +111,60 @@ enum {
   PROP_RUNNING
 };
 
-G_DEFINE_ABSTRACT_TYPE (ByzanzEncoder, byzanz_encoder, G_TYPE_OBJECT)
+static void
+byzanz_encoder_base_init (gpointer klass)
+{
+  ByzanzEncoderClass *encoder_class = klass;
+
+  encoder_class->filter = NULL;
+}
+
+static void
+byzanz_encoder_base_finalize (gpointer klass)
+{
+  ByzanzEncoderClass *encoder_class = klass;
+
+  if (encoder_class->filter)
+    g_object_unref (encoder_class->filter);
+}
+
+/* cannot use this here, the file filter requires base_init and base_finalize
+ * G_DEFINE_ABSTRACT_TYPE (ByzanzEncoder, byzanz_encoder, G_TYPE_OBJECT)
+ */
+static void     byzanz_encoder_init       (GTypeInstance *instance, gpointer klass);
+static void     byzanz_encoder_class_init (ByzanzEncoderClass *klass);
+static gpointer byzanz_encoder_parent_class = NULL;
+static void     byzanz_encoder_class_intern_init (gpointer klass, gpointer data)
+{
+  byzanz_encoder_parent_class = g_type_class_peek_parent (klass);
+  byzanz_encoder_class_init ((ByzanzEncoderClass*) klass);
+}
+
+GType
+byzanz_encoder_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile)) {
+    GTypeInfo info = {
+      sizeof (ByzanzEncoderClass),
+      byzanz_encoder_base_init,
+      byzanz_encoder_base_finalize,
+      byzanz_encoder_class_intern_init,
+      NULL,
+      NULL,
+      sizeof (ByzanzEncoder),
+      0,
+      byzanz_encoder_init,
+      NULL
+    };
+    GType g_define_type_id;
+
+    g_define_type_id = g_type_register_static (G_TYPE_OBJECT, g_intern_static_string ("ByzanzEncoder"),
+      &info, G_TYPE_FLAG_ABSTRACT);
+    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+  }
+  return g_define_type_id__volatile;
+}
 
 static void
 byzanz_encoder_get_property (GObject *object, guint param_id, GValue *value, 
@@ -235,22 +285,29 @@ byzanz_encoder_class_init (ByzanzEncoderClass *klass)
 }
 
 static void
-byzanz_encoder_init (ByzanzEncoder *encoder)
+byzanz_encoder_init (GTypeInstance *instance, gpointer klass)
 {
+  ByzanzEncoder *encoder = BYZANZ_ENCODER (instance);
+
   encoder->jobs = g_async_queue_new ();
 }
 
 ByzanzEncoder *
-byzanz_encoder_new (GOutputStream *stream, guint width, guint height, GCancellable *cancellable)
+byzanz_encoder_new (GType           encoder_type,
+                    GOutputStream * stream,
+                    guint           width,
+                    guint           height,
+                    GCancellable *  cancellable)
 {
   ByzanzEncoder *encoder;
 
+  g_return_val_if_fail (g_type_is_a (encoder_type, BYZANZ_TYPE_ENCODER), NULL);
   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), NULL);
   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
   g_return_val_if_fail (width > 0, NULL);
   g_return_val_if_fail (height > 0, NULL);
 
-  encoder = g_object_new (BYZANZ_TYPE_ENCODER_GIF, "output", stream,
+  encoder = g_object_new (encoder_type, "output", stream,
       "cancellable", cancellable, "width", width, "height", height, NULL);
 
   return encoder;
@@ -315,3 +372,127 @@ byzanz_encoder_get_error (ByzanzEncoder *encoder)
 
   return encoder->error;
 }
+
+GtkFileFilter *
+byzanz_encoder_type_get_filter (GType encoder_type)
+{
+  ByzanzEncoderClass *klass;
+  GtkFileFilter *filter;
+
+  g_return_val_if_fail (g_type_is_a (encoder_type, BYZANZ_TYPE_ENCODER), NULL);
+
+  klass = g_type_class_ref (encoder_type);
+  filter = klass->filter;
+  if (filter) {
+    g_assert (!g_object_is_floating (filter));
+    g_object_ref (filter);
+    g_object_set_data (G_OBJECT (filter), "byzanz-encoder-type",
+        GSIZE_TO_POINTER (encoder_type));
+  }
+
+  g_type_class_unref (klass);
+  return filter;
+}
+
+/* all the encoders */
+#include "byzanzencodergif.h"
+
+typedef GType (* TypeFunc) (void);
+static const TypeFunc functions[] = {
+  byzanz_encoder_gif_get_type
+};
+#define BYZANZ_ENCODER_DEFAULT_TYPE (functions[0] ())
+
+GType
+byzanz_encoder_type_iter_init (ByzanzEncoderIter *iter)
+{
+  g_return_val_if_fail (iter != NULL, G_TYPE_NONE);
+
+  *iter = GSIZE_TO_POINTER (0);
+
+  return functions[0] ();
+}
+
+GType
+byzanz_encoder_type_iter_next (ByzanzEncoderIter *iter)
+{
+  guint id;
+
+  g_return_val_if_fail (iter != NULL, G_TYPE_NONE);
+
+  id = GPOINTER_TO_SIZE (*iter);
+
+  id++;
+  if (id >= G_N_ELEMENTS (functions))
+    return G_TYPE_NONE;
+
+  *iter = GSIZE_TO_POINTER (id);
+
+  return functions[id] ();
+}
+
+GType
+byzanz_encoder_get_type_from_filter (GtkFileFilter *filter)
+{
+  GType type;
+
+  g_return_val_if_fail (filter == NULL || GTK_IS_FILE_FILTER (filter), BYZANZ_ENCODER_DEFAULT_TYPE);
+
+  if (filter == NULL)
+    return BYZANZ_ENCODER_DEFAULT_TYPE;
+
+  type = GPOINTER_TO_SIZE (g_object_get_data (G_OBJECT (filter), "byzanz-encoder-type"));
+  if (type == 0)
+    return BYZANZ_ENCODER_DEFAULT_TYPE;
+
+  return type;
+}
+
+GType
+byzanz_encoder_get_type_from_file (GFile *file)
+{
+  ByzanzEncoderIter iter;
+  GtkFileFilterInfo info;
+  GType type;
+
+  g_return_val_if_fail (G_IS_FILE (file), BYZANZ_ENCODER_DEFAULT_TYPE);
+
+  info.contains = 0;
+  
+  info.filename = g_file_get_path (file);
+  if (info.filename)
+    info.contains |= GTK_FILE_FILTER_FILENAME;
+
+  info.uri = g_file_get_uri (file);
+  if (info.uri)
+    info.contains |= GTK_FILE_FILTER_URI;
+
+  /* uh oh */
+  info.display_name = g_file_get_parse_name (file);
+  if (info.display_name)
+    info.contains |= GTK_FILE_FILTER_DISPLAY_NAME;
+
+  for (type = byzanz_encoder_type_iter_init (&iter);
+       type != G_TYPE_NONE;
+       type = byzanz_encoder_type_iter_next (&iter)) {
+    GtkFileFilter *filter = byzanz_encoder_type_get_filter (type);
+    if (filter == NULL)
+      continue;
+
+    if (gtk_file_filter_filter (filter, &info)) {
+      g_object_unref (filter);
+      break;
+    }
+    
+    g_object_unref (filter);
+  }
+  if (type == G_TYPE_NONE)
+    type = BYZANZ_ENCODER_DEFAULT_TYPE;
+
+  g_free ((char *) info.filename);
+  g_free ((char *) info.uri);
+  g_free ((char *) info.display_name);
+
+  return type;
+}
+
diff --git a/src/byzanzencoder.h b/src/byzanzencoder.h
index 2b323d2..86812ee 100644
--- a/src/byzanzencoder.h
+++ b/src/byzanzencoder.h
@@ -20,6 +20,7 @@
 #include <glib-object.h>
 #include <gio/gio.h>
 #include <gdk/gdk.h>
+#include <gtk/gtk.h>
 #include <cairo.h>
 
 #ifndef __HAVE_BYZANZ_ENCODER_H__
@@ -27,6 +28,7 @@
 
 typedef struct _ByzanzEncoder ByzanzEncoder;
 typedef struct _ByzanzEncoderClass ByzanzEncoderClass;
+typedef gpointer ByzanzEncoderIter;
 
 #define BYZANZ_TYPE_ENCODER                    (byzanz_encoder_get_type())
 #define BYZANZ_IS_ENCODER(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BYZANZ_TYPE_ENCODER))
@@ -52,6 +54,9 @@ struct _ByzanzEncoder {
 struct _ByzanzEncoderClass {
   GObjectClass		object_class;
 
+  /*< protected >*/
+  GtkFileFilter *       filter;                 /* filter to determine if a file should be encoded by this class */
+
   gboolean		(* setup)		(ByzanzEncoder *	encoder,
 						 GOutputStream *	stream,
                                                  guint                  width,
@@ -74,7 +79,8 @@ struct _ByzanzEncoderClass {
 
 GType		byzanz_encoder_get_type		(void) G_GNUC_CONST;
 
-ByzanzEncoder *	byzanz_encoder_new		(GOutputStream *        stream,
+ByzanzEncoder *	byzanz_encoder_new		(GType                  encoder_type,
+                                                 GOutputStream *        stream,
                                                  guint                  width,
                                                  guint                  height,
                                                  GCancellable *         cancellable);
@@ -88,5 +94,12 @@ void		byzanz_encoder_close		(ByzanzEncoder *	encoder,
 gboolean        byzanz_encoder_is_running       (ByzanzEncoder *        encoder);
 const GError *  byzanz_encoder_get_error        (ByzanzEncoder *        encoder);
 
+GtkFileFilter * byzanz_encoder_type_get_filter  (GType                  encoder_type);
+GType           byzanz_encoder_get_type_from_filter 
+                                                (GtkFileFilter *        filter);
+GType           byzanz_encoder_get_type_from_file
+                                                (GFile *                file);
+GType           byzanz_encoder_type_iter_init   (ByzanzEncoderIter *    iter);
+GType           byzanz_encoder_type_iter_next   (ByzanzEncoderIter *    iter);
 
 #endif /* __HAVE_BYZANZ_ENCODER_H__ */
diff --git a/src/byzanzencodergif.c b/src/byzanzencodergif.c
index 2eeae30..0fd09e0 100644
--- a/src/byzanzencodergif.c
+++ b/src/byzanzencodergif.c
@@ -24,6 +24,7 @@
 #include "byzanzencodergif.h"
 
 #include <string.h>
+#include <glib/gi18n.h>
 
 #include "gifenc.h"
 
@@ -208,7 +209,7 @@ byzanz_encoder_gif_close (ByzanzEncoder *  encoder,
   ByzanzEncoderGif *gif = BYZANZ_ENCODER_GIF (encoder);
 
   if (!gif->has_quantized) {
-    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No image to encode.");
+    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("No image to encode."));
     return FALSE;
   }
 
@@ -244,6 +245,12 @@ byzanz_encoder_gif_class_init (ByzanzEncoderGifClass *klass)
   encoder_class->setup = byzanz_encoder_gif_setup;
   encoder_class->process = byzanz_encoder_gif_process;
   encoder_class->close = byzanz_encoder_gif_close;
+
+  encoder_class->filter = gtk_file_filter_new ();
+  g_object_ref_sink (encoder_class->filter);
+  gtk_file_filter_set_name (encoder_class->filter, _("GIF images"));
+  gtk_file_filter_add_mime_type (encoder_class->filter, "image/gif");
+  gtk_file_filter_add_pattern (encoder_class->filter, "*.gif");
 }
 
 static void
diff --git a/src/byzanzsession.c b/src/byzanzsession.c
index 7d800ba..31314c9 100644
--- a/src/byzanzsession.c
+++ b/src/byzanzsession.c
@@ -49,7 +49,8 @@ enum {
   PROP_ERROR,
   PROP_FILE,
   PROP_AREA,
-  PROP_WINDOW
+  PROP_WINDOW,
+  PROP_ENCODER_TYPE
 };
 
 G_DEFINE_TYPE (ByzanzSession, byzanz_session, G_TYPE_OBJECT)
@@ -79,6 +80,9 @@ byzanz_session_get_property (GObject *object, guint param_id, GValue *value,
     case PROP_WINDOW:
       g_value_set_object (value, session->window);
       break;
+    case PROP_ENCODER_TYPE:
+      g_value_set_gtype (value, session->encoder_type);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
       break;
@@ -101,6 +105,9 @@ byzanz_session_set_property (GObject *object, guint param_id, const GValue *valu
     case PROP_WINDOW:
       session->window = g_value_dup_object (value);
       break;
+    case PROP_ENCODER_TYPE:
+      session->encoder_type = g_value_get_gtype (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
       break;
@@ -201,7 +208,7 @@ byzanz_session_constructed (GObject *object)
   stream = G_OUTPUT_STREAM (g_file_replace (session->file, NULL, 
         FALSE, G_FILE_CREATE_REPLACE_DESTINATION, session->cancellable, &session->error));
   if (stream != NULL) {
-    session->encoder = byzanz_encoder_new (stream,
+    session->encoder = byzanz_encoder_new (session->encoder_type, stream,
         session->area.width, session->area.height, session->cancellable);
     g_signal_connect (session->encoder, "notify", 
         G_CALLBACK (byzanz_session_encoder_notify_cb), session);
@@ -243,6 +250,9 @@ byzanz_session_class_init (ByzanzSessionClass *klass)
   g_object_class_install_property (object_class, PROP_FILE,
       g_param_spec_object ("file", "file", "file to record to",
 	  G_TYPE_FILE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class, PROP_ENCODER_TYPE,
+      g_param_spec_gtype ("encoder-type", "encoder type", "type for the encoder to use",
+	  BYZANZ_TYPE_ENCODER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 }
 
 static void
@@ -254,6 +264,7 @@ byzanz_session_init (ByzanzSession *session)
 /**
  * byzanz_session_new:
  * @file: file to record to. Any existing file will be overwritten.
+ * @encoder_type: the type of encoder to use
  * @window: window to record
  * @area: area of window that should be recorded
  * @record_cursor: if the cursor image should be recorded
@@ -266,10 +277,11 @@ byzanz_session_init (ByzanzSession *session)
  *          then. Another reason would be a thread creation failure.
  **/
 ByzanzSession *
-byzanz_session_new (GFile *file, GdkWindow *window, GdkRectangle *area,
-    gboolean record_cursor)
+byzanz_session_new (GFile *file, GType encoder_type, 
+    GdkWindow *window, GdkRectangle *area, gboolean record_cursor)
 {
   g_return_val_if_fail (G_IS_FILE (file), NULL);
+  g_return_val_if_fail (g_type_is_a (encoder_type, BYZANZ_TYPE_ENCODER), NULL);
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
   g_return_val_if_fail (area != NULL, NULL);
   g_return_val_if_fail (area->x >= 0, NULL);
@@ -279,7 +291,8 @@ byzanz_session_new (GFile *file, GdkWindow *window, GdkRectangle *area,
   
   /* FIXME: handle mouse cursor */
 
-  return g_object_new (BYZANZ_TYPE_SESSION, "file", file, "window", window, "area", area, NULL);
+  return g_object_new (BYZANZ_TYPE_SESSION, "file", file, "encoder-type", encoder_type,
+      "window", window, "area", area, NULL);
 }
 
 void
diff --git a/src/byzanzsession.h b/src/byzanzsession.h
index 02b1ae4..89e396d 100644
--- a/src/byzanzsession.h
+++ b/src/byzanzsession.h
@@ -44,6 +44,7 @@ struct _ByzanzSession {
   GFile *               file;           /* file we're saving to */
   GdkRectangle          area;           /* area of window to record */
   GdkWindow *           window;         /* window to record */
+  GType                 encoder_type;   /* type of encoder to use */
 
   /* internal objects */
   GCancellable *        cancellable;    /* cancellable to use for aborting the session */
@@ -60,6 +61,7 @@ GType		        byzanz_session_get_type		(void) G_GNUC_CONST;
 
 
 ByzanzSession * 	byzanz_session_new		(GFile *                file,
+                                                         GType                  encoder_type,
 							 GdkWindow *		window,
 							 GdkRectangle *		area,
 							 gboolean		record_cursor);
diff --git a/src/record.c b/src/record.c
index 7ab9e86..63406a6 100644
--- a/src/record.c
+++ b/src/record.c
@@ -119,8 +119,8 @@ main (int argc, char **argv)
     return 0;
   }
   file = g_file_new_for_commandline_arg (argv[1]);
-  rec = byzanz_session_new (file, gdk_get_default_root_window (),
-      &area, cursor);
+  rec = byzanz_session_new (file, byzanz_encoder_get_type_from_file (file),
+      gdk_get_default_root_window (), &area, cursor);
   g_object_unref (file);
   if (rec == NULL) {
     g_print (_("Could not prepare recording.\n"



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]