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