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