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