[rhythmbox] library: split the encoding settings widgets out



commit 454192edfcb47c30f56c74b26fb039dd873096e3
Author: Jonathan Matthew <jonathan d14n org>
Date:   Wed Jul 29 23:03:38 2015 +1000

    library: split the encoding settings widgets out
    
    More things can have their own encoding settings now, so making this bit
    reusable will help.

 data/ui/encoding-settings.ui   |  101 ++++++
 data/ui/library-prefs.ui       |   74 +----
 po/POTFILES.in                 |    2 +
 sources/rb-library-source.c    |  489 +--------------------------
 widgets/Makefile.am            |    8 +-
 widgets/rb-encoding-settings.c |  738 ++++++++++++++++++++++++++++++++++++++++
 widgets/rb-encoding-settings.h |   66 ++++
 7 files changed, 924 insertions(+), 554 deletions(-)
---
diff --git a/data/ui/encoding-settings.ui b/data/ui/encoding-settings.ui
new file mode 100644
index 0000000..a122a5c
--- /dev/null
+++ b/data/ui/encoding-settings.ui
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface>
+  <requires lib="gtk+" version="3.0"/>
+  <object class="GtkGrid" id="encoding-settings-grid">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="row_spacing">6</property>
+    <child>
+      <object class="GtkComboBox" id="format_select_combo">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="hexpand">True</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkComboBox" id="preset_select_combo">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="hexpand">True</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkButton" id="install_plugins_button">
+        <property name="label" translatable="yes">_Install additional software required to use this 
format</property>
+        <property name="use_action_appearance">False</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">True</property>
+        <property name="hexpand">True</property>
+        <property name="use_underline">True</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">3</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkGrid" id="encoder_property_holder">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="column_spacing">6</property>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">2</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkCheckButton" id="transcode_lossless_check">
+        <property name="label" translatable="yes">Transcode lossless files into this format</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">False</property>
+        <property name="xalign">0</property>
+        <property name="draw_indicator">True</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">4</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/data/ui/library-prefs.ui b/data/ui/library-prefs.ui
index 2781613..546abec 100644
--- a/data/ui/library-prefs.ui
+++ b/data/ui/library-prefs.ui
@@ -260,6 +260,7 @@
                     <property name="label" translatable="yes">_Preferred format:</property>
                     <property name="use_underline">True</property>
                     <property name="xalign">0</property>
+                    <property name="yalign">0</property>
                   </object>
                   <packing>
                     <property name="left_attach">0</property>
@@ -316,76 +317,7 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkLabel" id="format_settings_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="hexpand">True</property>
-                    <property name="label" translatable="yes">Format settings:</property>
-                    <property name="xalign">0</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">4</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkButton" id="install_plugins_button">
-                    <property name="label" translatable="yes">_Install additional software required to use 
this format</property>
-                    <property name="use_action_appearance">False</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="use_underline">True</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">6</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkComboBox" id="format_select_combo">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">3</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="blank1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="hexpand">True</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">6</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="blank2">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="hexpand">True</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">5</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkComboBox" id="preset_select_combo">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">4</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkGrid" id="encoder_property_holder">
+                  <object class="GtkGrid" id="encoding_settings_holder">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <child>
@@ -418,7 +350,7 @@
                   </object>
                   <packing>
                     <property name="left_attach">1</property>
-                    <property name="top_attach">5</property>
+                    <property name="top_attach">3</property>
                   </packing>
                 </child>
               </object>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f628ede..97e8da3 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -12,6 +12,7 @@ data/rhythmbox-device.desktop.in.in
 [type: gettext/glade]data/ui/create-playlist.ui
 [type: gettext/glade]data/ui/display-page-add-menu.ui
 [type: gettext/glade]data/ui/edit-menu.ui
+[type: gettext/glade]data/ui/encoding-settings.ui
 [type: gettext/glade]data/ui/general-prefs.ui
 [type: gettext/glade]data/ui/import-dialog.ui
 [type: gettext/glade]data/ui/import-errors-popup.ui
@@ -210,6 +211,7 @@ widgets/eggwrapbox.c
 widgets/rb-alert-dialog.c
 widgets/rb-cell-renderer-pixbuf.c
 widgets/rb-dialog.c
+widgets/rb-encoding-settings.c
 widgets/rb-entry-view.c
 widgets/rb-fading-image.c
 widgets/rb-header.c
diff --git a/sources/rb-library-source.c b/sources/rb-library-source.c
index 69b023e..9839c60 100644
--- a/sources/rb-library-source.c
+++ b/sources/rb-library-source.c
@@ -51,7 +51,6 @@
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
 #include <glib-object.h>
-#include <gst/pbutils/install-plugins.h>
 
 #include "rb-track-transfer-batch.h"
 #include "rb-track-transfer-queue.h"
@@ -65,9 +64,8 @@
 #include "rb-library-source.h"
 #include "rb-auto-playlist-source.h"
 #include "rb-encoder.h"
-#include "rb-missing-plugins.h"
 #include "rb-gst-media-types.h"
-#include "rb-object-property-editor.h"
+#include "rb-encoding-settings.h"
 #include "rb-import-dialog.h"
 #include "rb-application.h"
 #include "rb-display-page-menu.h"
@@ -111,12 +109,6 @@ static void rb_library_source_path_changed_cb (GtkComboBox *box,
                                                RBLibrarySource *source);
 static void rb_library_source_filename_changed_cb (GtkComboBox *box,
                                                   RBLibrarySource *source);
-static void rb_library_source_format_changed_cb (GtkWidget *widget,
-                                                RBLibrarySource *source);
-static void rb_library_source_preset_changed_cb (GtkWidget *widget,
-                                                RBLibrarySource *source);
-static void rb_library_source_install_plugins_cb (GtkWidget *widget,
-                                                 RBLibrarySource *source);
 static void update_layout_example_label (RBLibrarySource *source);
 static RhythmDBImportJob *maybe_create_import_job (RBLibrarySource *source);
 
@@ -144,19 +136,6 @@ static const LibraryPathElement library_layout_filenames[] = {
 };
 static const int num_library_layout_filenames = G_N_ELEMENTS (library_layout_filenames);
 
-#define CUSTOM_SETTINGS_PREFIX "rhythmbox-custom-settings"
-#define CBR_SETTINGS_PRESET CUSTOM_SETTINGS_PREFIX "-cbr"
-/* this preset name was used in releases where we only had VBR custom settings */
-#define VBR_SETTINGS_PRESET CUSTOM_SETTINGS_PREFIX
-
-static struct {
-       const char *style;
-       const char *label;
-       const char *preset;
-} library_encoding_styles[] = {
-       { "cbr", N_("Constant bit rate"), CBR_SETTINGS_PRESET },
-       { "vbr", N_("Variable bit rate"), VBR_SETTINGS_PRESET },
-};
 
 
 struct RBLibrarySourcePrivate
@@ -175,21 +154,10 @@ struct RBLibrarySourcePrivate
        GtkWidget *watch_library_check;
        GtkWidget *layout_path_menu;
        GtkWidget *layout_filename_menu;
-       GtkWidget *preferred_format_menu;
-       GtkWidget *preset_menu;
        GtkWidget *layout_example_label;
