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