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