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