Merge branch 'master' into windows+cc
[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         default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
247         default_dir_chooser->signal_current_folder_changed().connect (sigc::mem_fun (*this, &ArdourStartup::default_dir_changed));
248         default_dir_chooser->show ();
249
250         vbox->show_all ();
251
252         default_folder_page_index = append_page (*vbox);
253         set_page_title (*vbox, _("Default folder for new sessions"));
254         set_page_header_image (*vbox, icon_pixbuf);
255         set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
256
257         /* user can just skip all these settings if they want to */
258
259         set_page_complete (*vbox, true);
260 }
261
262 void
263 ArdourStartup::setup_monitoring_choice_page ()
264 {
265         mon_vbox.set_spacing (18);
266         mon_vbox.set_border_width (24);
267
268         HBox* hbox = manage (new HBox);
269         VBox* vbox = manage (new VBox);
270         /* first button will be on by default */
271         RadioButton::Group g (monitor_via_ardour_button.get_group());
272         monitor_via_hardware_button.set_group (g);
273
274         monitor_label.set_markup(_("\
275 While recording instruments or vocals, you probably want to listen to the\n\
276 signal as well as record it. This is called \"monitoring\". There are\n\
277 different ways to do this depending on the equipment you have and the\n\
278 configuration of that equipment. The two most common are presented here.\n\
279 Please choose whichever one is right for your setup.\n\n\
280 <i>(You can change this preference at any time, via the Preferences dialog)</i>\n\n\
281 <i>If you do not understand what this is about, just accept the default.</i>"));
282         monitor_label.set_alignment (0.0, 0.0);
283
284         vbox->set_spacing (6);
285
286         vbox->pack_start (monitor_via_hardware_button, false, true);
287         vbox->pack_start (monitor_via_ardour_button, false, true);
288         hbox->pack_start (*vbox, true, true, 8);
289         mon_vbox.pack_start (monitor_label, false, false);
290         mon_vbox.pack_start (*hbox, false, false);
291
292         mon_vbox.show_all ();
293
294         monitoring_page_index = append_page (mon_vbox);
295         set_page_title (mon_vbox, _("Monitoring Choices"));
296         set_page_header_image (mon_vbox, icon_pixbuf);
297
298         /* user could just click on "Forward" if default
299          * choice is correct.
300          */
301
302         set_page_complete (mon_vbox, true);
303 }
304
305 void
306 ArdourStartup::setup_monitor_section_choice_page ()
307 {
308         mon_sec_vbox.set_spacing (18);
309         mon_sec_vbox.set_border_width (24);
310
311         HBox* hbox = manage (new HBox);
312         VBox* main_vbox = manage (new VBox);
313         VBox* vbox;
314         Label* l = manage (new Label);
315
316         main_vbox->set_spacing (32);
317
318         no_monitor_section_button.set_label (_("Use a Master bus directly"));
319         l->set_alignment (0.0, 1.0);
320         l->set_markup(_("Connect the Master bus directly to your hardware outputs. This is preferable for simple usage."));
321
322         vbox = manage (new VBox);
323         vbox->set_spacing (6);
324         vbox->pack_start (no_monitor_section_button, false, true);
325         vbox->pack_start (*l, false, true);
326
327         main_vbox->pack_start (*vbox, false, false);
328
329         use_monitor_section_button.set_label (_("Use an additional Monitor bus"));
330         l = manage (new Label);
331         l->set_alignment (0.0, 1.0);
332         l->set_text (_("Use a Monitor bus between Master bus and hardware outputs for \n\
333 greater control in monitoring without affecting the mix."));
334
335         vbox = manage (new VBox);
336         vbox->set_spacing (6);
337         vbox->pack_start (use_monitor_section_button, false, true);
338         vbox->pack_start (*l, false, true);
339
340         main_vbox->pack_start (*vbox, false, false);
341
342         RadioButton::Group g (use_monitor_section_button.get_group());
343         no_monitor_section_button.set_group (g);
344
345         if (Config->get_use_monitor_bus()) {
346                 use_monitor_section_button.set_active (true);
347         } else {
348                 no_monitor_section_button.set_active (true);
349         }
350
351         use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
352         no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
353
354         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\
355 <i>If you do not understand what this is about, just accept the default.</i>"));
356         monitor_section_label.set_alignment (0.0, 0.0);
357
358         hbox->pack_start (*main_vbox, true, true, 8);
359         mon_sec_vbox.pack_start (*hbox, false, false);
360         mon_sec_vbox.pack_start (monitor_section_label, false, false);
361
362         mon_sec_vbox.show_all ();
363
364         monitor_section_page_index = append_page (mon_sec_vbox);
365         set_page_title (mon_sec_vbox, _("Monitor Section"));
366         set_page_header_image (mon_sec_vbox, icon_pixbuf);
367
368         /* user could just click on "Forward" if default
369          * choice is correct.
370          */
371
372         set_page_complete (mon_sec_vbox, true);
373 }
374
375 void
376 ArdourStartup::setup_final_page ()
377 {
378         string msg = string_compose (_("%1 is ready for use"), PROGRAM_NAME);
379         
380         final_page.set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", msg));
381         final_page.show ();
382         final_page_index = append_page (final_page);
383         set_page_complete (final_page, true);
384         set_page_header_image (final_page, icon_pixbuf);
385         set_page_type (final_page, ASSISTANT_PAGE_CONFIRM);
386 }
387
388 void
389 ArdourStartup::on_cancel ()
390 {
391         _response = RESPONSE_CANCEL;
392         gtk_main_quit ();
393 }
394
395 bool
396 ArdourStartup::on_delete_event (GdkEventAny*)
397 {
398         _response = RESPONSE_CLOSE;
399         gtk_main_quit ();
400         return true;
401 }
402
403 void
404 ArdourStartup::on_apply ()
405 {
406         if (config_modified) {
407
408                 if (default_dir_chooser) {
409                         Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
410                 }
411
412                 if (monitor_via_hardware_button.get_active()) {
413                         Config->set_monitoring_model (ExternalMonitoring);
414                 } else if (monitor_via_ardour_button.get_active()) {
415                         Config->set_monitoring_model (SoftwareMonitoring);
416                 }
417
418                 Config->set_use_monitor_bus (use_monitor_section_button.get_active());
419
420                 Config->save_state ();
421
422         }
423
424         {
425                 /* "touch" the been-here-before path now we've successfully
426                    made it through the first time setup (at least)
427                 */
428                 ofstream fout (been_here_before_path().c_str());
429
430         }
431                 
432         _response = RESPONSE_OK;
433         gtk_main_quit ();
434 }
435
436
437 void
438 ArdourStartup::move_along_now ()
439 {
440         on_apply ();
441 }
442
443
444