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