ardour
option_editor.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2001-2009 Paul Davis
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 #include <algorithm>
20 
21 #include <gtkmm/box.h>
22 #include <gtkmm/alignment.h>
23 #include "gtkmm2ext/utils.h"
24 
25 #include "ardour/dB.h"
27 #include "ardour/session.h"
28 #include "ardour/types.h"
29 #include "ardour/utils.h"
30 
31 #include "pbd/configuration.h"
32 #include "pbd/replace_all.h"
33 
34 #include "public_editor.h"
35 #include "option_editor.h"
36 #include "gui_thread.h"
37 #include "i18n.h"
38 
39 using namespace std;
40 using namespace Gtk;
41 using namespace Gtkmm2ext;
42 using namespace ARDOUR;
43 
44 void
46 {
47  int const n = p->table.property_n_rows();
48  int m = n + 1;
49  if (!_note.empty ()) {
50  ++m;
51  }
52 
53  p->table.resize (m, 3);
54  p->table.attach (*w, 1, 3, n, n + 1, FILL | EXPAND);
55 
56  maybe_add_note (p, n + 1);
57 }
58 
59 void
60 OptionEditorComponent::add_widgets_to_page (OptionEditorPage* p, Gtk::Widget* wa, Gtk::Widget* wb)
61 {
62  int const n = p->table.property_n_rows();
63  int m = n + 1;
64  if (!_note.empty ()) {
65  ++m;
66  }
67 
68  p->table.resize (m, 3);
69  p->table.attach (*wa, 1, 2, n, n + 1, FILL);
70  p->table.attach (*wb, 2, 3, n, n + 1, FILL | EXPAND);
71 
72  maybe_add_note (p, n + 1);
73 }
74 
75 void
77 {
78  if (!_note.empty ()) {
79  Gtk::Label* l = manage (new Gtk::Label (string_compose (X_("<i>%1</i>"), _note)));
80  l->set_use_markup (true);
81  p->table.attach (*l, 1, 3, n, n + 1, FILL | EXPAND);
82  }
83 }
84 
85 void
87 {
88  _note = n;
89 }
90 
92 {
93  std::stringstream s;
94  s << "<b>" << h << "</b>";
95  _label = manage (left_aligned_label (s.str()));
96  _label->set_use_markup (true);
97 }
98 
99 void
101 {
102  int const n = p->table.property_n_rows();
103  p->table.resize (n + 2, 3);
104 
105  p->table.attach (*manage (new Label ("")), 0, 3, n, n + 1, FILL | EXPAND);
106  p->table.attach (*_label, 0, 3, n + 1, n + 2, FILL | EXPAND);
107 }
108 
109 void
111 {
112  add_widget_to_page (p, _box);
113 }
114 
115 BoolOption::BoolOption (string const & i, string const & n, sigc::slot<bool> g, sigc::slot<bool, bool> s)
116  : Option (i, n),
117  _get (g),
118  _set (s)
119 {
120  _button = manage (new CheckButton);
121  _label = manage (new Label);
122  _label->set_markup (n);
123  _button->add (*_label);
124  _button->set_active (_get ());
125  _button->signal_toggled().connect (sigc::mem_fun (*this, &BoolOption::toggled));
126 }
127 
128 void
130 {
132 }
133 
134 void
136 {
137  _button->set_active (_get ());
138 }
139 
140 void
142 {
143  _set (_button->get_active ());
144 }
145 
146 RouteDisplayBoolOption::RouteDisplayBoolOption (string const & i, string const & n, sigc::slot<bool> g, sigc::slot<bool, bool> s)
147  : BoolOption (i, n, g, s)
148 {
149 }
150 
151 void
153 {
154  DisplaySuspender ds;
156 }
157 
158 EntryOption::EntryOption (string const & i, string const & n, sigc::slot<string> g, sigc::slot<bool, string> s)
159  : Option (i, n),
160  _get (g),
161  _set (s)
162 {
163  _label = manage (left_aligned_label (n + ":"));
164  _entry = manage (new Entry);
165  _entry->signal_activate().connect (sigc::mem_fun (*this, &EntryOption::activated));
166  _entry->signal_focus_out_event().connect (sigc::mem_fun (*this, &EntryOption::focus_out));
167  _entry->signal_insert_text().connect (sigc::mem_fun (*this, &EntryOption::filter_text));
168 }
169 
170 void
172 {
174 }
175 
176 void
178 {
179  _entry->set_text (_get ());
180 }
181 
182 void
184 {
185  _entry->set_sensitive (s);
186 }
187 
188 void
189 EntryOption::filter_text (const Glib::ustring&, int*)
190 {
191  std::string text = _entry->get_text ();
192  for (size_t i = 0; i < _invalid.length(); ++i) {
193  text.erase (std::remove(text.begin(), text.end(), _invalid.at(i)), text.end());
194  }
195  if (text != _entry->get_text ()) {
196  _entry->set_text (text);
197  }
198 }
199 
200 void
202 {
203  _set (_entry->get_text ());
204 }
205 
206 bool
207 EntryOption::focus_out (GdkEventFocus*)
208 {
209  _set (_entry->get_text ());
210  return true;
211 }
212 
222  string const & i, string const & n, string const & t, string const & f,
223  sigc::slot<bool> g, sigc::slot<bool, bool> s
224  )
225  : Option (i, n)
226  , _get (g)
227  , _set (s)
228 {
229  _label = manage (new Label (n + ":"));
230  _label->set_alignment (0, 0.5);
231  _combo = manage (new ComboBoxText);
232 
233  /* option 0 is the false option */
234  _combo->append_text (f);
235  /* and option 1 is the true */
236  _combo->append_text (t);
237 
238  _combo->signal_changed().connect (sigc::mem_fun (*this, &BoolComboOption::changed));
239 }
240 
241 void
243 {
244  _combo->set_active (_get() ? 1 : 0);
245 }
246 
247 void
249 {
251 }
252 
253 void
255 {
256  _set (_combo->get_active_row_number () == 0 ? false : true);
257 }
258 
259 void
261 {
262  _combo->set_sensitive (yn);
263 }
264 
265 
266 
267 FaderOption::FaderOption (string const & i, string const & n, sigc::slot<gain_t> g, sigc::slot<bool, gain_t> s)
268  : Option (i, n)
269  , _db_adjustment (gain_to_slider_position_with_max (1.0, Config->get_max_gain()), 0, 1, 0.01, 0.1)
270  , _get (g)
271  , _set (s)
272 {
274 
275  _label.set_text (n + ":");
276  _label.set_alignment (0, 0.5);
277  _label.set_name (X_("OptionsLabel"));
278 
279  _fader_centering_box.pack_start (*_db_slider, true, false);
280 
281  _box.set_spacing (4);
282  _box.set_homogeneous (false);
283  _box.pack_start (_fader_centering_box, false, false);
284  _box.pack_start (_db_display, false, false);
285  _box.show_all ();
286 
288 
289  _db_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &FaderOption::db_changed));
290 }
291 
292 void
294 {
295  gain_t const val = _get ();
296  _db_adjustment.set_value (gain_to_slider_position_with_max (val, Config->get_max_gain ()));
297 
298  char buf[16];
299 
300  if (val == 0.0) {
301  snprintf (buf, sizeof (buf), "-inf");
302  } else {
303  snprintf (buf, sizeof (buf), "%.2f", accurate_coefficient_to_dB (val));
304  }
305 
306  _db_display.set_text (buf);
307 }
308 
309 void
311 {
312  _set (slider_position_to_gain_with_max (_db_adjustment.get_value (), Config->get_max_gain()));
313 }
314 
315 void
317 {
319 }
320 
321 ClockOption::ClockOption (string const & i, string const & n, sigc::slot<std::string> g, sigc::slot<bool, std::string> s)
322  : Option (i, n)
323  , _clock (X_("timecode-offset"), true, X_(""), true, false, true, false)
324  , _get (g)
325  , _set (s)
326 {
327  _label.set_text (n + ":");
328  _label.set_alignment (0, 0.5);
329  _label.set_name (X_("OptionsLabel"));
330  _clock.ValueChanged.connect (sigc::mem_fun (*this, &ClockOption::save_clock_time));
331 }
332 
333 void
335 {
336  Timecode::Time TC;
337  framepos_t when;
338  if (!Timecode::parse_timecode_format(_get(), TC)) {
339  _clock.set (0, true);
340  }
341  TC.rate = _session->frames_per_timecode_frame();
342  TC.drop = _session->timecode_drop_frames();
343  _session->timecode_to_sample(TC, when, false, false);
344  if (TC.negative) { when=-when; }
345  _clock.set (when, true);
346 }
347 
348 void
350 {
351  Timecode::Time TC;
352  _session->sample_to_timecode(_clock.current_time(), TC, false, false);
353  _set (Timecode::timecode_format_time(TC));
354 }
355 
356 void
358 {
360 }
361 
362 void
364 {
365  _session = s;
366  _clock.set_session (s);
367 }
368 
369 OptionEditorPage::OptionEditorPage (Gtk::Notebook& n, std::string const & t)
370  : table (1, 3)
371 {
372  table.set_spacings (4);
373  table.set_col_spacing (0, 32);
374  box.pack_start (table, false, false);
375  box.set_border_width (4);
376  n.append_page (box, t);
377 }
378 
384  : ArdourWindow (t), _config (c)
385 {
386  using namespace Notebook_Helpers;
387 
388  set_default_size (300, 300);
389  // set_wmclass (X_("ardour_preferences"), PROGRAM_NAME);
390 
391  set_name ("Preferences");
392  add_events (Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK);
393 
394  set_border_width (4);
395 
396  add (_notebook);
397 
398  _notebook.set_show_tabs (true);
399  _notebook.set_show_border (true);
400  _notebook.set_name ("OptionsNotebook");
401 
402  show_all_children();
403 
404  /* Watch out for changes to parameters */
405  _config->ParameterChanged.connect (config_connection, invalidator (*this), boost::bind (&OptionEditor::parameter_changed, this, _1), gui_context());
406 }
407 
409 {
410  for (std::map<std::string, OptionEditorPage*>::iterator i = _pages.begin(); i != _pages.end(); ++i) {
411  for (std::list<OptionEditorComponent*>::iterator j = i->second->components.begin(); j != i->second->components.end(); ++j) {
412  delete *j;
413  }
414  delete i->second;
415  }
416 }
417 
421 void
422 OptionEditor::parameter_changed (std::string const & p)
423 {
425 
426  for (std::map<std::string, OptionEditorPage*>::iterator i = _pages.begin(); i != _pages.end(); ++i) {
427  for (std::list<OptionEditorComponent*>::iterator j = i->second->components.begin(); j != i->second->components.end(); ++j) {
428  (*j)->parameter_changed (p);
429  }
430  }
431 }
432 
437 void
439 {
440  if (_pages.find (pn) == _pages.end()) {
441  _pages[pn] = new OptionEditorPage (_notebook, pn);
442  }
443 
444  OptionEditorPage* p = _pages[pn];
445  p->components.push_back (o);
446 
447  o->add_to_page (p);
448  o->set_state_from_config ();
449 }
450 
455 void
456 OptionEditor::add_page (std::string const & pn, Gtk::Widget& w)
457 {
458  if (_pages.find (pn) == _pages.end()) {
459  _pages[pn] = new OptionEditorPage (_notebook, pn);
460  }
461 
462  OptionEditorPage* p = _pages[pn];
463  p->box.pack_start (w, true, true);
464 }
465 
466 void
468 {
469  int i = 0;
470  while (i < _notebook.get_n_pages ()) {
471  if (_notebook.get_tab_label_text (*_notebook.get_nth_page (i)) == p) {
472  _notebook.set_current_page (i);
473  return;
474  }
475 
476  ++i;
477  }
478 }
479 
480 
481 DirectoryOption::DirectoryOption (string const & i, string const & n, sigc::slot<string> g, sigc::slot<bool, string> s)
482  : Option (i, n)
483  , _get (g)
484  , _set (s)
485 {
486  _file_chooser.set_action (Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
487  _file_chooser.signal_selection_changed().connect (sigc::mem_fun (*this, &DirectoryOption::selection_changed));
488 }
489 
490 
491 void
493 {
494  _file_chooser.set_current_folder (poor_mans_glob(_get ()));
495 }
496 
497 void
499 {
500  Gtk::Label *label = manage (new Label (_name));
501  label->set_alignment (0, 0.5);
502  label->set_name (X_("OptionsLabel"));
503  add_widgets_to_page (p, label, &_file_chooser);
504 }
505 
506 void
508 {
509  _set (poor_mans_glob(_file_chooser.get_filename ()));
510 }
void set_note(std::string const &)
void db_changed()
void save_clock_time()
std::list< OptionEditorComponent * > components
framepos_t current_time(framepos_t position=0) const
void filter_text(const Glib::ustring &, int *)
void set(framepos_t, bool force=false, ARDOUR::framecnt_t offset=0)
Definition: audio_clock.cc:956
void selection_changed()
virtual void toggled()
void set_current_page(std::string const &)
void add_page(std::string const &, Gtk::Widget &page_widget)
void set_session(ARDOUR::Session *s)
LIBGTKMM2EXT_API void set_size_request_to_display_given_text(Gtk::Widget &w, const gchar *text, gint hpadding, gint vpadding)
Definition: utils.cc:70
OptionEditorPage(Gtk::Notebook &, std::string const &)
Gtkmm2ext::HSliderController * _db_slider
Gtk::Label _label
void set_state_from_config()
Gtk::Label _label
Definition: ardour_ui.h:130
DirectoryOption(std::string const &, std::string const &, sigc::slot< std::string >, sigc::slot< bool, std::string >)
Gtk::CheckButton * _button
UI button.
LIBARDOUR_API double slider_position_to_gain_with_max(double g, double max_gain=2.0)
Definition: utils.cc:762
ClockOption(std::string const &, std::string const &, sigc::slot< std::string >, sigc::slot< bool, std::string >)
void set_state_from_config()
std::map< std::string, OptionEditorPage * > _pages
tuple f
Definition: signals.py:35
Definition: Beats.hpp:239
float gain_t
Definition: types.h:58
Gtk::VBox _fader_centering_box
sigc::slot< bool, std::string > _set
slot to set the configuration variable's value
#define ENSURE_GUI_THREAD(obj, method,...)
Definition: gui_thread.h:34
#define invalidator(x)
Definition: gui_thread.h:40
sigc::slot< std::string > _get
slot to get the configuration variable's value
static float accurate_coefficient_to_dB(float coeff)
Definition: dB.h:38
sigc::slot< std::string > _get
AudioClock _clock
double frames_per_timecode_frame() const
Definition: session.h:370
virtual void parameter_changed(std::string const &)
void set_sensitive(bool)
sigc::slot< bool, std::string > _set
slot to set the configuration variable's value
void add_to_page(OptionEditorPage *)
Gtk::Table table
Gtk::FileChooserButton _file_chooser
bool timecode_drop_frames() const
Definition: session_time.cc:61
#define X_(Text)
Definition: i18n.h:13
ARDOUR::Session * _session
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
virtual void toggled()
PBD::ScopedConnection config_connection
void maybe_add_note(OptionEditorPage *, int)
std::string _invalid
sigc::slot< ARDOUR::gain_t > _get
Gtk::Notebook _notebook
Definition: amp.h:29
void add_option(std::string const &, OptionEditorComponent *)
#define gui_context()
Definition: gui_thread.h:36
Gtk::Entry _db_display
Base class for option editing dialog boxes.
void activated()
LIBGTKMM2EXT_API Gtk::Label * left_aligned_label(std::string const &)
LIBPBD_API std::string poor_mans_glob(std::string path)
Definition: strreplace.cc:41
void add_widget_to_page(OptionEditorPage *, Gtk::Widget *)
int64_t framepos_t
Definition: types.h:66
Gtk::Entry * _entry
UI entry.
void set_state_from_config()
PBD::Signal1< void, std::string > ParameterChanged
Definition: configuration.h:44
Gtk::Label * _label
sigc::signal< void > ValueChanged
Definition: audio_clock.h:92
void sample_to_timecode(framepos_t sample, Timecode::Time &timecode, bool use_offset, bool use_subframes) const
void set_state_from_config()
BoolComboOption(std::string const &, std::string const &, std::string const &, std::string const &, sigc::slot< bool >, sigc::slot< bool, bool >)
sigc::slot< bool > _get
void set_state_from_config()
void set_session(ARDOUR::Session *)
LIBARDOUR_API double gain_to_slider_position_with_max(double g, double max_gain=2.0)
Definition: utils.cc:756
void add_to_page(OptionEditorPage *)
sigc::slot< bool, bool > _set
void set_state_from_config()
void set_sensitive(bool)
sigc::slot< bool, std::string > _set
BoolOption(std::string const &, std::string const &, sigc::slot< bool >, sigc::slot< bool, bool >)
void add_widgets_to_page(OptionEditorPage *, Gtk::Widget *, Gtk::Widget *)
RouteDisplayBoolOption(std::string const &, std::string const &, sigc::slot< bool >, sigc::slot< bool, bool >)
virtual void add_to_page(OptionEditorPage *)=0
void timecode_to_sample(Timecode::Time &timecode, framepos_t &sample, bool use_offset, bool use_subframes) const
Gtk::Label * _label
label for button, so we can use markup
EntryOption(std::string const &, std::string const &, sigc::slot< std::string >, sigc::slot< bool, std::string >)
void add_to_page(OptionEditorPage *)
Gtk::Adjustment _db_adjustment
FaderOption(std::string const &, std::string const &, sigc::slot< ARDOUR::gain_t > g, sigc::slot< bool, ARDOUR::gain_t > s)
sigc::slot< bool, ARDOUR::gain_t > _set
std::string _name
Gtk::ComboBoxText * _combo
sigc::slot< std::string > _get
slot to get the configuration variable's value
virtual void set_state_from_config()=0
OptionEditor(PBD::Configuration *, std::string const &)
Gtk::Label * _label
UI label.
OptionEditorHeading(std::string const &)
void add_to_page(OptionEditorPage *)
void add_to_page(OptionEditorPage *)
Gtk::HBox _box
void add_to_page(OptionEditorPage *)
void add_to_page(OptionEditorPage *)
bool focus_out(GdkEventFocus *)
sigc::slot< bool, bool > _set
slot to set the configuration variable's value
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
PBD::Configuration * _config
sigc::slot< bool > _get
slot to get the configuration variable's value
void add_to_page(OptionEditorPage *)