[rhythmbox] add more utility functions for dealing with encoding profiles



commit fc8dbef7c33a6f2e338daa09a176583ab1fdc1f6
Author: Jonathan Matthew <jonathan d14n org>
Date:   Mon Apr 23 08:37:14 2012 +1000

    add more utility functions for dealing with encoding profiles
    
    Also, for some encoders, add a list of properties that could
    usefully be exposed to the user as an alternative to selecting a
    preset.  This is very conservative so far, just exposing quality
    settings for a few encoders.

 data/rhythmbox.gep       |   10 +++
 lib/rb-gst-media-types.c |  159 ++++++++++++++++++++++++++++++++++++++++++++--
 lib/rb-gst-media-types.h |    6 ++
 3 files changed, 170 insertions(+), 5 deletions(-)
---
diff --git a/data/rhythmbox.gep b/data/rhythmbox.gep
index 6383d96..9448922 100644
--- a/data/rhythmbox.gep
+++ b/data/rhythmbox.gep
@@ -15,6 +15,8 @@ type = audio
 format = audio/mpeg, mpegversion=1, layer=3
 presence = 1
 
+
+
 [profile-oggvorbis]
 name = oggvorbis
 description = Ogg Vorbis
@@ -27,12 +29,14 @@ type = audio
 format = audio/x-vorbis
 presence = 1
 
+
 [profile-flac]
 name = flac
 description = FLAC
 format = audio/x-flac
 type = audio
 
+
 [profile-m4a]
 name = m4a
 description = MPEG 4 Audio
@@ -44,3 +48,9 @@ parent = m4a
 type = audio
 format = audio/mpeg, mpegversion=4, stream-format=raw
 presence = 1
+
+[rhythmbox-encoder-settings]
+# maps encoder elements to lists of settings to expose
+lamemp3enc = quality
+faac = quality
+vorbisenc = quality
diff --git a/lib/rb-gst-media-types.c b/lib/rb-gst-media-types.c
index 3a76e1b..97c7881 100644
--- a/lib/rb-gst-media-types.c
+++ b/lib/rb-gst-media-types.c
@@ -50,6 +50,7 @@ static const char *container_formats[] = {
 
 #define ENCODING_TARGET_FILE "rhythmbox.gep"
 static GstEncodingTarget *default_target = NULL;
+static GKeyFile *target_keyfile = NULL;
 
 RBGstMediaType
 rb_gst_get_missing_plugin_type (const GstStructure *structure)
@@ -253,6 +254,20 @@ rb_gst_encoding_profile_get_media_type (GstEncodingProfile *profile)
 	}
 }
 
+static char *
+get_encoding_target_file ()
+{
+	char *target_file;
+
+	target_file = rb_find_user_data_file (ENCODING_TARGET_FILE);
+	if (g_file_test (target_file, G_FILE_TEST_EXISTS) == FALSE) {
+		g_free (target_file);
+		target_file = g_strdup (rb_file (ENCODING_TARGET_FILE));
+	}
+
+	return target_file;
+}
+
 GstEncodingTarget *
 rb_gst_get_default_encoding_target ()
 {
@@ -260,17 +275,15 @@ rb_gst_get_default_encoding_target ()
 		char *target_file;
 		GError *error = NULL;
 
-		target_file = rb_find_user_data_file (ENCODING_TARGET_FILE);
-		if (g_file_test (target_file, G_FILE_TEST_EXISTS) == FALSE) {
-			target_file = g_strdup (rb_file (ENCODING_TARGET_FILE));
-		}
-
+		target_file = get_encoding_target_file ();
 		default_target = gst_encoding_target_load_from_file (target_file, &error);
 		if (default_target == NULL) {
 			g_warning ("Unable to load encoding profiles from %s: %s", target_file, error ? error->message : "no error");
 			g_clear_error (&error);
+			g_free (target_file);
 			return NULL;
 		}
+		g_free (target_file);
 	}
 
 	return default_target;
@@ -312,3 +325,139 @@ rb_gst_media_type_is_lossless (const char *media_type)
 	}
 	return FALSE;
 }
