we always only use the "C" locale when saving.
[ardour.git] / gtk2_ardour / ui_config.cc
index 915c1176829a455d403d57d8bce1ff37ff979cff..354539b57b07cadfe446a7299bea55171b5b617e 100644 (file)
 
 */
 
+#if !defined USE_CAIRO_IMAGE_SURFACE && !defined NDEBUG
+#define OPTIONAL_CAIRO_IMAGE_SURFACE
+#endif
+
 #include <iostream>
 #include <sstream>
 #include <unistd.h>
 #include <cstdlib>
 #include <cstdio> /* for snprintf, grrr */
 
+#include <cairo/cairo.h>
+
+#include <pango/pangoft2.h> // for fontmap resolution control for GnomeCanvas
+#include <pango/pangocairo.h> // for fontmap resolution control for GnomeCanvas
+
+#include "pbd/gstdio_compat.h"
 #include <glibmm/miscutils.h>
-#include <glib/gstdio.h>
 
+#include <gtkmm/settings.h>
+
+#include "pbd/convert.h"
 #include "pbd/failed_constructor.h"
 #include "pbd/xml++.h"
 #include "pbd/file_utils.h"
+#include "pbd/locale_guard.h"
 #include "pbd/error.h"
 #include "pbd/stacktrace.h"
 
@@ -36,9 +49,8 @@
 #include "gtkmm2ext/gtk_ui.h"
 
 #include "ardour/filesystem_paths.h"
+#include "ardour/utils.h"
 
-#include "ardour_ui.h"
-#include "global_signals.h"
 #include "ui_config.h"
 
 #include "i18n.h"
@@ -50,10 +62,16 @@ using namespace ArdourCanvas;
 
 static const char* ui_config_file_name = "ui_config";
 static const char* default_ui_config_file_name = "default_ui_config";
-UIConfiguration* UIConfiguration::_instance = 0;
 
 static const double hue_width = 18.0;
 
+UIConfiguration&
+UIConfiguration::instance ()
+{
+       static UIConfiguration s_instance;
+       return s_instance;
+}
+
 UIConfiguration::UIConfiguration ()
        :
 #undef  UI_CONFIG_VARIABLE
@@ -64,53 +82,17 @@ UIConfiguration::UIConfiguration ()
 #undef  UI_CONFIG_VARIABLE
 #undef  CANVAS_FONT_VARIABLE
 
-       /* initialize all the base colors using default
-          colors for now. these will be reset when/if
-          we load the UI config file.
-       */
-
-#undef CANVAS_BASE_COLOR
-#define CANVAS_BASE_COLOR(var,name,val) var (name,quantized (val)),
-#include "base_colors.h"
-#undef CANVAS_BASE_COLOR
-
        _dirty (false),
        aliases_modified (false),
-       derived_modified (false),
-       _saved_state_node (""),
-       _saved_state_version (-1)
-       
+       colors_modified (false),
+       modifiers_modified (false),
+       block_save (0)
 {
-       _instance = this;
-
-       /* pack all base colors into the configurable color map so that
-          derived colors can use them.
-       */
-         
-#undef CANVAS_BASE_COLOR
-#define CANVAS_BASE_COLOR(var,name,color) configurable_colors.insert (make_pair (name,&var));
-#include "base_colors.h"
-#undef CANVAS_BASE_COLOR
-
-#undef CANVAS_COLOR
-#define CANVAS_COLOR(var,name,base,modifier) relative_colors.insert (make_pair (name, RelativeHSV (base,modifier)));
-#include "colors.h"
-#undef CANVAS_COLOR
-       
-#undef COLOR_ALIAS
-#define COLOR_ALIAS(var,name,alias) color_aliases.insert (make_pair (name,alias));
-#include "color_aliases.h"
-#undef CANVAS_COLOR
-
        load_state();
 
-       ARDOUR_UI_UTILS::ColorsChanged.connect (boost::bind (&UIConfiguration::colors_changed, this));
+       ColorsChanged.connect (boost::bind (&UIConfiguration::colors_changed, this));
 
        ParameterChanged.connect (sigc::mem_fun (*this, &UIConfiguration::parameter_changed));
-
-       /* force GTK theme setting, so that RC file will work */
-       
-       reset_gtk_theme ();
 }
 
 UIConfiguration::~UIConfiguration ()
