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