-       GtkWidget *install_plugins_button;
-       GtkWidget *encoder_property_holder;
-       GtkWidget *encoder_property_editor;
-       GtkTreeModel *profile_model;
-       GtkTreeModel *preset_model;
 
-       GstElement *encoder_element;
        GList *import_jobs;
        guint start_import_job_id;
-       gulong profile_changed_id;
-       gboolean profile_init;
-       char *preset_name;
        gboolean do_initial_import;
 
        GSettings *settings;
@@ -597,218 +565,11 @@ update_layout_filename (RBLibrarySource *source)
 }
 
 static void
-insert_preset (RBLibrarySource *source, const char *display_name, const char *name, gboolean select)
-{
-       GtkTreeIter iter;
-
-       gtk_list_store_insert_with_values (GTK_LIST_STORE (source->priv->preset_model),
-                                          &iter,
-                                          -1,
-                                          0, display_name,
-                                          1, name,
-                                          -1);
-       if (select) {
-               rb_debug ("preset %s is selected", display_name);
-               gtk_combo_box_set_active_iter (GTK_COMBO_BOX (source->priv->preset_menu), &iter);
-       }
-}
-
-static void
-profile_changed_cb (RBObjectPropertyEditor *editor, RBLibrarySource *source)
-{
-       if (source->priv->profile_init)
-               return;
-
-       if (source->priv->encoder_element) {
-               rb_debug ("updating preset %s", source->priv->preset_name);
-               gst_preset_save_preset (GST_PRESET (source->priv->encoder_element),
-                                                   source->priv->preset_name);
-       }
-}
-
-static void
-update_property_editor_for_preset (RBLibrarySource *source, const char *media_type, const char *preset)
-{
-       int i;
-       int style;
-
-       /* figure out if this is a user-settings preset name */
-       style = -1;
-       for (i = 0; i < G_N_ELEMENTS (library_encoding_styles); i++) {
-               if (g_strcmp0 (preset, library_encoding_styles[i].preset) == 0) {
-                       style = i;
-                       break;
-               }
-       }
-
-       /* remove old property editor, if there is one */
-       if (source->priv->encoder_property_editor != NULL) {
-               g_signal_handler_disconnect (source->priv->encoder_property_editor,
-                                            source->priv->profile_changed_id);
-
-               gtk_container_remove (GTK_CONTAINER (source->priv->encoder_property_holder),
-                                     source->priv->encoder_property_editor);
-               source->priv->profile_changed_id = 0;
-               source->priv->encoder_property_editor = NULL;
-               g_free (source->priv->preset_name);
-               source->priv->preset_name = NULL;
-       }
-
-       /* create new property editor, if required */
-       if (style != -1 && source->priv->encoder_element) {
-               GstEncodingProfile *profile;
-               char **profile_settings;
-
-               /* make sure the preset exists so encoder batches can use it */
-               if (gst_preset_load_preset (GST_PRESET (source->priv->encoder_element), preset) == FALSE) {
-                       if (rb_gst_encoder_set_encoding_style (source->priv->encoder_element,
-                                                              library_encoding_styles[style].style)) {
-                               gst_preset_save_preset (GST_PRESET (source->priv->encoder_element),
-                                                       preset);
-                       }
-               }
-
-               profile = rb_gst_get_encoding_profile (media_type);
-               profile_settings =
-                       rb_gst_encoding_profile_get_settings (profile,
-                                                             library_encoding_styles[style].style);
-               source->priv->encoder_property_editor =
-                       rb_object_property_editor_new (G_OBJECT (source->priv->encoder_element),
-                                                      profile_settings);
-               g_strfreev (profile_settings);
-               gst_encoding_profile_unref (profile);
-
-               source->priv->profile_changed_id =
-                       g_signal_connect (source->priv->encoder_property_editor,
-                                         "changed",
-                                         G_CALLBACK (profile_changed_cb),
-                                         source);
-
-               gtk_grid_attach (GTK_GRID (source->priv->encoder_property_holder),
-                                source->priv->encoder_property_editor,
-                                0, 0, 1, 1);
-               gtk_widget_show_all (source->priv->encoder_property_editor);
-
-               source->priv->preset_name = g_strdup (preset);
-       }
-}
-
-static void
-update_presets (RBLibrarySource *source, const char *media_type)
-{
-       GVariant *preset_settings;
-       char *active_preset;
-       GstEncodingProfile *profile;
-       char **profile_settings;
-       char **profile_presets;
-       int i;
-
-       source->priv->profile_init = TRUE;
-
-       gtk_list_store_clear (GTK_LIST_STORE (source->priv->preset_model));
-
-       if (source->priv->encoder_element != NULL) {
-               gst_object_unref (source->priv->encoder_element);
-               source->priv->encoder_element = NULL;
-       }
-
-       gtk_widget_set_sensitive (source->priv->preset_menu, FALSE);
-       if (media_type == NULL) {
-               source->priv->profile_init = FALSE;
-               return;
-       }
-
-       /* get preset for the media type from settings */
-       preset_settings = g_settings_get_value (source->priv->encoding_settings, "media-type-presets");
-       active_preset = NULL;
-       g_variant_lookup (preset_settings, media_type, "s", &active_preset);
-
-       rb_debug ("active preset for media type %s is %s", media_type, active_preset);
-
-       insert_preset (source,
-                      _("Default settings"),
-                      "",
-                      (active_preset == NULL || active_preset[0] == '\0'));
-
-       profile = rb_gst_get_encoding_profile (media_type);
-       if (profile == NULL) {
-               g_warning ("Don't know how to encode to media type %s", media_type);
-               source->priv->profile_init = FALSE;
-               return;
-       }
-       source->priv->encoder_element = rb_gst_encoding_profile_get_encoder (profile);
-
-       for (i = 0; i < G_N_ELEMENTS (library_encoding_styles); i++) {
-               profile_settings = rb_gst_encoding_profile_get_settings (profile, 
library_encoding_styles[i].style);
-               if (profile_settings == NULL)
-                       continue;
-
-               rb_debug ("profile has custom settings for style %s", library_encoding_styles[i].style);
-               insert_preset (source,
-                              gettext (library_encoding_styles[i].label),
-                              library_encoding_styles[i].preset,
-                              g_strcmp0 (active_preset, library_encoding_styles[i].preset) == 0);
-               gtk_widget_set_sensitive (source->priv->preset_menu, TRUE);
-       }
-
-       /* get list of actual presets for the media type */
-       profile_presets = rb_gst_encoding_profile_get_presets (profile);
-       if (profile_presets) {
-               int i;
-               for (i = 0; profile_presets[i] != NULL; i++) {
-                       if (g_str_has_prefix (profile_presets[i], CUSTOM_SETTINGS_PREFIX))
-                               continue;
-
-                       rb_debug ("profile has preset %s", profile_presets[i]);
-                       insert_preset (source,
-                                      profile_presets[i],
-                                      profile_presets[i],
-                                      g_strcmp0 (profile_presets[i], active_preset) == 0);
-                       gtk_widget_set_sensitive (source->priv->preset_menu, TRUE);
-               }
-               g_strfreev (profile_presets);
-       }
-
-       update_property_editor_for_preset (source, media_type, active_preset);
-
-       gst_encoding_profile_unref (profile);
-       source->priv->profile_init = FALSE;
-}
-
-static void
-update_preferred_media_type (RBLibrarySource *source)
+encoding_settings_changed_cb (GSettings *settings, const char *key, RBLibrarySource *source)
 {
-       GtkTreeIter iter;
-       gboolean done;
-       char *str;
-
-       if (source->priv->profile_model == NULL)
-               return;
-
-       done = FALSE;
-       str = g_settings_get_string (source->priv->encoding_settings, "media-type");
-       if (gtk_tree_model_get_iter_first (source->priv->profile_model, &iter)) {
-               do {
-                       char *media_type;
-
-                       gtk_tree_model_get (source->priv->profile_model, &iter,
-                                           0, &media_type,
-                                           -1);
-                       if (g_strcmp0 (media_type, str) == 0) {
-                               gtk_combo_box_set_active_iter (GTK_COMBO_BOX 
(source->priv->preferred_format_menu), &iter);
-                               update_presets (source, media_type);
-                               done = TRUE;
-                       }
-                       g_free (media_type);
-               } while (done == FALSE && gtk_tree_model_iter_next (source->priv->profile_model, &iter));
-       }
-
-       if (done == FALSE) {
-               gtk_combo_box_set_active_iter (GTK_COMBO_BOX (source->priv->preferred_format_menu), NULL);
-               update_presets (source, NULL);
+       if (g_strcmp0 (key, "media-type") == 0) {
+               update_layout_example_label (source);
        }
-
-       g_free (str);
 }
 
 static void
@@ -832,30 +593,14 @@ library_settings_changed_cb (GSettings *settings, const char *key, RBLibrarySour
        }
 }
 
