+ if (!_set (_button->get_active ())) {
+ _button->set_active (_get ());
+ }
+}
+
+/*--------------------------*/
+
+RouteDisplayBoolOption::RouteDisplayBoolOption (string const & i, string const & n, sigc::slot<bool> g, sigc::slot<bool, bool> s)
+ : BoolOption (i, n, g, s)
+{
+}
+
+void
+RouteDisplayBoolOption::toggled ()
+{
+ DisplaySuspender ds;
+ BoolOption::toggled ();
+}
+
+/*--------------------------*/
+
+EntryOption::EntryOption (string const & i, string const & n, sigc::slot<string> g, sigc::slot<bool, string> s)
+ : Option (i, n),
+ _get (g),
+ _set (s)
+{
+ _label = manage (left_aligned_label (n + ":"));
+ _entry = manage (new Entry);
+ _entry->signal_activate().connect (sigc::mem_fun (*this, &EntryOption::activated));
+ _entry->signal_focus_out_event().connect (sigc::mem_fun (*this, &EntryOption::focus_out));
+ _entry->signal_insert_text().connect (sigc::mem_fun (*this, &EntryOption::filter_text));
+}
+
+void
+EntryOption::add_to_page (OptionEditorPage* p)
+{
+ add_widgets_to_page (p, _label, _entry);
+}
+
+void
+EntryOption::set_state_from_config ()
+{
+ _entry->set_text (_get ());
+}
+
+void
+EntryOption::set_sensitive (bool s)
+{
+ _entry->set_sensitive (s);
+}
+
+void
+EntryOption::filter_text (const Glib::ustring&, int*)
+{
+ std::string text = _entry->get_text ();
+ for (size_t i = 0; i < _invalid.length(); ++i) {
+ text.erase (std::remove(text.begin(), text.end(), _invalid.at(i)), text.end());
+ }
+ if (text != _entry->get_text ()) {
+ _entry->set_text (text);
+ }
+}
+
+void
+EntryOption::activated ()
+{
+ _set (_entry->get_text ());
+}
+
+bool
+EntryOption::focus_out (GdkEventFocus*)
+{
+ _set (_entry->get_text ());
+ return true;
+}
+
+/*--------------------------*/
+HSliderOption::HSliderOption (
+ std::string const& i,
+ std::string const& n,
+ sigc::slot<float> g,
+ sigc::slot<bool, float> s,
+ double lower, double upper,
+ double step_increment,
+ double page_increment,
+ double mult,
+ bool logarithmic
+ )
+ : Option (i, n)
+ , _get (g)
+ , _set (s)
+ , _adj (lower, lower, upper, step_increment, page_increment, 0)
+ , _hscale (_adj)
+ , _label (n + ":")
+ , _mult (mult)
+ , _log (logarithmic)
+{
+ _label.set_alignment (0, 0.5);
+ _label.set_name ("OptionsLabel");
+ _adj.set_value (_get());
+ _adj.signal_value_changed().connect (sigc::mem_fun (*this, &HSliderOption::changed));
+ _hscale.set_update_policy (Gtk::UPDATE_DISCONTINUOUS);
+}
+
+void
+HSliderOption::set_state_from_config ()
+{
+ if (_log) {
+ _adj.set_value (log10(_get()) / _mult);
+ } else {
+ _adj.set_value (_get() / _mult);
+ }
+}
+
+void
+HSliderOption::changed ()
+{
+ if (_log) {
+ _set (pow (10, _adj.get_value () * _mult));
+ } else {
+ _set (_adj.get_value () * _mult);
+ }
+}
+
+void
+HSliderOption::add_to_page (OptionEditorPage* p)
+{
+ add_widgets_to_page (p, &_label, &_hscale);
+}
+
+void
+HSliderOption::set_sensitive (bool yn)
+{
+ _hscale.set_sensitive (yn);
+}
+
+/*--------------------------*/
+
+ComboStringOption::ComboStringOption (
+ std::string const & i,
+ std::string const & n,
+ sigc::slot<std::string> g,
+ sigc::slot<bool, std::string> s
+ )
+ : Option (i, n)
+ , _get (g)
+ , _set (s)
+{
+ _label = Gtk::manage (new Gtk::Label (n + ":"));
+ _label->set_alignment (0, 0.5);
+ _combo = Gtk::manage (new Gtk::ComboBoxText);
+ _combo->signal_changed().connect (sigc::mem_fun (*this, &ComboStringOption::changed));
+}
+
+void
+ComboStringOption::set_state_from_config () {
+ _combo->set_active_text (_get());
+}
+
+void
+ComboStringOption::add_to_page (OptionEditorPage* p)
+{
+ add_widgets_to_page (p, _label, _combo);
+}
+
+/** Set the allowed strings for this option
+ * @param strings a vector of allowed strings
+ */
+void
+ComboStringOption::set_popdown_strings (const std::vector<std::string>& strings) {
+ _combo->clear_items ();
+ for (std::vector<std::string>::const_iterator i = strings.begin(); i != strings.end(); ++i) {
+ _combo->append_text (*i);
+ }
+}
+
+void
+ComboStringOption::clear () {
+ _combo->clear_items();
+}
+
+void
+ComboStringOption::changed () {
+ _set (_combo->get_active_text ());
+}
+
+void
+ComboStringOption::set_sensitive (bool yn) {
+ _combo->set_sensitive (yn);
+}
+
+/*--------------------------*/
+
+/** Construct a BoolComboOption.
+ * @param i id
+ * @param n User-visible name.
+ * @param t Text to give for the variable being true.
+ * @param f Text to give for the variable being false.
+ * @param g Slot to get the variable's value.
+ * @param s Slot to set the variable's value.
+ */
+BoolComboOption::BoolComboOption (
+ string const & i, string const & n, string const & t, string const & f,
+ sigc::slot<bool> g, sigc::slot<bool, bool> s
+ )
+ : Option (i, n)
+ , _get (g)
+ , _set (s)
+{
+ _label = manage (new Label (n + ":"));
+ _label->set_alignment (0, 0.5);
+ _combo = manage (new ComboBoxText);
+
+ /* option 0 is the false option */
+ _combo->append_text (f);
+ /* and option 1 is the true */
+ _combo->append_text (t);
+
+ _combo->signal_changed().connect (sigc::mem_fun (*this, &BoolComboOption::changed));
+}
+
+void
+BoolComboOption::set_state_from_config ()
+{
+ _combo->set_active (_get() ? 1 : 0);
+}
+
+void
+BoolComboOption::add_to_page (OptionEditorPage* p)
+{
+ add_widgets_to_page (p, _label, _combo);
+}
+
+void
+BoolComboOption::changed ()
+{
+ _set (_combo->get_active_row_number () == 0 ? false : true);
+}
+
+void
+BoolComboOption::set_sensitive (bool yn)
+{
+ _combo->set_sensitive (yn);
+}
+
+/*--------------------------*/
+
+FaderOption::FaderOption (string const & i, string const & n, sigc::slot<gain_t> g, sigc::slot<bool, gain_t> s)
+ : Option (i, n)
+ , _db_adjustment (gain_to_slider_position_with_max (1.0, Config->get_max_gain()), 0, 1, 0.01, 0.1)
+ , _get (g)
+ , _set (s)
+{
+ _db_slider = manage (new HSliderController (&_db_adjustment, boost::shared_ptr<PBD::Controllable>(), 220, 18));
+
+ _label.set_text (n + ":");
+ _label.set_alignment (0, 0.5);
+ _label.set_name (X_("OptionsLabel"));
+
+ _fader_centering_box.pack_start (*_db_slider, true, false);
+
+ _box.set_spacing (4);
+ _box.set_homogeneous (false);
+ _box.pack_start (_fader_centering_box, false, false);
+ _box.pack_start (_db_display, false, false);
+ _box.pack_start (*manage (new Label ("dB")), false, false);
+ _box.show_all ();
+
+ set_size_request_to_display_given_text (_db_display, "-99.00", 12, 0);
+
+ _db_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &FaderOption::db_changed));
+ _db_display.signal_activate().connect (sigc::mem_fun (*this, &FaderOption::on_activate));
+ _db_display.signal_key_press_event().connect (sigc::mem_fun (*this, &FaderOption::on_key_press), false);
+}
+
+void
+FaderOption::set_state_from_config ()
+{
+ gain_t const val = _get ();
+ _db_adjustment.set_value (gain_to_slider_position_with_max (val, Config->get_max_gain ()));
+
+ char buf[16];
+
+ if (val == 0.0) {
+ snprintf (buf, sizeof (buf), "-inf");
+ } else {
+ snprintf (buf, sizeof (buf), "%.2f", accurate_coefficient_to_dB (val));
+ }
+
+ _db_display.set_text (buf);
+}
+
+void
+FaderOption::db_changed ()
+{
+ _set (slider_position_to_gain_with_max (_db_adjustment.get_value (), Config->get_max_gain()));
+}
+
+void
+FaderOption::on_activate ()
+{
+ float db_val = atof (_db_display.get_text ().c_str ());
+ gain_t coeff_val = dB_to_coefficient (db_val);
+
+ _db_adjustment.set_value (gain_to_slider_position_with_max (coeff_val, Config->get_max_gain ()));
+}
+
+bool
+FaderOption::on_key_press (GdkEventKey* ev)
+{
+ if (ARDOUR_UI_UTILS::key_is_legal_for_numeric_entry (ev->keyval)) {
+ /* drop through to normal handling */
+ return false;
+ }
+ /* illegal key for gain entry */
+ return true;
+}
+
+void
+FaderOption::add_to_page (OptionEditorPage* p)
+{
+ add_widgets_to_page (p, &_label, &_box);
+}
+
+/*--------------------------*/
+
+ClockOption::ClockOption (string const & i, string const & n, sigc::slot<std::string> g, sigc::slot<bool, std::string> s)
+ : Option (i, n)
+ , _clock (X_("timecode-offset"), true, X_(""), true, false, true, false)
+ , _get (g)
+ , _set (s)
+{
+ _label.set_text (n + ":");
+ _label.set_alignment (0, 0.5);
+ _label.set_name (X_("OptionsLabel"));
+ _clock.ValueChanged.connect (sigc::mem_fun (*this, &ClockOption::save_clock_time));
+}
+
+void
+ClockOption::set_state_from_config ()
+{
+ Timecode::Time TC;
+ framepos_t when;
+ if (!Timecode::parse_timecode_format(_get(), TC)) {
+ _clock.set (0, true);
+ }
+ TC.rate = _session->samples_per_timecode_frame();
+ TC.drop = _session->timecode_drop_frames();
+ _session->timecode_to_sample(TC, when, false, false);
+ if (TC.negative) { when=-when; }
+ _clock.set (when, true);
+}
+
+void
+ClockOption::save_clock_time ()
+{
+ Timecode::Time TC;
+ _session->sample_to_timecode(_clock.current_time(), TC, false, false);
+ _set (Timecode::timecode_format_time(TC));
+}
+
+void
+ClockOption::add_to_page (OptionEditorPage* p)
+{
+ add_widgets_to_page (p, &_label, &_clock);
+}
+
+void
+ClockOption::set_session (Session* s)
+{
+ _session = s;
+ _clock.set_session (s);
+}
+
+/*--------------------------*/
+
+OptionEditorPage::OptionEditorPage ()
+ : table (1, 3)
+{
+ init ();