don't double-load NestedSource nodes, which are listed both forthe parent/root region...
[ardour2.git] / gtk2_ardour / startup.cc
blobe1366c3acd09da8665cd0072f0d30fe70dc3d6e7
1 /*
2 Copyright (C) 2010 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #endif
24 #include <fstream>
25 #include <algorithm>
27 #include <gtkmm/main.h>
28 #include <gtkmm/filechooser.h>
30 #include "pbd/failed_constructor.h"
31 #include "pbd/file_utils.h"
32 #include "pbd/filesystem.h"
33 #include "pbd/replace_all.h"
34 #include "pbd/whitespace.h"
36 #include "ardour/filesystem_paths.h"
37 #include "ardour/recent_sessions.h"
38 #include "ardour/session.h"
39 #include "ardour/session_state_utils.h"
40 #include "ardour/template_utils.h"
42 #include "startup.h"
43 #include "opts.h"
44 #include "engine_dialog.h"
45 #include "i18n.h"
46 #include "utils.h"
48 using namespace std;
49 using namespace Gtk;
50 using namespace Gdk;
51 using namespace Glib;
52 using namespace PBD;
53 using namespace ARDOUR;
55 ArdourStartup* ArdourStartup::the_startup = 0;
57 static string poor_mans_glob (string path)
59 string copy = path;
60 replace_all (copy, "~", Glib::get_home_dir());
61 return copy;
65 ArdourStartup::ArdourStartup ()
66 : _response (RESPONSE_OK)
67 , ic_new_session_button (_("Open a new session"))
68 , ic_existing_session_button (_("Open an existing session"))
69 , monitor_via_hardware_button (_("Use an external mixer or the hardware mixer of your audio interface.\n\
70 Ardour will play NO role in monitoring"))
71 , monitor_via_ardour_button (string_compose (_("Ask %1 to playback material as it is being recorded"), PROGRAM_NAME))
72 , new_folder_chooser (FILE_CHOOSER_ACTION_SELECT_FOLDER)
73 , more_new_session_options_button (_("I'd like more options for this session"))
74 , _output_limit_count_adj (1, 0, 100, 1, 10, 0)
75 , _input_limit_count_adj (1, 0, 100, 1, 10, 0)
76 , _master_bus_channel_count_adj (2, 0, 100, 1, 10, 0)
77 , _existing_session_chooser_used (false)
79 audio_page_index = -1;
80 initial_choice_index = -1;
81 new_user_page_index = -1;
82 default_folder_page_index = -1;
83 monitoring_page_index = -1;
84 session_page_index = -1;
85 final_page_index = -1;
86 session_options_page_index = -1;
87 new_only = false;
89 engine_dialog = 0;
90 config_modified = false;
91 default_dir_chooser = 0;
93 use_template_button.set_group (session_template_group);
94 use_session_as_template_button.set_group (session_template_group);
96 set_keep_above (true);
97 set_resizable (false);
98 set_position (WIN_POS_CENTER);
99 set_border_width (12);
101 if ((icon_pixbuf = ::get_icon ("ardour_icon_48px")) == 0) {
102 throw failed_constructor();
105 sys::path been_here_before = user_config_directory();
106 been_here_before /= ".a3"; // XXXX use more specific version so we can catch upgrades
107 new_user = !exists (been_here_before);
109 bool need_audio_setup = !EngineControl::engine_running();
111 setup_alpha_page ();
113 if (new_user) {
114 /* "touch" the file */
115 ofstream fout (been_here_before.to_string().c_str());
116 setup_new_user_page ();
117 setup_first_time_config_page ();
118 setup_monitoring_choice_page ();
119 setup_monitor_section_choice_page ();
121 if (need_audio_setup) {
122 setup_audio_page ();
125 } else {
127 if (need_audio_setup) {
128 setup_audio_page ();
131 setup_initial_choice_page ();
134 setup_session_page ();
135 setup_more_options_page ();
137 if (new_user) {
138 setup_final_page ();
141 the_startup = this;
144 ArdourStartup::~ArdourStartup ()
148 void
149 ArdourStartup::setup_alpha_page ()
151 VBox* vbox = manage (new VBox);
152 Label* label = manage (new Label);
153 label->set_markup (_("<b>Welcome to this ALPHA release of Ardour 3.0</b>\n\n\
154 There are still many issues and bugs to be worked on,\n\
155 as well as general workflow improvements, before this can be considered\n\
156 release software. So, a few guidelines:\n\
158 1) Please do <b>NOT</b> use this software with the expectation that it is stable or reliable\n\
159 though it may be so, depending on your workflow.\n\
160 2) Please see http://ardour.org/a3_features for a guide to new features.\n\
161 3) <b>Please do NOT use the forums at ardour.org to report issues</b>.\n\
162 4) Please <b>DO</b> use the bugtracker at http://tracker.ardour.org/ to report issues\n\
163 making sure to note the product version number as 3.0-alpha.\n\
164 5) Please <b>DO</b> use the ardour-users mailing list to discuss ideas and pass on comments.\n\
165 6) Please <b>DO</b> join us on IRC for real time discussions about ardour3. You\n\
166 can get there directly from Ardour via the Help->Chat menu option.\n\
168 Full information on all the above can be found on the support page at\n\
170 http://ardour.org/support\n\
171 "));
173 vbox->set_border_width (12);
174 vbox->pack_start (*label, false, false, 12);
175 vbox->show_all ();
177 append_page (*vbox);
178 set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
179 set_page_title (*vbox, _("This is an ALPHA RELEASE"));
180 set_page_complete (*vbox, true);
183 void
184 ArdourStartup::set_new_only (bool yn)
186 new_only = yn;
188 if (new_only) {
189 ic_vbox.hide ();
190 } else {
191 ic_vbox.show ();
195 void
196 ArdourStartup::set_load_template (string load_template)
198 use_template_button.set_active (false);
199 load_template_override = load_template;
202 bool
203 ArdourStartup::use_session_template ()
205 if (!load_template_override.empty()) {
206 return true;
209 if (use_template_button.get_active()) {
210 return template_chooser.get_active_row_number() > 0;
211 } else {
212 return !session_template_chooser.get_filename().empty();
216 std::string
217 ArdourStartup::session_template_name ()
219 if (!load_template_override.empty()) {
220 string the_path = (ARDOUR::user_template_directory()/ (load_template_override + ".template")).to_string();
221 return the_path;
224 if (ic_existing_session_button.get_active()) {
225 return string();
228 if (use_template_button.get_active()) {
229 TreeModel::iterator iter = template_chooser.get_active ();
230 TreeModel::Row row = (*iter);
231 string s = row[session_template_columns.path];
232 return s;
233 } else {
234 return session_template_chooser.get_filename();
239 std::string
240 ArdourStartup::session_name (bool& should_be_new)
242 if (ic_new_session_button.get_active()) {
243 should_be_new = true;
244 string val = new_name_entry.get_text ();
245 strip_whitespace_edges (val);
246 return val;
247 } else if (_existing_session_chooser_used) {
248 /* existing session chosen from file chooser */
249 should_be_new = false;
250 return existing_session_chooser.get_filename ();
251 } else {
252 /* existing session chosen from recent list */
253 should_be_new = false;
255 TreeIter iter = recent_session_display.get_selection()->get_selected();
257 if (iter) {
258 return (*iter)[recent_session_columns.visible_name];
261 return "";
265 std::string
266 ArdourStartup::session_folder ()
268 if (ic_new_session_button.get_active()) {
269 std::string legal_session_folder_name = legalize_for_path (new_name_entry.get_text());
270 return Glib::build_filename (new_folder_chooser.get_current_folder(), legal_session_folder_name);
271 } else if (_existing_session_chooser_used) {
272 /* existing session chosen from file chooser */
273 return existing_session_chooser.get_current_folder ();
274 } else {
275 /* existing session chosen from recent list */
276 TreeIter iter = recent_session_display.get_selection()->get_selected();
278 if (iter) {
279 return (*iter)[recent_session_columns.fullpath];
281 return "";
285 void
286 ArdourStartup::setup_audio_page ()
288 engine_dialog = manage (new EngineControl);
290 engine_dialog->set_border_width (12);
292 engine_dialog->show_all ();
294 audio_page_index = append_page (*engine_dialog);
295 set_page_type (*engine_dialog, ASSISTANT_PAGE_CONTENT);
296 set_page_title (*engine_dialog, _("Audio / MIDI Setup"));
298 /* the default parameters should work, so the page is potentially complete */
300 set_page_complete (*engine_dialog, true);
303 void
304 ArdourStartup::setup_new_user_page ()
306 Label* foomatic = manage (new Label);
308 foomatic->set_markup (string_compose (_("\
309 <span size=\"larger\">%1 is a digital audio workstation. You can use it to\n\
310 record, edit and mix multi-track audio. You can produce your\n\
311 own CDs, mix video soundtracks, or just experiment with new\n\
312 ideas about music and sound.\n\
314 There are a few things that need to configured before you start\n\
315 using the program.</span>\
316 "), PROGRAM_NAME));
318 HBox* hbox = manage (new HBox);
319 HBox* vbox = manage (new HBox);
321 vbox->set_border_width (24);
323 hbox->pack_start (*foomatic, true, true);
324 vbox->pack_start (*hbox, true, true);
326 foomatic->show ();
327 hbox->show ();
328 vbox->show ();
330 new_user_page_index = append_page (*vbox);
331 set_page_type (*vbox, ASSISTANT_PAGE_INTRO);
332 set_page_title (*vbox, string_compose (_("Welcome to %1"), PROGRAM_NAME));
333 set_page_header_image (*vbox, icon_pixbuf);
334 set_page_complete (*vbox, true);
337 void
338 ArdourStartup::default_dir_changed ()
340 Config->set_default_session_parent_dir (default_dir_chooser->get_current_folder());
341 config_changed ();
344 void
345 ArdourStartup::config_changed ()
347 config_modified = true;
350 void
351 ArdourStartup::setup_first_time_config_page ()
353 default_dir_chooser = manage (new FileChooserButton (string_compose (_("Default folder for %1 sessions"), PROGRAM_NAME),
354 FILE_CHOOSER_ACTION_SELECT_FOLDER));
355 Gtk::Label* txt = manage (new Label);
356 HBox* hbox = manage (new HBox);
357 VBox* vbox = manage (new VBox);
359 txt->set_markup (string_compose (_("\
360 Each project that you work on with %1 has its own folder.\n\
361 These can require a lot of disk space if you are recording audio.\n\
363 Where would you like new %1 sessions to be stored by default?\n\n\
364 <i>(You can put new sessions anywhere, this is just a default)</i>"), PROGRAM_NAME));
365 txt->set_alignment (0.0, 0.0);
367 vbox->set_spacing (18);
368 vbox->set_border_width (24);
370 hbox->pack_start (*default_dir_chooser, false, true, 8);
371 vbox->pack_start (*txt, false, false);
372 vbox->pack_start (*hbox, false, true);
374 default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
375 default_dir_chooser->signal_current_folder_changed().connect (sigc::mem_fun (*this, &ArdourStartup::default_dir_changed));
376 default_dir_chooser->show ();
378 vbox->show_all ();
380 default_folder_page_index = append_page (*vbox);
381 set_page_title (*vbox, _("Default folder for new sessions"));
382 set_page_header_image (*vbox, icon_pixbuf);
383 set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
385 /* user can just skip all these settings if they want to */
387 set_page_complete (*vbox, true);
390 void
391 ArdourStartup::setup_monitoring_choice_page ()
393 mon_vbox.set_spacing (18);
394 mon_vbox.set_border_width (24);
396 HBox* hbox = manage (new HBox);
397 VBox* vbox = manage (new VBox);
398 RadioButton::Group g (monitor_via_hardware_button.get_group());
399 monitor_via_ardour_button.set_group (g);
401 monitor_label.set_markup(_("\
402 While recording instruments or vocals, you probably want to listen to the\n\
403 signal as well as record it. This is called \"monitoring\". There are\n\
404 different ways to do this depending on the equipment you have and the\n\
405 configuration of that equipment. The two most common are presented here.\n\
406 Please choose whichever one is right for your setup.\n\n\
407 <i>(You can change this preference at any time, via the Preferences dialog)</i>"));
408 monitor_label.set_alignment (0.0, 0.0);
410 vbox->set_spacing (6);
412 vbox->pack_start (monitor_via_hardware_button, false, true);
413 vbox->pack_start (monitor_via_ardour_button, false, true);
414 hbox->pack_start (*vbox, true, true, 8);
415 mon_vbox.pack_start (monitor_label, false, false);
416 mon_vbox.pack_start (*hbox, false, false);
418 mon_vbox.show_all ();
420 monitoring_page_index = append_page (mon_vbox);
421 set_page_title (mon_vbox, _("Monitoring Choices"));
422 set_page_header_image (mon_vbox, icon_pixbuf);
424 /* user could just click on "Forward" if default
425 * choice is correct.
428 set_page_complete (mon_vbox, true);
431 void
432 ArdourStartup::setup_monitor_section_choice_page ()
434 mon_sec_vbox.set_spacing (18);
435 mon_sec_vbox.set_border_width (24);
437 HBox* hbox = manage (new HBox);
438 VBox* main_vbox = manage (new VBox);
439 VBox* vbox;
440 Label* l = manage (new Label);
442 main_vbox->set_spacing (32);
444 no_monitor_section_button.set_label (_("Use a Master bus directly"));
445 l->set_alignment (0.0, 1.0);
446 l->set_markup(_("Connect the Master bus directly to your hardware outputs.\n\
447 <i>Preferable for simple use</i>."));
449 vbox = manage (new VBox);
450 vbox->set_spacing (6);
451 vbox->pack_start (no_monitor_section_button, false, true);
452 vbox->pack_start (*l, false, true);
454 main_vbox->pack_start (*vbox, false, false);
456 use_monitor_section_button.set_label (_("Use an additional Monitor bus"));
457 l = manage (new Label);
458 l->set_alignment (0.0, 1.0);
459 l->set_text (_("Use a Monitor bus between Master bus and hardware outputs for \n\
460 greater control in monitoring without affecting the mix."));
462 vbox = manage (new VBox);
463 vbox->set_spacing (6);
464 vbox->pack_start (use_monitor_section_button, false, true);
465 vbox->pack_start (*l, false, true);
467 main_vbox->pack_start (*vbox, false, false);
469 RadioButton::Group g (use_monitor_section_button.get_group());
470 no_monitor_section_button.set_group (g);
472 if (Config->get_use_monitor_bus()) {
473 use_monitor_section_button.set_active (true);
474 } else {
475 no_monitor_section_button.set_active (true);
478 use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
479 no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
481 monitor_section_label.set_markup(_("<i><small>(You can change this preference at any time, via the Preferences dialog)</small></i>"));
482 monitor_section_label.set_alignment (0.0, 0.0);
484 hbox->pack_start (*main_vbox, true, true, 8);
485 mon_sec_vbox.pack_start (*hbox, false, false);
486 mon_sec_vbox.pack_start (monitor_section_label, false, false);
488 mon_sec_vbox.show_all ();
490 monitor_section_page_index = append_page (mon_sec_vbox);
491 set_page_title (mon_sec_vbox, _("Monitor Section"));
492 set_page_header_image (mon_sec_vbox, icon_pixbuf);
494 /* user could just click on "Forward" if default
495 * choice is correct.
498 set_page_complete (mon_sec_vbox, true);
501 void
502 ArdourStartup::setup_initial_choice_page ()
504 ic_vbox.set_spacing (6);
505 ic_vbox.set_border_width (24);
507 RadioButton::Group g (ic_new_session_button.get_group());
508 ic_existing_session_button.set_group (g);
510 HBox* centering_hbox = manage (new HBox);
511 VBox* centering_vbox = manage (new VBox);
513 centering_vbox->set_spacing (6);
515 centering_vbox->pack_start (ic_new_session_button, false, true);
516 centering_vbox->pack_start (ic_existing_session_button, false, true);
518 ic_new_session_button.signal_button_press_event().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_press), false);
519 ic_new_session_button.signal_activate().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_activated), false);
521 ic_existing_session_button.signal_button_press_event().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_press), false);
522 ic_existing_session_button.signal_activate().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_activated), false);
524 centering_hbox->pack_start (*centering_vbox, true, true);
526 ic_vbox.pack_start (*centering_hbox, true, true);
528 ic_vbox.show_all ();
530 initial_choice_index = append_page (ic_vbox);
531 set_page_title (ic_vbox, _("What would you like to do ?"));
532 set_page_header_image (ic_vbox, icon_pixbuf);
534 /* user could just click on "Forward" if default
535 * choice is correct.
538 set_page_complete (ic_vbox, true);
541 bool
542 ArdourStartup::initial_button_press (GdkEventButton *event)
544 if (event && event->type == GDK_2BUTTON_PRESS && session_page_index != -1) {
545 set_current_page(session_page_index);
546 return true;
547 } else {
548 return false;
552 void
553 ArdourStartup::initial_button_activated ()
555 set_current_page(session_page_index);
558 void
559 ArdourStartup::setup_session_page ()
561 session_vbox.set_border_width (24);
563 session_vbox.pack_start (session_hbox, true, true);
564 session_vbox.show_all ();
566 session_page_index = append_page (session_vbox);
567 /* initial setting */
568 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
571 void
572 ArdourStartup::setup_final_page ()
574 final_page.set_text (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
575 final_page.show ();
576 final_page_index = append_page (final_page);
577 set_page_complete (final_page, true);
578 set_page_header_image (final_page, icon_pixbuf);
579 set_page_type (final_page, ASSISTANT_PAGE_CONFIRM);
582 void
583 ArdourStartup::on_cancel ()
585 _response = RESPONSE_CANCEL;
586 gtk_main_quit ();
589 bool
590 ArdourStartup::on_delete_event (GdkEventAny*)
592 _response = RESPONSE_CLOSE;
593 gtk_main_quit ();
594 return true;
597 void
598 ArdourStartup::on_apply ()
600 if (engine_dialog) {
601 engine_dialog->setup_engine ();
604 if (config_modified) {
606 if (default_dir_chooser) {
607 Config->set_default_session_parent_dir (default_dir_chooser->get_current_folder());
610 if (monitor_via_hardware_button.get_active()) {
611 Config->set_monitoring_model (ExternalMonitoring);
612 } else if (monitor_via_ardour_button.get_active()) {
613 Config->set_monitoring_model (SoftwareMonitoring);
616 Config->set_use_monitor_bus (use_monitor_section_button.get_active());
618 Config->save_state ();
621 _response = RESPONSE_OK;
622 gtk_main_quit ();
625 void
626 ArdourStartup::on_prepare (Gtk::Widget* page)
628 if (page == &session_vbox) {
630 if (ic_new_session_button.get_active()) {
631 /* new session requested */
632 setup_new_session_page ();
633 } else {
634 /* existing session requested */
635 setup_existing_session_page ();
639 /* HACK HACK HACK ... change the "Apply" button label
640 to say "Open"
643 Gtk::Widget* tl = session_vbox.get_toplevel();
644 Gtk::Window* win;
645 if ((win = dynamic_cast<Gtk::Window*>(tl)) != 0) {
646 /* ::get_default_widget() is not wrapped in gtkmm */
647 Gtk::Widget* def = wrap (gtk_window_get_default_widget (win->gobj()));
648 Gtk::Button* button;
649 if ((button = dynamic_cast<Gtk::Button*>(def)) != 0) {
650 button->set_label (_("Open"));
656 void
657 ArdourStartup::populate_session_templates ()
659 vector<TemplateInfo> templates;
661 find_session_templates (templates);
663 template_model->clear ();
665 for (vector<TemplateInfo>::iterator x = templates.begin(); x != templates.end(); ++x) {
666 TreeModel::Row row;
668 row = *(template_model->append ());
670 row[session_template_columns.name] = (*x).name;
671 row[session_template_columns.path] = (*x).path;
675 static bool
676 lost_name_entry_focus (GdkEventFocus*)
678 cerr << "lost focus\n";
679 return false;
682 void
683 ArdourStartup::setup_new_session_page ()
685 if (!session_hbox.get_children().empty()) {
686 session_hbox.remove (**session_hbox.get_children().begin());
689 session_new_vbox.set_spacing (18);
691 if (session_new_vbox.get_children().empty()) {
692 VBox *vbox1 = manage (new VBox);
693 HBox* hbox1 = manage (new HBox);
694 Label* label1 = manage (new Label);
696 vbox1->set_spacing (6);
698 hbox1->set_spacing (6);
699 hbox1->pack_start (*label1, false, false);
700 hbox1->pack_start (new_name_entry, true, true);
702 label1->set_text (_("Session name:"));
705 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
706 new_name_entry.set_text (Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name));
707 /* name provided - they can move right along */
708 set_page_complete (session_vbox, true);
711 new_name_entry.signal_changed().connect (sigc::mem_fun (*this, &ArdourStartup::new_name_changed));
712 new_name_entry.signal_activate().connect (sigc::mem_fun (*this, &ArdourStartup::move_along_now));
714 vbox1->pack_start (*hbox1, true, true);
716 /* --- */
718 HBox* hbox2 = manage (new HBox);
719 Label* label2 = manage (new Label);
721 hbox2->set_spacing (6);
722 hbox2->pack_start (*label2, false, false);
723 hbox2->pack_start (new_folder_chooser, true, true);
725 label2->set_text (_("Create session folder in:"));
727 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
728 new_folder_chooser.set_current_folder (poor_mans_glob (Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name)));
729 } else {
730 new_folder_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
732 new_folder_chooser.set_title (_("Select folder for session"));
734 #ifdef GTKOSX
735 new_folder_chooser.add_shortcut_folder ("/Volumes");
736 #endif
738 vbox1->pack_start (*hbox2, false, false);
740 session_new_vbox.pack_start (*vbox1, false, false);
742 /* --- */
744 VBox *vbox2 = manage (new VBox);
745 HBox* hbox3 = manage (new HBox);
746 Label* label3 = manage (new Label);
747 template_model = ListStore::create (session_template_columns);
748 populate_session_templates ();
750 vbox2->set_spacing (6);
752 label3->set_markup (_("<b>Options</b>"));
753 label3->set_alignment (0.0, 0.0);
755 vbox2->pack_start (*label3, false, true);
757 VBox *vbox3 = manage (new VBox);
759 vbox3->set_spacing (6);
761 if (!template_model->children().empty()) {
763 HBox* hbox4a = manage (new HBox);
764 use_template_button.set_label (_("Use this template"));
766 TreeModel::Row row = *template_model->prepend ();
767 row[session_template_columns.name] = (_("no template"));
768 row[session_template_columns.path] = string();
770 hbox4a->set_spacing (6);
771 hbox4a->pack_start (use_template_button, false, false);
772 hbox4a->pack_start (template_chooser, true, true);
774 template_chooser.set_model (template_model);
776 Gtk::CellRendererText* text_renderer = Gtk::manage (new Gtk::CellRendererText);
777 text_renderer->property_editable() = false;
779 template_chooser.pack_start (*text_renderer);
780 template_chooser.add_attribute (text_renderer->property_text(), session_template_columns.name);
781 template_chooser.set_active (0);
783 use_template_button.show();
784 template_chooser.show ();
786 vbox3->pack_start (*hbox4a, false, false);
789 /* --- */
791 if (!new_user) {
792 session_template_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
794 HBox* hbox4b = manage (new HBox);
795 use_session_as_template_button.set_label (_("Use an existing session as a template:"));
797 hbox4b->set_spacing (6);
798 hbox4b->pack_start (use_session_as_template_button, false, false);
799 hbox4b->pack_start (session_template_chooser, true, true);
801 use_session_as_template_button.show ();
802 session_template_chooser.show ();
804 Gtk::FileFilter* session_filter = manage (new (Gtk::FileFilter));
805 session_filter->add_pattern (X_("*.ardour"));
806 session_template_chooser.set_filter (*session_filter);
807 session_template_chooser.set_title (_("Select template"));
809 vbox3->pack_start (*hbox4b, false, false);
812 /* --- */
814 HBox* hbox5 = manage (new HBox);
816 hbox5->set_spacing (6);
817 hbox5->pack_start (more_new_session_options_button, false, false);
819 more_new_session_options_button.show ();
820 more_new_session_options_button.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::more_new_session_options_button_clicked));
822 vbox3->pack_start (*hbox5, false, false);
823 hbox3->pack_start (*vbox3, true, true, 8);
824 vbox2->pack_start (*hbox3, false, false);
826 /* --- */
828 session_new_vbox.pack_start (*vbox2, false, false);
831 session_new_vbox.show_all ();
832 session_hbox.pack_start (session_new_vbox, true, true);
833 set_page_title (session_vbox, _("New Session"));
834 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
836 new_name_entry.signal_map().connect (sigc::mem_fun (*this, &ArdourStartup::new_name_mapped));
837 new_name_entry.signal_focus_out_event().connect (sigc::ptr_fun (lost_name_entry_focus));
840 void
841 ArdourStartup::new_name_mapped ()
843 cerr << "Grab new name focus\n";
844 new_name_entry.grab_focus ();
847 void
848 ArdourStartup::new_name_changed ()
850 if (!new_name_entry.get_text().empty()) {
851 set_page_complete (session_vbox, true);
852 } else {
853 set_page_complete (session_vbox, false);
858 ArdourStartup::redisplay_recent_sessions ()
860 std::vector<sys::path> session_directories;
861 RecentSessionsSorter cmp;
863 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
864 recent_session_model->clear ();
866 ARDOUR::RecentSessions rs;
867 ARDOUR::read_recent_sessions (rs);
869 if (rs.empty()) {
870 recent_session_display.set_model (recent_session_model);
871 return 0;
874 // sort them alphabetically
875 sort (rs.begin(), rs.end(), cmp);
877 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
878 session_directories.push_back ((*i).second);
881 for (vector<sys::path>::const_iterator i = session_directories.begin(); i != session_directories.end(); ++i)
883 std::vector<sys::path> state_file_paths;
885 // now get available states for this session
887 get_state_files_in_directory (*i, state_file_paths);
889 vector<string*>* states;
890 vector<const gchar*> item;
891 string fullpath = (*i).to_string();
893 /* remove any trailing / */
895 if (fullpath[fullpath.length()-1] == '/') {
896 fullpath = fullpath.substr (0, fullpath.length()-1);
899 /* check whether session still exists */
900 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
901 /* session doesn't exist */
902 continue;
905 /* now get available states for this session */
907 if ((states = Session::possible_states (fullpath)) == 0) {
908 /* no state file? */
909 continue;
912 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
914 Gtk::TreeModel::Row row = *(recent_session_model->append());
916 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
917 row[recent_session_columns.fullpath] = fullpath;
919 if (state_file_names.size() > 1) {
921 // add the children
923 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
924 i2 != state_file_names.end(); ++i2)
927 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
929 child_row[recent_session_columns.visible_name] = *i2;
930 child_row[recent_session_columns.fullpath] = fullpath;
935 recent_session_display.set_model (recent_session_model);
936 return rs.size();
939 void
940 ArdourStartup::recent_session_row_selected ()
942 if (recent_session_display.get_selection()->count_selected_rows() > 0) {
943 set_page_complete (session_vbox, true);
944 } else {
945 set_page_complete (session_vbox, false);
949 void
950 ArdourStartup::setup_existing_session_page ()
952 recent_session_model = TreeStore::create (recent_session_columns);
953 redisplay_recent_sessions ();
955 if (!session_hbox.get_children().empty()) {
956 session_hbox.remove (**session_hbox.get_children().begin());
959 if (session_existing_vbox.get_children().empty()) {
961 recent_session_display.set_model (recent_session_model);
962 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
963 recent_session_display.set_headers_visible (false);
964 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
966 recent_session_display.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ArdourStartup::recent_session_row_selected));
968 recent_scroller.add (recent_session_display);
969 recent_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
970 recent_scroller.set_shadow_type (Gtk::SHADOW_IN);
972 recent_session_display.show();
974 recent_scroller.show();
975 int cnt = redisplay_recent_sessions ();
976 recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &ArdourStartup::recent_row_activated));
978 if (cnt > 4) {
979 recent_scroller.set_size_request (-1, 300);
982 session_existing_vbox.set_spacing (8);
983 session_existing_vbox.pack_start (recent_scroller, true, true);
985 existing_session_chooser.set_title (_("Select session file"));
986 existing_session_chooser.signal_file_set().connect (sigc::mem_fun (*this, &ArdourStartup::existing_session_selected));
988 #ifdef GTKOSX
989 existing_session_chooser.add_shortcut_folder ("/Volumes");
990 #endif
992 HBox* hbox = manage (new HBox);
993 hbox->set_spacing (4);
994 hbox->pack_start (*manage (new Label (_("Browse:"))), PACK_SHRINK);
995 hbox->pack_start (existing_session_chooser);
996 session_existing_vbox.pack_start (*hbox, false, false);
997 hbox->show_all ();
1000 session_existing_vbox.show_all ();
1001 session_hbox.pack_start (session_existing_vbox, true, true);
1003 set_page_title (session_vbox, _("Select a session"));
1004 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
1007 void
1008 ArdourStartup::more_new_session_options_button_clicked ()
1010 if (more_new_session_options_button.get_active()) {
1011 more_options_vbox.show_all ();
1012 set_page_type (more_options_vbox, ASSISTANT_PAGE_CONFIRM);
1013 set_page_type (session_vbox, ASSISTANT_PAGE_CONTENT);
1014 } else {
1015 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
1016 more_options_vbox.hide ();
1020 void
1021 ArdourStartup::setup_more_options_page ()
1023 more_options_vbox.set_border_width (24);
1025 _output_limit_count.set_adjustment (_output_limit_count_adj);
1026 _input_limit_count.set_adjustment (_input_limit_count_adj);
1027 _master_bus_channel_count.set_adjustment (_master_bus_channel_count_adj);
1029 chan_count_label_1.set_text (_("channels"));
1030 chan_count_label_3.set_text (_("channels"));
1031 chan_count_label_4.set_text (_("channels"));
1033 chan_count_label_1.set_alignment(0,0.5);
1034 chan_count_label_1.set_padding(0,0);
1035 chan_count_label_1.set_line_wrap(false);
1037 chan_count_label_3.set_alignment(0,0.5);
1038 chan_count_label_3.set_padding(0,0);
1039 chan_count_label_3.set_line_wrap(false);
1041 chan_count_label_4.set_alignment(0,0.5);
1042 chan_count_label_4.set_padding(0,0);
1043 chan_count_label_4.set_line_wrap(false);
1045 bus_label.set_markup (_("<b>Busses</b>"));
1046 input_label.set_markup (_("<b>Inputs</b>"));
1047 output_label.set_markup (_("<b>Outputs</b>"));
1049 _master_bus_channel_count.set_flags(Gtk::CAN_FOCUS);
1050 _master_bus_channel_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1051 _master_bus_channel_count.set_numeric(true);
1052 _master_bus_channel_count.set_digits(0);
1053 _master_bus_channel_count.set_wrap(false);
1055 _create_master_bus.set_label (_("Create master bus"));
1056 _create_master_bus.set_flags(Gtk::CAN_FOCUS);
1057 _create_master_bus.set_relief(Gtk::RELIEF_NORMAL);
1058 _create_master_bus.set_mode(true);
1059 _create_master_bus.set_active(true);
1060 _create_master_bus.set_border_width(0);
1062 advanced_table.set_row_spacings(0);
1063 advanced_table.set_col_spacings(0);
1065 _connect_inputs.set_label (_("Automatically connect to physical_inputs"));
1066 _connect_inputs.set_flags(Gtk::CAN_FOCUS);
1067 _connect_inputs.set_relief(Gtk::RELIEF_NORMAL);
1068 _connect_inputs.set_mode(true);
1069 _connect_inputs.set_active(true);
1070 _connect_inputs.set_border_width(0);
1072 _limit_input_ports.set_label (_("Use only"));
1073 _limit_input_ports.set_flags(Gtk::CAN_FOCUS);
1074 _limit_input_ports.set_relief(Gtk::RELIEF_NORMAL);
1075 _limit_input_ports.set_mode(true);
1076 _limit_input_ports.set_sensitive(true);
1077 _limit_input_ports.set_border_width(0);
1079 _input_limit_count.set_flags(Gtk::CAN_FOCUS);
1080 _input_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1081 _input_limit_count.set_numeric(true);
1082 _input_limit_count.set_digits(0);
1083 _input_limit_count.set_wrap(false);
1084 _input_limit_count.set_sensitive(false);
1086 bus_hbox.pack_start (bus_table, Gtk::PACK_SHRINK, 18);
1088 bus_label.set_alignment(0, 0.5);
1089 bus_label.set_padding(0,0);
1090 bus_label.set_line_wrap(false);
1091 bus_label.set_selectable(false);
1092 bus_label.set_use_markup(true);
1093 bus_frame.set_shadow_type(Gtk::SHADOW_NONE);
1094 bus_frame.set_label_align(0,0.5);
1095 bus_frame.add(bus_hbox);
1096 bus_frame.set_label_widget(bus_label);
1098 bus_table.set_row_spacings (0);
1099 bus_table.set_col_spacings (0);
1100 bus_table.attach (_create_master_bus, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
1101 bus_table.attach (_master_bus_channel_count, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
1102 bus_table.attach (chan_count_label_1, 2, 3, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 0);
1104 input_port_limit_hbox.pack_start(_limit_input_ports, Gtk::PACK_SHRINK, 6);
1105 input_port_limit_hbox.pack_start(_input_limit_count, Gtk::PACK_SHRINK, 0);
1106 input_port_limit_hbox.pack_start(chan_count_label_3, Gtk::PACK_SHRINK, 6);
1107 input_port_vbox.pack_start(_connect_inputs, Gtk::PACK_SHRINK, 0);
1108 input_port_vbox.pack_start(input_port_limit_hbox, Gtk::PACK_EXPAND_PADDING, 0);
1109 input_table.set_row_spacings(0);
1110 input_table.set_col_spacings(0);
1111 input_table.attach(input_port_vbox, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 6);
1113 input_hbox.pack_start (input_table, Gtk::PACK_SHRINK, 18);
1115 input_label.set_alignment(0, 0.5);
1116 input_label.set_padding(0,0);
1117 input_label.set_line_wrap(false);
1118 input_label.set_selectable(false);
1119 input_label.set_use_markup(true);
1120 input_frame.set_shadow_type(Gtk::SHADOW_NONE);
1121 input_frame.set_label_align(0,0.5);
1122 input_frame.add(input_hbox);
1123 input_frame.set_label_widget(input_label);
1125 _connect_outputs.set_label (_("Automatically connect outputs"));
1126 _connect_outputs.set_flags(Gtk::CAN_FOCUS);
1127 _connect_outputs.set_relief(Gtk::RELIEF_NORMAL);
1128 _connect_outputs.set_mode(true);
1129 _connect_outputs.set_active(true);
1130 _connect_outputs.set_border_width(0);
1131 _limit_output_ports.set_label (_("Use only"));
1132 _limit_output_ports.set_flags(Gtk::CAN_FOCUS);
1133 _limit_output_ports.set_relief(Gtk::RELIEF_NORMAL);
1134 _limit_output_ports.set_mode(true);
1135 _limit_output_ports.set_sensitive(true);
1136 _limit_output_ports.set_border_width(0);
1137 _output_limit_count.set_flags(Gtk::CAN_FOCUS);
1138 _output_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1139 _output_limit_count.set_numeric(false);
1140 _output_limit_count.set_digits(0);
1141 _output_limit_count.set_wrap(false);
1142 _output_limit_count.set_sensitive(false);
1143 output_port_limit_hbox.pack_start(_limit_output_ports, Gtk::PACK_SHRINK, 6);
1144 output_port_limit_hbox.pack_start(_output_limit_count, Gtk::PACK_SHRINK, 0);
1145 output_port_limit_hbox.pack_start(chan_count_label_4, Gtk::PACK_SHRINK, 6);
1147 _connect_outputs_to_master.set_label (_("... to master bus"));
1148 _connect_outputs_to_master.set_flags(Gtk::CAN_FOCUS);
1149 _connect_outputs_to_master.set_relief(Gtk::RELIEF_NORMAL);
1150 _connect_outputs_to_master.set_mode(true);
1151 _connect_outputs_to_master.set_active(false);
1152 _connect_outputs_to_master.set_border_width(0);
1154 _connect_outputs_to_master.set_group (connect_outputs_group);
1155 _connect_outputs_to_physical.set_group (connect_outputs_group);
1157 _connect_outputs_to_physical.set_label (_("... to physical outputs"));
1158 _connect_outputs_to_physical.set_flags(Gtk::CAN_FOCUS);
1159 _connect_outputs_to_physical.set_relief(Gtk::RELIEF_NORMAL);
1160 _connect_outputs_to_physical.set_mode(true);
1161 _connect_outputs_to_physical.set_active(false);
1162 _connect_outputs_to_physical.set_border_width(0);
1164 output_conn_vbox.pack_start(_connect_outputs, Gtk::PACK_SHRINK, 0);
1165 output_conn_vbox.pack_start(_connect_outputs_to_master, Gtk::PACK_SHRINK, 0);
1166 output_conn_vbox.pack_start(_connect_outputs_to_physical, Gtk::PACK_SHRINK, 0);
1167 output_vbox.set_border_width(6);
1169 output_port_vbox.pack_start(output_port_limit_hbox, Gtk::PACK_SHRINK, 0);
1171 output_vbox.pack_start(output_conn_vbox);
1172 output_vbox.pack_start(output_port_vbox);
1174 output_label.set_alignment(0, 0.5);
1175 output_label.set_padding(0,0);
1176 output_label.set_line_wrap(false);
1177 output_label.set_selectable(false);
1178 output_label.set_use_markup(true);
1179 output_frame.set_shadow_type(Gtk::SHADOW_NONE);
1180 output_frame.set_label_align(0,0.5);
1182 output_hbox.pack_start (output_vbox, Gtk::PACK_SHRINK, 18);
1184 output_frame.add(output_hbox);
1185 output_frame.set_label_widget(output_label);
1187 more_options_vbox.pack_start(advanced_table, Gtk::PACK_SHRINK, 0);
1188 more_options_vbox.pack_start(bus_frame, Gtk::PACK_SHRINK, 6);
1189 more_options_vbox.pack_start(input_frame, Gtk::PACK_SHRINK, 6);
1190 more_options_vbox.pack_start(output_frame, Gtk::PACK_SHRINK, 0);
1192 /* signals */
1194 _connect_inputs.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::connect_inputs_clicked));
1195 _connect_outputs.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::connect_outputs_clicked));
1196 _limit_input_ports.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::limit_inputs_clicked));
1197 _limit_output_ports.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::limit_outputs_clicked));
1198 _create_master_bus.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::master_bus_button_clicked));
1200 /* note that more_options_vbox is NOT visible by
1201 * default. this is entirely by design - this page
1202 * should be skipped unless explicitly requested.
1205 session_options_page_index = append_page (more_options_vbox);
1206 set_page_title (more_options_vbox, _("Advanced Session Options"));
1207 set_page_complete (more_options_vbox, true);
1210 bool
1211 ArdourStartup::create_master_bus() const
1213 return _create_master_bus.get_active();
1217 ArdourStartup::master_channel_count() const
1219 return _master_bus_channel_count.get_value_as_int();
1222 bool
1223 ArdourStartup::connect_inputs() const
1225 return _connect_inputs.get_active();
1228 bool
1229 ArdourStartup::limit_inputs_used_for_connection() const
1231 return _limit_input_ports.get_active();
1235 ArdourStartup::input_limit_count() const
1237 return _input_limit_count.get_value_as_int();
1240 bool
1241 ArdourStartup::connect_outputs() const
1243 return _connect_outputs.get_active();
1246 bool
1247 ArdourStartup::limit_outputs_used_for_connection() const
1249 return _limit_output_ports.get_active();
1253 ArdourStartup::output_limit_count() const
1255 return _output_limit_count.get_value_as_int();
1258 bool
1259 ArdourStartup::connect_outs_to_master() const
1261 return _connect_outputs_to_master.get_active();
1264 bool
1265 ArdourStartup::connect_outs_to_physical() const
1267 return _connect_outputs_to_physical.get_active();
1270 void
1271 ArdourStartup::connect_inputs_clicked ()
1273 _limit_input_ports.set_sensitive(_connect_inputs.get_active());
1275 if (_connect_inputs.get_active() && _limit_input_ports.get_active()) {
1276 _input_limit_count.set_sensitive(true);
1277 } else {
1278 _input_limit_count.set_sensitive(false);
1282 void
1283 ArdourStartup::connect_outputs_clicked ()
1285 _limit_output_ports.set_sensitive(_connect_outputs.get_active());
1287 if (_connect_outputs.get_active() && _limit_output_ports.get_active()) {
1288 _output_limit_count.set_sensitive(true);
1289 } else {
1290 _output_limit_count.set_sensitive(false);
1294 void
1295 ArdourStartup::limit_inputs_clicked ()
1297 _input_limit_count.set_sensitive(_limit_input_ports.get_active());
1300 void
1301 ArdourStartup::limit_outputs_clicked ()
1303 _output_limit_count.set_sensitive(_limit_output_ports.get_active());
1306 void
1307 ArdourStartup::master_bus_button_clicked ()
1309 bool yn = _create_master_bus.get_active();
1311 _master_bus_channel_count.set_sensitive(yn);
1314 void
1315 ArdourStartup::move_along_now ()
1317 gint cur = get_current_page ();
1319 if (cur == session_page_index) {
1320 if (more_new_session_options_button.get_active()) {
1321 set_current_page (session_options_page_index);
1322 } else {
1323 on_apply ();
1328 void
1329 ArdourStartup::recent_row_activated (const Gtk::TreePath&, Gtk::TreeViewColumn*)
1331 set_page_complete (session_vbox, true);
1332 move_along_now ();
1335 void
1336 ArdourStartup::existing_session_selected ()
1338 _existing_session_chooser_used = true;
1340 set_page_complete (session_vbox, true);
1341 move_along_now ();