-static void
-encoding_settings_changed_cb (GSettings *settings, const char *key, RBLibrarySource *source)
-{
-       if (g_strcmp0 (key, "media-type") == 0) {
-               rb_debug ("preferred media type changed");
-               update_preferred_media_type (source);
-       } else if (g_strcmp0 (key, "media-type-presets") == 0) {
-               rb_debug ("media type presets changed");
-               /* need to do anything here?  update selection if the
-                * preset for the preferred media type changed?
-                */
-       }
-}
-
 static GtkWidget *
 impl_get_config_widget (RBDisplayPage *asource, RBShellPreferences *prefs)
 {
        RBLibrarySource *source = RB_LIBRARY_SOURCE (asource);
-       GtkCellRenderer *renderer;
-       GstEncodingTarget *target;
        GtkBuilder *builder;
        GObject *tmp;
        GObject *label;
-       const GList *p;
+       GtkWidget *holder;
        int i;
 
        if (source->priv->config_widget)
@@ -916,62 +661,15 @@ impl_get_config_widget (RBDisplayPage *asource, RBShellPreferences *prefs)
                                                _(library_layout_filenames[i].title));
        }
 
-       target = rb_gst_get_default_encoding_target ();
-       source->priv->profile_model = GTK_TREE_MODEL (gtk_tree_store_new (3, G_TYPE_STRING, G_TYPE_STRING, 
G_TYPE_POINTER));
-       for (p = gst_encoding_target_get_profiles (target); p != NULL; p = p->next) {
-               GstEncodingProfile *profile = GST_ENCODING_PROFILE (p->data);
-               char *media_type;
-
-               media_type = rb_gst_encoding_profile_get_media_type (profile);
-               if (media_type == NULL) {
-                       continue;
-               }
-               gtk_tree_store_insert_with_values (GTK_TREE_STORE (source->priv->profile_model),
-                                                  NULL,
-                                                  NULL,
-                                                  -1,
-                                                  0, media_type,
-                                                  1, gst_encoding_profile_get_description (profile),
-                                                  2, profile,
-                                                  -1);
-               g_free (media_type);
-       }
-
-       source->priv->preset_model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING));
-
-       source->priv->preferred_format_menu = GTK_WIDGET (gtk_builder_get_object (builder, 
"format_select_combo"));
-       gtk_combo_box_set_model (GTK_COMBO_BOX (source->priv->preferred_format_menu), 
source->priv->profile_model);
-       renderer = gtk_cell_renderer_text_new ();
-       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (source->priv->preferred_format_menu), renderer, TRUE);
-       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (source->priv->preferred_format_menu), renderer, 
"text", 1, NULL);
-
-       g_signal_connect (source->priv->preferred_format_menu,
-                         "changed",
-                         G_CALLBACK (rb_library_source_format_changed_cb),
-                         asource);
-
-       source->priv->preset_menu = GTK_WIDGET (gtk_builder_get_object (builder, "preset_select_combo"));
-       gtk_combo_box_set_model (GTK_COMBO_BOX (source->priv->preset_menu), source->priv->preset_model);
-       renderer = gtk_cell_renderer_text_new ();
-       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (source->priv->preset_menu), renderer, TRUE);
-       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (source->priv->preset_menu), renderer, "text", 0, 
NULL);
-
-       g_signal_connect (source->priv->preset_menu,
-                         "changed",
-                         G_CALLBACK (rb_library_source_preset_changed_cb),
-                         asource);
-
+       holder = GTK_WIDGET (gtk_builder_get_object (builder, "encoding_settings_holder"));
+       gtk_container_add (GTK_CONTAINER (holder),
+                          rb_encoding_settings_new (source->priv->encoding_settings,
+                                                    rb_gst_get_default_encoding_target (),
+                                                    FALSE));
 
        source->priv->layout_example_label = GTK_WIDGET (gtk_builder_get_object (builder, 
"layout_example_label"));
 
-       source->priv->install_plugins_button = GTK_WIDGET (gtk_builder_get_object (builder, 
"install_plugins_button"));
-       gtk_widget_set_no_show_all (source->priv->install_plugins_button, TRUE);
-       g_signal_connect (source->priv->install_plugins_button, "clicked", G_CALLBACK 
(rb_library_source_install_plugins_cb), source);
-
-       source->priv->encoder_property_holder = GTK_WIDGET (gtk_builder_get_object (builder, 
"encoder_property_holder"));
-
        update_library_locations (source);
-       update_preferred_media_type (source);
 
        update_layout_path (source);
        update_layout_filename (source);
@@ -1075,170 +773,6 @@ rb_library_source_filename_changed_cb (GtkComboBox *box, RBLibrarySource *source
        }
 }
 
