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