@@ -120,8 +102,6 @@ UIConfiguration::~UIConfiguration ()
 void
 UIConfiguration::colors_changed ()
 {
-       _dirty = true;
-
        reset_gtk_theme ();
 
        /* In theory, one of these ought to work:
@@ -133,16 +113,18 @@ UIConfiguration::colors_changed ()
           GTK RC file, which causes a reset of all styles and a redraw
        */
 
-       parameter_changed ("ui-rc_file");
+       parameter_changed ("ui-rc-file");
 }
 
 void
 UIConfiguration::parameter_changed (string param)
 {
        _dirty = true;
-       
+
        if (param == "ui-rc-file") {
-               load_rc_file (get_ui_rc_file(), true);
+               load_rc_file (true);
+       } else if (param == "color-file") {
+               load_color_theme ();
        }
 
        save_state ();
@@ -154,11 +136,10 @@ UIConfiguration::reset_gtk_theme ()
        stringstream ss;
 
        ss << "gtk_color_scheme = \"" << hex;
-       
+
        for (ColorAliases::iterator g = color_aliases.begin(); g != color_aliases.end(); ++g) {
-               
+
                if (g->first.find ("gtk_") == 0) {
-                       ColorAliases::const_iterator a = color_aliases.find (g->first);
                        const string gtk_name = g->first.substr (4);
                        ss << gtk_name << ":#" << std::setw (6) << setfill ('0') << (color (g->second) >> 8) << ';';
                }
@@ -170,65 +151,39 @@ UIConfiguration::reset_gtk_theme ()
 
        Gtk::Settings::get_default()->property_gtk_color_scheme() = ss.str();
 }
-       
-UIConfiguration::RelativeHSV
-UIConfiguration::color_as_relative_hsv (Color c)
+
+void
+UIConfiguration::reset_dpi ()
 {
-       HSV variable (c);
-       HSV closest;
-       double shortest_distance = DBL_MAX;
-       string closest_name;
+       long val = get_font_scale();
+       set_pango_fontsize ();
+       /* Xft rendering */
 
-       map<string,ColorVariable<Color>*>::iterator f;
-       std::map<std::string,HSV> palette;
+       gtk_settings_set_long_property (gtk_settings_get_default(),
+                                       "gtk-xft-dpi", val, "ardour");
+       DPIReset(); //Emit Signal
+}
 
-       for (f = configurable_colors.begin(); f != configurable_colors.end(); ++f) {
-               palette.insert (make_pair (f->first, HSV (f->second->get())));
-       }
+void
+UIConfiguration::set_pango_fontsize ()
+{
+       long val = get_font_scale();
 
-       for (map<string,HSV>::iterator f = palette.begin(); f != palette.end(); ++f) {
-               
-               double d;
-               HSV fixed (f->second);
-               
-               if (fixed.is_gray() || variable.is_gray()) {
-                       /* at least one is achromatic; HSV::distance() will do
-                        * the right thing
-                        */
-                       d = fixed.distance (variable);
-               } else {
-                       /* chromatic: compare ONLY hue because our task is
-                          to pick the HUE closest and then compute
-                          a modifier. We want to keep the number of 
-                          hues low, and by computing perceptual distance 
-                          we end up finding colors that are to each
-                          other without necessarily be close in hue.
-                       */
-                       d = fabs (variable.h - fixed.h);
-               }
+       /* FT2 rendering - used by GnomeCanvas, sigh */
 
-               if (d < shortest_distance) {
-                       closest = fixed;
-                       closest_name = f->first;
-                       shortest_distance = d;
-               }
-       }
-       
-       /* we now know the closest color of the fixed colors to 
-          this variable color. Compute the HSV diff and
-          use it to redefine the variable color in terms of the
-          fixed one.
-       */
-       
-       HSV delta = variable.delta (closest);
+#ifndef PLATFORM_WINDOWS
+       pango_ft2_font_map_set_resolution ((PangoFT2FontMap*) pango_ft2_font_map_new(), val/1024, val/1024);
+#endif
 
-       /* quantize hue delta so we don't end up with many subtle hues caused
-        * by original color choices
-        */
+       /* Cairo rendering, in case there is any */
 
-       delta.h = hue_width * (round (delta.h/hue_width));
+       pango_cairo_font_map_set_resolution ((PangoCairoFontMap*) pango_cairo_font_map_get_default(), val/1024);
+}
 
-       return RelativeHSV (closest_name, delta);
+float
+UIConfiguration::get_ui_scale ()
+{
+       return get_font_scale () / 102400.;
 }
 
 void
@@ -240,34 +195,163 @@ UIConfiguration::map_parameters (boost::function<void (std::string)>& functor)
 #undef  UI_CONFIG_VARIABLE
 }
 
