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"
52 #include "engine_dialog.h"
61 using namespace ARDOUR;
62 using namespace ARDOUR_UI_UTILS;
64 ArdourStartup* ArdourStartup::the_startup = 0;
66 ArdourStartup::ArdourStartup ()
67 : _response (RESPONSE_OK)
68 , config_modified (false)
69 , default_dir_chooser (0)
70 , monitor_via_hardware_button (string_compose (_("Use an external mixer or the hardware mixer of your audio interface.\n"
71 "%1 will play NO role in monitoring"), PROGRAM_NAME))
72 , monitor_via_ardour_button (string_compose (_("Ask %1 to play back material as it is being recorded"), PROGRAM_NAME))
73 , audio_page_index (-1)
74 , new_user_page_index (-1)
75 , default_folder_page_index (-1)
76 , monitoring_page_index (-1)
77 , final_page_index (-1)
79 set_position (WIN_POS_CENTER);
80 set_border_width (12);
82 if ((icon_pixbuf = ::get_icon ("ardour_icon_48px")) == 0) {
83 throw failed_constructor();
86 list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
87 Glib::RefPtr<Gdk::Pixbuf> icon;
89 if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
90 window_icons.push_back (icon);
92 if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
93 window_icons.push_back (icon);
95 if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
96 window_icons.push_back (icon);
98 if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
99 window_icons.push_back (icon);
101 if (!window_icons.empty ()) {
102 set_default_icon_list (window_icons);
105 setup_new_user_page ();
106 setup_first_time_config_page ();
107 setup_monitoring_choice_page ();
108 setup_monitor_section_choice_page ();
114 ArdourStartup::~ArdourStartup ()
119 ArdourStartup::required ()
121 /* look for a "been here before" file for this version or earlier
125 const int current_version = atoi (PROGRAM_VERSION);
127 for (int v = current_version; v != 0; --v) {
128 if (Glib::file_test (ARDOUR::been_here_before_path (v), Glib::FILE_TEST_EXISTS)) {
129 if (v != current_version) {
130 /* older version exists, create the current one */
131 PBD::ScopedFileDescriptor fout (g_open (been_here_before_path (current_version).c_str(), O_CREAT|O_TRUNC|O_RDWR, 0666));
141 ArdourStartup::setup_new_user_page ()
143 Label* foomatic = manage (new Label);
145 foomatic->set_markup (string_compose (_("\
146 <span size=\"larger\">%1 is a digital audio workstation. You can use it to \
147 record, edit and mix multi-track audio. You can produce your \
148 own CDs, mix video soundtracks, or experiment with new \
149 ideas about music and sound. \
151 There are a few things that need to be configured before you start \
152 using the program.</span> \
154 foomatic->set_justify (JUSTIFY_FILL);
155 foomatic->set_line_wrap ();
157 HBox* hbox = manage (new HBox);
158 HBox* vbox = manage (new HBox);
160 vbox->set_border_width (24);
162 hbox->pack_start (*foomatic, true, true);
163 vbox->pack_start (*hbox, true, true);
169 new_user_page_index = append_page (*vbox);
170 set_page_type (*vbox, ASSISTANT_PAGE_INTRO);
171 set_page_title (*vbox, string_compose (_("Welcome to %1"), PROGRAM_NAME));
172 set_page_header_image (*vbox, icon_pixbuf);
173 set_page_complete (*vbox, true);
177 ArdourStartup::default_dir_changed ()
179 Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
180 // make new session folder chooser point to the new default
181 new_folder_chooser.set_current_folder (Config->get_default_session_parent_dir());
186 ArdourStartup::config_changed ()
188 config_modified = true;
192 ArdourStartup::setup_first_time_config_page ()
194 default_dir_chooser = manage (new FileChooserButton (string_compose (_("Default folder for %1 sessions"), PROGRAM_NAME),
195 FILE_CHOOSER_ACTION_SELECT_FOLDER));
196 Gtk::Label* txt = manage (new Label);
197 HBox* hbox = manage (new HBox);
198 VBox* vbox = manage (new VBox);
200 txt->set_markup (string_compose (_("\
201 Each project that you work on with %1 has its own folder.\n\
202 These can require a lot of disk space if you are recording audio.\n\
204 Where would you like new %1 sessions to be stored by default?\n\n\
205 <i>(You can put new sessions anywhere, this is just a default)</i>"), PROGRAM_NAME));
206 txt->set_alignment (0.0, 0.0);
208 vbox->set_spacing (18);
209 vbox->set_border_width (24);
211 hbox->pack_start (*default_dir_chooser, false, true, 8);
212 vbox->pack_start (*txt, false, false);
213 vbox->pack_start (*hbox, false, true);
215 cerr << "set default folder to " << poor_mans_glob (Config->get_default_session_parent_dir()) << endl;
216 default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
217 default_dir_chooser->signal_current_folder_changed().connect (sigc::mem_fun (*this, &ArdourStartup::default_dir_changed));
218 default_dir_chooser->show ();
222 default_folder_page_index = append_page (*vbox);
223 set_page_title (*vbox, _("Default folder for new sessions"));
224 set_page_header_image (*vbox, icon_pixbuf);
225 set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
227 /* user can just skip all these settings if they want to */
229 set_page_complete (*vbox, true);
233 ArdourStartup::setup_monitoring_choice_page ()
235 mon_vbox.set_spacing (18);
236 mon_vbox.set_border_width (24);
238 HBox* hbox = manage (new HBox);
239 VBox* vbox = manage (new VBox);
240 /* first button will be on by default */
241 RadioButton::Group g (monitor_via_ardour_button.get_group());
242 monitor_via_hardware_button.set_group (g);
244 monitor_label.set_markup(_("\
245 While recording instruments or vocals, you probably want to listen to the\n\
246 signal as well as record it. This is called \"monitoring\". There are\n\
247 different ways to do this depending on the equipment you have and the\n\
248 configuration of that equipment. The two most common are presented here.\n\
249 Please choose whichever one is right for your setup.\n\n\
250 <i>(You can change this preference at any time, via the Preferences dialog)</i>\n\n\
251 <i>If you do not understand what this is about, just accept the default.</i>"));
252 monitor_label.set_alignment (0.0, 0.0);
254 vbox->set_spacing (6);
256 vbox->pack_start (monitor_via_hardware_button, false, true);
257 vbox->pack_start (monitor_via_ardour_button, false, true);
258 hbox->pack_start (*vbox, true, true, 8);
259 mon_vbox.pack_start (monitor_label, false, false);
260 mon_vbox.pack_start (*hbox, false, false);
262 mon_vbox.show_all ();
264 monitoring_page_index = append_page (mon_vbox);
265 set_page_title (mon_vbox, _("Monitoring Choices"));
266 set_page_header_image (mon_vbox, icon_pixbuf);
268 /* user could just click on "Forward" if default
272 set_page_complete (mon_vbox, true);
276 ArdourStartup::setup_monitor_section_choice_page ()
278 mon_sec_vbox.set_spacing (18);
279 mon_sec_vbox.set_border_width (24);
281 HBox* hbox = manage (new HBox);
282 VBox* main_vbox = manage (new VBox);
284 Label* l = manage (new Label);
286 main_vbox->set_spacing (32);
288 no_monitor_section_button.set_label (_("Use a Master bus directly"));
289 l->set_alignment (0.0, 1.0);
290 l->set_markup(_("Connect the Master bus directly to your hardware outputs. This is preferable for simple usage."));
292 vbox = manage (new VBox);
293 vbox->set_spacing (6);
294 vbox->pack_start (no_monitor_section_button, false, true);
295 vbox->pack_start (*l, false, true);
297 main_vbox->pack_start (*vbox, false, false);
299 use_monitor_section_button.set_label (_("Use an additional Monitor bus"));
300 l = manage (new Label);
301 l->set_alignment (0.0, 1.0);
302 l->set_text (_("Use a Monitor bus between Master bus and hardware outputs for \n\
303 greater control in monitoring without affecting the mix."));
305 vbox = manage (new VBox);
306 vbox->set_spacing (6);
307 vbox->pack_start (use_monitor_section_button, false, true);
308 vbox->pack_start (*l, false, true);
310 main_vbox->pack_start (*vbox, false, false);
312 RadioButton::Group g (use_monitor_section_button.get_group());
313 no_monitor_section_button.set_group (g);
315 if (Config->get_use_monitor_bus()) {
316 use_monitor_section_button.set_active (true);
318 no_monitor_section_button.set_active (true);
321 use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
322 no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
324 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\
325 <i>If you do not understand what this is about, just accept the default.</i>"));
326 monitor_section_label.set_alignment (0.0, 0.0);
328 hbox->pack_start (*main_vbox, true, true, 8);
329 mon_sec_vbox.pack_start (*hbox, false, false);
330 mon_sec_vbox.pack_start (monitor_section_label, false, false);
332 mon_sec_vbox.show_all ();
334 monitor_section_page_index = append_page (mon_sec_vbox);
335 set_page_title (mon_sec_vbox, _("Monitor Section"));
336 set_page_header_image (mon_sec_vbox, icon_pixbuf);
338 /* user could just click on "Forward" if default
342 set_page_complete (mon_sec_vbox, true);
346 ArdourStartup::setup_final_page ()
348 string msg = string_compose (_("%1 is ready for use"), PROGRAM_NAME);
350 plugin_disco_button.signal_clicked().connect (sigc::mem_fun(*this, &ArdourStartup::discover_plugins));
351 plugin_disco_button.set_label (_("Scan for Plugins"));
352 plugin_disco_button.show ();
354 Gtk::Label* final_label = manage (new Label);
355 final_label->set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", msg));
356 final_label->show ();
358 VBox* vbox = manage (new VBox);
359 vbox->pack_start (*final_label, true, true);
360 vbox->pack_start (plugin_disco_button, true, false);
363 final_page_index = append_page (*vbox);
364 set_page_complete (*vbox, true);
365 set_page_header_image (*vbox, icon_pixbuf);
366 set_page_type (*vbox, ASSISTANT_PAGE_CONFIRM);
370 ArdourStartup::discover_plugins () {
371 plugin_disco_button.set_sensitive (false);
372 PluginManager::instance().refresh();
376 ArdourStartup::on_cancel ()
378 _response = RESPONSE_CANCEL;
383 ArdourStartup::on_delete_event (GdkEventAny*)
385 _response = RESPONSE_CLOSE;
391 ArdourStartup::on_apply ()
393 /* file-chooser button does not emit 'current_folder_changed' signal
394 * when a folder from the dropdown or the sidebar is chosen.
395 * -> explicitly poll for the dir as suggested by the gtk documentation.
397 if (default_dir_chooser && default_dir_chooser->get_filename() != Config->get_default_session_parent_dir ()) {
398 config_modified = true;
401 if (config_modified) {
403 if (default_dir_chooser) {
404 Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
407 if (monitor_via_hardware_button.get_active()) {
408 Config->set_monitoring_model (ExternalMonitoring);
409 } else if (monitor_via_ardour_button.get_active()) {
410 Config->set_monitoring_model (SoftwareMonitoring);
413 Config->set_use_monitor_bus (use_monitor_section_button.get_active());
415 Config->save_state ();
420 /* "touch" the been-here-before path now we've successfully
421 made it through the first time setup (at least)
423 PBD::ScopedFileDescriptor fout (g_open (been_here_before_path ().c_str(), O_CREAT|O_TRUNC|O_RDWR, 0666));
427 _response = RESPONSE_OK;
433 ArdourStartup::move_along_now ()