Strip trailing whitespace and fix other whitespace errors (e.g. space/tab mixing...
[ardour.git] / gtk2_ardour / startup.cc
1 #include <fstream>
2 #include <algorithm>
3
4 #include <gtkmm/main.h>
5 #include <gtkmm/filechooser.h>
6
7 #include "pbd/failed_constructor.h"
8 #include "pbd/file_utils.h"
9 #include "pbd/filesystem.h"
10 #include "pbd/replace_all.h"
11
12 #include "ardour/filesystem_paths.h"
13 #include "ardour/recent_sessions.h"
14 #include "ardour/session.h"
15 #include "ardour/session_state_utils.h"
16 #include "ardour/template_utils.h"
17
18 #include "startup.h"
19 #include "opts.h"
20 #include "engine_dialog.h"
21 #include "i18n.h"
22
23 using namespace std;
24 using namespace Gtk;
25 using namespace Gdk;
26 using namespace Glib;
27 using namespace PBD;
28 using namespace ARDOUR;
29
30 ArdourStartup* ArdourStartup::the_startup = 0;
31
32 static string poor_mans_glob (string path)
33 {
34         string copy = path;
35         replace_all (copy, "~", Glib::get_home_dir());
36         return copy;
37 }
38
39
40 ArdourStartup::ArdourStartup ()
41         : applying (false)
42         , ic_new_session_button (_("Open a new session"))
43         , ic_existing_session_button (_("Open an existing session"))
44         , monitor_via_hardware_button (_("Use an external mixer or the hardware mixer of your audio interface.\n\
45 Ardour will play NO role in monitoring"))
46         , monitor_via_ardour_button (_("Ask Ardour to playback material as it is being recorded"))
47         , new_folder_chooser (FILE_CHOOSER_ACTION_SELECT_FOLDER)
48         , more_new_session_options_button (_("I'd like more options for this session"))
49         , _output_limit_count_adj (1, 0, 100, 1, 10, 0)
50         , _input_limit_count_adj (1, 0, 100, 1, 10, 0)
51         , _control_bus_channel_count_adj (2, 0, 100, 1, 10, 0)
52         , _master_bus_channel_count_adj (2, 0, 100, 1, 10, 0)
53
54 {
55         audio_page_index = -1;
56         initial_choice_index = -1;
57         new_user_page_index = -1;
58         default_folder_page_index = -1;
59         monitoring_page_index = -1;
60         session_page_index = -1;
61         final_page_index = -1;
62         session_options_page_index = -1;
63         new_only = false;
64
65         engine_dialog = 0;
66         config_modified = false;
67         default_dir_chooser = 0;
68
69         use_template_button.set_group (session_template_group);
70         use_session_as_template_button.set_group (session_template_group);
71
72         set_keep_above (true);
73         set_resizable (false);
74         set_position (WIN_POS_CENTER);
75         set_border_width (12);
76
77         sys::path icon_file;
78
79         if (!find_file_in_search_path (ardour_search_path() + system_data_search_path().add_subdirectory_to_paths("icons"), "ardour_icon_48px.png", icon_file)) {
80                 throw failed_constructor();
81         }
82
83         try {
84                 icon_pixbuf = Gdk::Pixbuf::create_from_file (icon_file.to_string());
85         }
86
87         catch (...) {
88                 throw failed_constructor();
89         }
90
91         sys::path been_here_before = user_config_directory();
92         been_here_before /= ".a3"; // XXXX use more specific version so we can catch upgrades
93         new_user = !exists (been_here_before);
94
95         bool need_audio_setup = !EngineControl::engine_running();
96
97         if (new_user) {
98                 /* "touch" the file */
99                 ofstream fout (been_here_before.to_string().c_str());
100                 setup_new_user_page ();
101                 setup_first_time_config_page ();
102                 setup_monitoring_choice_page ();
103
104                 if (need_audio_setup) {
105                         setup_audio_page ();
106                 }
107
108         } else {
109
110                 if (need_audio_setup) {
111                         setup_audio_page ();
112                 }
113
114                 setup_initial_choice_page ();
115         }
116
117         setup_session_page ();
118         setup_more_options_page ();
119
120         if (new_user) {
121                 setup_final_page ();
122         }
123
124         the_startup = this;
125 }
126
127 ArdourStartup::~ArdourStartup ()
128 {
129 }
130
131 void
132 ArdourStartup::set_new_only (bool yn)
133 {
134         new_only = yn;
135
136         if (new_only) {
137                 ic_vbox.hide ();
138         } else {
139                 ic_vbox.show ();
140         }
141 }
142
143 bool
144 ArdourStartup::use_session_template ()
145 {
146         if (use_template_button.get_active()) {
147                 return template_chooser.get_active_row_number() > 0;
148         } else {
149                 return !session_template_chooser.get_filename().empty();
150         }
151 }
152
153 Glib::ustring
154 ArdourStartup::session_template_name ()
155 {
156         if (ic_existing_session_button.get_active()) {
157                 return ustring();
158         }
159
160         if (use_template_button.get_active()) {
161                 TreeModel::iterator iter = template_chooser.get_active ();
162                 TreeModel::Row row = (*iter);
163                 string s = row[session_template_columns.path];
164                 return s;
165         } else {
166                 return session_template_chooser.get_filename();
167
168         }
169 }
170
171 Glib::ustring
172 ArdourStartup::session_name (bool& should_be_new)
173 {
174         if (ic_new_session_button.get_active()) {
175                 should_be_new = true;
176                 return new_name_entry.get_text ();
177         } else {
178                 should_be_new = false;
179
180                 TreeIter iter = recent_session_display.get_selection()->get_selected();
181
182                 if (iter) {
183                         return (*iter)[recent_session_columns.visible_name];
184                 }
185
186                 return "";
187         }
188 }
189
190 Glib::ustring
191 ArdourStartup::session_folder ()
192 {
193         if (ic_new_session_button.get_active()) {
194                 Glib::ustring legal_session_folder_name = legalize_for_path (new_name_entry.get_text());
195                 return Glib::build_filename (new_folder_chooser.get_current_folder(), legal_session_folder_name);
196         } else {
197                 TreeIter iter = recent_session_display.get_selection()->get_selected();
198
199                 if (iter) {
200                         return (*iter)[recent_session_columns.fullpath];
201                 }
202                 return "";
203         }
204 }
205
206 void
207 ArdourStartup::setup_audio_page ()
208 {
209         engine_dialog = manage (new EngineControl);
210
211         engine_dialog->set_border_width (12);
212
213         engine_dialog->show_all ();
214
215         audio_page_index = append_page (*engine_dialog);
216         set_page_type (*engine_dialog, ASSISTANT_PAGE_CONTENT);
217         set_page_title (*engine_dialog, _("Audio Setup"));
218
219         /* the default parameters should work, so the page is potentially complete */
220
221         set_page_complete (*engine_dialog, true);
222 }
223
224 void
225 ArdourStartup::setup_new_user_page ()
226 {
227         Label* foomatic = manage (new Label);
228
229         foomatic->set_markup (_("\
230 <span size=\"larger\">Ardour is a digital audio workstation. You can use it to\n\
231 record, edit and mix multi-track audio. You can produce your\n\
232 own CDs, mix video soundtracks, or just experiment with new\n\
233 ideas about music and sound.\n\
234 \n\
235 There are a few things that need to configured before you start\n\
236 using the program.</span>\
237 "));
238
239         HBox* hbox = manage (new HBox);
240         HBox* vbox = manage (new HBox);
241
242         vbox->set_border_width (24);
243
244         hbox->pack_start (*foomatic, true, true);
245         vbox->pack_start (*hbox, true, true);
246
247         foomatic->show ();
248         hbox->show ();
249         vbox->show ();
250
251         new_user_page_index = append_page (*vbox);
252         set_page_type (*vbox, ASSISTANT_PAGE_INTRO);
253         set_page_title (*vbox, _("Welcome to Ardour"));
254         set_page_header_image (*vbox, icon_pixbuf);
255         set_page_complete (*vbox, true);
256 }
257
258 void
259 ArdourStartup::default_dir_changed ()
260 {
261         Config->set_default_session_parent_dir (default_dir_chooser->get_current_folder());
262         config_modified = true;
263 }
264
265 void
266 ArdourStartup::setup_first_time_config_page ()
267 {
268         default_dir_chooser = manage (new FileChooserButton (_("Default folder for Ardour sessions"),
269                                                              FILE_CHOOSER_ACTION_SELECT_FOLDER));
270         Gtk::Label* txt = manage (new Label);
271         HBox* hbox = manage (new HBox);
272         VBox* vbox = manage (new VBox);
273
274         txt->set_markup (_("\
275 Each project that you work on with Ardour has its own folder.\n\
276 These can require a lot of disk space if you are recording audio.\n\
277 \n\
278 Where would you like new Ardour sessions to be stored by default?\n\n\
279 <i>(You can put new sessions anywhere, this is just a default)</i>"));
280         txt->set_alignment (0.0, 0.0);
281
282         vbox->set_spacing (18);
283         vbox->set_border_width (24);
284
285         hbox->pack_start (*default_dir_chooser, false, true, 8);
286         vbox->pack_start (*txt, false, false);
287         vbox->pack_start (*hbox, false, true);
288
289         default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
290         default_dir_chooser->signal_current_folder_changed().connect (mem_fun (*this, &ArdourStartup::default_dir_changed));
291         default_dir_chooser->show ();
292
293         vbox->show_all ();
294
295         default_folder_page_index = append_page (*vbox);
296         set_page_title (*vbox, _("Default folder for new sessions"));
297         set_page_header_image (*vbox, icon_pixbuf);
298         set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
299
300         /* user can just skip all these settings if they want to */
301
302         set_page_complete (*vbox, true);
303 }
304
305 void
306 ArdourStartup::setup_monitoring_choice_page ()
307 {
308         mon_vbox.set_spacing (18);
309         mon_vbox.set_border_width (24);
310
311         HBox* hbox = manage (new HBox);
312         VBox* vbox = manage (new VBox);
313         RadioButton::Group g (monitor_via_hardware_button.get_group());
314         monitor_via_ardour_button.set_group (g);
315
316         monitor_label.set_markup("\
317 While recording instruments or vocals, you probably want to listen to the\n\
318 signal as well as record it. This is called \"monitoring\". There are\n\
319 different ways to do this depending on the equipment you have and the\n\
320 configuration of that equipment. The two most common are presented here.\n\
321 Please choose whichever one is right for your setup.\n\n\
322 <i>(You can change this preference at any time, via the Options menu)</i>");
323         monitor_label.set_alignment (0.0, 0.0);
324
325         vbox->set_spacing (6);
326
327         vbox->pack_start (monitor_via_hardware_button, false, true);
328         vbox->pack_start (monitor_via_ardour_button, false, true);
329         hbox->pack_start (*vbox, true, true, 8);
330         mon_vbox.pack_start (monitor_label, false, false);
331         mon_vbox.pack_start (*hbox, false, false);
332
333         mon_vbox.show_all ();
334
335         monitoring_page_index = append_page (mon_vbox);
336         set_page_title (mon_vbox, _("Monitoring Choices"));
337         set_page_header_image (mon_vbox, icon_pixbuf);
338
339         /* user could just click on "Forward" if default
340          * choice is correct.
341          */
342
343         set_page_complete (mon_vbox, true);
344 }
345
346 void
347 ArdourStartup::setup_initial_choice_page ()
348 {
349         ic_vbox.set_spacing (6);
350         ic_vbox.set_border_width (24);
351
352         RadioButton::Group g (ic_new_session_button.get_group());
353         ic_existing_session_button.set_group (g);
354
355         HBox* centering_hbox = manage (new HBox);
356         VBox* centering_vbox = manage (new VBox);
357
358         centering_vbox->set_spacing (6);
359
360         centering_vbox->pack_start (ic_new_session_button, false, true);
361         centering_vbox->pack_start (ic_existing_session_button, false, true);
362         ic_new_session_button.signal_button_press_event().connect(mem_fun(*this, &ArdourStartup::initial_choice_activated), false);
363         ic_existing_session_button.signal_button_press_event().connect(mem_fun(*this, &ArdourStartup::initial_choice_activated), false);
364
365         centering_hbox->pack_start (*centering_vbox, true, true);
366
367         ic_vbox.pack_start (*centering_hbox, true, true);
368
369         ic_vbox.show_all ();
370
371         initial_choice_index = append_page (ic_vbox);
372         set_page_title (ic_vbox, _("What would you like to do ?"));
373         set_page_header_image (ic_vbox, icon_pixbuf);
374
375         /* user could just click on "Forward" if default
376          * choice is correct.
377          */
378
379         set_page_complete (ic_vbox, true);
380 }
381
382 bool
383 ArdourStartup::initial_choice_activated(GdkEventButton *event)
384 {
385   if (event && event->type == GDK_2BUTTON_PRESS && session_page_index != -1)
386     {
387       set_current_page(session_page_index);
388       return true;
389     }
390   else
391     return false;
392 }
393
394 void
395 ArdourStartup::setup_session_page ()
396 {
397         session_vbox.set_border_width (24);
398
399         session_vbox.pack_start (session_hbox, true, true);
400         session_vbox.show_all ();
401
402         session_page_index = append_page (session_vbox);
403         /* initial setting */
404         set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
405 }
406
407 void
408 ArdourStartup::setup_final_page ()
409 {
410         final_page.set_text ("Ardour is ready for use");
411         final_page.show ();
412         final_page_index = append_page (final_page);
413         set_page_complete (final_page, true);
414         set_page_header_image (final_page, icon_pixbuf);
415         set_page_type (final_page, ASSISTANT_PAGE_CONFIRM);
416 }
417
418 void
419 ArdourStartup::on_cancel ()
420 {
421         exit (1);
422 }
423
424 void
425 ArdourStartup::on_close ()
426 {
427         if (!applying) {
428                 exit (1);
429         }
430 }
431
432 void
433 ArdourStartup::on_apply ()
434 {
435         applying = true;
436
437         // XXX do stuff and then ....
438
439         if (engine_dialog) {
440                 engine_dialog->setup_engine ();
441         }
442
443         if (config_modified) {
444
445                 if (default_dir_chooser) {
446                         Config->set_default_session_parent_dir (default_dir_chooser->get_current_folder());
447                 }
448
449                 if (monitor_via_hardware_button.get_active()) {
450                         Config->set_monitoring_model (ExternalMonitoring);
451                 } else if (monitor_via_ardour_button.get_active()) {
452                         Config->set_monitoring_model (SoftwareMonitoring);
453                 }
454
455                 Config->save_state ();
456         }
457
458         gtk_main_quit ();
459 }
460
461 void
462 ArdourStartup::on_prepare (Gtk::Widget* page)
463 {
464         if (page == &session_vbox) {
465
466                 if (ic_new_session_button.get_active()) {
467                         /* new session requested */
468                         setup_new_session_page ();
469                 } else {
470                         /* existing session requested */
471                         setup_existing_session_page ();
472                 }
473         }
474 }
475
476 void
477 ArdourStartup::populate_session_templates ()
478 {
479         vector<TemplateInfo> templates;
480
481         find_session_templates (templates);
482
483         template_model->clear ();
484
485         for (vector<TemplateInfo>::iterator x = templates.begin(); x != templates.end(); ++x) {
486                 TreeModel::Row row;
487
488                 row = *(template_model->append ());
489
490                 row[session_template_columns.name] = (*x).name;
491                 row[session_template_columns.path] = (*x).path;
492         }
493 }
494
495 void
496 ArdourStartup::setup_new_session_page ()
497 {
498         if (!session_hbox.get_children().empty()) {
499                 session_hbox.remove (**session_hbox.get_children().begin());
500         }
501
502         session_new_vbox.set_spacing (18);
503
504         if (session_new_vbox.get_children().empty()) {
505                 VBox *vbox1 = manage (new VBox);
506                 HBox* hbox1 = manage (new HBox);
507                 Label* label1 = manage (new Label);
508
509                 vbox1->set_spacing (6);
510
511                 hbox1->set_spacing (6);
512                 hbox1->pack_start (*label1, false, false);
513                 hbox1->pack_start (new_name_entry, true, true);
514
515                 label1->set_text (_("Session name:"));
516
517
518                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
519                         new_name_entry.set_text  (Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name));
520                         /* name provided - they can move right along */
521                         set_page_complete (session_vbox, true);
522                 }
523
524                 new_name_entry.signal_changed().connect (mem_fun (*this, &ArdourStartup::new_name_changed));
525                 new_name_entry.signal_activate().connect (mem_fun (*this, &ArdourStartup::move_along_now));
526
527                 vbox1->pack_start (*hbox1, true, true);
528
529                 /* --- */
530
531                 HBox* hbox2 = manage (new HBox);
532                 Label* label2 = manage (new Label);
533
534                 hbox2->set_spacing (6);
535                 hbox2->pack_start (*label2, false, false);
536                 hbox2->pack_start (new_folder_chooser, true, true);
537
538                 label2->set_text (_("Create session folder in:"));
539
540                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
541                         new_folder_chooser.set_current_folder (poor_mans_glob (Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name)));
542                 } else {
543                         new_folder_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
544                 }
545                 new_folder_chooser.set_title (_("Select folder for session"));
546
547                 vbox1->pack_start (*hbox2, false, false);
548
549                 session_new_vbox.pack_start (*vbox1, false, false);
550
551                 /* --- */
552
553                 VBox *vbox2 = manage (new VBox);
554                 HBox* hbox3 = manage (new HBox);
555                 Label* label3 = manage (new Label);
556                 template_model = ListStore::create (session_template_columns);
557                 populate_session_templates ();
558
559                 vbox2->set_spacing (6);
560
561                 label3->set_markup (_("<b>Options</b>"));
562                 label3->set_alignment (0.0, 0.0);
563
564                 vbox2->pack_start (*label3, false, true);
565
566                 VBox *vbox3 = manage (new VBox);
567
568                 vbox3->set_spacing (6);
569
570                 if (!template_model->children().empty()) {
571
572                         HBox* hbox4a = manage (new HBox);
573                         use_template_button.set_label (_("Use this template"));
574
575                         TreeModel::Row row = *template_model->prepend ();
576                         row[session_template_columns.name] = (_("no template"));
577                         row[session_template_columns.path] = string();
578
579                         hbox4a->set_spacing (6);
580                         hbox4a->pack_start (use_template_button, false, false);
581                         hbox4a->pack_start (template_chooser, true, true);
582
583                         template_chooser.set_model (template_model);
584
585                         Gtk::CellRendererText* text_renderer = Gtk::manage (new Gtk::CellRendererText);
586                         text_renderer->property_editable() = false;
587
588                         template_chooser.pack_start (*text_renderer);
589                         template_chooser.add_attribute (text_renderer->property_text(), session_template_columns.name);
590                         template_chooser.set_active (0);
591
592                         use_template_button.show();
593                         template_chooser.show ();
594
595                         vbox3->pack_start (*hbox4a, false, false);
596                 }
597
598                 /* --- */
599
600                 if (!new_user) {
601                         session_template_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
602
603                         HBox* hbox4b = manage (new HBox);
604                         use_session_as_template_button.set_label (_("Use an existing session as a template:"));
605
606                         hbox4b->set_spacing (6);
607                         hbox4b->pack_start (use_session_as_template_button, false, false);
608                         hbox4b->pack_start (session_template_chooser, true, true);
609
610                         use_session_as_template_button.show ();
611                         session_template_chooser.show ();
612
613                         Gtk::FileFilter* template_filter = manage (new (Gtk::FileFilter));
614                         template_filter->add_pattern(X_("*.template"));
615                         session_template_chooser.set_filter (*template_filter);
616                         session_template_chooser.set_title (_("Select template"));
617
618                         vbox3->pack_start (*hbox4b, false, false);
619                 }
620
621                 /* --- */
622
623                 HBox* hbox5 = manage (new HBox);
624
625                 hbox5->set_spacing (6);
626                 hbox5->pack_start (more_new_session_options_button, false, false);
627
628                 more_new_session_options_button.show ();
629                 more_new_session_options_button.signal_clicked().connect (mem_fun (*this, &ArdourStartup::more_new_session_options_button_clicked));
630
631                 vbox3->pack_start (*hbox5, false, false);
632                 hbox3->pack_start (*vbox3, true, true, 8);
633                 vbox2->pack_start (*hbox3, false, false);
634
635                 /* --- */
636
637                 session_new_vbox.pack_start (*vbox2, false, false);
638         }
639
640         session_new_vbox.show_all ();
641         session_hbox.pack_start (session_new_vbox, true, true);
642         set_page_title (session_vbox, _("New Session"));
643         set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
644
645         new_name_entry.grab_focus ();
646 }
647
648 void
649 ArdourStartup::new_name_changed ()
650 {
651         if (!new_name_entry.get_text().empty()) {
652                 set_page_complete (session_vbox, true);
653         } else {
654                 set_page_complete (session_vbox, false);
655         }
656 }
657
658 void
659 ArdourStartup::redisplay_recent_sessions ()
660 {
661         std::vector<sys::path> session_directories;
662         RecentSessionsSorter cmp;
663
664         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
665         recent_session_model->clear ();
666
667         ARDOUR::RecentSessions rs;
668         ARDOUR::read_recent_sessions (rs);
669
670         if (rs.empty()) {
671                 recent_session_display.set_model (recent_session_model);
672                 return;
673         }
674         //
675         // sort them alphabetically
676         sort (rs.begin(), rs.end(), cmp);
677
678         for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
679                 session_directories.push_back ((*i).second);
680         }
681
682         for (vector<sys::path>::const_iterator i = session_directories.begin(); i != session_directories.end(); ++i)
683         {
684                 std::vector<sys::path> state_file_paths;
685
686                 // now get available states for this session
687
688                 get_state_files_in_directory (*i, state_file_paths);
689
690                 vector<string*>* states;
691                 vector<const gchar*> item;
692                 string fullpath = (*i).to_string();
693
694                 /* remove any trailing / */
695
696                 if (fullpath[fullpath.length()-1] == '/') {
697                         fullpath = fullpath.substr (0, fullpath.length()-1);
698                 }
699
700                 /* check whether session still exists */
701                 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
702                         /* session doesn't exist */
703                         continue;
704                 }
705
706                 /* now get available states for this session */
707
708                 if ((states = Session::possible_states (fullpath)) == 0) {
709                         /* no state file? */
710                         continue;
711                 }
712
713                 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
714
715                 Gtk::TreeModel::Row row = *(recent_session_model->append());
716
717                 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
718                 row[recent_session_columns.fullpath] = fullpath;
719
720                 if (state_file_names.size() > 1) {
721
722                         // add the children
723
724                         for (std::vector<std::string>::iterator i2 = state_file_names.begin();
725                                         i2 != state_file_names.end(); ++i2)
726                         {
727
728                                 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
729
730                                 child_row[recent_session_columns.visible_name] = *i2;
731                                 child_row[recent_session_columns.fullpath] = fullpath;
732                         }
733                 }
734         }
735
736         recent_session_display.set_model (recent_session_model);
737 }
738
739 void
740 ArdourStartup::recent_session_row_selected ()
741 {
742         if (recent_session_display.get_selection()->count_selected_rows() > 0) {
743                 set_page_complete (session_vbox, true);
744         } else {
745                 set_page_complete (session_vbox, false);
746         }
747 }
748
749 void
750 ArdourStartup::setup_existing_session_page ()
751 {
752         if (!session_hbox.get_children().empty()) {
753                 session_hbox.remove (**session_hbox.get_children().begin());
754         }
755
756         if (recent_scroller.get_children().empty()) {
757
758                 recent_session_model = TreeStore::create (recent_session_columns);
759                 recent_session_display.set_model (recent_session_model);
760                 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
761                 recent_session_display.set_headers_visible (false);
762                 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
763
764                 recent_session_display.get_selection()->signal_changed().connect (mem_fun (*this, &ArdourStartup::recent_session_row_selected));
765
766                 recent_scroller.add (recent_session_display);
767                 recent_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
768                 recent_scroller.set_shadow_type (Gtk::SHADOW_IN);
769
770                 recent_session_display.show();
771         }
772
773         recent_scroller.show();
774         redisplay_recent_sessions ();
775         recent_session_display.signal_row_activated().connect (mem_fun (*this, &ArdourStartup::recent_row_activated));
776
777         session_hbox.pack_start (recent_scroller, true, true);
778         set_page_title (session_vbox, _("Select a session"));
779         set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
780 }
781
782 void
783 ArdourStartup::more_new_session_options_button_clicked ()
784 {
785         if (more_new_session_options_button.get_active()) {
786                 more_options_vbox.show_all ();
787                 set_page_type (more_options_vbox, ASSISTANT_PAGE_CONFIRM);
788                 set_page_type (session_vbox, ASSISTANT_PAGE_CONTENT);
789         } else {
790                 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
791                 more_options_vbox.hide ();
792         }
793 }
794
795 void
796 ArdourStartup::setup_more_options_page ()
797 {
798         more_options_vbox.set_border_width (24);
799
800         _output_limit_count.set_adjustment (_output_limit_count_adj);
801         _input_limit_count.set_adjustment (_input_limit_count_adj);
802         _control_bus_channel_count.set_adjustment (_control_bus_channel_count_adj);
803         _master_bus_channel_count.set_adjustment (_master_bus_channel_count_adj);
804
805         chan_count_label_1.set_text (_("channels"));
806         chan_count_label_2.set_text (_("channels"));
807         chan_count_label_3.set_text (_("channels"));
808         chan_count_label_4.set_text (_("channels"));
809
810         chan_count_label_1.set_alignment(0,0.5);
811         chan_count_label_1.set_padding(0,0);
812         chan_count_label_1.set_line_wrap(false);
813
814         chan_count_label_2.set_alignment(0,0.5);
815         chan_count_label_2.set_padding(0,0);
816         chan_count_label_2.set_line_wrap(false);
817
818         chan_count_label_3.set_alignment(0,0.5);
819         chan_count_label_3.set_padding(0,0);
820         chan_count_label_3.set_line_wrap(false);
821
822         chan_count_label_4.set_alignment(0,0.5);
823         chan_count_label_4.set_padding(0,0);
824         chan_count_label_4.set_line_wrap(false);
825
826         bus_label.set_markup (_("<b>Busses</b>"));
827         input_label.set_markup (_("<b>Inputs</b>"));
828         output_label.set_markup (_("<b>Outputs</b>"));
829
830         _create_control_bus.set_label (_("Create monitor bus"));
831         _create_control_bus.set_flags(Gtk::CAN_FOCUS);
832         _create_control_bus.set_relief(Gtk::RELIEF_NORMAL);
833         _create_control_bus.set_mode(true);
834         _create_control_bus.set_active(false);
835         _create_control_bus.set_border_width(0);
836
837         _control_bus_channel_count.set_flags(Gtk::CAN_FOCUS);
838         _control_bus_channel_count.set_update_policy(Gtk::UPDATE_ALWAYS);
839         _control_bus_channel_count.set_numeric(true);
840         _control_bus_channel_count.set_digits(0);
841         _control_bus_channel_count.set_wrap(false);
842         _control_bus_channel_count.set_sensitive(false);
843
844         _master_bus_channel_count.set_flags(Gtk::CAN_FOCUS);
845         _master_bus_channel_count.set_update_policy(Gtk::UPDATE_ALWAYS);
846         _master_bus_channel_count.set_numeric(true);
847         _master_bus_channel_count.set_digits(0);
848         _master_bus_channel_count.set_wrap(false);
849
850         _create_master_bus.set_label (_("Create master bus"));
851         _create_master_bus.set_flags(Gtk::CAN_FOCUS);
852         _create_master_bus.set_relief(Gtk::RELIEF_NORMAL);
853         _create_master_bus.set_mode(true);
854         _create_master_bus.set_active(true);
855         _create_master_bus.set_border_width(0);
856
857         advanced_table.set_row_spacings(0);
858         advanced_table.set_col_spacings(0);
859
860         _connect_inputs.set_label (_("Automatically connect to physical_inputs"));
861         _connect_inputs.set_flags(Gtk::CAN_FOCUS);
862         _connect_inputs.set_relief(Gtk::RELIEF_NORMAL);
863         _connect_inputs.set_mode(true);
864         _connect_inputs.set_active(true);
865         _connect_inputs.set_border_width(0);
866
867         _limit_input_ports.set_label (_("Use only"));
868         _limit_input_ports.set_flags(Gtk::CAN_FOCUS);
869         _limit_input_ports.set_relief(Gtk::RELIEF_NORMAL);
870         _limit_input_ports.set_mode(true);
871         _limit_input_ports.set_sensitive(true);
872         _limit_input_ports.set_border_width(0);
873
874         _input_limit_count.set_flags(Gtk::CAN_FOCUS);
875         _input_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
876         _input_limit_count.set_numeric(true);
877         _input_limit_count.set_digits(0);
878         _input_limit_count.set_wrap(false);
879         _input_limit_count.set_sensitive(false);
880
881         bus_hbox.pack_start (bus_table, Gtk::PACK_SHRINK, 18);
882
883         bus_label.set_alignment(0, 0.5);
884         bus_label.set_padding(0,0);
885         bus_label.set_line_wrap(false);
886         bus_label.set_selectable(false);
887         bus_label.set_use_markup(true);
888         bus_frame.set_shadow_type(Gtk::SHADOW_NONE);
889         bus_frame.set_label_align(0,0.5);
890         bus_frame.add(bus_hbox);
891         bus_frame.set_label_widget(bus_label);
892
893         bus_table.set_row_spacings (0);
894         bus_table.set_col_spacings (0);
895         bus_table.attach (_create_master_bus, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
896         bus_table.attach (_master_bus_channel_count, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
897         bus_table.attach (chan_count_label_1, 2, 3, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 0);
898         bus_table.attach (_create_control_bus, 0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
899         bus_table.attach (_control_bus_channel_count, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
900         bus_table.attach (chan_count_label_2, 2, 3, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 0);
901
902         input_port_limit_hbox.pack_start(_limit_input_ports, Gtk::PACK_SHRINK, 6);
903         input_port_limit_hbox.pack_start(_input_limit_count, Gtk::PACK_SHRINK, 0);
904         input_port_limit_hbox.pack_start(chan_count_label_3, Gtk::PACK_SHRINK, 6);
905         input_port_vbox.pack_start(_connect_inputs, Gtk::PACK_SHRINK, 0);
906         input_port_vbox.pack_start(input_port_limit_hbox, Gtk::PACK_EXPAND_PADDING, 0);
907         input_table.set_row_spacings(0);
908         input_table.set_col_spacings(0);
909         input_table.attach(input_port_vbox, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 6);
910
911         input_hbox.pack_start (input_table, Gtk::PACK_SHRINK, 18);
912
913         input_label.set_alignment(0, 0.5);
914         input_label.set_padding(0,0);
915         input_label.set_line_wrap(false);
916         input_label.set_selectable(false);
917         input_label.set_use_markup(true);
918         input_frame.set_shadow_type(Gtk::SHADOW_NONE);
919         input_frame.set_label_align(0,0.5);
920         input_frame.add(input_hbox);
921         input_frame.set_label_widget(input_label);
922
923         _connect_outputs.set_label (_("Automatically connect outputs"));
924         _connect_outputs.set_flags(Gtk::CAN_FOCUS);
925         _connect_outputs.set_relief(Gtk::RELIEF_NORMAL);
926         _connect_outputs.set_mode(true);
927         _connect_outputs.set_active(true);
928         _connect_outputs.set_border_width(0);
929         _limit_output_ports.set_label (_("Use only"));
930         _limit_output_ports.set_flags(Gtk::CAN_FOCUS);
931         _limit_output_ports.set_relief(Gtk::RELIEF_NORMAL);
932         _limit_output_ports.set_mode(true);
933         _limit_output_ports.set_sensitive(true);
934         _limit_output_ports.set_border_width(0);
935         _output_limit_count.set_flags(Gtk::CAN_FOCUS);
936         _output_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
937         _output_limit_count.set_numeric(false);
938         _output_limit_count.set_digits(0);
939         _output_limit_count.set_wrap(false);
940         _output_limit_count.set_sensitive(false);
941         output_port_limit_hbox.pack_start(_limit_output_ports, Gtk::PACK_SHRINK, 6);
942         output_port_limit_hbox.pack_start(_output_limit_count, Gtk::PACK_SHRINK, 0);
943         output_port_limit_hbox.pack_start(chan_count_label_4, Gtk::PACK_SHRINK, 6);
944
945         _connect_outputs_to_master.set_label (_("... to master bus"));
946         _connect_outputs_to_master.set_flags(Gtk::CAN_FOCUS);
947         _connect_outputs_to_master.set_relief(Gtk::RELIEF_NORMAL);
948         _connect_outputs_to_master.set_mode(true);
949         _connect_outputs_to_master.set_active(false);
950         _connect_outputs_to_master.set_border_width(0);
951
952         _connect_outputs_to_master.set_group (connect_outputs_group);
953         _connect_outputs_to_physical.set_group (connect_outputs_group);
954
955         _connect_outputs_to_physical.set_label (_("... to physical outputs"));
956         _connect_outputs_to_physical.set_flags(Gtk::CAN_FOCUS);
957         _connect_outputs_to_physical.set_relief(Gtk::RELIEF_NORMAL);
958         _connect_outputs_to_physical.set_mode(true);
959         _connect_outputs_to_physical.set_active(false);
960         _connect_outputs_to_physical.set_border_width(0);
961
962         output_conn_vbox.pack_start(_connect_outputs, Gtk::PACK_SHRINK, 0);
963         output_conn_vbox.pack_start(_connect_outputs_to_master, Gtk::PACK_SHRINK, 0);
964         output_conn_vbox.pack_start(_connect_outputs_to_physical, Gtk::PACK_SHRINK, 0);
965         output_vbox.set_border_width(6);
966
967         output_port_vbox.pack_start(output_port_limit_hbox, Gtk::PACK_SHRINK, 0);
968
969         output_vbox.pack_start(output_conn_vbox);
970         output_vbox.pack_start(output_port_vbox);
971
972         output_label.set_alignment(0, 0.5);
973         output_label.set_padding(0,0);
974         output_label.set_line_wrap(false);
975         output_label.set_selectable(false);
976         output_label.set_use_markup(true);
977         output_frame.set_shadow_type(Gtk::SHADOW_NONE);
978         output_frame.set_label_align(0,0.5);
979
980         output_hbox.pack_start (output_vbox, Gtk::PACK_SHRINK, 18);
981
982         output_frame.add(output_hbox);
983         output_frame.set_label_widget(output_label);
984
985         more_options_vbox.pack_start(advanced_table, Gtk::PACK_SHRINK, 0);
986         more_options_vbox.pack_start(bus_frame, Gtk::PACK_SHRINK, 6);
987         more_options_vbox.pack_start(input_frame, Gtk::PACK_SHRINK, 6);
988         more_options_vbox.pack_start(output_frame, Gtk::PACK_SHRINK, 0);
989
990         /* signals */
991
992         _connect_inputs.signal_clicked().connect (mem_fun (*this, &ArdourStartup::connect_inputs_clicked));
993         _connect_outputs.signal_clicked().connect (mem_fun (*this, &ArdourStartup::connect_outputs_clicked));
994         _limit_input_ports.signal_clicked().connect (mem_fun (*this, &ArdourStartup::limit_inputs_clicked));
995         _limit_output_ports.signal_clicked().connect (mem_fun (*this, &ArdourStartup::limit_outputs_clicked));
996         _create_master_bus.signal_clicked().connect (mem_fun (*this, &ArdourStartup::master_bus_button_clicked));
997         _create_control_bus.signal_clicked().connect (mem_fun (*this, &ArdourStartup::monitor_bus_button_clicked));
998
999         /* note that more_options_vbox is NOT visible by
1000          * default. this is entirely by design - this page
1001          * should be skipped unless explicitly requested.
1002          */
1003
1004         session_options_page_index = append_page (more_options_vbox);
1005         set_page_title (more_options_vbox, _("Advanced Session Options"));
1006         set_page_complete (more_options_vbox, true);
1007 }
1008
1009 bool
1010 ArdourStartup::create_master_bus() const
1011 {
1012         return _create_master_bus.get_active();
1013 }
1014
1015 int
1016 ArdourStartup::master_channel_count() const
1017 {
1018         return _master_bus_channel_count.get_value_as_int();
1019 }
1020
1021 bool
1022 ArdourStartup::create_control_bus() const
1023 {
1024         return _create_control_bus.get_active();
1025 }
1026
1027 int
1028 ArdourStartup::control_channel_count() const
1029 {
1030         return _control_bus_channel_count.get_value_as_int();
1031 }
1032
1033 bool
1034 ArdourStartup::connect_inputs() const
1035 {
1036         return _connect_inputs.get_active();
1037 }
1038
1039 bool
1040 ArdourStartup::limit_inputs_used_for_connection() const
1041 {
1042         return _limit_input_ports.get_active();
1043 }
1044
1045 int
1046 ArdourStartup::input_limit_count() const
1047 {
1048         return _input_limit_count.get_value_as_int();
1049 }
1050
1051 bool
1052 ArdourStartup::connect_outputs() const
1053 {
1054         return _connect_outputs.get_active();
1055 }
1056
1057 bool
1058 ArdourStartup::limit_outputs_used_for_connection() const
1059 {
1060         return _limit_output_ports.get_active();
1061 }
1062
1063 int
1064 ArdourStartup::output_limit_count() const
1065 {
1066         return _output_limit_count.get_value_as_int();
1067 }
1068
1069 bool
1070 ArdourStartup::connect_outs_to_master() const
1071 {
1072         return _connect_outputs_to_master.get_active();
1073 }
1074
1075 bool
1076 ArdourStartup::connect_outs_to_physical() const
1077 {
1078         return _connect_outputs_to_physical.get_active();
1079 }
1080
1081 void
1082 ArdourStartup::connect_inputs_clicked ()
1083 {
1084         _limit_input_ports.set_sensitive(_connect_inputs.get_active());
1085
1086         if (_connect_inputs.get_active() && _limit_input_ports.get_active()) {
1087                 _input_limit_count.set_sensitive(true);
1088         } else {
1089                 _input_limit_count.set_sensitive(false);
1090         }
1091 }
1092
1093 void
1094 ArdourStartup::connect_outputs_clicked ()
1095 {
1096         _limit_output_ports.set_sensitive(_connect_outputs.get_active());
1097
1098         if (_connect_outputs.get_active() && _limit_output_ports.get_active()) {
1099                 _output_limit_count.set_sensitive(true);
1100         } else {
1101                 _output_limit_count.set_sensitive(false);
1102         }
1103 }
1104
1105 void
1106 ArdourStartup::limit_inputs_clicked ()
1107 {
1108         _input_limit_count.set_sensitive(_limit_input_ports.get_active());
1109 }
1110
1111 void
1112 ArdourStartup::limit_outputs_clicked ()
1113 {
1114         _output_limit_count.set_sensitive(_limit_output_ports.get_active());
1115 }
1116
1117 void
1118 ArdourStartup::master_bus_button_clicked ()
1119 {
1120         _master_bus_channel_count.set_sensitive(_create_master_bus.get_active());
1121 }
1122
1123 void
1124 ArdourStartup::monitor_bus_button_clicked ()
1125 {
1126         _control_bus_channel_count.set_sensitive(_create_control_bus.get_active());
1127 }
1128
1129 void
1130 ArdourStartup::move_along_now ()
1131 {
1132         gint cur = get_current_page ();
1133
1134         if (cur == session_page_index) {
1135                 if (more_new_session_options_button.get_active()) {
1136                         set_current_page (session_options_page_index);
1137                 } else {
1138                         on_apply ();
1139                 }
1140         }
1141 }
1142
1143 void
1144 ArdourStartup::recent_row_activated (const Gtk::TreePath&, Gtk::TreeViewColumn*)
1145 {
1146         set_page_complete (session_vbox, true);
1147         move_along_now ();
1148 }