use new syntax for connecting to backend signals that enforces explicit connection...
[ardour.git] / gtk2_ardour / session_option_editor.cc
1 #include "ardour/session.h"
2 #include "ardour/io.h"
3 #include "ardour/auditioner.h"
4 #include "ardour/audioengine.h"
5 #include "ardour/port.h"
6 #include "session_option_editor.h"
7 #include "port_matrix.h"
8 #include "i18n.h"
9
10 using namespace std;
11 using namespace ARDOUR;
12
13 class OptionsPortMatrix : public PortMatrix
14 {
15 public:
16         OptionsPortMatrix (Gtk::Window* parent, ARDOUR::Session* session)
17                 : PortMatrix (parent, session, DataType::AUDIO)
18         {
19                 _port_group.reset (new PortGroup (""));
20                 _ports[OURS].add_group (_port_group);
21
22                 setup_all_ports ();
23                 init ();
24         }
25
26         void setup_ports (int dim)
27         {
28                 if (dim == OURS) {
29                         _port_group->clear ();
30                         _port_group->add_bundle (_session->click_io()->bundle());
31                         _port_group->add_bundle (_session->the_auditioner()->output()->bundle());
32                 } else {
33                         _ports[OTHER].gather (_session, true, false);
34                 }
35         }
36
37         void set_state (ARDOUR::BundleChannel c[2], bool s)
38         {
39                 Bundle::PortList const & our_ports = c[OURS].bundle->channel_ports (c[OURS].channel);
40                 Bundle::PortList const & other_ports = c[OTHER].bundle->channel_ports (c[OTHER].channel);
41
42                 if (c[OURS].bundle == _session->click_io()->bundle()) {
43
44                         for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_ports.end(); ++i) {
45                                 for (ARDOUR::Bundle::PortList::const_iterator j = other_ports.begin(); j != other_ports.end(); ++j) {
46
47                                         Port* f = _session->engine().get_port_by_name (*i);
48                                         assert (f);
49
50                                         if (s) {
51                                                 _session->click_io()->connect (f, *j, 0);
52                                         } else {
53                                                 _session->click_io()->disconnect (f, *j, 0);
54                                         }
55                                 }
56                         }
57                 }
58         }
59
60         PortMatrixNode::State get_state (ARDOUR::BundleChannel c[2]) const
61         {
62                 Bundle::PortList const & our_ports = c[OURS].bundle->channel_ports (c[OURS].channel);
63                 Bundle::PortList const & other_ports = c[OTHER].bundle->channel_ports (c[OTHER].channel);
64
65                 if (c[OURS].bundle == _session->click_io()->bundle()) {
66
67                         for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_ports.end(); ++i) {
68                                 for (ARDOUR::Bundle::PortList::const_iterator j = other_ports.begin(); j != other_ports.end(); ++j) {
69                                         Port* f = _session->engine().get_port_by_name (*i);
70                                         assert (f);
71
72                                         if (f->connected_to (*j)) {
73                                                 return PortMatrixNode::ASSOCIATED;
74                                         } else {
75                                                 return PortMatrixNode::NOT_ASSOCIATED;
76                                         }
77                                 }
78                         }
79
80                 } else {
81
82                         /* XXX */
83
84                 }
85
86                 return PortMatrixNode::NOT_ASSOCIATED;
87         }
88
89         bool list_is_global (int dim) const {
90                 return (dim == OTHER);
91         }
92
93         bool can_remove_channels (boost::shared_ptr<Bundle>) const {
94                 return false;
95         }
96
97         void remove_channel (ARDOUR::BundleChannel) {}
98
99         std::string disassociation_verb () const {
100                 return _("Disassociate");
101         }
102
103 private:
104         /* see PortMatrix: signal flow from 0 to 1 (out to in) */
105         enum {
106                 OURS = 0,
107                 OTHER = 1,
108         };
109
110         boost::shared_ptr<PortGroup> _port_group;
111
112 };
113
114
115 class ConnectionOptions : public OptionEditorBox
116 {
117 public:
118         ConnectionOptions (Gtk::Window* parent, ARDOUR::Session* s)
119                 : _port_matrix (parent, s)
120         {
121                 _box->pack_start (_port_matrix);
122         }
123
124         void parameter_changed (string const &)
125         {
126
127         }
128
129         void set_state_from_config ()
130         {
131
132         }
133
134 private:
135         OptionsPortMatrix _port_matrix;
136 };
137
138 SessionOptionEditor::SessionOptionEditor (Session* s)
139         : OptionEditor (&(s->config), _("Session Preferences"))
140         , _session_config (&(s->config))
141 {
142         /* SYNC */
143
144         ComboOption<uint32_t>* spf = new ComboOption<uint32_t> (
145                 "subframes-per-frame",
146                 _("Subframes per frame"),
147                 sigc::mem_fun (*_session_config, &SessionConfiguration::get_subframes_per_frame),
148                 sigc::mem_fun (*_session_config, &SessionConfiguration::set_subframes_per_frame)
149                 );
150
151         spf->add (80, _("80"));
152         spf->add (100, _("100"));
153
154         add_option (_("Sync"), spf);
155
156         ComboOption<SyncSource>* ssrc = new ComboOption<SyncSource> (
157                 "sync-source",
158                 _("External sync source"),
159                 sigc::mem_fun (*_session_config, &SessionConfiguration::get_sync_source),
160                 sigc::mem_fun (*_session_config, &SessionConfiguration::set_sync_source)
161                 );
162         
163         s->MTC_PortChanged.connect (_session_connections, boost::bind (&SessionOptionEditor::populate_sync_options, this, s, ssrc));
164         s->MIDIClock_PortChanged.connect (_session_connections, boost::bind (&SessionOptionEditor::populate_sync_options, this, s, ssrc));
165         s->config.ParameterChanged.connect (_session_connections, boost::bind (&SessionOptionEditor::follow_sync_state, this, _1, s, ssrc));
166
167         populate_sync_options (s, ssrc);
168         follow_sync_state (string ("external-sync"), s, ssrc);
169
170         add_option (_("Sync"), ssrc);
171
172         ComboOption<TimecodeFormat>* smf = new ComboOption<TimecodeFormat> (
173                 "timecode-format",
174                 _("Timecode frames-per-second"),
175                 sigc::mem_fun (*_session_config, &SessionConfiguration::get_timecode_format),
176                 sigc::mem_fun (*_session_config, &SessionConfiguration::set_timecode_format)
177                 );
178
179         smf->add (timecode_23976, _("23.976"));
180         smf->add (timecode_24, _("24"));
181         smf->add (timecode_24976, _("24.976"));
182         smf->add (timecode_25, _("25"));
183         smf->add (timecode_2997, _("29.97"));
184         smf->add (timecode_2997drop, _("29.97 drop"));
185         smf->add (timecode_30, _("30"));
186         smf->add (timecode_30drop, _("30 drop"));
187         smf->add (timecode_5994, _("59.94"));
188         smf->add (timecode_60, _("60"));
189
190         add_option (_("Sync"), smf);
191
192         add_option (_("Sync"), new BoolOption (
193                             "timecode-source-is-synced",
194                             _("Timecode source shares sample clock with audio interface"),
195                             sigc::mem_fun (*_session_config, &SessionConfiguration::get_timecode_source_is_synced),
196                             sigc::mem_fun (*_session_config, &SessionConfiguration::set_timecode_source_is_synced)
197                             ));
198
199         ComboOption<float>* vpu = new ComboOption<float> (
200                 "video-pullup",
201                 _("Pull-up / pull-down"),
202                 sigc::mem_fun (*_session_config, &SessionConfiguration::get_video_pullup),
203                 sigc::mem_fun (*_session_config, &SessionConfiguration::set_video_pullup)
204                 );
205
206         vpu->add (4.1667 + 0.1, _("4.1667 + 0.1%"));
207         vpu->add (4.1667, _("4.1667"));
208         vpu->add (4.1667 - 0.1, _("4.1667 - 0.1%"));
209         vpu->add (0.1, _("0.1"));
210         vpu->add (0, _("none"));
211         vpu->add (-0.1, _("-0.1"));
212         vpu->add (-4.1667 + 0.1, _("-4.1667 + 0.1%"));
213         vpu->add (-4.1667, _("-4.1667"));
214         vpu->add (-4.1667 - 0.1, _("-4.1667 - 0.1%"));
215
216         add_option (_("Sync"), vpu);
217
218         /* FADES */
219
220         ComboOption<CrossfadeModel>* cfm = new ComboOption<CrossfadeModel> (
221                 "xfade-model",
222                 _("Crossfades are created"),
223                 sigc::mem_fun (*_session_config, &SessionConfiguration::get_xfade_model),
224                 sigc::mem_fun (*_session_config, &SessionConfiguration::set_xfade_model)
225                 );
226
227         cfm->add (FullCrossfade, _("to span entire overlap"));
228         cfm->add (ShortCrossfade, _("short"));
229
230         add_option (_("Fades"), cfm);
231
232         add_option (_("Fades"), new SpinOption<float> (
233                 _("short-xfade-seconds"),
234                 _("Short crossfade length"),
235                 sigc::mem_fun (*_session_config, &SessionConfiguration::get_short_xfade_seconds),
236                 sigc::mem_fun (*_session_config, &SessionConfiguration::set_short_xfade_seconds),
237                 0, 1000, 1, 10,
238                 _("ms"), 0.001
239                             ));
240
241         add_option (_("Fades"), new SpinOption<float> (
242                 _("destructive-xfade-seconds"),
243                 _("Destructive crossfade length"),
244                 sigc::mem_fun (*_session_config, &SessionConfiguration::get_destructive_xfade_msecs),
245                 sigc::mem_fun (*_session_config, &SessionConfiguration::set_destructive_xfade_msecs),
246                 0, 1000, 1, 10,
247                 _("ms")
248                             ));
249
250         add_option (_("Fades"), new BoolOption (
251                             "auto-xfade",
252                             _("Create crossfades automatically"),
253                             sigc::mem_fun (*_session_config, &SessionConfiguration::get_auto_xfade),
254                             sigc::mem_fun (*_session_config, &SessionConfiguration::set_auto_xfade)
255                             ));
256
257         add_option (_("Fades"), new BoolOption (
258                             "xfades-active",
259                             _("Crossfades active"),
260                             sigc::mem_fun (*_session_config, &SessionConfiguration::get_xfades_active),
261                             sigc::mem_fun (*_session_config, &SessionConfiguration::set_xfades_active)
262                             ));
263
264         add_option (_("Fades"), new BoolOption (
265                             "xfades-visible",
266                             _("Crossfades visible"),
267                             sigc::mem_fun (*_session_config, &SessionConfiguration::get_xfades_visible),
268                             sigc::mem_fun (*_session_config, &SessionConfiguration::set_xfades_visible)
269                             ));
270
271         add_option (_("Fades"), new BoolOption (
272                             "use-region-fades",
273                             _("Region fades active"),
274                             sigc::mem_fun (*_session_config, &SessionConfiguration::get_use_region_fades),
275                             sigc::mem_fun (*_session_config, &SessionConfiguration::set_use_region_fades)
276                             ));
277
278         add_option (_("Fades"), new BoolOption (
279                             "show-region-fades",
280                             _("Region fades visible"),
281                             sigc::mem_fun (*_session_config, &SessionConfiguration::get_show_region_fades),
282                             sigc::mem_fun (*_session_config, &SessionConfiguration::set_show_region_fades)
283                             ));
284
285         /* MISC */
286
287         add_option (_("Misc"), new OptionEditorHeading (_("Audio file format")));
288
289         ComboOption<SampleFormat>* sf = new ComboOption<SampleFormat> (
290                 "native-file-data-format",
291                 _("Sample format"),
292                 sigc::mem_fun (*_session_config, &SessionConfiguration::get_native_file_data_format),
293                 sigc::mem_fun (*_session_config, &SessionConfiguration::set_native_file_data_format)
294                 );
295
296         sf->add (FormatFloat, _("32-bit floating point"));
297         sf->add (FormatInt24, _("24-bit integer"));
298         sf->add (FormatInt16, _("16-bit integer"));
299
300         add_option (_("Misc"), sf);
301
302         ComboOption<HeaderFormat>* hf = new ComboOption<HeaderFormat> (
303                 "native-file-header-format",
304                 _("File type"),
305                 sigc::mem_fun (*_session_config, &SessionConfiguration::get_native_file_header_format),
306                 sigc::mem_fun (*_session_config, &SessionConfiguration::set_native_file_header_format)
307                 );
308
309         hf->add (BWF, _("Broadcast WAVE"));
310         hf->add (WAVE, _("WAVE"));
311         hf->add (WAVE64, _("WAVE-64"));
312         hf->add (CAF, _("CAF"));
313
314         add_option (_("Misc"), hf);
315
316         add_option (_("Misc"), new OptionEditorHeading (_("Layering")));
317
318         ComboOption<LayerModel>* lm = new ComboOption<LayerModel> (
319                 "layer-model",
320                 _("Layering model in overlaid mode"),
321                 sigc::mem_fun (*_session_config, &SessionConfiguration::get_layer_model),
322                 sigc::mem_fun (*_session_config, &SessionConfiguration::set_layer_model)
323                 );
324
325         lm->add (LaterHigher, _("later is higher"));
326         lm->add (MoveAddHigher, _("most recently moved or added is higher"));
327         lm->add (AddHigher, _("most recently added is higher"));
328
329         add_option (_("Misc"), lm);
330
331         add_option (_("Misc"), new OptionEditorHeading (_("Broadcast WAVE metadata")));
332
333         add_option (_("Misc"), new EntryOption (
334                             "bwf-country-code",
335                             _("Country code"),
336                             sigc::mem_fun (*_session_config, &SessionConfiguration::get_bwf_country_code),
337                             sigc::mem_fun (*_session_config, &SessionConfiguration::set_bwf_country_code)
338                             ));
339
340         add_option (_("Misc"), new EntryOption (
341                             "bwf-organization-code",
342                             _("Organization code"),
343                             sigc::mem_fun (*_session_config, &SessionConfiguration::get_bwf_organization_code),
344                             sigc::mem_fun (*_session_config, &SessionConfiguration::set_bwf_organization_code)
345                             ));
346
347         add_option (_("Connections"), new ConnectionOptions (this, s));
348 }
349
350 void
351 SessionOptionEditor::populate_sync_options (Session* s, Option* opt)
352 {
353         ComboOption<SyncSource>* sync_opt = dynamic_cast<ComboOption<SyncSource>* > (opt);
354
355         vector<SyncSource> sync_opts = s->get_available_sync_options ();
356
357         sync_opt->clear ();
358
359         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
360                 sync_opt->add (*i, sync_source_to_string (*i));
361         }
362 }
363
364 void
365 SessionOptionEditor::follow_sync_state (std::string p, Session* s, Option* opt)
366 {
367         ComboOption<SyncSource>* sync_opt = dynamic_cast<ComboOption<SyncSource>* > (opt);
368         if (p == "external-sync") {
369                 if (s->config.get_external_sync()) {
370                         sync_opt->set_sensitive (false);
371                 } else {
372                         sync_opt->set_sensitive (true);
373                 }
374         }
375 }