[byzanz] Allow to record sound
- From: Benjamin Otte <otte src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [byzanz] Allow to record sound
- Date: Mon, 8 Feb 2010 17:18:49 +0000 (UTC)
commit 60cc168f6cf1294b07ce3b8fea74a2280150abdc
Author: Benjamin Otte <otte redhat com>
Date: Mon Feb 8 17:19:05 2010 +0100
Allow to record sound
Only the Theora encoder supports this. Other formats will throw an error
at people.
src/byzanzapplet.c | 15 ++++++++++++++-
src/byzanzencoder.c | 26 +++++++++++++++++++++++---
src/byzanzencoder.h | 3 +++
src/byzanzencodergstreamer.c | 18 ++++++++++++++++--
src/byzanzencodergstreamer.h | 2 ++
src/byzanzencoderogv.c | 4 ++++
src/byzanzsession.c | 18 +++++++++++++++---
src/byzanzsession.h | 4 +++-
src/playback.c | 2 +-
src/record.c | 4 +++-
10 files changed, 84 insertions(+), 12 deletions(-)
---
diff --git a/src/byzanzapplet.c b/src/byzanzapplet.c
index c5742e5..2041a35 100644
--- a/src/byzanzapplet.c
+++ b/src/byzanzapplet.c
@@ -191,7 +191,8 @@ byzanz_applet_select_done (GdkWindow *window, const GdkRectangle *area, gpointer
if (encoder_type == 0)
encoder_type = byzanz_encoder_get_type_from_file (priv->file);
- priv->rec = byzanz_session_new (priv->file, encoder_type, window, area, TRUE);
+ priv->rec = byzanz_session_new (priv->file, encoder_type, window, area, FALSE,
+ panel_applet_gconf_get_bool (priv->applet, "record_audio", NULL));
g_signal_connect_swapped (priv->rec, "notify", G_CALLBACK (byzanz_applet_session_notify), priv);
byzanz_session_start (priv->rec);
}
@@ -234,6 +235,10 @@ panel_applet_start_response (GtkWidget *dialog, int response, AppletPrivate *pri
priv->encoder_type = 0;
}
+ panel_applet_gconf_set_bool (priv->applet, "record_audio",
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
+ gtk_file_chooser_get_extra_widget (GTK_FILE_CHOOSER (priv->dialog)))), NULL);
+
gtk_widget_destroy (dialog);
priv->dialog = NULL;
byzanz_select_method_select (priv->method, byzanz_applet_select_done, priv);
@@ -284,6 +289,14 @@ byzanz_applet_start_recording (AppletPrivate *priv)
g_object_unref (filter);
}
}
+
+ gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (priv->dialog),
+ gtk_check_button_new_with_label (_("Record audio")));
+ if (panel_applet_gconf_get_bool (priv->applet, "record_audio", NULL)) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (
+ gtk_file_chooser_get_extra_widget (GTK_FILE_CHOOSER (priv->dialog))), TRUE);
+ }
+
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 5846d34..f899e7a 100644
--- a/src/byzanzencoder.c
+++ b/src/byzanzencoder.c
@@ -23,6 +23,8 @@
#include "byzanzencoder.h"
+#include <glib/gi18n-lib.h>
+
#include "byzanzserialize.h"
typedef struct _ByzanzEncoderJob ByzanzEncoderJob;
@@ -71,6 +73,7 @@ static gboolean
byzanz_encoder_run (ByzanzEncoder * encoder,
GInputStream * input,
GOutputStream * output,
+ gboolean record_audio,
GCancellable * cancellable,
GError ** error)
{
@@ -81,6 +84,12 @@ byzanz_encoder_run (ByzanzEncoder * encoder,
guint64 msecs;
gboolean success;
+ if (record_audio) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("This format does not support recording audio."));
+ return FALSE;
+ }
+
if (!byzanz_deserialize_header (input, &width, &height, cancellable, error) ||
!klass->setup (encoder, output, width, height, cancellable, error))
return FALSE;
@@ -112,7 +121,7 @@ byzanz_encoder_thread (gpointer enc)
GError *error = NULL;
klass->run (encoder, encoder->input_stream, encoder->output_stream,
- encoder->cancellable, &error);
+ encoder->record_audio, encoder->cancellable, &error);
g_idle_add_full (G_PRIORITY_DEFAULT, byzanz_encoder_finished, enc, NULL);
return error;
@@ -124,6 +133,7 @@ enum {
PROP_0,
PROP_INPUT,
PROP_OUTPUT,
+ PROP_SOUND,
PROP_CANCELLABLE,
PROP_ERROR,
PROP_RUNNING
@@ -197,6 +207,9 @@ byzanz_encoder_get_property (GObject *object, guint param_id, GValue *value,
case PROP_OUTPUT:
g_value_set_object (value, encoder->output_stream);
break;
+ case PROP_SOUND:
+ g_value_set_boolean (value, encoder->record_audio);
+ break;
case PROP_CANCELLABLE:
g_value_set_object (value, encoder->cancellable);
break;
@@ -227,6 +240,9 @@ byzanz_encoder_set_property (GObject *object, guint param_id, const GValue *valu
encoder->output_stream = g_value_dup_object (value);
g_assert (encoder->output_stream != NULL);
break;
+ case PROP_SOUND:
+ encoder->record_audio = g_value_get_boolean (value);
+ break;
case PROP_CANCELLABLE:
encoder->cancellable = g_value_dup_object (value);
break;
@@ -285,6 +301,9 @@ byzanz_encoder_class_init (ByzanzEncoderClass *klass)
g_object_class_install_property (object_class, PROP_OUTPUT,
g_param_spec_object ("output", "output", "stream to write data to",
G_TYPE_OUTPUT_STREAM, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class, PROP_SOUND,
+ g_param_spec_boolean ("record-audio", "record audio", "TRUE when recording audio",
+ FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class, PROP_CANCELLABLE,
g_param_spec_object ("cancellable", "cancellable", "cancellable for stopping the thread",
G_TYPE_CANCELLABLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
@@ -310,6 +329,7 @@ ByzanzEncoder *
byzanz_encoder_new (GType encoder_type,
GInputStream * input,
GOutputStream * output,
+ gboolean record_audio,
GCancellable * cancellable)
{
ByzanzEncoder *encoder;
@@ -319,8 +339,8 @@ byzanz_encoder_new (GType encoder_type,
g_return_val_if_fail (G_IS_OUTPUT_STREAM (output), NULL);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
- encoder = g_object_new (encoder_type, "input", input, "output", output,
- "cancellable", cancellable, NULL);
+ encoder = g_object_new (encoder_type, "input", input, "output", output,
+ "record-audio", record_audio, "cancellable", cancellable, NULL);
return encoder;
}
diff --git a/src/byzanzencoder.h b/src/byzanzencoder.h
index 8d711a6..54f816e 100644
--- a/src/byzanzencoder.h
+++ b/src/byzanzencoder.h
@@ -43,6 +43,7 @@ struct _ByzanzEncoder {
/*<private >*/
GInputStream * input_stream; /* stream to read from in byzanzserialize.h format */
GOutputStream * output_stream; /* stream we write to (passed to the vfuncs) */
+ gboolean record_audio; /* TRUE when we're recording audio */
GCancellable * cancellable; /* cancellable to use in thread */
GError * error; /* NULL or the encoding error */
@@ -60,6 +61,7 @@ struct _ByzanzEncoderClass {
gboolean (* run) (ByzanzEncoder * encoder,
GInputStream * input,
GOutputStream * output,
+ gboolean record_audio,
GCancellable * cancellable,
GError ** error);
@@ -89,6 +91,7 @@ GType byzanz_encoder_get_type (void) G_GNUC_CONST;
ByzanzEncoder * byzanz_encoder_new (GType encoder_type,
GInputStream * input,
GOutputStream * output,
+ gboolean record_audio,
GCancellable * cancellable);
/*
void byzanz_encoder_process (ByzanzEncoder * encoder,
diff --git a/src/byzanzencodergstreamer.c b/src/byzanzencodergstreamer.c
index 179dc6f..2d89bab 100644
--- a/src/byzanzencodergstreamer.c
+++ b/src/byzanzencodergstreamer.c
@@ -23,7 +23,7 @@
#include "byzanzencodergstreamer.h"
-#include <glib/gi18n.h>
+#include <glib/gi18n-lib.h>
#include <gst/app/gstappbuffer.h>
#include <gst/video/video.h>
@@ -52,6 +52,8 @@ byzanz_encoder_gstreamer_need_data (GstAppSrc *src, guint length, gpointer data)
if (surface == NULL) {
gst_app_src_end_of_stream (gst->src);
+ if (gst->audiosrc)
+ gst_element_send_event (gst->audiosrc, gst_event_new_eos ());
return;
}
@@ -93,6 +95,7 @@ static gboolean
byzanz_encoder_gstreamer_run (ByzanzEncoder * encoder,
GInputStream * input,
GOutputStream * output,
+ gboolean record_audio,
GCancellable * cancellable,
GError ** error)
{
@@ -109,7 +112,18 @@ byzanz_encoder_gstreamer_run (ByzanzEncoder * encoder,
gstreamer->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
g_assert (klass->pipeline_string);
- gstreamer->pipeline = gst_parse_launch (klass->pipeline_string, error);
+ if (record_audio) {
+ if (klass->audio_pipeline_string == NULL) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("This format does not support recording audio."));
+ return FALSE;
+ }
+ gstreamer->pipeline = gst_parse_launch (klass->audio_pipeline_string, error);
+ gstreamer->audiosrc = gst_bin_get_by_name (GST_BIN (gstreamer->pipeline), "audiosrc");
+ g_assert (gstreamer->audiosrc);
+ } else {
+ gstreamer->pipeline = gst_parse_launch (klass->pipeline_string, error);
+ }
if (gstreamer->pipeline == NULL)
return FALSE;
diff --git a/src/byzanzencodergstreamer.h b/src/byzanzencodergstreamer.h
index 3dde771..77ea20f 100644
--- a/src/byzanzencodergstreamer.h
+++ b/src/byzanzencodergstreamer.h
@@ -42,6 +42,7 @@ struct _ByzanzEncoderGStreamer {
GTimeVal start_time; /* timestamp of first image */
GstElement * pipeline; /* The pipeline */
+ GstElement * audiosrc; /* the source we record audio from */
GstAppSrc * src; /* the source we feed with images */
GstCaps * caps; /* caps of video stream */
};
@@ -50,6 +51,7 @@ struct _ByzanzEncoderGStreamerClass {
ByzanzEncoderClass encoder_class;
const char * pipeline_string;
+ const char * audio_pipeline_string;
};
GType byzanz_encoder_gstreamer_get_type (void) G_GNUC_CONST;
diff --git a/src/byzanzencoderogv.c b/src/byzanzencoderogv.c
index dd6a379..f834b77 100644
--- a/src/byzanzencoderogv.c
+++ b/src/byzanzencoderogv.c
@@ -43,6 +43,10 @@ byzanz_encoder_ogv_class_init (ByzanzEncoderOgvClass *klass)
gstreamer_class->pipeline_string =
"appsrc name=src ! ffmpegcolorspace ! videorate ! "
"video/x-raw-yuv,framerate=25/1 ! theoraenc ! oggmux ! giostreamsink name=sink";
+ gstreamer_class->audio_pipeline_string =
+ "autoaudiosrc name=audiosrc ! audioconvert ! vorbisenc ! queue ! oggmux name=muxer ! giostreamsink name=sink "
+ "appsrc name=src ! ffmpegcolorspace ! videorate ! "
+ "video/x-raw-yuv,framerate=25/1 ! theoraenc ! queue ! muxer.";
}
static void
diff --git a/src/byzanzsession.c b/src/byzanzsession.c
index d3f0c80..df36c62 100644
--- a/src/byzanzsession.c
+++ b/src/byzanzsession.c
@@ -51,6 +51,7 @@ enum {
PROP_FILE,
PROP_AREA,
PROP_WINDOW,
+ PROP_AUDIO,
PROP_ENCODER_TYPE
};
@@ -81,6 +82,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_AUDIO:
+ g_value_set_boolean (value, session->record_audio);
+ break;
case PROP_ENCODER_TYPE:
g_value_set_gtype (value, session->encoder_type);
break;
@@ -106,6 +110,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_AUDIO:
+ session->record_audio = g_value_get_boolean (value);
+ break;
case PROP_ENCODER_TYPE:
session->encoder_type = g_value_get_gtype (value);
break;
@@ -245,7 +252,7 @@ byzanz_session_constructed (GObject *object)
if (stream != NULL) {
session->encoder = byzanz_encoder_new (session->encoder_type,
byzanz_queue_get_input_stream (session->queue),
- stream, session->cancellable);
+ stream, session->record_audio, session->cancellable);
g_signal_connect (session->encoder, "notify",
G_CALLBACK (byzanz_session_encoder_notify_cb), session);
g_object_unref (stream);
@@ -288,6 +295,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_AUDIO,
+ g_param_spec_boolean ("record-audio", "record audio", "TRUE to record audio",
+ FALSE, 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));
@@ -307,6 +317,7 @@ byzanz_session_init (ByzanzSession *session)
* @window: window to record
* @area: area of window that should be recorded
* @record_cursor: if the cursor image should be recorded
+ * @record_audio: if audio should be recorded
*
* Creates a new #ByzanzSession and initializes all basic variables.
* gtk_init() and g_thread_init() must have been called before.
@@ -317,7 +328,8 @@ byzanz_session_init (ByzanzSession *session)
**/
ByzanzSession *
byzanz_session_new (GFile *file, GType encoder_type,
- GdkWindow *window, const GdkRectangle *area, gboolean record_cursor)
+ GdkWindow *window, const GdkRectangle *area, gboolean record_cursor,
+ gboolean record_audio)
{
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);
@@ -331,7 +343,7 @@ byzanz_session_new (GFile *file, GType encoder_type,
/* FIXME: handle mouse cursor */
return g_object_new (BYZANZ_TYPE_SESSION, "file", file, "encoder-type", encoder_type,
- "window", window, "area", area, NULL);
+ "window", window, "area", area, "record-audio", record_audio, NULL);
}
void
diff --git a/src/byzanzsession.h b/src/byzanzsession.h
index db95825..ed6c32d 100644
--- a/src/byzanzsession.h
+++ b/src/byzanzsession.h
@@ -45,6 +45,7 @@ struct _ByzanzSession {
GFile * file; /* file we're saving to */
GdkRectangle area; /* area of window to record */
GdkWindow * window; /* window to record */
+ gboolean record_audio; /* TRUE to record audio */
GType encoder_type; /* type of encoder to use */
ByzanzQueue * queue; /* queue we use as data cache */
GTimeVal start_time; /* when we started writing to queue */
@@ -67,7 +68,8 @@ ByzanzSession * byzanz_session_new (GFile * file,
GType encoder_type,
GdkWindow * window,
const GdkRectangle * area,
- gboolean record_cursor);
+ gboolean record_cursor,
+ gboolean record_audio);
void byzanz_session_start (ByzanzSession * session);
void byzanz_session_stop (ByzanzSession * session);
void byzanz_session_abort (ByzanzSession * session);
diff --git a/src/playback.c b/src/playback.c
index 813ff65..f5087e1 100644
--- a/src/playback.c
+++ b/src/playback.c
@@ -109,7 +109,7 @@ main (int argc, char **argv)
return 1;
}
encoder = byzanz_encoder_new (byzanz_encoder_get_type_from_file (outfile),
- instream, outstream, NULL);
+ instream, outstream, FALSE, NULL);
g_signal_connect (encoder, "notify", G_CALLBACK (encoder_notify), loop);
diff --git a/src/record.c b/src/record.c
index 6cdff64..fa29397 100644
--- a/src/record.c
+++ b/src/record.c
@@ -28,6 +28,7 @@
static int duration = 10;
static int delay = 1;
static gboolean cursor = FALSE;
+static gboolean audio = FALSE;
static gboolean verbose = FALSE;
static GdkRectangle area = { 0, 0, G_MAXINT / 2, G_MAXINT / 2 };
@@ -36,6 +37,7 @@ static GOptionEntry entries[] =
{ "duration", 'd', 0, G_OPTION_ARG_INT, &duration, N_("Duration of animation (default: 10 seconds)"), N_("SECS") },
{ "delay", 0, 0, G_OPTION_ARG_INT, &delay, N_("Delay before start (default: 1 second)"), N_("SECS") },
{ "cursor", 'c', 0, G_OPTION_ARG_NONE, &cursor, N_("Record mouse cursor"), NULL },
+ { "audio", 'a', 0, G_OPTION_ARG_NONE, &audio, N_("Record audio"), NULL },
{ "x", 'x', 0, G_OPTION_ARG_INT, &area.x, N_("X coordinate of rectangle to record"), N_("PIXEL") },
{ "y", 'y', 0, G_OPTION_ARG_INT, &area.y, N_("Y coordinate of rectangle to record"), N_("PIXEL") },
{ "width", 'w', 0, G_OPTION_ARG_INT, &area.width, N_("Width of recording rectangle"), N_("PIXEL") },
@@ -149,7 +151,7 @@ main (int argc, char **argv)
}
file = g_file_new_for_commandline_arg (argv[1]);
rec = byzanz_session_new (file, byzanz_encoder_get_type_from_file (file),
- gdk_get_default_root_window (), &area, cursor);
+ gdk_get_default_root_window (), &area, cursor, audio);
g_object_unref (file);
g_signal_connect (rec, "notify", G_CALLBACK (session_notify_cb), NULL);
delay = MAX (delay, 1);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]