Merge remote-tracking branch 'origin/master' into export-dialog
[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 #endif
23
24 #include <fstream>
25 #include <algorithm>
26
27 #include <gtkmm/main.h>
28 #include <gtkmm/filechooser.h>
29
30 #include "pbd/failed_constructor.h"
31 #include "pbd/file_utils.h"
32 #include "pbd/replace_all.h"
33 #include "pbd/whitespace.h"
34 #include "pbd/stacktrace.h"
35 #include "pbd/openuri.h"
36
37 #include "ardour/audioengine.h"
38 #include "ardour/filesystem_paths.h"
39 #include "ardour/recent_sessions.h"
40 #include "ardour/session.h"
41 #include "ardour/session_state_utils.h"
42 #include "ardour/template_utils.h"
43 #include "ardour/filename_extensions.h"
44
45 #include "ardour_ui.h"
46 #include "startup.h"
47 #include "opts.h"
48 #include "engine_dialog.h"
49 #include "i18n.h"
50 #include "utils.h"
51
52 using namespace std;
53 using namespace Gtk;
54 using namespace Gdk;
55 using namespace Glib;
56 using namespace PBD;
57 using namespace ARDOUR;
58
59 ArdourStartup* ArdourStartup::the_startup = 0;
60
61 static string poor_mans_glob (string path)
62 {
63         string copy = path;
64         replace_all (copy, "~", Glib::get_home_dir());
65         return copy;
66 }
67
68 ArdourStartup::ArdourStartup ()
69         : _response (RESPONSE_OK)
70         , config_modified (false)
71         , default_dir_chooser (0)
72         , monitor_via_hardware_button (string_compose (_("Use an external mixer or the hardware mixer of your audio interface.\n"
73                                                          "%1 will play NO role in monitoring"), PROGRAM_NAME))
74         , monitor_via_ardour_button (string_compose (_("Ask %1 to play back material as it is being recorded"), PROGRAM_NAME))
75         , audio_page_index (-1)
76         , new_user_page_index (-1)
77         , default_folder_page_index (-1)
78         , monitoring_page_index (-1)
79         , final_page_index (-1)
80 {
81         set_keep_above (true);
82         set_position (WIN_POS_CENTER);
83         set_border_width (12);
84         
85         if ((icon_pixbuf = ::get_icon ("ardour_icon_48px")) == 0) {
86                 throw failed_constructor();
87         }
88         
89         list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
90         Glib::RefPtr<Gdk::Pixbuf> icon;
91         
92         if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
93                 window_icons.push_back (icon);
94         }
95         if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
96                 window_icons.push_back (icon);
97         }
98         if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
99                 window_icons.push_back (icon);
100         }
101         if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
102                 window_icons.push_back (icon);
103         }
104         if (!window_icons.empty ()) {
105                 set_default_icon_list (window_icons);
106         }
107         
108 #ifdef __APPLE__
109         setup_prerelease_page ();
110 #endif
111         
112         setup_new_user_page ();
113         setup_first_time_config_page ();
114         setup_monitoring_choice_page ();
115         setup_monitor_section_choice_page ();
116         setup_final_page ();
117
118         the_startup = this;
119 }
120
121 ArdourStartup::~ArdourStartup ()
122 {
123 }
124
125 bool
126 ArdourStartup::required ()
127 {
128         return !Glib::file_test (been_here_before_path(), Glib::FILE_TEST_EXISTS);
129 }
130
131 std::string
132 ArdourStartup::been_here_before_path ()
133 {
134         // XXXX use more specific version so we can catch upgrades
135         return Glib::build_filename (user_config_directory (), ".a3");
136 }
137
138 void
139 ArdourStartup::setup_prerelease_page ()
140 {
141         VBox* vbox = manage (new VBox);
142         Label* label = manage (new Label);
143         label->set_markup (string_compose (_("<b>Welcome to this BETA release of Ardour %1</b>\n\n\
144 Ardour %1 has been released for Linux but because of the lack of testers,\n\
145 it is still at the beta stage on OS X. So, a few guidelines:\n\
146 \n\
147 1) Please do <b>NOT</b> use this software with the expectation that it is stable or reliable\n\
148    though it may be so, depending on your workflow.\n\
149 2) <b>Please do NOT use the forums at ardour.org to report issues</b>.\n\
150 3) Please <b>DO</b> use the bugtracker at http://tracker.ardour.org/ to report issues\n\
151    making sure to note the product version number as %1-beta.\n\
152 4) Please <b>DO</b> use the ardour-users mailing list to discuss ideas and pass on comments.\n\
153 5) Please <b>DO</b> join us on IRC for real time discussions about ardour3. You\n\
154    can get there directly from Ardour via the Help->Chat menu option.\n\
155 \n\
156 Full information on all the above can be found on the support page at\n\
157 \n\
158                 http://ardour.org/support\n\
159 "), VERSIONSTRING));
160
161         vbox->set_border_width (12);
162         vbox->pack_start (*label, false, false, 12);
163         vbox->show_all ();
164         
165         append_page (*vbox);
166         set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
167         set_page_title (*vbox, _("This is a BETA RELEASE"));
168         set_page_complete (*vbox, true);
169 }
170
171 void
172 ArdourStartup::setup_new_user_page ()
173 {
174         Label* foomatic = manage (new Label);
175
176         foomatic->set_markup (string_compose (_("\
177 <span size=\"larger\">%1 is a digital audio workstation. You can use it to \
178 record, edit and mix multi-track audio. You can produce your \
179 own CDs, mix video soundtracks, or experiment with new \
180 ideas about music and sound. \
181 \n\n\
182 There are a few things that need to be configured before you start \
183 using the program.</span> \
184 "), PROGRAM_NAME));
185         foomatic->set_justify (JUSTIFY_FILL);
186         foomatic->set_line_wrap ();
187
188         HBox* hbox = manage (new HBox);
189         HBox* vbox = manage (new HBox);
190
191         vbox->set_border_width (24);
192
193         hbox->pack_start (*foomatic, true, true);
194         vbox->pack_start (*hbox, true, true);
195
196         foomatic->show ();
197         hbox->show ();
198         vbox->show ();
199
200         new_user_page_index = append_page (*vbox);
201         set_page_type (*vbox, ASSISTANT_PAGE_INTRO);
202         set_page_title (*vbox, string_compose (_("Welcome to %1"), PROGRAM_NAME));
203         set_page_header_image (*vbox, icon_pixbuf);
204         set_page_complete (*vbox, true);
205 }
206
207 void
208 ArdourStartup::default_dir_changed ()
209 {
210         Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
211         // make new session folder chooser point to the new default
212         new_folder_chooser.set_current_folder (Config->get_default_session_parent_dir());       
213         config_changed ();
214 }
215
216 void
217 ArdourStartup::config_changed ()
218 {
219         config_modified = true;
220 }
221
222 void
223 ArdourStartup::setup_first_time_config_page ()
224 {
225         default_dir_chooser = manage (new FileChooserButton (string_compose (_("Default folder for %1 sessions"), PROGRAM_NAME),
226                                                              FILE_CHOOSER_ACTION_SELECT_FOLDER));
227         Gtk::Label* txt = manage (new Label);
228         HBox* hbox = manage (new HBox);
229         VBox* vbox = manage (new VBox);
230
231         txt->set_markup (string_compose (_("\
232 Each project that you work on with %1 has its own folder.\n\
233 These can require a lot of disk space if you are recording audio.\n\
234 \n\
235 Where would you like new %1 sessions to be stored by default?\n\n\
236 <i>(You can put new sessions anywhere, this is just a default)</i>"), PROGRAM_NAME));
237         txt->set_alignment (0.0, 0.0);
238
239         vbox->set_spacing (18);
240         vbox->set_border_width (24);
241
242         hbox->pack_start (*default_dir_chooser, false, true, 8);
243         vbox->pack_start (*txt, false, false);
244         vbox->pack_start (*hbox, false, true);
245
246         cerr << "set default folder to " << poor_mans_glob (Config->get_default_session_parent_dir()) << endl;
247         default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
248         default_dir_chooser->signal_current_folder_changed().connect (sigc::mem_fun (*this, &ArdourStartup::default_dir_changed));
249         default_dir_chooser->show ();
250
251         vbox->show_all ();
252
253         default_folder_page_index = append_page (*vbox);
254         set_page_title (*vbox, _("Default folder for new sessions"));
255         set_page_header_image (*vbox, icon_pixbuf);
256         set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
257
258         /* user can just skip all these settings if they want to */
259
260         set_page_complete (*vbox, true);
261 }
262
263 void
264 ArdourStartup::setup_monitoring_choice_page ()
265 {
266         mon_vbox.set_spacing (18);
267         mon_vbox.set_border_width (24);
268
269         HBox* hbox = manage (new HBox);
270         VBox* vbox = manage (new VBox);
271         /* first button will be on by default */
272         RadioButton::Group g (monitor_via_ardour_button.get_group());
273         monitor_via_hardware_button.set_group (g);
274
275         monitor_label.set_markup(_("\
276 While recording instruments or vocals, you probably want to listen to the\n\
277 signal as well as record it. This is called \"monitoring\". There are\n\
278 different ways to do this depending on the equipment you have and the\n\
279 configuration of that equipment. The two most common are presented here.\n\
280 Please choose whichever one is right for your setup.\n\n\
281 <i>(You can change this preference at any time, via the Preferences dialog)</i>\n\n\
282 <i>If you do not understand what this is about, just accept the default.</i>"));
283         monitor_label.set_alignment (0.0, 0.0);
284
285         vbox->set_spacing (6);
286
287         vbox->pack_start (monitor_via_hardware_button, false, true);
288         vbox->pack_start (monitor_via_ardour_button, false, true);
289         hbox->pack_start (*vbox, true, true, 8);
290         mon_vbox.pack_start (monitor_label, false, false);
291         mon_vbox.pack_start (*hbox, false, false);
292
293         mon_vbox.show_all ();
294
295         monitoring_page_index = append_page (mon_vbox);
296         set_page_title (mon_vbox, _("Monitoring Choices"));
297         set_page_header_image (mon_vbox, icon_pixbuf);
298
299         /* user could just click on "Forward" if default
300          * choice is correct.
301          */
302
303         set_page_complete (mon_vbox, true);
304 }
305
306 void
307 ArdourStartup::setup_monitor_section_choice_page ()
308 {
309         mon_sec_vbox.set_spacing (18);
310         mon_sec_vbox.set_border_width (24);
311
312         HBox* hbox = manage (new HBox);
313         VBox* main_vbox = manage (new VBox);
314         VBox* vbox;
315         Label* l = manage (new Label);
316
317         main_vbox->set_spacing (32);
318
319         no_monitor_section_button.set_label (_("Use a Master bus directly"));
320         l->set_alignment (0.0, 1.0);
321         l->set_markup(_("Connect the Master bus directly to your hardware outputs. This is preferable for simple usage."));
322
323         vbox = manage (new VBox);
324         vbox->set_spacing (6);
325         vbox->pack_start (no_monitor_section_button, false, true);
326         vbox->pack_start (*l, false, true);
327
328         main_vbox->pack_start (*vbox, false, false);
329
330         use_monitor_section_button.set_label (_("Use an additional Monitor bus"));
331         l = manage (new Label);
332         l->set_alignment (0.0, 1.0);
333         l->set_text (_("Use a Monitor bus between Master bus and hardware outputs for \n\
334 greater control in monitoring without affecting the mix."));
335
336         vbox = manage (new VBox);
337         vbox->set_spacing (6);
338         vbox->pack_start (use_monitor_section_button, false, true);
339         vbox->pack_start (*l, false, true);
340
341         main_vbox->pack_start (*vbox, false, false);
342
343         RadioButton::Group g (use_monitor_section_button.get_group());
344         no_monitor_section_button.set_group (g);
345
346         if (Config->get_use_monitor_bus()) {
347                 use_monitor_section_button.set_active (true);
348         } else {
349                 no_monitor_section_button.set_active (true);
350         }
351
352         use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
353         no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
354
355         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\
356 <i>If you do not understand what this is about, just accept the default.</i>"));
357         monitor_section_label.set_alignment (0.0, 0.0);
358
359         hbox->pack_start (*main_vbox, true, true, 8);
360         mon_sec_vbox.pack_start (*hbox, false, false);
361         mon_sec_vbox.pack_start (monitor_section_label, false, false);
362
363         mon_sec_vbox.show_all ();
364
365         monitor_section_page_index = append_page (mon_sec_vbox);
366         set_page_title (mon_sec_vbox, _("Monitor Section"));
367         set_page_header_image (mon_sec_vbox, icon_pixbuf);
368
369         /* user could just click on "Forward" if default
370          * choice is correct.
371          */
372
373         set_page_complete (mon_sec_vbox, true);
374 }
375
376 void
377 ArdourStartup::setup_final_page ()
378 {
379         string msg = string_compose (_("%1 is ready for use"), PROGRAM_NAME);
380         
381         final_page.set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", msg));
382         final_page.show ();
383         final_page_index = append_page (final_page);
384         set_page_complete (final_page, true);
385         set_page_header_image (final_page, icon_pixbuf);
386         set_page_type (final_page, ASSISTANT_PAGE_CONFIRM);
387 }
388
389 void
390 ArdourStartup::on_cancel ()
391 {
392         _response = RESPONSE_CANCEL;
393         gtk_main_quit ();
394 }
395
396 bool
397 ArdourStartup::on_delete_event (GdkEventAny*)
398 {
399         _response = RESPONSE_CLOSE;
400         gtk_main_quit ();
401         return true;
402 }
403
404 void
405 ArdourStartup::on_apply ()
406 {
407         if (config_modified) {
408
409                 if (default_dir_chooser) {
410                         Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
411                 }
412
413                 if (monitor_via_hardware_button.get_active()) {
414                         Config->set_monitoring_model (ExternalMonitoring);
415                 } else if (monitor_via_ardour_button.get_active()) {
416                         Config->set_monitoring_model (SoftwareMonitoring);
417                 }
418
419                 Config->set_use_monitor_bus (use_monitor_section_button.get_active());
420
421                 Config->save_state ();
422
423         }
424
425         {
426                 /* "touch" the been-here-before path now we've successfully
427                    made it through the first time setup (at least)
428                 */
429                 ofstream fout (been_here_before_path().c_str());
430
431         }
432                 
433         _response = RESPONSE_OK;
434         gtk_main_quit ();
435 }
436
437
438 void
439 ArdourStartup::move_along_now ()
440 {
441         on_apply ();
442 }
443
444
445