-static void
-rb_library_source_format_changed_cb (GtkWidget *widget, RBLibrarySource *source)
-{
-       GtkTreeIter iter;
-       char *media_type = NULL;
-       GstEncodingProfile *profile;
-       RBEncoder *encoder;
-
-       if (source->priv->profile_init)
-               return;
-
-       /* get selected media type */
-       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE)
-               return;
-       gtk_tree_model_get (GTK_TREE_MODEL (source->priv->profile_model),
-                           &iter,
-                           0, &media_type,
-                           2, &profile,
-                           -1);
-
-       g_settings_set_string (source->priv->encoding_settings, "media-type", media_type);
-
-       update_layout_example_label (source);
-
-       /* indicate whether additional plugins are required to encode in this format */
-       encoder = rb_encoder_new ();
-       if (rb_encoder_get_missing_plugins (encoder, profile, NULL, NULL)) {
-               rb_debug ("additional plugins are required to encode %s", media_type);
-               gtk_widget_set_visible (source->priv->install_plugins_button, TRUE);
-               /* not a great way to handle this situation; probably should describe
-                * the plugins that are missing when automatic install isn't available.
-                */
-               gtk_widget_set_sensitive (source->priv->install_plugins_button,
-                                       gst_install_plugins_supported ());
-       } else {
-               rb_debug ("can encode %s", media_type);
-               gtk_widget_set_visible (source->priv->install_plugins_button, FALSE);
-       }
-       g_free (media_type);
-}
-
-static void
-rb_library_source_preset_changed_cb (GtkWidget *widget, RBLibrarySource *source)
-{
-       GtkTreeIter iter;
-       char *media_type = NULL;
-       char *preset = NULL;
-       char *stored;
-       gboolean have_preset;
-       GVariant *settings;
-
-       if (source->priv->profile_init)
-               return;
-
-       /* get selected media type */
-       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (source->priv->preferred_format_menu), &iter) == 
FALSE) {
-               rb_debug ("no media type selected?");
-               return;
-       }
-       gtk_tree_model_get (GTK_TREE_MODEL (source->priv->profile_model),
-                           &iter,
-                           0, &media_type,
-                           -1);
-
-       /* get selected preset */
-       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (source->priv->preset_menu), &iter)) {
-               gtk_tree_model_get (GTK_TREE_MODEL (source->priv->preset_model),
-                                   &iter,
-                                   1, &preset,
-                                   -1);
-               rb_debug ("preset %s now selected for media type %s", preset, media_type);
-       } else {
-               rb_debug ("no preset selected for media type %s?", media_type);
-       }
-
-       update_property_editor_for_preset (source, media_type, preset);
-
-       /* store selected preset */
-       settings = g_settings_get_value (source->priv->encoding_settings, "media-type-presets");
-       stored = NULL;
-       have_preset = (preset != NULL && preset[0] != '\0');
-       g_variant_lookup (settings, media_type, "s", &stored);
-       if (have_preset == FALSE && (stored == NULL || stored[0] == '\0')) {
-               /* don't bother */
-       } else if (g_strcmp0 (stored, preset) != 0) {
-               GVariantBuilder b;
-               GVariantIter i;
-               char *mt;
-               char *p;
-               gboolean stored;
-
-               g_variant_builder_init (&b, G_VARIANT_TYPE ("a{ss}"));
-               g_variant_iter_init (&i, settings);
-               stored = FALSE;
-               while (g_variant_iter_loop (&i, "{ss}", &mt, &p)) {
-                       if (g_strcmp0 (mt, media_type) == 0) {
-                               if (have_preset) {
-                                       g_variant_builder_add (&b, "{ss}", mt, preset);
-                               }
-                               stored = TRUE;
-                       } else {
-                               g_variant_builder_add (&b, "{ss}", mt, p);
-                               rb_debug ("keeping %s => %s", mt, p);
-                       }
-               }
-
-               if (have_preset && stored == FALSE) {
-                       g_variant_builder_add (&b, "{ss}", media_type, preset);
-               }
-
-               g_settings_set_value (source->priv->encoding_settings, "media-type-presets", 
g_variant_builder_end (&b));
-       }
-       g_variant_unref (settings);
-
-       g_free (stored);
-       g_free (preset);
-       g_free (media_type);
-}
-
-static void
-plugin_install_done_cb (gpointer inst, gboolean retry, RBLibrarySource *source)
-{
-       rb_library_source_format_changed_cb (source->priv->preferred_format_menu, source);
-}
-
-static void
-rb_library_source_install_plugins_cb (GtkWidget *widget, RBLibrarySource *source)
-{
-       char *media_type;
-       GstEncodingProfile *profile;
-       RBEncoder *encoder;
-       char **details;
-       GClosure *closure;
-
-       /* get profile */
-       media_type = g_settings_get_string (source->priv->encoding_settings, "media-type");
-       profile = rb_gst_get_encoding_profile (media_type);
-       if (profile == NULL) {
-               g_warning ("no encoding profile available for %s, so how can we install plugins?",
-                          media_type);
-               g_free (media_type);
-               return;
-       }
-       g_free (media_type);
-
-       /* get plugin details */
-       encoder = rb_encoder_new ();
-       if (rb_encoder_get_missing_plugins (encoder, profile, &details, NULL) == FALSE) {
-               /* what? */
-               g_object_unref (encoder);
-               return;
-       }
-
-       /* attempt installation */
-       closure = g_cclosure_new ((GCallback) plugin_install_done_cb,
-                                 g_object_ref (source),
-                                 (GClosureNotify) g_object_unref);
-       g_closure_set_marshal (closure, g_cclosure_marshal_VOID__BOOLEAN);
-
-       rb_missing_plugins_install ((const char **)details, TRUE, closure);
-
-       g_closure_sink (closure);
-       g_strfreev (details);
-}
 
 /*
  * Perform magic on a path to make it safe.
@@ -1705,9 +1239,6 @@ impl_paste (RBSource *asource, GList *entries)
        preferred_media_type = g_settings_get_string (source->priv->encoding_settings, "media-type");
        profile = rb_gst_get_encoding_profile (preferred_media_type);
        g_free (preferred_media_type);
-       /* have a preset as part of the user settings too?  would that work for containerful streams,
-        * where the interesting settings are on the stream inside the container?
-        */
        if (profile != NULL) {
                gst_encoding_target_add_profile (target, profile);
        }
diff --git a/widgets/Makefile.am b/widgets/Makefile.am
index 65603a0..1820fe2 100644
--- a/widgets/Makefile.am
+++ b/widgets/Makefile.am
@@ -18,7 +18,8 @@ widgetinclude_HEADERS =                                       \
        rb-object-property-editor.h                     \
        rb-import-dialog.h                              \
        rb-button-bar.h                                 \
-       rb-task-list-display.h
+       rb-task-list-display.h                          \
+       rb-encoding-settings.h
 
 librbwidgets_la_SOURCES =                              \
        $(widgetinclude_HEADERS)                        \
@@ -54,7 +55,8 @@ librbwidgets_la_SOURCES =                             \
        rb-object-property-editor.c                     \
        rb-import-dialog.c                              \
        rb-button-bar.c                                 \
