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