Monitor new signal to rebuild sendlist
[ardour.git] / gtk2_ardour / startup.cc
1 /*
2  * Copyright (C) 2009-2011 David Robillard <d@drobilla.net>
3  * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
4  * Copyright (C) 2009-2016 Paul Davis <paul@linuxaudiosystems.com>
5  * Copyright (C) 2012-2015 Tim Mayberry <mojofunk@gmail.com>
6  * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
7  * Copyright (C) 2013 Colin Fletcher <colin.m.fletcher@googlemail.com>
8  * Copyright (C) 2013 Michael R. Fisher <mfisher@bketech.com>
9  * Copyright (C) 2015 John Emmas <john@creativepost.co.uk>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #ifdef WAF_BUILD
27 #include "gtk2ardour-config.h"
28 #include "gtk2ardour-version.h"
29 #endif
30
31 #include <algorithm>
32 #include <fcntl.h>
33
34 #include "pbd/gstdio_compat.h"
35
36 #include <gtkmm/main.h>
37 #include <gtkmm/filechooser.h>
38
39 #include "pbd/failed_constructor.h"
40 #include "pbd/scoped_file_descriptor.h"
41 #include "pbd/file_utils.h"
42 #include "pbd/replace_all.h"
43 #include "pbd/whitespace.h"
44 #include "pbd/stacktrace.h"
45 #include "pbd/openuri.h"
46
47 #include "ardour/audioengine.h"
48 #include "ardour/filesystem_paths.h"
49 #include "ardour/filename_extensions.h"
50 #include "ardour/plugin_manager.h"
51 #include "ardour/recent_sessions.h"
52 #include "ardour/session.h"
53 #include "ardour/session_state_utils.h"
54 #include "ardour/template_utils.h"
55 #include "ardour/profile.h"
56
57 #include "gtkmm2ext/utils.h"
58
59 #include "startup.h"
60 #include "opts.h"
61 #include "engine_dialog.h"
62 #include "pbd/i18n.h"
63 #include "utils.h"
64
65 using namespace std;
66 using namespace Gtk;
67 using namespace Gdk;
68 using namespace Glib;
69 using namespace PBD;
70 using namespace ARDOUR;
71 using namespace ARDOUR_UI_UTILS;
72
73 ArdourStartup* ArdourStartup::the_startup = 0;
74
75 ArdourStartup::ArdourStartup ()
76         : _response (RESPONSE_OK)
77         , config_modified (false)
78         , default_dir_chooser (0)
79         , monitor_via_hardware_button (string_compose (_("Use an external mixer or the hardware mixer of your audio interface.\n"
80                                                          "%1 will play NO role in monitoring"), PROGRAM_NAME))
81         , monitor_via_ardour_button (string_compose (_("Ask %1 to play back material as it is being recorded"), PROGRAM_NAME))
82         , audio_page_index (-1)
83         , new_user_page_index (-1)
84         , default_folder_page_index (-1)
85         , monitoring_page_index (-1)
86         , final_page_index (-1)
87 {
88         set_position (WIN_POS_CENTER);
89         set_border_width (12);
90
91         if (! (icon_pixbuf = ::get_icon (PROGRAM_NAME "-icon_48px"))) {
92                 throw failed_constructor();
93         }
94
95         list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
96         Glib::RefPtr<Gdk::Pixbuf> icon;
97
98         if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px"))) {
99                 window_icons.push_back (icon);
100         }
101         if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px"))) {
102                 window_icons.push_back (icon);
103         }
104         if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px"))) {
105                 window_icons.push_back (icon);
106         }
107         if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px"))) {
108                 window_icons.push_back (icon);
109         }
110         if (!window_icons.empty ()) {
111                 set_default_icon_list (window_icons);
112         }
113
114         setup_new_user_page ();
115         setup_first_time_config_page ();
116         setup_monitoring_choice_page ();
117         setup_monitor_section_choice_page ();
118         setup_final_page ();
119
120         the_startup = this;
121 }
122
123 ArdourStartup::~ArdourStartup ()
124 {
125 }
126
127 bool
128 ArdourStartup::required ()
129 {
130         if (Glib::file_test (ARDOUR::been_here_before_path (), Glib::FILE_TEST_EXISTS)) {
131                 return false;
132         }
133
134         return true;
135 }
136
137 void
138 ArdourStartup::setup_new_user_page ()
139 {
140         Label* foomatic = manage (new Label);
141
142         foomatic->set_markup (string_compose (_("\
143 <span size=\"larger\">%1 is a digital audio workstation. You can use it to \
144 record, edit and mix multi-track audio. You can produce your \
145 own CDs, mix video soundtracks, or experiment with new \
146 ideas about music and sound. \
147 \n\n\
148 There are a few things that need to be configured before you start \
149 using the program.</span> \
150 "), PROGRAM_NAME));
151         foomatic->set_justify (JUSTIFY_FILL);
152         foomatic->set_line_wrap ();
153
154         HBox* hbox = manage (new HBox);
155         HBox* vbox = manage (new HBox);
156
157         vbox->set_border_width (24);
158
159         hbox->pack_start (*foomatic, true, true);
160         vbox->pack_start (*hbox, true, true);
161
162         foomatic->show ();
163         hbox->show ();
164         vbox->show ();
165
166         new_user_page_index = append_page (*vbox);
167         set_page_type (*vbox, ASSISTANT_PAGE_INTRO);
168         set_page_title (*vbox, string_compose (_("Welcome to %1"), PROGRAM_NAME));
169         set_page_header_image (*vbox, icon_pixbuf);
170         set_page_complete (*vbox, true);
171 }
172
173 void
174 ArdourStartup::default_dir_changed ()
175 {
176         Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
177         // make new session folder chooser point to the new default
178         new_folder_chooser.set_current_folder (Config->get_default_session_parent_dir());
179         config_changed ();
180 }
181
182 void
183 ArdourStartup::config_changed ()
184 {
185         config_modified = true;
186 }
187
188 void
189 ArdourStartup::setup_first_time_config_page ()
190 {
191         default_dir_chooser = manage (new FileChooserButton (string_compose (_("Default folder for %1 sessions"), PROGRAM_NAME),
192                                                              FILE_CHOOSER_ACTION_SELECT_FOLDER));
193         Gtk::Label* txt = manage (new Label);
194         HBox* hbox = manage (new HBox);
195         VBox* vbox = manage (new VBox);
196
197         txt->set_markup (string_compose (_("\
198 Each project that you work on with %1 has its own folder.\n\
199 These can require a lot of disk space if you are recording audio.\n\
200 \n\
201 Where would you like new %1 sessions to be stored by default?\n\n\
202 <i>(You can put new sessions anywhere, this is just a default)</i>"), PROGRAM_NAME));
203         txt->set_alignment (0.0, 0.0);
204
205         vbox->set_spacing (18);
206         vbox->set_border_width (24);
207
208         hbox->pack_start (*default_dir_chooser, false, true, 8);
209         vbox->pack_start (*txt, false, false);
210         vbox->pack_start (*hbox, false, true);
211
212         cerr << "set default folder to " << poor_mans_glob (Config->get_default_session_parent_dir()) << endl;
213         Gtkmm2ext::add_volume_shortcuts (*default_dir_chooser);
214         default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
215         default_dir_chooser->signal_current_folder_changed().connect (sigc::mem_fun (*this, &ArdourStartup::default_dir_changed));
216         default_dir_chooser->show ();
217
218         vbox->show_all ();
219
220         default_folder_page_index = append_page (*vbox);
221         set_page_title (*vbox, _("Default folder for new sessions"));
222         set_page_header_image (*vbox, icon_pixbuf);
223         set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
224
225         /* user can just skip all these settings if they want to */
226
227         set_page_complete (*vbox, true);
228 }
229
230 void
231 ArdourStartup::setup_monitoring_choice_page ()
232 {
233         mon_vbox.set_spacing (18);
234         mon_vbox.set_border_width (24);
235
236         HBox* hbox = manage (new HBox);
237         VBox* vbox = manage (new VBox);
238         /* first button will be on by default */
239         RadioButton::Group g (monitor_via_ardour_button.get_group());
240         monitor_via_hardware_button.set_group (g);
241
242         monitor_label.set_markup(_("\
243 While recording instruments or vocals, you probably want to listen to the\n\
244 signal as well as record it. This is called \"monitoring\". There are\n\
245 different ways to do this depending on the equipment you have and the\n\
246 configuration of that equipment. The two most common are presented here.\n\
247 Please choose whichever one is right for your setup.\n\n\
248 <i>(You can change this preference at any time, via the Preferences dialog)</i>\n\n\
249 <i>If you do not understand what this is about, just accept the default.</i>"));
250         monitor_label.set_alignment (0.0, 0.0);
251
252         vbox->set_spacing (6);
253
254         vbox->pack_start (monitor_via_hardware_button, false, true);
255         vbox->pack_start (monitor_via_ardour_button, false, true);
256         hbox->pack_start (*vbox, true, true, 8);
257         mon_vbox.pack_start (monitor_label, false, false);
258         mon_vbox.pack_start (*hbox, false, false);
259
260         mon_vbox.show_all ();
261
262         monitoring_page_index = append_page (mon_vbox);
263         set_page_title (mon_vbox, _("Monitoring Choices"));
264         set_page_header_image (mon_vbox, icon_pixbuf);
265
266         monitor_via_hardware_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
267         monitor_via_ardour_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
268
269         /* user could just click on "Forward" if default
270          * choice is correct.
271          */
272
273         set_page_complete (mon_vbox, true);
274 }
275
276 void
277 ArdourStartup::setup_monitor_section_choice_page ()
278 {
279         mon_sec_vbox.set_spacing (18);
280         mon_sec_vbox.set_border_width (24);
281
282         HBox* hbox = manage (new HBox);
283         VBox* main_vbox = manage (new VBox);
284         VBox* vbox;
285         Label* l = manage (new Label);
286
287         main_vbox->set_spacing (32);
288
289         no_monitor_section_button.set_label (_("Use a Master bus directly"));
290         l->set_alignment (0.0, 1.0);
291         l->set_markup(_("Connect the Master bus directly to your hardware outputs. This is preferable for simple usage."));
292
293         vbox = manage (new VBox);
294         vbox->set_spacing (6);
295         vbox->pack_start (no_monitor_section_button, false, true);
296         vbox->pack_start (*l, false, true);
297
298         main_vbox->pack_start (*vbox, false, false);
299
300         use_monitor_section_button.set_label (_("Use an additional Monitor bus"));
301         l = manage (new Label);
302         l->set_alignment (0.0, 1.0);
303         l->set_text (_("Use a Monitor bus between Master bus and hardware outputs for \n\
304 greater control in monitoring without affecting the mix."));
305
306         vbox = manage (new VBox);
307         vbox->set_spacing (6);
308         vbox->pack_start (use_monitor_section_button, false, true);
309         vbox->pack_start (*l, false, true);
310
311         main_vbox->pack_start (*vbox, false, false);
312
313         RadioButton::Group g (use_monitor_section_button.get_group());
314         no_monitor_section_button.set_group (g);
315
316         if (Config->get_use_monitor_bus()) {
317                 use_monitor_section_button.set_active (true);
318         } else {
319                 no_monitor_section_button.set_active (true);
320         }
321
322         use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
323         no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
324
325         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\
326 <i>If you do not understand what this is about, just accept the default.</i>"));
327         monitor_section_label.set_alignment (0.0, 0.0);
328
329         hbox->pack_start (*main_vbox, true, true, 8);
330         mon_sec_vbox.pack_start (*hbox, false, false);
331         mon_sec_vbox.pack_start (monitor_section_label, false, false);
332
333         mon_sec_vbox.show_all ();
334
335         monitor_section_page_index = append_page (mon_sec_vbox);
336         set_page_title (mon_sec_vbox, _("Monitor Section"));
337         set_page_header_image (mon_sec_vbox, icon_pixbuf);
338
339         /* user could just click on "Forward" if default
340          * choice is correct.
341          */
342
343         set_page_complete (mon_sec_vbox, true);
344 }
345
346 void
347 ArdourStartup::setup_final_page ()
348 {
349         string msg = string_compose (_("%1 is ready for use"), PROGRAM_NAME);
350
351         plugin_disco_button.signal_clicked().connect (sigc::mem_fun(*this, &ArdourStartup::discover_plugins));
352         plugin_disco_button.set_label (_("Scan for Plugins"));
353         plugin_disco_button.show ();
354
355         Gtk::Label* final_label = manage (new Label);
356         final_label->set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", msg));
357         final_label->show ();
358
359         VBox* vbox = manage (new VBox);
360         vbox->pack_start (*final_label, true, true);
361         if (!Profile->get_mixbus()) {
362                 vbox->pack_start (plugin_disco_button, true, false);
363         }
364         vbox->show ();
365
366         final_page_index = append_page (*vbox);
367         set_page_complete (*vbox, true);
368         set_page_header_image (*vbox, icon_pixbuf);
369         set_page_type (*vbox, ASSISTANT_PAGE_CONFIRM);
370 }
371
372 void
373 ArdourStartup::discover_plugins () {
374         plugin_disco_button.set_sensitive (false);
375         PluginManager::instance().refresh();
376 }
377
378 void
379 ArdourStartup::on_cancel ()
380 {
381         _response = RESPONSE_CANCEL;
382         gtk_main_quit ();
383 }
384
385 bool
386 ArdourStartup::on_delete_event (GdkEventAny*)
387 {
388         _response = RESPONSE_CLOSE;
389         gtk_main_quit ();
390         return true;
391 }
392
393 void
394 ArdourStartup::on_apply ()
395 {
396         /* file-chooser button does not emit 'current_folder_changed' signal
397          * when a folder from the dropdown or the sidebar is chosen.
398          * -> explicitly poll for the dir as suggested by the gtk documentation.
399          */
400         if (default_dir_chooser && default_dir_chooser->get_filename() != Config->get_default_session_parent_dir ()) {
401                 config_modified = true;
402         }
403
404         if (config_modified) {
405
406                 if (default_dir_chooser) {
407                         Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
408                 }
409
410                 if (monitor_via_hardware_button.get_active()) {
411                         Config->set_monitoring_model (ExternalMonitoring);
412                 } else if (monitor_via_ardour_button.get_active()) {
413                         Config->set_monitoring_model (SoftwareMonitoring);
414                 }
415
416                 Config->set_use_monitor_bus (use_monitor_section_button.get_active());
417
418                 Config->save_state ();
419
420         }
421
422         {
423                 /* "touch" the been-here-before path now we've successfully
424                    made it through the first time setup (at least)
425                 */
426                 PBD::ScopedFileDescriptor fout (g_open (been_here_before_path ().c_str(), O_CREAT|O_TRUNC|O_RDWR, 0666));
427
428         }
429
430         _response = RESPONSE_OK;
431         gtk_main_quit ();
432 }
433
434
435 void
436 ArdourStartup::move_along_now ()
437 {
438         on_apply ();
439 }