Stop ardour exiting in the case where you have a loaded session, then select New...
[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         gtk_main_quit ();
422 }
423
424 void
425 ArdourStartup::on_close ()
426 {
427         gtk_main_quit ();
428 }
429
430 void
431 ArdourStartup::on_apply ()
432 {
433         _applying = true;
434
435         // XXX do stuff and then ....
436
437         if (engine_dialog) {
438                 engine_dialog->setup_engine ();
439         }
440
441         if (config_modified) {
442
443                 if (default_dir_chooser) {
444                         Config->set_default_session_parent_dir (default_dir_chooser->get_current_folder());
445                 }
446
447                 if (monitor_via_hardware_button.get_active()) {
448                         Config->set_monitoring_model (ExternalMonitoring);
449                 } else if (monitor_via_ardour_button.get_active()) {
450                         Config->set_monitoring_model (SoftwareMonitoring);
451                 }
452
453                 Config->save_state ();
454         }
455
456         gtk_main_quit ();
457 }
458
459 void
460 ArdourStartup::on_prepare (Gtk::Widget* page)
461 {
462         if (page == &session_vbox) {
463
464                 if (ic_new_session_button.get_active()) {
465                         /* new session requested */
466                         setup_new_session_page ();
467                 } else {
468                         /* existing session requested */
469                         setup_existing_session_page ();
470                 }
471         }
472 }
473
474 void
475 ArdourStartup::populate_session_templates ()
476 {
477         vector<TemplateInfo> templates;
478
479         find_session_templates (templates);
480
481         template_model->clear ();
482
483         for (vector<TemplateInfo>::iterator x = templates.begin(); x != templates.end(); ++x) {
484                 TreeModel::Row row;
485
486                 row = *(template_model->append ());
487
488                 row[session_template_columns.name] = (*x).name;
489                 row[session_template_columns.path] = (*x).path;
490         }
491 }
492
493 void
494 ArdourStartup::setup_new_session_page ()
495 {
496         if (!session_hbox.get_children().empty()) {
497                 session_hbox.remove (**session_hbox.get_children().begin());
498         }
499
500         session_new_vbox.set_spacing (18);
501
502         if (session_new_vbox.get_children().empty()) {
503                 VBox *vbox1 = manage (new VBox);
504                 HBox* hbox1 = manage (new HBox);
505                 Label* label1 = manage (new Label);
506
507                 vbox1->set_spacing (6);
508
509                 hbox1->set_spacing (6);
510                 hbox1->pack_start (*label1, false, false);
511                 hbox1->pack_start (new_name_entry, true, true);
512
513                 label1->set_text (_("Session name:"));
514
515
516                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
517                         new_name_entry.set_text  (Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name));
518                         /* name provided - they can move right along */
519                         set_page_complete (session_vbox, true);
520                 }
521
522                 new_name_entry.signal_changed().connect (mem_fun (*this, &ArdourStartup::new_name_changed));
523                 new_name_entry.signal_activate().connect (mem_fun (*this, &ArdourStartup::move_along_now));
524
525                 vbox1->pack_start (*hbox1, true, true);
526
527                 /* --- */
528
529                 HBox* hbox2 = manage (new HBox);
530                 Label* label2 = manage (new Label);
531
532                 hbox2->set_spacing (6);
533                 hbox2->pack_start (*label2, false, false);
534                 hbox2->pack_start (new_folder_chooser, true, true);
535
536                 label2->set_text (_("Create session folder in:"));
537
538                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
539                         new_folder_chooser.set_current_folder (poor_mans_glob (Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name)));
540                 } else {
541                         new_folder_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
542                 }
543                 new_folder_chooser.set_title (_("Select folder for session"));
544
545                 vbox1->pack_start (*hbox2, false, false);
546
547                 session_new_vbox.pack_start (*vbox1, false, false);
548
549                 /* --- */
550
551                 VBox *vbox2 = manage (new VBox);
552                 HBox* hbox3 = manage (new HBox);
553                 Label* label3 = manage (new Label);
554                 template_model = ListStore::create (session_template_columns);
555                 populate_session_templates ();
556
557                 vbox2->set_spacing (6);
558
559                 label3->set_markup (_("<b>Options</b>"));
560                 label3->set_alignment (0.0, 0.0);
561
562                 vbox2->pack_start (*label3, false, true);
563
564                 VBox *vbox3 = manage (new VBox);
565
566                 vbox3->set_spacing (6);
567
568                 if (!template_model->children().empty()) {
569
570                         HBox* hbox4a = manage (new HBox);
571                         use_template_button.set_label (_("Use this template"));
572
573                         TreeModel::Row row = *template_model->prepend ();
574                         row[session_template_columns.name] = (_("no template"));
575                         row[session_template_columns.path] = string();
576
577                         hbox4a->set_spacing (6);
578                         hbox4a->pack_start (use_template_button, false, false);
579                         hbox4a->pack_start (template_chooser, true, true);
580
581                         template_chooser.set_model (template_model);
582
583                         Gtk::CellRendererText* text_renderer = Gtk::manage (new Gtk::CellRendererText);
584                         text_renderer->property_editable() = false;
585
586                         template_chooser.pack_start (*text_renderer);
587                         template_chooser.add_attribute (text_renderer->property_text(), session_template_columns.name);
588                         template_chooser.set_active (0);
589
590                         use_template_button.show();
591                         template_chooser.show ();
592
593                         vbox3->pack_start (*hbox4a, false, false);
594                 }
595
596                 /* --- */
597
598                 if (!new_user) {
599                         session_template_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
600
601                         HBox* hbox4b = manage (new HBox);
602                         use_session_as_template_button.set_label (_("Use an existing session as a template:"));
603
604                         hbox4b->set_spacing (6);
605                         hbox4b->pack_start (use_session_as_template_button, false, false);
606                         hbox4b->pack_start (session_template_chooser, true, true);
607
608                         use_session_as_template_button.show ();
609                         session_template_chooser.show ();
610
611                         Gtk::FileFilter* template_filter = manage (new (Gtk::FileFilter));
612                         template_filter->add_pattern(X_("*.template"));
613                         session_template_chooser.set_filter (*template_filter);
614                         session_template_chooser.set_title (_("Select template"));
615
616                         vbox3->pack_start (*hbox4b, false, false);
617                 }
618
619                 /* --- */
620
621                 HBox* hbox5 = manage (new HBox);
622
623                 hbox5->set_spacing (6);
624                 hbox5->pack_start (more_new_session_options_button, false, false);
625
626                 more_new_session_options_button.show ();
627                 more_new_session_options_button.signal_clicked().connect (mem_fun (*this, &ArdourStartup::more_new_session_options_button_clicked));
628
629                 vbox3->pack_start (*hbox5, false, false);
630                 hbox3->pack_start (*vbox3, true, true, 8);
631                 vbox2->pack_start (*hbox3, false, false);
632
633                 /* --- */
634
635                 session_new_vbox.pack_start (*vbox2, false, false);
636         }
637
638         session_new_vbox.show_all ();
639         session_hbox.pack_start (session_new_vbox, true, true);
640         set_page_title (session_vbox, _("New Session"));
641         set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
642
643         new_name_entry.grab_focus ();
644 }
645
646 void
647 ArdourStartup::new_name_changed ()
648 {
649         if (!new_name_entry.get_text().empty()) {
650                 set_page_complete (session_vbox, true);
651         } else {
652                 set_page_complete (session_vbox, false);
653         }
654 }
655
656 void
657 ArdourStartup::redisplay_recent_sessions ()
658 {
659         std::vector<sys::path> session_directories;
660         RecentSessionsSorter cmp;
661
662         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
663         recent_session_model->clear ();
664
665         ARDOUR::RecentSessions rs;
666         ARDOUR::read_recent_sessions (rs);
667
668         if (rs.empty()) {
669                 recent_session_display.set_model (recent_session_model);
670                 return;
671         }
672         //
673         // sort them alphabetically
674         sort (rs.begin(), rs.end(), cmp);
675
676         for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
677                 session_directories.push_back ((*i).second);
678         }
679
680         for (vector<sys::path>::const_iterator i = session_directories.begin(); i != session_directories.end(); ++i)
681         {
682                 std::vector<sys::path> state_file_paths;
683
684                 // now get available states for this session
685
686                 get_state_files_in_directory (*i, state_file_paths);
687
688                 vector<string*>* states;
689                 vector<const gchar*> item;
690                 string fullpath = (*i).to_string();
691
692                 /* remove any trailing / */
693
694                 if (fullpath[fullpath.length()-1] == '/') {
695                         fullpath = fullpath.substr (0, fullpath.length()-1);
696                 }
697
698                 /* check whether session still exists */
699                 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
700                         /* session doesn't exist */
701                         continue;
702                 }
703
704                 /* now get available states for this session */
705
706                 if ((states = Session::possible_states (fullpath)) == 0) {
707                         /* no state file? */
708                         continue;
709                 }
710
711                 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
712
713                 Gtk::TreeModel::Row row = *(recent_session_model->append());
714
715                 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
716                 row[recent_session_columns.fullpath] = fullpath;
717
718                 if (state_file_names.size() > 1) {
719
720                         // add the children
721
722                         for (std::vector<std::string>::iterator i2 = state_file_names.begin();
723                                         i2 != state_file_names.end(); ++i2)
724                         {
725
726                                 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
727
728                                 child_row[recent_session_columns.visible_name] = *i2;
729                                 child_row[recent_session_columns.fullpath] = fullpath;
730                         }
731                 }
732         }
733
734         recent_session_display.set_model (recent_session_model);
735 }
736
737 void
738 ArdourStartup::recent_session_row_selected ()
739 {
740         if (recent_session_display.get_selection()->count_selected_rows() > 0) {
741                 set_page_complete (session_vbox, true);
742         } else {
743                 set_page_complete (session_vbox, false);
744         }
745 }
746
747 void
748 ArdourStartup::setup_existing_session_page ()
749 {
750         if (!session_hbox.get_children().empty()) {
751                 session_hbox.remove (**session_hbox.get_children().begin());
752         }
753
754         if (recent_scroller.get_children().empty()) {
755
756                 recent_session_model = TreeStore::create (recent_session_columns);
757                 recent_session_display.set_model (recent_session_model);
758                 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
759                 recent_session_display.set_headers_visible (false);
760                 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
761
762                 recent_session_display.get_selection()->signal_changed().connect (mem_fun (*this, &ArdourStartup::recent_session_row_selected));
763
764                 recent_scroller.add (recent_session_display);
765                 recent_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
766                 recent_scroller.set_shadow_type (Gtk::SHADOW_IN);
767
768                 recent_session_display.show();
769         }
770
771         recent_scroller.show();
772         redisplay_recent_sessions ();
773         recent_session_display.signal_row_activated().connect (mem_fun (*this, &ArdourStartup::recent_row_activated));
774
775         session_hbox.pack_start (recent_scroller, true, true);
776         set_page_title (session_vbox, _("Select a session"));
777         set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
778 }
779
780 void
781 ArdourStartup::more_new_session_options_button_clicked ()
782 {
783         if (more_new_session_options_button.get_active()) {
784                 more_options_vbox.show_all ();
785                 set_page_type (more_options_vbox, ASSISTANT_PAGE_CONFIRM);
786                 set_page_type (session_vbox, ASSISTANT_PAGE_CONTENT);
787         } else {
788                 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
789                 more_options_vbox.hide ();
790         }
791 }
792
793 void
794 ArdourStartup::setup_more_options_page ()
795 {
796         more_options_vbox.set_border_width (24);
797
798         _output_limit_count.set_adjustment (_output_limit_count_adj);
799         _input_limit_count.set_adjustment (_input_limit_count_adj);
800         _control_bus_channel_count.set_adjustment (_control_bus_channel_count_adj);
801         _master_bus_channel_count.set_adjustment (_master_bus_channel_count_adj);
802
803         chan_count_label_1.set_text (_("channels"));
804         chan_count_label_2.set_text (_("channels"));
805         chan_count_label_3.set_text (_("channels"));
806         chan_count_label_4.set_text (_("channels"));
807
808         chan_count_label_1.set_alignment(0,0.5);
809         chan_count_label_1.set_padding(0,0);
810         chan_count_label_1.set_line_wrap(false);
811
812         chan_count_label_2.set_alignment(0,0.5);
813         chan_count_label_2.set_padding(0,0);
814         chan_count_label_2.set_line_wrap(false);
815
816         chan_count_label_3.set_alignment(0,0.5);
817         chan_count_label_3.set_padding(0,0);
818         chan_count_label_3.set_line_wrap(false);
819
820         chan_count_label_4.set_alignment(0,0.5);
821         chan_count_label_4.set_padding(0,0);
822         chan_count_label_4.set_line_wrap(false);
823
824         bus_label.set_markup (_("<b>Busses</b>"));
825         input_label.set_markup (_("<b>Inputs</b>"));
826         output_label.set_markup (_("<b>Outputs</b>"));
827
828         _create_control_bus.set_label (_("Create monitor bus"));
829         _create_control_bus.set_flags(Gtk::CAN_FOCUS);
830         _create_control_bus.set_relief(Gtk::RELIEF_NORMAL);
831         _create_control_bus.set_mode(true);
832         _create_control_bus.set_active(false);
833         _create_control_bus.set_border_width(0);
834
835         _control_bus_channel_count.set_flags(Gtk::CAN_FOCUS);
836         _control_bus_channel_count.set_update_policy(Gtk::UPDATE_ALWAYS);
837         _control_bus_channel_count.set_numeric(true);
838         _control_bus_channel_count.set_digits(0);
839         _control_bus_channel_count.set_wrap(false);
840         _control_bus_channel_count.set_sensitive(false);
841
842         _master_bus_channel_count.set_flags(Gtk::CAN_FOCUS);
843         _master_bus_channel_count.set_update_policy(Gtk::UPDATE_ALWAYS);
844         _master_bus_channel_count.set_numeric(true);
845         _master_bus_channel_count.set_digits(0);
846         _master_bus_channel_count.set_wrap(false);
847
848         _create_master_bus.set_label (_("Create master bus"));
849         _create_master_bus.set_flags(Gtk::CAN_FOCUS);
850         _create_master_bus.set_relief(Gtk::RELIEF_NORMAL);
851         _create_master_bus.set_mode(true);
852         _create_master_bus.set_active(true);
853         _create_master_bus.set_border_width(0);
854
855         advanced_table.set_row_spacings(0);
856         advanced_table.set_col_spacings(0);
857
858         _connect_inputs.set_label (_("Automatically connect to physical_inputs"));
859         _connect_inputs.set_flags(Gtk::CAN_FOCUS);
860         _connect_inputs.set_relief(Gtk::RELIEF_NORMAL);
861         _connect_inputs.set_mode(true);
862         _connect_inputs.set_active(true);
863         _connect_inputs.set_border_width(0);
864
865         _limit_input_ports.set_label (_("Use only"));
866         _limit_input_ports.set_flags(Gtk::CAN_FOCUS);
867         _limit_input_ports.set_relief(Gtk::RELIEF_NORMAL);
868         _limit_input_ports.set_mode(true);
869         _limit_input_ports.set_sensitive(true);
870         _limit_input_ports.set_border_width(0);
871
872         _input_limit_count.set_flags(Gtk::CAN_FOCUS);
873         _input_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
874         _input_limit_count.set_numeric(true);
875         _input_limit_count.set_digits(0);
876         _input_limit_count.set_wrap(false);
877         _input_limit_count.set_sensitive(false);
878
879         bus_hbox.pack_start (bus_table, Gtk::PACK_SHRINK, 18);
880
881         bus_label.set_alignment(0, 0.5);
882         bus_label.set_padding(0,0);
883         bus_label.set_line_wrap(false);
884         bus_label.set_selectable(false);
885         bus_label.set_use_markup(true);
886         bus_frame.set_shadow_type(Gtk::SHADOW_NONE);
887         bus_frame.set_label_align(0,0.5);
888         bus_frame.add(bus_hbox);
889         bus_frame.set_label_widget(bus_label);
890
891         bus_table.set_row_spacings (0);
892         bus_table.set_col_spacings (0);
893         bus_table.attach (_create_master_bus, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
894         bus_table.attach (_master_bus_channel_count, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
895         bus_table.attach (chan_count_label_1, 2, 3, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 0);
896         bus_table.attach (_create_control_bus, 0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
897         bus_table.attach (_control_bus_channel_count, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
898         bus_table.attach (chan_count_label_2, 2, 3, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 0);
899
900         input_port_limit_hbox.pack_start(_limit_input_ports, Gtk::PACK_SHRINK, 6);
901         input_port_limit_hbox.pack_start(_input_limit_count, Gtk::PACK_SHRINK, 0);
902         input_port_limit_hbox.pack_start(chan_count_label_3, Gtk::PACK_SHRINK, 6);
903         input_port_vbox.pack_start(_connect_inputs, Gtk::PACK_SHRINK, 0);
904         input_port_vbox.pack_start(input_port_limit_hbox, Gtk::PACK_EXPAND_PADDING, 0);
905         input_table.set_row_spacings(0);
906         input_table.set_col_spacings(0);
907         input_table.attach(input_port_vbox, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 6);
908
909         input_hbox.pack_start (input_table, Gtk::PACK_SHRINK, 18);
910
911         input_label.set_alignment(0, 0.5);
912         input_label.set_padding(0,0);
913         input_label.set_line_wrap(false);
914         input_label.set_selectable(false);
915         input_label.set_use_markup(true);
916         input_frame.set_shadow_type(Gtk::SHADOW_NONE);
917         input_frame.set_label_align(0,0.5);
918         input_frame.add(input_hbox);
919         input_frame.set_label_widget(input_label);
920
921         _connect_outputs.set_label (_("Automatically connect outputs"));
922         _connect_outputs.set_flags(Gtk::CAN_FOCUS);
923         _connect_outputs.set_relief(Gtk::RELIEF_NORMAL);
924         _connect_outputs.set_mode(true);
925         _connect_outputs.set_active(true);
926         _connect_outputs.set_border_width(0);
927         _limit_output_ports.set_label (_("Use only"));
928         _limit_output_ports.set_flags(Gtk::CAN_FOCUS);
929         _limit_output_ports.set_relief(Gtk::RELIEF_NORMAL);
930         _limit_output_ports.set_mode(true);
931         _limit_output_ports.set_sensitive(true);
932         _limit_output_ports.set_border_width(0);
933         _output_limit_count.set_flags(Gtk::CAN_FOCUS);
934         _output_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
935         _output_limit_count.set_numeric(false);
936         _output_limit_count.set_digits(0);
937         _output_limit_count.set_wrap(false);
938         _output_limit_count.set_sensitive(false);
939         output_port_limit_hbox.pack_start(_limit_output_ports, Gtk::PACK_SHRINK, 6);
940         output_port_limit_hbox.pack_start(_output_limit_count, Gtk::PACK_SHRINK, 0);
941         output_port_limit_hbox.pack_start(chan_count_label_4, Gtk::PACK_SHRINK, 6);
942
943         _connect_outputs_to_master.set_label (_("... to master bus"));
944         _connect_outputs_to_master.set_flags(Gtk::CAN_FOCUS);
945         _connect_outputs_to_master.set_relief(Gtk::RELIEF_NORMAL);
946         _connect_outputs_to_master.set_mode(true);
947         _connect_outputs_to_master.set_active(false);
948         _connect_outputs_to_master.set_border_width(0);
949
950         _connect_outputs_to_master.set_group (connect_outputs_group);
951         _connect_outputs_to_physical.set_group (connect_outputs_group);
952
953         _connect_outputs_to_physical.set_label (_("... to physical outputs"));
954         _connect_outputs_to_physical.set_flags(Gtk::CAN_FOCUS);
955         _connect_outputs_to_physical.set_relief(Gtk::RELIEF_NORMAL);
956         _connect_outputs_to_physical.set_mode(true);
957         _connect_outputs_to_physical.set_active(false);
958         _connect_outputs_to_physical.set_border_width(0);
959
960         output_conn_vbox.pack_start(_connect_outputs, Gtk::PACK_SHRINK, 0);
961         output_conn_vbox.pack_start(_connect_outputs_to_master, Gtk::PACK_SHRINK, 0);
962         output_conn_vbox.pack_start(_connect_outputs_to_physical, Gtk::PACK_SHRINK, 0);
963         output_vbox.set_border_width(6);
964
965         output_port_vbox.pack_start(output_port_limit_hbox, Gtk::PACK_SHRINK, 0);
966
967         output_vbox.pack_start(output_conn_vbox);
968         output_vbox.pack_start(output_port_vbox);
969
970         output_label.set_alignment(0, 0.5);
971         output_label.set_padding(0,0);
972         output_label.set_line_wrap(false);
973         output_label.set_selectable(false);
974         output_label.set_use_markup(true);
975         output_frame.set_shadow_type(Gtk::SHADOW_NONE);
976         output_frame.set_label_align(0,0.5);
977
978         output_hbox.pack_start (output_vbox, Gtk::PACK_SHRINK, 18);
979
980         output_frame.add(output_hbox);
981         output_frame.set_label_widget(output_label);
982
983         more_options_vbox.pack_start(advanced_table, Gtk::PACK_SHRINK, 0);
984         more_options_vbox.pack_start(bus_frame, Gtk::PACK_SHRINK, 6);
985         more_options_vbox.pack_start(input_frame, Gtk::PACK_SHRINK, 6);
986         more_options_vbox.pack_start(output_frame, Gtk::PACK_SHRINK, 0);
987
988         /* signals */
989
990         _connect_inputs.signal_clicked().connect (mem_fun (*this, &ArdourStartup::connect_inputs_clicked));
991         _connect_outputs.signal_clicked().connect (mem_fun (*this, &ArdourStartup::connect_outputs_clicked));
992         _limit_input_ports.signal_clicked().connect (mem_fun (*this, &ArdourStartup::limit_inputs_clicked));
993         _limit_output_ports.signal_clicked().connect (mem_fun (*this, &ArdourStartup::limit_outputs_clicked));
994         _create_master_bus.signal_clicked().connect (mem_fun (*this, &ArdourStartup::master_bus_button_clicked));
995         _create_control_bus.signal_clicked().connect (mem_fun (*this, &ArdourStartup::monitor_bus_button_clicked));
996
997         /* note that more_options_vbox is NOT visible by
998          * default. this is entirely by design - this page
999          * should be skipped unless explicitly requested.
1000          */
1001
1002         session_options_page_index = append_page (more_options_vbox);
1003         set_page_title (more_options_vbox, _("Advanced Session Options"));
1004         set_page_complete (more_options_vbox, true);
1005 }
1006
1007 bool
1008 ArdourStartup::create_master_bus() const
1009 {
1010         return _create_master_bus.get_active();
1011 }
1012
1013 int
1014 ArdourStartup::master_channel_count() const
1015 {
1016         return _master_bus_channel_count.get_value_as_int();
1017 }
1018
1019 bool
1020 ArdourStartup::create_control_bus() const
1021 {
1022         return _create_control_bus.get_active();
1023 }
1024
1025 int
1026 ArdourStartup::control_channel_count() const
1027 {
1028         return _control_bus_channel_count.get_value_as_int();
1029 }
1030
1031 bool
1032 ArdourStartup::connect_inputs() const
1033 {
1034         return _connect_inputs.get_active();
1035 }
1036
1037 bool
1038 ArdourStartup::limit_inputs_used_for_connection() const
1039 {
1040         return _limit_input_ports.get_active();
1041 }
1042
1043 int
1044 ArdourStartup::input_limit_count() const
1045 {
1046         return _input_limit_count.get_value_as_int();
1047 }
1048
1049 bool
1050 ArdourStartup::connect_outputs() const
1051 {
1052         return _connect_outputs.get_active();
1053 }
1054
1055 bool
1056 ArdourStartup::limit_outputs_used_for_connection() const
1057 {
1058         return _limit_output_ports.get_active();
1059 }
1060
1061 int
1062 ArdourStartup::output_limit_count() const
1063 {
1064         return _output_limit_count.get_value_as_int();
1065 }
1066
1067 bool
1068 ArdourStartup::connect_outs_to_master() const
1069 {
1070         return _connect_outputs_to_master.get_active();
1071 }
1072
1073 bool
1074 ArdourStartup::connect_outs_to_physical() const
1075 {
1076         return _connect_outputs_to_physical.get_active();
1077 }
1078
1079 void
1080 ArdourStartup::connect_inputs_clicked ()
1081 {
1082         _limit_input_ports.set_sensitive(_connect_inputs.get_active());
1083
1084         if (_connect_inputs.get_active() && _limit_input_ports.get_active()) {
1085                 _input_limit_count.set_sensitive(true);
1086         } else {
1087                 _input_limit_count.set_sensitive(false);
1088         }
1089 }
1090
1091 void
1092 ArdourStartup::connect_outputs_clicked ()
1093 {
1094         _limit_output_ports.set_sensitive(_connect_outputs.get_active());
1095
1096         if (_connect_outputs.get_active() && _limit_output_ports.get_active()) {
1097                 _output_limit_count.set_sensitive(true);
1098         } else {
1099                 _output_limit_count.set_sensitive(false);
1100         }
1101 }
1102
1103 void
1104 ArdourStartup::limit_inputs_clicked ()
1105 {
1106         _input_limit_count.set_sensitive(_limit_input_ports.get_active());
1107 }
1108
1109 void
1110 ArdourStartup::limit_outputs_clicked ()
1111 {
1112         _output_limit_count.set_sensitive(_limit_output_ports.get_active());
1113 }
1114
1115 void
1116 ArdourStartup::master_bus_button_clicked ()
1117 {
1118         _master_bus_channel_count.set_sensitive(_create_master_bus.get_active());
1119 }
1120
1121 void
1122 ArdourStartup::monitor_bus_button_clicked ()
1123 {
1124         _control_bus_channel_count.set_sensitive(_create_control_bus.get_active());
1125 }
1126
1127 void
1128 ArdourStartup::move_along_now ()
1129 {
1130         gint cur = get_current_page ();
1131
1132         if (cur == session_page_index) {
1133                 if (more_new_session_options_button.get_active()) {
1134                         set_current_page (session_options_page_index);
1135                 } else {
1136                         on_apply ();
1137                 }
1138         }
1139 }
1140
1141 void
1142 ArdourStartup::recent_row_activated (const Gtk::TreePath&, Gtk::TreeViewColumn*)
1143 {
1144         set_page_complete (session_vbox, true);
1145         move_along_now ();
1146 }