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