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"
22 #include "gtk2ardour-version.h"
28 #include "pbd/gstdio_compat.h"
30 #include <gtkmm/main.h>
31 #include <gtkmm/filechooser.h>
33 #include "pbd/failed_constructor.h"
34 #include "pbd/scoped_file_descriptor.h"
35 #include "pbd/file_utils.h"
36 #include "pbd/replace_all.h"
37 #include "pbd/whitespace.h"
38 #include "pbd/stacktrace.h"
39 #include "pbd/openuri.h"
41 #include "ardour/audioengine.h"
42 #include "ardour/filesystem_paths.h"
43 #include "ardour/filename_extensions.h"
44 #include "ardour/plugin_manager.h"
45 #include "ardour/recent_sessions.h"
46 #include "ardour/session.h"
47 #include "ardour/session_state_utils.h"
48 #include "ardour/template_utils.h"
49 #include "ardour/profile.h"
53 #include "engine_dialog.h"
62 using namespace ARDOUR;
63 using namespace ARDOUR_UI_UTILS;
65 ArdourStartup* ArdourStartup::the_startup = 0;
67 ArdourStartup::ArdourStartup ()
68 : _response (RESPONSE_OK)
69 , config_modified (false)
70 , default_dir_chooser (0)
71 , monitor_via_hardware_button (string_compose (_("Use an external mixer or the hardware mixer of your audio interface.\n"
72 "%1 will play NO role in monitoring"), PROGRAM_NAME))
73 , monitor_via_ardour_button (string_compose (_("Ask %1 to play back material as it is being recorded"), PROGRAM_NAME))
74 , audio_page_index (-1)
75 , new_user_page_index (-1)
76 , default_folder_page_index (-1)
77 , monitoring_page_index (-1)
78 , final_page_index (-1)
80 set_position (WIN_POS_CENTER);
81 set_border_width (12);
83 if ((icon_pixbuf = ::get_icon (PROGRAM_NAME "-icon_48px")) == 0) {
84 throw failed_constructor();
87 list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
88 Glib::RefPtr<Gdk::Pixbuf> icon;
90 if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px")) != 0) {
91 window_icons.push_back (icon);
93 if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px")) != 0) {
94 window_icons.push_back (icon);
96 if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px")) != 0) {
97 window_icons.push_back (icon);
99 if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px")) != 0) {
100 window_icons.push_back (icon);
102 if (!window_icons.empty ()) {
103 set_default_icon_list (window_icons);
106 setup_prerelease_page ();
107 setup_new_user_page ();
108 setup_first_time_config_page ();
109 setup_monitoring_choice_page ();
110 setup_monitor_section_choice_page ();
116 ArdourStartup::~ArdourStartup ()
121 ArdourStartup::required ()
123 /* look for a "been here before" file for this version or earlier
127 const int current_version = atoi (PROGRAM_VERSION);
129 for (int v = current_version; v != 0; --v) {
130 if (Glib::file_test (ARDOUR::been_here_before_path (v), Glib::FILE_TEST_EXISTS)) {
131 if (v != current_version) {
132 /* older version exists, create the current one */
133 PBD::ScopedFileDescriptor fout (g_open (been_here_before_path (current_version).c_str(), O_CREAT|O_TRUNC|O_RDWR, 0666));
143 ArdourStartup::setup_prerelease_page ()
145 VBox* vbox = manage (new VBox);
146 Label* label = manage (new Label);
147 label->set_markup (string_compose (_("<b>Welcome to this build of %1 %2</b>\n\n\
148 There are still several issues and bugs to be worked on,\n\
149 as well as general workflow improvements, before this can be considered\n\
150 release software. So, a few guidelines:\n\
152 1) Please do <b>NOT</b> use this software with the expectation that it is stable or reliable\n\
153 though it may be so, depending on your workflow.\n\
154 2) Please wait for a helpful writeup of new features.\n\
155 3) <b>Please do NOT use the forums at ardour.org to report issues</b>.\n\
156 4) Please <b>DO</b> use the bugtracker at http://tracker.ardour.org/ to report issues\n\
157 making sure to note the product version number as 5.0-pre.\n\
158 5) Please <b>DO</b> use the ardour-users mailing list to discuss ideas and pass on comments.\n\
159 6) Please <b>DO</b> join us on IRC for real time discussions about %1 %2. You\n\
160 can get there directly from within the program via the Help->Chat menu option.\n\
162 Full information on all the above can be found on the support page at\n\
164 http://ardour.org/support\n\
165 "), PROGRAM_NAME, VERSIONSTRING));
167 vbox->set_border_width (12);
168 vbox->pack_start (*label, false, false, 12);
172 set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
173 set_page_title (*vbox, _("This is a BETA RELEASE"));
174 set_page_complete (*vbox, true);
178 ArdourStartup::setup_new_user_page ()
180 Label* foomatic = manage (new Label);
182 foomatic->set_markup (string_compose (_("\
183 <span size=\"larger\">%1 is a digital audio workstation. You can use it to \
184 record, edit and mix multi-track audio. You can produce your \
185 own CDs, mix video soundtracks, or experiment with new \
186 ideas about music and sound. \
188 There are a few things that need to be configured before you start \
189 using the program.</span> \
191 foomatic->set_justify (JUSTIFY_FILL);
192 foomatic->set_line_wrap ();
194 HBox* hbox = manage (new HBox);
195 HBox* vbox = manage (new HBox);
197 vbox->set_border_width (24);
199 hbox->pack_start (*foomatic, true, true);
200 vbox->pack_start (*hbox, true, true);
206 new_user_page_index = append_page (*vbox);
207 set_page_type (*vbox, ASSISTANT_PAGE_INTRO);
208 set_page_title (*vbox, string_compose (_("Welcome to %1"), PROGRAM_NAME));
209 set_page_header_image (*vbox, icon_pixbuf);
210 set_page_complete (*vbox, true);
214 ArdourStartup::default_dir_changed ()
216 Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
217 // make new session folder chooser point to the new default
218 new_folder_chooser.set_current_folder (Config->get_default_session_parent_dir());
223 ArdourStartup::config_changed ()
225 config_modified = true;
229 ArdourStartup::setup_first_time_config_page ()
231 default_dir_chooser = manage (new FileChooserButton (string_compose (_("Default folder for %1 sessions"), PROGRAM_NAME),
232 FILE_CHOOSER_ACTION_SELECT_FOLDER));
233 Gtk::Label* txt = manage (new Label);
234 HBox* hbox = manage (new HBox);
235 VBox* vbox = manage (new VBox);
237 txt->set_markup (string_compose (_("\
238 Each project that you work on with %1 has its own folder.\n\
239 These can require a lot of disk space if you are recording audio.\n\
241 Where would you like new %1 sessions to be stored by default?\n\n\
242 <i>(You can put new sessions anywhere, this is just a default)</i>"), PROGRAM_NAME));
243 txt->set_alignment (0.0, 0.0);
245 vbox->set_spacing (18);
246 vbox->set_border_width (24);
248 hbox->pack_start (*default_dir_chooser, false, true, 8);
249 vbox->pack_start (*txt, false, false);
250 vbox->pack_start (*hbox, false, true);
252 cerr << "set default folder to " << poor_mans_glob (Config->get_default_session_parent_dir()) << endl;
253 default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
254 default_dir_chooser->signal_current_folder_changed().connect (sigc::mem_fun (*this, &ArdourStartup::default_dir_changed));
255 default_dir_chooser->show ();
259 default_folder_page_index = append_page (*vbox);
260 set_page_title (*vbox, _("Default folder for new sessions"));
261 set_page_header_image (*vbox, icon_pixbuf);
262 set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
264 /* user can just skip all these settings if they want to */
266 set_page_complete (*vbox, true);
270 ArdourStartup::setup_monitoring_choice_page ()
272 mon_vbox.set_spacing (18);
273 mon_vbox.set_border_width (24);
275 HBox* hbox = manage (new HBox);
276 VBox* vbox = manage (new VBox);
277 /* first button will be on by default */
278 RadioButton::Group g (monitor_via_ardour_button.get_group());
279 monitor_via_hardware_button.set_group (g);
281 monitor_label.set_markup(_("\
282 While recording instruments or vocals, you probably want to listen to the\n\
283 signal as well as record it. This is called \"monitoring\". There are\n\
284 different ways to do this depending on the equipment you have and the\n\
285 configuration of that equipment. The two most common are presented here.\n\
286 Please choose whichever one is right for your setup.\n\n\
287 <i>(You can change this preference at any time, via the Preferences dialog)</i>\n\n\
288 <i>If you do not understand what this is about, just accept the default.</i>"));
289 monitor_label.set_alignment (0.0, 0.0);
291 vbox->set_spacing (6);
293 vbox->pack_start (monitor_via_hardware_button, false, true);
294 vbox->pack_start (monitor_via_ardour_button, false, true);
295 hbox->pack_start (*vbox, true, true, 8);
296 mon_vbox.pack_start (monitor_label, false, false);
297 mon_vbox.pack_start (*hbox, false, false);
299 mon_vbox.show_all ();
301 monitoring_page_index = append_page (mon_vbox);
302 set_page_title (mon_vbox, _("Monitoring Choices"));
303 set_page_header_image (mon_vbox, icon_pixbuf);
305 /* user could just click on "Forward" if default
309 set_page_complete (mon_vbox, true);
313 ArdourStartup::setup_monitor_section_choice_page ()
315 mon_sec_vbox.set_spacing (18);
316 mon_sec_vbox.set_border_width (24);
318 HBox* hbox = manage (new HBox);
319 VBox* main_vbox = manage (new VBox);
321 Label* l = manage (new Label);
323 main_vbox->set_spacing (32);
325 no_monitor_section_button.set_label (_("Use a Master bus directly"));
326 l->set_alignment (0.0, 1.0);
327 l->set_markup(_("Connect the Master bus directly to your hardware outputs. This is preferable for simple usage."));
329 vbox = manage (new VBox);
330 vbox->set_spacing (6);
331 vbox->pack_start (no_monitor_section_button, false, true);
332 vbox->pack_start (*l, false, true);
334 main_vbox->pack_start (*vbox, false, false);
336 use_monitor_section_button.set_label (_("Use an additional Monitor bus"));
337 l = manage (new Label);
338 l->set_alignment (0.0, 1.0);
339 l->set_text (_("Use a Monitor bus between Master bus and hardware outputs for \n\
340 greater control in monitoring without affecting the mix."));
342 vbox = manage (new VBox);
343 vbox->set_spacing (6);
344 vbox->pack_start (use_monitor_section_button, false, true);
345 vbox->pack_start (*l, false, true);
347 main_vbox->pack_start (*vbox, false, false);
349 RadioButton::Group g (use_monitor_section_button.get_group());
350 no_monitor_section_button.set_group (g);
352 if (Config->get_use_monitor_bus()) {
353 use_monitor_section_button.set_active (true);
355 no_monitor_section_button.set_active (true);
358 use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
359 no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
361 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\
362 <i>If you do not understand what this is about, just accept the default.</i>"));
363 monitor_section_label.set_alignment (0.0, 0.0);
365 hbox->pack_start (*main_vbox, true, true, 8);
366 mon_sec_vbox.pack_start (*hbox, false, false);
367 mon_sec_vbox.pack_start (monitor_section_label, false, false);
369 mon_sec_vbox.show_all ();
371 monitor_section_page_index = append_page (mon_sec_vbox);
372 set_page_title (mon_sec_vbox, _("Monitor Section"));
373 set_page_header_image (mon_sec_vbox, icon_pixbuf);
375 /* user could just click on "Forward" if default
379 set_page_complete (mon_sec_vbox, true);
383 ArdourStartup::setup_final_page ()
385 string msg = string_compose (_("%1 is ready for use"), PROGRAM_NAME);
387 plugin_disco_button.signal_clicked().connect (sigc::mem_fun(*this, &ArdourStartup::discover_plugins));
388 plugin_disco_button.set_label (_("Scan for Plugins"));
389 plugin_disco_button.show ();
391 Gtk::Label* final_label = manage (new Label);
392 final_label->set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", msg));
393 final_label->show ();
395 VBox* vbox = manage (new VBox);
396 vbox->pack_start (*final_label, true, true);
397 if (!Profile->get_mixbus()) {
398 vbox->pack_start (plugin_disco_button, true, false);
402 final_page_index = append_page (*vbox);
403 set_page_complete (*vbox, true);
404 set_page_header_image (*vbox, icon_pixbuf);
405 set_page_type (*vbox, ASSISTANT_PAGE_CONFIRM);
409 ArdourStartup::discover_plugins () {
410 plugin_disco_button.set_sensitive (false);
411 PluginManager::instance().refresh();
415 ArdourStartup::on_cancel ()
417 _response = RESPONSE_CANCEL;
422 ArdourStartup::on_delete_event (GdkEventAny*)
424 _response = RESPONSE_CLOSE;
430 ArdourStartup::on_apply ()
432 /* file-chooser button does not emit 'current_folder_changed' signal
433 * when a folder from the dropdown or the sidebar is chosen.
434 * -> explicitly poll for the dir as suggested by the gtk documentation.
436 if (default_dir_chooser && default_dir_chooser->get_filename() != Config->get_default_session_parent_dir ()) {
437 config_modified = true;
440 if (config_modified) {
442 if (default_dir_chooser) {
443 Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
446 if (monitor_via_hardware_button.get_active()) {
447 Config->set_monitoring_model (ExternalMonitoring);
448 } else if (monitor_via_ardour_button.get_active()) {
449 Config->set_monitoring_model (SoftwareMonitoring);
452 Config->set_use_monitor_bus (use_monitor_section_button.get_active());
454 Config->save_state ();
459 /* "touch" the been-here-before path now we've successfully
460 made it through the first time setup (at least)
462 PBD::ScopedFileDescriptor fout (g_open (been_here_before_path ().c_str(), O_CREAT|O_TRUNC|O_RDWR, 0666));
466 _response = RESPONSE_OK;
472 ArdourStartup::move_along_now ()