1 /*
2 * Copyright (C) 2005-2006 Taybin Rutkin <taybin@taybin.com>
3 * Copyright (C) 2005-2017 Paul Davis <paul@linuxaudiosystems.com>
4 * Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
5 * Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net>
6 * Copyright (C) 2014-2019 Robin Gareus <robin@gareus.org>
7 * Copyright (C) 2015-2017 Ben Loftis <ben@harrisonconsoles.com>
8 * Copyright (C) 2015 Nick Mainsbridge <mainsbridge@gmail.com>
9 * Copyright (C) 2018 Len Ovens <len@ovenwerks.net>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26 #include <cstdio>
27 #include <cmath>
28
29 #include <sigc++/bind.h>
30 #include <gtkmm/stock.h>
31 #include <gtkmm/messagedialog.h>
32 #include <gtkmm/separator.h>
33 #include <gtkmm/table.h>
34
35 #include "pbd/error.h"
36 #include "pbd/convert.h"
37
38 #include "gtkmm2ext/utils.h"
39 #include "gtkmm2ext/doi.h"
40
41 #include "widgets/tooltips.h"
42
43 #include "ardour/plugin_manager.h"
44 #include "ardour/profile.h"
45 #include "ardour/template_utils.h"
46 #include "ardour/route_group.h"
47 #include "ardour/session.h"
48 #include "ardour/vca.h"
49
50 #include "LuaBridge/LuaBridge.h"
51
52 #include "ardour_message.h"
53 #include "add_route_dialog.h"
54 #include "ardour_ui.h"
55 #include "route_group_dialog.h"
56 #include "utils.h"
57
58 #include "pbd/i18n.h"
59
60 using namespace Gtk;
61 using namespace Gtkmm2ext;
62 using namespace std;
63 using namespace PBD;
64 using namespace ARDOUR;
65 using namespace ARDOUR_UI_UTILS;
66
67 std::vector<std::string> AddRouteDialog::channel_combo_strings;
68 std::vector<std::pair<std::string,std::string> > AddRouteDialog::builtin_types;
69
AddRouteDialog()70 AddRouteDialog::AddRouteDialog ()
71 : ArdourDialog (_("Add Track/Bus/VCA"))
72 , routes_adjustment (1, 1, 128, 1, 4)
73 , routes_spinner (routes_adjustment)
74 , configuration_label (_("Configuration:"))
75 , manual_label (_("Configuration:"))
76 , add_label (_("Add:"))
77 , name_label (_("Name:"))
78 , group_label (_("Group:"))
79 , insert_label (_("Position:"))
80 , strict_io_label (_("Pin Mode:"))
81 , mode_label (_("Record Mode:"))
82 , instrument_label (_("Instrument:"))
83 , last_route_count (1)
84 , route_count_set_by_template (false)
85 , name_edited_by_user (false)
86 {
87 set_name ("AddRouteDialog");
88 set_skip_taskbar_hint (true);
89 set_resizable (false);
90 set_position (WIN_POS_MOUSE);
91
92 name_template_entry.set_name (X_("AddRouteDialogNameTemplateEntry"));
93 // routes_spinner.set_name (X_("AddRouteDialogSpinner"));
94 channel_combo.set_name (X_("ChannelCountSelector"));
95 mode_combo.set_name (X_("ChannelCountSelector"));
96
97 refill_track_modes ();
98
99 if (builtin_types.empty()) {
100 builtin_types.push_back (
101 std::pair<string,string> (_("Audio Tracks"), std::string () +
102 _("Use these settings to create one or more audio tracks.") + "\n\n" +
103 _("You may select:") + "\n" +
104 "* " + _("The number of tracks to add") + "\n" +
105 "* " + _("A name for the track(s)") + "\n" +
106 "* " + _("Mono, stereo, or multi-channel operation for the track(s)") + "\n" +
107 "* " + _("A group which the track(s) will be assigned to") + "\n" +
108 #ifndef MIXBUS
109 "* " + _("The pin connections mode (see tooltip for details)") + "\n" +
110 #endif
111 "\n" + _("The track(s) will be added at the location specified by \"Position\"")
112 ));
113
114 builtin_types.push_back (
115 std::pair<string,string> (_("MIDI Tracks"), std::string () +
116 _("Use these settings to create one or more MIDI tracks.") + "\n\n" +
117 _("You may select:") + "\n" +
118 "* " + _("The number of tracks to add") + "\n" +
119 "* " + _("A name for the track(s)") + "\n" +
120 "* " + _("An instrument plugin (or select \"None\" to drive an external device)") + "\n" +
121 "* " + _("A group which the track(s) will be assigned to") + "\n" +
122 #ifndef MIXBUS
123 "* " + _("The pin connections mode (see tooltip for details)") + "\n" +
124 #endif
125 "\n" + _("The track(s) will be added at the location specified by \"Position\"")
126 ));
127
128 builtin_types.push_back (
129 std::pair<string,string> (_("Audio Busses"), std::string () +
130 _("Use these settings to create one or more audio busses.") + "\n\n" +
131 _("You may select:") + "\n" +
132 "* " + _("The number of busses to add") + "\n" +
133 "* " + _("A name for the buss(es)") + "\n" +
134 "* " + _("A group which the buss(es) will be assigned to") + "\n" +
135 #ifndef MIXBUS
136 "* " + _("The pin connections mode (see tooltip for details)") + "\n" +
137 #endif
138 "\n" + _("The buss(es) will be added at the location specified by \"Position\"")
139 ));
140
141 builtin_types.push_back (
142 std::pair<string,string> (_("MIDI Busses"), std::string () +
143 _("Use these settings to create one or more MIDI busses.") + "\n\n" +
144 _("MIDI busses can combine the output of multiple tracks. They are sometimes used\nto host a single \"heavy\" instrument plugin which is fed from multiple MIDI tracks.") + "\n\n" +
145 _("You may select:") + "\n" +
146 "* " + _("The number of busses to add") + "\n" +
147 "* " + _("A name for the buss(es)") + "\n" +
148 "* " + _("An instrument plugin (or select \"None\" to drive an external device)") + "\n" +
149 "* " + _("A group which the buss(es) will be assigned to") + "\n" +
150 #ifndef MIXBUS
151 "* " + _("The pin connections mode (see tooltip for details)") + "\n" +
152 #endif
153 "\n" + _("The buss(es) will be added at the location specified by \"Position\"")
154 ));
155
156 builtin_types.push_back (
157 std::pair<string,string> (_("VCA Masters"), std::string () +
158 _("Use these settings to create one or more VCA masters.") + "\n\n" +
159 _("You may select:") + "\n" +
160 "* " + _("The number of VCAs to add") + "\n" +
161 "* " + _("A name for the VCA(s). \"%n\" will be replaced by an index number for each VCA")
162 ));
163
164 builtin_types.push_back (
165 std::pair<string,string> (_("Foldback Busses"), std::string () +
166 _("Use these settings to create one or more foldback busses.") + "\n\n" +
167 _("Foldback busses are used as master outputs for monitor channels and are fed by\nhidden monitor sends.") + "\n\n" +
168 _("You may select:") + "\n" +
169 "* " + _("The number of busses to add") + "\n" +
170 "* " + _("A name for the buss(es)")
171 ));
172 }
173
174 insert_at_combo.append_text (_("First"));
175 insert_at_combo.append_text (_("Before Selection"));
176 insert_at_combo.append_text (_("After Selection"));
177 insert_at_combo.append_text (_("Last"));
178 insert_at_combo.set_active (3);
179
180 strict_io_combo.append_text (_("Flexible-I/O"));
181 strict_io_combo.append_text (_("Strict-I/O"));
182 strict_io_combo.set_active (Config->get_strict_io () ? 1 : 0);
183
184 /* top-level VBox */
185 VBox* vbox = manage (new VBox);
186 get_vbox()->set_spacing (4);
187 vbox->set_spacing (18);
188 vbox->set_border_width (5);
189
190 /* this box contains the template chooser, and the template details */
191 HBox* template_hbox = manage (new HBox);
192 template_hbox->set_spacing (8);
193
194 /* scrollbars for the template chooser and template descriptions.... */
195 Gtk::ScrolledWindow *template_scroller = manage (new Gtk::ScrolledWindow());
196 template_scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
197 template_scroller->add (trk_template_chooser);
198
199 Gtk::ScrolledWindow *desc_scroller = manage (new Gtk::ScrolledWindow());
200 desc_scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
201 desc_scroller->add (trk_template_desc);
202
203 /* this is the outer sample that surrounds the description and the settings-table */
204 trk_template_outer_frame.set_name (X_("TextHighlightFrame"));
205
206 /* this is the "inner frame" that surrounds the description text */
207 trk_template_desc_frame.set_name (X_("TextHighlightFrame"));
208 trk_template_desc_frame.add (*desc_scroller);
209
210 /* template_chooser is the treeview showing available templates */
211 trk_template_model = TreeStore::create (track_template_columns);
212 trk_template_chooser.set_model (trk_template_model);
213 trk_template_chooser.append_column (_("Template/Type"), track_template_columns.name);
214 #ifdef MIXBUS
215 trk_template_chooser.append_column (_("Modified With"), track_template_columns.modified_with);
216 #endif
217 trk_template_chooser.set_headers_visible (true);
218 trk_template_chooser.get_selection()->set_mode (SELECTION_SINGLE);
219 trk_template_chooser.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &AddRouteDialog::trk_template_row_selected));
220 trk_template_chooser.set_sensitive (true);
221
222 /* template_desc is the textview that displays the currently selected template's description */
223 trk_template_desc.set_editable (false);
224 trk_template_desc.set_can_focus (false);
225 trk_template_desc.set_wrap_mode (Gtk::WRAP_WORD);
226 trk_template_desc.set_size_request(400,200);
227 trk_template_desc.set_name (X_("TextOnBackground"));
228 trk_template_desc.set_border_width (6);
229
230 Table *settings_table = manage (new Table (2, 6, false));
231 settings_table->set_row_spacings (8);
232 settings_table->set_col_spacings (4);
233 settings_table->set_col_spacing (3, 20);
234 settings_table->set_border_width (12);
235
236 VBox* settings_vbox = manage (new VBox);
237 settings_vbox->pack_start(trk_template_desc_frame , true, true);
238 settings_vbox->pack_start(*settings_table , true, true);
239 settings_vbox->set_border_width (4);
240
241 trk_template_outer_frame.add (*settings_vbox);
242
243 template_hbox->pack_start (*template_scroller, true, true);
244 template_hbox->pack_start (trk_template_outer_frame, true, true);
245
246 vbox->pack_start (*template_hbox, true, true);
247
248
249 /* Now pack the "settings table" with manual controls (these controls are sensitized by the left-side selection) */
250
251 int n = 0;
252
253 HBox *separator_hbox = manage (new HBox);
254 separator_hbox->pack_start (manual_label, false, false);
255 separator_hbox->pack_start (*(manage (new Gtk::HSeparator)), true, true);
256 separator_hbox->set_spacing (6);
257 settings_table->attach (*separator_hbox, 0, 6, n, n + 1, Gtk::FILL, Gtk::SHRINK, 0, 0);
258
259 ++n;
260
261 /* Number */
262 add_label.set_alignment (Gtk::ALIGN_RIGHT, Gtk::ALIGN_CENTER);
263 settings_table->attach (add_label, 0, 1, n, n + 1, Gtk::FILL, Gtk::SHRINK, 0, 0);
264 Gtk::Alignment *align = manage (new Alignment (0, .5, 0, 0));
265 align->add (routes_spinner);
266 settings_table->attach (*align, 1, 2, n, n + 1, Gtk::FILL, Gtk::SHRINK, 0, 0);
267
268 ++n;
269
270 /* Name */
271 name_label.set_alignment (Gtk::ALIGN_RIGHT, Gtk::ALIGN_CENTER);
272 settings_table->attach (name_label, 0, 1, n, n + 1, Gtk::FILL, Gtk::SHRINK, 0, 0);
273 settings_table->attach (name_template_entry, 1, 3, n, n + 1, Gtk::FILL, Gtk::SHRINK, 0, 0);
274
275 /* Route configuration */
276 configuration_label.set_alignment (Gtk::ALIGN_RIGHT, Gtk::ALIGN_CENTER);
277 settings_table->attach (configuration_label, 4, 5, n, n + 1, Gtk::FILL, Gtk::SHRINK, 0, 0);
278 settings_table->attach (channel_combo, 5, 6, n, n + 1, Gtk::FILL, Gtk::SHRINK, 0, 0);
279
280 ++n;
281
282 /* instrument choice (for MIDI) */
283 instrument_label.set_alignment (Gtk::ALIGN_RIGHT, Gtk::ALIGN_CENTER);
284 settings_table->attach (instrument_label, 0, 1, n, n + 1, Gtk::FILL, Gtk::SHRINK, 0, 0);
285 settings_table->attach (instrument_combo, 1, 3, n, n + 1, Gtk::FILL, Gtk::SHRINK, 0, 0);
286
287 /* Group choice */
288 group_label.set_alignment (Gtk::ALIGN_RIGHT, Gtk::ALIGN_CENTER);
289 settings_table->attach (group_label, 4, 5, n, n + 1, Gtk::FILL, Gtk::SHRINK, 0, 0);
290 settings_table->attach (route_group_combo, 5, 6, n, n + 1, Gtk::FILL, Gtk::SHRINK, 0, 0);
291
292 ++n;
293
294 /* New Route's I/O is.. {strict/flexible} */
295 if (Profile->get_mixbus ()) {
296 strict_io_combo.set_active (1);
297 } else {
298 strict_io_label.set_alignment (Gtk::ALIGN_RIGHT, Gtk::ALIGN_CENTER);
299 settings_table->attach (strict_io_label, 0, 1, n, n + 1, Gtk::FILL, Gtk::SHRINK, 0, 0);
300 settings_table->attach (strict_io_combo, 1, 3, n, n + 1, Gtk::FILL, Gtk::SHRINK, 0, 0);
301
302 ArdourWidgets::set_tooltip (strict_io_combo,
303 _("With strict-i/o enabled, Effect Processors will not modify the number of channels on a track. The number of output channels will always match the number of input channels."));
304
305 /* recording mode */
306 mode_label.set_alignment (Gtk::ALIGN_RIGHT, Gtk::ALIGN_CENTER);
307 settings_table->attach (mode_label, 4, 5, n, n + 1, Gtk::FILL, Gtk::SHRINK, 0, 0);
308 settings_table->attach (mode_combo, 5, 6, n, n + 1, Gtk::FILL, Gtk::SHRINK, 0, 0);
309
310 ++n;
311 }
312
313 HBox* outer_box = manage (new HBox);
314 outer_box->set_spacing (4);
315
316 /* New route will be inserted at.. */
317 insert_label.set_alignment (Gtk::ALIGN_RIGHT, Gtk::ALIGN_CENTER);
318 outer_box->pack_start (insert_label, false, false);
319 outer_box->pack_start (insert_at_combo, false, false);
320
321 /* quick-add button (add item but don't close dialog) */
322 Gtk::Button* addnoclose_button = manage (new Gtk::Button(_("Add selected items (and leave dialog open)")));
323 addnoclose_button->set_can_default ();
324 addnoclose_button->signal_clicked ().connect (sigc::bind (sigc::mem_fun (*this, &Gtk::Dialog::response), Add));
325 outer_box->pack_end (*addnoclose_button, false, false);
326
327 vbox->pack_start (*outer_box, true, true);
328
329 get_vbox()->pack_start (*vbox, false, false);
330
331 name_template_entry.signal_insert_text ().connect (sigc::mem_fun (*this, &AddRouteDialog::name_template_entry_insertion));
332 name_template_entry.signal_delete_text ().connect (sigc::mem_fun (*this, &AddRouteDialog::name_template_entry_deletion));
333 channel_combo.signal_changed().connect (sigc::mem_fun (*this, &AddRouteDialog::channel_combo_changed));
334 channel_combo.set_row_separator_func (sigc::mem_fun (*this, &AddRouteDialog::channel_separator));
335 route_group_combo.set_row_separator_func (sigc::mem_fun (*this, &AddRouteDialog::route_separator));
336 route_group_combo.signal_changed ().connect (sigc::mem_fun (*this, &AddRouteDialog::group_changed));
337 instrument_combo.signal_changed ().connect (sigc::mem_fun (*this, &AddRouteDialog::instrument_changed));
338
339 routes_spinner.signal_activate ().connect (sigc::bind (sigc::mem_fun (*this, &Gtk::Dialog::response), AddAndClose));
340 name_template_entry.signal_activate ().connect (sigc::bind (sigc::mem_fun (*this, &Gtk::Dialog::response), AddAndClose));
341 trk_template_chooser.signal_row_activated ().connect (sigc::hide (sigc::hide (sigc::bind (sigc::mem_fun (*this, &Gtk::Dialog::response), AddAndClose))));
342
343 show_all_children ();
344
345 /* track template info will be managed whenever
346 * this dialog is shown, via ::on_show()
347 */
348
349 add_button (_("Add and Close"), AddAndClose);
350 set_response_sensitive (AddAndClose, true);
351 set_default_response (AddAndClose);
352
353 refill_channel_setups ();
354 }
355
~AddRouteDialog()356 AddRouteDialog::~AddRouteDialog ()
357 {
358 }
359
360 void
on_response(int r)361 AddRouteDialog::on_response (int r)
362 {
363 reset_name_edited ();
364 /* Don't call ArdourDialog::on_response() because that will
365 automatically hide the dialog.
366 */
367 Gtk::Dialog::on_response (r);
368 }
369
370 void
trk_template_row_selected()371 AddRouteDialog::trk_template_row_selected ()
372 {
373 if (trk_template_chooser.get_selection()->count_selected_rows() != 1) {
374 return;
375 }
376
377 TreeIter iter = trk_template_chooser.get_selection ()->get_selected ();
378 assert (iter);
379
380 string d = (*iter)[track_template_columns.description];
381 trk_template_desc.get_buffer ()->set_text (d);
382
383 const string n = (*iter)[track_template_columns.name];
384 const string p = (*iter)[track_template_columns.path];
385
386 bool route_count_now_set_by_template = false;
387
388 if (p.substr (0, 11) == "urn:ardour:") {
389 /* lua script - meta-template */
390 const std::map<std::string, std::string> rs (ARDOUR_UI::instance()->route_setup_info (p.substr (11)));
391
392 trk_template_desc.set_sensitive (true);
393
394 add_label.set_sensitive (rs.find ("how_many") != rs.end ());
395 name_label.set_sensitive (rs.find ("name") != rs.end());
396 group_label.set_sensitive (rs.find ("group") != rs.end());
397 configuration_label.set_sensitive (rs.find ("channels") != rs.end ());
398 mode_label.set_sensitive (rs.find ("track_mode") != rs.end ());
399 instrument_label.set_sensitive (rs.find ("instrument") != rs.end ());
400 strict_io_label.set_sensitive (rs.find ("strict_io") != rs.end());
401
402 routes_spinner.set_sensitive (rs.find ("how_many") != rs.end ());
403 name_template_entry.set_sensitive (rs.find ("name") != rs.end ());
404 route_group_combo.set_sensitive (rs.find ("group") != rs.end());
405 channel_combo.set_sensitive (rs.find ("channels") != rs.end ());
406 mode_combo.set_sensitive (rs.find ("track_mode") != rs.end ());
407 instrument_combo.set_sensitive (rs.find ("instrument") != rs.end ());
408 strict_io_combo.set_sensitive (rs.find ("strict_io") != rs.end());
409
410 bool any_enabled = rs.find ("how_many") != rs.end ()
411 || rs.find ("name") != rs.end ()
412 || rs.find ("group") != rs.end()
413 || rs.find ("channels") != rs.end ()
414 || rs.find ("track_mode") != rs.end ()
415 || rs.find ("instrument") != rs.end ()
416 || rs.find ("strict_io") != rs.end();
417
418 manual_label.set_sensitive (any_enabled);
419
420 std::map<string,string>::const_iterator it;
421
422 if ((it = rs.find ("name")) != rs.end()) {
423 name_template_entry.set_text (it->second);
424 } else {
425 name_template_entry.set_text ("");
426 }
427
428 if ((it = rs.find ("how_many")) != rs.end() && atoi (it->second.c_str()) > 0) {
429 if (!route_count_set_by_template) {
430 last_route_count = routes_adjustment.get_value();
431 }
432 routes_adjustment.set_value (atoi (it->second.c_str()));
433 route_count_now_set_by_template = true;
434 route_count_set_by_template = true;
435 }
436
437 if ((it = rs.find ("track_mode")) != rs.end()) {
438 switch ((ARDOUR::TrackMode) atoi (it->second.c_str())) {
439 case ARDOUR::Normal:
440 mode_combo.set_active_text (_("Normal"));
441 break;
442 default: // "NonLayered" enum is still present for session-format compat
443 break;
444 }
445 }
446
447 if ((it = rs.find ("strict_io")) != rs.end()) {
448 if (it->second == X_("true")) {
449 strict_io_combo.set_active (1);
450 } else if (it->second == X_("false")) {
451 strict_io_combo.set_active (0);
452 }
453 }
454
455 if ((it = rs.find ("channels")) != rs.end()) {
456 uint32_t channels = atoi (it->second.c_str());
457 for (ChannelSetups::iterator i = channel_setups.begin(); i != channel_setups.end(); ++i) {
458 if ((*i).channels == channels) {
459 channel_combo.set_active_text ((*i).name);
460 break;
461 }
462 }
463 }
464
465 } else if (!p.empty ()) {
466 /* user-template */
467 trk_template_desc.set_sensitive (true);
468
469 manual_label.set_sensitive (true);
470 add_label.set_sensitive (true);
471 name_label.set_sensitive (true);
472 group_label.set_sensitive (false);
473 strict_io_label.set_sensitive (false);
474 configuration_label.set_sensitive (false);
475 mode_label.set_sensitive (false);
476 instrument_label.set_sensitive (false);
477
478 routes_spinner.set_sensitive (true);
479 name_template_entry.set_sensitive (true);
480 channel_combo.set_sensitive (false);
481 mode_combo.set_sensitive (false);
482 instrument_combo.set_sensitive (false);
483 strict_io_combo.set_sensitive (false);
484 route_group_combo.set_sensitive (false);
485
486 } else {
487 /* all manual mode */
488 trk_template_desc.set_sensitive (false);
489
490 manual_label.set_sensitive (true);
491 add_label.set_sensitive (true);
492 name_label.set_sensitive (true);
493 group_label.set_sensitive (true);
494 strict_io_label.set_sensitive (true);
495
496 routes_spinner.set_sensitive (true);
497 name_template_entry.set_sensitive (true);
498 track_type_chosen ();
499 }
500
501 if (!route_count_now_set_by_template && route_count_set_by_template) {
502 routes_adjustment.set_value (last_route_count);
503 route_count_set_by_template = false;
504 }
505 }
506
507 void
instrument_changed()508 AddRouteDialog::instrument_changed ()
509 {
510 if (name_edited_by_user) {
511 return;
512 }
513 std::string n = instrument_combo.selected_instrument_name ();
514 name_template_entry.set_text (n.empty () ? _("MIDI") : n);
515 reset_name_edited ();
516 }
517
518 void
name_template_entry_insertion(Glib::ustring const &,int *)519 AddRouteDialog::name_template_entry_insertion (Glib::ustring const &,int*)
520 {
521 if (name_template ().empty ()) {
522 name_edited_by_user = false;
523 } else {
524 name_edited_by_user = true;
525 }
526 }
527
528 void
name_template_entry_deletion(int,int)529 AddRouteDialog::name_template_entry_deletion (int, int)
530 {
531 if (name_template ().empty ()) {
532 name_edited_by_user = false;
533 } else {
534 name_edited_by_user = true;
535 }
536 }
537
538 void
channel_combo_changed()539 AddRouteDialog::channel_combo_changed ()
540 {
541 refill_track_modes ();
542 }
543
544 std::string
get_template_path()545 AddRouteDialog::get_template_path ()
546 {
547 string p;
548
549 if (trk_template_chooser.get_selection()->count_selected_rows() > 0) {
550 TreeIter iter = trk_template_chooser.get_selection()->get_selected();
551
552 if (iter) {
553 string n = (*iter)[track_template_columns.name];
554 if (n != _("Manual Configuration")) {
555 p = (*iter)[track_template_columns.path];
556 }
557 }
558 }
559
560 return p;
561 }
562
563
564 AddRouteDialog::TypeWanted
type_wanted()565 AddRouteDialog::type_wanted()
566 {
567 if (trk_template_chooser.get_selection()->count_selected_rows() != 1) {
568 return AudioTrack;
569 }
570 TreeIter iter = trk_template_chooser.get_selection ()->get_selected ();
571 assert (iter);
572
573 const string str = (*iter)[track_template_columns.name];
574 if (str == _("Audio Busses")) {
575 return AudioBus;
576 } else if (str == _("MIDI Busses")){
577 return MidiBus;
578 } else if (str == _("MIDI Tracks")){
579 return MidiTrack;
580 } else if (str == _("Audio Tracks")) {
581 return AudioTrack;
582 } else if (str == _("VCA Masters")) {
583 return VCAMaster;
584 } else if (str == _("Foldback Busses")) {
585 return FoldbackBus;
586 } else {
587 assert (0);
588 return AudioTrack;
589 }
590 }
591
592 void
maybe_update_name_template_entry()593 AddRouteDialog::maybe_update_name_template_entry ()
594 {
595 if (name_edited_by_user) {
596 return;
597 }
598
599 switch (type_wanted()) {
600 case AudioTrack:
601 name_template_entry.set_text (_("Audio"));
602 break;
603 case MidiTrack:
604 /* set name of instrument or _("MIDI") */
605 instrument_changed ();
606 break;
607 case AudioBus:
608 case MidiBus:
609 name_template_entry.set_text (_("Bus"));
610 break;
611 case FoldbackBus:
612 name_template_entry.set_text (_("Foldback"));
613 break;
614 case VCAMaster:
615 name_template_entry.set_text (VCA::default_name_template());
616 break;
617 }
618 /* ignore programatic change, restore false */
619 reset_name_edited ();
620 }
621
622 void
track_type_chosen()623 AddRouteDialog::track_type_chosen ()
624 {
625 switch (type_wanted()) {
626 case AudioTrack:
627
628 configuration_label.set_sensitive (true);
629 channel_combo.set_sensitive (true);
630
631 mode_label.set_sensitive (true);
632 mode_combo.set_sensitive (true);
633
634 instrument_label.set_sensitive (false);
635 instrument_combo.set_sensitive (false);
636
637 group_label.set_sensitive (true);
638 route_group_combo.set_sensitive (true);
639
640 strict_io_label.set_sensitive (true);
641 strict_io_combo.set_sensitive (true);
642
643 insert_label.set_sensitive (true);
644 insert_at_combo.set_sensitive (true);
645
646 break;
647 case MidiTrack:
648
649 configuration_label.set_sensitive (false);
650 channel_combo.set_sensitive (false);
651
652 mode_label.set_sensitive (false);
653 mode_combo.set_sensitive (false);
654
655 instrument_label.set_sensitive (true);
656 instrument_combo.set_sensitive (true);
657
658 group_label.set_sensitive (true);
659 route_group_combo.set_sensitive (true);
660
661 strict_io_label.set_sensitive (true);
662 strict_io_combo.set_sensitive (true);
663
664 insert_label.set_sensitive (true);
665 insert_at_combo.set_sensitive (true);
666
667 break;
668 case AudioBus:
669
670 configuration_label.set_sensitive (true);
671 channel_combo.set_sensitive (true);
672
673 mode_label.set_sensitive (false);
674 mode_combo.set_sensitive (false);
675
676 instrument_label.set_sensitive (false);
677 instrument_combo.set_sensitive (false);
678
679 group_label.set_sensitive (true);
680 route_group_combo.set_sensitive (true);
681
682 strict_io_label.set_sensitive (true);
683 strict_io_combo.set_sensitive (true);
684
685 insert_label.set_sensitive (true);
686 insert_at_combo.set_sensitive (true);
687
688 break;
689 case VCAMaster:
690
691 configuration_label.set_sensitive (false);
692 channel_combo.set_sensitive (false);
693
694 mode_label.set_sensitive (false);
695 mode_combo.set_sensitive (false);
696
697 instrument_label.set_sensitive (false);
698 instrument_combo.set_sensitive (false);
699
700 group_label.set_sensitive (false);
701 route_group_combo.set_sensitive (false);
702
703 strict_io_label.set_sensitive (false);
704 strict_io_combo.set_sensitive (false);
705
706 insert_label.set_sensitive (false);
707 insert_at_combo.set_sensitive (false);
708
709 break;
710 case MidiBus:
711
712 configuration_label.set_sensitive (false);
713 channel_combo.set_sensitive (false);
714
715 mode_label.set_sensitive (false);
716 mode_combo.set_sensitive (false);
717
718 instrument_label.set_sensitive (true);
719 instrument_combo.set_sensitive (true);
720
721 group_label.set_sensitive (true);
722 route_group_combo.set_sensitive (true);
723
724 strict_io_label.set_sensitive (true);
725 strict_io_combo.set_sensitive (true);
726
727 insert_label.set_sensitive (true);
728 insert_at_combo.set_sensitive (true);
729
730 break;
731 case FoldbackBus:
732
733 configuration_label.set_sensitive (true);
734 channel_combo.set_sensitive (true);
735
736 mode_label.set_sensitive (false);
737 mode_combo.set_sensitive (false);
738
739 instrument_label.set_sensitive (false);
740 instrument_combo.set_sensitive (false);
741
742 group_label.set_sensitive (false);
743 route_group_combo.set_sensitive (false);
744
745 strict_io_label.set_sensitive (false);
746 strict_io_combo.set_sensitive (false);
747
748 insert_label.set_sensitive (false);
749 insert_at_combo.set_sensitive (false);
750
751 break;
752 }
753
754 maybe_update_name_template_entry ();
755 }
756
757 string
name_template() const758 AddRouteDialog::name_template () const
759 {
760 return name_template_entry.get_text ();
761 }
762
763 bool
name_template_is_default() const764 AddRouteDialog::name_template_is_default () const
765 {
766 string n = name_template();
767
768 if (n == _("Audio") ||
769 n == _("MIDI") ||
770 n == _("Bus") ||
771 n == _("Foldback") ||
772 n == VCA::default_name_template()) {
773 return true;
774 }
775
776 return false;
777 }
778
779 int
count()780 AddRouteDialog::count ()
781 {
782 return (int) floor (routes_adjustment.get_value ());
783 }
784
785 void
refill_track_modes()786 AddRouteDialog::refill_track_modes ()
787 {
788 vector<string> s;
789
790 s.push_back (_("Normal"));
791 set_popdown_strings (mode_combo, s);
792 mode_combo.set_active_text (s.front());
793 }
794
795 ARDOUR::TrackMode
mode()796 AddRouteDialog::mode ()
797 {
798 std::string str = mode_combo.get_active_text();
799 if (str == _("Normal")) {
800 return ARDOUR::Normal;
801 } else if (str == _("Non Layered")){
802 return ARDOUR::NonLayered;
803 } else {
804 fatal << string_compose (X_("programming error: unknown track mode in add route dialog combo = %1"), str)
805 << endmsg;
806 abort(); /*NOTREACHED*/
807 }
808 /* keep gcc happy */
809 return ARDOUR::Normal;
810 }
811
812 uint32_t
channel_count()813 AddRouteDialog::channel_count ()
814 {
815 string str = channel_combo.get_active_text();
816 for (ChannelSetups::iterator i = channel_setups.begin(); i != channel_setups.end(); ++i) {
817 if (str == (*i).name) {
818 return (*i).channels;
819 }
820 }
821 return 0;
822 }
823
824 ChanCount
channels()825 AddRouteDialog::channels ()
826 {
827 ChanCount ret;
828 switch (type_wanted()) {
829 case AudioTrack:
830 case AudioBus:
831 ret.set (DataType::AUDIO, channel_count ());
832 ret.set (DataType::MIDI, 0);
833 break;
834
835 case MidiBus:
836 case MidiTrack:
837 ret.set (DataType::AUDIO, 0);
838 ret.set (DataType::MIDI, 1);
839 break;
840
841 case FoldbackBus:
842 ret.set (DataType::AUDIO, channel_count ());
843 ret.set (DataType::MIDI, 0);
844 break;
845
846 default:
847 break;
848 }
849
850 return ret;
851 }
852
853 void
on_show()854 AddRouteDialog::on_show ()
855 {
856 routes_spinner.grab_focus ();
857 reset_name_edited ();
858
859 refill_route_groups ();
860 refill_channel_setups ();
861
862 Dialog::on_show ();
863 }
864
865 void
refill_channel_setups()866 AddRouteDialog::refill_channel_setups ()
867 {
868 ChannelSetup chn;
869
870 string channel_current_choice = channel_combo.get_active_text();
871
872 channel_combo_strings.clear ();
873 channel_setups.clear ();
874
875 chn.name = _("Mono");
876 chn.channels = 1;
877 channel_setups.push_back (chn);
878
879 chn.name = _("Stereo");
880 chn.channels = 2;
881 channel_setups.push_back (chn);
882
883 if (!ARDOUR::Profile->get_mixbus()) {
884
885 chn.name = "separator";
886 channel_setups.push_back (chn);
887
888 chn.name = _("3 Channel");
889 chn.channels = 3;
890 channel_setups.push_back (chn);
891
892 chn.name = _("4 Channel");
893 chn.channels = 4;
894 channel_setups.push_back (chn);
895
896 chn.name = _("5 Channel");
897 chn.channels = 5;
898 channel_setups.push_back (chn);
899
900 chn.name = _("6 Channel");
901 chn.channels = 6;
902 channel_setups.push_back (chn);
903
904 chn.name = _("8 Channel");
905 chn.channels = 8;
906 channel_setups.push_back (chn);
907
908 chn.name = _("12 Channel");
909 chn.channels = 12;
910 channel_setups.push_back (chn);
911
912 chn.name = _("Custom");
913 chn.channels = 0;
914 channel_setups.push_back (chn);
915 }
916
917 for (ChannelSetups::iterator i = channel_setups.begin(); i != channel_setups.end(); ++i) {
918 channel_combo_strings.push_back ((*i).name);
919 }
920
921 trk_template_model->clear();
922 bool selected_default = false;
923
924 for (std::vector<std::pair<std::string,std::string> >::const_iterator i = builtin_types.begin(); i != builtin_types.end(); ++i) {
925 TreeModel::Row row = *(trk_template_model->append ());
926 row[track_template_columns.name] = (*i).first;
927 row[track_template_columns.path] = "";
928 row[track_template_columns.description] = (*i).second;
929 row[track_template_columns.modified_with] = "";
930
931 if (!selected_default && !Profile->get_mixbus ()) {
932 trk_template_chooser.get_selection()->select(row);
933 selected_default = true;
934 }
935 }
936
937 /* Add any Lua scripts (factory templates) found in the scripts folder */
938 LuaScriptList& ms (LuaScripting::instance ().scripts (LuaScriptInfo::EditorAction));
939 for (LuaScriptList::const_iterator s = ms.begin(); s != ms.end(); ++s) {
940 if (!((*s)->subtype & LuaScriptInfo::RouteSetup)) {
941 continue;
942 }
943 TreeModel::Row row;
944 if ((*s)->name == "Create Audio Tracks Interactively" && Profile->get_mixbus ()) {
945 /* somewhat-special, Ben says: "most-used template" */
946 row = *(trk_template_model->prepend ());
947 } else {
948 row = *(trk_template_model->append ());
949 }
950 row[track_template_columns.name] = (*s)->name;
951 row[track_template_columns.path] = "urn:ardour:" + (*s)->path;
952 row[track_template_columns.description] = (*s)->description;
953 row[track_template_columns.modified_with] = string_compose ("{%1}", _("Factory Template"));
954
955 if ((*s)->name == "Create Audio Tracks Interactively" && Profile->get_mixbus ()) {
956 trk_template_chooser.get_selection()->select(row);
957 selected_default = true;
958 }
959 }
960
961 if (!selected_default && !trk_template_model->children().empty()) {
962 TreeModel::Children rows = trk_template_model->children();
963 trk_template_chooser.get_selection()->select(rows[0]);
964 }
965
966 std::vector<ARDOUR::TemplateInfo> route_templates;
967 ARDOUR::find_route_templates (route_templates);
968
969 for (vector<TemplateInfo>::iterator x = route_templates.begin(); x != route_templates.end(); ++x) {
970 TreeModel::Row row = *(trk_template_model->append ());
971
972 row[track_template_columns.name] = x->name;
973 row[track_template_columns.path] = x->path;
974 row[track_template_columns.description] = x->description;
975 row[track_template_columns.modified_with] = x->modified_with;
976 }
977
978 set_popdown_strings (channel_combo, channel_combo_strings);
979
980 if (!channel_current_choice.empty()) {
981 channel_combo.set_active_text (channel_current_choice);
982 } else {
983 channel_combo.set_active_text (channel_combo_strings.front());
984 }
985 }
986
987 void
add_route_group(RouteGroup * g)988 AddRouteDialog::add_route_group (RouteGroup* g)
989 {
990 route_group_combo.insert_text (3, g->name ());
991 }
992
993 RouteGroup*
route_group()994 AddRouteDialog::route_group ()
995 {
996 if (!_session || route_group_combo.get_active_row_number () == 2) {
997 return 0;
998 }
999
1000 return _session->route_group_by_name (route_group_combo.get_active_text());
1001 }
1002
1003 bool
use_strict_io()1004 AddRouteDialog::use_strict_io() {
1005 return strict_io_combo.get_active_row_number () == 1;
1006 }
1007
1008 void
refill_route_groups()1009 AddRouteDialog::refill_route_groups ()
1010 {
1011 route_group_combo.clear ();
1012 route_group_combo.append_text (_("New Group..."));
1013
1014 route_group_combo.append_text ("separator");
1015
1016 route_group_combo.append_text (_("No Group"));
1017
1018 if (_session) {
1019 _session->foreach_route_group (sigc::mem_fun (*this, &AddRouteDialog::add_route_group));
1020 }
1021
1022 route_group_combo.set_active (2);
1023 }
1024
1025 void
group_changed()1026 AddRouteDialog::group_changed ()
1027 {
1028 if (_session && route_group_combo.get_active_text () == _("New Group...")) {
1029 RouteGroup* g = new RouteGroup (*_session, "");
1030 RouteGroupDialog* d = new RouteGroupDialog (g, true);
1031
1032 d->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &AddRouteDialog::new_group_dialog_finished), d));
1033 d->present();
1034 }
1035 }
1036
1037 void
new_group_dialog_finished(int r,RouteGroupDialog * d)1038 AddRouteDialog::new_group_dialog_finished (int r, RouteGroupDialog* d)
1039 {
1040 if (r == RESPONSE_OK) {
1041
1042 if (!d->name_check()) {
1043 return;
1044 }
1045
1046 if (_session) {
1047 _session->add_route_group (d->group());
1048 }
1049
1050 add_route_group (d->group());
1051 route_group_combo.set_active (3);
1052 } else {
1053 delete d->group ();
1054 route_group_combo.set_active (2);
1055 }
1056
1057 delete_when_idle (d);
1058 }
1059
1060 RouteDialogs::InsertAt
insert_at()1061 AddRouteDialog::insert_at ()
1062 {
1063 using namespace RouteDialogs;
1064
1065 std::string str = insert_at_combo.get_active_text();
1066
1067 if (str == _("First")) {
1068 return First;
1069 } else if (str == _("After Selection")) {
1070 return AfterSelection;
1071 } else if (str == _("Before Selection")){
1072 return BeforeSelection;
1073 }
1074 return Last;
1075 }
1076
1077 bool
channel_separator(const Glib::RefPtr<Gtk::TreeModel> &,const Gtk::TreeModel::iterator & i)1078 AddRouteDialog::channel_separator (const Glib::RefPtr<Gtk::TreeModel> &, const Gtk::TreeModel::iterator &i)
1079 {
1080 channel_combo.set_active (i);
1081
1082 return channel_combo.get_active_text () == "separator";
1083 }
1084
1085 bool
route_separator(const Glib::RefPtr<Gtk::TreeModel> &,const Gtk::TreeModel::iterator & i)1086 AddRouteDialog::route_separator (const Glib::RefPtr<Gtk::TreeModel> &, const Gtk::TreeModel::iterator &i)
1087 {
1088 route_group_combo.set_active (i);
1089
1090 return route_group_combo.get_active_text () == "separator";
1091 }
1092
1093 PluginInfoPtr
requested_instrument()1094 AddRouteDialog::requested_instrument ()
1095 {
1096 return instrument_combo.selected_instrument();
1097 }
1098