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