[byzanz] Add API for automatic encoder selection and use it
- From: Benjamin Otte <otte src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [byzanz] Add API for automatic encoder selection and use it
- Date: Fri, 28 Aug 2009 14:02:49 +0000 (UTC)
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]