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.
21 #include "gtk2ardour-config.h"
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/replace_all.h"
33 #include "pbd/whitespace.h"
34 #include "pbd/stacktrace.h"
35 #include "pbd/openuri.h"
37 #include "ardour/audioengine.h"
38 #include "ardour/filesystem_paths.h"
39 #include "ardour/recent_sessions.h"
40 #include "ardour/session.h"
41 #include "ardour/session_state_utils.h"
42 #include "ardour/template_utils.h"
43 #include "ardour/filename_extensions.h"
45 #include "ardour_ui.h"
48 #include "engine_dialog.h"
57 using namespace ARDOUR;
59 ArdourStartup* ArdourStartup::the_startup = 0;
61 static string poor_mans_glob (string path)
64 replace_all (copy, "~", Glib::get_home_dir());
68 ArdourStartup::ArdourStartup (bool require_new, const std::string& session_name, const std::string& session_path, const std::string& template_name)
69 : _response (RESPONSE_OK)
70 , config_modified (false)
71 , new_only (require_new)
72 , default_dir_chooser (0)
73 , ic_new_session_button (_("Create a new session"))
74 , ic_existing_session_button (_("Open an existing session"))
75 , monitor_via_hardware_button (string_compose (_("Use an external mixer or the hardware mixer of your audio interface.\n"
76 "%1 will play NO role in monitoring"), PROGRAM_NAME))
77 , monitor_via_ardour_button (string_compose (_("Ask %1 to play back material as it is being recorded"), PROGRAM_NAME))
78 , new_folder_chooser (FILE_CHOOSER_ACTION_SELECT_FOLDER)
79 , more_new_session_options_button (_("I'd like more options for this session"))
80 , _output_limit_count_adj (1, 0, 100, 1, 10, 0)
81 , _input_limit_count_adj (1, 0, 100, 1, 10, 0)
82 , _master_bus_channel_count_adj (2, 0, 100, 1, 10, 0)
83 , audio_page_index (-1)
84 , new_user_page_index (-1)
85 , default_folder_page_index (-1)
86 , monitoring_page_index (-1)
87 , session_page_index (-1)
88 , initial_choice_index (-1)
89 , final_page_index (-1)
90 , session_options_page_index (-1)
91 , _existing_session_chooser_used (false)
93 new_user = !Glib::file_test (been_here_before_path(), Glib::FILE_TEST_EXISTS);
94 need_session_info = (session_name.empty() || require_new);
96 _provided_session_name = session_name;
97 _provided_session_path = session_path;
99 if (need_session_info || new_user) {
101 use_template_button.set_group (session_template_group);
102 use_session_as_template_button.set_group (session_template_group);
104 set_keep_above (true);
105 set_position (WIN_POS_CENTER);
106 set_border_width (12);
108 if ((icon_pixbuf = ::get_icon ("ardour_icon_48px")) == 0) {
109 throw failed_constructor();
112 list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
113 Glib::RefPtr<Gdk::Pixbuf> icon;
115 if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
116 window_icons.push_back (icon);
118 if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
119 window_icons.push_back (icon);
121 if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
122 window_icons.push_back (icon);
124 if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
125 window_icons.push_back (icon);
127 if (!window_icons.empty ()) {
128 set_default_icon_list (window_icons);
132 setup_prerelease_page ();
136 setup_new_user_page ();
137 setup_first_time_config_page ();
138 setup_monitoring_choice_page ();
139 setup_monitor_section_choice_page ();
141 ic_new_session_button.set_active (true); // always create new session on first run
145 setup_initial_choice_page ();
148 setup_session_page ();
149 setup_more_options_page ();
161 if (!template_name.empty()) {
162 use_template_button.set_active (false);
163 load_template_override = template_name;
170 ArdourStartup::~ArdourStartup ()
175 ArdourStartup::ready_without_display () const
177 return !new_user && !need_session_info;
181 ArdourStartup::setup_prerelease_page ()
183 VBox* vbox = manage (new VBox);
184 Label* label = manage (new Label);
185 label->set_markup (string_compose (_("<b>Welcome to this BETA release of Ardour %1</b>\n\n\
186 Ardour %1 has been released for Linux but because of the lack of testers,\n\
187 it is still at the beta stage on OS X. So, a few guidelines:\n\
189 1) Please do <b>NOT</b> use this software with the expectation that it is stable or reliable\n\
190 though it may be so, depending on your workflow.\n\
191 2) <b>Please do NOT use the forums at ardour.org to report issues</b>.\n\
192 3) Please <b>DO</b> use the bugtracker at http://tracker.ardour.org/ to report issues\n\
193 making sure to note the product version number as %1-beta.\n\
194 4) Please <b>DO</b> use the ardour-users mailing list to discuss ideas and pass on comments.\n\
195 5) Please <b>DO</b> join us on IRC for real time discussions about ardour3. You\n\
196 can get there directly from Ardour via the Help->Chat menu option.\n\
198 Full information on all the above can be found on the support page at\n\
200 http://ardour.org/support\n\
203 vbox->set_border_width (12);
204 vbox->pack_start (*label, false, false, 12);
208 set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
209 set_page_title (*vbox, _("This is a BETA RELEASE"));
210 set_page_complete (*vbox, true);
214 ArdourStartup::use_session_template ()
216 if (!load_template_override.empty()) {
220 if (use_template_button.get_active()) {
221 return template_chooser.get_active_row_number() > 0;
223 return !session_template_chooser.get_filename().empty();
228 ArdourStartup::session_template_name ()
230 if (!load_template_override.empty()) {
231 string the_path (ARDOUR::user_template_directory());
232 return Glib::build_filename (the_path, load_template_override + ARDOUR::template_suffix);
235 if (ic_existing_session_button.get_active()) {
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];
245 return session_template_chooser.get_filename();
251 ArdourStartup::session_name (bool& should_be_new)
253 if (ready_without_display()) {
254 return _provided_session_name;
257 if (ic_new_session_button.get_active()) {
258 should_be_new = true;
259 string val = new_name_entry.get_text ();
260 strip_whitespace_edges (val);
262 } else if (_existing_session_chooser_used) {
263 /* existing session chosen from file chooser */
264 should_be_new = false;
265 return existing_session_chooser.get_filename ();
267 /* existing session chosen from recent list */
268 should_be_new = false;
270 TreeIter iter = recent_session_display.get_selection()->get_selected();
273 return (*iter)[recent_session_columns.visible_name];
281 ArdourStartup::session_folder ()
283 if (ready_without_display()) {
284 return _provided_session_path;
287 if (ic_new_session_button.get_active()) {
288 std::string legal_session_folder_name = legalize_for_path (new_name_entry.get_text());
289 return Glib::build_filename (new_folder_chooser.get_current_folder(), legal_session_folder_name);
290 } else if (_existing_session_chooser_used) {
291 /* existing session chosen from file chooser */
292 return existing_session_chooser.get_current_folder ();
294 /* existing session chosen from recent list */
295 TreeIter iter = recent_session_display.get_selection()->get_selected();
298 return (*iter)[recent_session_columns.fullpath];
305 ArdourStartup::setup_new_user_page ()
307 Label* foomatic = manage (new Label);
309 foomatic->set_markup (string_compose (_("\
310 <span size=\"larger\">%1 is a digital audio workstation. You can use it to \
311 record, edit and mix multi-track audio. You can produce your \
312 own CDs, mix video soundtracks, or experiment with new \
313 ideas about music and sound. \
315 There are a few things that need to be configured before you start \
316 using the program.</span> \
318 foomatic->set_justify (JUSTIFY_FILL);
319 foomatic->set_line_wrap ();
321 HBox* hbox = manage (new HBox);
322 HBox* vbox = manage (new HBox);
324 vbox->set_border_width (24);
326 hbox->pack_start (*foomatic, true, true);
327 vbox->pack_start (*hbox, true, true);
333 new_user_page_index = append_page (*vbox);
334 set_page_type (*vbox, ASSISTANT_PAGE_INTRO);
335 set_page_title (*vbox, string_compose (_("Welcome to %1"), PROGRAM_NAME));
336 set_page_header_image (*vbox, icon_pixbuf);
337 set_page_complete (*vbox, true);
341 ArdourStartup::default_dir_changed ()
343 Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
344 // make new session folder chooser point to the new default
345 new_folder_chooser.set_current_folder (Config->get_default_session_parent_dir());
350 ArdourStartup::config_changed ()
352 config_modified = true;
356 ArdourStartup::setup_first_time_config_page ()
358 default_dir_chooser = manage (new FileChooserButton (string_compose (_("Default folder for %1 sessions"), PROGRAM_NAME),
359 FILE_CHOOSER_ACTION_SELECT_FOLDER));
360 Gtk::Label* txt = manage (new Label);
361 HBox* hbox = manage (new HBox);
362 VBox* vbox = manage (new VBox);
364 txt->set_markup (string_compose (_("\
365 Each project that you work on with %1 has its own folder.\n\
366 These can require a lot of disk space if you are recording audio.\n\
368 Where would you like new %1 sessions to be stored by default?\n\n\
369 <i>(You can put new sessions anywhere, this is just a default)</i>"), PROGRAM_NAME));
370 txt->set_alignment (0.0, 0.0);
372 vbox->set_spacing (18);
373 vbox->set_border_width (24);
375 hbox->pack_start (*default_dir_chooser, false, true, 8);
376 vbox->pack_start (*txt, false, false);
377 vbox->pack_start (*hbox, false, true);
379 default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
380 default_dir_chooser->signal_current_folder_changed().connect (sigc::mem_fun (*this, &ArdourStartup::default_dir_changed));
381 default_dir_chooser->show ();
385 default_folder_page_index = append_page (*vbox);
386 set_page_title (*vbox, _("Default folder for new sessions"));
387 set_page_header_image (*vbox, icon_pixbuf);
388 set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
390 /* user can just skip all these settings if they want to */
392 set_page_complete (*vbox, true);
396 ArdourStartup::setup_monitoring_choice_page ()
398 mon_vbox.set_spacing (18);
399 mon_vbox.set_border_width (24);
401 HBox* hbox = manage (new HBox);
402 VBox* vbox = manage (new VBox);
403 /* first button will be on by default */
404 RadioButton::Group g (monitor_via_ardour_button.get_group());
405 monitor_via_hardware_button.set_group (g);
407 monitor_label.set_markup(_("\
408 While recording instruments or vocals, you probably want to listen to the\n\
409 signal as well as record it. This is called \"monitoring\". There are\n\
410 different ways to do this depending on the equipment you have and the\n\
411 configuration of that equipment. The two most common are presented here.\n\
412 Please choose whichever one is right for your setup.\n\n\
413 <i>(You can change this preference at any time, via the Preferences dialog)</i>\n\n\
414 <i>If you do not understand what this is about, just accept the default.</i>"));
415 monitor_label.set_alignment (0.0, 0.0);
417 vbox->set_spacing (6);
419 vbox->pack_start (monitor_via_hardware_button, false, true);
420 vbox->pack_start (monitor_via_ardour_button, false, true);
421 hbox->pack_start (*vbox, true, true, 8);
422 mon_vbox.pack_start (monitor_label, false, false);
423 mon_vbox.pack_start (*hbox, false, false);
425 mon_vbox.show_all ();
427 monitoring_page_index = append_page (mon_vbox);
428 set_page_title (mon_vbox, _("Monitoring Choices"));
429 set_page_header_image (mon_vbox, icon_pixbuf);
431 /* user could just click on "Forward" if default
435 set_page_complete (mon_vbox, true);
439 ArdourStartup::setup_monitor_section_choice_page ()
441 mon_sec_vbox.set_spacing (18);
442 mon_sec_vbox.set_border_width (24);
444 HBox* hbox = manage (new HBox);
445 VBox* main_vbox = manage (new VBox);
447 Label* l = manage (new Label);
449 main_vbox->set_spacing (32);
451 no_monitor_section_button.set_label (_("Use a Master bus directly"));
452 l->set_alignment (0.0, 1.0);
453 l->set_markup(_("Connect the Master bus directly to your hardware outputs. This is preferable for simple usage."));
455 vbox = manage (new VBox);
456 vbox->set_spacing (6);
457 vbox->pack_start (no_monitor_section_button, false, true);
458 vbox->pack_start (*l, false, true);
460 main_vbox->pack_start (*vbox, false, false);
462 use_monitor_section_button.set_label (_("Use an additional Monitor bus"));
463 l = manage (new Label);
464 l->set_alignment (0.0, 1.0);
465 l->set_text (_("Use a Monitor bus between Master bus and hardware outputs for \n\
466 greater control in monitoring without affecting the mix."));
468 vbox = manage (new VBox);
469 vbox->set_spacing (6);
470 vbox->pack_start (use_monitor_section_button, false, true);
471 vbox->pack_start (*l, false, true);
473 main_vbox->pack_start (*vbox, false, false);
475 RadioButton::Group g (use_monitor_section_button.get_group());
476 no_monitor_section_button.set_group (g);
478 if (Config->get_use_monitor_bus()) {
479 use_monitor_section_button.set_active (true);
481 no_monitor_section_button.set_active (true);
484 use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
485 no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
487 monitor_section_label.set_markup(_("<i>You can change this preference at any time via the Preferences dialog.\nYou can also add or remove the monitor section to/from any session.</i>\n\n\
488 <i>If you do not understand what this is about, just accept the default.</i>"));
489 monitor_section_label.set_alignment (0.0, 0.0);
491 hbox->pack_start (*main_vbox, true, true, 8);
492 mon_sec_vbox.pack_start (*hbox, false, false);
493 mon_sec_vbox.pack_start (monitor_section_label, false, false);
495 mon_sec_vbox.show_all ();
497 monitor_section_page_index = append_page (mon_sec_vbox);
498 set_page_title (mon_sec_vbox, _("Monitor Section"));
499 set_page_header_image (mon_sec_vbox, icon_pixbuf);
501 /* user could just click on "Forward" if default
505 set_page_complete (mon_sec_vbox, true);
509 ArdourStartup::setup_initial_choice_page ()
511 ic_vbox.set_spacing (6);
512 ic_vbox.set_border_width (24);
514 RadioButton::Group g (ic_new_session_button.get_group());
515 ic_existing_session_button.set_group (g);
517 HBox* centering_hbox = manage (new HBox);
518 VBox* centering_vbox = manage (new VBox);
520 centering_vbox->set_spacing (6);
522 centering_vbox->pack_start (ic_new_session_button, false, true);
523 centering_vbox->pack_start (ic_existing_session_button, false, true);
525 if (ARDOUR_UI::instance()->announce_string() != "" ) {
527 Gtk::Frame *info_frame = manage(new Gtk::Frame);
528 info_frame->set_shadow_type(SHADOW_ETCHED_OUT);
529 centering_vbox->pack_start (*info_frame, false, false, 20);
531 Box *info_box = manage (new VBox);
532 info_box->set_border_width (12);
533 info_box->set_spacing (6);
534 info_box->set_name("mixbus_info_box");
536 info_box->pack_start (info_scroller_label, false, false);
538 info_frame->add (*info_box);
539 info_frame->show_all();
541 info_scroller_count = 0;
542 info_scroller_connection = Glib::signal_timeout().connect (mem_fun(*this, &ArdourStartup::info_scroller_update), 50);
544 Gtk::Button *updates_button = manage (new Gtk::Button (_("Check the website for more...")));
546 updates_button->signal_clicked().connect (mem_fun(*this, &ArdourStartup::updates_button_clicked) );
547 ARDOUR_UI::instance()->tooltips().set_tip (*updates_button, _("Click to open the program website in your web browser"));
549 info_box->pack_start (*updates_button, false, false);
552 ic_new_session_button.signal_button_press_event().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_clicked), false);
553 ic_new_session_button.signal_activate().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_activated), false);
555 ic_existing_session_button.signal_button_press_event().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_clicked), false);
556 ic_existing_session_button.signal_activate().connect(sigc::mem_fun(*this, &ArdourStartup::initial_button_activated), false);
558 centering_hbox->pack_start (*centering_vbox, true, true);
560 ic_vbox.pack_start (*centering_hbox, true, true);
564 initial_choice_index = append_page (ic_vbox);
565 set_page_title (ic_vbox, string_compose("%1 %2", PROGRAM_NAME, VERSIONSTRING));
566 set_page_header_image (ic_vbox, icon_pixbuf);
568 /* user could just click on "Forward" if default
572 set_page_complete (ic_vbox, true);
576 ArdourStartup::initial_button_clicked (GdkEventButton* ev)
578 if (ev->type == GDK_2BUTTON_PRESS && session_page_index != -1) {
579 set_current_page(session_page_index);
586 ArdourStartup::initial_button_activated ()
588 if (session_page_index != -1) {
589 set_current_page(session_page_index);
594 ArdourStartup::setup_session_page ()
596 session_vbox.set_border_width (24);
598 session_vbox.pack_start (session_hbox, true, true);
599 session_vbox.show_all ();
601 session_page_index = append_page (session_vbox);
602 /* initial setting */
603 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
607 ArdourStartup::setup_final_page ()
609 final_page.set_text (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
611 final_page_index = append_page (final_page);
612 set_page_complete (final_page, true);
613 set_page_header_image (final_page, icon_pixbuf);
614 set_page_type (final_page, ASSISTANT_PAGE_CONFIRM);
618 ArdourStartup::on_cancel ()
620 _response = RESPONSE_CANCEL;
625 ArdourStartup::on_delete_event (GdkEventAny*)
627 _response = RESPONSE_CLOSE;
633 ArdourStartup::on_apply ()
635 if (config_modified) {
637 if (default_dir_chooser) {
638 Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
641 if (monitor_via_hardware_button.get_active()) {
642 Config->set_monitoring_model (ExternalMonitoring);
643 } else if (monitor_via_ardour_button.get_active()) {
644 Config->set_monitoring_model (SoftwareMonitoring);
647 Config->set_use_monitor_bus (use_monitor_section_button.get_active());
649 Config->save_state ();
654 /* "touch" the been-here-before path now we've successfully
655 made it through the first time setup (at least)
657 ofstream fout (been_here_before_path().c_str());
661 _response = RESPONSE_OK;
666 ArdourStartup::on_prepare (Gtk::Widget* page)
668 if (page == &session_vbox) {
670 if (ic_new_session_button.get_active()) {
671 /* new session requested */
672 setup_new_session_page ();
674 /* existing session requested */
675 setup_existing_session_page ();
679 /* HACK HACK HACK ... change the "Apply" button label
683 Gtk::Widget* tl = session_vbox.get_toplevel();
685 if ((win = dynamic_cast<Gtk::Window*>(tl)) != 0) {
686 /* ::get_default_widget() is not wrapped in gtkmm */
687 Gtk::Widget* def = wrap (gtk_window_get_default_widget (win->gobj()));
689 if ((button = dynamic_cast<Gtk::Button*>(def)) != 0) {
690 if (more_new_session_options_button.get_active()) {
691 button->set_label (_("Forward"));
693 button->set_label (_("Open"));
701 ArdourStartup::populate_session_templates ()
703 vector<TemplateInfo> templates;
705 find_session_templates (templates);
707 template_model->clear ();
709 for (vector<TemplateInfo>::iterator x = templates.begin(); x != templates.end(); ++x) {
712 row = *(template_model->append ());
714 row[session_template_columns.name] = (*x).name;
715 row[session_template_columns.path] = (*x).path;
720 ArdourStartup::setup_new_session_page ()
722 if (!session_hbox.get_children().empty()) {
723 session_hbox.remove (**session_hbox.get_children().begin());
726 session_new_vbox.set_spacing (18);
728 if (session_new_vbox.get_children().empty()) {
729 VBox *vbox1 = manage (new VBox);
730 HBox* hbox1 = manage (new HBox);
731 Label* label1 = manage (new Label);
733 vbox1->set_spacing (6);
735 hbox1->set_spacing (6);
736 hbox1->pack_start (*label1, false, false);
737 hbox1->pack_start (new_name_entry, true, true);
739 label1->set_text (_("Session name:"));
742 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
743 new_name_entry.set_text (Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name));
744 /* name provided - they can move right along */
745 set_page_complete (session_vbox, true);
748 new_name_entry.signal_changed().connect (sigc::mem_fun (*this, &ArdourStartup::new_name_changed));
749 new_name_entry.signal_activate().connect (sigc::mem_fun (*this, &ArdourStartup::move_along_now));
751 vbox1->pack_start (*hbox1, true, true);
755 HBox* hbox2 = manage (new HBox);
756 Label* label2 = manage (new Label);
758 hbox2->set_spacing (6);
759 hbox2->pack_start (*label2, false, false);
760 hbox2->pack_start (new_folder_chooser, true, true);
762 label2->set_text (_("Create session folder in:"));
764 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
765 new_folder_chooser.set_current_folder (poor_mans_glob (Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name)));
766 } else if (ARDOUR_UI::instance()->session_loaded) {
767 // point the new session file chooser at the parent directory of the current session
768 string session_parent_dir = Glib::path_get_dirname(ARDOUR_UI::instance()->the_session()->path());
769 string::size_type last_dir_sep = session_parent_dir.rfind(G_DIR_SEPARATOR);
770 session_parent_dir = session_parent_dir.substr(0, last_dir_sep);
771 new_folder_chooser.set_current_folder (session_parent_dir);
772 string default_session_folder = poor_mans_glob (Config->get_default_session_parent_dir());
775 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
776 new_folder_chooser.add_shortcut_folder (default_session_folder);
778 catch (Glib::Error & e) {
779 std::cerr << "new_folder_chooser.add_shortcut_folder (" << default_session_folder << ") threw Glib::Error " << e.what() << std::endl;
782 new_folder_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
784 new_folder_chooser.show ();
785 new_folder_chooser.set_title (_("Select folder for session"));
788 new_folder_chooser.add_shortcut_folder ("/Volumes");
791 vbox1->pack_start (*hbox2, false, false);
793 session_new_vbox.pack_start (*vbox1, false, false);
797 VBox *vbox2 = manage (new VBox);
798 HBox* hbox3 = manage (new HBox);
799 Label* label3 = manage (new Label);
800 template_model = ListStore::create (session_template_columns);
801 populate_session_templates ();
803 vbox2->set_spacing (6);
805 label3->set_markup (_("<b>Options</b>"));
806 label3->set_alignment (0.0, 0.0);
808 vbox2->pack_start (*label3, false, true);
810 VBox *vbox3 = manage (new VBox);
812 vbox3->set_spacing (6);
814 if (!template_model->children().empty()) {
816 HBox* hbox4a = manage (new HBox);
817 use_template_button.set_label (_("Use this template"));
819 TreeModel::Row row = *template_model->prepend ();
820 row[session_template_columns.name] = (_("no template"));
821 row[session_template_columns.path] = string();
823 hbox4a->set_spacing (6);
824 hbox4a->pack_start (use_template_button, false, false);
825 hbox4a->pack_start (template_chooser, true, true);
827 template_chooser.set_model (template_model);
829 Gtk::CellRendererText* text_renderer = Gtk::manage (new Gtk::CellRendererText);
830 text_renderer->property_editable() = false;
832 template_chooser.pack_start (*text_renderer);
833 template_chooser.add_attribute (text_renderer->property_text(), session_template_columns.name);
834 template_chooser.set_active (0);
836 use_template_button.show();
837 template_chooser.show ();
839 vbox3->pack_start (*hbox4a, false, false);
845 session_template_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
847 HBox* hbox4b = manage (new HBox);
848 use_session_as_template_button.set_label (_("Use an existing session as a template:"));
850 hbox4b->set_spacing (6);
851 hbox4b->pack_start (use_session_as_template_button, false, false);
852 hbox4b->pack_start (session_template_chooser, true, true);
854 use_session_as_template_button.show ();
855 session_template_chooser.show ();
857 Gtk::FileFilter* session_filter = manage (new (Gtk::FileFilter));
858 session_filter->add_pattern (X_("*.ardour"));
859 session_template_chooser.set_filter (*session_filter);
860 session_template_chooser.set_title (_("Select template"));
862 vbox3->pack_start (*hbox4b, false, false);
867 HBox* hbox5 = manage (new HBox);
869 hbox5->set_spacing (6);
870 hbox5->pack_start (more_new_session_options_button, false, false);
872 more_new_session_options_button.show ();
873 more_new_session_options_button.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::more_new_session_options_button_clicked));
875 vbox3->pack_start (*hbox5, false, false);
876 hbox3->pack_start (*vbox3, true, true, 8);
877 vbox2->pack_start (*hbox3, false, false);
881 session_new_vbox.pack_start (*vbox2, false, false);
884 session_new_vbox.show_all ();
885 session_hbox.pack_start (session_new_vbox, true, true);
886 set_page_title (session_vbox, _("New Session"));
887 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
889 if (more_new_session_options_button.get_active()) {
890 set_page_type (session_vbox, ASSISTANT_PAGE_CONTENT);
892 session_hbox.show_all();
896 ArdourStartup::new_name_changed ()
898 if (!new_name_entry.get_text().empty()) {
899 set_page_complete (session_vbox, true);
901 set_page_complete (session_vbox, false);
906 ArdourStartup::redisplay_recent_sessions ()
908 std::vector<std::string> session_directories;
909 RecentSessionsSorter cmp;
911 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
912 recent_session_model->clear ();
914 ARDOUR::RecentSessions rs;
915 ARDOUR::read_recent_sessions (rs);
918 recent_session_display.set_model (recent_session_model);
922 // sort them alphabetically
923 sort (rs.begin(), rs.end(), cmp);
925 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
926 session_directories.push_back ((*i).second);
929 int session_snapshot_count = 0;
931 for (vector<std::string>::const_iterator i = session_directories.begin(); i != session_directories.end(); ++i)
933 std::vector<std::string> state_file_paths;
935 // now get available states for this session
937 get_state_files_in_directory (*i, state_file_paths);
939 vector<string*>* states;
940 vector<const gchar*> item;
941 string fullpath = *i;
943 /* remove any trailing / */
945 if (fullpath[fullpath.length()-1] == '/') {
946 fullpath = fullpath.substr (0, fullpath.length()-1);
949 /* check whether session still exists */
950 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
951 /* session doesn't exist */
955 /* now get available states for this session */
957 if ((states = Session::possible_states (fullpath)) == 0) {
962 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
964 Gtk::TreeModel::Row row = *(recent_session_model->append());
966 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
967 row[recent_session_columns.fullpath] = fullpath;
968 row[recent_session_columns.tip] = Glib::Markup::escape_text (fullpath);
970 ++session_snapshot_count;
972 if (state_file_names.size() > 1) {
976 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
977 i2 != state_file_names.end(); ++i2) {
979 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
981 child_row[recent_session_columns.visible_name] = *i2;
982 child_row[recent_session_columns.fullpath] = fullpath;
983 child_row[recent_session_columns.tip] = Glib::Markup::escape_text (fullpath);
984 ++session_snapshot_count;
989 recent_session_display.set_tooltip_column(1); // recent_session_columns.tip
990 recent_session_display.set_model (recent_session_model);
991 return session_snapshot_count;
996 ArdourStartup::recent_session_row_selected ()
998 if (recent_session_display.get_selection()->count_selected_rows() > 0) {
999 set_page_complete (session_vbox, true);
1001 set_page_complete (session_vbox, false);
1006 ArdourStartup::setup_existing_session_page ()
1008 recent_session_model = TreeStore::create (recent_session_columns);
1009 redisplay_recent_sessions ();
1011 if (!session_hbox.get_children().empty()) {
1012 session_hbox.remove (**session_hbox.get_children().begin());
1015 if (session_existing_vbox.get_children().empty()) {
1017 recent_session_display.set_model (recent_session_model);
1018 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1019 recent_session_display.set_headers_visible (false);
1020 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1022 recent_session_display.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ArdourStartup::recent_session_row_selected));
1024 recent_scroller.add (recent_session_display);
1025 recent_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1026 recent_scroller.set_shadow_type (Gtk::SHADOW_IN);
1028 recent_session_display.show();
1030 recent_scroller.show();
1031 int cnt = redisplay_recent_sessions ();
1032 recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &ArdourStartup::recent_row_activated));
1035 recent_scroller.set_size_request (-1, 300);
1038 session_existing_vbox.set_spacing (8);
1039 session_existing_vbox.pack_start (recent_scroller, true, true);
1041 existing_session_chooser.set_title (_("Select session file"));
1042 existing_session_chooser.signal_file_set().connect (sigc::mem_fun (*this, &ArdourStartup::existing_session_selected));
1043 existing_session_chooser.set_current_folder(poor_mans_glob (Config->get_default_session_parent_dir()));
1045 FileFilter session_filter;
1046 session_filter.add_pattern ("*.ardour");
1047 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1048 existing_session_chooser.add_filter (session_filter);
1049 existing_session_chooser.set_filter (session_filter);
1052 existing_session_chooser.add_shortcut_folder ("/Volumes");
1055 HBox* hbox = manage (new HBox);
1056 hbox->set_spacing (4);
1057 hbox->pack_start (*manage (new Label (_("Browse:"))), PACK_SHRINK);
1058 hbox->pack_start (existing_session_chooser);
1059 session_existing_vbox.pack_start (*hbox, false, false);
1063 session_existing_vbox.show_all ();
1064 session_hbox.pack_start (session_existing_vbox, true, true);
1066 set_page_title (session_vbox, _("Select a session"));
1067 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
1068 session_hbox.show_all();
1072 ArdourStartup::more_new_session_options_button_clicked ()
1074 if (more_new_session_options_button.get_active()) {
1075 more_options_vbox.show_all ();
1076 set_page_type (more_options_vbox, ASSISTANT_PAGE_CONFIRM);
1077 set_page_type (session_vbox, ASSISTANT_PAGE_CONTENT);
1079 set_page_type (session_vbox, ASSISTANT_PAGE_CONFIRM);
1080 more_options_vbox.hide ();
1085 ArdourStartup::setup_more_options_page ()
1087 more_options_vbox.set_border_width (24);
1089 _output_limit_count.set_adjustment (_output_limit_count_adj);
1090 _input_limit_count.set_adjustment (_input_limit_count_adj);
1091 _master_bus_channel_count.set_adjustment (_master_bus_channel_count_adj);
1093 chan_count_label_1.set_text (_("channels"));
1094 chan_count_label_3.set_text (_("channels"));
1095 chan_count_label_4.set_text (_("channels"));
1097 chan_count_label_1.set_alignment(0,0.5);
1098 chan_count_label_1.set_padding(0,0);
1099 chan_count_label_1.set_line_wrap(false);
1101 chan_count_label_3.set_alignment(0,0.5);
1102 chan_count_label_3.set_padding(0,0);
1103 chan_count_label_3.set_line_wrap(false);
1105 chan_count_label_4.set_alignment(0,0.5);
1106 chan_count_label_4.set_padding(0,0);
1107 chan_count_label_4.set_line_wrap(false);
1109 bus_label.set_markup (_("<b>Busses</b>"));
1110 input_label.set_markup (_("<b>Inputs</b>"));
1111 output_label.set_markup (_("<b>Outputs</b>"));
1113 _master_bus_channel_count.set_flags(Gtk::CAN_FOCUS);
1114 _master_bus_channel_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1115 _master_bus_channel_count.set_numeric(true);
1116 _master_bus_channel_count.set_digits(0);
1117 _master_bus_channel_count.set_wrap(false);
1119 _create_master_bus.set_label (_("Create master bus"));
1120 _create_master_bus.set_flags(Gtk::CAN_FOCUS);
1121 _create_master_bus.set_relief(Gtk::RELIEF_NORMAL);
1122 _create_master_bus.set_mode(true);
1123 _create_master_bus.set_active(true);
1124 _create_master_bus.set_border_width(0);
1126 advanced_table.set_row_spacings(0);
1127 advanced_table.set_col_spacings(0);
1129 _connect_inputs.set_label (_("Automatically connect to physical inputs"));
1130 _connect_inputs.set_flags(Gtk::CAN_FOCUS);
1131 _connect_inputs.set_relief(Gtk::RELIEF_NORMAL);
1132 _connect_inputs.set_mode(true);
1133 _connect_inputs.set_active(Config->get_input_auto_connect() != ManualConnect);
1134 _connect_inputs.set_border_width(0);
1136 _limit_input_ports.set_label (_("Use only"));
1137 _limit_input_ports.set_flags(Gtk::CAN_FOCUS);
1138 _limit_input_ports.set_relief(Gtk::RELIEF_NORMAL);
1139 _limit_input_ports.set_mode(true);
1140 _limit_input_ports.set_sensitive(true);
1141 _limit_input_ports.set_border_width(0);
1143 _input_limit_count.set_flags(Gtk::CAN_FOCUS);
1144 _input_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1145 _input_limit_count.set_numeric(true);
1146 _input_limit_count.set_digits(0);
1147 _input_limit_count.set_wrap(false);
1148 _input_limit_count.set_sensitive(false);
1150 bus_hbox.pack_start (bus_table, Gtk::PACK_SHRINK, 18);
1152 bus_label.set_alignment(0, 0.5);
1153 bus_label.set_padding(0,0);
1154 bus_label.set_line_wrap(false);
1155 bus_label.set_selectable(false);
1156 bus_label.set_use_markup(true);
1157 bus_frame.set_shadow_type(Gtk::SHADOW_NONE);
1158 bus_frame.set_label_align(0,0.5);
1159 bus_frame.add(bus_hbox);
1160 bus_frame.set_label_widget(bus_label);
1162 bus_table.set_row_spacings (0);
1163 bus_table.set_col_spacings (0);
1164 bus_table.attach (_create_master_bus, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
1165 bus_table.attach (_master_bus_channel_count, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
1166 bus_table.attach (chan_count_label_1, 2, 3, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 0);
1168 input_port_limit_hbox.pack_start(_limit_input_ports, Gtk::PACK_SHRINK, 6);
1169 input_port_limit_hbox.pack_start(_input_limit_count, Gtk::PACK_SHRINK, 0);
1170 input_port_limit_hbox.pack_start(chan_count_label_3, Gtk::PACK_SHRINK, 6);
1171 input_port_vbox.pack_start(_connect_inputs, Gtk::PACK_SHRINK, 0);
1172 input_port_vbox.pack_start(input_port_limit_hbox, Gtk::PACK_EXPAND_PADDING, 0);
1173 input_table.set_row_spacings(0);
1174 input_table.set_col_spacings(0);
1175 input_table.attach(input_port_vbox, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 6);
1177 input_hbox.pack_start (input_table, Gtk::PACK_SHRINK, 18);
1179 input_label.set_alignment(0, 0.5);
1180 input_label.set_padding(0,0);
1181 input_label.set_line_wrap(false);
1182 input_label.set_selectable(false);
1183 input_label.set_use_markup(true);
1184 input_frame.set_shadow_type(Gtk::SHADOW_NONE);
1185 input_frame.set_label_align(0,0.5);
1186 input_frame.add(input_hbox);
1187 input_frame.set_label_widget(input_label);
1189 _connect_outputs.set_label (_("Automatically connect outputs"));
1190 _connect_outputs.set_flags(Gtk::CAN_FOCUS);
1191 _connect_outputs.set_relief(Gtk::RELIEF_NORMAL);
1192 _connect_outputs.set_mode(true);
1193 _connect_outputs.set_active(Config->get_output_auto_connect() != ManualConnect);
1194 _connect_outputs.set_border_width(0);
1195 _limit_output_ports.set_label (_("Use only"));
1196 _limit_output_ports.set_flags(Gtk::CAN_FOCUS);
1197 _limit_output_ports.set_relief(Gtk::RELIEF_NORMAL);
1198 _limit_output_ports.set_mode(true);
1199 _limit_output_ports.set_sensitive(true);
1200 _limit_output_ports.set_border_width(0);
1201 _output_limit_count.set_flags(Gtk::CAN_FOCUS);
1202 _output_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1203 _output_limit_count.set_numeric(false);
1204 _output_limit_count.set_digits(0);
1205 _output_limit_count.set_wrap(false);
1206 _output_limit_count.set_sensitive(false);
1207 output_port_limit_hbox.pack_start(_limit_output_ports, Gtk::PACK_SHRINK, 6);
1208 output_port_limit_hbox.pack_start(_output_limit_count, Gtk::PACK_SHRINK, 0);
1209 output_port_limit_hbox.pack_start(chan_count_label_4, Gtk::PACK_SHRINK, 6);
1211 _connect_outputs_to_master.set_label (_("... to master bus"));
1212 _connect_outputs_to_master.set_flags(Gtk::CAN_FOCUS);
1213 _connect_outputs_to_master.set_relief(Gtk::RELIEF_NORMAL);
1214 _connect_outputs_to_master.set_mode(true);
1215 _connect_outputs_to_master.set_active(Config->get_output_auto_connect() == AutoConnectMaster);
1216 _connect_outputs_to_master.set_border_width(0);
1218 _connect_outputs_to_master.set_group (connect_outputs_group);
1219 _connect_outputs_to_physical.set_group (connect_outputs_group);
1221 _connect_outputs_to_physical.set_label (_("... to physical outputs"));
1222 _connect_outputs_to_physical.set_flags(Gtk::CAN_FOCUS);
1223 _connect_outputs_to_physical.set_relief(Gtk::RELIEF_NORMAL);
1224 _connect_outputs_to_physical.set_mode(true);
1225 _connect_outputs_to_physical.set_active(Config->get_output_auto_connect() == AutoConnectPhysical);
1226 _connect_outputs_to_physical.set_border_width(0);
1228 output_conn_vbox.pack_start(_connect_outputs, Gtk::PACK_SHRINK, 0);
1229 output_conn_vbox.pack_start(_connect_outputs_to_master, Gtk::PACK_SHRINK, 0);
1230 output_conn_vbox.pack_start(_connect_outputs_to_physical, Gtk::PACK_SHRINK, 0);
1231 output_vbox.set_border_width(6);
1233 output_port_vbox.pack_start(output_port_limit_hbox, Gtk::PACK_SHRINK, 0);
1235 output_vbox.pack_start(output_conn_vbox);
1236 output_vbox.pack_start(output_port_vbox);
1238 output_label.set_alignment(0, 0.5);
1239 output_label.set_padding(0,0);
1240 output_label.set_line_wrap(false);
1241 output_label.set_selectable(false);
1242 output_label.set_use_markup(true);
1243 output_frame.set_shadow_type(Gtk::SHADOW_NONE);
1244 output_frame.set_label_align(0,0.5);
1246 output_hbox.pack_start (output_vbox, Gtk::PACK_SHRINK, 18);
1248 output_frame.add(output_hbox);
1249 output_frame.set_label_widget(output_label);
1251 more_options_vbox.pack_start(advanced_table, Gtk::PACK_SHRINK, 0);
1252 more_options_vbox.pack_start(bus_frame, Gtk::PACK_SHRINK, 6);
1253 more_options_vbox.pack_start(input_frame, Gtk::PACK_SHRINK, 6);
1254 more_options_vbox.pack_start(output_frame, Gtk::PACK_SHRINK, 0);
1258 _connect_inputs.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::connect_inputs_clicked));
1259 _connect_outputs.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::connect_outputs_clicked));
1260 _limit_input_ports.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::limit_inputs_clicked));
1261 _limit_output_ports.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::limit_outputs_clicked));
1262 _create_master_bus.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::master_bus_button_clicked));
1264 /* note that more_options_vbox is "visible" by default even
1265 * though it may not be displayed to the user, this is so the dialog
1268 more_options_vbox.show_all ();
1270 session_options_page_index = append_page (more_options_vbox);
1271 set_page_title (more_options_vbox, _("Advanced Session Options"));
1272 set_page_complete (more_options_vbox, true);
1276 ArdourStartup::create_master_bus() const
1278 return _create_master_bus.get_active();
1282 ArdourStartup::master_channel_count() const
1284 return _master_bus_channel_count.get_value_as_int();
1288 ArdourStartup::connect_inputs() const
1290 return _connect_inputs.get_active();
1294 ArdourStartup::limit_inputs_used_for_connection() const
1296 return _limit_input_ports.get_active();
1300 ArdourStartup::input_limit_count() const
1302 return _input_limit_count.get_value_as_int();
1306 ArdourStartup::connect_outputs() const
1308 return _connect_outputs.get_active();
1312 ArdourStartup::limit_outputs_used_for_connection() const
1314 return _limit_output_ports.get_active();
1318 ArdourStartup::output_limit_count() const
1320 return _output_limit_count.get_value_as_int();
1324 ArdourStartup::connect_outs_to_master() const
1326 return _connect_outputs_to_master.get_active();
1330 ArdourStartup::connect_outs_to_physical() const
1332 return _connect_outputs_to_physical.get_active();
1336 ArdourStartup::connect_inputs_clicked ()
1338 _limit_input_ports.set_sensitive(_connect_inputs.get_active());
1340 if (_connect_inputs.get_active() && _limit_input_ports.get_active()) {
1341 _input_limit_count.set_sensitive(true);
1343 _input_limit_count.set_sensitive(false);
1348 ArdourStartup::connect_outputs_clicked ()
1350 bool const co = _connect_outputs.get_active ();
1351 _limit_output_ports.set_sensitive(co);
1352 _connect_outputs_to_master.set_sensitive(co);
1353 _connect_outputs_to_physical.set_sensitive(co);
1355 if (co && _limit_output_ports.get_active()) {
1356 _output_limit_count.set_sensitive(true);
1358 _output_limit_count.set_sensitive(false);
1363 ArdourStartup::limit_inputs_clicked ()
1365 _input_limit_count.set_sensitive(_limit_input_ports.get_active());
1369 ArdourStartup::limit_outputs_clicked ()
1371 _output_limit_count.set_sensitive(_limit_output_ports.get_active());
1375 ArdourStartup::master_bus_button_clicked ()
1377 bool const yn = _create_master_bus.get_active();
1379 _master_bus_channel_count.set_sensitive(yn);
1380 _connect_outputs_to_master.set_sensitive(yn);
1384 ArdourStartup::move_along_now ()
1386 gint cur = get_current_page ();
1388 if (cur == session_page_index) {
1389 if (more_new_session_options_button.get_active()) {
1390 set_current_page (session_options_page_index);
1398 ArdourStartup::recent_row_activated (const Gtk::TreePath&, Gtk::TreeViewColumn*)
1400 set_page_complete (session_vbox, true);
1405 ArdourStartup::existing_session_selected ()
1407 _existing_session_chooser_used = true;
1409 set_page_complete (session_vbox, true);
1414 ArdourStartup::been_here_before_path () const
1416 // XXXX use more specific version so we can catch upgrades
1417 return Glib::build_filename (user_config_directory (), ".a3");
1421 ArdourStartup::updates_button_clicked ()
1423 //now open a browser window so user can see more
1424 PBD::open_uri (Config->get_updates_url());
1428 ArdourStartup::info_scroller_update()
1430 info_scroller_count++;
1433 snprintf (buf, std::min(info_scroller_count,sizeof(buf)-1), "%s", ARDOUR_UI::instance()->announce_string().c_str() );
1434 buf[info_scroller_count] = 0;
1435 info_scroller_label.set_text (buf);
1436 info_scroller_label.show();
1438 if (info_scroller_count > ARDOUR_UI::instance()->announce_string().length()) {
1439 info_scroller_connection.disconnect();