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