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