+int
+UIConfiguration::pre_gui_init ()
+{
+#ifdef CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE
+       if (get_buggy_gradients()) {
+               g_setenv ("FORCE_BUGGY_GRADIENTS", "1", 1);
+       }
+#endif
+#ifdef OPTIONAL_CAIRO_IMAGE_SURFACE
+       if (get_cairo_image_surface()) {
+               g_setenv ("ARDOUR_IMAGE_SURFACE", "1", 1);
+       }
+#endif
+       return 0;
+}
+
+UIConfiguration*
+UIConfiguration::post_gui_init ()
+{
+       load_color_theme ();
+       return this;
+}
+
 int
 UIConfiguration::load_defaults ()
 {
-       int found = 0;
         std::string rcfile;
+       int ret = -1;
 
        if (find_file (ardour_config_search_path(), default_ui_config_file_name, rcfile) ) {
                XMLTree tree;
-               found = 1;
 
                info << string_compose (_("Loading default ui configuration file %1"), rcfile) << endmsg;
 
                if (!tree.read (rcfile.c_str())) {
                        error << string_compose(_("cannot read default ui configuration file \"%1\""), rcfile) << endmsg;
+               } else {
+                       if (set_state (*tree.root(), Stateful::loading_state_version)) {
+                               error << string_compose(_("default ui configuration file \"%1\" not loaded successfully."), rcfile) << endmsg;
+                       } else {
+                               _dirty = false;
+                               ret = 0;
+                       }
+               }
+
+       } else {
+               warning << string_compose (_("Could not find default UI configuration file %1"), default_ui_config_file_name) << endmsg;
+       }
+
+
+       if (ret == 0) {
+               /* reload color theme */
+               load_color_theme (false);
+               ColorsChanged (); /* EMIT SIGNAL */
+       }
+
+       return ret;
+}
+
+int
+UIConfiguration::load_color_theme (bool allow_own)
+{
+       std::string cfile;
+       string basename;
+       bool found = false;
+
+       if (allow_own) {
+               basename = "my-";
+               basename += color_file.get();
+               basename += ".colors";
+
+               if (find_file (ardour_config_search_path(), basename, cfile)) {
+                       found = true;
+               }
+       }
+
+       if (!found) {
+               basename = color_file.get();
+               basename += ".colors";
+
+               if (find_file (ardour_config_search_path(), basename, cfile)) {
+                       found = true;
+               }
+       }
+
+       if (found) {
+
+               XMLTree tree;
+
+               info << string_compose (_("Loading color file %1"), cfile) << endmsg;
+
+               if (!tree.read (cfile.c_str())) {
+                       error << string_compose(_("cannot read color file \"%1\""), cfile) << endmsg;
                        return -1;
                }
 
                if (set_state (*tree.root(), Stateful::loading_state_version)) {
-                       error << string_compose(_("default ui configuration file \"%1\" not loaded successfully."), rcfile) << endmsg;
+                       error << string_compose(_("color file \"%1\" not loaded successfully."), cfile) << endmsg;
                        return -1;
                }
-               
-               _dirty = false;
+
+               ColorsChanged ();
+       } else {
+               warning << string_compose (_("Color file %1 not found"), basename) << endmsg;
        }
 
-       ARDOUR_UI_UTILS::ColorsChanged ();
+       return 0;
+}
+
+int
+UIConfiguration::store_color_theme ()
+{
+       XMLNode* root;
+       LocaleGuard lg ();
+
+       root = new XMLNode("Ardour");
+
+       XMLNode* parent = new XMLNode (X_("Colors"));
+       for (Colors::const_iterator i = colors.begin(); i != colors.end(); ++i) {
+               XMLNode* node = new XMLNode (X_("Color"));
+               node->add_property (X_("name"), i->first);
+               stringstream ss;
+               ss << "0x" << setw (8) << setfill ('0') << hex << i->second;
+               node->add_property (X_("value"), ss.str());
+               parent->add_child_nocopy (*node);
+       }
+       root->add_child_nocopy (*parent);
+
+       parent = new XMLNode (X_("ColorAliases"));
+       for (ColorAliases::const_iterator i = color_aliases.begin(); i != color_aliases.end(); ++i) {
+               XMLNode* node = new XMLNode (X_("ColorAlias"));
+               node->add_property (X_("name"), i->first);
+               node->add_property (X_("alias"), i->second);
+               parent->add_child_nocopy (*node);
+       }
+       root->add_child_nocopy (*parent);
+
+       parent = new XMLNode (X_("Modifiers"));
+       for (Modifiers::const_iterator i = modifiers.begin(); i != modifiers.end(); ++i) {
+               XMLNode* node = new XMLNode (X_("Modifier"));
+               node->add_property (X_("name"), i->first);
+               node->add_property (X_("modifier"), i->second.to_string());
+               parent->add_child_nocopy (*node);
+       }
+       root->add_child_nocopy (*parent);
+
+       XMLTree tree;
+       std::string colorfile = Glib::build_filename (user_config_directory(), (string ("my-") + color_file.get() + ".colors"));
 
-       return found;
+       tree.set_root (root);
+
+       if (!tree.write (colorfile.c_str())){
+               error << string_compose (_("Color file %1 not saved"), colorfile) << endmsg;
+               return -1;
+       }
+
+       return 0;
 }
 
 int
