2 * Copyright (C) 2009-2011 David Robillard <d@drobilla.net>
3 * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
4 * Copyright (C) 2009-2016 Paul Davis <paul@linuxaudiosystems.com>
5 * Copyright (C) 2012-2015 Tim Mayberry <mojofunk@gmail.com>
6 * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
7 * Copyright (C) 2013 Colin Fletcher <colin.m.fletcher@googlemail.com>
8 * Copyright (C) 2013 Michael R. Fisher <mfisher@bketech.com>
9 * Copyright (C) 2015 John Emmas <john@creativepost.co.uk>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "gtk2ardour-config.h"
28 #include "gtk2ardour-version.h"
34 #include "pbd/gstdio_compat.h"
36 #include <gtkmm/main.h>
37 #include <gtkmm/filechooser.h>
39 #include "pbd/failed_constructor.h"
40 #include "pbd/scoped_file_descriptor.h"
41 #include "pbd/file_utils.h"
42 #include "pbd/replace_all.h"
43 #include "pbd/whitespace.h"
44 #include "pbd/stacktrace.h"
45 #include "pbd/openuri.h"
47 #include "ardour/audioengine.h"
48 #include "ardour/filesystem_paths.h"
49 #include "ardour/filename_extensions.h"
50 #include "ardour/plugin_manager.h"
51 #include "ardour/recent_sessions.h"
52 #include "ardour/session.h"
53 #include "ardour/session_state_utils.h"
54 #include "ardour/template_utils.h"
55 #include "ardour/profile.h"
57 #include "gtkmm2ext/utils.h"
61 #include "engine_dialog.h"
70 using namespace ARDOUR;
71 using namespace ARDOUR_UI_UTILS;
73 ArdourStartup* ArdourStartup::the_startup = 0;
75 ArdourStartup::ArdourStartup ()
76 : _response (RESPONSE_OK)
77 , config_modified (false)
78 , default_dir_chooser (0)
79 , monitor_via_hardware_button (string_compose (_("Use an external mixer or the hardware mixer of your audio interface.\n"
80 "%1 will play NO role in monitoring"), PROGRAM_NAME))
81 , monitor_via_ardour_button (string_compose (_("Ask %1 to play back material as it is being recorded"), PROGRAM_NAME))
82 , audio_page_index (-1)
83 , new_user_page_index (-1)
84 , default_folder_page_index (-1)
85 , monitoring_page_index (-1)
86 , final_page_index (-1)
88 set_position (WIN_POS_CENTER);
89 set_border_width (12);
91 if (! (icon_pixbuf = ::get_icon (PROGRAM_NAME "-icon_48px"))) {
92 throw failed_constructor();
95 list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
96 Glib::RefPtr<Gdk::Pixbuf> icon;
98 if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px"))) {
99 window_icons.push_back (icon);
101 if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px"))) {
102 window_icons.push_back (icon);
104 if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px"))) {
105 window_icons.push_back (icon);
107 if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px"))) {
108 window_icons.push_back (icon);
110 if (!window_icons.empty ()) {
111 set_default_icon_list (window_icons);
114 setup_new_user_page ();
115 setup_first_time_config_page ();
116 setup_monitoring_choice_page ();
117 setup_monitor_section_choice_page ();
123 ArdourStartup::~ArdourStartup ()
128 ArdourStartup::required ()
130 if (Glib::file_test (ARDOUR::been_here_before_path (), Glib::FILE_TEST_EXISTS)) {
138 ArdourStartup::setup_new_user_page ()
140 Label* foomatic = manage (new Label);
142 foomatic->set_markup (string_compose (_("\
143 <span size=\"larger\">%1 is a digital audio workstation. You can use it to \
144 record, edit and mix multi-track audio. You can produce your \
145 own CDs, mix video soundtracks, or experiment with new \
146 ideas about music and sound. \
148 There are a few things that need to be configured before you start \
149 using the program.</span> \
151 foomatic->set_justify (JUSTIFY_FILL);
152 foomatic->set_line_wrap ();
154 HBox* hbox = manage (new HBox);
155 HBox* vbox = manage (new HBox);
157 vbox->set_border_width (24);
159 hbox->pack_start (*foomatic, true, true);
160 vbox->pack_start (*hbox, true, true);
166 new_user_page_index = append_page (*vbox);
167 set_page_type (*vbox, ASSISTANT_PAGE_INTRO);
168 set_page_title (*vbox, string_compose (_("Welcome to %1"), PROGRAM_NAME));
169 set_page_header_image (*vbox, icon_pixbuf);
170 set_page_complete (*vbox, true);
174 ArdourStartup::default_dir_changed ()
176 Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
177 // make new session folder chooser point to the new default
178 new_folder_chooser.set_current_folder (Config->get_default_session_parent_dir());
183 ArdourStartup::config_changed ()
185 config_modified = true;
189 ArdourStartup::setup_first_time_config_page ()
191 default_dir_chooser = manage (new FileChooserButton (string_compose (_("Default folder for %1 sessions"), PROGRAM_NAME),
192 FILE_CHOOSER_ACTION_SELECT_FOLDER));
193 Gtk::Label* txt = manage (new Label);
194 HBox* hbox = manage (new HBox);
195 VBox* vbox = manage (new VBox);
197 txt->set_markup (string_compose (_("\
198 Each project that you work on with %1 has its own folder.\n\
199 These can require a lot of disk space if you are recording audio.\n\
201 Where would you like new %1 sessions to be stored by default?\n\n\
202 <i>(You can put new sessions anywhere, this is just a default)</i>"), PROGRAM_NAME));
203 txt->set_alignment (0.0, 0.0);
205 vbox->set_spacing (18);
206 vbox->set_border_width (24);
208 hbox->pack_start (*default_dir_chooser, false, true, 8);
209 vbox->pack_start (*txt, false, false);
210 vbox->pack_start (*hbox, false, true);
212 cerr << "set default folder to " << poor_mans_glob (Config->get_default_session_parent_dir()) << endl;
213 Gtkmm2ext::add_volume_shortcuts (*default_dir_chooser);
214 default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
215 default_dir_chooser->signal_current_folder_changed().connect (sigc::mem_fun (*this, &ArdourStartup::default_dir_changed));
216 default_dir_chooser->show ();
220 default_folder_page_index = append_page (*vbox);
221 set_page_title (*vbox, _("Default folder for new sessions"));
222 set_page_header_image (*vbox, icon_pixbuf);
223 set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
225 /* user can just skip all these settings if they want to */
227 set_page_complete (*vbox, true);
231 ArdourStartup::setup_monitoring_choice_page ()
233 mon_vbox.set_spacing (18);
234 mon_vbox.set_border_width (24);
236 HBox* hbox = manage (new HBox);
237 VBox* vbox = manage (new VBox);
238 /* first button will be on by default */
239 RadioButton::Group g (monitor_via_ardour_button.get_group());
240 monitor_via_hardware_button.set_group (g);
242 monitor_label.set_markup(_("\
243 While recording instruments or vocals, you probably want to listen to the\n\
244 signal as well as record it. This is called \"monitoring\". There are\n\
245 different ways to do this depending on the equipment you have and the\n\
246 configuration of that equipment. The two most common are presented here.\n\
247 Please choose whichever one is right for your setup.\n\n\
248 <i>(You can change this preference at any time, via the Preferences dialog)</i>\n\n\
249 <i>If you do not understand what this is about, just accept the default.</i>"));
250 monitor_label.set_alignment (0.0, 0.0);
252 vbox->set_spacing (6);
254 vbox->pack_start (monitor_via_hardware_button, false, true);
255 vbox->pack_start (monitor_via_ardour_button, false, true);
256 hbox->pack_start (*vbox, true, true, 8);
257 mon_vbox.pack_start (monitor_label, false, false);
258 mon_vbox.pack_start (*hbox, false, false);
260 mon_vbox.show_all ();
262 monitoring_page_index = append_page (mon_vbox);
263 set_page_title (mon_vbox, _("Monitoring Choices"));
264 set_page_header_image (mon_vbox, icon_pixbuf);
266 monitor_via_hardware_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
267 monitor_via_ardour_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
269 /* user could just click on "Forward" if default
273 set_page_complete (mon_vbox, true);
277 ArdourStartup::setup_monitor_section_choice_page ()
279 mon_sec_vbox.set_spacing (18);
280 mon_sec_vbox.set_border_width (24);
282 HBox* hbox = manage (new HBox);
283 VBox* main_vbox = manage (new VBox);
285 Label* l = manage (new Label);
287 main_vbox->set_spacing (32);
289 no_monitor_section_button.set_label (_("Use a Master bus directly"));
290 l->set_alignment (0.0, 1.0);
291 l->set_markup(_("Connect the Master bus directly to your hardware outputs. This is preferable for simple usage."));
293 vbox = manage (new VBox);
294 vbox->set_spacing (6);
295 vbox->pack_start (no_monitor_section_button, false, true);
296 vbox->pack_start (*l, false, true);
298 main_vbox->pack_start (*vbox, false, false);
300 use_monitor_section_button.set_label (_("Use an additional Monitor bus"));
301 l = manage (new Label);
302 l->set_alignment (0.0, 1.0);
303 l->set_text (_("Use a Monitor bus between Master bus and hardware outputs for \n\
304 greater control in monitoring without affecting the mix."));
306 vbox = manage (new VBox);
307 vbox->set_spacing (6);
308 vbox->pack_start (use_monitor_section_button, false, true);
309 vbox->pack_start (*l, false, true);
311 main_vbox->pack_start (*vbox, false, false);
313 RadioButton::Group g (use_monitor_section_button.get_group());
314 no_monitor_section_button.set_group (g);
316 if (Config->get_use_monitor_bus()) {
317 use_monitor_section_button.set_active (true);
319 no_monitor_section_button.set_active (true);
322 use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
323 no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
325 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\
326 <i>If you do not understand what this is about, just accept the default.</i>"));
327 monitor_section_label.set_alignment (0.0, 0.0);
329 hbox->pack_start (*main_vbox, true, true, 8);
330 mon_sec_vbox.pack_start (*hbox, false, false);
331 mon_sec_vbox.pack_start (monitor_section_label, false, false);
333 mon_sec_vbox.show_all ();
335 monitor_section_page_index = append_page (mon_sec_vbox);
336 set_page_title (mon_sec_vbox, _("Monitor Section"));
337 set_page_header_image (mon_sec_vbox, icon_pixbuf);
339 /* user could just click on "Forward" if default
343 set_page_complete (mon_sec_vbox, true);
347 ArdourStartup::setup_final_page ()
349 string msg = string_compose (_("%1 is ready for use"), PROGRAM_NAME);
351 plugin_disco_button.signal_clicked().connect (sigc::mem_fun(*this, &ArdourStartup::discover_plugins));
352 plugin_disco_button.set_label (_("Scan for Plugins"));
353 plugin_disco_button.show ();
355 Gtk::Label* final_label = manage (new Label);
356 final_label->set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", msg));
357 final_label->show ();
359 VBox* vbox = manage (new VBox);
360 vbox->pack_start (*final_label, true, true);
361 if (!Profile->get_mixbus()) {
362 vbox->pack_start (plugin_disco_button, true, false);
366 final_page_index = append_page (*vbox);
367 set_page_complete (*vbox, true);
368 set_page_header_image (*vbox, icon_pixbuf);
369 set_page_type (*vbox, ASSISTANT_PAGE_CONFIRM);
373 ArdourStartup::discover_plugins () {
374 plugin_disco_button.set_sensitive (false);
375 PluginManager::instance().refresh();
379 ArdourStartup::on_cancel ()
381 _response = RESPONSE_CANCEL;
386 ArdourStartup::on_delete_event (GdkEventAny*)
388 _response = RESPONSE_CLOSE;
394 ArdourStartup::on_apply ()
396 /* file-chooser button does not emit 'current_folder_changed' signal
397 * when a folder from the dropdown or the sidebar is chosen.
398 * -> explicitly poll for the dir as suggested by the gtk documentation.
400 if (default_dir_chooser && default_dir_chooser->get_filename() != Config->get_default_session_parent_dir ()) {
401 config_modified = true;
404 if (config_modified) {
406 if (default_dir_chooser) {
407 Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
410 if (monitor_via_hardware_button.get_active()) {
411 Config->set_monitoring_model (ExternalMonitoring);
412 } else if (monitor_via_ardour_button.get_active()) {
413 Config->set_monitoring_model (SoftwareMonitoring);
416 Config->set_use_monitor_bus (use_monitor_section_button.get_active());
418 Config->save_state ();
423 /* "touch" the been-here-before path now we've successfully
424 made it through the first time setup (at least)
426 PBD::ScopedFileDescriptor fout (g_open (been_here_before_path ().c_str(), O_CREAT|O_TRUNC|O_RDWR, 0666));
430 _response = RESPONSE_OK;
436 ArdourStartup::move_along_now ()