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 , monitor_via_hardware_button (string_compose (_("Use an external mixer or the hardware mixer of your audio interface.\n"
74 "%1 will play NO role in monitoring"), PROGRAM_NAME))
75 , monitor_via_ardour_button (string_compose (_("Ask %1 to play back material as it is being recorded"), PROGRAM_NAME))
76 , new_folder_chooser (FILE_CHOOSER_ACTION_SELECT_FOLDER)
77 , more_new_session_options_button (_("Advanced options ..."))
78 , _output_limit_count_adj (1, 0, 100, 1, 10, 0)
79 , _input_limit_count_adj (1, 0, 100, 1, 10, 0)
80 , _master_bus_channel_count_adj (2, 0, 100, 1, 10, 0)
81 , audio_page_index (-1)
82 , new_user_page_index (-1)
83 , default_folder_page_index (-1)
84 , monitoring_page_index (-1)
85 , new_session_page_index (-1)
86 , initial_choice_index (-1)
87 , final_page_index (-1)
88 , session_options_page_index (-1)
89 , _existing_session_chooser_used (false)
91 new_user = !Glib::file_test (been_here_before_path(), Glib::FILE_TEST_EXISTS);
92 need_session_info = (session_name.empty() || require_new);
94 _provided_session_name = session_name;
95 _provided_session_path = session_path;
97 if (need_session_info || new_user) {
99 use_template_button.set_group (session_template_group);
100 use_session_as_template_button.set_group (session_template_group);
102 set_keep_above (true);
103 set_position (WIN_POS_CENTER);
104 set_border_width (12);
106 if ((icon_pixbuf = ::get_icon ("ardour_icon_48px")) == 0) {
107 throw failed_constructor();
110 list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
111 Glib::RefPtr<Gdk::Pixbuf> icon;
113 if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
114 window_icons.push_back (icon);
116 if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
117 window_icons.push_back (icon);
119 if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
120 window_icons.push_back (icon);
122 if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
123 window_icons.push_back (icon);
125 if (!window_icons.empty ()) {
126 set_default_icon_list (window_icons);
130 setup_prerelease_page ();
134 setup_new_user_page ();
135 setup_first_time_config_page ();
136 setup_monitoring_choice_page ();
137 setup_monitor_section_choice_page ();
139 setup_new_session_page ();
144 setup_initial_choice_page ();
146 setup_new_session_page ();
149 if (!template_name.empty()) {
150 use_template_button.set_active (false);
151 load_template_override = template_name;
158 ArdourStartup::~ArdourStartup ()
163 ArdourStartup::ready_without_display () const
165 return !new_user && !need_session_info;
169 ArdourStartup::setup_prerelease_page ()
171 VBox* vbox = manage (new VBox);
172 Label* label = manage (new Label);
173 label->set_markup (string_compose (_("<b>Welcome to this BETA release of Ardour %1</b>\n\n\
174 Ardour %1 has been released for Linux but because of the lack of testers,\n\
175 it is still at the beta stage on OS X. So, a few guidelines:\n\
177 1) Please do <b>NOT</b> use this software with the expectation that it is stable or reliable\n\
178 though it may be so, depending on your workflow.\n\
179 2) <b>Please do NOT use the forums at ardour.org to report issues</b>.\n\
180 3) Please <b>DO</b> use the bugtracker at http://tracker.ardour.org/ to report issues\n\
181 making sure to note the product version number as %1-beta.\n\
182 4) Please <b>DO</b> use the ardour-users mailing list to discuss ideas and pass on comments.\n\
183 5) Please <b>DO</b> join us on IRC for real time discussions about ardour3. You\n\
184 can get there directly from Ardour via the Help->Chat menu option.\n\
186 Full information on all the above can be found on the support page at\n\
188 http://ardour.org/support\n\
191 vbox->set_border_width (12);
192 vbox->pack_start (*label, false, false, 12);
196 set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
197 set_page_title (*vbox, _("This is a BETA RELEASE"));
198 set_page_complete (*vbox, true);
202 ArdourStartup::use_session_template ()
204 if (!load_template_override.empty()) {
208 if (use_template_button.get_active()) {
209 return template_chooser.get_active_row_number() > 0;
211 return !session_template_chooser.get_filename().empty();
216 ArdourStartup::session_template_name ()
218 if (!load_template_override.empty()) {
219 string the_path (ARDOUR::user_template_directory());
220 return Glib::build_filename (the_path, load_template_override + ARDOUR::template_suffix);
223 if (use_template_button.get_active()) {
224 TreeModel::iterator iter = template_chooser.get_active ();
225 TreeModel::Row row = (*iter);
226 string s = row[session_template_columns.path];
229 return session_template_chooser.get_filename();
235 ArdourStartup::session_name (bool& should_be_new)
237 if (ready_without_display()) {
238 return _provided_session_name;
241 /* Try recent session selection */
243 TreeIter iter = recent_session_display.get_selection()->get_selected();
246 should_be_new = false;
247 return (*iter)[recent_session_columns.visible_name];
250 if (_existing_session_chooser_used) {
251 /* existing session chosen from file chooser */
252 should_be_new = false;
253 return existing_session_chooser.get_filename ();
255 should_be_new = true;
256 string val = new_name_entry.get_text ();
257 strip_whitespace_edges (val);
263 ArdourStartup::session_folder ()
265 if (ready_without_display()) {
266 return _provided_session_path;
269 /* Try recent session selection */
271 TreeIter iter = recent_session_display.get_selection()->get_selected();
274 return (*iter)[recent_session_columns.fullpath];
277 if (_existing_session_chooser_used) {
278 /* existing session chosen from file chooser */
279 return existing_session_chooser.get_current_folder ();
281 std::string legal_session_folder_name = legalize_for_path (new_name_entry.get_text());
282 return Glib::build_filename (new_folder_chooser.get_current_folder(), legal_session_folder_name);
287 ArdourStartup::setup_new_user_page ()
289 Label* foomatic = manage (new Label);
291 foomatic->set_markup (string_compose (_("\
292 <span size=\"larger\">%1 is a digital audio workstation. You can use it to \
293 record, edit and mix multi-track audio. You can produce your \
294 own CDs, mix video soundtracks, or experiment with new \
295 ideas about music and sound. \
297 There are a few things that need to be configured before you start \
298 using the program.</span> \
300 foomatic->set_justify (JUSTIFY_FILL);
301 foomatic->set_line_wrap ();
303 HBox* hbox = manage (new HBox);
304 HBox* vbox = manage (new HBox);
306 vbox->set_border_width (24);
308 hbox->pack_start (*foomatic, true, true);
309 vbox->pack_start (*hbox, true, true);
315 new_user_page_index = append_page (*vbox);
316 set_page_type (*vbox, ASSISTANT_PAGE_INTRO);
317 set_page_title (*vbox, string_compose (_("Welcome to %1"), PROGRAM_NAME));
318 set_page_header_image (*vbox, icon_pixbuf);
319 set_page_complete (*vbox, true);
323 ArdourStartup::default_dir_changed ()
325 Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
326 // make new session folder chooser point to the new default
327 new_folder_chooser.set_current_folder (Config->get_default_session_parent_dir());
332 ArdourStartup::config_changed ()
334 config_modified = true;
338 ArdourStartup::setup_first_time_config_page ()
340 default_dir_chooser = manage (new FileChooserButton (string_compose (_("Default folder for %1 sessions"), PROGRAM_NAME),
341 FILE_CHOOSER_ACTION_SELECT_FOLDER));
342 Gtk::Label* txt = manage (new Label);
343 HBox* hbox = manage (new HBox);
344 VBox* vbox = manage (new VBox);
346 txt->set_markup (string_compose (_("\
347 Each project that you work on with %1 has its own folder.\n\
348 These can require a lot of disk space if you are recording audio.\n\
350 Where would you like new %1 sessions to be stored by default?\n\n\
351 <i>(You can put new sessions anywhere, this is just a default)</i>"), PROGRAM_NAME));
352 txt->set_alignment (0.0, 0.0);
354 vbox->set_spacing (18);
355 vbox->set_border_width (24);
357 hbox->pack_start (*default_dir_chooser, false, true, 8);
358 vbox->pack_start (*txt, false, false);
359 vbox->pack_start (*hbox, false, true);
361 default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
362 default_dir_chooser->signal_current_folder_changed().connect (sigc::mem_fun (*this, &ArdourStartup::default_dir_changed));
363 default_dir_chooser->show ();
367 default_folder_page_index = append_page (*vbox);
368 set_page_title (*vbox, _("Default folder for new sessions"));
369 set_page_header_image (*vbox, icon_pixbuf);
370 set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
372 /* user can just skip all these settings if they want to */
374 set_page_complete (*vbox, true);
378 ArdourStartup::setup_monitoring_choice_page ()
380 mon_vbox.set_spacing (18);
381 mon_vbox.set_border_width (24);
383 HBox* hbox = manage (new HBox);
384 VBox* vbox = manage (new VBox);
385 /* first button will be on by default */
386 RadioButton::Group g (monitor_via_ardour_button.get_group());
387 monitor_via_hardware_button.set_group (g);
389 monitor_label.set_markup(_("\
390 While recording instruments or vocals, you probably want to listen to the\n\
391 signal as well as record it. This is called \"monitoring\". There are\n\
392 different ways to do this depending on the equipment you have and the\n\
393 configuration of that equipment. The two most common are presented here.\n\
394 Please choose whichever one is right for your setup.\n\n\
395 <i>(You can change this preference at any time, via the Preferences dialog)</i>\n\n\
396 <i>If you do not understand what this is about, just accept the default.</i>"));
397 monitor_label.set_alignment (0.0, 0.0);
399 vbox->set_spacing (6);
401 vbox->pack_start (monitor_via_hardware_button, false, true);
402 vbox->pack_start (monitor_via_ardour_button, false, true);
403 hbox->pack_start (*vbox, true, true, 8);
404 mon_vbox.pack_start (monitor_label, false, false);
405 mon_vbox.pack_start (*hbox, false, false);
407 mon_vbox.show_all ();
409 monitoring_page_index = append_page (mon_vbox);
410 set_page_title (mon_vbox, _("Monitoring Choices"));
411 set_page_header_image (mon_vbox, icon_pixbuf);
413 /* user could just click on "Forward" if default
417 set_page_complete (mon_vbox, true);
421 ArdourStartup::setup_monitor_section_choice_page ()
423 mon_sec_vbox.set_spacing (18);
424 mon_sec_vbox.set_border_width (24);
426 HBox* hbox = manage (new HBox);
427 VBox* main_vbox = manage (new VBox);
429 Label* l = manage (new Label);
431 main_vbox->set_spacing (32);
433 no_monitor_section_button.set_label (_("Use a Master bus directly"));
434 l->set_alignment (0.0, 1.0);
435 l->set_markup(_("Connect the Master bus directly to your hardware outputs. This is preferable for simple usage."));
437 vbox = manage (new VBox);
438 vbox->set_spacing (6);
439 vbox->pack_start (no_monitor_section_button, false, true);
440 vbox->pack_start (*l, false, true);
442 main_vbox->pack_start (*vbox, false, false);
444 use_monitor_section_button.set_label (_("Use an additional Monitor bus"));
445 l = manage (new Label);
446 l->set_alignment (0.0, 1.0);
447 l->set_text (_("Use a Monitor bus between Master bus and hardware outputs for \n\
448 greater control in monitoring without affecting the mix."));
450 vbox = manage (new VBox);
451 vbox->set_spacing (6);
452 vbox->pack_start (use_monitor_section_button, false, true);
453 vbox->pack_start (*l, false, true);
455 main_vbox->pack_start (*vbox, false, false);
457 RadioButton::Group g (use_monitor_section_button.get_group());
458 no_monitor_section_button.set_group (g);
460 if (Config->get_use_monitor_bus()) {
461 use_monitor_section_button.set_active (true);
463 no_monitor_section_button.set_active (true);
466 use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
467 no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
469 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\
470 <i>If you do not understand what this is about, just accept the default.</i>"));
471 monitor_section_label.set_alignment (0.0, 0.0);
473 hbox->pack_start (*main_vbox, true, true, 8);
474 mon_sec_vbox.pack_start (*hbox, false, false);
475 mon_sec_vbox.pack_start (monitor_section_label, false, false);
477 mon_sec_vbox.show_all ();
479 monitor_section_page_index = append_page (mon_sec_vbox);
480 set_page_title (mon_sec_vbox, _("Monitor Section"));
481 set_page_header_image (mon_sec_vbox, icon_pixbuf);
483 /* user could just click on "Forward" if default
487 set_page_complete (mon_sec_vbox, true);
491 ArdourStartup::setup_initial_choice_page ()
493 ic_vbox.set_spacing (6);
494 ic_vbox.set_border_width (24);
496 /* append the page early because the recent session display will cause
497 calls to set_page_complete() on this page.
500 initial_choice_index = append_page (ic_vbox);
501 set_page_title (ic_vbox, string_compose("%1 %2", PROGRAM_NAME, VERSIONSTRING));
502 set_page_header_image (ic_vbox, icon_pixbuf);
505 HBox* centering_hbox = manage (new HBox);
506 VBox* centering_vbox = manage (new VBox);
508 centering_vbox->set_spacing (6);
510 Label* new_label = manage (new Label);
511 new_label->set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", _("Create a new session")));
512 new_label->set_alignment (0, 0.5);
514 ic_new_session_button.set_label (_("Configure the new session ..."));
515 ic_new_session_button.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::new_session_button_clicked));
517 centering_vbox->pack_start (*new_label, false, false, 12);
518 centering_vbox->pack_start (ic_new_session_button, false, true);
520 /* Possible update message */
522 if (ARDOUR_UI::instance()->announce_string() != "" ) {
524 Gtk::Frame *info_frame = manage(new Gtk::Frame);
525 info_frame->set_shadow_type(SHADOW_ETCHED_OUT);
526 centering_vbox->pack_start (*info_frame, false, false, 20);
528 Box *info_box = manage (new VBox);
529 info_box->set_border_width (12);
530 info_box->set_spacing (6);
531 info_box->set_name("mixbus_info_box");
533 info_box->pack_start (info_scroller_label, false, false);
535 info_frame->add (*info_box);
536 info_frame->show_all();
538 info_scroller_count = 0;
539 info_scroller_connection = Glib::signal_timeout().connect (mem_fun(*this, &ArdourStartup::info_scroller_update), 50);
541 Gtk::Button *updates_button = manage (new Gtk::Button (_("Check the website for more...")));
543 updates_button->signal_clicked().connect (mem_fun(*this, &ArdourStartup::updates_button_clicked) );
544 ARDOUR_UI::instance()->tooltips().set_tip (*updates_button, _("Click to open the program website in your web browser"));
546 info_box->pack_start (*updates_button, false, false);
549 /* recent session scroller */
551 recent_label.set_no_show_all (true);
552 recent_scroller.set_no_show_all (true);
554 recent_label.set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", _("Load a recent session")));
555 recent_label.set_alignment (0, 0.5);
557 recent_session_model = TreeStore::create (recent_session_columns);
559 recent_session_display.set_model (recent_session_model);
560 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
561 recent_session_display.set_headers_visible (false);
562 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
564 recent_session_display.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ArdourStartup::recent_session_row_selected));
566 recent_scroller.add (recent_session_display);
567 recent_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
568 recent_scroller.set_shadow_type (Gtk::SHADOW_IN);
570 recent_session_display.show();
571 recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &ArdourStartup::recent_row_activated));
573 centering_vbox->pack_start (recent_label, false, false, 12);
574 centering_vbox->pack_start (recent_scroller, false, true);
578 existing_session_chooser.set_title (_("Select session file"));
579 existing_session_chooser.signal_file_set().connect (sigc::mem_fun (*this, &ArdourStartup::existing_session_selected));
580 existing_session_chooser.set_current_folder(poor_mans_glob (Config->get_default_session_parent_dir()));
582 FileFilter session_filter;
583 session_filter.add_pattern ("*.ardour");
584 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
585 existing_session_chooser.add_filter (session_filter);
586 existing_session_chooser.set_filter (session_filter);
589 existing_session_chooser.add_shortcut_folder ("/Volumes");
592 Label* browse_label = manage (new Label);
593 browse_label->set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", _("Browse for other sessions")));
594 browse_label->set_alignment (0, 0.5);
596 centering_vbox->pack_start (*browse_label, false, false, 12);
597 centering_vbox->pack_start (existing_session_chooser, false, false);
601 centering_hbox->pack_start (*centering_vbox, true, true);
602 ic_vbox.pack_start (*centering_hbox, true, true);
605 /* user could just click on "Forward" if default
609 set_page_complete (ic_vbox, true);
613 ArdourStartup::session_selected ()
615 /* HACK HACK HACK ... change the "Apply" button label
619 Gtk::Widget* tl = ic_vbox.get_toplevel();
621 if ((win = dynamic_cast<Gtk::Window*>(tl)) != 0) {
622 /* ::get_default_widget() is not wrapped in gtkmm */
623 Gtk::Widget* def = wrap (gtk_window_get_default_widget (win->gobj()));
625 if ((button = dynamic_cast<Gtk::Button*>(def)) != 0) {
626 button->set_label (_("Open"));
632 ArdourStartup::new_session_button_clicked ()
634 _existing_session_chooser_used = false;
635 recent_session_display.get_selection()->unselect_all ();
636 set_current_page (new_session_page_index);
640 ArdourStartup::setup_final_page ()
642 final_page.set_text (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
644 final_page_index = append_page (final_page);
645 set_page_complete (final_page, true);
646 set_page_header_image (final_page, icon_pixbuf);
647 set_page_type (final_page, ASSISTANT_PAGE_CONFIRM);
651 ArdourStartup::on_cancel ()
653 _response = RESPONSE_CANCEL;
658 ArdourStartup::on_prepare (Gtk::Widget* page)
660 if (page == &session_new_vbox) {
662 /* if the user already defined a name by using the recent
663 * session list or browsing to an existing session
667 bool expect_new_ignored;
669 if (!session_name (expect_new_ignored).empty()) {
676 ArdourStartup::on_delete_event (GdkEventAny*)
678 _response = RESPONSE_CLOSE;
684 ArdourStartup::on_apply ()
686 if (config_modified) {
688 if (default_dir_chooser) {
689 Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
692 if (monitor_via_hardware_button.get_active()) {
693 Config->set_monitoring_model (ExternalMonitoring);
694 } else if (monitor_via_ardour_button.get_active()) {
695 Config->set_monitoring_model (SoftwareMonitoring);
698 Config->set_use_monitor_bus (use_monitor_section_button.get_active());
700 Config->save_state ();
705 /* "touch" the been-here-before path now we've successfully
706 made it through the first time setup (at least)
708 ofstream fout (been_here_before_path().c_str());
712 _response = RESPONSE_OK;
717 ArdourStartup::populate_session_templates ()
719 vector<TemplateInfo> templates;
721 find_session_templates (templates);
723 template_model->clear ();
725 for (vector<TemplateInfo>::iterator x = templates.begin(); x != templates.end(); ++x) {
728 row = *(template_model->append ());
730 row[session_template_columns.name] = (*x).name;
731 row[session_template_columns.path] = (*x).path;
734 if (!templates.empty()) {
735 /* select first row */
736 template_chooser.set_active (0);
741 ArdourStartup::setup_new_session_page ()
743 session_new_vbox.set_border_width (12);
744 session_new_vbox.set_spacing (18);
746 VBox *vbox1 = manage (new VBox);
747 HBox* hbox1 = manage (new HBox);
748 Label* label1 = manage (new Label);
750 vbox1->set_spacing (6);
752 hbox1->set_spacing (6);
753 hbox1->pack_start (*label1, false, false);
754 hbox1->pack_start (new_name_entry, true, true);
756 label1->set_text (_("Session name:"));
759 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
760 new_name_entry.set_text (Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name));
761 /* name provided - they can move right along */
762 set_page_complete (session_new_vbox, true);
765 new_name_entry.signal_changed().connect (sigc::mem_fun (*this, &ArdourStartup::new_name_changed));
766 new_name_entry.signal_activate().connect (sigc::mem_fun (*this, &ArdourStartup::move_along_now));
768 vbox1->pack_start (*hbox1, true, true);
772 HBox* hbox2 = manage (new HBox);
773 Label* label2 = manage (new Label);
775 hbox2->set_spacing (6);
776 hbox2->pack_start (*label2, false, false);
777 hbox2->pack_start (new_folder_chooser, true, true);
779 label2->set_text (_("Create session folder in:"));
781 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
782 new_folder_chooser.set_current_folder (poor_mans_glob (Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name)));
783 } else if (ARDOUR_UI::instance()->session_loaded) {
784 // point the new session file chooser at the parent directory of the current session
785 string session_parent_dir = Glib::path_get_dirname(ARDOUR_UI::instance()->the_session()->path());
786 string::size_type last_dir_sep = session_parent_dir.rfind(G_DIR_SEPARATOR);
787 session_parent_dir = session_parent_dir.substr(0, last_dir_sep);
788 new_folder_chooser.set_current_folder (session_parent_dir);
789 string default_session_folder = poor_mans_glob (Config->get_default_session_parent_dir());
792 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
793 new_folder_chooser.add_shortcut_folder (default_session_folder);
795 catch (Glib::Error & e) {
796 std::cerr << "new_folder_chooser.add_shortcut_folder (" << default_session_folder << ") threw Glib::Error " << e.what() << std::endl;
799 new_folder_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
801 new_folder_chooser.show ();
802 new_folder_chooser.set_title (_("Select folder for session"));
805 new_folder_chooser.add_shortcut_folder ("/Volumes");
808 vbox1->pack_start (*hbox2, false, false);
810 session_new_vbox.pack_start (*vbox1, false, false);
814 VBox *vbox2 = manage (new VBox);
815 HBox* hbox3 = manage (new HBox);
816 template_model = ListStore::create (session_template_columns);
818 vbox2->set_spacing (6);
820 VBox *vbox3 = manage (new VBox);
822 vbox3->set_spacing (6);
824 /* we may want to hide this and show it at various
825 times depending on the existence of templates.
827 template_chooser.set_no_show_all (true);
828 use_template_button.set_no_show_all (true);
830 HBox* hbox4a = manage (new HBox);
831 use_template_button.set_label (_("Use this template"));
833 TreeModel::Row row = *template_model->prepend ();
834 row[session_template_columns.name] = (_("no template"));
835 row[session_template_columns.path] = string();
837 hbox4a->set_spacing (6);
838 hbox4a->pack_start (use_template_button, false, false);
839 hbox4a->pack_start (template_chooser, true, true);
841 template_chooser.set_model (template_model);
843 Gtk::CellRendererText* text_renderer = Gtk::manage (new Gtk::CellRendererText);
844 text_renderer->property_editable() = false;
846 template_chooser.pack_start (*text_renderer);
847 template_chooser.add_attribute (text_renderer->property_text(), session_template_columns.name);
848 template_chooser.set_active (0);
850 vbox3->pack_start (*hbox4a, false, false);
855 session_template_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
857 HBox* hbox4b = manage (new HBox);
858 use_session_as_template_button.set_label (_("Use an existing session as a template:"));
860 hbox4b->set_spacing (6);
861 hbox4b->pack_start (use_session_as_template_button, false, false);
862 hbox4b->pack_start (session_template_chooser, true, true);
864 use_session_as_template_button.show ();
865 session_template_chooser.show ();
867 Gtk::FileFilter* session_filter = manage (new (Gtk::FileFilter));
868 session_filter->add_pattern (X_("*.ardour"));
869 session_template_chooser.set_filter (*session_filter);
870 session_template_chooser.set_title (_("Select template"));
872 vbox3->pack_start (*hbox4b, false, false);
877 HBox* hbox5 = manage (new HBox);
879 hbox5->set_spacing (6);
880 hbox5->pack_start (more_new_session_options_button, false, false);
882 setup_more_options_box ();
883 more_new_session_options_button.add (more_options_vbox);
885 vbox3->pack_start (*hbox5, false, false);
886 hbox3->pack_start (*vbox3, true, true, 8);
887 vbox2->pack_start (*hbox3, false, false);
891 session_new_vbox.pack_start (*vbox2, false, false);
892 session_new_vbox.show_all ();
894 new_session_page_index = append_page (session_new_vbox);
895 set_page_type (session_new_vbox, ASSISTANT_PAGE_CONTENT);
896 set_page_title (session_new_vbox, _("New Session"));
898 set_page_type (session_new_vbox, ASSISTANT_PAGE_CONFIRM);
902 ArdourStartup::new_name_changed ()
904 if (!new_name_entry.get_text().empty()) {
906 set_page_complete (session_new_vbox, true);
908 set_page_complete (session_new_vbox, false);
913 ArdourStartup::redisplay_recent_sessions ()
915 std::vector<std::string> session_directories;
916 RecentSessionsSorter cmp;
918 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
919 recent_session_model->clear ();
921 ARDOUR::RecentSessions rs;
922 ARDOUR::read_recent_sessions (rs);
925 recent_session_display.set_model (recent_session_model);
929 // sort them alphabetically
930 sort (rs.begin(), rs.end(), cmp);
932 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
933 session_directories.push_back ((*i).second);
936 int session_snapshot_count = 0;
938 for (vector<std::string>::const_iterator i = session_directories.begin(); i != session_directories.end(); ++i)
940 std::vector<std::string> state_file_paths;
942 // now get available states for this session
944 get_state_files_in_directory (*i, state_file_paths);
946 vector<string*>* states;
947 vector<const gchar*> item;
948 string fullpath = *i;
950 /* remove any trailing / */
952 if (fullpath[fullpath.length()-1] == '/') {
953 fullpath = fullpath.substr (0, fullpath.length()-1);
956 /* check whether session still exists */
957 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
958 /* session doesn't exist */
962 /* now get available states for this session */
964 if ((states = Session::possible_states (fullpath)) == 0) {
969 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
971 Gtk::TreeModel::Row row = *(recent_session_model->append());
973 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
974 row[recent_session_columns.fullpath] = fullpath;
975 row[recent_session_columns.tip] = Glib::Markup::escape_text (fullpath);
977 ++session_snapshot_count;
979 if (state_file_names.size() > 1) {
983 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
984 i2 != state_file_names.end(); ++i2) {
986 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
988 child_row[recent_session_columns.visible_name] = *i2;
989 child_row[recent_session_columns.fullpath] = fullpath;
990 child_row[recent_session_columns.tip] = Glib::Markup::escape_text (fullpath);
991 ++session_snapshot_count;
996 recent_session_display.set_tooltip_column(1); // recent_session_columns.tip
997 recent_session_display.set_model (recent_session_model);
998 return session_snapshot_count;
1003 ArdourStartup::recent_session_row_selected ()
1005 if (recent_session_display.get_selection()->count_selected_rows() > 0) {
1006 set_page_complete (ic_vbox, true);
1007 session_selected ();
1009 set_page_complete (ic_vbox, false);
1014 ArdourStartup::setup_more_options_box ()
1016 more_options_vbox.set_border_width (24);
1018 _output_limit_count.set_adjustment (_output_limit_count_adj);
1019 _input_limit_count.set_adjustment (_input_limit_count_adj);
1020 _master_bus_channel_count.set_adjustment (_master_bus_channel_count_adj);
1022 chan_count_label_1.set_text (_("channels"));
1023 chan_count_label_3.set_text (_("channels"));
1024 chan_count_label_4.set_text (_("channels"));
1026 chan_count_label_1.set_alignment(0,0.5);
1027 chan_count_label_1.set_padding(0,0);
1028 chan_count_label_1.set_line_wrap(false);
1030 chan_count_label_3.set_alignment(0,0.5);
1031 chan_count_label_3.set_padding(0,0);
1032 chan_count_label_3.set_line_wrap(false);
1034 chan_count_label_4.set_alignment(0,0.5);
1035 chan_count_label_4.set_padding(0,0);
1036 chan_count_label_4.set_line_wrap(false);
1038 bus_label.set_markup (_("<b>Busses</b>"));
1039 input_label.set_markup (_("<b>Inputs</b>"));
1040 output_label.set_markup (_("<b>Outputs</b>"));
1042 _master_bus_channel_count.set_flags(Gtk::CAN_FOCUS);
1043 _master_bus_channel_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1044 _master_bus_channel_count.set_numeric(true);
1045 _master_bus_channel_count.set_digits(0);
1046 _master_bus_channel_count.set_wrap(false);
1048 _create_master_bus.set_label (_("Create master bus"));
1049 _create_master_bus.set_flags(Gtk::CAN_FOCUS);
1050 _create_master_bus.set_relief(Gtk::RELIEF_NORMAL);
1051 _create_master_bus.set_mode(true);
1052 _create_master_bus.set_active(true);
1053 _create_master_bus.set_border_width(0);
1055 advanced_table.set_row_spacings(0);
1056 advanced_table.set_col_spacings(0);
1058 _connect_inputs.set_label (_("Automatically connect to physical inputs"));
1059 _connect_inputs.set_flags(Gtk::CAN_FOCUS);
1060 _connect_inputs.set_relief(Gtk::RELIEF_NORMAL);
1061 _connect_inputs.set_mode(true);
1062 _connect_inputs.set_active(Config->get_input_auto_connect() != ManualConnect);
1063 _connect_inputs.set_border_width(0);
1065 _limit_input_ports.set_label (_("Use only"));
1066 _limit_input_ports.set_flags(Gtk::CAN_FOCUS);
1067 _limit_input_ports.set_relief(Gtk::RELIEF_NORMAL);
1068 _limit_input_ports.set_mode(true);
1069 _limit_input_ports.set_sensitive(true);
1070 _limit_input_ports.set_border_width(0);
1072 _input_limit_count.set_flags(Gtk::CAN_FOCUS);
1073 _input_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1074 _input_limit_count.set_numeric(true);
1075 _input_limit_count.set_digits(0);
1076 _input_limit_count.set_wrap(false);
1077 _input_limit_count.set_sensitive(false);
1079 bus_hbox.pack_start (bus_table, Gtk::PACK_SHRINK, 18);
1081 bus_label.set_alignment(0, 0.5);
1082 bus_label.set_padding(0,0);
1083 bus_label.set_line_wrap(false);
1084 bus_label.set_selectable(false);
1085 bus_label.set_use_markup(true);
1086 bus_frame.set_shadow_type(Gtk::SHADOW_NONE);
1087 bus_frame.set_label_align(0,0.5);
1088 bus_frame.add(bus_hbox);
1089 bus_frame.set_label_widget(bus_label);
1091 bus_table.set_row_spacings (0);
1092 bus_table.set_col_spacings (0);
1093 bus_table.attach (_create_master_bus, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
1094 bus_table.attach (_master_bus_channel_count, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
1095 bus_table.attach (chan_count_label_1, 2, 3, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 0);
1097 input_port_limit_hbox.pack_start(_limit_input_ports, Gtk::PACK_SHRINK, 6);
1098 input_port_limit_hbox.pack_start(_input_limit_count, Gtk::PACK_SHRINK, 0);
1099 input_port_limit_hbox.pack_start(chan_count_label_3, Gtk::PACK_SHRINK, 6);
1100 input_port_vbox.pack_start(_connect_inputs, Gtk::PACK_SHRINK, 0);
1101 input_port_vbox.pack_start(input_port_limit_hbox, Gtk::PACK_EXPAND_PADDING, 0);
1102 input_table.set_row_spacings(0);
1103 input_table.set_col_spacings(0);
1104 input_table.attach(input_port_vbox, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 6);
1106 input_hbox.pack_start (input_table, Gtk::PACK_SHRINK, 18);
1108 input_label.set_alignment(0, 0.5);
1109 input_label.set_padding(0,0);
1110 input_label.set_line_wrap(false);
1111 input_label.set_selectable(false);
1112 input_label.set_use_markup(true);
1113 input_frame.set_shadow_type(Gtk::SHADOW_NONE);
1114 input_frame.set_label_align(0,0.5);
1115 input_frame.add(input_hbox);
1116 input_frame.set_label_widget(input_label);
1118 _connect_outputs.set_label (_("Automatically connect outputs"));
1119 _connect_outputs.set_flags(Gtk::CAN_FOCUS);
1120 _connect_outputs.set_relief(Gtk::RELIEF_NORMAL);
1121 _connect_outputs.set_mode(true);
1122 _connect_outputs.set_active(Config->get_output_auto_connect() != ManualConnect);
1123 _connect_outputs.set_border_width(0);
1124 _limit_output_ports.set_label (_("Use only"));
1125 _limit_output_ports.set_flags(Gtk::CAN_FOCUS);
1126 _limit_output_ports.set_relief(Gtk::RELIEF_NORMAL);
1127 _limit_output_ports.set_mode(true);
1128 _limit_output_ports.set_sensitive(true);
1129 _limit_output_ports.set_border_width(0);
1130 _output_limit_count.set_flags(Gtk::CAN_FOCUS);
1131 _output_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
1132 _output_limit_count.set_numeric(false);
1133 _output_limit_count.set_digits(0);
1134 _output_limit_count.set_wrap(false);
1135 _output_limit_count.set_sensitive(false);
1136 output_port_limit_hbox.pack_start(_limit_output_ports, Gtk::PACK_SHRINK, 6);
1137 output_port_limit_hbox.pack_start(_output_limit_count, Gtk::PACK_SHRINK, 0);
1138 output_port_limit_hbox.pack_start(chan_count_label_4, Gtk::PACK_SHRINK, 6);
1140 _connect_outputs_to_master.set_label (_("... to master bus"));
1141 _connect_outputs_to_master.set_flags(Gtk::CAN_FOCUS);
1142 _connect_outputs_to_master.set_relief(Gtk::RELIEF_NORMAL);
1143 _connect_outputs_to_master.set_mode(true);
1144 _connect_outputs_to_master.set_active(Config->get_output_auto_connect() == AutoConnectMaster);
1145 _connect_outputs_to_master.set_border_width(0);
1147 _connect_outputs_to_master.set_group (connect_outputs_group);
1148 _connect_outputs_to_physical.set_group (connect_outputs_group);
1150 _connect_outputs_to_physical.set_label (_("... to physical outputs"));
1151 _connect_outputs_to_physical.set_flags(Gtk::CAN_FOCUS);
1152 _connect_outputs_to_physical.set_relief(Gtk::RELIEF_NORMAL);
1153 _connect_outputs_to_physical.set_mode(true);
1154 _connect_outputs_to_physical.set_active(Config->get_output_auto_connect() == AutoConnectPhysical);
1155 _connect_outputs_to_physical.set_border_width(0);
1157 output_conn_vbox.pack_start(_connect_outputs, Gtk::PACK_SHRINK, 0);
1158 output_conn_vbox.pack_start(_connect_outputs_to_master, Gtk::PACK_SHRINK, 0);
1159 output_conn_vbox.pack_start(_connect_outputs_to_physical, Gtk::PACK_SHRINK, 0);
1160 output_vbox.set_border_width(6);
1162 output_port_vbox.pack_start(output_port_limit_hbox, Gtk::PACK_SHRINK, 0);
1164 output_vbox.pack_start(output_conn_vbox);
1165 output_vbox.pack_start(output_port_vbox);
1167 output_label.set_alignment(0, 0.5);
1168 output_label.set_padding(0,0);
1169 output_label.set_line_wrap(false);
1170 output_label.set_selectable(false);
1171 output_label.set_use_markup(true);
1172 output_frame.set_shadow_type(Gtk::SHADOW_NONE);
1173 output_frame.set_label_align(0,0.5);
1175 output_hbox.pack_start (output_vbox, Gtk::PACK_SHRINK, 18);
1177 output_frame.add(output_hbox);
1178 output_frame.set_label_widget(output_label);
1180 more_options_vbox.pack_start(advanced_table, Gtk::PACK_SHRINK, 0);
1181 more_options_vbox.pack_start(bus_frame, Gtk::PACK_SHRINK, 6);
1182 more_options_vbox.pack_start(input_frame, Gtk::PACK_SHRINK, 6);
1183 more_options_vbox.pack_start(output_frame, Gtk::PACK_SHRINK, 0);
1187 _connect_inputs.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::connect_inputs_clicked));
1188 _connect_outputs.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::connect_outputs_clicked));
1189 _limit_input_ports.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::limit_inputs_clicked));
1190 _limit_output_ports.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::limit_outputs_clicked));
1191 _create_master_bus.signal_clicked().connect (sigc::mem_fun (*this, &ArdourStartup::master_bus_button_clicked));
1193 /* note that more_options_vbox is "visible" by default even
1194 * though it may not be displayed to the user, this is so the dialog
1197 more_options_vbox.show_all ();
1201 ArdourStartup::create_master_bus() const
1203 return _create_master_bus.get_active();
1207 ArdourStartup::master_channel_count() const
1209 return _master_bus_channel_count.get_value_as_int();
1213 ArdourStartup::connect_inputs() const
1215 return _connect_inputs.get_active();
1219 ArdourStartup::limit_inputs_used_for_connection() const
1221 return _limit_input_ports.get_active();
1225 ArdourStartup::input_limit_count() const
1227 return _input_limit_count.get_value_as_int();
1231 ArdourStartup::connect_outputs() const
1233 return _connect_outputs.get_active();
1237 ArdourStartup::limit_outputs_used_for_connection() const
1239 return _limit_output_ports.get_active();
1243 ArdourStartup::output_limit_count() const
1245 return _output_limit_count.get_value_as_int();
1249 ArdourStartup::connect_outs_to_master() const
1251 return _connect_outputs_to_master.get_active();
1255 ArdourStartup::connect_outs_to_physical() const
1257 return _connect_outputs_to_physical.get_active();
1261 ArdourStartup::connect_inputs_clicked ()
1263 _limit_input_ports.set_sensitive(_connect_inputs.get_active());
1265 if (_connect_inputs.get_active() && _limit_input_ports.get_active()) {
1266 _input_limit_count.set_sensitive(true);
1268 _input_limit_count.set_sensitive(false);
1273 ArdourStartup::connect_outputs_clicked ()
1275 bool const co = _connect_outputs.get_active ();
1276 _limit_output_ports.set_sensitive(co);
1277 _connect_outputs_to_master.set_sensitive(co);
1278 _connect_outputs_to_physical.set_sensitive(co);
1280 if (co && _limit_output_ports.get_active()) {
1281 _output_limit_count.set_sensitive(true);
1283 _output_limit_count.set_sensitive(false);
1288 ArdourStartup::limit_inputs_clicked ()
1290 _input_limit_count.set_sensitive(_limit_input_ports.get_active());
1294 ArdourStartup::limit_outputs_clicked ()
1296 _output_limit_count.set_sensitive(_limit_output_ports.get_active());
1300 ArdourStartup::master_bus_button_clicked ()
1302 bool const yn = _create_master_bus.get_active();
1304 _master_bus_channel_count.set_sensitive(yn);
1305 _connect_outputs_to_master.set_sensitive(yn);
1309 ArdourStartup::move_along_now ()
1315 ArdourStartup::recent_row_activated (const Gtk::TreePath&, Gtk::TreeViewColumn*)
1317 set_page_complete (ic_vbox, true);
1322 ArdourStartup::existing_session_selected ()
1324 _existing_session_chooser_used = true;
1326 session_selected ();
1327 set_page_complete (ic_vbox, true);
1332 ArdourStartup::been_here_before_path () const
1334 // XXXX use more specific version so we can catch upgrades
1335 return Glib::build_filename (user_config_directory (), ".a3");
1339 ArdourStartup::updates_button_clicked ()
1341 //now open a browser window so user can see more
1342 PBD::open_uri (Config->get_updates_url());
1346 ArdourStartup::info_scroller_update()
1348 info_scroller_count++;
1351 snprintf (buf, std::min(info_scroller_count,sizeof(buf)-1), "%s", ARDOUR_UI::instance()->announce_string().c_str() );
1352 buf[info_scroller_count] = 0;
1353 info_scroller_label.set_text (buf);
1354 info_scroller_label.show();
1356 if (info_scroller_count > ARDOUR_UI::instance()->announce_string().length()) {
1357 info_scroller_connection.disconnect();
1364 ArdourStartup::on_map ()
1366 Gtk::Assistant::on_map ();
1368 populate_session_templates ();
1370 if (!template_model->children().empty()) {
1371 use_template_button.show();
1372 template_chooser.show ();
1374 use_template_button.hide();
1375 template_chooser.hide ();
1378 if (recent_session_model) {
1379 int cnt = redisplay_recent_sessions ();
1381 recent_scroller.show();
1382 recent_label.show ();
1385 recent_scroller.set_size_request (-1, 300);
1388 recent_scroller.hide();
1389 recent_label.hide ();