+
+static GstEncodingProfile *
+get_audio_encoding_profile (GstEncodingProfile *profile)
+{
+	if (GST_IS_ENCODING_AUDIO_PROFILE (profile)) {
+		return profile;
+	} else if (GST_IS_ENCODING_CONTAINER_PROFILE (profile)) {
+		const GList *l = gst_encoding_container_profile_get_profiles (GST_ENCODING_CONTAINER_PROFILE (profile));
+		for (; l != NULL; l = l->next) {
+			GstEncodingProfile *p = get_audio_encoding_profile (l->data);
+			if (p != NULL) {
+				return p;
+			}
+		}
+	}
+
+	g_warning ("no audio encoding profile in profile %s", gst_encoding_profile_get_name (profile));
+	return NULL;
+}
+
+static GstElementFactory *
+get_audio_encoder_factory (GstEncodingProfile *profile)
+{
+	GstEncodingProfile *p = get_audio_encoding_profile (profile);
+	GstElementFactory *f;
+	GList *l;
+	GList *fl;
+
+	if (p == NULL)
+		return NULL;
+
+	l = gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER, GST_RANK_MARGINAL);
+	fl = gst_element_factory_list_filter (l, gst_encoding_profile_get_format (p), GST_PAD_SRC, FALSE);
+
+	if (fl != NULL) {
+		f = gst_object_ref (fl->data);
+	} else {
+		g_warning ("no encoder factory for profile %s", gst_encoding_profile_get_name (p));
+		f = NULL;
+	}
+	gst_plugin_feature_list_free (l);
+	gst_plugin_feature_list_free (fl);
+	return f;
+}
+
+/**
+ * rb_gst_encoding_profile_set_preset:
+ * @profile: a #GstEncodingProfile
+ * @preset: preset to apply
+ *
+ * Applies the preset @preset to the audio encoding profile within @profile.
+ */
+void
+rb_gst_encoding_profile_set_preset (GstEncodingProfile *profile, const char *preset)
+{
+	GstEncodingProfile *p;
+
+	p = get_audio_encoding_profile (profile);
+	if (p != NULL) {
+		gst_encoding_profile_set_preset (p, preset);
+	}
+}
+
+/**
+ * rb_gst_encoding_profile_get_settings:
+ * @profile: a #GstEncodingProfile
+ *
+ * Returns a list of settings for the profile @profile that can usefully
+ * be exposed to a user.  This usually means just bitrate/quality settings.
+ * This works by finding the name of the encoder element for the profile
+ * and retrieving a list specific to that encoder.
+ *
+ * Return value: (transfer full) (element-type GParamSpec): list of settings
+ */
+char **
+rb_gst_encoding_profile_get_settings (GstEncodingProfile *profile)
+{
+	GstElementFactory *factory;
+	char **setting_names;
+
+	factory = get_audio_encoder_factory (profile);
+	if (factory == NULL) {
+		return NULL;
+	}
+
+	/* look up list of settings;
+	 * if we don't have one for the encoder, what do we do?  return everything?
+	 */
+	if (target_keyfile == NULL) {
+		char *file = get_encoding_target_file ();
+		GError *error = NULL;
+
+		target_keyfile = g_key_file_new ();
+		g_key_file_set_list_separator (target_keyfile, ',');
+		g_key_file_load_from_file (target_keyfile, file, G_KEY_FILE_NONE, &error);
+		if (error != NULL) {
+			g_warning ("Unable to load encoding target keyfile %s: %s", file, error->message);
+			g_clear_error (&error);
+		}
+	}
+
+	setting_names = g_key_file_get_string_list (target_keyfile,
+						    "rhythmbox-encoder-settings",
+						    gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)),
+						    NULL,
+						    NULL);
+	return setting_names;
+}
+
+GstElement *
+rb_gst_encoding_profile_get_encoder (GstEncodingProfile *profile)
+{
+	GstElementFactory *factory;
+
+	factory = get_audio_encoder_factory (profile);
+	if (factory == NULL) {
+		return NULL;
+	}
+
+	return gst_element_factory_create (factory, NULL);
+}
+
+char **
+rb_gst_encoding_profile_get_presets (GstEncodingProfile *profile)
+{
+	GstElement *encoder;
+	char **presets = NULL;
+
+	encoder = rb_gst_encoding_profile_get_encoder (profile);
+	if (encoder != NULL && GST_IS_PRESET (encoder)) {
+		presets = gst_preset_get_preset_names (GST_PRESET (encoder));
+		g_object_unref (encoder);
+	}
+	return presets;
+}
+
diff --git a/lib/rb-gst-media-types.h b/lib/rb-gst-media-types.h
index 836a6b3..fd1840e 100644
--- a/lib/rb-gst-media-types.h
+++ b/lib/rb-gst-media-types.h
@@ -70,6 +70,12 @@ char *		rb_gst_encoding_profile_get_media_type (GstEncodingProfile *profile);
 
 gboolean	rb_gst_media_type_is_lossless (const char *media_type);
 
+char **		rb_gst_encoding_profile_get_settings (GstEncodingProfile *profile);
+char **		rb_gst_encoding_profile_get_presets (GstEncodingProfile *profile);
+void		rb_gst_encoding_profile_set_preset (GstEncodingProfile *profile, const char *preset);
+
+GstElement *	rb_gst_encoding_profile_get_encoder (GstEncodingProfile *profile);
+
 G_END_DECLS
 
 #endif /* __RB_GST_MEDIA_TYPES_H */



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