-       rb-task-list-display.c
+       rb-task-list-display.c                          \
+       rb-encoding-settings.c
 
 AM_CPPFLAGS =                                          \
        -DGNOMELOCALEDIR=\""$(datadir)/locale"\"        \
@@ -62,12 +64,10 @@ AM_CPPFLAGS =                                               \
        -I$(top_srcdir)                                 \
        -I$(top_srcdir)/lib                             \
        -I$(top_builddir)/lib                           \
-       -I$(top_srcdir)/player                          \
        -I$(top_srcdir)/metadata                        \
        -I$(top_srcdir)/rhythmdb                        \
        -I$(top_srcdir)/sources                         \
        -I$(top_srcdir)/library                         \
-       -I$(top_srcdir)/iradio                          \
        -I$(top_srcdir)/shell                           \
        -I$(top_srcdir)/backends                        \
        $(NOTIFY_CFLAGS)                                \
diff --git a/widgets/rb-encoding-settings.c b/widgets/rb-encoding-settings.c
new file mode 100644
index 0000000..d3949ee
--- /dev/null
+++ b/widgets/rb-encoding-settings.c
@@ -0,0 +1,738 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ *  Copyright (C) 2012 Jonathan Matthew <jonathan d14n org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The Rhythmbox authors hereby grant permission for non-GPL compatible
+ *  GStreamer plugins to be used and distributed together with GStreamer
+ *  and Rhythmbox. This permission is above and beyond the permissions granted
+ *  by the GPL license by which Rhythmbox is covered. If you modify this code
+ *  you may extend this exception to your version of the code, but you are not
+ *  obligated to do so. If you do not wish to do so, delete this exception
+ *  statement from your version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
+ *
+ */
+
+#include <config.h>
+
+#include <glib/gi18n.h>
+
+#include <gst/gst.h>
+#include <gst/pbutils/install-plugins.h>
+
+#include <backends/rb-encoder.h>
+#include <widgets/rb-encoding-settings.h>
+#include <widgets/rb-object-property-editor.h>
+#include <lib/rb-builder-helpers.h>
+#include <lib/rb-util.h>
+#include <lib/rb-debug.h>
+#include <lib/rb-missing-plugins.h>
+
+#define CUSTOM_SETTINGS_PREFIX "rhythmbox-custom-settings"
+#define CBR_SETTINGS_PRESET CUSTOM_SETTINGS_PREFIX "-cbr"
+/* this preset name was used in releases where we only had VBR custom settings */
+#define VBR_SETTINGS_PRESET CUSTOM_SETTINGS_PREFIX
+
+static struct {
+       const char *style;
+       const char *label;
+       const char *preset;
+} encoding_styles[] = {
+       { "cbr", N_("Constant bit rate"), CBR_SETTINGS_PRESET },
+       { "vbr", N_("Variable bit rate"), VBR_SETTINGS_PRESET },
+};
+
+static void rb_encoding_settings_class_init (RBEncodingSettingsClass *klass);
+static void rb_encoding_settings_init (RBEncodingSettings *settings);
+
+struct _RBEncodingSettingsPrivate
+{
+       GSettings *gsettings;
+       GstEncodingTarget *target;
+       GstElement *encoder_element;
+
+       GtkTreeModel *profile_model;
+       GtkTreeModel *preset_model;
+
+       GtkWidget *preferred_format_menu;
+       GtkWidget *preset_menu;
+       GtkWidget *install_plugins_button;
+       GtkWidget *encoder_property_holder;
+       GtkWidget *encoder_property_editor;
+       GtkWidget *lossless_check;
+
+       gboolean show_lossless;
+
+       gboolean profile_init;
+       char *preset_name;
+
+       gulong profile_changed_id;
+};
+
+G_DEFINE_TYPE (RBEncodingSettings, rb_encoding_settings, GTK_TYPE_BOX);
+
+/**
+ * SECTION:rb-encoding-settings
+ * @short_description: encapsulates widgets for editing encoding settings
+ *
+ * RBEncodingSettings provides an interface for selecting and configuring
+ * an encoding profile from an encoding target.
+ */
+
+enum
+{
+       PROP_0,
+       PROP_SETTINGS,
+       PROP_TARGET,
+       PROP_SHOW_LOSSLESS
+};
+
+static void
+profile_changed_cb (RBObjectPropertyEditor *editor, RBEncodingSettings *settings)
+{
+       if (settings->priv->profile_init)
+               return;
+
+       if (settings->priv->encoder_element) {
+               rb_debug ("updating preset %s", settings->priv->preset_name);
+               gst_preset_save_preset (GST_PRESET (settings->priv->encoder_element),
+                                                   settings->priv->preset_name);
+       }
+}
+
+static void
+update_property_editor_for_preset (RBEncodingSettings *settings, const char *media_type, const char *preset)
+{
+       int i;
+       int style;
+
+       /* figure out if this is a user-settings preset name */
+       style = -1;
+       for (i = 0; i < G_N_ELEMENTS (encoding_styles); i++) {
+               if (g_strcmp0 (preset, encoding_styles[i].preset) == 0) {
+                       style = i;
+                       break;
+               }
+       }
+
+       /* remove old property editor, if there is one */
+       if (settings->priv->encoder_property_editor != NULL) {
+               g_signal_handler_disconnect (settings->priv->encoder_property_editor,
+                                            settings->priv->profile_changed_id);
+
+               gtk_container_remove (GTK_CONTAINER (settings->priv->encoder_property_holder),
+                                     settings->priv->encoder_property_editor);
+               settings->priv->profile_changed_id = 0;
+               settings->priv->encoder_property_editor = NULL;
+               g_free (settings->priv->preset_name);
+               settings->priv->preset_name = NULL;
+       }
+
+       /* create new property editor, if required */
+       if (style != -1 && settings->priv->encoder_element) {
+               GstEncodingProfile *profile;
+               char **profile_settings;
+
+               /* make sure the preset exists so encoder batches can use it */
+               if (gst_preset_load_preset (GST_PRESET (settings->priv->encoder_element), preset) == FALSE) {
+                       if (rb_gst_encoder_set_encoding_style (settings->priv->encoder_element,
+                                                              encoding_styles[style].style)) {
+                               gst_preset_save_preset (GST_PRESET (settings->priv->encoder_element),
+                                                       preset);
+                       }
+               }
+
+               profile = rb_gst_get_encoding_profile (media_type);
+               profile_settings =
+                       rb_gst_encoding_profile_get_settings (profile,
+                                                             encoding_styles[style].style);
+               settings->priv->encoder_property_editor =
+                       rb_object_property_editor_new (G_OBJECT (settings->priv->encoder_element),
+                                                      profile_settings);
+               g_strfreev (profile_settings);
+               gst_encoding_profile_unref (profile);
+
+               settings->priv->profile_changed_id =
+                       g_signal_connect (settings->priv->encoder_property_editor,
+                                         "changed",
+                                         G_CALLBACK (profile_changed_cb),
+                                         settings);
+
+               gtk_grid_attach (GTK_GRID (settings->priv->encoder_property_holder),
+                                settings->priv->encoder_property_editor,
+                                0, 0, 1, 1);
+               gtk_widget_show_all (settings->priv->encoder_property_editor);
+
+               settings->priv->preset_name = g_strdup (preset);
+       }
+}
+
+static void
+format_changed_cb (GtkWidget *widget, RBEncodingSettings *settings)
+{
+       GtkTreeIter iter;
+       char *media_type = NULL;
+       GstEncodingProfile *profile;
+       RBEncoder *encoder;
+
+       if (settings->priv->profile_init)
+               return;
+
+       /* get selected media type */
+       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE)
+               return;
+       gtk_tree_model_get (GTK_TREE_MODEL (settings->priv->profile_model),
+                           &iter,
+                           0, &media_type,
+                           2, &profile,
+                           -1);
+
+       g_settings_set_string (settings->priv->gsettings, "media-type", media_type);
+
+       /* indicate whether additional plugins are required to encode in this format */
+       encoder = rb_encoder_new ();
+       if (rb_encoder_get_missing_plugins (encoder, profile, NULL, NULL)) {
+               rb_debug ("additional plugins are required to encode %s", media_type);
+               gtk_widget_set_visible (settings->priv->install_plugins_button, TRUE);
+               /* not a great way to handle this situation; probably should describe
+                * the plugins that are missing when automatic install isn't available.
+                */
+               gtk_widget_set_sensitive (settings->priv->install_plugins_button,
+                                         gst_install_plugins_supported ());
+       } else {
+               rb_debug ("can encode %s", media_type);
+               gtk_widget_set_visible (settings->priv->install_plugins_button, FALSE);
+       }
+
+       gtk_widget_set_sensitive (settings->priv->lossless_check, rb_gst_media_type_is_lossless (media_type) 
== FALSE);
+
+       g_free (media_type);
+}
+
+static void
+preset_changed_cb (GtkWidget *widget, RBEncodingSettings *settings)
+{
+       GtkTreeIter iter;
+       char *media_type = NULL;
+       char *preset = NULL;
+       char *stored;
+       gboolean have_preset;
+       GVariant *presets;
+
+       if (settings->priv->profile_init)
+               return;
+
+       /* get selected media type */
+       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (settings->priv->preferred_format_menu), &iter) == 
FALSE) {
+               rb_debug ("no media type selected?");
+               return;
+       }
+       gtk_tree_model_get (GTK_TREE_MODEL (settings->priv->profile_model),
+                           &iter,
+                           0, &media_type,
+                           -1);
+
+       /* get selected preset */
+       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (settings->priv->preset_menu), &iter)) {
+               gtk_tree_model_get (GTK_TREE_MODEL (settings->priv->preset_model),
+                                   &iter,
+                                   1, &preset,
+                                   -1);
+               rb_debug ("preset %s now selected for media type %s", preset, media_type);
+       } else {
+               rb_debug ("no preset selected for media type %s?", media_type);
+       }
+
+       update_property_editor_for_preset (settings, media_type, preset);
+
+       /* store selected preset */
+       presets = g_settings_get_value (settings->priv->gsettings, "media-type-presets");
+       stored = NULL;
+       have_preset = (preset != NULL && preset[0] != '\0');
+       g_variant_lookup (presets, media_type, "s", &stored);
+       if (have_preset == FALSE && (stored == NULL || stored[0] == '\0')) {
+               /* don't bother */
+       } else if (g_strcmp0 (stored, preset) != 0) {
+               GVariantBuilder b;
+               GVariantIter i;
+               char *mt;
+               char *p;
+               gboolean stored;
+
+               g_variant_builder_init (&b, G_VARIANT_TYPE ("a{ss}"));
+               g_variant_iter_init (&i, presets);
+               stored = FALSE;
+               while (g_variant_iter_loop (&i, "{ss}", &mt, &p)) {
+                       if (g_strcmp0 (mt, media_type) == 0) {
+                               if (have_preset) {
+                                       g_variant_builder_add (&b, "{ss}", mt, preset);
+                               }
+                               stored = TRUE;
+                       } else {
+                               g_variant_builder_add (&b, "{ss}", mt, p);
+                               rb_debug ("keeping %s => %s", mt, p);
+                       }
+               }
+
+               if (have_preset && stored == FALSE) {
+                       g_variant_builder_add (&b, "{ss}", media_type, preset);
+               }
+
+               g_settings_set_value (settings->priv->gsettings, "media-type-presets", g_variant_builder_end 
(&b));
+       }
+       g_variant_unref (presets);
+
+       g_free (stored);
+       g_free (preset);
+       g_free (media_type);
+}
+
+static void
+plugin_install_done_cb (gpointer inst, gboolean retry, RBEncodingSettings *settings)
+{
+       format_changed_cb (settings->priv->preferred_format_menu, settings);
+}
+
+static void
+install_plugins_cb (GtkWidget *widget, RBEncodingSettings *settings)
+{
+       char *media_type;
+       GstEncodingProfile *profile;
+       RBEncoder *encoder;
+       char **details;
+       GClosure *closure;
+
+       /* get profile */
+       media_type = g_settings_get_string (settings->priv->gsettings, "media-type");
+       profile = rb_gst_get_encoding_profile (media_type);
+       if (profile == NULL) {
+               g_warning ("no encoding profile available for %s, so how can we install plugins?",
+                          media_type);
+               g_free (media_type);
+               return;
+       }
+       g_free (media_type);
+
+       /* get plugin details */
+       encoder = rb_encoder_new ();
+       if (rb_encoder_get_missing_plugins (encoder, profile, &details, NULL) == FALSE) {
+               /* what? */
+               g_object_unref (encoder);
+               return;
+       }
+
+       /* attempt installation */
+       closure = g_cclosure_new ((GCallback) plugin_install_done_cb,
+                                 g_object_ref (settings),
+                                 (GClosureNotify) g_object_unref);
+       g_closure_set_marshal (closure, g_cclosure_marshal_VOID__BOOLEAN);
+
+       rb_missing_plugins_install ((const char **)details, TRUE, closure);
+
+       g_closure_sink (closure);
+       g_strfreev (details);
+}
+
+static void
+insert_preset (RBEncodingSettings *settings, const char *display_name, const char *name, gboolean select)
+{
+       GtkTreeIter iter;
+
+       gtk_list_store_insert_with_values (GTK_LIST_STORE (settings->priv->preset_model),
+                                          &iter,
+                                          -1,
+                                          0, display_name,
+                                          1, name,
+                                          -1);
+       if (select) {
+               rb_debug ("preset %s is selected", display_name);
+               gtk_combo_box_set_active_iter (GTK_COMBO_BOX (settings->priv->preset_menu), &iter);
+       }
+}
+
+
+static void
+update_presets (RBEncodingSettings *settings, const char *media_type)
+{
+       GVariant *preset_settings;
+       char *active_preset;
+       GstEncodingProfile *profile;
+       char **profile_settings;
+       char **profile_presets;
+       int i;
+
+       settings->priv->profile_init = TRUE;
+
+       gtk_list_store_clear (GTK_LIST_STORE (settings->priv->preset_model));
+
+       if (settings->priv->encoder_element != NULL) {
+               gst_object_unref (settings->priv->encoder_element);
+               settings->priv->encoder_element = NULL;
+       }
+
+       gtk_widget_set_sensitive (settings->priv->preset_menu, FALSE);
+       if (media_type == NULL) {
+               settings->priv->profile_init = FALSE;
+               return;
+       }
+
+       /* get preset for the media type from settings */
+       preset_settings = g_settings_get_value (settings->priv->gsettings, "media-type-presets");
+       active_preset = NULL;
+       g_variant_lookup (preset_settings, media_type, "s", &active_preset);
+
+       rb_debug ("active preset for media type %s is %s", media_type, active_preset);
+
+       insert_preset (settings,
+                      _("Default settings"),
+                      "",
+                      (active_preset == NULL || active_preset[0] == '\0'));
+
+       profile = rb_gst_get_encoding_profile (media_type);
+       if (profile == NULL) {
+               g_warning ("Don't know how to encode to media type %s", media_type);
+               settings->priv->profile_init = FALSE;
+               return;
+       }
+       settings->priv->encoder_element = rb_gst_encoding_profile_get_encoder (profile);
+
+       for (i = 0; i < G_N_ELEMENTS (encoding_styles); i++) {
+               profile_settings = rb_gst_encoding_profile_get_settings (profile, encoding_styles[i].style);
+               if (profile_settings == NULL)
+                       continue;
+
+               rb_debug ("profile has custom settings for style %s", encoding_styles[i].style);
+               insert_preset (settings,
+                              gettext (encoding_styles[i].label),
+                              encoding_styles[i].preset,
+                              g_strcmp0 (active_preset, encoding_styles[i].preset) == 0);
+               gtk_widget_set_sensitive (settings->priv->preset_menu, TRUE);
+       }
+
+       /* get list of actual presets for the media type */
+       profile_presets = rb_gst_encoding_profile_get_presets (profile);
+       if (profile_presets) {
+               int i;
+               for (i = 0; profile_presets[i] != NULL; i++) {
+                       if (g_str_has_prefix (profile_presets[i], CUSTOM_SETTINGS_PREFIX))
+                               continue;
+
+                       rb_debug ("profile has preset %s", profile_presets[i]);
+                       insert_preset (settings,
+                                      profile_presets[i],
+                                      profile_presets[i],
+                                      g_strcmp0 (profile_presets[i], active_preset) == 0);
+                       gtk_widget_set_sensitive (settings->priv->preset_menu, TRUE);
+               }
+               g_strfreev (profile_presets);
+       }
+
+       update_property_editor_for_preset (settings, media_type, active_preset);
+
+       gst_encoding_profile_unref (profile);
+       settings->priv->profile_init = FALSE;
+}
+
+static void
+update_preferred_media_type (RBEncodingSettings *settings)
+{
+       GtkTreeIter iter;
+       gboolean done;
+       char *str;
+
+       done = FALSE;
+       str = g_settings_get_string (settings->priv->gsettings, "media-type");
+       if (gtk_tree_model_get_iter_first (settings->priv->profile_model, &iter)) {
+               do {
+                       char *media_type;
+
+                       gtk_tree_model_get (settings->priv->profile_model, &iter,
+                                           0, &media_type,
+                                           -1);
+                       if (g_strcmp0 (media_type, str) == 0) {
+                               gtk_combo_box_set_active_iter (GTK_COMBO_BOX 
(settings->priv->preferred_format_menu), &iter);
+                               update_presets (settings, media_type);
+                               done = TRUE;
+                       }
+                       g_free (media_type);
+               } while (done == FALSE && gtk_tree_model_iter_next (settings->priv->profile_model, &iter));
+       }
+
+       if (done == FALSE) {
+               gtk_combo_box_set_active_iter (GTK_COMBO_BOX (settings->priv->preferred_format_menu), NULL);
+               update_presets (settings, NULL);
+       }
+
+       g_free (str);
+}
+
+static void
+encoding_settings_changed_cb (GSettings *gsettings, const char *key, RBEncodingSettings *settings)
+{
+       if (g_strcmp0 (key, "media-type") == 0) {
+               rb_debug ("preferred media type changed");
+               update_preferred_media_type (settings);
+       } else if (g_strcmp0 (key, "media-type-presets") == 0) {
+               rb_debug ("media type presets changed");
+               /* need to do anything here?  update selection if the
+                * preset for the preferred media type changed?
+                */
+       }
+}
+
+static void
+impl_constructed (GObject *object)
+{
+       RBEncodingSettings *settings;
+       GtkBuilder *builder;
+       GtkWidget *grid;
+       GtkCellRenderer *renderer;
+       const GList *p;
+
+       RB_CHAIN_GOBJECT_METHOD (rb_encoding_settings_parent_class, constructed, object);
+
+       settings = RB_ENCODING_SETTINGS (object);
+
+       g_signal_connect_object (settings->priv->gsettings,
+                                "changed",
+                                G_CALLBACK (encoding_settings_changed_cb),
+                                settings, 0);
+
+       builder = rb_builder_load ("encoding-settings.ui", NULL);
+       grid = GTK_WIDGET (gtk_builder_get_object (builder, "encoding-settings-grid"));
+       gtk_container_add (GTK_CONTAINER (settings), grid);
+
+       settings->priv->profile_model = GTK_TREE_MODEL (gtk_tree_store_new (3, G_TYPE_STRING, G_TYPE_STRING, 
G_TYPE_POINTER));
+       for (p = gst_encoding_target_get_profiles (settings->priv->target); p != NULL; p = p->next) {
+               GstEncodingProfile *profile = GST_ENCODING_PROFILE (p->data);
+               char *media_type;
+
+               media_type = rb_gst_encoding_profile_get_media_type (profile);
+               if (media_type == NULL) {
+                       continue;
+               }
+               gtk_tree_store_insert_with_values (GTK_TREE_STORE (settings->priv->profile_model),
+                                                  NULL,
+                                                  NULL,
+                                                  -1,
+                                                  0, media_type,
+                                                  1, gst_encoding_profile_get_description (profile),
+                                                  2, profile,
+                                                  -1);
+               g_free (media_type);
+       }
+
+       settings->priv->preset_model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING));
+
+       settings->priv->preferred_format_menu = GTK_WIDGET (gtk_builder_get_object (builder, 
"format_select_combo"));
+       gtk_combo_box_set_model (GTK_COMBO_BOX (settings->priv->preferred_format_menu), 
settings->priv->profile_model);
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (settings->priv->preferred_format_menu), renderer, TRUE);
+       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (settings->priv->preferred_format_menu), renderer, 
"text", 1, NULL);
+
+       g_signal_connect (G_OBJECT (settings->priv->preferred_format_menu),
+                         "changed",
+                         G_CALLBACK (format_changed_cb),
+                         settings);
+
+       settings->priv->preset_menu = GTK_WIDGET (gtk_builder_get_object (builder, "preset_select_combo"));
+       gtk_combo_box_set_model (GTK_COMBO_BOX (settings->priv->preset_menu), settings->priv->preset_model);
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (settings->priv->preset_menu), renderer, TRUE);
+       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (settings->priv->preset_menu), renderer, "text", 0, 
NULL);
+
+       g_signal_connect (G_OBJECT (settings->priv->preset_menu),
+                         "changed",
+                         G_CALLBACK (preset_changed_cb),
+                         settings);
+
+       settings->priv->install_plugins_button = GTK_WIDGET (gtk_builder_get_object (builder, 
"install_plugins_button"));
+       gtk_widget_set_no_show_all (settings->priv->install_plugins_button, TRUE);
+       g_signal_connect (G_OBJECT (settings->priv->install_plugins_button),
+                         "clicked",
+                         G_CALLBACK (install_plugins_cb),
+                         settings);
+
+       settings->priv->encoder_property_holder = GTK_WIDGET (gtk_builder_get_object (builder, 
"encoder_property_holder"));
+
+       settings->priv->lossless_check = GTK_WIDGET (gtk_builder_get_object (builder, 
"transcode_lossless_check"));
+       gtk_widget_set_no_show_all (settings->priv->lossless_check, TRUE);
+       if (settings->priv->show_lossless) {
+               gtk_widget_show (settings->priv->lossless_check);
+               g_settings_bind (settings->priv->gsettings,
+                                "transcode-lossless",
+                                settings->priv->lossless_check,
+                                "active",
+                                G_SETTINGS_BIND_DEFAULT);
+       } else {
+               gtk_widget_hide (settings->priv->lossless_check);
+       }
+
+       update_preferred_media_type (settings);
+
+       g_object_unref (builder);
+}
+
+static void
+impl_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+       RBEncodingSettings *settings = RB_ENCODING_SETTINGS (object);
+       switch (prop_id) {
+       case PROP_SETTINGS:
+               settings->priv->gsettings = g_value_dup_object (value);
+               break;
+       case PROP_TARGET:
+               settings->priv->target = GST_ENCODING_TARGET (g_value_dup_object (value));
+               break;
+       case PROP_SHOW_LOSSLESS:
+               settings->priv->show_lossless = g_value_get_boolean (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+       }
+}
+
+static void
+impl_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+       RBEncodingSettings *settings = RB_ENCODING_SETTINGS (object);
+       switch (prop_id) {
+       case PROP_SETTINGS:
+               g_value_set_object (value, settings->priv->gsettings);
+               break;
+       case PROP_TARGET:
+               g_value_set_object (value, GST_MINI_OBJECT (settings->priv->target));
+               break;
+       case PROP_SHOW_LOSSLESS:
+               g_value_set_boolean (value, settings->priv->show_lossless);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+       }
+}
+
+static void
+rb_encoding_settings_init (RBEncodingSettings *settings)
+{
+       settings->priv = G_TYPE_INSTANCE_GET_PRIVATE (settings,
+                                                     RB_TYPE_ENCODING_SETTINGS,
+                                                     RBEncodingSettingsPrivate);
+}
+
+static void
+impl_dispose (GObject *object)
+{
+       RBEncodingSettings *settings = RB_ENCODING_SETTINGS (object);
+
+       if (settings->priv->gsettings != NULL) {
+               g_object_unref (settings->priv->gsettings);
+               settings->priv->gsettings = NULL;
+       }
+
+       if (settings->priv->target != NULL) {
+               g_object_unref (settings->priv->target);
+               settings->priv->target = NULL;
+       }
+
+       /* models and widgets and crap? */
+
+       G_OBJECT_CLASS (rb_encoding_settings_parent_class)->dispose (object);
+}
+
+static void
+impl_finalize (GObject *object)
+{
+       RBEncodingSettings *settings = RB_ENCODING_SETTINGS (object);
+
+       g_free (settings->priv->preset_name);
+
+       G_OBJECT_CLASS (rb_encoding_settings_parent_class)->finalize (object);
+}
+
+
+static void
+rb_encoding_settings_class_init (RBEncodingSettingsClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->constructed = impl_constructed;
+       object_class->dispose = impl_dispose;
+       object_class->finalize = impl_finalize;
+       object_class->set_property = impl_set_property;
+       object_class->get_property = impl_get_property;
+
+       /**
+        * RBEncodingSettings:settings
+        *
+        * GSettings instance holding the settings to edit.
+        */
+       g_object_class_install_property (object_class,
+                                        PROP_SETTINGS,
+                                        g_param_spec_object ("settings",
+                                                             "settings",
+                                                             "GSettings instance to edit",
+                                                             G_TYPE_OBJECT,
+                                                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+       /**
+        * RBEncodingSettings:encoding-target
+        *
+        * The encoding target to select a profile from.
+        */
+       g_object_class_install_property (object_class,
+                                        PROP_TARGET,
+                                        g_param_spec_object ("encoding-target",
+                                                             "encoding target",
+                                                             "GstEncodingTarget",
+                                                             GST_TYPE_ENCODING_TARGET,
+                                                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+       /**
+        * RBEncodingSettings:show-lossless
+        *
+        * If %TRUE, show widgets for controlling lossless encodings.
+        */
+       g_object_class_install_property (object_class,
+                                        PROP_SHOW_LOSSLESS,
+                                        g_param_spec_boolean ("show-lossless",
+                                                              "show-lossless",
+                                                              "whether to show options relating to lossless 
encodings",
+                                                              FALSE,
+                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+       g_type_class_add_private (klass, sizeof (RBEncodingSettingsPrivate));
+}
+
+/**
+ * rb_encoding_settings_new:
+ * @settings: the #GSettings instance to edit
+ * @target: the #GstEncodingTarget to select a profile from
+ * @show_lossless: show widgets for controlling lossless encodings
+ *
+ * Creates widgets for selecting and configuring an encoding
+ * profile from @target.
+ *
+ * Return value: encoding settings widget.
+ */
+GtkWidget *
+rb_encoding_settings_new (GSettings *settings, GstEncodingTarget *target, gboolean show_lossless)
+{
+       return GTK_WIDGET (g_object_new (RB_TYPE_ENCODING_SETTINGS,
+                                        "settings", settings,
+                                        "encoding-target", target,
+                                        "show-lossless", show_lossless,
+                                        NULL));
+}
diff --git a/widgets/rb-encoding-settings.h b/widgets/rb-encoding-settings.h
new file mode 100644
index 0000000..07f38d8
--- /dev/null
+++ b/widgets/rb-encoding-settings.h
@@ -0,0 +1,66 @@
+/*
+ *  Copyright (C) 2012  Jonathan Matthew <jonathan d14n org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The Rhythmbox authors hereby grant permission for non-GPL compatible
+ *  GStreamer plugins to be used and distributed together with GStreamer
+ *  and Rhythmbox. This permission is above and beyond the permissions granted
+ *  by the GPL license by which Rhythmbox is covered. If you modify this code
+ *  you may extend this exception to your version of the code, but you are not
+ *  obligated to do so. If you do not wish to do so, delete this exception
+ *  statement from your version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
+ *
+ */
+
+#include <gtk/gtk.h>
+
+#include <lib/rb-gst-media-types.h>
+
+#ifndef RB_ENCODING_SETTINGS_H
+#define RB_ENCODING_SETTINGS_H
+
+G_BEGIN_DECLS
+
+#define RB_TYPE_ENCODING_SETTINGS         (rb_encoding_settings_get_type ())
+#define RB_ENCODING_SETTINGS(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), RB_TYPE_ENCODING_SETTINGS, 
RBEncodingSettings))
+#define RB_ENCODING_SETTINGS_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), RB_TYPE_ENCODING_SETTINGS, 
RBEncodingSettingsClass))
+#define RB_IS_ENCODING_SETTINGS(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), RB_TYPE_ENCODING_SETTINGS))
+#define RB_IS_ENCODING_SETTINGS_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), RB_TYPE_ENCODING_SETTINGS))
+#define RB_ENCODING_SETTINGS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), RB_TYPE_ENCODING_SETTINGS, 
RBEncodingSettingsClass))
+
+typedef struct _RBEncodingSettings RBEncodingSettings;
+typedef struct _RBEncodingSettingsClass RBEncodingSettingsClass;
+typedef struct _RBEncodingSettingsPrivate RBEncodingSettingsPrivate;
+
+struct _RBEncodingSettings
+{
+       GtkBox parent;
+
+       RBEncodingSettingsPrivate *priv;
+};
+
+struct _RBEncodingSettingsClass
+{
+       GtkBoxClass parent_class;
+};
+
+GType          rb_encoding_settings_get_type (void);
+
+GtkWidget *    rb_encoding_settings_new (GSettings *settings, GstEncodingTarget *target, gboolean 
show_lossless);
+
+G_END_DECLS
+
+#endif /* RB_ENCODING_SETTINGS_H */


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