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