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