merge fix
[ardour.git] / gtk2_ardour / startup.cc
1 /*
2     Copyright (C) 2010 Paul Davis
3
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.
8
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.
13
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.
17
18 */
19
20 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #include "gtk2ardour-version.h"
23 #endif
24
25 #include <fstream>
26 #include <algorithm>
27
28 #include <gtkmm/main.h>
29 #include <gtkmm/filechooser.h>
30
31 #include "pbd/failed_constructor.h"
32 #include "pbd/file_utils.h"
33 #include "pbd/replace_all.h"
34 #include "pbd/whitespace.h"
35 #include "pbd/stacktrace.h"
36 #include "pbd/openuri.h"
37
38 #include "ardour/audioengine.h"
39 #include "ardour/filesystem_paths.h"
40 #include "ardour/filename_extensions.h"
41 #include "ardour/plugin_manager.h"
42 #include "ardour/recent_sessions.h"
43 #include "ardour/session.h"
44 #include "ardour/session_state_utils.h"
45 #include "ardour/template_utils.h"
46
47 #include "ardour_ui.h"
48 #include "startup.h"
49 #include "opts.h"
50 #include "engine_dialog.h"
51 #include "i18n.h"
52 #include "utils.h"
53
54 using namespace std;
55 using namespace Gtk;
56 using namespace Gdk;
57 using namespace Glib;
58 using namespace PBD;
59 using namespace ARDOUR;
60 using namespace ARDOUR_UI_UTILS;
61
62 ArdourStartup* ArdourStartup::the_startup = 0;
63
64 ArdourStartup::ArdourStartup ()
65         : _response (RESPONSE_OK)
66         , config_modified (false)
67         , default_dir_chooser (0)
68         , monitor_via_hardware_button (string_compose (_("Use an external mixer or the hardware mixer of your audio interface.\n"
69                                                          "%1 will play NO role in monitoring"), PROGRAM_NAME))
70         , monitor_via_ardour_button (string_compose (_("Ask %1 to play back material as it is being recorded"), PROGRAM_NAME))
71         , audio_page_index (-1)
72         , new_user_page_index (-1)
73         , default_folder_page_index (-1)
74         , monitoring_page_index (-1)
75         , final_page_index (-1)
76 {
77         set_position (WIN_POS_CENTER);
78         set_border_width (12);
79         
80         if ((icon_pixbuf = ::get_icon ("ardour_icon_48px")) == 0) {
81                 throw failed_constructor();
82         }
83         
84         list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
85         Glib::RefPtr<Gdk::Pixbuf> icon;
86         
87         if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
88                 window_icons.push_back (icon);
89         }
90         if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
91                 window_icons.push_back (icon);
92         }
93         if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
94                 window_icons.push_back (icon);
95         }
96         if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
97                 window_icons.push_back (icon);
98         }
99         if (!window_icons.empty ()) {
100                 set_default_icon_list (window_icons);
101         }
102         
103         setup_new_user_page ();
104         setup_first_time_config_page ();
105         setup_monitoring_choice_page ();
106         setup_monitor_section_choice_page ();
107         setup_final_page ();
108
109         the_startup = this;
110 }
111
112 ArdourStartup::~ArdourStartup ()
113 {
114 }
115
116 bool
117 ArdourStartup::required ()
118 {
119         /* look for a "been here before" file for this version or earlier
120          * versions
121          */
122
123         const int current_version = atoi (PROGRAM_VERSION);
124         
125         for (int v = current_version; v != 0; --v) {
126                 if (Glib::file_test (ARDOUR::been_here_before_path (v), Glib::FILE_TEST_EXISTS)) {
127                         if (v != current_version) {
128                                 /* older version exists, create the current one */
129                                 ofstream fout (been_here_before_path (current_version).c_str());
130                         }
131                         return false;
132                 }
133         }
134
135         return true;
136 }
137
138 void
139 ArdourStartup::setup_new_user_page ()
140 {
141         Label* foomatic = manage (new Label);
142
143         foomatic->set_markup (string_compose (_("\
144 <span size=\"larger\">%1 is a digital audio workstation. You can use it to \
145 record, edit and mix multi-track audio. You can produce your \
146 own CDs, mix video soundtracks, or experiment with new \
147 ideas about music and sound. \
148 \n\n\
149 There are a few things that need to be configured before you start \
150 using the program.</span> \
151 "), PROGRAM_NAME));
152         foomatic->set_justify (JUSTIFY_FILL);
153         foomatic->set_line_wrap ();
154
155         HBox* hbox = manage (new HBox);
156         HBox* vbox = manage (new HBox);
157
158         vbox->set_border_width (24);
159
160         hbox->pack_start (*foomatic, true, true);
161         vbox->pack_start (*hbox, true, true);
162
163         foomatic->show ();
164         hbox->show ();
165         vbox->show ();
166
167         new_user_page_index = append_page (*vbox);
168         set_page_type (*vbox, ASSISTANT_PAGE_INTRO);
169         set_page_title (*vbox, string_compose (_("Welcome to %1"), PROGRAM_NAME));
170         set_page_header_image (*vbox, icon_pixbuf);
171         set_page_complete (*vbox, true);
172 }
173
174 void
175 ArdourStartup::default_dir_changed ()
176 {
177         Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
178         // make new session folder chooser point to the new default
179         new_folder_chooser.set_current_folder (Config->get_default_session_parent_dir());       
180         config_changed ();
181 }
182
183 void
184 ArdourStartup::config_changed ()
185 {
186         config_modified = true;
187 }
188
189 void
190 ArdourStartup::setup_first_time_config_page ()
191 {
192         default_dir_chooser = manage (new FileChooserButton (string_compose (_("Default folder for %1 sessions"), PROGRAM_NAME),
193                                                              FILE_CHOOSER_ACTION_SELECT_FOLDER));
194         Gtk::Label* txt = manage (new Label);
195         HBox* hbox = manage (new HBox);
196         VBox* vbox = manage (new VBox);
197
198         txt->set_markup (string_compose (_("\
199 Each project that you work on with %1 has its own folder.\n\
200 These can require a lot of disk space if you are recording audio.\n\
201 \n\
202 Where would you like new %1 sessions to be stored by default?\n\n\
203 <i>(You can put new sessions anywhere, this is just a default)</i>"), PROGRAM_NAME));
204         txt->set_alignment (0.0, 0.0);
205
206         vbox->set_spacing (18);
207         vbox->set_border_width (24);
208
209         hbox->pack_start (*default_dir_chooser, false, true, 8);
210         vbox->pack_start (*txt, false, false);
211         vbox->pack_start (*hbox, false, true);
212
213         cerr << "set default folder to " << poor_mans_glob (Config->get_default_session_parent_dir()) << endl;
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 ();
217
218         vbox->show_all ();
219
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);
224
225         /* user can just skip all these settings if they want to */
226
227         set_page_complete (*vbox, true);
228 }
229
230 void
231 ArdourStartup::setup_monitoring_choice_page ()
232 {
233         mon_vbox.set_spacing (18);
234         mon_vbox.set_border_width (24);
235
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);
241
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);
251
252         vbox->set_spacing (6);
253
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);
259
260         mon_vbox.show_all ();
261
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);
265
266         /* user could just click on "Forward" if default
267          * choice is correct.
268          */
269
270         set_page_complete (mon_vbox, true);
271 }
272
273 void
274 ArdourStartup::setup_monitor_section_choice_page ()
275 {
276         mon_sec_vbox.set_spacing (18);
277         mon_sec_vbox.set_border_width (24);
278
279         HBox* hbox = manage (new HBox);
280         VBox* main_vbox = manage (new VBox);
281         VBox* vbox;
282         Label* l = manage (new Label);
283
284         main_vbox->set_spacing (32);
285
286         no_monitor_section_button.set_label (_("Use a Master bus directly"));
287         l->set_alignment (0.0, 1.0);
288         l->set_markup(_("Connect the Master bus directly to your hardware outputs. This is preferable for simple usage."));
289
290         vbox = manage (new VBox);
291         vbox->set_spacing (6);
292         vbox->pack_start (no_monitor_section_button, false, true);
293         vbox->pack_start (*l, false, true);
294
295         main_vbox->pack_start (*vbox, false, false);
296
297         use_monitor_section_button.set_label (_("Use an additional Monitor bus"));
298         l = manage (new Label);
299         l->set_alignment (0.0, 1.0);
300         l->set_text (_("Use a Monitor bus between Master bus and hardware outputs for \n\
301 greater control in monitoring without affecting the mix."));
302
303         vbox = manage (new VBox);
304         vbox->set_spacing (6);
305         vbox->pack_start (use_monitor_section_button, false, true);
306         vbox->pack_start (*l, false, true);
307
308         main_vbox->pack_start (*vbox, false, false);
309
310         RadioButton::Group g (use_monitor_section_button.get_group());
311         no_monitor_section_button.set_group (g);
312
313         if (Config->get_use_monitor_bus()) {
314                 use_monitor_section_button.set_active (true);
315         } else {
316                 no_monitor_section_button.set_active (true);
317         }
318
319         use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
320         no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
321
322         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\
323 <i>If you do not understand what this is about, just accept the default.</i>"));
324         monitor_section_label.set_alignment (0.0, 0.0);
325
326         hbox->pack_start (*main_vbox, true, true, 8);
327         mon_sec_vbox.pack_start (*hbox, false, false);
328         mon_sec_vbox.pack_start (monitor_section_label, false, false);
329
330         mon_sec_vbox.show_all ();
331
332         monitor_section_page_index = append_page (mon_sec_vbox);
333         set_page_title (mon_sec_vbox, _("Monitor Section"));
334         set_page_header_image (mon_sec_vbox, icon_pixbuf);
335
336         /* user could just click on "Forward" if default
337          * choice is correct.
338          */
339
340         set_page_complete (mon_sec_vbox, true);
341 }
342
343 void
344 ArdourStartup::setup_final_page ()
345 {
346         string msg = string_compose (_("%1 is ready for use"), PROGRAM_NAME);
347
348         plugin_disco_button.signal_clicked().connect (sigc::mem_fun(*this, &ArdourStartup::discover_plugins));
349         plugin_disco_button.set_label (_("Scan for Plugins"));
350         plugin_disco_button.show ();
351
352         Gtk::Label* final_label = manage (new Label);
353         final_label->set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", msg));
354         final_label->show ();
355
356         VBox* vbox = manage (new VBox);
357         vbox->pack_start (*final_label, true, true);
358         vbox->pack_start (plugin_disco_button, true, false);
359         vbox->show ();
360
361         final_page_index = append_page (*vbox);
362         set_page_complete (*vbox, true);
363         set_page_header_image (*vbox, icon_pixbuf);
364         set_page_type (*vbox, ASSISTANT_PAGE_CONFIRM);
365 }
366
367 void
368 ArdourStartup::discover_plugins () {
369         plugin_disco_button.set_sensitive (false);
370         PluginManager::instance().refresh();
371 }
372
373 void
374 ArdourStartup::on_cancel ()
375 {
376         _response = RESPONSE_CANCEL;
377         gtk_main_quit ();
378 }
379
380 bool
381 ArdourStartup::on_delete_event (GdkEventAny*)
382 {
383         _response = RESPONSE_CLOSE;
384         gtk_main_quit ();
385         return true;
386 }
387
388 void
389 ArdourStartup::on_apply ()
390 {
391         /* file-chooser button does not emit 'current_folder_changed' signal
392          * when a folder from the dropdown or the sidebar is chosen.
393          * -> explicitly poll for the dir as suggested by the gtk documentation.
394          */
395         if (default_dir_chooser && default_dir_chooser->get_filename() != Config->get_default_session_parent_dir ()) {
396                 config_modified = true;
397         }
398
399         if (config_modified) {
400
401                 if (default_dir_chooser) {
402                         Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
403                 }
404
405                 if (monitor_via_hardware_button.get_active()) {
406                         Config->set_monitoring_model (ExternalMonitoring);
407                 } else if (monitor_via_ardour_button.get_active()) {
408                         Config->set_monitoring_model (SoftwareMonitoring);
409                 }
410
411                 Config->set_use_monitor_bus (use_monitor_section_button.get_active());
412
413                 Config->save_state ();
414
415         }
416
417         {
418                 /* "touch" the been-here-before path now we've successfully
419                    made it through the first time setup (at least)
420                 */
421                 ofstream fout (been_here_before_path().c_str());
422
423         }
424                 
425         _response = RESPONSE_OK;
426         gtk_main_quit ();
427 }
428
429
430 void
431 ArdourStartup::move_along_now ()
432 {
433         on_apply ();
434 }