@@ -292,8 +376,6 @@ UIConfiguration::load_state ()
                        error << string_compose(_("default ui configuration file \"%1\" not loaded successfully."), rcfile) << endmsg;
                        return -1;
                }
-
-               /* make a copy */
        }
 
        if (find_file (ardour_config_search_path(), ui_config_file_name, rcfile)) {
@@ -319,35 +401,40 @@ UIConfiguration::load_state ()
                error << _("could not find any ui configuration file, canvas will look broken.") << endmsg;
        }
 
-       ARDOUR_UI_UTILS::ColorsChanged ();
-
        return 0;
 }
 
 int
 UIConfiguration::save_state()
 {
-       XMLTree tree;
 
-       PBD::stacktrace (cerr, 20);
-       
-       if (!dirty()) {
-               return 0;
-       }
-       
-       std::string rcfile(user_config_directory());
-       rcfile = Glib::build_filename (rcfile, ui_config_file_name);
+       if (_dirty) {
+               std::string rcfile = Glib::build_filename (user_config_directory(), ui_config_file_name);
+
+               XMLTree tree;
 
-       // this test seems bogus?
-       if (rcfile.length()) {
                tree.set_root (&get_state());
+
                if (!tree.write (rcfile.c_str())){
                        error << string_compose (_("Config file %1 not saved"), rcfile) << endmsg;
                        return -1;
                }
+
+               _dirty = false;
+       }
+
+       if (aliases_modified || colors_modified || modifiers_modified) {
+
+               if (store_color_theme ()) {
+                       error << string_compose (_("Color file %1 not saved"), color_file.get()) << endmsg;
+                       return -1;
+               }
+
+               aliases_modified = false;
+               colors_modified = false;
+               modifiers_modified = false;
        }
 
-       _dirty = false;
 
        return 0;
 }
@@ -356,28 +443,13 @@ XMLNode&
 UIConfiguration::get_state ()
 {
        XMLNode* root;
-       LocaleGuard lg (X_("POSIX"));
+       LocaleGuard lg ();
 
        root = new XMLNode("Ardour");
 
        root->add_child_nocopy (get_variables ("UI"));
        root->add_child_nocopy (get_variables ("Canvas"));
 
-       if (derived_modified) {
-
-       }
-
-       if (aliases_modified) {
-               XMLNode* parent = new XMLNode (X_("ColorAliases"));
-               for (ColorAliases::const_iterator i = color_aliases.begin(); i != color_aliases.end(); ++i) {
-                       XMLNode* node = new XMLNode (X_("ColorAlias"));
-                       node->add_property (X_("name"), i->first);
-                       node->add_property (X_("alias"), i->second);
-                       parent->add_child_nocopy (*node);
-               }
-               root->add_child_nocopy (*parent);
-       }
-       
        if (_extra_xml) {
                root->add_child_copy (*_extra_xml);
        }
@@ -389,7 +461,7 @@ XMLNode&
 UIConfiguration::get_variables (std::string which_node)
 {
        XMLNode* node;
-       LocaleGuard lg (X_("POSIX"));
+       LocaleGuard lg ();
 
        node = new XMLNode (which_node);
 
@@ -408,6 +480,8 @@ UIConfiguration::get_variables (std::string which_node)
 int
 UIConfiguration::set_state (const XMLNode& root, int /*version*/)
 {
+       /* this can load a generic UI configuration file or a colors file */
+
        if (root.name() != "Ardour") {
                return -1;
        }
@@ -428,19 +502,24 @@ UIConfiguration::set_state (const XMLNode& root, int /*version*/)
                }
        }
 
-       XMLNode* relative = find_named_node (root, X_("RelativeColors"));
-       
-       if (relative) {
-               // load_relative_colors (*relative);
+       XMLNode* colors = find_named_node (root, X_("Colors"));
+
+       if (colors) {
+               load_colors (*colors);
        }
 
-       
        XMLNode* aliases = find_named_node (root, X_("ColorAliases"));
 
        if (aliases) {
                load_color_aliases (*aliases);
        }
 
+       XMLNode* modifiers = find_named_node (root, X_("Modifiers"));
+
+       if (modifiers) {
+               load_modifiers (*modifiers);
+       }
+
        return 0;
 }
 
@@ -451,15 +530,16 @@ UIConfiguration::load_color_aliases (XMLNode const & node)
        XMLNodeConstIterator niter;
        XMLProperty const *name;
        XMLProperty const *alias;
-       
+
        color_aliases.clear ();
 
        for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
-               if ((*niter)->name() != X_("ColorAlias")) {
+               XMLNode const * child = *niter;
+               if (child->name() != X_("ColorAlias")) {
                        continue;
                }
-               name = (*niter)->property (X_("name"));
-               alias = (*niter)->property (X_("alias"));
+               name = child->property (X_("name"));
+               alias = child->property (X_("alias"));
 
                if (name && alias) {
                        color_aliases.insert (make_pair (name->value(), alias->value()));
@@ -467,159 +547,132 @@ UIConfiguration::load_color_aliases (XMLNode const & node)
        }
 }
 
-
-#if 0
 void
-UIConfiguration::load_relative_colors (XMLNode const & node)
+UIConfiguration::load_colors (XMLNode const & node)
 {
        XMLNodeList const nlist = node.children();
        XMLNodeConstIterator niter;
        XMLProperty const *name;
-       XMLProperty const *alias;
-       
-       color_aliases.clear ();
+       XMLProperty const *color;
+
+       colors.clear ();
 
        for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
-               if ((*niter)->name() != X_("RelativeColor")) {
+               XMLNode const * child = *niter;
+               if (child->name() != X_("Color")) {
                        continue;
                }
-               name = (*niter)->property (X_("name"));
-               alias = (*niter)->property (X_("alias"));
+               name = child->property (X_("name"));
+               color = child->property (X_("value"));
 
-               if (name && alias) {
-                       color_aliases.insert (make_pair (name->value(), alias->value()));
+               if (name && color) {
+                       ArdourCanvas::Color c;
+                       c = strtoul (color->value().c_str(), 0, 16);
+                       colors.insert (make_pair (name->value(), c));
                }
        }
+}
+
+void
+UIConfiguration::load_modifiers (XMLNode const & node)
+{
+       PBD::LocaleGuard lg ();
+       XMLNodeList const nlist = node.children();
+       XMLNodeConstIterator niter;
+       XMLProperty const *name;
+       XMLProperty const *mod;
+
+       modifiers.clear ();
+
+       for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+               XMLNode const * child = *niter;
+               if (child->name() != X_("Modifier")) {
+                       continue;
+               }
 
+               name = child->property (X_("name"));
+               mod = child->property (X_("modifier"));
+
+               if (name && mod) {
+                       SVAModifier svam (mod->value());
+                       modifiers.insert (make_pair (name->value(), svam));
+               }
+       }
 }
-#endif
+
 void
 UIConfiguration::set_variables (const XMLNode& node)
 {
 #undef  UI_CONFIG_VARIABLE
-#define UI_CONFIG_VARIABLE(Type,var,name,val) \
-         if (var.set_from_node (node)) { \
-                ParameterChanged (name); \
-                }
-#define CANVAS_FONT_VARIABLE(var,name) \
-         if (var.set_from_node (node)) { \
-                ParameterChanged (name); \
-                }
+#define UI_CONFIG_VARIABLE(Type,var,name,val) if (var.set_from_node (node)) { ParameterChanged (name); }
+#define CANVAS_FONT_VARIABLE(var,name)        if (var.set_from_node (node)) { ParameterChanged (name); }
 #include "ui_config_vars.h"
 #include "canvas_vars.h"
 #undef  UI_CONFIG_VARIABLE
 #undef  CANVAS_FONT_VARIABLE
-
-       /* Reset base colors */
-
-#undef  CANVAS_BASE_COLOR
-#define CANVAS_BASE_COLOR(var,name,val) \
-       var.set_from_node (node);
-#include "base_colors.h"
-#undef CANVAS_BASE_COLOR       
-
 }
 
-void
-UIConfiguration::set_dirty ()
+ArdourCanvas::SVAModifier
+UIConfiguration::modifier (string const & name) const
 {
-       _dirty = true;
+       Modifiers::const_iterator m = modifiers.find (name);
+       if (m != modifiers.end()) {
+               return m->second;
+       }
+       return SVAModifier ();
 }
 
-bool
-UIConfiguration::dirty () const
+ArdourCanvas::Color
+UIConfiguration::color_mod (std::string const & colorname, std::string const & modifiername) const
 {
-       return _dirty || aliases_modified || derived_modified;
+       return HSV (color (colorname)).mod (modifier (modifiername)).color ();
 }
 
 ArdourCanvas::Color
-UIConfiguration::base_color_by_name (const std::string& name) const
-{
-       map<std::string,ColorVariable<Color>* >::const_iterator i = configurable_colors.find (name);
-
-       if (i != configurable_colors.end()) {
-               return i->second->get();
-       }
-
-#if 0 // yet unsed experimental style postfix
-       /* Idea: use identical colors but different font/sizes
-        * for variants of the same 'widget'.
-        *
-        * example:
-        *  set_name("mute button");  // in route_ui.cc
-        *  set_name("mute button small"); // in mixer_strip.cc
-        *
-        * ardour3_widget_list.rc:
-        *  widget "*mute button" style:highest "small_button"
-        *  widget "*mute button small" style:highest "very_small_text"
-        *
-        * both use color-schema of defined in
-        *   BUTTON_VARS(MuteButton, "mute button")
-        *
-        * (in this particular example the widgets should be packed
-        * vertically shinking the mixer strip ones are currently not)
-        */
-       const size_t name_len = name.size();
-       const size_t name_sep = name.find(':');
-       for (i = configurable_colors.begin(); i != configurable_colors.end(), name_sep != string::npos; ++i) {
-               const size_t cmp_len = i->first.size();
-               const size_t cmp_sep = i->first.find(':');
-               if (cmp_len >= name_len || cmp_sep == string::npos) continue;
-               if (name.substr(name_sep) != i->first.substr(cmp_sep)) continue;
-               if (name.substr(0, cmp_sep) != i->first.substr(0, cmp_sep)) continue;
-               return i->second->get();
-       }
-#endif
-
-       cerr << string_compose (_("Base Color %1 not found"), name) << endl;
-       return RGBA_TO_UINT (g_random_int()%256,g_random_int()%256,g_random_int()%256,0xff);
+UIConfiguration::color_mod (const ArdourCanvas::Color& color, std::string const & modifiername) const
+{
+       return HSV (color).mod (modifier (modifiername)).color ();
 }
 
 ArdourCanvas::Color
-UIConfiguration::color (const std::string& name) const
+UIConfiguration::color (const std::string& name, bool* failed) const
 {
-       map<string,string>::const_iterator e = color_aliases.find (name);
+       ColorAliases::const_iterator e = color_aliases.find (name);
+
+       if (failed) {
+               *failed = false;
+       }
 
        if (e != color_aliases.end ()) {
-               map<string,RelativeHSV>::const_iterator rc = relative_colors.find (e->second);
-               if (rc != relative_colors.end()) {
-                       return rc->second.get();
+               Colors::const_iterator rc = colors.find (e->second);
+               if (rc != colors.end()) {
+                       return rc->second;
                }
        } else {
                /* not an alias, try directly */
-               map<string,RelativeHSV>::const_iterator rc = relative_colors.find (name);
-               if (rc != relative_colors.end()) {
-                       return rc->second.get();
+               Colors::const_iterator rc = colors.find (name);
+               if (rc != colors.end()) {
+                       return rc->second;
                }
        }
-       
-       cerr << string_compose (_("Color %1 not found"), name) << endl;
-       
+
+       if (!failed) {
+               /* only show this message if the caller wasn't interested in
+                  the fail status.
+               */
+               cerr << string_compose (_("Color %1 not found"), name) << endl;
+       }
+
+       if (failed) {
+               *failed = true;
+       }
+
        return rgba_to_color ((g_random_int()%256)/255.0,
                              (g_random_int()%256)/255.0,
                              (g_random_int()%256)/255.0,
                              0xff);
 }
 
-ArdourCanvas::HSV
-UIConfiguration::RelativeHSV::get() const
-{
-       HSV base (UIConfiguration::instance()->base_color_by_name (base_color));
-       
-       /* this operation is a little wierd. because of the way we originally
-        * computed the alpha specification for the modifiers used here
-        * we need to reset base's alpha to zero before adding the modifier.
-        */
-
-       HSV self (base + modifier);
-       
-       if (quantized_hue >= 0.0) {
-               self.h = quantized_hue;
-       }
-       
-       return self;
-}
-
 Color
 UIConfiguration::quantized (Color c) const
 {
@@ -629,20 +682,16 @@ UIConfiguration::quantized (Color c) const
 }
 
 void
-UIConfiguration::reset_relative (const string& name, const RelativeHSV& rhsv)
+UIConfiguration::set_color (string const& name, ArdourCanvas::Color color)
 {
-       RelativeColors::iterator i = relative_colors.find (name);
-
-       if (i == relative_colors.end()) {
+       Colors::iterator i = colors.find (name);
+       if (i == colors.end()) {
                return;
        }
+       i->second = color;
+       colors_modified = true;
 
-       i->second = rhsv;
-       derived_modified = true;
-
-       ARDOUR_UI_UTILS::ColorsChanged (); /* EMIT SIGNAL */
-
-       save_state ();
+       ColorsChanged (); /* EMIT SIGNAL */
 }
 
 void
@@ -656,19 +705,33 @@ UIConfiguration::set_alias (string const & name, string const & alias)
        i->second = alias;
        aliases_modified = true;
 
-       ARDOUR_UI_UTILS::ColorsChanged (); /* EMIT SIGNAL */
+       ColorsChanged (); /* EMIT SIGNAL */
+}
 
-       save_state ();
+void
+UIConfiguration::set_modifier (string const & name, SVAModifier svam)
+{
+       Modifiers::iterator m = modifiers.find (name);
+
+       if (m == modifiers.end()) {
+               return;
+       }
+
+       m->second = svam;
+       modifiers_modified = true;
+
+       ColorsChanged (); /* EMIT SIGNAL */
 }
 
 void
-UIConfiguration::load_rc_file (const string& filename, bool themechange)
+UIConfiguration::load_rc_file (bool themechange, bool allow_own)
 {
+       string basename = ui_rc_file.get();
        std::string rc_file_path;
 
-       if (!find_file (ardour_config_search_path(), filename, rc_file_path)) {
+       if (!find_file (ardour_config_search_path(), basename, rc_file_path)) {
                warning << string_compose (_("Unable to find UI style file %1 in search path %2. %3 will look strange"),
-                                           filename, ardour_config_search_path().to_string(), PROGRAM_NAME)
+                                           basename, ardour_config_search_path().to_string(), PROGRAM_NAME)
                                << endmsg;
                return;
        }
@@ -677,3 +740,5 @@ UIConfiguration::load_rc_file (const string& filename, bool themechange)
 
        Gtkmm2ext::UI::instance()->load_rcfile (rc_file_path, themechange);
 }
+
+