Optimize automation-event process splitting
[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         monitor_via_hardware_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
258         monitor_via_ardour_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
259
260         /* user could just click on "Forward" if default
261          * choice is correct.
262          */
263
264         set_page_complete (mon_vbox, true);
265 }
266
267 void
268 ArdourStartup::setup_monitor_section_choice_page ()
269 {
270         mon_sec_vbox.set_spacing (18);
271         mon_sec_vbox.set_border_width (24);
272
273         HBox* hbox = manage (new HBox);
274         VBox* main_vbox = manage (new VBox);
275         VBox* vbox;
276         Label* l = manage (new Label);
277
278         main_vbox->set_spacing (32);
279
280         no_monitor_section_button.set_label (_("Use a Master bus directly"));
281         l->set_alignment (0.0, 1.0);
282         l->set_markup(_("Connect the Master bus directly to your hardware outputs. This is preferable for simple usage."));
283
284         vbox = manage (new VBox);
285         vbox->set_spacing (6);
286         vbox->pack_start (no_monitor_section_button, false, true);
287         vbox->pack_start (*l, false, true);
288
289         main_vbox->pack_start (*vbox, false, false);
290
291         use_monitor_section_button.set_label (_("Use an additional Monitor bus"));
292         l = manage (new Label);
293         l->set_alignment (0.0, 1.0);
294         l->set_text (_("Use a Monitor bus between Master bus and hardware outputs for \n\
295 greater control in monitoring without affecting the mix."));
296
297         vbox = manage (new VBox);
298         vbox->set_spacing (6);
299         vbox->pack_start (use_monitor_section_button, false, true);
300         vbox->pack_start (*l, false, true);
301
302         main_vbox->pack_start (*vbox, false, false);
303
304         RadioButton::Group g (use_monitor_section_button.get_group());
305         no_monitor_section_button.set_group (g);
306
307         if (Config->get_use_monitor_bus()) {
308                 use_monitor_section_button.set_active (true);
309         } else {
310                 no_monitor_section_button.set_active (true);
311         }
312
313         use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
314         no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
315
316         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\
317 <i>If you do not understand what this is about, just accept the default.</i>"));
318         monitor_section_label.set_alignment (0.0, 0.0);
319
320         hbox->pack_start (*main_vbox, true, true, 8);
321         mon_sec_vbox.pack_start (*hbox, false, false);
322         mon_sec_vbox.pack_start (monitor_section_label, false, false);
323
324         mon_sec_vbox.show_all ();
325
326         monitor_section_page_index = append_page (mon_sec_vbox);
327         set_page_title (mon_sec_vbox, _("Monitor Section"));
328         set_page_header_image (mon_sec_vbox, icon_pixbuf);
329
330         /* user could just click on "Forward" if default
331          * choice is correct.
332          */
333
334         set_page_complete (mon_sec_vbox, true);
335 }
336
337 void
338 ArdourStartup::setup_final_page ()
339 {
340         string msg = string_compose (_("%1 is ready for use"), PROGRAM_NAME);
341
342         plugin_disco_button.signal_clicked().connect (sigc::mem_fun(*this, &ArdourStartup::discover_plugins));
343         plugin_disco_button.set_label (_("Scan for Plugins"));
344         plugin_disco_button.show ();
345
346         Gtk::Label* final_label = manage (new Label);
347         final_label->set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", msg));
348         final_label->show ();
349
350         VBox* vbox = manage (new VBox);
351         vbox->pack_start (*final_label, true, true);
352         if (!Profile->get_mixbus()) {
353                 vbox->pack_start (plugin_disco_button, true, false);
354         }
355         vbox->show ();
356
357         final_page_index = append_page (*vbox);
358         set_page_complete (*vbox, true);
359         set_page_header_image (*vbox, icon_pixbuf);
360         set_page_type (*vbox, ASSISTANT_PAGE_CONFIRM);
361 }
362
363 void
364 ArdourStartup::discover_plugins () {
365         plugin_disco_button.set_sensitive (false);
366         PluginManager::instance().refresh();
367 }
368
369 void
370 ArdourStartup::on_cancel ()
371 {
372         _response = RESPONSE_CANCEL;
373         gtk_main_quit ();
374 }
375
376 bool
377 ArdourStartup::on_delete_event (GdkEventAny*)
378 {
379         _response = RESPONSE_CLOSE;
380         gtk_main_quit ();
381         return true;
382 }
383
384 void
385 ArdourStartup::on_apply ()
386 {
387         /* file-chooser button does not emit 'current_folder_changed' signal
388          * when a folder from the dropdown or the sidebar is chosen.
389          * -> explicitly poll for the dir as suggested by the gtk documentation.
390          */
391         if (default_dir_chooser && default_dir_chooser->get_filename() != Config->get_default_session_parent_dir ()) {
392                 config_modified = true;
393         }
394
395         if (config_modified) {
396
397                 if (default_dir_chooser) {
398                         Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
399                 }
400
401                 if (monitor_via_hardware_button.get_active()) {
402                         Config->set_monitoring_model (ExternalMonitoring);
403                 } else if (monitor_via_ardour_button.get_active()) {
404                         Config->set_monitoring_model (SoftwareMonitoring);
405                 }
406
407                 Config->set_use_monitor_bus (use_monitor_section_button.get_active());
408
409                 Config->save_state ();
410
411         }
412
413         {
414                 /* "touch" the been-here-before path now we've successfully
415                    made it through the first time setup (at least)
416                 */
417                 PBD::ScopedFileDescriptor fout (g_open (been_here_before_path ().c_str(), O_CREAT|O_TRUNC|O_RDWR, 0666));
418
419         }
420
421         _response = RESPONSE_OK;
422         gtk_main_quit ();
423 }
424
425
426 void
427 ArdourStartup::move_along_now ()
428 {
429         on_apply ();
430 }