fix horiz alignment (corner-radius is added to layout)
[ardour.git] / gtk2_ardour / startup.cc
1 /*
2     Copyright (C) 2010 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #endif
23
24 #include <fstream>
25 #include <algorithm>
26
27 #include <gtkmm/main.h>
28 #include <gtkmm/filechooser.h>
29
30 #include "pbd/failed_constructor.h"
31 #include "pbd/file_utils.h"
32 #include "pbd/replace_all.h"
33 #include "pbd/whitespace.h"
34
35 #include "ardour/filesystem_paths.h"
36 #include "ardour/recent_sessions.h"
37 #include "ardour/session.h"
38 #include "ardour/session_state_utils.h"
39 #include "ardour/template_utils.h"
40 #include "ardour/filename_extensions.h"
41
42 #include "ardour_ui.h"
43 #include "startup.h"
44 #include "opts.h"
45 #include "engine_dialog.h"
46 #include "i18n.h"
47 #include "utils.h"
48
49 using namespace std;
50 using namespace Gtk;
51 using namespace Gdk;
52 using namespace Glib;
53 using namespace PBD;
54 using namespace ARDOUR;
55
56 ArdourStartup* ArdourStartup::the_startup = 0;
57
58 static string poor_mans_glob (string path)
59 {
60         string copy = path;
61         replace_all (copy, "~", Glib::get_home_dir());
62         return copy;
63 }
64
65
66 ArdourStartup::ArdourStartup (bool require_new, const std::string& session_name, const std::string& session_path, const std::string& template_name)
67         : _response (RESPONSE_OK)
68         , config_modified (false)
69         , new_only (require_new)
70         , default_dir_chooser (0)
71         , ic_new_session_button (_("Create a new session"))
72         , ic_existing_session_button (_("Open an existing session"))
73         , monitor_via_hardware_button (_("Use an external mixer or the hardware mixer of your audio interface.\n\
74 Ardour will play NO role in monitoring"))
75         , monitor_via_ardour_button (string_compose (_("Ask %1 to play back material as it is being recorded"), PROGRAM_NAME))
76         , engine_dialog (0)
77         , new_folder_chooser (FILE_CHOOSER_ACTION_SELECT_FOLDER)
78         , more_new_session_options_button (_("I'd like more options for this session"))
79         , _output_limit_count_adj (1, 0, 100, 1, 10, 0)
80         , _input_limit_count_adj (1, 0, 100, 1, 10, 0)
81         , _master_bus_channel_count_adj (2, 0, 100, 1, 10, 0)
82         , audio_page_index (-1)
83         , new_user_page_index (-1)
84         , default_folder_page_index (-1)
85         , monitoring_page_index (-1)
86         , session_page_index (-1)
87         , initial_choice_index (-1)
88         , final_page_index (-1)
89         , session_options_page_index (-1)
90         , _existing_session_chooser_used (false)
91 {
92         new_user = !Glib::file_test (been_here_before_path(), Glib::FILE_TEST_EXISTS);
93         need_audio_setup = EngineControl::need_setup ();
94         need_session_info = (session_name.empty() || require_new);
95
96         _provided_session_name = session_name;
97         _provided_session_path = session_path;
98         
99         if (need_audio_setup || need_session_info || new_user) {
100
101                 use_template_button.set_group (session_template_group);
102                 use_session_as_template_button.set_group (session_template_group);
103                 
104                 set_keep_above (true);
105                 set_position (WIN_POS_CENTER);
106                 set_border_width (12);
107                 
108                 if ((icon_pixbuf = ::get_icon ("ardour_icon_48px")) == 0) {
109                         throw failed_constructor();
110                 }
111                 
112                 list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
113                 Glib::RefPtr<Gdk::Pixbuf> icon;
114                 
115                 if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
116                         window_icons.push_back (icon);
117                 }
118                 if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
119                         window_icons.push_back (icon);
120                 }
121                 if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
122                         window_icons.push_back (icon);
123                 }
124                 if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
125                         window_icons.push_back (icon);
126                 }
127                 if (!window_icons.empty ()) {
128                         set_default_icon_list (window_icons);
129                 }
130                 
131                 // setup_prerelease_page ();
132                 
133                 if (new_user) {
134                         
135                         setup_new_user_page ();
136                         setup_first_time_config_page ();
137                         setup_monitoring_choice_page ();
138                         setup_monitor_section_choice_page ();
139                         
140                         if (need_audio_setup) {
141                                 setup_audio_page ();
142                         }
143                         
144                         ic_new_session_button.set_active (true); // always create new session on first run
145                         
146                 } else {
147                         
148                         if (need_audio_setup) {
149                                 setup_audio_page ();
150                         }
151                         
152                         setup_initial_choice_page ();
153                 }
154
155                 setup_session_page ();
156                 setup_more_options_page ();
157                 
158                 if (new_user) {
159                         setup_final_page ();
160                 }
161
162                 if (new_only) {
163                         ic_vbox.hide ();
164                 } else {
165                         ic_vbox.show ();
166                 }
167
168                 if (!template_name.empty()) {
169                         use_template_button.set_active (false);
170                         load_template_override = template_name;
171                 }
172         }
173
174         the_startup = this;
175 }
176
177 ArdourStartup::~ArdourStartup ()
178 {
179 }
180
181 bool
182 ArdourStartup::ready_without_display () const
183 {
184         return !new_user && !need_audio_setup && !need_session_info;
185 }
186
187 void
188 ArdourStartup::setup_prerelease_page ()
189 {
190         VBox* vbox = manage (new VBox);
191         Label* label = manage (new Label);
192         label->set_markup (_("<b>Welcome to this BETA release of Ardour 3.0</b>\n\n\
193 There are still several issues and bugs to be worked on,\n\
194 as well as general workflow improvements, before this can be considered\n\
195 release software. So, a few guidelines:\n\
196 \n\
197 1) Please do <b>NOT</b> use this software with the expectation that it is stable or reliable\n\
198    though it may be so, depending on your workflow.\n\
199 2) Please see http://ardour.org/a3_features for a guide to new features.\n\
200 3) <b>Please do NOT use the forums at ardour.org to report issues</b>.\n\
201 4) Please <b>DO</b> use the bugtracker at http://tracker.ardour.org/ to report issues\n\
202    making sure to note the product version number as 3.0-beta.\n\
203 5) Please <b>DO</b> use the ardour-users mailing list to discuss ideas and pass on comments.\n\
204 6) Please <b>DO</b> join us on IRC for real time discussions about ardour3. You\n\
205    can get there directly from Ardour via the Help->Chat menu option.\n\
206 \n\
207 Full information on all the above can be found on the support page at\n\
208 \n\
209                 http://ardour.org/support\n\
210 "));
211
212         vbox->set_border_width (12);
213         vbox->pack_start (*label, false, false, 12);
214         vbox->show_all ();
215
216         append_page (*vbox);
217         set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
218         set_page_title (*vbox, _("This is a BETA RELEASE"));
219         set_page_complete (*vbox, true);
220 }
221
222 bool
223 ArdourStartup::use_session_template ()
224 {
225         if (!load_template_override.empty()) {
226                 return true;
227         }
228
229         if (use_template_button.get_active()) {
230                 return template_chooser.get_active_row_number() > 0;
231         } else {
232                 return !session_template_chooser.get_filename().empty();
233         }
234 }
235
236 std::string
237 ArdourStartup::session_template_name ()
238 {
239         if (!load_template_override.empty()) {
240                 string the_path (ARDOUR::user_template_directory());
241                 return Glib::build_filename (the_path, load_template_override + ARDOUR::template_suffix);
242         }
243
244         if (ic_existing_session_button.get_active()) {
245                 return string();
246         }
247
248         if (use_template_button.get_active()) {
249                 TreeModel::iterator iter = template_chooser.get_active ();
250                 TreeModel::Row row = (*iter);
251                 string s = row[session_template_columns.path];
252                 return s;
253         } else {
254                 return session_template_chooser.get_filename();
255
256         }
257 }
258
259 std::string
260 ArdourStartup::session_name (bool& should_be_new)
261 {
262         if (ready_without_display()) {
263                 return _provided_session_name;
264         }
265
266         if (ic_new_session_button.get_active()) {
267                 should_be_new = true;
268                 string val = new_name_entry.get_text ();
269                 strip_whitespace_edges (val);
270                 return val;
271         } else if (_existing_session_chooser_used) {
272                 /* existing session chosen from file chooser */
273                 should_be_new = false;
274                 return existing_session_chooser.get_filename ();
275         } else {
276                 /* existing session chosen from recent list */
277                 should_be_new = false;
278
279                 TreeIter iter = recent_session_display.get_selection()->get_selected();
280
281                 if (iter) {
282                         return (*iter)[recent_session_columns.visible_name];
283                 }
284
285                 return "";
286         }
287 }
288
289 std::string
290 ArdourStartup::session_folder ()
291 {
292         if (ready_without_display()) {
293                 return _provided_session_path;
294         }
295
296         if (ic_new_session_button.get_active()) {
297                 std::string legal_session_folder_name = legalize_for_path (new_name_entry.get_text());
298                 return Glib::build_filename (new_folder_chooser.get_current_folder(), legal_session_folder_name);
299         } else if (_existing_session_chooser_used) {
300                 /* existing session chosen from file chooser */
301                 return existing_session_chooser.get_current_folder ();
302         } else {
303                 /* existing session chosen from recent list */
304                 TreeIter iter = recent_session_display.get_selection()->get_selected();
305
306                 if (iter) {
307                         return (*iter)[recent_session_columns.fullpath];
308                 }
309                 return "";
310         }
311 }
312
313 void
314 ArdourStartup::setup_audio_page ()
315 {
316         engine_dialog = manage (new EngineControl);
317
318         engine_dialog->set_border_width (12);
319
320         engine_dialog->show_all ();
321
322         audio_page_index = append_page (*engine_dialog);
323         set_page_type (*engine_dialog, ASSISTANT_PAGE_CONTENT);
324         set_page_title (*engine_dialog, _("Audio / MIDI Setup"));
325
326         /* the default parameters should work, so the page is potentially complete */
327
328         set_page_complete (*engine_dialog, true);
329 }
330
331 void
332 ArdourStartup::setup_new_user_page ()
333 {
334         Label* foomatic = manage (new Label);
335
336         foomatic->set_markup (string_compose (_("\
337 <span size=\"larger\">%1 is a digital audio workstation. You can use it to \
338 record, edit and mix multi-track audio. You can produce your \
339 own CDs, mix video soundtracks, or experiment with new \
340 ideas about music and sound. \
341 \n\n\
342 There are a few things that need to be configured before you start \
343 using the program.</span> \
344 "), PROGRAM_NAME));
345         foomatic->set_justify (JUSTIFY_FILL);
346         foomatic->set_line_wrap ();
347
348         HBox* hbox = manage (new HBox);
349         HBox* vbox = manage (new HBox);
350
351         vbox->set_border_width (24);
352
353         hbox->pack_start (*foomatic, true, true);
354         vbox->pack_start (*hbox, true, true);
355
356         foomatic->show ();
357         hbox->show ();
358         vbox->show ();
359
360         new_user_page_index = append_page (*vbox);
361         set_page_type (*vbox, ASSISTANT_PAGE_INTRO);
362         set_page_title (*vbox, string_compose (_("Welcome to %1"), PROGRAM_NAME));
363         set_page_header_image (*vbox, icon_pixbuf);
364         set_page_complete (*vbox, true);
365 }
366
367 void
368 ArdourStartup::default_dir_changed ()
369 {
370         Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
371         // make new session folder chooser point to the new default
372         new_folder_chooser.set_current_folder (Config->get_default_session_parent_dir());       
373         config_changed ();
374 }
375
376 void
377 ArdourStartup::config_changed ()
378 {
379         config_modified = true;
380 }
381
382 void
383 ArdourStartup::setup_first_time_config_page ()
384 {
385         default_dir_chooser = manage (new FileChooserButton (string_compose (_("Default folder for %1 sessions"), PROGRAM_NAME),
386                                                              FILE_CHOOSER_ACTION_SELECT_FOLDER));
387         Gtk::Label* txt = manage (new Label);
388         HBox* hbox = manage (new HBox);
389         VBox* vbox = manage (new VBox);
390
391         txt->set_markup (string_compose (_("\
392 Each project that you work on with %1 has its own folder.\n\
393 These can require a lot of disk space if you are recording audio.\n\
394 \n\
395 Where would you like new %1 sessions to be stored by default?\n\n\
396 <i>(You can put new sessions anywhere, this is just a default)</i>"), PROGRAM_NAME));
397         txt->set_alignment (0.0, 0.0);
398
399         vbox->set_spacing (18);
400         vbox->set_border_width (24);
401
402         hbox->pack_start (*default_dir_chooser, false, true, 8);
403         vbox->pack_start (*txt, false, false);
404         vbox->pack_start (*hbox, false, true);
405
406         default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
407         default_dir_chooser->signal_current_folder_changed().connect (sigc::mem_fun (*this, &ArdourStartup::default_dir_changed));
408         default_dir_chooser->show ();
409
410         vbox->show_all ();
411
412         default_folder_page_index = append_page (*vbox);
413         set_page_title (*vbox, _("Default folder for new sessions"));
414         set_page_header_image (*vbox, icon_pixbuf);
415         set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
416
417         /* user can just skip all these settings if they want to */
418
419         set_page_complete (*vbox, true);
420 }
421
422 void
423 ArdourStartup::setup_monitoring_choice_page ()
424 {
425         mon_vbox.set_spacing (18);
426         mon_vbox.set_border_width (24);
427
428         HBox* hbox = manage (new HBox);
429         VBox* vbox = manage (new VBox);
430         RadioButton::Group g (monitor_via_hardware_button.get_group());
431         monitor_via_ardour_button.set_group (g);
432
433         monitor_label.set_markup(_("\
434 While recording instruments or vocals, you probably want to listen to the\n\
435 signal as well as record it. This is called \"monitoring\". There are\n\
436 different ways to do this depending on the equipment you have and the\n\
437 configuration of that equipment. The two most common are presented here.\n\
438 Please choose whichever one is right for your setup.\n\n\
439 <i>(You can change this preference at any time, via the Preferences dialog)</i>\n\n\
440 <i>If you do not understand what this is about, just accept the default.</i>"));
441         monitor_label.set_alignment (0.0, 0.0);
442
443         vbox->set_spacing (6);
444
445         vbox->pack_start (monitor_via_hardware_button, false, true);
446         vbox->pack_start (monitor_via_ardour_button, false, true);
447         hbox->pack_start (*vbox, true, true, 8);
448         mon_vbox.pack_start (monitor_label, false, false);
449         mon_vbox.pack_start (*hbox, false, false);
450
451         mon_vbox.show_all ();
452
453         monitoring_page_index = append_page (mon_vbox);
454         set_page_title (mon_vbox, _("Monitoring Choices"));
455         set_page_header_image (mon_vbox, icon_pixbuf);
456
457         /* user could just click on "Forward" if default
458          * choice is correct.
459          */
460
461         set_page_complete (mon_vbox, true);
462 }
463
464 void
465 ArdourStartup::setup_monitor_section_choice_page ()
466 {
467         mon_sec_vbox.set_spacing (18);
468         mon_sec_vbox.set_border_width (24);
469
470         HBox* hbox = manage (new HBox);
471         VBox* main_vbox = manage (new VBox);
472         VBox* vbox;
473         Label* l = manage (new Label);
474
475         main_vbox->set_spacing (32);
476
477         no_monitor_section_button.set_label (_("Use a Master bus directly"));
478         l->set_alignment (0.0, 1.0);
479         l->set_markup(_("Connect the Master bus directly to your hardware outputs. This is preferable for simple usage."));
480
481         vbox = manage (new VBox);
482         vbox->set_spacing (6);
483         vbox->pack_start (no_monitor_section_button, false, true);
484         vbox->pack_start (*l, false, true);
485
486         main_vbox->pack_start (*vbox, false, false);
487
488         use_monitor_section_button.set_label (_("Use an additional Monitor bus"));
489         l = manage (new Label);
490         l->set_alignment (0.0, 1.0);
491         l->set_text (_("Use a Monitor bus between Master bus and hardware outputs for \n\
492 greater control in monitoring without affecting the mix."));
493
494         vbox = manage (new VBox);
495         vbox->set_spacing (6);
496         vbox->pack_start (use_monitor_section_button, false, true);
497         vbox->pack_start (*l, false, true);
498
499         main_vbox->pack_start (*vbox, false, false);
500
501         RadioButton::Group g (use_monitor_section_button.get_group());
502         no_monitor_section_button.set_group (g);
503
504         if (Config->get_use_monitor_bus()) {
505                 use_monitor_section_button.set_active (true);
506         } else {
507                 no_monitor_section_button.set_active (true);
508         }
509
510         use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
511         no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
512
513         monitor_section_label.set_markup(_("<i>You can change this preference at any time via the Preferences dialog.\nYou can also add or remove the monitor section to/from any session.</i>\n\n\
514 <i>If you do not understand what this is about, just accept the default.</i>"));
515         monitor_section_label.set_alignment (0.0, 0.0);
516
517         hbox->pack_start (*main_vbox, true, true, 8);
518         mon_sec_vbox.pack_start (*hbox, false, false);
519         mon_sec_vbox.pack_start (monitor_section_label, false, false);
520
521         mon_sec_vbox.show_all ();
522
523         monitor_section_page_index = append_page (mon_sec_vbox);
524         set_page_title (mon_sec_vbox, _("Monitor Section"));
525         set_page_header_image (mon_sec_vbox, icon_pixbuf);
526
527         /* user could just click on "Forward" if default
528          * choice is correct.
529          */
530
531         set_page_complete (mon_sec_vbox, true);
532 }
533
534 void
535 ArdourStartup::setup_initial_choice_page ()
536 {
537         ic_vbox.set_spacing (6);
538         ic_vbox.set_border_width (24);
539
540         RadioButton::Group g (ic_new_session_button.get_group());
541         ic_existing_session_button.set_group (g);
542
543         HBox* centering_hbox = manage (new HBox);
544         VBox* centering_vbox = manage (new VBox);
545
546         centering_vbox->set_spacing (6);
547
548         centering_vbox->pack_start (ic_new_session_button, false, true);
549         centering_vbox->pack_start (ic_existing_session_button, false, true);
550
551         ic_new_session_button.signal_button_press_event().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_clicked), false);
552         ic_new_session_button.signal_activate().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_activated), false);
553
554         ic_existing_session_button.signal_button_press_event().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_clicked), false);
555         ic_existing_session_button.signal_activate().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_activated), false);
556
557         centering_hbox->pack_start (*centering_vbox, true, true);
558
559         ic_vbox.pack_start (*centering_hbox, true, true);
560
561         ic_vbox.show_all ();
562
563         initial_choice_index = append_page (ic_vbox);
564         set_page_title (ic_vbox, _("What would you like to do ?"));
565         set_page_header_image (ic_vbox, icon_pixbuf);
566
567         /* user could just click on "Forward" if default
568          * choice is correct.
569          */
570
571         set_page_complete (ic_vbox, true);
572 }
573
574 bool
575 ArdourStartup::initial_button_clicked (GdkEventButton* ev)
576 {
577         if (ev->type == GDK_2BUTTON_PRESS && session_page_index != -1) {
578                 set_current_page(session_page_index);
579         }
580
581         return false;
582 }
583
584 void
585 ArdourStartup::initial_button_activated ()
586 {
587         if (session_page_index != -1) {
588                 set_current_page(session_page_index);
589         }
590 }
591
592 void
593 ArdourStartup::setup_session_page ()
594 {
595         session_vbox.set_border_width (24);
596
597         session_vbox.pack_start (session_hbox, true, true);
598         session_vbox.show_all ();
599
600         session_page_index = append_page (session_vbox);
601         /* initial setting */
602         set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
603 }
604
605 void
606 ArdourStartup::setup_final_page ()
607 {
608         final_page.set_text (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
609         final_page.show ();
610         final_page_index = append_page (final_page);
611         set_page_complete (final_page, true);
612         set_page_header_image (final_page, icon_pixbuf);
613         set_page_type (final_page, ASSISTANT_PAGE_CONFIRM);
614 }
615
616 void
617 ArdourStartup::on_cancel ()
618 {
619         _response = RESPONSE_CANCEL;
620         gtk_main_quit ();
621 }
622
623 bool
624 ArdourStartup::on_delete_event (GdkEventAny*)
625 {
626         _response = RESPONSE_CLOSE;
627         gtk_main_quit ();
628         return true;
629 }
630
631 void
632 ArdourStartup::on_apply ()
633 {
634         if (engine_dialog) {
635                 if (engine_dialog->setup_engine ()) {
636                         set_current_page (audio_page_index);
637                         return;
638                 }
639         }
640
641         if (config_modified) {
642
643                 if (default_dir_chooser) {
644                         Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
645                 }
646
647                 if (monitor_via_hardware_button.get_active()) {
648                         Config->set_monitoring_model (ExternalMonitoring);
649                 } else if (monitor_via_ardour_button.get_active()) {
650                         Config->set_monitoring_model (SoftwareMonitoring);
651                 }
652
653                 Config->set_use_monitor_bus (use_monitor_section_button.get_active());
654
655                 /* "touch" the been-here-before path now that we're about to save Config */
656                 ofstream fout (been_here_before_path().c_str());
657                 
658                 Config->save_state ();
659         }
660
661         _response = RESPONSE_OK;
662         gtk_main_quit ();
663 }
664
665 void
666 ArdourStartup::on_prepare (Gtk::Widget* page)
667 {
668         if (page == &session_vbox) {
669
670                 if (ic_new_session_button.get_active()) {
671                         /* new session requested */
672                         setup_new_session_page ();
673                 } else {
674                         /* existing session requested */
675                         setup_existing_session_page ();
676
677                 }
678
679                 /* HACK HACK HACK ... change the "Apply" button label
680                    to say "Open"
681                 */
682
683                 Gtk::Widget* tl = session_vbox.get_toplevel();
684                 Gtk::Window* win;
685                 if ((win = dynamic_cast<Gtk::Window*>(tl)) != 0) {
686                         /* ::get_default_widget() is not wrapped in gtkmm */
687                         Gtk::Widget* def = wrap (gtk_window_get_default_widget (win->gobj()));
688                         Gtk::Button* button;
689                         if ((button = dynamic_cast<Gtk::Button*>(def)) != 0) {
690                                 if (more_new_session_options_button.get_active()) {
691                                         button->set_label (_("Forward"));
692                                 }else{
693                                         button->set_label (_("Open"));
694                                 }
695                         }
696                 }
697         }
698 }
699
700 void
701 ArdourStartup::populate_session_templates ()
702 {
703         vector<TemplateInfo> templates;
704
705         find_session_templates (templates);
706
707         template_model->clear ();
708
709         for (vector<TemplateInfo>::iterator x = templates.begin(); x != templates.end(); ++x) {
710                 TreeModel::Row row;
711
712                 row = *(template_model->append ());
713
714                 row[session_template_columns.name] = (*x).name;
715                 row[session_template_columns.path] = (*x).path;
716         }
717 }
718
719 static bool
720 lost_name_entry_focus (GdkEventFocus*)
721 {
722         // cerr << "lost focus\n";
723         return false;
724 }
725
726 void
727 ArdourStartup::setup_new_session_page ()
728 {
729         if (!session_hbox.get_children().empty()) {
730                 session_hbox.remove (**session_hbox.get_children().begin());
731         }
732
733         session_new_vbox.set_spacing (18);
734
735         if (session_new_vbox.get_children().empty()) {
736                 VBox *vbox1 = manage (new VBox);
737                 HBox* hbox1 = manage (new HBox);
738                 Label* label1 = manage (new Label);
739
740                 vbox1->set_spacing (6);
741
742                 hbox1->set_spacing (6);
743                 hbox1->pack_start (*label1, false, false);
744                 hbox1->pack_start (new_name_entry, true, true);
745
746                 label1->set_text (_("Session name:"));
747
748
749                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
750                         new_name_entry.set_text  (Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name));
751                         /* name provided - they can move right along */
752                         set_page_complete (session_vbox, true);
753                 }
754
755                 new_name_entry.signal_changed().connect (sigc::mem_fun (*this, &ArdourStartup::new_name_changed));
756                 new_name_entry.signal_activate().connect (sigc::mem_fun (*this, &ArdourStartup::move_along_now));
757
758                 vbox1->pack_start (*hbox1, true, true);
759
760                 /* --- */
761
762                 HBox* hbox2 = manage (new HBox);
763                 Label* label2 = manage (new Label);
764
765                 hbox2->set_spacing (6);
766                 hbox2->pack_start (*label2, false, false);
767                 hbox2->pack_start (new_folder_chooser, true, true);
768
769                 label2->set_text (_("Create session folder in:"));
770
771                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
772                         new_folder_chooser.set_current_folder (poor_mans_glob (Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name)));
773                 } else if (ARDOUR_UI::instance()->session_loaded) {
774                         // point the new session file chooser at the parent directory of the current session
775                         string session_parent_dir = Glib::path_get_dirname(ARDOUR_UI::instance()->the_session()->path());
776                         string::size_type last_dir_sep = session_parent_dir.rfind(G_DIR_SEPARATOR);
777                         session_parent_dir = session_parent_dir.substr(0, last_dir_sep);
778                         new_folder_chooser.set_current_folder (session_parent_dir);
779                         new_folder_chooser.add_shortcut_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
780                 } else {
781                         new_folder_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
782                 }
783                 new_folder_chooser.set_title (_("Select folder for session"));
784
785 #ifdef GTKOSX
786                 new_folder_chooser.add_shortcut_folder ("/Volumes");
787 #endif
788
789                 vbox1->pack_start (*hbox2, false, false);
790
791                 session_new_vbox.pack_start (*vbox1, false, false);
792
793                 /* --- */
794
795                 VBox *vbox2 = manage (new VBox);
796                 HBox* hbox3 = manage (new HBox);
797                 Label* label3 = manage (new Label);
798                 template_model = ListStore::create (session_template_columns);
799                 populate_session_templates ();
800
801                 vbox2->set_spacing (6);
802
803                 label3->set_markup (_("<b>Options</b>"));
804                 label3->set_alignment (0.0, 0.0);
805
806                 vbox2->pack_start (*label3, false, true);
807
808                 VBox *vbox3 = manage (new VBox);
809
810                 vbox3->set_spacing (6);
811
812                 if (!template_model->children().empty()) {
813
814                         HBox* hbox4a = manage (new HBox);
815                         use_template_button.set_label (_("Use this template"));
816
817                         TreeModel::Row row = *template_model->prepend ();
818                         row[session_template_columns.name] = (_("no template"));
819                         row[session_template_columns.path] = string();
820
821                         hbox4a->set_spacing (6);
822                         hbox4a->pack_start (use_template_button, false, false);
823                         hbox4a->pack_start (template_chooser, true, true);
824
825                         template_chooser.set_model (template_model);
826
827                         Gtk::CellRendererText* text_renderer = Gtk::manage (new Gtk::CellRendererText);
828                         text_renderer->property_editable() = false;
829
830                         template_chooser.pack_start (*text_renderer);
831                         template_chooser.add_attribute (text_renderer->property_text(), session_template_columns.name);
832                         template_chooser.set_active (0);
833
834                         use_template_button.show();
835                         template_chooser.show ();
836
837                         vbox3->pack_start (*hbox4a, false, false);
838                 }
839
840                 /* --- */
841
842                 if (!new_user) {
843                         session_template_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
844
845                         HBox* hbox4b = manage (new HBox);
846                         use_session_as_template_button.set_label (_("Use an existing session as a template:"));
847
848                         hbox4b->set_spacing (6);
849                         hbox4b->pack_start (use_session_as_template_button, false, false);
850                         hbox4b->pack_start (session_template_chooser, true, true);
851
852                         use_session_as_template_button.show ();
853                         session_template_chooser.show ();
854
855                         Gtk::FileFilter* session_filter = manage (new (Gtk::FileFilter));
856                         session_filter->add_pattern (X_("*.ardour"));
857                         session_template_chooser.set_filter (*session_filter);
858                         session_template_chooser.set_title (_("Select template"));
859
860                         vbox3->pack_start (*hbox4b, false, false);
861                 }
862
863                 /* --- */
864
865                 HBox* hbox5 = manage (new HBox);
866
867                 hbox5->set_spacing (6);
868                 hbox5->pack_start (more_new_session_options_button, false, false);
869
870                 more_new_session_options_button.show ();
871                 more_new_session_options_button.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::more_new_session_options_button_clicked));
872
873                 vbox3->pack_start (*hbox5, false, false);
874                 hbox3->pack_start (*vbox3, true, true, 8);
875                 vbox2->pack_start (*hbox3, false, false);
876
877                 /* --- */
878
879                 session_new_vbox.pack_start (*vbox2, false, false);
880         }
881
882         session_new_vbox.show_all ();
883         session_hbox.pack_start (session_new_vbox, true, true);
884         set_page_title (session_vbox, _("New Session"));
885         set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
886
887         if (more_new_session_options_button.get_active()) {
888                 set_page_type (session_vbox, ASSISTANT_PAGE_CONTENT);
889         }
890
891         new_name_entry.signal_map().connect (sigc::mem_fun (*this, &ArdourStartup::new_name_mapped));
892         new_name_entry.signal_focus_out_event().connect (sigc::ptr_fun (lost_name_entry_focus));
893 }
894
895 void
896 ArdourStartup::new_name_mapped ()
897 {
898         // cerr << "Grab new name focus\n";
899         new_name_entry.grab_focus ();
900 }
901
902 void
903 ArdourStartup::new_name_changed ()
904 {
905         if (!new_name_entry.get_text().empty()) {
906                 set_page_complete (session_vbox, true);
907         } else {
908                 set_page_complete (session_vbox, false);
909         }
910 }
911
912 int
913 ArdourStartup::redisplay_recent_sessions ()
914 {
915         std::vector<std::string> session_directories;
916         RecentSessionsSorter cmp;
917
918         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
919         recent_session_model->clear ();
920
921         ARDOUR::RecentSessions rs;
922         ARDOUR::read_recent_sessions (rs);
923
924         if (rs.empty()) {
925                 recent_session_display.set_model (recent_session_model);
926                 return 0;
927         }
928         //
929         // sort them alphabetically
930         sort (rs.begin(), rs.end(), cmp);
931
932         for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
933                 session_directories.push_back ((*i).second);
934         }
935         
936         int session_snapshot_count = 0;
937
938         for (vector<std::string>::const_iterator i = session_directories.begin(); i != session_directories.end(); ++i)
939         {
940                 std::vector<std::string> state_file_paths;
941
942                 // now get available states for this session
943
944                 get_state_files_in_directory (*i, state_file_paths);
945
946                 vector<string*>* states;
947                 vector<const gchar*> item;
948                 string fullpath = *i;
949
950                 /* remove any trailing / */
951
952                 if (fullpath[fullpath.length()-1] == '/') {
953                         fullpath = fullpath.substr (0, fullpath.length()-1);
954                 }
955
956                 /* check whether session still exists */
957                 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
958                         /* session doesn't exist */
959                         continue;
960                 }
961
962                 /* now get available states for this session */
963
964                 if ((states = Session::possible_states (fullpath)) == 0) {
965                         /* no state file? */
966                         continue;
967                 }
968
969                 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
970
971                 Gtk::TreeModel::Row row = *(recent_session_model->append());
972
973                 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
974                 row[recent_session_columns.fullpath] = fullpath;
975                 
976                 ++session_snapshot_count;
977
978                 if (state_file_names.size() > 1) {
979
980                         // add the children
981
982                         for (std::vector<std::string>::iterator i2 = state_file_names.begin();
983                                         i2 != state_file_names.end(); ++i2)
984                         {
985
986                                 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
987
988                                 child_row[recent_session_columns.visible_name] = *i2;
989                                 child_row[recent_session_columns.fullpath] = fullpath;
990                                 ++session_snapshot_count;
991                         }
992                 }
993         }
994
995         recent_session_display.set_tooltip_column(1); // recent_session_columns.fullpath 
996         recent_session_display.set_model (recent_session_model);
997         return session_snapshot_count;
998         // return rs.size();
999 }
1000
1001 void
1002 ArdourStartup::recent_session_row_selected ()
1003 {
1004         if (recent_session_display.get_selection()->count_selected_rows() > 0) {
1005                 set_page_complete (session_vbox, true);
1006         } else {
1007                 set_page_complete (session_vbox, false);
1008         }
1009 }
1010
1011 void
1012 ArdourStartup::setup_existing_session_page ()
1013 {
1014         recent_session_model = TreeStore::create (recent_session_columns);
1015         redisplay_recent_sessions ();
1016
1017         if (!session_hbox.get_children().empty()) {
1018                 session_hbox.remove (**session_hbox.get_children().begin());
1019         }
1020
1021         if (session_existing_vbox.get_children().empty()) {
1022
1023                 recent_session_display.set_model (recent_session_model);
1024                 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1025                 recent_session_display.set_headers_visible (false);
1026                 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1027
1028                 recent_session_display.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ArdourStartup::recent_session_row_selected));
1029
1030                 recent_scroller.add (recent_session_display);
1031                 recent_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1032                 recent_scroller.set_shadow_type (Gtk::SHADOW_IN);
1033
1034                 recent_session_display.show();
1035
1036                 recent_scroller.show();
1037                 int cnt = redisplay_recent_sessions ();
1038                 recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &ArdourStartup::recent_row_activated));
1039
1040                 if (cnt > 4) {
1041                         recent_scroller.set_size_request (-1, 300);
1042                 }
1043
1044                 session_existing_vbox.set_spacing (8);
1045                 session_existing_vbox.pack_start (recent_scroller, true, true);
1046
1047                 existing_session_chooser.set_title (_("Select session file"));
1048                 existing_session_chooser.signal_file_set().connect (sigc::mem_fun (*this, &ArdourStartup::existing_session_selected));
1049                 existing_session_chooser.set_current_folder(poor_mans_glob (Config->get_default_session_parent_dir()));
1050
1051                 FileFilter session_filter;
1052                 session_filter.add_pattern ("*.ardour");
1053                 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1054                 existing_session_chooser.add_filter (session_filter);
1055                 existing_session_chooser.set_filter (session_filter);
1056                 
1057 #ifdef GTKOSX
1058                 existing_session_chooser.add_shortcut_folder ("/Volumes");
1059 #endif
1060
1061                 HBox* hbox = manage (new HBox);
1062                 hbox->set_spacing (4);
1063                 hbox->pack_start (*manage (new Label (_("Browse:"))), PACK_SHRINK);
1064                 hbox->pack_start (existing_session_chooser);
1065                 session_existing_vbox.pack_start (*hbox, false, false);
1066                 hbox->show_all ();
1067         }
1068
1069         session_existing_vbox.show_all ();
1070         session_hbox.pack_start (session_existing_vbox, true, true);
1071
1072         set_page_title (session_vbox, _("Select a session"));
1073         set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
1074 }
1075
1076 void
1077 ArdourStartup::more_new_session_options_button_clicked ()
1078 {
1079         if (more_new_session_options_button.get_active()) {
1080                 more_options_vbox.show_all ();
1081                 set_page_type (more_options_vbox, ASSISTANT_PAGE_CONFIRM);
1082                 set_page_type (session_vbox, ASSISTANT_PAGE_CONTENT);
1083         } else {
1084                 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
1085                 more_options_vbox.hide ();
1086         }
1087 }
1088
1089 void
1090 ArdourStartup::setup_more_options_page ()
1091 {
1092         more_options_vbox.set_border_width (24);
1093
1094         _output_limit_count.set_adjustment (_output_limit_count_adj);
1095         _input_limit_count.set_adjustment (_input_limit_count_adj);
1096         _master_bus_channel_count.set_adjustment (_master_bus_channel_count_adj);
1097
1098         chan_count_label_1.set_text (_("channels"));
1099         chan_count_label_3.set_text (_("channels"));
1100         chan_count_label_4.set_text (_("channels"));
1101
1102         chan_count_label_1.set_alignment(0,0.5);
1103         chan_count_label_1.set_padding(0,0);
1104         chan_count_label_1.set_line_wrap(false);
1105
1106         chan_count_label_3.set_alignment(0,0.5);
1107         chan_count_label_3.set_padding(0,0);
1108         chan_count_label_3.set_line_wrap(false);
1109
1110         chan_count_label_4.set_alignment(0,0.5);
1111         chan_count_label_4.set_padding(0,0);
1112         chan_count_label_4.set_line_wrap(false);
1113
1114         bus_label.set_markup (_("<b>Busses</b>"));
1115         input_label.set_markup (_("<b>Inputs</b>"));
1116         output_label.set_markup (_("<b>Outputs</b>"));
1117
1118         _master_bus_channel_count.set_flags(Gtk::CAN_FOCUS);
1119         _master_bus_channel_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1120         _master_bus_channel_count.set_numeric(true);
1121         _master_bus_channel_count.set_digits(0);
1122         _master_bus_channel_count.set_wrap(false);
1123
1124         _create_master_bus.set_label (_("Create master bus"));
1125         _create_master_bus.set_flags(Gtk::CAN_FOCUS);
1126         _create_master_bus.set_relief(Gtk::RELIEF_NORMAL);
1127         _create_master_bus.set_mode(true);
1128         _create_master_bus.set_active(true);
1129         _create_master_bus.set_border_width(0);
1130
1131         advanced_table.set_row_spacings(0);
1132         advanced_table.set_col_spacings(0);
1133
1134         _connect_inputs.set_label (_("Automatically connect to physical inputs"));
1135         _connect_inputs.set_flags(Gtk::CAN_FOCUS);
1136         _connect_inputs.set_relief(Gtk::RELIEF_NORMAL);
1137         _connect_inputs.set_mode(true);
1138         _connect_inputs.set_active(Config->get_input_auto_connect() != ManualConnect);
1139         _connect_inputs.set_border_width(0);
1140
1141         _limit_input_ports.set_label (_("Use only"));
1142         _limit_input_ports.set_flags(Gtk::CAN_FOCUS);
1143         _limit_input_ports.set_relief(Gtk::RELIEF_NORMAL);
1144         _limit_input_ports.set_mode(true);
1145         _limit_input_ports.set_sensitive(true);
1146         _limit_input_ports.set_border_width(0);
1147
1148         _input_limit_count.set_flags(Gtk::CAN_FOCUS);
1149         _input_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1150         _input_limit_count.set_numeric(true);
1151         _input_limit_count.set_digits(0);
1152         _input_limit_count.set_wrap(false);
1153         _input_limit_count.set_sensitive(false);
1154
1155         bus_hbox.pack_start (bus_table, Gtk::PACK_SHRINK, 18);
1156
1157         bus_label.set_alignment(0, 0.5);
1158         bus_label.set_padding(0,0);
1159         bus_label.set_line_wrap(false);
1160         bus_label.set_selectable(false);
1161         bus_label.set_use_markup(true);
1162         bus_frame.set_shadow_type(Gtk::SHADOW_NONE);
1163         bus_frame.set_label_align(0,0.5);
1164         bus_frame.add(bus_hbox);
1165         bus_frame.set_label_widget(bus_label);
1166
1167         bus_table.set_row_spacings (0);
1168         bus_table.set_col_spacings (0);
1169         bus_table.attach (_create_master_bus, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
1170         bus_table.attach (_master_bus_channel_count, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
1171         bus_table.attach (chan_count_label_1, 2, 3, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 0);
1172
1173         input_port_limit_hbox.pack_start(_limit_input_ports, Gtk::PACK_SHRINK, 6);
1174         input_port_limit_hbox.pack_start(_input_limit_count, Gtk::PACK_SHRINK, 0);
1175         input_port_limit_hbox.pack_start(chan_count_label_3, Gtk::PACK_SHRINK, 6);
1176         input_port_vbox.pack_start(_connect_inputs, Gtk::PACK_SHRINK, 0);
1177         input_port_vbox.pack_start(input_port_limit_hbox, Gtk::PACK_EXPAND_PADDING, 0);
1178         input_table.set_row_spacings(0);
1179         input_table.set_col_spacings(0);
1180         input_table.attach(input_port_vbox, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 6);
1181
1182         input_hbox.pack_start (input_table, Gtk::PACK_SHRINK, 18);
1183
1184         input_label.set_alignment(0, 0.5);
1185         input_label.set_padding(0,0);
1186         input_label.set_line_wrap(false);
1187         input_label.set_selectable(false);
1188         input_label.set_use_markup(true);
1189         input_frame.set_shadow_type(Gtk::SHADOW_NONE);
1190         input_frame.set_label_align(0,0.5);
1191         input_frame.add(input_hbox);
1192         input_frame.set_label_widget(input_label);
1193
1194         _connect_outputs.set_label (_("Automatically connect outputs"));
1195         _connect_outputs.set_flags(Gtk::CAN_FOCUS);
1196         _connect_outputs.set_relief(Gtk::RELIEF_NORMAL);
1197         _connect_outputs.set_mode(true);
1198         _connect_outputs.set_active(Config->get_output_auto_connect() != ManualConnect);
1199         _connect_outputs.set_border_width(0);
1200         _limit_output_ports.set_label (_("Use only"));
1201         _limit_output_ports.set_flags(Gtk::CAN_FOCUS);
1202         _limit_output_ports.set_relief(Gtk::RELIEF_NORMAL);
1203         _limit_output_ports.set_mode(true);
1204         _limit_output_ports.set_sensitive(true);
1205         _limit_output_ports.set_border_width(0);
1206         _output_limit_count.set_flags(Gtk::CAN_FOCUS);
1207         _output_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1208         _output_limit_count.set_numeric(false);
1209         _output_limit_count.set_digits(0);
1210         _output_limit_count.set_wrap(false);
1211         _output_limit_count.set_sensitive(false);
1212         output_port_limit_hbox.pack_start(_limit_output_ports, Gtk::PACK_SHRINK, 6);
1213         output_port_limit_hbox.pack_start(_output_limit_count, Gtk::PACK_SHRINK, 0);
1214         output_port_limit_hbox.pack_start(chan_count_label_4, Gtk::PACK_SHRINK, 6);
1215
1216         _connect_outputs_to_master.set_label (_("... to master bus"));
1217         _connect_outputs_to_master.set_flags(Gtk::CAN_FOCUS);
1218         _connect_outputs_to_master.set_relief(Gtk::RELIEF_NORMAL);
1219         _connect_outputs_to_master.set_mode(true);
1220         _connect_outputs_to_master.set_active(Config->get_output_auto_connect() == AutoConnectMaster);
1221         _connect_outputs_to_master.set_border_width(0);
1222
1223         _connect_outputs_to_master.set_group (connect_outputs_group);
1224         _connect_outputs_to_physical.set_group (connect_outputs_group);
1225
1226         _connect_outputs_to_physical.set_label (_("... to physical outputs"));
1227         _connect_outputs_to_physical.set_flags(Gtk::CAN_FOCUS);
1228         _connect_outputs_to_physical.set_relief(Gtk::RELIEF_NORMAL);
1229         _connect_outputs_to_physical.set_mode(true);
1230         _connect_outputs_to_physical.set_active(Config->get_output_auto_connect() == AutoConnectPhysical);
1231         _connect_outputs_to_physical.set_border_width(0);
1232
1233         output_conn_vbox.pack_start(_connect_outputs, Gtk::PACK_SHRINK, 0);
1234         output_conn_vbox.pack_start(_connect_outputs_to_master, Gtk::PACK_SHRINK, 0);
1235         output_conn_vbox.pack_start(_connect_outputs_to_physical, Gtk::PACK_SHRINK, 0);
1236         output_vbox.set_border_width(6);
1237
1238         output_port_vbox.pack_start(output_port_limit_hbox, Gtk::PACK_SHRINK, 0);
1239
1240         output_vbox.pack_start(output_conn_vbox);
1241         output_vbox.pack_start(output_port_vbox);
1242
1243         output_label.set_alignment(0, 0.5);
1244         output_label.set_padding(0,0);
1245         output_label.set_line_wrap(false);
1246         output_label.set_selectable(false);
1247         output_label.set_use_markup(true);
1248         output_frame.set_shadow_type(Gtk::SHADOW_NONE);
1249         output_frame.set_label_align(0,0.5);
1250
1251         output_hbox.pack_start (output_vbox, Gtk::PACK_SHRINK, 18);
1252
1253         output_frame.add(output_hbox);
1254         output_frame.set_label_widget(output_label);
1255
1256         more_options_vbox.pack_start(advanced_table, Gtk::PACK_SHRINK, 0);
1257         more_options_vbox.pack_start(bus_frame, Gtk::PACK_SHRINK, 6);
1258         more_options_vbox.pack_start(input_frame, Gtk::PACK_SHRINK, 6);
1259         more_options_vbox.pack_start(output_frame, Gtk::PACK_SHRINK, 0);
1260
1261         /* signals */
1262
1263         _connect_inputs.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::connect_inputs_clicked));
1264         _connect_outputs.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::connect_outputs_clicked));
1265         _limit_input_ports.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::limit_inputs_clicked));
1266         _limit_output_ports.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::limit_outputs_clicked));
1267         _create_master_bus.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::master_bus_button_clicked));
1268
1269         /* note that more_options_vbox is "visible" by default even
1270          * though it may not be displayed to the user, this is so the dialog
1271          * doesn't resize.
1272          */
1273         more_options_vbox.show_all ();
1274
1275         session_options_page_index = append_page (more_options_vbox);
1276         set_page_title (more_options_vbox, _("Advanced Session Options"));
1277         set_page_complete (more_options_vbox, true);
1278 }
1279
1280 bool
1281 ArdourStartup::create_master_bus() const
1282 {
1283         return _create_master_bus.get_active();
1284 }
1285
1286 int
1287 ArdourStartup::master_channel_count() const
1288 {
1289         return _master_bus_channel_count.get_value_as_int();
1290 }
1291
1292 bool
1293 ArdourStartup::connect_inputs() const
1294 {
1295         return _connect_inputs.get_active();
1296 }
1297
1298 bool
1299 ArdourStartup::limit_inputs_used_for_connection() const
1300 {
1301         return _limit_input_ports.get_active();
1302 }
1303
1304 int
1305 ArdourStartup::input_limit_count() const
1306 {
1307         return _input_limit_count.get_value_as_int();
1308 }
1309
1310 bool
1311 ArdourStartup::connect_outputs() const
1312 {
1313         return _connect_outputs.get_active();
1314 }
1315
1316 bool
1317 ArdourStartup::limit_outputs_used_for_connection() const
1318 {
1319         return _limit_output_ports.get_active();
1320 }
1321
1322 int
1323 ArdourStartup::output_limit_count() const
1324 {
1325         return _output_limit_count.get_value_as_int();
1326 }
1327
1328 bool
1329 ArdourStartup::connect_outs_to_master() const
1330 {
1331         return _connect_outputs_to_master.get_active();
1332 }
1333
1334 bool
1335 ArdourStartup::connect_outs_to_physical() const
1336 {
1337         return _connect_outputs_to_physical.get_active();
1338 }
1339
1340 void
1341 ArdourStartup::connect_inputs_clicked ()
1342 {
1343         _limit_input_ports.set_sensitive(_connect_inputs.get_active());
1344
1345         if (_connect_inputs.get_active() && _limit_input_ports.get_active()) {
1346                 _input_limit_count.set_sensitive(true);
1347         } else {
1348                 _input_limit_count.set_sensitive(false);
1349         }
1350 }
1351
1352 void
1353 ArdourStartup::connect_outputs_clicked ()
1354 {
1355         bool const co = _connect_outputs.get_active ();
1356         _limit_output_ports.set_sensitive(co);
1357         _connect_outputs_to_master.set_sensitive(co);
1358         _connect_outputs_to_physical.set_sensitive(co);
1359
1360         if (co && _limit_output_ports.get_active()) {
1361                 _output_limit_count.set_sensitive(true);
1362         } else {
1363                 _output_limit_count.set_sensitive(false);
1364         }
1365 }
1366
1367 void
1368 ArdourStartup::limit_inputs_clicked ()
1369 {
1370         _input_limit_count.set_sensitive(_limit_input_ports.get_active());
1371 }
1372
1373 void
1374 ArdourStartup::limit_outputs_clicked ()
1375 {
1376         _output_limit_count.set_sensitive(_limit_output_ports.get_active());
1377 }
1378
1379 void
1380 ArdourStartup::master_bus_button_clicked ()
1381 {
1382         bool const yn = _create_master_bus.get_active();
1383
1384         _master_bus_channel_count.set_sensitive(yn);
1385         _connect_outputs_to_master.set_sensitive(yn);
1386 }
1387
1388 void
1389 ArdourStartup::move_along_now ()
1390 {
1391         gint cur = get_current_page ();
1392
1393         if (cur == session_page_index) {
1394                 if (more_new_session_options_button.get_active()) {
1395                         set_current_page (session_options_page_index);
1396                 } else {
1397                         on_apply ();
1398                 }
1399         }
1400 }
1401
1402 void
1403 ArdourStartup::recent_row_activated (const Gtk::TreePath&, Gtk::TreeViewColumn*)
1404 {
1405         set_page_complete (session_vbox, true);
1406         move_along_now ();
1407 }
1408
1409 void
1410 ArdourStartup::existing_session_selected ()
1411 {
1412         _existing_session_chooser_used = true;
1413
1414         set_page_complete (session_vbox, true);
1415         move_along_now ();
1416 }
1417
1418 std::string
1419 ArdourStartup::been_here_before_path () const
1420 {
1421         // XXXX use more specific version so we can catch upgrades
1422         return Glib::build_filename (user_config_directory (), ".a3");
1423 }