Fix a couple of minor typos.
[ardour2.git] / gtk2_ardour / startup.cc
blob1cf32824ed81be42a92a3875a0fa750739f47e6b
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) {
115 /* Create the config directory so that we have somewhere to put the
116 been_here_before file.
118 try {
119 sys::create_directories (user_config_directory ());
121 catch (const sys::filesystem_error& ex) {
122 error << "Could not create user configuration directory" << endmsg;
125 /* "touch" the file */
126 ofstream fout (been_here_before.to_string().c_str());
127 setup_new_user_page ();
128 setup_first_time_config_page ();
129 setup_monitoring_choice_page ();
130 setup_monitor_section_choice_page ();
132 if (need_audio_setup) {
133 setup_audio_page ();
136 } else {
138 if (need_audio_setup) {
139 setup_audio_page ();
142 setup_initial_choice_page ();
145 setup_session_page ();
146 setup_more_options_page ();
148 if (new_user) {
149 setup_final_page ();
152 the_startup = this;
155 ArdourStartup::~ArdourStartup ()
159 void
160 ArdourStartup::setup_alpha_page ()
162 VBox* vbox = manage (new VBox);
163 Label* label = manage (new Label);
164 label->set_markup (_("<b>Welcome to this ALPHA release of Ardour 3.0</b>\n\n\
165 There are still many issues and bugs to be worked on,\n\
166 as well as general workflow improvements, before this can be considered\n\
167 release software. So, a few guidelines:\n\
169 1) Please do <b>NOT</b> use this software with the expectation that it is stable or reliable\n\
170 though it may be so, depending on your workflow.\n\
171 2) Please see http://ardour.org/a3_features for a guide to new features.\n\
172 3) <b>Please do NOT use the forums at ardour.org to report issues</b>.\n\
173 4) Please <b>DO</b> use the bugtracker at http://tracker.ardour.org/ to report issues\n\
174 making sure to note the product version number as 3.0-alpha.\n\
175 5) Please <b>DO</b> use the ardour-users mailing list to discuss ideas and pass on comments.\n\
176 6) Please <b>DO</b> join us on IRC for real time discussions about ardour3. You\n\
177 can get there directly from Ardour via the Help->Chat menu option.\n\
179 Full information on all the above can be found on the support page at\n\
181 http://ardour.org/support\n\
182 "));
184 vbox->set_border_width (12);
185 vbox->pack_start (*label, false, false, 12);
186 vbox->show_all ();
188 append_page (*vbox);
189 set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
190 set_page_title (*vbox, _("This is an ALPHA RELEASE"));
191 set_page_complete (*vbox, true);
194 void
195 ArdourStartup::set_new_only (bool yn)
197 new_only = yn;
199 if (new_only) {
200 ic_vbox.hide ();
201 } else {
202 ic_vbox.show ();
206 void
207 ArdourStartup::set_load_template (string load_template)
209 use_template_button.set_active (false);
210 load_template_override = load_template;
213 bool
214 ArdourStartup::use_session_template ()
216 if (!load_template_override.empty()) {
217 return true;
220 if (use_template_button.get_active()) {
221 return template_chooser.get_active_row_number() > 0;
222 } else {
223 return !session_template_chooser.get_filename().empty();
227 std::string
228 ArdourStartup::session_template_name ()
230 if (!load_template_override.empty()) {
231 string the_path = (ARDOUR::user_template_directory()/ (load_template_override + ".template")).to_string();
232 return the_path;
235 if (ic_existing_session_button.get_active()) {
236 return string();
239 if (use_template_button.get_active()) {
240 TreeModel::iterator iter = template_chooser.get_active ();
241 TreeModel::Row row = (*iter);
242 string s = row[session_template_columns.path];
243 return s;
244 } else {
245 return session_template_chooser.get_filename();
250 std::string
251 ArdourStartup::session_name (bool& should_be_new)
253 if (ic_new_session_button.get_active()) {
254 should_be_new = true;
255 string val = new_name_entry.get_text ();
256 strip_whitespace_edges (val);
257 return val;
258 } else if (_existing_session_chooser_used) {
259 /* existing session chosen from file chooser */
260 should_be_new = false;
261 return existing_session_chooser.get_filename ();
262 } else {
263 /* existing session chosen from recent list */
264 should_be_new = false;
266 TreeIter iter = recent_session_display.get_selection()->get_selected();
268 if (iter) {
269 return (*iter)[recent_session_columns.visible_name];
272 return "";
276 std::string
277 ArdourStartup::session_folder ()
279 if (ic_new_session_button.get_active()) {
280 std::string legal_session_folder_name = legalize_for_path (new_name_entry.get_text());
281 return Glib::build_filename (new_folder_chooser.get_current_folder(), legal_session_folder_name);
282 } else if (_existing_session_chooser_used) {
283 /* existing session chosen from file chooser */
284 return existing_session_chooser.get_current_folder ();
285 } else {
286 /* existing session chosen from recent list */
287 TreeIter iter = recent_session_display.get_selection()->get_selected();
289 if (iter) {
290 return (*iter)[recent_session_columns.fullpath];
292 return "";
296 void
297 ArdourStartup::setup_audio_page ()
299 engine_dialog = manage (new EngineControl);
301 engine_dialog->set_border_width (12);
303 engine_dialog->show_all ();
305 audio_page_index = append_page (*engine_dialog);
306 set_page_type (*engine_dialog, ASSISTANT_PAGE_CONTENT);
307 set_page_title (*engine_dialog, _("Audio / MIDI Setup"));
309 /* the default parameters should work, so the page is potentially complete */
311 set_page_complete (*engine_dialog, true);
314 void
315 ArdourStartup::setup_new_user_page ()
317 Label* foomatic = manage (new Label);
319 foomatic->set_markup (string_compose (_("\
320 <span size=\"larger\">%1 is a digital audio workstation. You can use it to\n\
321 record, edit and mix multi-track audio. You can produce your\n\
322 own CDs, mix video soundtracks, or just experiment with new\n\
323 ideas about music and sound.\n\
325 There are a few things that need to configured before you start\n\
326 using the program.</span>\
327 "), PROGRAM_NAME));
329 HBox* hbox = manage (new HBox);
330 HBox* vbox = manage (new HBox);
332 vbox->set_border_width (24);
334 hbox->pack_start (*foomatic, true, true);
335 vbox->pack_start (*hbox, true, true);
337 foomatic->show ();
338 hbox->show ();
339 vbox->show ();
341 new_user_page_index = append_page (*vbox);
342 set_page_type (*vbox, ASSISTANT_PAGE_INTRO);
343 set_page_title (*vbox, string_compose (_("Welcome to %1"), PROGRAM_NAME));
344 set_page_header_image (*vbox, icon_pixbuf);
345 set_page_complete (*vbox, true);
348 void
349 ArdourStartup::default_dir_changed ()
351 Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
352 config_changed ();
355 void
356 ArdourStartup::config_changed ()
358 config_modified = true;
361 void
362 ArdourStartup::setup_first_time_config_page ()
364 default_dir_chooser = manage (new FileChooserButton (string_compose (_("Default folder for %1 sessions"), PROGRAM_NAME),
365 FILE_CHOOSER_ACTION_SELECT_FOLDER));
366 Gtk::Label* txt = manage (new Label);
367 HBox* hbox = manage (new HBox);
368 VBox* vbox = manage (new VBox);
370 txt->set_markup (string_compose (_("\
371 Each project that you work on with %1 has its own folder.\n\
372 These can require a lot of disk space if you are recording audio.\n\
374 Where would you like new %1 sessions to be stored by default?\n\n\
375 <i>(You can put new sessions anywhere, this is just a default)</i>"), PROGRAM_NAME));
376 txt->set_alignment (0.0, 0.0);
378 vbox->set_spacing (18);
379 vbox->set_border_width (24);
381 hbox->pack_start (*default_dir_chooser, false, true, 8);
382 vbox->pack_start (*txt, false, false);
383 vbox->pack_start (*hbox, false, true);
385 default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
386 default_dir_chooser->signal_current_folder_changed().connect (sigc::mem_fun (*this, &ArdourStartup::default_dir_changed));
387 default_dir_chooser->show ();
389 vbox->show_all ();
391 default_folder_page_index = append_page (*vbox);
392 set_page_title (*vbox, _("Default folder for new sessions"));
393 set_page_header_image (*vbox, icon_pixbuf);
394 set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
396 /* user can just skip all these settings if they want to */
398 set_page_complete (*vbox, true);
401 void
402 ArdourStartup::setup_monitoring_choice_page ()
404 mon_vbox.set_spacing (18);
405 mon_vbox.set_border_width (24);
407 HBox* hbox = manage (new HBox);
408 VBox* vbox = manage (new VBox);
409 RadioButton::Group g (monitor_via_hardware_button.get_group());
410 monitor_via_ardour_button.set_group (g);
412 monitor_label.set_markup(_("\
413 While recording instruments or vocals, you probably want to listen to the\n\
414 signal as well as record it. This is called \"monitoring\". There are\n\
415 different ways to do this depending on the equipment you have and the\n\
416 configuration of that equipment. The two most common are presented here.\n\
417 Please choose whichever one is right for your setup.\n\n\
418 <i>(You can change this preference at any time, via the Preferences dialog)</i>"));
419 monitor_label.set_alignment (0.0, 0.0);
421 vbox->set_spacing (6);
423 vbox->pack_start (monitor_via_hardware_button, false, true);
424 vbox->pack_start (monitor_via_ardour_button, false, true);
425 hbox->pack_start (*vbox, true, true, 8);
426 mon_vbox.pack_start (monitor_label, false, false);
427 mon_vbox.pack_start (*hbox, false, false);
429 mon_vbox.show_all ();
431 monitoring_page_index = append_page (mon_vbox);
432 set_page_title (mon_vbox, _("Monitoring Choices"));
433 set_page_header_image (mon_vbox, icon_pixbuf);
435 /* user could just click on "Forward" if default
436 * choice is correct.
439 set_page_complete (mon_vbox, true);
442 void
443 ArdourStartup::setup_monitor_section_choice_page ()
445 mon_sec_vbox.set_spacing (18);
446 mon_sec_vbox.set_border_width (24);
448 HBox* hbox = manage (new HBox);
449 VBox* main_vbox = manage (new VBox);
450 VBox* vbox;
451 Label* l = manage (new Label);
453 main_vbox->set_spacing (32);
455 no_monitor_section_button.set_label (_("Use a Master bus directly"));
456 l->set_alignment (0.0, 1.0);
457 l->set_markup(_("Connect the Master bus directly to your hardware outputs.\n\
458 <i>Preferable for simple use</i>."));
460 vbox = manage (new VBox);
461 vbox->set_spacing (6);
462 vbox->pack_start (no_monitor_section_button, false, true);
463 vbox->pack_start (*l, false, true);
465 main_vbox->pack_start (*vbox, false, false);
467 use_monitor_section_button.set_label (_("Use an additional Monitor bus"));
468 l = manage (new Label);
469 l->set_alignment (0.0, 1.0);
470 l->set_text (_("Use a Monitor bus between Master bus and hardware outputs for \n\
471 greater control in monitoring without affecting the mix."));
473 vbox = manage (new VBox);
474 vbox->set_spacing (6);
475 vbox->pack_start (use_monitor_section_button, false, true);
476 vbox->pack_start (*l, false, true);
478 main_vbox->pack_start (*vbox, false, false);
480 RadioButton::Group g (use_monitor_section_button.get_group());
481 no_monitor_section_button.set_group (g);
483 if (Config->get_use_monitor_bus()) {
484 use_monitor_section_button.set_active (true);
485 } else {
486 no_monitor_section_button.set_active (true);
489 use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
490 no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
492 monitor_section_label.set_markup(_("<i><small>(You can change this preference at any time, via the Preferences dialog)</small></i>"));
493 monitor_section_label.set_alignment (0.0, 0.0);
495 hbox->pack_start (*main_vbox, true, true, 8);
496 mon_sec_vbox.pack_start (*hbox, false, false);
497 mon_sec_vbox.pack_start (monitor_section_label, false, false);
499 mon_sec_vbox.show_all ();
501 monitor_section_page_index = append_page (mon_sec_vbox);
502 set_page_title (mon_sec_vbox, _("Monitor Section"));
503 set_page_header_image (mon_sec_vbox, icon_pixbuf);
505 /* user could just click on "Forward" if default
506 * choice is correct.
509 set_page_complete (mon_sec_vbox, true);
512 void
513 ArdourStartup::setup_initial_choice_page ()
515 ic_vbox.set_spacing (6);
516 ic_vbox.set_border_width (24);
518 RadioButton::Group g (ic_new_session_button.get_group());
519 ic_existing_session_button.set_group (g);
521 HBox* centering_hbox = manage (new HBox);
522 VBox* centering_vbox = manage (new VBox);
524 centering_vbox->set_spacing (6);
526 centering_vbox->pack_start (ic_new_session_button, false, true);
527 centering_vbox->pack_start (ic_existing_session_button, false, true);
529 ic_new_session_button.signal_button_press_event().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_press), false);
530 ic_new_session_button.signal_activate().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_activated), false);
532 ic_existing_session_button.signal_button_press_event().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_press), false);
533 ic_existing_session_button.signal_activate().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_activated), false);
535 centering_hbox->pack_start (*centering_vbox, true, true);
537 ic_vbox.pack_start (*centering_hbox, true, true);
539 ic_vbox.show_all ();
541 initial_choice_index = append_page (ic_vbox);
542 set_page_title (ic_vbox, _("What would you like to do ?"));
543 set_page_header_image (ic_vbox, icon_pixbuf);
545 /* user could just click on "Forward" if default
546 * choice is correct.
549 set_page_complete (ic_vbox, true);
552 bool
553 ArdourStartup::initial_button_press (GdkEventButton *event)
555 if (event && event->type == GDK_2BUTTON_PRESS && session_page_index != -1) {
556 set_current_page(session_page_index);
557 return true;
558 } else {
559 return false;
563 void
564 ArdourStartup::initial_button_activated ()
566 set_current_page(session_page_index);
569 void
570 ArdourStartup::setup_session_page ()
572 session_vbox.set_border_width (24);
574 session_vbox.pack_start (session_hbox, true, true);
575 session_vbox.show_all ();
577 session_page_index = append_page (session_vbox);
578 /* initial setting */
579 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
582 void
583 ArdourStartup::setup_final_page ()
585 final_page.set_text (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
586 final_page.show ();
587 final_page_index = append_page (final_page);
588 set_page_complete (final_page, true);
589 set_page_header_image (final_page, icon_pixbuf);
590 set_page_type (final_page, ASSISTANT_PAGE_CONFIRM);
593 void
594 ArdourStartup::on_cancel ()
596 _response = RESPONSE_CANCEL;
597 gtk_main_quit ();
600 bool
601 ArdourStartup::on_delete_event (GdkEventAny*)
603 _response = RESPONSE_CLOSE;
604 gtk_main_quit ();
605 return true;
608 void
609 ArdourStartup::on_apply ()
611 if (engine_dialog) {
612 engine_dialog->setup_engine ();
615 if (config_modified) {
617 if (default_dir_chooser) {
618 Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
621 if (monitor_via_hardware_button.get_active()) {
622 Config->set_monitoring_model (ExternalMonitoring);
623 } else if (monitor_via_ardour_button.get_active()) {
624 Config->set_monitoring_model (SoftwareMonitoring);
627 Config->set_use_monitor_bus (use_monitor_section_button.get_active());
629 Config->save_state ();
632 _response = RESPONSE_OK;
633 gtk_main_quit ();
636 void
637 ArdourStartup::on_prepare (Gtk::Widget* page)
639 if (page == &session_vbox) {
641 if (ic_new_session_button.get_active()) {
642 /* new session requested */
643 setup_new_session_page ();
644 } else {
645 /* existing session requested */
646 setup_existing_session_page ();
650 /* HACK HACK HACK ... change the "Apply" button label
651 to say "Open"
654 Gtk::Widget* tl = session_vbox.get_toplevel();
655 Gtk::Window* win;
656 if ((win = dynamic_cast<Gtk::Window*>(tl)) != 0) {
657 /* ::get_default_widget() is not wrapped in gtkmm */
658 Gtk::Widget* def = wrap (gtk_window_get_default_widget (win->gobj()));
659 Gtk::Button* button;
660 if ((button = dynamic_cast<Gtk::Button*>(def)) != 0) {
661 if (more_new_session_options_button.get_active()) {
662 button->set_label (_("Forward"));
663 }else{
664 button->set_label (_("Open"));
671 void
672 ArdourStartup::populate_session_templates ()
674 vector<TemplateInfo> templates;
676 find_session_templates (templates);
678 template_model->clear ();
680 for (vector<TemplateInfo>::iterator x = templates.begin(); x != templates.end(); ++x) {
681 TreeModel::Row row;
683 row = *(template_model->append ());
685 row[session_template_columns.name] = (*x).name;
686 row[session_template_columns.path] = (*x).path;
690 static bool
691 lost_name_entry_focus (GdkEventFocus*)
693 cerr << "lost focus\n";
694 return false;
697 void
698 ArdourStartup::setup_new_session_page ()
700 if (!session_hbox.get_children().empty()) {
701 session_hbox.remove (**session_hbox.get_children().begin());
704 session_new_vbox.set_spacing (18);
706 if (session_new_vbox.get_children().empty()) {
707 VBox *vbox1 = manage (new VBox);
708 HBox* hbox1 = manage (new HBox);
709 Label* label1 = manage (new Label);
711 vbox1->set_spacing (6);
713 hbox1->set_spacing (6);
714 hbox1->pack_start (*label1, false, false);
715 hbox1->pack_start (new_name_entry, true, true);
717 label1->set_text (_("Session name:"));
720 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
721 new_name_entry.set_text (Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name));
722 /* name provided - they can move right along */
723 set_page_complete (session_vbox, true);
726 new_name_entry.signal_changed().connect (sigc::mem_fun (*this, &ArdourStartup::new_name_changed));
727 new_name_entry.signal_activate().connect (sigc::mem_fun (*this, &ArdourStartup::move_along_now));
729 vbox1->pack_start (*hbox1, true, true);
731 /* --- */
733 HBox* hbox2 = manage (new HBox);
734 Label* label2 = manage (new Label);
736 hbox2->set_spacing (6);
737 hbox2->pack_start (*label2, false, false);
738 hbox2->pack_start (new_folder_chooser, true, true);
740 label2->set_text (_("Create session folder in:"));
742 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
743 new_folder_chooser.set_current_folder (poor_mans_glob (Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name)));
744 } else {
745 new_folder_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
747 new_folder_chooser.set_title (_("Select folder for session"));
749 #ifdef GTKOSX
750 new_folder_chooser.add_shortcut_folder ("/Volumes");
751 #endif
753 vbox1->pack_start (*hbox2, false, false);
755 session_new_vbox.pack_start (*vbox1, false, false);
757 /* --- */
759 VBox *vbox2 = manage (new VBox);
760 HBox* hbox3 = manage (new HBox);
761 Label* label3 = manage (new Label);
762 template_model = ListStore::create (session_template_columns);
763 populate_session_templates ();
765 vbox2->set_spacing (6);
767 label3->set_markup (_("<b>Options</b>"));
768 label3->set_alignment (0.0, 0.0);
770 vbox2->pack_start (*label3, false, true);
772 VBox *vbox3 = manage (new VBox);
774 vbox3->set_spacing (6);
776 if (!template_model->children().empty()) {
778 HBox* hbox4a = manage (new HBox);
779 use_template_button.set_label (_("Use this template"));
781 TreeModel::Row row = *template_model->prepend ();
782 row[session_template_columns.name] = (_("no template"));
783 row[session_template_columns.path] = string();
785 hbox4a->set_spacing (6);
786 hbox4a->pack_start (use_template_button, false, false);
787 hbox4a->pack_start (template_chooser, true, true);
789 template_chooser.set_model (template_model);
791 Gtk::CellRendererText* text_renderer = Gtk::manage (new Gtk::CellRendererText);
792 text_renderer->property_editable() = false;
794 template_chooser.pack_start (*text_renderer);
795 template_chooser.add_attribute (text_renderer->property_text(), session_template_columns.name);
796 template_chooser.set_active (0);
798 use_template_button.show();
799 template_chooser.show ();
801 vbox3->pack_start (*hbox4a, false, false);
804 /* --- */
806 if (!new_user) {
807 session_template_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
809 HBox* hbox4b = manage (new HBox);
810 use_session_as_template_button.set_label (_("Use an existing session as a template:"));
812 hbox4b->set_spacing (6);
813 hbox4b->pack_start (use_session_as_template_button, false, false);
814 hbox4b->pack_start (session_template_chooser, true, true);
816 use_session_as_template_button.show ();
817 session_template_chooser.show ();
819 Gtk::FileFilter* session_filter = manage (new (Gtk::FileFilter));
820 session_filter->add_pattern (X_("*.ardour"));
821 session_template_chooser.set_filter (*session_filter);
822 session_template_chooser.set_title (_("Select template"));
824 vbox3->pack_start (*hbox4b, false, false);
827 /* --- */
829 HBox* hbox5 = manage (new HBox);
831 hbox5->set_spacing (6);
832 hbox5->pack_start (more_new_session_options_button, false, false);
834 more_new_session_options_button.show ();
835 more_new_session_options_button.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::more_new_session_options_button_clicked));
837 vbox3->pack_start (*hbox5, false, false);
838 hbox3->pack_start (*vbox3, true, true, 8);
839 vbox2->pack_start (*hbox3, false, false);
841 /* --- */
843 session_new_vbox.pack_start (*vbox2, false, false);
846 session_new_vbox.show_all ();
847 session_hbox.pack_start (session_new_vbox, true, true);
848 set_page_title (session_vbox, _("New Session"));
849 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
851 if (more_new_session_options_button.get_active()) {
852 set_page_type (session_vbox, ASSISTANT_PAGE_CONTENT);
855 new_name_entry.signal_map().connect (sigc::mem_fun (*this, &ArdourStartup::new_name_mapped));
856 new_name_entry.signal_focus_out_event().connect (sigc::ptr_fun (lost_name_entry_focus));
859 void
860 ArdourStartup::new_name_mapped ()
862 cerr << "Grab new name focus\n";
863 new_name_entry.grab_focus ();
866 void
867 ArdourStartup::new_name_changed ()
869 if (!new_name_entry.get_text().empty()) {
870 set_page_complete (session_vbox, true);
871 } else {
872 set_page_complete (session_vbox, false);
877 ArdourStartup::redisplay_recent_sessions ()
879 std::vector<sys::path> session_directories;
880 RecentSessionsSorter cmp;
882 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
883 recent_session_model->clear ();
885 ARDOUR::RecentSessions rs;
886 ARDOUR::read_recent_sessions (rs);
888 if (rs.empty()) {
889 recent_session_display.set_model (recent_session_model);
890 return 0;
893 // sort them alphabetically
894 sort (rs.begin(), rs.end(), cmp);
896 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
897 session_directories.push_back ((*i).second);
900 for (vector<sys::path>::const_iterator i = session_directories.begin(); i != session_directories.end(); ++i)
902 std::vector<sys::path> state_file_paths;
904 // now get available states for this session
906 get_state_files_in_directory (*i, state_file_paths);
908 vector<string*>* states;
909 vector<const gchar*> item;
910 string fullpath = (*i).to_string();
912 /* remove any trailing / */
914 if (fullpath[fullpath.length()-1] == '/') {
915 fullpath = fullpath.substr (0, fullpath.length()-1);
918 /* check whether session still exists */
919 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
920 /* session doesn't exist */
921 continue;
924 /* now get available states for this session */
926 if ((states = Session::possible_states (fullpath)) == 0) {
927 /* no state file? */
928 continue;
931 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
933 Gtk::TreeModel::Row row = *(recent_session_model->append());
935 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
936 row[recent_session_columns.fullpath] = fullpath;
938 if (state_file_names.size() > 1) {
940 // add the children
942 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
943 i2 != state_file_names.end(); ++i2)
946 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
948 child_row[recent_session_columns.visible_name] = *i2;
949 child_row[recent_session_columns.fullpath] = fullpath;
954 recent_session_display.set_model (recent_session_model);
955 return rs.size();
958 void
959 ArdourStartup::recent_session_row_selected ()
961 if (recent_session_display.get_selection()->count_selected_rows() > 0) {
962 set_page_complete (session_vbox, true);
963 } else {
964 set_page_complete (session_vbox, false);
968 void
969 ArdourStartup::setup_existing_session_page ()
971 recent_session_model = TreeStore::create (recent_session_columns);
972 redisplay_recent_sessions ();
974 if (!session_hbox.get_children().empty()) {
975 session_hbox.remove (**session_hbox.get_children().begin());
978 if (session_existing_vbox.get_children().empty()) {
980 recent_session_display.set_model (recent_session_model);
981 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
982 recent_session_display.set_headers_visible (false);
983 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
985 recent_session_display.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ArdourStartup::recent_session_row_selected));
987 recent_scroller.add (recent_session_display);
988 recent_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
989 recent_scroller.set_shadow_type (Gtk::SHADOW_IN);
991 recent_session_display.show();
993 recent_scroller.show();
994 int cnt = redisplay_recent_sessions ();
995 recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &ArdourStartup::recent_row_activated));
997 if (cnt > 4) {
998 recent_scroller.set_size_request (-1, 300);
1001 session_existing_vbox.set_spacing (8);
1002 session_existing_vbox.pack_start (recent_scroller, true, true);
1004 existing_session_chooser.set_title (_("Select session file"));
1005 existing_session_chooser.signal_file_set().connect (sigc::mem_fun (*this, &ArdourStartup::existing_session_selected));
1007 #ifdef GTKOSX
1008 existing_session_chooser.add_shortcut_folder ("/Volumes");
1009 #endif
1011 HBox* hbox = manage (new HBox);
1012 hbox->set_spacing (4);
1013 hbox->pack_start (*manage (new Label (_("Browse:"))), PACK_SHRINK);
1014 hbox->pack_start (existing_session_chooser);
1015 session_existing_vbox.pack_start (*hbox, false, false);
1016 hbox->show_all ();
1019 session_existing_vbox.show_all ();
1020 session_hbox.pack_start (session_existing_vbox, true, true);
1022 set_page_title (session_vbox, _("Select a session"));
1023 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
1026 void
1027 ArdourStartup::more_new_session_options_button_clicked ()
1029 if (more_new_session_options_button.get_active()) {
1030 more_options_vbox.show_all ();
1031 set_page_type (more_options_vbox, ASSISTANT_PAGE_CONFIRM);
1032 set_page_type (session_vbox, ASSISTANT_PAGE_CONTENT);
1033 } else {
1034 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
1035 more_options_vbox.hide ();
1039 void
1040 ArdourStartup::setup_more_options_page ()
1042 more_options_vbox.set_border_width (24);
1044 _output_limit_count.set_adjustment (_output_limit_count_adj);
1045 _input_limit_count.set_adjustment (_input_limit_count_adj);
1046 _master_bus_channel_count.set_adjustment (_master_bus_channel_count_adj);
1048 chan_count_label_1.set_text (_("channels"));
1049 chan_count_label_3.set_text (_("channels"));
1050 chan_count_label_4.set_text (_("channels"));
1052 chan_count_label_1.set_alignment(0,0.5);
1053 chan_count_label_1.set_padding(0,0);
1054 chan_count_label_1.set_line_wrap(false);
1056 chan_count_label_3.set_alignment(0,0.5);
1057 chan_count_label_3.set_padding(0,0);
1058 chan_count_label_3.set_line_wrap(false);
1060 chan_count_label_4.set_alignment(0,0.5);
1061 chan_count_label_4.set_padding(0,0);
1062 chan_count_label_4.set_line_wrap(false);
1064 bus_label.set_markup (_("<b>Busses</b>"));
1065 input_label.set_markup (_("<b>Inputs</b>"));
1066 output_label.set_markup (_("<b>Outputs</b>"));
1068 _master_bus_channel_count.set_flags(Gtk::CAN_FOCUS);
1069 _master_bus_channel_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1070 _master_bus_channel_count.set_numeric(true);
1071 _master_bus_channel_count.set_digits(0);
1072 _master_bus_channel_count.set_wrap(false);
1074 _create_master_bus.set_label (_("Create master bus"));
1075 _create_master_bus.set_flags(Gtk::CAN_FOCUS);
1076 _create_master_bus.set_relief(Gtk::RELIEF_NORMAL);
1077 _create_master_bus.set_mode(true);
1078 _create_master_bus.set_active(true);
1079 _create_master_bus.set_border_width(0);
1081 advanced_table.set_row_spacings(0);
1082 advanced_table.set_col_spacings(0);
1084 _connect_inputs.set_label (_("Automatically connect to physical_inputs"));
1085 _connect_inputs.set_flags(Gtk::CAN_FOCUS);
1086 _connect_inputs.set_relief(Gtk::RELIEF_NORMAL);
1087 _connect_inputs.set_mode(true);
1088 _connect_inputs.set_active(Config->get_input_auto_connect() != ManualConnect);
1089 _connect_inputs.set_border_width(0);
1091 _limit_input_ports.set_label (_("Use only"));
1092 _limit_input_ports.set_flags(Gtk::CAN_FOCUS);
1093 _limit_input_ports.set_relief(Gtk::RELIEF_NORMAL);
1094 _limit_input_ports.set_mode(true);
1095 _limit_input_ports.set_sensitive(true);
1096 _limit_input_ports.set_border_width(0);
1098 _input_limit_count.set_flags(Gtk::CAN_FOCUS);
1099 _input_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1100 _input_limit_count.set_numeric(true);
1101 _input_limit_count.set_digits(0);
1102 _input_limit_count.set_wrap(false);
1103 _input_limit_count.set_sensitive(false);
1105 bus_hbox.pack_start (bus_table, Gtk::PACK_SHRINK, 18);
1107 bus_label.set_alignment(0, 0.5);
1108 bus_label.set_padding(0,0);
1109 bus_label.set_line_wrap(false);
1110 bus_label.set_selectable(false);
1111 bus_label.set_use_markup(true);
1112 bus_frame.set_shadow_type(Gtk::SHADOW_NONE);
1113 bus_frame.set_label_align(0,0.5);
1114 bus_frame.add(bus_hbox);
1115 bus_frame.set_label_widget(bus_label);
1117 bus_table.set_row_spacings (0);
1118 bus_table.set_col_spacings (0);
1119 bus_table.attach (_create_master_bus, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
1120 bus_table.attach (_master_bus_channel_count, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
1121 bus_table.attach (chan_count_label_1, 2, 3, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 0);
1123 input_port_limit_hbox.pack_start(_limit_input_ports, Gtk::PACK_SHRINK, 6);
1124 input_port_limit_hbox.pack_start(_input_limit_count, Gtk::PACK_SHRINK, 0);
1125 input_port_limit_hbox.pack_start(chan_count_label_3, Gtk::PACK_SHRINK, 6);
1126 input_port_vbox.pack_start(_connect_inputs, Gtk::PACK_SHRINK, 0);
1127 input_port_vbox.pack_start(input_port_limit_hbox, Gtk::PACK_EXPAND_PADDING, 0);
1128 input_table.set_row_spacings(0);
1129 input_table.set_col_spacings(0);
1130 input_table.attach(input_port_vbox, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 6);
1132 input_hbox.pack_start (input_table, Gtk::PACK_SHRINK, 18);
1134 input_label.set_alignment(0, 0.5);
1135 input_label.set_padding(0,0);
1136 input_label.set_line_wrap(false);
1137 input_label.set_selectable(false);
1138 input_label.set_use_markup(true);
1139 input_frame.set_shadow_type(Gtk::SHADOW_NONE);
1140 input_frame.set_label_align(0,0.5);
1141 input_frame.add(input_hbox);
1142 input_frame.set_label_widget(input_label);
1144 _connect_outputs.set_label (_("Automatically connect outputs"));
1145 _connect_outputs.set_flags(Gtk::CAN_FOCUS);
1146 _connect_outputs.set_relief(Gtk::RELIEF_NORMAL);
1147 _connect_outputs.set_mode(true);
1148 _connect_outputs.set_active(Config->get_output_auto_connect() != ManualConnect);
1149 _connect_outputs.set_border_width(0);
1150 _limit_output_ports.set_label (_("Use only"));
1151 _limit_output_ports.set_flags(Gtk::CAN_FOCUS);
1152 _limit_output_ports.set_relief(Gtk::RELIEF_NORMAL);
1153 _limit_output_ports.set_mode(true);
1154 _limit_output_ports.set_sensitive(true);
1155 _limit_output_ports.set_border_width(0);
1156 _output_limit_count.set_flags(Gtk::CAN_FOCUS);
1157 _output_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1158 _output_limit_count.set_numeric(false);
1159 _output_limit_count.set_digits(0);
1160 _output_limit_count.set_wrap(false);
1161 _output_limit_count.set_sensitive(false);
1162 output_port_limit_hbox.pack_start(_limit_output_ports, Gtk::PACK_SHRINK, 6);
1163 output_port_limit_hbox.pack_start(_output_limit_count, Gtk::PACK_SHRINK, 0);
1164 output_port_limit_hbox.pack_start(chan_count_label_4, Gtk::PACK_SHRINK, 6);
1166 _connect_outputs_to_master.set_label (_("... to master bus"));
1167 _connect_outputs_to_master.set_flags(Gtk::CAN_FOCUS);
1168 _connect_outputs_to_master.set_relief(Gtk::RELIEF_NORMAL);
1169 _connect_outputs_to_master.set_mode(true);
1170 _connect_outputs_to_master.set_active(Config->get_output_auto_connect() == AutoConnectMaster);
1171 _connect_outputs_to_master.set_border_width(0);
1173 _connect_outputs_to_master.set_group (connect_outputs_group);
1174 _connect_outputs_to_physical.set_group (connect_outputs_group);
1176 _connect_outputs_to_physical.set_label (_("... to physical outputs"));
1177 _connect_outputs_to_physical.set_flags(Gtk::CAN_FOCUS);
1178 _connect_outputs_to_physical.set_relief(Gtk::RELIEF_NORMAL);
1179 _connect_outputs_to_physical.set_mode(true);
1180 _connect_outputs_to_physical.set_active(Config->get_output_auto_connect() == AutoConnectPhysical);
1181 _connect_outputs_to_physical.set_border_width(0);
1183 output_conn_vbox.pack_start(_connect_outputs, Gtk::PACK_SHRINK, 0);
1184 output_conn_vbox.pack_start(_connect_outputs_to_master, Gtk::PACK_SHRINK, 0);
1185 output_conn_vbox.pack_start(_connect_outputs_to_physical, Gtk::PACK_SHRINK, 0);
1186 output_vbox.set_border_width(6);
1188 output_port_vbox.pack_start(output_port_limit_hbox, Gtk::PACK_SHRINK, 0);
1190 output_vbox.pack_start(output_conn_vbox);
1191 output_vbox.pack_start(output_port_vbox);
1193 output_label.set_alignment(0, 0.5);
1194 output_label.set_padding(0,0);
1195 output_label.set_line_wrap(false);
1196 output_label.set_selectable(false);
1197 output_label.set_use_markup(true);
1198 output_frame.set_shadow_type(Gtk::SHADOW_NONE);
1199 output_frame.set_label_align(0,0.5);
1201 output_hbox.pack_start (output_vbox, Gtk::PACK_SHRINK, 18);
1203 output_frame.add(output_hbox);
1204 output_frame.set_label_widget(output_label);
1206 more_options_vbox.pack_start(advanced_table, Gtk::PACK_SHRINK, 0);
1207 more_options_vbox.pack_start(bus_frame, Gtk::PACK_SHRINK, 6);
1208 more_options_vbox.pack_start(input_frame, Gtk::PACK_SHRINK, 6);
1209 more_options_vbox.pack_start(output_frame, Gtk::PACK_SHRINK, 0);
1211 /* signals */
1213 _connect_inputs.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::connect_inputs_clicked));
1214 _connect_outputs.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::connect_outputs_clicked));
1215 _limit_input_ports.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::limit_inputs_clicked));
1216 _limit_output_ports.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::limit_outputs_clicked));
1217 _create_master_bus.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::master_bus_button_clicked));
1219 /* note that more_options_vbox is NOT visible by
1220 * default. this is entirely by design - this page
1221 * should be skipped unless explicitly requested.
1224 session_options_page_index = append_page (more_options_vbox);
1225 set_page_title (more_options_vbox, _("Advanced Session Options"));
1226 set_page_complete (more_options_vbox, true);
1229 bool
1230 ArdourStartup::create_master_bus() const
1232 return _create_master_bus.get_active();
1236 ArdourStartup::master_channel_count() const
1238 return _master_bus_channel_count.get_value_as_int();
1241 bool
1242 ArdourStartup::connect_inputs() const
1244 return _connect_inputs.get_active();
1247 bool
1248 ArdourStartup::limit_inputs_used_for_connection() const
1250 return _limit_input_ports.get_active();
1254 ArdourStartup::input_limit_count() const
1256 return _input_limit_count.get_value_as_int();
1259 bool
1260 ArdourStartup::connect_outputs() const
1262 return _connect_outputs.get_active();
1265 bool
1266 ArdourStartup::limit_outputs_used_for_connection() const
1268 return _limit_output_ports.get_active();
1272 ArdourStartup::output_limit_count() const
1274 return _output_limit_count.get_value_as_int();
1277 bool
1278 ArdourStartup::connect_outs_to_master() const
1280 return _connect_outputs_to_master.get_active();
1283 bool
1284 ArdourStartup::connect_outs_to_physical() const
1286 return _connect_outputs_to_physical.get_active();
1289 void
1290 ArdourStartup::connect_inputs_clicked ()
1292 _limit_input_ports.set_sensitive(_connect_inputs.get_active());
1294 if (_connect_inputs.get_active() && _limit_input_ports.get_active()) {
1295 _input_limit_count.set_sensitive(true);
1296 } else {
1297 _input_limit_count.set_sensitive(false);
1301 void
1302 ArdourStartup::connect_outputs_clicked ()
1304 _limit_output_ports.set_sensitive(_connect_outputs.get_active());
1306 if (_connect_outputs.get_active() && _limit_output_ports.get_active()) {
1307 _output_limit_count.set_sensitive(true);
1308 } else {
1309 _output_limit_count.set_sensitive(false);
1313 void
1314 ArdourStartup::limit_inputs_clicked ()
1316 _input_limit_count.set_sensitive(_limit_input_ports.get_active());
1319 void
1320 ArdourStartup::limit_outputs_clicked ()
1322 _output_limit_count.set_sensitive(_limit_output_ports.get_active());
1325 void
1326 ArdourStartup::master_bus_button_clicked ()
1328 bool yn = _create_master_bus.get_active();
1330 _master_bus_channel_count.set_sensitive(yn);
1333 void
1334 ArdourStartup::move_along_now ()
1336 gint cur = get_current_page ();
1338 if (cur == session_page_index) {
1339 if (more_new_session_options_button.get_active()) {
1340 set_current_page (session_options_page_index);
1341 } else {
1342 on_apply ();
1347 void
1348 ArdourStartup::recent_row_activated (const Gtk::TreePath&, Gtk::TreeViewColumn*)
1350 set_page_complete (session_vbox, true);
1351 move_along_now ();
1354 void
1355 ArdourStartup::existing_session_selected ()
1357 _existing_session_chooser_used = true;
1359 set_page_complete (session_vbox, true);
1360 move_along_now ();