fix crash when trying to create a non-template track/bus with >2 channels; put MIDI...
[ardour.git] / gtk2_ardour / add_route_dialog.cc
1 /*
2   Copyright (C) 2003 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
20 #include <cstdio>
21 #include <cmath>
22
23 #include <sigc++/bind.h>
24 #include <gtkmm/stock.h>
25 #include <gtkmm/separator.h>
26 #include <gtkmm/table.h>
27 #include <gtkmm2ext/window_title.h>
28
29 #include "pbd/error.h"
30 #include "pbd/convert.h"
31 #include "gtkmm2ext/utils.h"
32 #include "ardour/profile.h"
33 #include "ardour/template_utils.h"
34 #include "ardour/route_group.h"
35 #include "ardour/session.h"
36
37 #include "utils.h"
38 #include "add_route_dialog.h"
39 #include "route_group_dialog.h"
40 #include "i18n.h"
41
42 using namespace Gtk;
43 using namespace Gtkmm2ext;
44 using namespace sigc;
45 using namespace std;
46 using namespace PBD;
47 using namespace ARDOUR;
48
49 static const char* track_mode_names[] = {
50         N_("Normal"),
51         N_("Non Layered"),
52         N_("Tape"),
53         0
54 };
55
56 AddRouteDialog::AddRouteDialog (Session & s)
57         : ArdourDialog (X_("add route dialog"))
58         , _session (s)
59         , routes_adjustment (1, 1, 128, 1, 4)
60         , routes_spinner (routes_adjustment)
61         , track_mode_label (_("Track mode:"))
62 {
63         if (track_mode_strings.empty()) {
64                 track_mode_strings = I18N (track_mode_names);
65
66                 if (ARDOUR::Profile->get_sae()) {
67                         /* remove all but the first track mode (Normal) */
68
69                         while (track_mode_strings.size() > 1) {
70                                 track_mode_strings.pop_back();
71                         }
72                 }
73         }
74         
75         set_name ("AddRouteDialog");
76         set_position (Gtk::WIN_POS_MOUSE);
77         set_modal (true);
78         set_skip_taskbar_hint (true);
79         set_resizable (false);
80
81         WindowTitle title(Glib::get_application_name());
82         title += _("Add Route");
83         set_title(title.get_string());
84
85         name_template_entry.set_name (X_("AddRouteDialogNameTemplateEntry"));
86         routes_spinner.set_name (X_("AddRouteDialogSpinner"));
87         channel_combo.set_name (X_("ChannelCountSelector"));
88         track_mode_combo.set_name (X_("ChannelCountSelector"));
89
90         refill_channel_setups ();
91         refill_route_groups ();
92         set_popdown_strings (track_mode_combo, track_mode_strings, true);
93
94         channel_combo.set_active_text (channel_combo_strings.front());
95         track_mode_combo.set_active_text (track_mode_strings.front());
96
97         track_bus_combo.append_text (_("tracks"));
98         track_bus_combo.append_text (_("busses"));
99         track_bus_combo.set_active (0);
100
101         VBox* vbox = manage (new VBox);
102         Gtk::Label* l;
103
104         get_vbox()->set_spacing (4);
105
106         vbox->set_spacing (18);
107         vbox->set_border_width (5);
108
109         HBox *type_hbox = manage (new HBox);
110         type_hbox->set_spacing (6);
111         
112         /* track/bus choice */
113
114         type_hbox->pack_start (*manage (new Label (_("Add:"))));
115         type_hbox->pack_start (routes_spinner);
116         type_hbox->pack_start (track_bus_combo);
117         
118         vbox->pack_start (*type_hbox, false, true);
119
120         VBox* options_box = manage (new VBox);
121         Table *table2 = manage (new Table (3, 3, false));
122
123         options_box->set_spacing (6);
124         table2->set_row_spacings (6);
125         table2->set_col_spacing (1, 6);
126
127         l = manage (new Label (_("<b>Options</b>"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
128         l->set_use_markup ();
129         options_box->pack_start (*l, false, true);
130
131         l = manage (new Label ("", Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
132         l->set_padding (8, 0);
133         table2->attach (*l, 0, 1, 0, 3, Gtk::FILL, Gtk::FILL, 0, 0);
134
135         /* Route configuration */
136
137         l = manage (new Label (_("Configuration:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
138         table2->attach (*l, 1, 2, 0, 1, Gtk::FILL, Gtk::EXPAND, 0, 0);
139         table2->attach (channel_combo, 2, 3, 0, 1, Gtk::FILL, Gtk::EXPAND & Gtk::FILL, 0, 0);
140
141         if (!ARDOUR::Profile->get_sae ()) {
142
143                 /* Track mode */
144
145                 track_mode_label.set_alignment (Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER);
146                 table2->attach (track_mode_label, 1, 2, 1, 2, Gtk::FILL, Gtk::EXPAND, 0, 0);
147                 table2->attach (track_mode_combo, 2, 3, 1, 2, Gtk::FILL, Gtk::EXPAND & Gtk::FILL, 0, 0);
148
149         }
150
151         /* Group choise */
152
153         l = manage (new Label (_("Group:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
154         table2->attach (*l, 1, 2, 2, 3, Gtk::FILL, Gtk::EXPAND, 0, 0);
155         table2->attach (route_group_combo, 2, 3, 2, 3, Gtk::FILL, Gtk::EXPAND & Gtk::FILL, 0, 0);
156         
157         options_box->pack_start (*table2, false, true);
158         vbox->pack_start (*options_box, false, true);
159
160         get_vbox()->pack_start (*vbox, false, false);
161
162         track_bus_combo.signal_changed().connect (mem_fun (*this, &AddRouteDialog::track_type_chosen));
163         channel_combo.set_row_separator_func (mem_fun (*this, &AddRouteDialog::channel_separator));
164         route_group_combo.set_row_separator_func (mem_fun (*this, &AddRouteDialog::route_separator));
165         route_group_combo.signal_changed ().connect (mem_fun (*this, &AddRouteDialog::group_changed));
166
167         show_all_children ();
168
169         /* track template info will be managed whenever
170            this dialog is shown, via ::on_show()
171         */
172
173         add_button (Stock::CANCEL, RESPONSE_CANCEL);
174         add_button (Stock::ADD, RESPONSE_ACCEPT);
175
176         track_type_chosen ();
177 }
178
179 AddRouteDialog::~AddRouteDialog ()
180 {
181 }
182
183 void
184 AddRouteDialog::track_type_chosen ()
185 {
186         track_mode_label.set_sensitive (track ());
187         track_mode_combo.set_sensitive (track ());
188 }
189
190 bool
191 AddRouteDialog::track ()
192 {
193         return track_bus_combo.get_active_row_number () == 0;
194 }
195
196 ARDOUR::DataType
197 AddRouteDialog::type ()
198 {
199         // FIXME: ew
200         
201         const string str = channel_combo.get_active_text();
202         if (str == _("MIDI")) {
203                 return ARDOUR::DataType::MIDI;
204         } else {
205                 return ARDOUR::DataType::AUDIO;
206         }
207 }
208
209 string
210 AddRouteDialog::name_template ()
211 {
212         return name_template_entry.get_text ();
213 }
214
215 int
216 AddRouteDialog::count ()
217 {
218         return (int) floor (routes_adjustment.get_value ());
219 }
220
221 ARDOUR::TrackMode
222 AddRouteDialog::mode ()
223 {
224         if (ARDOUR::Profile->get_sae()) {
225                 return ARDOUR::Normal;
226         }
227
228         Glib::ustring str = track_mode_combo.get_active_text();
229         if (str == _("Normal")) {
230                 return ARDOUR::Normal;
231         } else if (str == _("Non Layered")){
232                 return ARDOUR::NonLayered;
233         } else if (str == _("Tape")) {
234                 return ARDOUR::Destructive;
235         } else {
236                 fatal << string_compose (X_("programming error: unknown track mode in add route dialog combo = %1"), str)
237                       << endmsg;
238                 /*NOTREACHED*/
239         }
240         /* keep gcc happy */
241         return ARDOUR::Normal;
242 }
243
244 int
245 AddRouteDialog::channels ()
246 {
247         string str = channel_combo.get_active_text();
248         
249         for (ChannelSetups::iterator i = channel_setups.begin(); i != channel_setups.end(); ++i) {
250                 if (str == (*i).name) {
251                         return (*i).channels;
252                 }
253         }
254
255         return 0;
256 }
257
258 string
259 AddRouteDialog::track_template ()
260 {
261         string str = channel_combo.get_active_text();
262
263         for (ChannelSetups::iterator i = channel_setups.begin(); i != channel_setups.end(); ++i) {
264                 if (str == (*i).name) {
265                         return (*i).template_path;
266                 }
267         }
268
269         return string();
270 }
271
272 void
273 AddRouteDialog::on_show ()
274 {
275         refill_channel_setups ();
276         refill_route_groups ();
277         
278         Dialog::on_show ();
279 }
280
281 void
282 AddRouteDialog::refill_channel_setups ()
283 {
284         ChannelSetup chn;
285         
286         route_templates.clear ();
287         channel_combo_strings.clear ();
288         channel_setups.clear ();
289
290         chn.name = _("Mono");
291         chn.channels = 1;
292         channel_setups.push_back (chn);
293
294         chn.name = _("Stereo");
295         chn.channels = 2;
296         channel_setups.push_back (chn);
297
298         chn.name = "separator";
299         channel_setups.push_back (chn);
300
301         chn.name = X_("MIDI");
302         chn.channels = 0;
303         channel_setups.push_back (chn);
304
305         chn.name = "separator";
306         channel_setups.push_back (chn);
307
308         ARDOUR::find_route_templates (route_templates);
309
310         if (!ARDOUR::Profile->get_sae()) {
311                 if (!route_templates.empty()) {
312                         vector<string> v;
313                         for (vector<TemplateInfo>::iterator x = route_templates.begin(); x != route_templates.end(); ++x) {
314                                 chn.name = x->name;
315                                 chn.channels = 0;
316                                 chn.template_path = x->path;
317                                 channel_setups.push_back (chn);
318                         }
319                 } 
320
321                 /* clear template path for the rest */
322                 
323                 chn.template_path = "";
324
325                 chn.name = _("3 Channel");
326                 chn.channels = 3;
327                 channel_setups.push_back (chn);
328
329                 chn.name = _("4 Channel");
330                 chn.channels = 4;
331                 channel_setups.push_back (chn);
332
333                 chn.name = _("5 Channel");
334                 chn.channels = 5;
335                 channel_setups.push_back (chn);
336
337                 chn.name = _("6 Channel");
338                 chn.channels = 6;
339                 channel_setups.push_back (chn);
340
341                 chn.name = _("8 Channel");
342                 chn.channels = 8;
343                 channel_setups.push_back (chn);
344
345                 chn.name = _("12 Channel");
346                 chn.channels = 12;
347                 channel_setups.push_back (chn);
348
349                 chn.name = X_("Custom");
350                 chn.channels = 0;
351                 channel_setups.push_back (chn);
352         }
353
354         for (ChannelSetups::iterator i = channel_setups.begin(); i != channel_setups.end(); ++i) {
355                 channel_combo_strings.push_back ((*i).name);
356         }
357
358         set_popdown_strings (channel_combo, channel_combo_strings, true);
359         channel_combo.set_active_text (channel_combo_strings.front());
360 }
361
362 void
363 AddRouteDialog::add_route_group (RouteGroup* g)
364 {
365         route_group_combo.insert_text (3, g->name ());
366 }
367
368 RouteGroup*
369 AddRouteDialog::route_group ()
370 {
371         if (route_group_combo.get_active_row_number () == 2) {
372                 return 0;
373         }
374
375         return _session.route_group_by_name (route_group_combo.get_active_text());
376 }
377
378 void
379 AddRouteDialog::refill_route_groups ()
380 {
381         route_group_combo.clear ();
382         route_group_combo.append_text (_("New group..."));
383
384         route_group_combo.append_text ("separator");
385
386         route_group_combo.append_text (_("No group"));
387
388         _session.foreach_route_group (mem_fun (*this, &AddRouteDialog::add_route_group));
389         
390         route_group_combo.set_active (2);
391 }
392
393 void
394 AddRouteDialog::group_changed ()
395 {
396         if (route_group_combo.get_active_text () == _("New group...")) {
397                 RouteGroup* g = new RouteGroup (_session, "", RouteGroup::Active);
398         
399                 RouteGroupDialog d (g, Gtk::Stock::NEW);
400                 int const r = d.do_run ();
401
402                 if (r == Gtk::RESPONSE_OK) {
403                         _session.add_route_group (g);
404                         add_route_group (g);
405                         route_group_combo.set_active (3);
406                 } else {
407                         delete g;
408
409                         route_group_combo.set_active (2);
410                 }
411         }
412 }
413
414 bool
415 AddRouteDialog::channel_separator (const Glib::RefPtr<Gtk::TreeModel> &, const Gtk::TreeModel::iterator &i)
416 {
417         channel_combo.set_active (i);
418
419         return channel_combo.get_active_text () == "separator";
420 }
421
422 bool
423 AddRouteDialog::route_separator (const Glib::RefPtr<Gtk::TreeModel> &, const Gtk::TreeModel::iterator &i)
424 {
425         route_group_combo.set_active (i);
426
427         return route_group_combo.get_active_text () == "separator";
428 }
429