Wrap calls to add_shortcut_folder() in try { ... } block.
[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 #include "pbd/openuri.h"
36
37 #include "ardour/filesystem_paths.h"
38 #include "ardour/recent_sessions.h"
39 #include "ardour/session.h"
40 #include "ardour/session_state_utils.h"
41 #include "ardour/template_utils.h"
42 #include "ardour/filename_extensions.h"
43
44 #include "ardour_ui.h"
45 #include "startup.h"
46 #include "opts.h"
47 #include "engine_dialog.h"
48 #include "i18n.h"
49 #include "utils.h"
50
51 using namespace std;
52 using namespace Gtk;
53 using namespace Gdk;
54 using namespace Glib;
55 using namespace PBD;
56 using namespace ARDOUR;
57
58 ArdourStartup* ArdourStartup::the_startup = 0;
59
60 static string poor_mans_glob (string path)
61 {
62         string copy = path;
63         replace_all (copy, "~", Glib::get_home_dir());
64         return copy;
65 }
66
67 ArdourStartup::ArdourStartup (bool require_new, const std::string& session_name, const std::string& session_path, const std::string& template_name)
68         : _response (RESPONSE_OK)
69         , config_modified (false)
70         , new_only (require_new)
71         , default_dir_chooser (0)
72         , ic_new_session_button (_("Create a new session"))
73         , ic_existing_session_button (_("Open an existing session"))
74         , monitor_via_hardware_button (string_compose (_("Use an external mixer or the hardware mixer of your audio interface.\n"
75                                                          "%1 will play NO role in monitoring"), PROGRAM_NAME))
76         , monitor_via_ardour_button (string_compose (_("Ask %1 to play back material as it is being recorded"), PROGRAM_NAME))
77         , engine_dialog (0)
78         , new_folder_chooser (FILE_CHOOSER_ACTION_SELECT_FOLDER)
79         , more_new_session_options_button (_("I'd like more options for this session"))
80         , _output_limit_count_adj (1, 0, 100, 1, 10, 0)
81         , _input_limit_count_adj (1, 0, 100, 1, 10, 0)
82         , _master_bus_channel_count_adj (2, 0, 100, 1, 10, 0)
83         , audio_page_index (-1)
84         , new_user_page_index (-1)
85         , default_folder_page_index (-1)
86         , monitoring_page_index (-1)
87         , session_page_index (-1)
88         , initial_choice_index (-1)
89         , final_page_index (-1)
90         , session_options_page_index (-1)
91         , _existing_session_chooser_used (false)
92 {
93         new_user = !Glib::file_test (been_here_before_path(), Glib::FILE_TEST_EXISTS);
94         need_audio_setup = EngineControl::need_setup ();
95         need_session_info = (session_name.empty() || require_new);
96
97         _provided_session_name = session_name;
98         _provided_session_path = session_path;
99         
100         if (need_audio_setup || need_session_info || new_user) {
101
102                 use_template_button.set_group (session_template_group);
103                 use_session_as_template_button.set_group (session_template_group);
104                 
105                 set_keep_above (true);
106                 set_position (WIN_POS_CENTER);
107                 set_border_width (12);
108                 
109                 if ((icon_pixbuf = ::get_icon ("ardour_icon_48px")) == 0) {
110                         throw failed_constructor();
111                 }
112                 
113                 list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
114                 Glib::RefPtr<Gdk::Pixbuf> icon;
115                 
116                 if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
117                         window_icons.push_back (icon);
118                 }
119                 if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
120                         window_icons.push_back (icon);
121                 }
122                 if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
123                         window_icons.push_back (icon);
124                 }
125                 if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
126                         window_icons.push_back (icon);
127                 }
128                 if (!window_icons.empty ()) {
129                         set_default_icon_list (window_icons);
130                 }
131
132 #ifdef __APPLE__
133                 setup_prerelease_page ();
134 #endif
135                 if (new_user) {
136                         
137                         setup_new_user_page ();
138                         setup_first_time_config_page ();
139                         setup_monitoring_choice_page ();
140                         setup_monitor_section_choice_page ();
141                         
142                         if (need_audio_setup) {
143                                 setup_audio_page ();
144                         }
145                         
146                         ic_new_session_button.set_active (true); // always create new session on first run
147                         
148                 } else {
149                         
150                         if (need_audio_setup) {
151                                 setup_audio_page ();
152                         }
153                         
154                         setup_initial_choice_page ();
155                 }
156
157                 setup_session_page ();
158                 setup_more_options_page ();
159                 
160                 if (new_user) {
161                         setup_final_page ();
162                 }
163
164                 if (new_only) {
165                         ic_vbox.hide ();
166                 } else {
167                         ic_vbox.show ();
168                 }
169
170                 if (!template_name.empty()) {
171                         use_template_button.set_active (false);
172                         load_template_override = template_name;
173                 }
174         }
175
176         the_startup = this;
177 }
178
179 ArdourStartup::~ArdourStartup ()
180 {
181 }
182
183 bool
184 ArdourStartup::ready_without_display () const
185 {
186         return !new_user && !need_audio_setup && !need_session_info;
187 }
188
189 void
190 ArdourStartup::setup_prerelease_page ()
191 {
192         VBox* vbox = manage (new VBox);
193         Label* label = manage (new Label);
194         label->set_markup (string_compose (_("<b>Welcome to this BETA release of Ardour %1</b>\n\n\
195 Ardour %1 has been released for Linux but because of the lack of testers,\n\
196 it is still at the beta stage on OS X. So, a few guidelines:\n\
197 \n\
198 1) Please do <b>NOT</b> use this software with the expectation that it is stable or reliable\n\
199    though it may be so, depending on your workflow.\n\
200 2) <b>Please do NOT use the forums at ardour.org to report issues</b>.\n\
201 3) 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 %1-beta.\n\
203 4) Please <b>DO</b> use the ardour-users mailing list to discuss ideas and pass on comments.\n\
204 5) 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 "), VERSIONSTRING));
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         cerr << "Setting defaultDIR session dir to [" << Config->get_default_session_parent_dir() << "]\n";
407
408         default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
409         default_dir_chooser->signal_current_folder_changed().connect (sigc::mem_fun (*this, &ArdourStartup::default_dir_changed));
410         default_dir_chooser->show ();
411
412         vbox->show_all ();
413
414         default_folder_page_index = append_page (*vbox);
415         set_page_title (*vbox, _("Default folder for new sessions"));
416         set_page_header_image (*vbox, icon_pixbuf);
417         set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
418
419         /* user can just skip all these settings if they want to */
420
421         set_page_complete (*vbox, true);
422 }
423
424 void
425 ArdourStartup::setup_monitoring_choice_page ()
426 {
427         mon_vbox.set_spacing (18);
428         mon_vbox.set_border_width (24);
429
430         HBox* hbox = manage (new HBox);
431         VBox* vbox = manage (new VBox);
432         /* first button will be on by default */
433         RadioButton::Group g (monitor_via_ardour_button.get_group());
434         monitor_via_hardware_button.set_group (g);
435
436         monitor_label.set_markup(_("\
437 While recording instruments or vocals, you probably want to listen to the\n\
438 signal as well as record it. This is called \"monitoring\". There are\n\
439 different ways to do this depending on the equipment you have and the\n\
440 configuration of that equipment. The two most common are presented here.\n\
441 Please choose whichever one is right for your setup.\n\n\
442 <i>(You can change this preference at any time, via the Preferences dialog)</i>\n\n\
443 <i>If you do not understand what this is about, just accept the default.</i>"));
444         monitor_label.set_alignment (0.0, 0.0);
445
446         vbox->set_spacing (6);
447
448         vbox->pack_start (monitor_via_hardware_button, false, true);
449         vbox->pack_start (monitor_via_ardour_button, false, true);
450         hbox->pack_start (*vbox, true, true, 8);
451         mon_vbox.pack_start (monitor_label, false, false);
452         mon_vbox.pack_start (*hbox, false, false);
453
454         mon_vbox.show_all ();
455
456         monitoring_page_index = append_page (mon_vbox);
457         set_page_title (mon_vbox, _("Monitoring Choices"));
458         set_page_header_image (mon_vbox, icon_pixbuf);
459
460         /* user could just click on "Forward" if default
461          * choice is correct.
462          */
463
464         set_page_complete (mon_vbox, true);
465 }
466
467 void
468 ArdourStartup::setup_monitor_section_choice_page ()
469 {
470         mon_sec_vbox.set_spacing (18);
471         mon_sec_vbox.set_border_width (24);
472
473         HBox* hbox = manage (new HBox);
474         VBox* main_vbox = manage (new VBox);
475         VBox* vbox;
476         Label* l = manage (new Label);
477
478         main_vbox->set_spacing (32);
479
480         no_monitor_section_button.set_label (_("Use a Master bus directly"));
481         l->set_alignment (0.0, 1.0);
482         l->set_markup(_("Connect the Master bus directly to your hardware outputs. This is preferable for simple usage."));
483
484         vbox = manage (new VBox);
485         vbox->set_spacing (6);
486         vbox->pack_start (no_monitor_section_button, false, true);
487         vbox->pack_start (*l, false, true);
488
489         main_vbox->pack_start (*vbox, false, false);
490
491         use_monitor_section_button.set_label (_("Use an additional Monitor bus"));
492         l = manage (new Label);
493         l->set_alignment (0.0, 1.0);
494         l->set_text (_("Use a Monitor bus between Master bus and hardware outputs for \n\
495 greater control in monitoring without affecting the mix."));
496
497         vbox = manage (new VBox);
498         vbox->set_spacing (6);
499         vbox->pack_start (use_monitor_section_button, false, true);
500         vbox->pack_start (*l, false, true);
501
502         main_vbox->pack_start (*vbox, false, false);
503
504         RadioButton::Group g (use_monitor_section_button.get_group());
505         no_monitor_section_button.set_group (g);
506
507         if (Config->get_use_monitor_bus()) {
508                 use_monitor_section_button.set_active (true);
509         } else {
510                 no_monitor_section_button.set_active (true);
511         }
512
513         use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
514         no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
515
516         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\
517 <i>If you do not understand what this is about, just accept the default.</i>"));
518         monitor_section_label.set_alignment (0.0, 0.0);
519
520         hbox->pack_start (*main_vbox, true, true, 8);
521         mon_sec_vbox.pack_start (*hbox, false, false);
522         mon_sec_vbox.pack_start (monitor_section_label, false, false);
523
524         mon_sec_vbox.show_all ();
525
526         monitor_section_page_index = append_page (mon_sec_vbox);
527         set_page_title (mon_sec_vbox, _("Monitor Section"));
528         set_page_header_image (mon_sec_vbox, icon_pixbuf);
529
530         /* user could just click on "Forward" if default
531          * choice is correct.
532          */
533
534         set_page_complete (mon_sec_vbox, true);
535 }
536
537 void
538 ArdourStartup::setup_initial_choice_page ()
539 {
540         ic_vbox.set_spacing (6);
541         ic_vbox.set_border_width (24);
542
543         RadioButton::Group g (ic_new_session_button.get_group());
544         ic_existing_session_button.set_group (g);
545
546         HBox* centering_hbox = manage (new HBox);
547         VBox* centering_vbox = manage (new VBox);
548
549         centering_vbox->set_spacing (6);
550
551         centering_vbox->pack_start (ic_new_session_button, false, true);
552         centering_vbox->pack_start (ic_existing_session_button, false, true);
553         
554         if (ARDOUR_UI::instance()->announce_string() != "" ) {
555
556                 Gtk::Frame *info_frame = manage(new Gtk::Frame);
557                 info_frame->set_shadow_type(SHADOW_ETCHED_OUT);
558                 centering_vbox->pack_start (*info_frame, false, false, 20);
559
560                 Box *info_box = manage (new VBox);
561                 info_box->set_border_width (12);
562                 info_box->set_spacing (6);
563                 info_box->set_name("mixbus_info_box");
564
565                 info_box->pack_start (info_scroller_label, false, false);
566
567                 info_frame->add (*info_box);
568                 info_frame->show_all();
569
570                 info_scroller_count = 0;
571                 info_scroller_connection = Glib::signal_timeout().connect (mem_fun(*this, &ArdourStartup::info_scroller_update), 50);
572
573                 Gtk::Button *updates_button = manage (new Gtk::Button (_("Check the website for more...")));
574
575                 updates_button->signal_clicked().connect (mem_fun(*this, &ArdourStartup::updates_button_clicked) );
576                 ARDOUR_UI::instance()->tooltips().set_tip (*updates_button, _("Click to open the program website in your web browser"));
577
578                 info_box->pack_start (*updates_button, false, false);
579         }
580         
581         ic_new_session_button.signal_button_press_event().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_clicked), false);
582         ic_new_session_button.signal_activate().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_activated), false);
583
584         ic_existing_session_button.signal_button_press_event().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_clicked), false);
585         ic_existing_session_button.signal_activate().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_activated), false);
586
587         centering_hbox->pack_start (*centering_vbox, true, true);
588
589         ic_vbox.pack_start (*centering_hbox, true, true);
590
591         ic_vbox.show_all ();
592
593         initial_choice_index = append_page (ic_vbox);
594         set_page_title (ic_vbox, string_compose("%1 %2", PROGRAM_NAME, VERSIONSTRING));
595         set_page_header_image (ic_vbox, icon_pixbuf);
596
597         /* user could just click on "Forward" if default
598          * choice is correct.
599          */
600
601         set_page_complete (ic_vbox, true);
602 }
603
604 bool
605 ArdourStartup::initial_button_clicked (GdkEventButton* ev)
606 {
607         if (ev->type == GDK_2BUTTON_PRESS && session_page_index != -1) {
608                 set_current_page(session_page_index);
609         }
610
611         return false;
612 }
613
614 void
615 ArdourStartup::initial_button_activated ()
616 {
617         if (session_page_index != -1) {
618                 set_current_page(session_page_index);
619         }
620 }
621
622 void
623 ArdourStartup::setup_session_page ()
624 {
625         session_vbox.set_border_width (24);
626
627         session_vbox.pack_start (session_hbox, true, true);
628         session_vbox.show_all ();
629
630         session_page_index = append_page (session_vbox);
631         /* initial setting */
632         set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
633 }
634
635 void
636 ArdourStartup::setup_final_page ()
637 {
638         final_page.set_text (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
639         final_page.show ();
640         final_page_index = append_page (final_page);
641         set_page_complete (final_page, true);
642         set_page_header_image (final_page, icon_pixbuf);
643         set_page_type (final_page, ASSISTANT_PAGE_CONFIRM);
644 }
645
646 void
647 ArdourStartup::on_cancel ()
648 {
649         _response = RESPONSE_CANCEL;
650         gtk_main_quit ();
651 }
652
653 bool
654 ArdourStartup::on_delete_event (GdkEventAny*)
655 {
656         _response = RESPONSE_CLOSE;
657         gtk_main_quit ();
658         return true;
659 }
660
661 void
662 ArdourStartup::on_apply ()
663 {
664         if (engine_dialog) {
665                 if (engine_dialog->setup_engine ()) {
666                         set_current_page (audio_page_index);
667                         return;
668                 }
669         }
670
671         if (config_modified) {
672
673                 if (default_dir_chooser) {
674                         Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
675                 }
676
677                 if (monitor_via_hardware_button.get_active()) {
678                         Config->set_monitoring_model (ExternalMonitoring);
679                 } else if (monitor_via_ardour_button.get_active()) {
680                         Config->set_monitoring_model (SoftwareMonitoring);
681                 }
682
683                 Config->set_use_monitor_bus (use_monitor_section_button.get_active());
684
685                 Config->save_state ();
686
687         }
688
689         {
690                 /* "touch" the been-here-before path now we've successfully
691                    made it through the first time setup (at least)
692                 */
693                 ofstream fout (been_here_before_path().c_str());
694
695         }
696                 
697         _response = RESPONSE_OK;
698         gtk_main_quit ();
699 }
700
701 void
702 ArdourStartup::on_prepare (Gtk::Widget* page)
703 {
704         if (page == &session_vbox) {
705
706                 if (ic_new_session_button.get_active()) {
707                         /* new session requested */
708                         setup_new_session_page ();
709                 } else {
710                         /* existing session requested */
711                         setup_existing_session_page ();
712
713                 }
714
715                 /* HACK HACK HACK ... change the "Apply" button label
716                    to say "Open"
717                 */
718
719                 Gtk::Widget* tl = session_vbox.get_toplevel();
720                 Gtk::Window* win;
721                 if ((win = dynamic_cast<Gtk::Window*>(tl)) != 0) {
722                         /* ::get_default_widget() is not wrapped in gtkmm */
723                         Gtk::Widget* def = wrap (gtk_window_get_default_widget (win->gobj()));
724                         Gtk::Button* button;
725                         if ((button = dynamic_cast<Gtk::Button*>(def)) != 0) {
726                                 if (more_new_session_options_button.get_active()) {
727                                         button->set_label (_("Forward"));
728                                 }else{
729                                         button->set_label (_("Open"));
730                                 }
731                         }
732                 }
733         }
734 }
735
736 void
737 ArdourStartup::populate_session_templates ()
738 {
739         vector<TemplateInfo> templates;
740
741         find_session_templates (templates);
742
743         template_model->clear ();
744
745         for (vector<TemplateInfo>::iterator x = templates.begin(); x != templates.end(); ++x) {
746                 TreeModel::Row row;
747
748                 row = *(template_model->append ());
749
750                 row[session_template_columns.name] = (*x).name;
751                 row[session_template_columns.path] = (*x).path;
752         }
753 }
754
755 void
756 ArdourStartup::setup_new_session_page ()
757 {
758         if (!session_hbox.get_children().empty()) {
759                 session_hbox.remove (**session_hbox.get_children().begin());
760         }
761
762         session_new_vbox.set_spacing (18);
763
764         if (session_new_vbox.get_children().empty()) {
765                 VBox *vbox1 = manage (new VBox);
766                 HBox* hbox1 = manage (new HBox);
767                 Label* label1 = manage (new Label);
768
769                 vbox1->set_spacing (6);
770
771                 hbox1->set_spacing (6);
772                 hbox1->pack_start (*label1, false, false);
773                 hbox1->pack_start (new_name_entry, true, true);
774
775                 label1->set_text (_("Session name:"));
776
777
778                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
779                         new_name_entry.set_text  (Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name));
780                         /* name provided - they can move right along */
781                         set_page_complete (session_vbox, true);
782                 }
783
784                 new_name_entry.signal_changed().connect (sigc::mem_fun (*this, &ArdourStartup::new_name_changed));
785                 new_name_entry.signal_activate().connect (sigc::mem_fun (*this, &ArdourStartup::move_along_now));
786
787                 vbox1->pack_start (*hbox1, true, true);
788
789                 /* --- */
790
791                 HBox* hbox2 = manage (new HBox);
792                 Label* label2 = manage (new Label);
793
794                 hbox2->set_spacing (6);
795                 hbox2->pack_start (*label2, false, false);
796                 hbox2->pack_start (new_folder_chooser, true, true);
797
798                 label2->set_text (_("Create session folder in:"));
799
800                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
801                         new_folder_chooser.set_current_folder (poor_mans_glob (Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name)));
802                 } else if (ARDOUR_UI::instance()->session_loaded) {
803                         // point the new session file chooser at the parent directory of the current session
804                         string session_parent_dir = Glib::path_get_dirname(ARDOUR_UI::instance()->the_session()->path());
805                         string::size_type last_dir_sep = session_parent_dir.rfind(G_DIR_SEPARATOR);
806                         session_parent_dir = session_parent_dir.substr(0, last_dir_sep);
807                         new_folder_chooser.set_current_folder (session_parent_dir);
808                         string default_session_folder = poor_mans_glob (Config->get_default_session_parent_dir());
809
810                         try {
811                                 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
812                                 new_folder_chooser.add_shortcut_folder (default_session_folder);
813                         }
814                         catch (Glib::Error & e) {
815                                 std::cerr << "new_folder_chooser.add_shortcut_folder (" << default_session_folder << ") threw Glib::Error " << e.what() << std::endl;
816                         }
817                 } else {
818                         new_folder_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
819                 }
820                 new_folder_chooser.show ();
821                 new_folder_chooser.set_title (_("Select folder for session"));
822
823 #ifdef __APPLE__
824                 new_folder_chooser.add_shortcut_folder ("/Volumes");
825 #endif
826
827                 vbox1->pack_start (*hbox2, false, false);
828                 
829                 session_new_vbox.pack_start (*vbox1, false, false);
830
831                 /* --- */
832
833                 VBox *vbox2 = manage (new VBox);
834                 HBox* hbox3 = manage (new HBox);
835                 Label* label3 = manage (new Label);
836                 template_model = ListStore::create (session_template_columns);
837                 populate_session_templates ();
838
839                 vbox2->set_spacing (6);
840
841                 label3->set_markup (_("<b>Options</b>"));
842                 label3->set_alignment (0.0, 0.0);
843
844                 vbox2->pack_start (*label3, false, true);
845
846                 VBox *vbox3 = manage (new VBox);
847
848                 vbox3->set_spacing (6);
849
850                 if (!template_model->children().empty()) {
851
852                         HBox* hbox4a = manage (new HBox);
853                         use_template_button.set_label (_("Use this template"));
854
855                         TreeModel::Row row = *template_model->prepend ();
856                         row[session_template_columns.name] = (_("no template"));
857                         row[session_template_columns.path] = string();
858
859                         hbox4a->set_spacing (6);
860                         hbox4a->pack_start (use_template_button, false, false);
861                         hbox4a->pack_start (template_chooser, true, true);
862
863                         template_chooser.set_model (template_model);
864
865                         Gtk::CellRendererText* text_renderer = Gtk::manage (new Gtk::CellRendererText);
866                         text_renderer->property_editable() = false;
867
868                         template_chooser.pack_start (*text_renderer);
869                         template_chooser.add_attribute (text_renderer->property_text(), session_template_columns.name);
870                         template_chooser.set_active (0);
871
872                         use_template_button.show();
873                         template_chooser.show ();
874
875                         vbox3->pack_start (*hbox4a, false, false);
876                 }
877
878                 /* --- */
879
880                 if (!new_user) {
881                         session_template_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
882
883                         HBox* hbox4b = manage (new HBox);
884                         use_session_as_template_button.set_label (_("Use an existing session as a template:"));
885
886                         hbox4b->set_spacing (6);
887                         hbox4b->pack_start (use_session_as_template_button, false, false);
888                         hbox4b->pack_start (session_template_chooser, true, true);
889
890                         use_session_as_template_button.show ();
891                         session_template_chooser.show ();
892
893                         Gtk::FileFilter* session_filter = manage (new (Gtk::FileFilter));
894                         session_filter->add_pattern (X_("*.ardour"));
895                         session_template_chooser.set_filter (*session_filter);
896                         session_template_chooser.set_title (_("Select template"));
897
898                         vbox3->pack_start (*hbox4b, false, false);
899                 }
900
901                 /* --- */
902
903                 HBox* hbox5 = manage (new HBox);
904
905                 hbox5->set_spacing (6);
906                 hbox5->pack_start (more_new_session_options_button, false, false);
907
908                 more_new_session_options_button.show ();
909                 more_new_session_options_button.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::more_new_session_options_button_clicked));
910
911                 vbox3->pack_start (*hbox5, false, false);
912                 hbox3->pack_start (*vbox3, true, true, 8);
913                 vbox2->pack_start (*hbox3, false, false);
914
915                 /* --- */
916
917                 session_new_vbox.pack_start (*vbox2, false, false);
918         }
919
920         session_new_vbox.show_all ();
921         session_hbox.pack_start (session_new_vbox, true, true);
922         set_page_title (session_vbox, _("New Session"));
923         set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
924
925         if (more_new_session_options_button.get_active()) {
926                 set_page_type (session_vbox, ASSISTANT_PAGE_CONTENT);
927         }
928         session_hbox.show_all();
929 }
930
931 void
932 ArdourStartup::new_name_changed ()
933 {
934         if (!new_name_entry.get_text().empty()) {
935                 set_page_complete (session_vbox, true);
936         } else {
937                 set_page_complete (session_vbox, false);
938         }
939 }
940
941 int
942 ArdourStartup::redisplay_recent_sessions ()
943 {
944         std::vector<std::string> session_directories;
945         RecentSessionsSorter cmp;
946
947         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
948         recent_session_model->clear ();
949
950         ARDOUR::RecentSessions rs;
951         ARDOUR::read_recent_sessions (rs);
952
953         if (rs.empty()) {
954                 recent_session_display.set_model (recent_session_model);
955                 return 0;
956         }
957         //
958         // sort them alphabetically
959         sort (rs.begin(), rs.end(), cmp);
960
961         for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
962                 session_directories.push_back ((*i).second);
963         }
964         
965         int session_snapshot_count = 0;
966
967         for (vector<std::string>::const_iterator i = session_directories.begin(); i != session_directories.end(); ++i)
968         {
969                 std::vector<std::string> state_file_paths;
970
971                 // now get available states for this session
972
973                 get_state_files_in_directory (*i, state_file_paths);
974
975                 vector<string*>* states;
976                 vector<const gchar*> item;
977                 string fullpath = *i;
978
979                 /* remove any trailing / */
980
981                 if (fullpath[fullpath.length()-1] == '/') {
982                         fullpath = fullpath.substr (0, fullpath.length()-1);
983                 }
984
985                 /* check whether session still exists */
986                 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
987                         /* session doesn't exist */
988                         continue;
989                 }
990
991                 /* now get available states for this session */
992
993                 if ((states = Session::possible_states (fullpath)) == 0) {
994                         /* no state file? */
995                         continue;
996                 }
997
998                 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
999
1000                 Gtk::TreeModel::Row row = *(recent_session_model->append());
1001
1002                 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1003                 row[recent_session_columns.fullpath] = fullpath;
1004                 row[recent_session_columns.tip] = Glib::Markup::escape_text (fullpath);
1005                 
1006                 ++session_snapshot_count;
1007
1008                 if (state_file_names.size() > 1) {
1009
1010                         // add the children
1011
1012                         for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1013                                         i2 != state_file_names.end(); ++i2) {
1014
1015                                 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1016
1017                                 child_row[recent_session_columns.visible_name] = *i2;
1018                                 child_row[recent_session_columns.fullpath] = fullpath;
1019                                 child_row[recent_session_columns.tip] = Glib::Markup::escape_text (fullpath);
1020                                 ++session_snapshot_count;
1021                         }
1022                 }
1023         }
1024
1025         recent_session_display.set_tooltip_column(1); // recent_session_columns.tip 
1026         recent_session_display.set_model (recent_session_model);
1027         return session_snapshot_count;
1028         // return rs.size();
1029 }
1030
1031 void
1032 ArdourStartup::recent_session_row_selected ()
1033 {
1034         if (recent_session_display.get_selection()->count_selected_rows() > 0) {
1035                 set_page_complete (session_vbox, true);
1036         } else {
1037                 set_page_complete (session_vbox, false);
1038         }
1039 }
1040
1041 void
1042 ArdourStartup::setup_existing_session_page ()
1043 {
1044         recent_session_model = TreeStore::create (recent_session_columns);
1045         redisplay_recent_sessions ();
1046
1047         if (!session_hbox.get_children().empty()) {
1048                 session_hbox.remove (**session_hbox.get_children().begin());
1049         }
1050
1051         if (session_existing_vbox.get_children().empty()) {
1052
1053                 recent_session_display.set_model (recent_session_model);
1054                 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1055                 recent_session_display.set_headers_visible (false);
1056                 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1057
1058                 recent_session_display.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ArdourStartup::recent_session_row_selected));
1059
1060                 recent_scroller.add (recent_session_display);
1061                 recent_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1062                 recent_scroller.set_shadow_type (Gtk::SHADOW_IN);
1063
1064                 recent_session_display.show();
1065
1066                 recent_scroller.show();
1067                 int cnt = redisplay_recent_sessions ();
1068                 recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &ArdourStartup::recent_row_activated));
1069
1070                 if (cnt > 4) {
1071                         recent_scroller.set_size_request (-1, 300);
1072                 }
1073
1074                 session_existing_vbox.set_spacing (8);
1075                 session_existing_vbox.pack_start (recent_scroller, true, true);
1076
1077                 existing_session_chooser.set_title (_("Select session file"));
1078                 existing_session_chooser.signal_file_set().connect (sigc::mem_fun (*this, &ArdourStartup::existing_session_selected));
1079                 existing_session_chooser.set_current_folder(poor_mans_glob (Config->get_default_session_parent_dir()));
1080
1081                 FileFilter session_filter;
1082                 session_filter.add_pattern ("*.ardour");
1083                 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1084                 existing_session_chooser.add_filter (session_filter);
1085                 existing_session_chooser.set_filter (session_filter);
1086                 
1087 #ifdef GTKOSX
1088                 existing_session_chooser.add_shortcut_folder ("/Volumes");
1089 #endif
1090
1091                 HBox* hbox = manage (new HBox);
1092                 hbox->set_spacing (4);
1093                 hbox->pack_start (*manage (new Label (_("Browse:"))), PACK_SHRINK);
1094                 hbox->pack_start (existing_session_chooser);
1095                 session_existing_vbox.pack_start (*hbox, false, false);
1096                 hbox->show_all ();
1097         }
1098
1099         session_existing_vbox.show_all ();
1100         session_hbox.pack_start (session_existing_vbox, true, true);
1101
1102         set_page_title (session_vbox, _("Select a session"));
1103         set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
1104         session_hbox.show_all();
1105 }
1106
1107 void
1108 ArdourStartup::more_new_session_options_button_clicked ()
1109 {
1110         if (more_new_session_options_button.get_active()) {
1111                 more_options_vbox.show_all ();
1112                 set_page_type (more_options_vbox, ASSISTANT_PAGE_CONFIRM);
1113                 set_page_type (session_vbox, ASSISTANT_PAGE_CONTENT);
1114         } else {
1115                 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
1116                 more_options_vbox.hide ();
1117         }
1118 }
1119
1120 void
1121 ArdourStartup::setup_more_options_page ()
1122 {
1123         more_options_vbox.set_border_width (24);
1124
1125         _output_limit_count.set_adjustment (_output_limit_count_adj);
1126         _input_limit_count.set_adjustment (_input_limit_count_adj);
1127         _master_bus_channel_count.set_adjustment (_master_bus_channel_count_adj);
1128
1129         chan_count_label_1.set_text (_("channels"));
1130         chan_count_label_3.set_text (_("channels"));
1131         chan_count_label_4.set_text (_("channels"));
1132
1133         chan_count_label_1.set_alignment(0,0.5);
1134         chan_count_label_1.set_padding(0,0);
1135         chan_count_label_1.set_line_wrap(false);
1136
1137         chan_count_label_3.set_alignment(0,0.5);
1138         chan_count_label_3.set_padding(0,0);
1139         chan_count_label_3.set_line_wrap(false);
1140
1141         chan_count_label_4.set_alignment(0,0.5);
1142         chan_count_label_4.set_padding(0,0);
1143         chan_count_label_4.set_line_wrap(false);
1144
1145         bus_label.set_markup (_("<b>Busses</b>"));
1146         input_label.set_markup (_("<b>Inputs</b>"));
1147         output_label.set_markup (_("<b>Outputs</b>"));
1148
1149         _master_bus_channel_count.set_flags(Gtk::CAN_FOCUS);
1150         _master_bus_channel_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1151         _master_bus_channel_count.set_numeric(true);
1152         _master_bus_channel_count.set_digits(0);
1153         _master_bus_channel_count.set_wrap(false);
1154
1155         _create_master_bus.set_label (_("Create master bus"));
1156         _create_master_bus.set_flags(Gtk::CAN_FOCUS);
1157         _create_master_bus.set_relief(Gtk::RELIEF_NORMAL);
1158         _create_master_bus.set_mode(true);
1159         _create_master_bus.set_active(true);
1160         _create_master_bus.set_border_width(0);
1161
1162         advanced_table.set_row_spacings(0);
1163         advanced_table.set_col_spacings(0);
1164
1165         _connect_inputs.set_label (_("Automatically connect to physical inputs"));
1166         _connect_inputs.set_flags(Gtk::CAN_FOCUS);
1167         _connect_inputs.set_relief(Gtk::RELIEF_NORMAL);
1168         _connect_inputs.set_mode(true);
1169         _connect_inputs.set_active(Config->get_input_auto_connect() != ManualConnect);
1170         _connect_inputs.set_border_width(0);
1171
1172         _limit_input_ports.set_label (_("Use only"));
1173         _limit_input_ports.set_flags(Gtk::CAN_FOCUS);
1174         _limit_input_ports.set_relief(Gtk::RELIEF_NORMAL);
1175         _limit_input_ports.set_mode(true);
1176         _limit_input_ports.set_sensitive(true);
1177         _limit_input_ports.set_border_width(0);
1178
1179         _input_limit_count.set_flags(Gtk::CAN_FOCUS);
1180         _input_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1181         _input_limit_count.set_numeric(true);
1182         _input_limit_count.set_digits(0);
1183         _input_limit_count.set_wrap(false);
1184         _input_limit_count.set_sensitive(false);
1185
1186         bus_hbox.pack_start (bus_table, Gtk::PACK_SHRINK, 18);
1187
1188         bus_label.set_alignment(0, 0.5);
1189         bus_label.set_padding(0,0);
1190         bus_label.set_line_wrap(false);
1191         bus_label.set_selectable(false);
1192         bus_label.set_use_markup(true);
1193         bus_frame.set_shadow_type(Gtk::SHADOW_NONE);
1194         bus_frame.set_label_align(0,0.5);
1195         bus_frame.add(bus_hbox);
1196         bus_frame.set_label_widget(bus_label);
1197
1198         bus_table.set_row_spacings (0);
1199         bus_table.set_col_spacings (0);
1200         bus_table.attach (_create_master_bus, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
1201         bus_table.attach (_master_bus_channel_count, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
1202         bus_table.attach (chan_count_label_1, 2, 3, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 0);
1203
1204         input_port_limit_hbox.pack_start(_limit_input_ports, Gtk::PACK_SHRINK, 6);
1205         input_port_limit_hbox.pack_start(_input_limit_count, Gtk::PACK_SHRINK, 0);
1206         input_port_limit_hbox.pack_start(chan_count_label_3, Gtk::PACK_SHRINK, 6);
1207         input_port_vbox.pack_start(_connect_inputs, Gtk::PACK_SHRINK, 0);
1208         input_port_vbox.pack_start(input_port_limit_hbox, Gtk::PACK_EXPAND_PADDING, 0);
1209         input_table.set_row_spacings(0);
1210         input_table.set_col_spacings(0);
1211         input_table.attach(input_port_vbox, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 6);
1212
1213         input_hbox.pack_start (input_table, Gtk::PACK_SHRINK, 18);
1214
1215         input_label.set_alignment(0, 0.5);
1216         input_label.set_padding(0,0);
1217         input_label.set_line_wrap(false);
1218         input_label.set_selectable(false);
1219         input_label.set_use_markup(true);
1220         input_frame.set_shadow_type(Gtk::SHADOW_NONE);
1221         input_frame.set_label_align(0,0.5);
1222         input_frame.add(input_hbox);
1223         input_frame.set_label_widget(input_label);
1224
1225         _connect_outputs.set_label (_("Automatically connect outputs"));
1226         _connect_outputs.set_flags(Gtk::CAN_FOCUS);
1227         _connect_outputs.set_relief(Gtk::RELIEF_NORMAL);
1228         _connect_outputs.set_mode(true);
1229         _connect_outputs.set_active(Config->get_output_auto_connect() != ManualConnect);
1230         _connect_outputs.set_border_width(0);
1231         _limit_output_ports.set_label (_("Use only"));
1232         _limit_output_ports.set_flags(Gtk::CAN_FOCUS);
1233         _limit_output_ports.set_relief(Gtk::RELIEF_NORMAL);
1234         _limit_output_ports.set_mode(true);
1235         _limit_output_ports.set_sensitive(true);
1236         _limit_output_ports.set_border_width(0);
1237         _output_limit_count.set_flags(Gtk::CAN_FOCUS);
1238         _output_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1239         _output_limit_count.set_numeric(false);
1240         _output_limit_count.set_digits(0);
1241         _output_limit_count.set_wrap(false);
1242         _output_limit_count.set_sensitive(false);
1243         output_port_limit_hbox.pack_start(_limit_output_ports, Gtk::PACK_SHRINK, 6);
1244         output_port_limit_hbox.pack_start(_output_limit_count, Gtk::PACK_SHRINK, 0);
1245         output_port_limit_hbox.pack_start(chan_count_label_4, Gtk::PACK_SHRINK, 6);
1246
1247         _connect_outputs_to_master.set_label (_("... to master bus"));
1248         _connect_outputs_to_master.set_flags(Gtk::CAN_FOCUS);
1249         _connect_outputs_to_master.set_relief(Gtk::RELIEF_NORMAL);
1250         _connect_outputs_to_master.set_mode(true);
1251         _connect_outputs_to_master.set_active(Config->get_output_auto_connect() == AutoConnectMaster);
1252         _connect_outputs_to_master.set_border_width(0);
1253
1254         _connect_outputs_to_master.set_group (connect_outputs_group);
1255         _connect_outputs_to_physical.set_group (connect_outputs_group);
1256
1257         _connect_outputs_to_physical.set_label (_("... to physical outputs"));
1258         _connect_outputs_to_physical.set_flags(Gtk::CAN_FOCUS);
1259         _connect_outputs_to_physical.set_relief(Gtk::RELIEF_NORMAL);
1260         _connect_outputs_to_physical.set_mode(true);
1261         _connect_outputs_to_physical.set_active(Config->get_output_auto_connect() == AutoConnectPhysical);
1262         _connect_outputs_to_physical.set_border_width(0);
1263
1264         output_conn_vbox.pack_start(_connect_outputs, Gtk::PACK_SHRINK, 0);
1265         output_conn_vbox.pack_start(_connect_outputs_to_master, Gtk::PACK_SHRINK, 0);
1266         output_conn_vbox.pack_start(_connect_outputs_to_physical, Gtk::PACK_SHRINK, 0);
1267         output_vbox.set_border_width(6);
1268
1269         output_port_vbox.pack_start(output_port_limit_hbox, Gtk::PACK_SHRINK, 0);
1270
1271         output_vbox.pack_start(output_conn_vbox);
1272         output_vbox.pack_start(output_port_vbox);
1273
1274         output_label.set_alignment(0, 0.5);
1275         output_label.set_padding(0,0);
1276         output_label.set_line_wrap(false);
1277         output_label.set_selectable(false);
1278         output_label.set_use_markup(true);
1279         output_frame.set_shadow_type(Gtk::SHADOW_NONE);
1280         output_frame.set_label_align(0,0.5);
1281
1282         output_hbox.pack_start (output_vbox, Gtk::PACK_SHRINK, 18);
1283
1284         output_frame.add(output_hbox);
1285         output_frame.set_label_widget(output_label);
1286
1287         more_options_vbox.pack_start(advanced_table, Gtk::PACK_SHRINK, 0);
1288         more_options_vbox.pack_start(bus_frame, Gtk::PACK_SHRINK, 6);
1289         more_options_vbox.pack_start(input_frame, Gtk::PACK_SHRINK, 6);
1290         more_options_vbox.pack_start(output_frame, Gtk::PACK_SHRINK, 0);
1291
1292         /* signals */
1293
1294         _connect_inputs.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::connect_inputs_clicked));
1295         _connect_outputs.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::connect_outputs_clicked));
1296         _limit_input_ports.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::limit_inputs_clicked));
1297         _limit_output_ports.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::limit_outputs_clicked));
1298         _create_master_bus.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::master_bus_button_clicked));
1299
1300         /* note that more_options_vbox is "visible" by default even
1301          * though it may not be displayed to the user, this is so the dialog
1302          * doesn't resize.
1303          */
1304         more_options_vbox.show_all ();
1305
1306         session_options_page_index = append_page (more_options_vbox);
1307         set_page_title (more_options_vbox, _("Advanced Session Options"));
1308         set_page_complete (more_options_vbox, true);
1309 }
1310
1311 bool
1312 ArdourStartup::create_master_bus() const
1313 {
1314         return _create_master_bus.get_active();
1315 }
1316
1317 int
1318 ArdourStartup::master_channel_count() const
1319 {
1320         return _master_bus_channel_count.get_value_as_int();
1321 }
1322
1323 bool
1324 ArdourStartup::connect_inputs() const
1325 {
1326         return _connect_inputs.get_active();
1327 }
1328
1329 bool
1330 ArdourStartup::limit_inputs_used_for_connection() const
1331 {
1332         return _limit_input_ports.get_active();
1333 }
1334
1335 int
1336 ArdourStartup::input_limit_count() const
1337 {
1338         return _input_limit_count.get_value_as_int();
1339 }
1340
1341 bool
1342 ArdourStartup::connect_outputs() const
1343 {
1344         return _connect_outputs.get_active();
1345 }
1346
1347 bool
1348 ArdourStartup::limit_outputs_used_for_connection() const
1349 {
1350         return _limit_output_ports.get_active();
1351 }
1352
1353 int
1354 ArdourStartup::output_limit_count() const
1355 {
1356         return _output_limit_count.get_value_as_int();
1357 }
1358
1359 bool
1360 ArdourStartup::connect_outs_to_master() const
1361 {
1362         return _connect_outputs_to_master.get_active();
1363 }
1364
1365 bool
1366 ArdourStartup::connect_outs_to_physical() const
1367 {
1368         return _connect_outputs_to_physical.get_active();
1369 }
1370
1371 void
1372 ArdourStartup::connect_inputs_clicked ()
1373 {
1374         _limit_input_ports.set_sensitive(_connect_inputs.get_active());
1375
1376         if (_connect_inputs.get_active() && _limit_input_ports.get_active()) {
1377                 _input_limit_count.set_sensitive(true);
1378         } else {
1379                 _input_limit_count.set_sensitive(false);
1380         }
1381 }
1382
1383 void
1384 ArdourStartup::connect_outputs_clicked ()
1385 {
1386         bool const co = _connect_outputs.get_active ();
1387         _limit_output_ports.set_sensitive(co);
1388         _connect_outputs_to_master.set_sensitive(co);
1389         _connect_outputs_to_physical.set_sensitive(co);
1390
1391         if (co && _limit_output_ports.get_active()) {
1392                 _output_limit_count.set_sensitive(true);
1393         } else {
1394                 _output_limit_count.set_sensitive(false);
1395         }
1396 }
1397
1398 void
1399 ArdourStartup::limit_inputs_clicked ()
1400 {
1401         _input_limit_count.set_sensitive(_limit_input_ports.get_active());
1402 }
1403
1404 void
1405 ArdourStartup::limit_outputs_clicked ()
1406 {
1407         _output_limit_count.set_sensitive(_limit_output_ports.get_active());
1408 }
1409
1410 void
1411 ArdourStartup::master_bus_button_clicked ()
1412 {
1413         bool const yn = _create_master_bus.get_active();
1414
1415         _master_bus_channel_count.set_sensitive(yn);
1416         _connect_outputs_to_master.set_sensitive(yn);
1417 }
1418
1419 void
1420 ArdourStartup::move_along_now ()
1421 {
1422         gint cur = get_current_page ();
1423
1424         if (cur == session_page_index) {
1425                 if (more_new_session_options_button.get_active()) {
1426                         set_current_page (session_options_page_index);
1427                 } else {
1428                         on_apply ();
1429                 }
1430         }
1431 }
1432
1433 void
1434 ArdourStartup::recent_row_activated (const Gtk::TreePath&, Gtk::TreeViewColumn*)
1435 {
1436         set_page_complete (session_vbox, true);
1437         move_along_now ();
1438 }
1439
1440 void
1441 ArdourStartup::existing_session_selected ()
1442 {
1443         _existing_session_chooser_used = true;
1444
1445         set_page_complete (session_vbox, true);
1446         move_along_now ();
1447 }
1448
1449 std::string
1450 ArdourStartup::been_here_before_path () const
1451 {
1452         // XXXX use more specific version so we can catch upgrades
1453         return Glib::build_filename (user_config_directory (), ".a3");
1454 }
1455
1456 void
1457 ArdourStartup::updates_button_clicked ()
1458 {
1459         //now open a browser window so user can see more
1460         PBD::open_uri (Config->get_updates_url());
1461 }
1462
1463 bool
1464 ArdourStartup::info_scroller_update()
1465 {
1466         info_scroller_count++;
1467
1468         char buf[512];
1469         snprintf (buf, std::min(info_scroller_count,sizeof(buf)-1), "%s", ARDOUR_UI::instance()->announce_string().c_str() );
1470         buf[info_scroller_count] = 0;
1471         info_scroller_label.set_text (buf);
1472         info_scroller_label.show();
1473
1474         if (info_scroller_count > ARDOUR_UI::instance()->announce_string().length()) {
1475                 info_scroller_connection.disconnect();
1476         }
1477
1478         return true;
1479 }