ardour
startup.cc
Go to the documentation of this file.
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"
40 #include "ardour/recent_sessions.h"
41 #include "ardour/session.h"
43 #include "ardour/template_utils.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 
62 
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 
106  setup_final_page ();
107 
108  the_startup = this;
109 }
110 
112 {
113 }
114 
115 bool
117 {
118  /* look for a "been here before" file for this version or earlier
119  * versions
120  */
121 
122  const int current_version = atoi (PROGRAM_VERSION);
123 
124  for (int v = current_version; v != 0; --v) {
125  if (Glib::file_test (ARDOUR::been_here_before_path (v), Glib::FILE_TEST_EXISTS)) {
126  if (v != current_version) {
127  /* older version exists, create the current one */
128  ofstream fout (been_here_before_path (current_version).c_str());
129  }
130  return false;
131  }
132  }
133 
134  return true;
135 }
136 
137 void
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
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
184 {
185  config_modified = true;
186 }
187 
188 void
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  default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
214  default_dir_chooser->signal_current_folder_changed().connect (sigc::mem_fun (*this, &ArdourStartup::default_dir_changed));
215  default_dir_chooser->show ();
216 
217  vbox->show_all ();
218 
219  default_folder_page_index = append_page (*vbox);
220  set_page_title (*vbox, _("Default folder for new sessions"));
221  set_page_header_image (*vbox, icon_pixbuf);
222  set_page_type (*vbox, ASSISTANT_PAGE_CONTENT);
223 
224  /* user can just skip all these settings if they want to */
225 
226  set_page_complete (*vbox, true);
227 }
228 
229 void
231 {
232  mon_vbox.set_spacing (18);
233  mon_vbox.set_border_width (24);
234 
235  HBox* hbox = manage (new HBox);
236  VBox* vbox = manage (new VBox);
237  /* first button will be on by default */
238  RadioButton::Group g (monitor_via_ardour_button.get_group());
239  monitor_via_hardware_button.set_group (g);
240 
241  monitor_label.set_markup(_("\
242 While recording instruments or vocals, you probably want to listen to the\n\
243 signal as well as record it. This is called \"monitoring\". There are\n\
244 different ways to do this depending on the equipment you have and the\n\
245 configuration of that equipment. The two most common are presented here.\n\
246 Please choose whichever one is right for your setup.\n\n\
247 <i>(You can change this preference at any time, via the Preferences dialog)</i>\n\n\
248 <i>If you do not understand what this is about, just accept the default.</i>"));
249  monitor_label.set_alignment (0.0, 0.0);
250 
251  vbox->set_spacing (6);
252 
253  vbox->pack_start (monitor_via_hardware_button, false, true);
254  vbox->pack_start (monitor_via_ardour_button, false, true);
255  hbox->pack_start (*vbox, true, true, 8);
256  mon_vbox.pack_start (monitor_label, false, false);
257  mon_vbox.pack_start (*hbox, false, false);
258 
259  mon_vbox.show_all ();
260 
261  monitoring_page_index = append_page (mon_vbox);
262  set_page_title (mon_vbox, _("Monitoring Choices"));
263  set_page_header_image (mon_vbox, icon_pixbuf);
264 
265  /* user could just click on "Forward" if default
266  * choice is correct.
267  */
268 
269  set_page_complete (mon_vbox, true);
270 }
271 
272 void
274 {
275  mon_sec_vbox.set_spacing (18);
276  mon_sec_vbox.set_border_width (24);
277 
278  HBox* hbox = manage (new HBox);
279  VBox* main_vbox = manage (new VBox);
280  VBox* vbox;
281  Label* l = manage (new Label);
282 
283  main_vbox->set_spacing (32);
284 
285  no_monitor_section_button.set_label (_("Use a Master bus directly"));
286  l->set_alignment (0.0, 1.0);
287  l->set_markup(_("Connect the Master bus directly to your hardware outputs. This is preferable for simple usage."));
288 
289  vbox = manage (new VBox);
290  vbox->set_spacing (6);
291  vbox->pack_start (no_monitor_section_button, false, true);
292  vbox->pack_start (*l, false, true);
293 
294  main_vbox->pack_start (*vbox, false, false);
295 
296  use_monitor_section_button.set_label (_("Use an additional Monitor bus"));
297  l = manage (new Label);
298  l->set_alignment (0.0, 1.0);
299  l->set_text (_("Use a Monitor bus between Master bus and hardware outputs for \n\
300 greater control in monitoring without affecting the mix."));
301 
302  vbox = manage (new VBox);
303  vbox->set_spacing (6);
304  vbox->pack_start (use_monitor_section_button, false, true);
305  vbox->pack_start (*l, false, true);
306 
307  main_vbox->pack_start (*vbox, false, false);
308 
309  RadioButton::Group g (use_monitor_section_button.get_group());
310  no_monitor_section_button.set_group (g);
311 
312  if (Config->get_use_monitor_bus()) {
313  use_monitor_section_button.set_active (true);
314  } else {
315  no_monitor_section_button.set_active (true);
316  }
317 
318  use_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
319  no_monitor_section_button.signal_toggled().connect (sigc::mem_fun (*this, &ArdourStartup::config_changed));
320 
321  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\
322 <i>If you do not understand what this is about, just accept the default.</i>"));
323  monitor_section_label.set_alignment (0.0, 0.0);
324 
325  hbox->pack_start (*main_vbox, true, true, 8);
326  mon_sec_vbox.pack_start (*hbox, false, false);
327  mon_sec_vbox.pack_start (monitor_section_label, false, false);
328 
329  mon_sec_vbox.show_all ();
330 
332  set_page_title (mon_sec_vbox, _("Monitor Section"));
333  set_page_header_image (mon_sec_vbox, icon_pixbuf);
334 
335  /* user could just click on "Forward" if default
336  * choice is correct.
337  */
338 
339  set_page_complete (mon_sec_vbox, true);
340 }
341 
342 void
344 {
345  string msg = string_compose (_("%1 is ready for use"), PROGRAM_NAME);
346 
347  final_page.set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", msg));
348  final_page.show ();
349  final_page_index = append_page (final_page);
350  set_page_complete (final_page, true);
351  set_page_header_image (final_page, icon_pixbuf);
352  set_page_type (final_page, ASSISTANT_PAGE_CONFIRM);
353 }
354 
355 void
357 {
358  _response = RESPONSE_CANCEL;
359  gtk_main_quit ();
360 }
361 
362 bool
364 {
365  _response = RESPONSE_CLOSE;
366  gtk_main_quit ();
367  return true;
368 }
369 
370 void
372 {
373  /* file-chooser button does not emit 'current_folder_changed' signal
374  * when a folder from the dropdown or the sidebar is chosen.
375  * -> explicitly poll for the dir as suggested by the gtk documentation.
376  */
377  if (default_dir_chooser && default_dir_chooser->get_filename() != Config->get_default_session_parent_dir ()) {
378  config_modified = true;
379  }
380 
381  if (config_modified) {
382 
383  if (default_dir_chooser) {
384  Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
385  }
386 
387  if (monitor_via_hardware_button.get_active()) {
388  Config->set_monitoring_model (ExternalMonitoring);
389  } else if (monitor_via_ardour_button.get_active()) {
390  Config->set_monitoring_model (SoftwareMonitoring);
391  }
392 
393  Config->set_use_monitor_bus (use_monitor_section_button.get_active());
394 
395  Config->save_state ();
396 
397  }
398 
399  {
400  /* "touch" the been-here-before path now we've successfully
401  made it through the first time setup (at least)
402  */
403  ofstream fout (been_here_before_path().c_str());
404 
405  }
406 
407  _response = RESPONSE_OK;
408  gtk_main_quit ();
409 }
410 
411 
412 void
414 {
415  on_apply ();
416 }
gint new_user_page_index
Definition: startup.h:113
int atoi(const string &s)
Definition: convert.cc:140
void setup_monitoring_choice_page()
Definition: startup.cc:230
gint monitoring_page_index
Definition: startup.h:115
Definition: ardour_ui.h:130
Gtk::Label monitor_label
Definition: startup.h:88
Gtk::RadioButton monitor_via_hardware_button
Definition: startup.h:89
Definition: Beats.hpp:239
Gtk::Label final_page
Definition: startup.h:104
Gtk::FileChooserButton * default_dir_chooser
Definition: startup.h:80
void setup_monitor_section_choice_page()
Definition: startup.cc:273
bool config_modified
Definition: startup.h:60
void config_changed()
Definition: startup.cc:183
void default_dir_changed()
Definition: startup.cc:174
#define _(Text)
Definition: i18n.h:11
we leave monitoring to the audio hardware
Definition: types.h:383
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
Gtk::RadioButton no_monitor_section_button
Definition: startup.h:98
void setup_final_page()
Definition: startup.cc:343
void setup_new_user_page()
Definition: startup.cc:138
void move_along_now()
Definition: startup.cc:413
Definition: amp.h:29
LIBARDOUR_API std::string been_here_before_path(int version=-1)
LIBPBD_API std::string poor_mans_glob(std::string path)
Definition: strreplace.cc:41
Glib::RefPtr< Gdk::Pixbuf > icon_pixbuf
Definition: startup.h:69
gint _response
Definition: startup.h:59
static bool required()
Definition: startup.cc:116
Ardour does monitoring.
Definition: types.h:382
void setup_first_time_config_page()
Definition: startup.cc:189
bool on_delete_event(GdkEventAny *)
Definition: startup.cc:363
void on_cancel()
Definition: startup.cc:356
void on_apply()
Definition: startup.cc:371
Gtk::VBox mon_sec_vbox
Definition: startup.h:95
gint monitor_section_page_index
Definition: startup.h:116
Definition: debug.h:30
Gtk::RadioButton monitor_via_ardour_button
Definition: startup.h:90
Gtk::VBox mon_vbox
Definition: startup.h:87
Gtk::Label monitor_section_label
Definition: startup.h:96
Gtk::FileChooserButton new_folder_chooser
Definition: startup.h:83
Gtk::RadioButton use_monitor_section_button
Definition: startup.h:97
Glib::RefPtr< Gdk::Pixbuf > get_icon(const char *cname)
Definition: utils.cc:674
gint default_folder_page_index
Definition: startup.h:114
gint final_page_index
Definition: startup.h:117
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
static ArdourStartup * the_startup
Definition: startup.h:67