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