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