ardour
session_dialog.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2013 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 #endif
23 
24 #include <fstream>
25 #include <algorithm>
26 
27 #include <gtkmm/filechooser.h>
28 
29 #include "pbd/failed_constructor.h"
30 #include "pbd/file_utils.h"
31 #include "pbd/replace_all.h"
32 #include "pbd/whitespace.h"
33 #include "pbd/stacktrace.h"
34 #include "pbd/stl_delete.h"
35 #include "pbd/openuri.h"
36 
37 #include "ardour/audioengine.h"
39 #include "ardour/recent_sessions.h"
40 #include "ardour/session.h"
42 #include "ardour/template_utils.h"
44 
45 #include "ardour_ui.h"
46 #include "session_dialog.h"
47 #include "opts.h"
48 #include "engine_dialog.h"
49 #include "i18n.h"
50 #include "utils.h"
51 
52 using namespace std;
53 using namespace Gtk;
54 using namespace Gdk;
55 using namespace Glib;
56 using namespace PBD;
57 using namespace ARDOUR;
58 using namespace ARDOUR_UI_UTILS;
59 
60 SessionDialog::SessionDialog (bool require_new, const std::string& session_name, const std::string& session_path, const std::string& template_name, bool cancel_not_quit)
61  : ArdourDialog (_("Session Setup"), true, true)
62  , new_only (require_new)
63  , _provided_session_name (session_name)
64  , _provided_session_path (session_path)
65  , new_folder_chooser (FILE_CHOOSER_ACTION_SELECT_FOLDER)
66  , more_new_session_options_button (_("Advanced options ..."))
67  , _output_limit_count_adj (1, 0, 100, 1, 10, 0)
68  , _input_limit_count_adj (1, 0, 100, 1, 10, 0)
69  , _master_bus_channel_count_adj (2, 0, 100, 1, 10, 0)
70  , _existing_session_chooser_used (false)
71 {
72  set_position (WIN_POS_CENTER);
73  get_vbox()->set_spacing (6);
74 
75  cancel_button = add_button ((cancel_not_quit ? Stock::CANCEL : Stock::QUIT), RESPONSE_CANCEL);
76  back_button = add_button (Stock::GO_BACK, RESPONSE_NO);
77  open_button = add_button (Stock::OPEN, RESPONSE_ACCEPT);
78 
79  back_button->signal_button_press_event().connect (sigc::mem_fun (*this, &SessionDialog::back_button_pressed), false);
80 
81  open_button->set_sensitive (false);
82  back_button->set_sensitive (false);
83 
84  /* this is where announcements will be displayed, but it may be empty
85  * and invisible most of the time.
86  */
87 
88  info_frame.set_shadow_type(SHADOW_ETCHED_OUT);
89  info_frame.set_no_show_all (true);
90  info_frame.set_border_width (12);
91  get_vbox()->pack_start (info_frame, false, false);
92 
94 
95  if (!new_only) {
97  get_vbox()->pack_start (ic_vbox, true, true);
98  } else {
99  get_vbox()->pack_start (session_new_vbox, true, true);
100  }
101 
102  if (!template_name.empty()) {
103  use_template_button.set_active (false);
104  load_template_override = template_name;
105  }
106 
107  get_vbox()->show_all ();
108 
109  /* fill data models and show/hide accordingly */
110 
112 
113  if (!template_model->children().empty()) {
114  use_template_button.show();
115  template_chooser.show ();
116  } else {
117  use_template_button.hide();
118  template_chooser.hide ();
119  }
120 
121  if (recent_session_model) {
122  int cnt = redisplay_recent_sessions ();
123  if (cnt > 0) {
124  recent_scroller.show();
125  recent_label.show ();
126 
127  if (cnt > 4) {
128  recent_scroller.set_size_request (-1, 300);
129  }
130  } else {
131  recent_scroller.hide();
132  recent_label.hide ();
133  }
134  }
135 
136  /* possibly get out of here immediately if everything is ready to go.
137  We still need to set up the whole dialog because of the way
138  ARDOUR_UI::get_session_parameters() might skip it on a first
139  pass then require it for a second pass (e.g. when there
140  is an error with session loading and we have to ask the user
141  what to do next).
142  */
143 
144  if (!session_name.empty() && !require_new) {
145  response (RESPONSE_OK);
146  return;
147  }
148 }
149 
151 {
152 }
153 
154 void
156 {
159 }
160 
161 bool
163 {
164  if (!load_template_override.empty()) {
165  return true;
166  }
167 
168  if (use_template_button.get_active()) {
169  return true;
170  }
171 
172  return false;
173 }
174 
175 std::string
177 {
178  if (!load_template_override.empty()) {
179  string the_path (ARDOUR::user_template_directory());
180  return Glib::build_filename (the_path, load_template_override + ARDOUR::template_suffix);
181  }
182 
183  if (use_template_button.get_active()) {
184  TreeModel::iterator iter = template_chooser.get_active ();
185  TreeModel::Row row = (*iter);
186  string s = row[session_template_columns.path];
187  return s;
188  }
189 
190  return string();
191 }
192 
193 std::string
194 SessionDialog::session_name (bool& should_be_new)
195 {
196  if (!_provided_session_name.empty() && !new_only) {
197  should_be_new = false;
198  return _provided_session_name;
199  }
200 
201  /* Try recent session selection */
202 
203  TreeIter iter = recent_session_display.get_selection()->get_selected();
204 
205  if (iter) {
206  should_be_new = false;
207  return (*iter)[recent_session_columns.visible_name];
208  }
209 
211  /* existing session chosen from file chooser */
212  should_be_new = false;
213  return existing_session_chooser.get_filename ();
214  } else {
215  should_be_new = true;
216  string val = new_name_entry.get_text ();
218  return val;
219  }
220 }
221 
222 std::string
224 {
225  if (!_provided_session_path.empty() && !new_only) {
226  return _provided_session_path;
227  }
228 
229  /* Try recent session selection */
230 
231  TreeIter iter = recent_session_display.get_selection()->get_selected();
232 
233  if (iter) {
234  string s = (*iter)[recent_session_columns.fullpath];
235  if (Glib::file_test (s, Glib::FILE_TEST_IS_REGULAR)) {
236  return Glib::path_get_dirname (s);
237  }
238  return s;
239  }
240 
242  /* existing session chosen from file chooser */
243  return Glib::path_get_dirname (existing_session_chooser.get_current_folder ());
244  } else {
245  std::string val = new_name_entry.get_text();
247  std::string legal_session_folder_name = legalize_for_path (val);
248  return Glib::build_filename (new_folder_chooser.get_filename (), legal_session_folder_name);
249  }
250 }
251 
252 void
254 {
255  ic_vbox.set_spacing (6);
256 
257  HBox* centering_hbox = manage (new HBox);
258  VBox* centering_vbox = manage (new VBox);
259 
260  centering_vbox->set_spacing (6);
261 
262  Label* new_label = manage (new Label);
263  new_label->set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", _("New Session")));
264  new_label->set_justify (JUSTIFY_CENTER);
265 
266  ic_new_session_button.add (*new_label);
267  ic_new_session_button.signal_clicked().connect (sigc::mem_fun (*this, &SessionDialog::new_session_button_clicked));
268 
269  Gtk::HBox* hbox = manage (new HBox);
270  Gtk::VBox* vbox = manage (new VBox);
271  hbox->set_spacing (12);
272  vbox->set_spacing (12);
273 
274  string image_path;
275 
276  if (find_file (ardour_data_search_path(), "small-splash.png", image_path)) {
277  Gtk::Image* image;
278  if ((image = manage (new Gtk::Image (image_path))) != 0) {
279  hbox->pack_start (*image, false, false);
280  }
281  }
282 
283  vbox->pack_start (ic_new_session_button, true, true, 20);
284  hbox->pack_start (*vbox, true, true, 20);
285 
286  centering_vbox->pack_start (*hbox, false, false);
287 
288  /* Possible update message */
289 
290  if (ARDOUR_UI::instance()->announce_string() != "" ) {
291 
292  Box *info_box = manage (new VBox);
293  info_box->set_border_width (12);
294  info_box->set_spacing (6);
295 
296  info_box->pack_start (info_scroller_label, false, false);
297 
299  info_scroller_connection = Glib::signal_timeout().connect (mem_fun(*this, &SessionDialog::info_scroller_update), 50);
300 
301  Gtk::Button *updates_button = manage (new Gtk::Button (_("Check the website for more...")));
302 
303  updates_button->signal_clicked().connect (mem_fun(*this, &SessionDialog::updates_button_clicked) );
304  ARDOUR_UI::instance()->tooltips().set_tip (*updates_button, _("Click to open the program website in your web browser"));
305 
306  info_box->pack_start (*updates_button, false, false);
307 
308  info_frame.add (*info_box);
309  info_box->show_all ();
310  info_frame.show ();
311  }
312 
313  /* recent session scroller */
314 
315  recent_label.set_no_show_all (true);
316  recent_scroller.set_no_show_all (true);
317 
318  recent_label.set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", _("Recent Sessions")));
319 
320  recent_session_model = TreeStore::create (recent_session_columns);
321 
323  recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
324  recent_session_display.append_column (_("Sample Rate"), recent_session_columns.sample_rate);
325  recent_session_display.append_column (_("Disk Format"), recent_session_columns.disk_format);
326  recent_session_display.set_headers_visible (false);
327  recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
328 
329  recent_session_display.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &SessionDialog::recent_session_row_selected));
330 
332  recent_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
333  recent_scroller.set_shadow_type (Gtk::SHADOW_IN);
334 
335  recent_session_display.show();
336  recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &SessionDialog::recent_row_activated));
337 
338  centering_vbox->pack_start (recent_label, false, false, 12);
339  centering_vbox->pack_start (recent_scroller, true, true);
340 
341  /* Browse button */
342 
343  existing_session_chooser.set_title (_("Select session file"));
344  existing_session_chooser.signal_file_set().connect (sigc::mem_fun (*this, &SessionDialog::existing_session_selected));
345  existing_session_chooser.set_current_folder(poor_mans_glob (Config->get_default_session_parent_dir()));
346 
347  FileFilter session_filter;
348  session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
349  session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
350  existing_session_chooser.add_filter (session_filter);
351  existing_session_chooser.set_filter (session_filter);
352 
353 #ifdef GTKOSX
354  existing_session_chooser.add_shortcut_folder ("/Volumes");
355 #endif
356 
357  Label* browse_label = manage (new Label);
358  browse_label->set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", _("Other Sessions")));
359 
360  centering_vbox->pack_start (*browse_label, false, false, 12);
361  centering_vbox->pack_start (existing_session_chooser, false, false);
362 
363  /* pack it all up */
364 
365  centering_hbox->pack_start (*centering_vbox, true, true);
366  ic_vbox.pack_start (*centering_hbox, true, true);
367  ic_vbox.show_all ();
368 }
369 
370 void
372 {
373  /* HACK HACK HACK ... change the "Apply" button label
374  to say "Open"
375  */
376 
377  Gtk::Widget* tl = ic_vbox.get_toplevel();
378  Gtk::Window* win;
379  if ((win = dynamic_cast<Gtk::Window*>(tl)) != 0) {
380  /* ::get_default_widget() is not wrapped in gtkmm */
381  Gtk::Widget* def = wrap (gtk_window_get_default_widget (win->gobj()));
382  Gtk::Button* button;
383  if ((button = dynamic_cast<Gtk::Button*>(def)) != 0) {
384  button->set_label (_("Open"));
385  }
386  }
387 }
388 
389 void
391 {
393  recent_session_display.get_selection()->unselect_all ();
394 
395  get_vbox()->remove (ic_vbox);
396  get_vbox()->pack_start (session_new_vbox, true, true);
397  back_button->set_sensitive (true);
398  new_name_entry.grab_focus ();
399 }
400 
401 bool
403 {
404  get_vbox()->remove (session_new_vbox);
405  back_button->set_sensitive (false);
406  get_vbox()->pack_start (ic_vbox);
407 
408  return true;
409 }
410 
411 void
413 {
414  vector<TemplateInfo> templates;
415 
416  find_session_templates (templates);
417 
418  template_model->clear ();
419 
420  for (vector<TemplateInfo>::iterator x = templates.begin(); x != templates.end(); ++x) {
421  TreeModel::Row row;
422 
423  row = *(template_model->append ());
424 
425  row[session_template_columns.name] = (*x).name;
426  row[session_template_columns.path] = (*x).path;
427  }
428 
429  if (!templates.empty()) {
430  /* select first row */
431  template_chooser.set_active (0);
432  }
433 }
434 
435 void
437 {
438  session_new_vbox.set_border_width (12);
439  session_new_vbox.set_spacing (18);
440 
441  VBox *vbox1 = manage (new VBox);
442  HBox* hbox1 = manage (new HBox);
443  Label* label1 = manage (new Label);
444 
445  vbox1->set_spacing (6);
446 
447  hbox1->set_spacing (6);
448  hbox1->pack_start (*label1, false, false);
449  hbox1->pack_start (new_name_entry, true, true);
450 
451  label1->set_text (_("Session name:"));
452 
453  if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
454  new_name_entry.set_text (Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name));
455  /* name provided - they can move right along */
456  open_button->set_sensitive (true);
457  }
458 
459  new_name_entry.signal_changed().connect (sigc::mem_fun (*this, &SessionDialog::new_name_changed));
460  new_name_entry.signal_activate().connect (sigc::mem_fun (*this, &SessionDialog::new_name_activated));
461 
462  vbox1->pack_start (*hbox1, true, true);
463 
464  /* --- */
465 
466  HBox* hbox2 = manage (new HBox);
467  Label* label2 = manage (new Label);
468 
469  hbox2->set_spacing (6);
470  hbox2->pack_start (*label2, false, false);
471  hbox2->pack_start (new_folder_chooser, true, true);
472 
473  label2->set_text (_("Create session folder in:"));
474 
475  if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
476  new_folder_chooser.set_current_folder (poor_mans_glob (Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name)));
477  } else if (ARDOUR_UI::instance()->session_loaded) {
478  // point the new session file chooser at the parent directory of the current session
479  string session_parent_dir = Glib::path_get_dirname(ARDOUR_UI::instance()->the_session()->path());
480  string::size_type last_dir_sep = session_parent_dir.rfind(G_DIR_SEPARATOR);
481  session_parent_dir = session_parent_dir.substr(0, last_dir_sep);
482  new_folder_chooser.set_current_folder (session_parent_dir);
483  string default_session_folder = poor_mans_glob (Config->get_default_session_parent_dir());
484 
485  try {
486  /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
487  new_folder_chooser.add_shortcut_folder (default_session_folder);
488  }
489  catch (Glib::Error & e) {
490  std::cerr << "new_folder_chooser.add_shortcut_folder (" << default_session_folder << ") threw Glib::Error " << e.what() << std::endl;
491  }
492  } else {
493  new_folder_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
494  }
495  new_folder_chooser.show ();
496  new_folder_chooser.set_title (_("Select folder for session"));
497 
498 #ifdef __APPLE__
499  new_folder_chooser.add_shortcut_folder ("/Volumes");
500 #endif
501 
502  vbox1->pack_start (*hbox2, false, false);
503 
504  session_new_vbox.pack_start (*vbox1, false, false);
505 
506  /* --- */
507 
508  VBox *vbox2 = manage (new VBox);
509  HBox* hbox3 = manage (new HBox);
510  template_model = ListStore::create (session_template_columns);
511 
512  vbox2->set_spacing (6);
513 
514  VBox *vbox3 = manage (new VBox);
515 
516  vbox3->set_spacing (6);
517 
518  /* we may want to hide this and show it at various
519  times depending on the existence of templates.
520  */
521  template_chooser.set_no_show_all (true);
522  use_template_button.set_no_show_all (true);
523 
524  HBox* hbox4a = manage (new HBox);
525  use_template_button.set_label (_("Use this template"));
526 
527  TreeModel::Row row = *template_model->prepend ();
528  row[session_template_columns.name] = (_("no template"));
529  row[session_template_columns.path] = string();
530 
531  hbox4a->set_spacing (6);
532  hbox4a->pack_start (use_template_button, false, false);
533  hbox4a->pack_start (template_chooser, true, true);
534 
535  template_chooser.set_model (template_model);
536 
537  Gtk::CellRendererText* text_renderer = Gtk::manage (new Gtk::CellRendererText);
538  text_renderer->property_editable() = false;
539 
540  template_chooser.pack_start (*text_renderer);
541  template_chooser.add_attribute (text_renderer->property_text(), session_template_columns.name);
542  template_chooser.set_active (0);
543 
544  vbox3->pack_start (*hbox4a, false, false);
545 
546  /* --- */
547 
548  HBox* hbox5 = manage (new HBox);
549 
550  hbox5->set_spacing (6);
551  hbox5->pack_start (more_new_session_options_button, false, false);
552 
555 
556  vbox3->pack_start (*hbox5, false, false);
557  hbox3->pack_start (*vbox3, true, true, 8);
558  vbox2->pack_start (*hbox3, false, false);
559 
560  /* --- */
561 
562  session_new_vbox.pack_start (*vbox2, false, false);
563  session_new_vbox.show_all ();
564 }
565 
566 void
568 {
569  if (!new_name_entry.get_text().empty()) {
570  session_selected ();
571  open_button->set_sensitive (true);
572  } else {
573  open_button->set_sensitive (false);
574  }
575 }
576 
577 void
579 {
580  response (RESPONSE_ACCEPT);
581 }
582 
583 int
585 {
586  std::vector<std::string> session_directories;
588 
589  recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
590  recent_session_model->clear ();
591 
594 
595  if (rs.empty()) {
597  return 0;
598  }
599  //
600  // sort them alphabetically
601  sort (rs.begin(), rs.end(), cmp);
602 
603  for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
604  session_directories.push_back ((*i).second);
605  }
606 
607  int session_snapshot_count = 0;
608 
609  for (vector<std::string>::const_iterator i = session_directories.begin(); i != session_directories.end(); ++i)
610  {
611  std::vector<std::string> state_file_paths;
612 
613  // now get available states for this session
614 
615  get_state_files_in_directory (*i, state_file_paths);
616 
617  vector<string> states;
618  vector<const gchar*> item;
619  string dirname = *i;
620 
621  /* remove any trailing / */
622 
623  if (dirname[dirname.length()-1] == '/') {
624  dirname = dirname.substr (0, dirname.length()-1);
625  }
626 
627  /* check whether session still exists */
628  if (!Glib::file_test(dirname.c_str(), Glib::FILE_TEST_EXISTS)) {
629  /* session doesn't exist */
630  continue;
631  }
632 
633  /* now get available states for this session */
634 
635  states = Session::possible_states (dirname);
636 
637  if (states.empty()) {
638  /* no state file? */
639  continue;
640  }
641 
642  std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
643 
644  if (state_file_names.empty()) {
645  continue;
646  }
647 
648  Gtk::TreeModel::Row row = *(recent_session_model->append());
649 
650  float sr;
651  SampleFormat sf;
652  std::string state_file_basename = state_file_names.front();
653 
654  std::string s = Glib::build_filename (dirname, state_file_basename + statefile_suffix);
655 
656  row[recent_session_columns.fullpath] = dirname; /* just the dir, but this works too */
657  row[recent_session_columns.tip] = Glib::Markup::escape_text (dirname);
658 
659  if (Session::get_info_from_path (s, sr, sf) == 0) {
661  switch (sf) {
662  case FormatFloat:
663  row[recent_session_columns.disk_format] = _("32 bit float");
664  break;
665  case FormatInt24:
666  row[recent_session_columns.disk_format] = _("24 bit");
667  break;
668  case FormatInt16:
669  row[recent_session_columns.disk_format] = _("16 bit");
670  break;
671  }
672  } else {
675  }
676 
677  ++session_snapshot_count;
678 
679  if (state_file_names.size() > 1) {
680  // multiple session files in the session directory - show the directory name.
681  // if there's not a session file with the same name as the session directory,
682  // opening the parent item will fail, but expanding it will show the session
683  // files that actually exist, and the right one can then be opened.
684  row[recent_session_columns.visible_name] = Glib::path_get_basename (dirname);
685 
686  // add the children
687  for (std::vector<std::string>::iterator i2 = state_file_names.begin(); i2 != state_file_names.end(); ++i2) {
688 
689  Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
690 
691  child_row[recent_session_columns.visible_name] = *i2;
692  child_row[recent_session_columns.fullpath] = Glib::build_filename (dirname, *i2 + statefile_suffix);
693  child_row[recent_session_columns.tip] = Glib::Markup::escape_text (dirname);
694 
695  if (Session::get_info_from_path (s, sr, sf) == 0) {
697  switch (sf) {
698  case FormatFloat:
699  child_row[recent_session_columns.disk_format] = _("32 bit float");
700  break;
701  case FormatInt24:
702  child_row[recent_session_columns.disk_format] = _("24 bit");
703  break;
704  case FormatInt16:
705  child_row[recent_session_columns.disk_format] = _("16 bit");
706  break;
707  }
708  } else {
709  child_row[recent_session_columns.sample_rate] = "??";
710  child_row[recent_session_columns.disk_format] = "--";
711  }
712 
713 
714  ++session_snapshot_count;
715  }
716  } else {
717  // only a single session file in the directory - show its actual name.
718  row[recent_session_columns.visible_name] = state_file_basename;
719  }
720  }
721 
722  recent_session_display.set_tooltip_column(1); // recent_session_columns.tip
724  return session_snapshot_count;
725 }
726 
727 void
729 {
730  if (recent_session_display.get_selection()->count_selected_rows() > 0) {
731  open_button->set_sensitive (true);
732  session_selected ();
733  } else {
734  open_button->set_sensitive (false);
735  }
736 }
737 
738 void
740 {
741  more_options_vbox.set_border_width (24);
742 
746 
747  chan_count_label_1.set_text (_("channels"));
748  chan_count_label_3.set_text (_("channels"));
749  chan_count_label_4.set_text (_("channels"));
750 
751  chan_count_label_1.set_alignment(0,0.5);
752  chan_count_label_1.set_padding(0,0);
753  chan_count_label_1.set_line_wrap(false);
754 
755  chan_count_label_3.set_alignment(0,0.5);
756  chan_count_label_3.set_padding(0,0);
757  chan_count_label_3.set_line_wrap(false);
758 
759  chan_count_label_4.set_alignment(0,0.5);
760  chan_count_label_4.set_padding(0,0);
761  chan_count_label_4.set_line_wrap(false);
762 
763  bus_label.set_markup (_("<b>Busses</b>"));
764  input_label.set_markup (_("<b>Inputs</b>"));
765  output_label.set_markup (_("<b>Outputs</b>"));
766 
767  _master_bus_channel_count.set_flags(Gtk::CAN_FOCUS);
768  _master_bus_channel_count.set_update_policy(Gtk::UPDATE_ALWAYS);
769  _master_bus_channel_count.set_numeric(true);
770  _master_bus_channel_count.set_digits(0);
771  _master_bus_channel_count.set_wrap(false);
772 
773  _create_master_bus.set_label (_("Create master bus"));
774  _create_master_bus.set_flags(Gtk::CAN_FOCUS);
775  _create_master_bus.set_relief(Gtk::RELIEF_NORMAL);
776  _create_master_bus.set_mode(true);
777  _create_master_bus.set_active(true);
778  _create_master_bus.set_border_width(0);
779 
780  advanced_table.set_row_spacings(0);
781  advanced_table.set_col_spacings(0);
782 
783  _connect_inputs.set_label (_("Automatically connect to physical inputs"));
784  _connect_inputs.set_flags(Gtk::CAN_FOCUS);
785  _connect_inputs.set_relief(Gtk::RELIEF_NORMAL);
786  _connect_inputs.set_mode(true);
787  _connect_inputs.set_active(Config->get_input_auto_connect() != ManualConnect);
788  _connect_inputs.set_border_width(0);
789 
790  _limit_input_ports.set_label (_("Use only"));
791  _limit_input_ports.set_flags(Gtk::CAN_FOCUS);
792  _limit_input_ports.set_relief(Gtk::RELIEF_NORMAL);
793  _limit_input_ports.set_mode(true);
794  _limit_input_ports.set_sensitive(true);
795  _limit_input_ports.set_border_width(0);
796 
797  _input_limit_count.set_flags(Gtk::CAN_FOCUS);
798  _input_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
799  _input_limit_count.set_numeric(true);
800  _input_limit_count.set_digits(0);
801  _input_limit_count.set_wrap(false);
802  _input_limit_count.set_sensitive(false);
803 
804  bus_hbox.pack_start (bus_table, Gtk::PACK_SHRINK, 18);
805 
806  bus_label.set_alignment(0, 0.5);
807  bus_label.set_padding(0,0);
808  bus_label.set_line_wrap(false);
809  bus_label.set_selectable(false);
810  bus_label.set_use_markup(true);
811  bus_frame.set_shadow_type(Gtk::SHADOW_NONE);
812  bus_frame.set_label_align(0,0.5);
813  bus_frame.add(bus_hbox);
814  bus_frame.set_label_widget(bus_label);
815 
816  bus_table.set_row_spacings (0);
817  bus_table.set_col_spacings (0);
818  bus_table.attach (_create_master_bus, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
819  bus_table.attach (_master_bus_channel_count, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
820  bus_table.attach (chan_count_label_1, 2, 3, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 0);
821 
822  input_port_limit_hbox.pack_start(_limit_input_ports, Gtk::PACK_SHRINK, 6);
823  input_port_limit_hbox.pack_start(_input_limit_count, Gtk::PACK_SHRINK, 0);
824  input_port_limit_hbox.pack_start(chan_count_label_3, Gtk::PACK_SHRINK, 6);
825  input_port_vbox.pack_start(_connect_inputs, Gtk::PACK_SHRINK, 0);
826  input_port_vbox.pack_start(input_port_limit_hbox, Gtk::PACK_EXPAND_PADDING, 0);
827  input_table.set_row_spacings(0);
828  input_table.set_col_spacings(0);
829  input_table.attach(input_port_vbox, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 6, 6);
830 
831  input_hbox.pack_start (input_table, Gtk::PACK_SHRINK, 18);
832 
833  input_label.set_alignment(0, 0.5);
834  input_label.set_padding(0,0);
835  input_label.set_line_wrap(false);
836  input_label.set_selectable(false);
837  input_label.set_use_markup(true);
838  input_frame.set_shadow_type(Gtk::SHADOW_NONE);
839  input_frame.set_label_align(0,0.5);
840  input_frame.add(input_hbox);
841  input_frame.set_label_widget(input_label);
842 
843  _connect_outputs.set_label (_("Automatically connect outputs"));
844  _connect_outputs.set_flags(Gtk::CAN_FOCUS);
845  _connect_outputs.set_relief(Gtk::RELIEF_NORMAL);
846  _connect_outputs.set_mode(true);
847  _connect_outputs.set_active(Config->get_output_auto_connect() != ManualConnect);
848  _connect_outputs.set_border_width(0);
849  _limit_output_ports.set_label (_("Use only"));
850  _limit_output_ports.set_flags(Gtk::CAN_FOCUS);
851  _limit_output_ports.set_relief(Gtk::RELIEF_NORMAL);
852  _limit_output_ports.set_mode(true);
853  _limit_output_ports.set_sensitive(true);
854  _limit_output_ports.set_border_width(0);
855  _output_limit_count.set_flags(Gtk::CAN_FOCUS);
856  _output_limit_count.set_update_policy(Gtk::UPDATE_ALWAYS);
857  _output_limit_count.set_numeric(false);
858  _output_limit_count.set_digits(0);
859  _output_limit_count.set_wrap(false);
860  _output_limit_count.set_sensitive(false);
861  output_port_limit_hbox.pack_start(_limit_output_ports, Gtk::PACK_SHRINK, 6);
862  output_port_limit_hbox.pack_start(_output_limit_count, Gtk::PACK_SHRINK, 0);
863  output_port_limit_hbox.pack_start(chan_count_label_4, Gtk::PACK_SHRINK, 6);
864 
865  _connect_outputs_to_master.set_label (_("... to master bus"));
866  _connect_outputs_to_master.set_flags(Gtk::CAN_FOCUS);
867  _connect_outputs_to_master.set_relief(Gtk::RELIEF_NORMAL);
868  _connect_outputs_to_master.set_mode(true);
869  _connect_outputs_to_master.set_active(Config->get_output_auto_connect() == AutoConnectMaster);
870  _connect_outputs_to_master.set_border_width(0);
871 
874 
875  _connect_outputs_to_physical.set_label (_("... to physical outputs"));
876  _connect_outputs_to_physical.set_flags(Gtk::CAN_FOCUS);
877  _connect_outputs_to_physical.set_relief(Gtk::RELIEF_NORMAL);
878  _connect_outputs_to_physical.set_mode(true);
879  _connect_outputs_to_physical.set_active(Config->get_output_auto_connect() == AutoConnectPhysical);
880  _connect_outputs_to_physical.set_border_width(0);
881 
882  output_conn_vbox.pack_start(_connect_outputs, Gtk::PACK_SHRINK, 0);
883  output_conn_vbox.pack_start(_connect_outputs_to_master, Gtk::PACK_SHRINK, 0);
884  output_conn_vbox.pack_start(_connect_outputs_to_physical, Gtk::PACK_SHRINK, 0);
885  output_vbox.set_border_width(6);
886 
887  output_port_vbox.pack_start(output_port_limit_hbox, Gtk::PACK_SHRINK, 0);
888 
889  output_vbox.pack_start(output_conn_vbox);
890  output_vbox.pack_start(output_port_vbox);
891 
892  output_label.set_alignment(0, 0.5);
893  output_label.set_padding(0,0);
894  output_label.set_line_wrap(false);
895  output_label.set_selectable(false);
896  output_label.set_use_markup(true);
897  output_frame.set_shadow_type(Gtk::SHADOW_NONE);
898  output_frame.set_label_align(0,0.5);
899 
900  output_hbox.pack_start (output_vbox, Gtk::PACK_SHRINK, 18);
901 
903  output_frame.set_label_widget(output_label);
904 
905  more_options_vbox.pack_start(advanced_table, Gtk::PACK_SHRINK, 0);
906  more_options_vbox.pack_start(bus_frame, Gtk::PACK_SHRINK, 6);
907  more_options_vbox.pack_start(input_frame, Gtk::PACK_SHRINK, 6);
908  more_options_vbox.pack_start(output_frame, Gtk::PACK_SHRINK, 0);
909 
910  /* signals */
911 
912  _connect_inputs.signal_clicked().connect (sigc::mem_fun (*this, &SessionDialog::connect_inputs_clicked));
913  _connect_outputs.signal_clicked().connect (sigc::mem_fun (*this, &SessionDialog::connect_outputs_clicked));
914  _limit_input_ports.signal_clicked().connect (sigc::mem_fun (*this, &SessionDialog::limit_inputs_clicked));
915  _limit_output_ports.signal_clicked().connect (sigc::mem_fun (*this, &SessionDialog::limit_outputs_clicked));
916  _create_master_bus.signal_clicked().connect (sigc::mem_fun (*this, &SessionDialog::master_bus_button_clicked));
917 
918  /* note that more_options_vbox is "visible" by default even
919  * though it may not be displayed to the user, this is so the dialog
920  * doesn't resize.
921  */
922  more_options_vbox.show_all ();
923 }
924 
925 bool
927 {
928  return _create_master_bus.get_active();
929 }
930 
931 int
933 {
934  return _master_bus_channel_count.get_value_as_int();
935 }
936 
937 bool
939 {
940  return _connect_inputs.get_active();
941 }
942 
943 bool
945 {
946  return _limit_input_ports.get_active();
947 }
948 
949 int
951 {
952  return _input_limit_count.get_value_as_int();
953 }
954 
955 bool
957 {
958  return _connect_outputs.get_active();
959 }
960 
961 bool
963 {
964  return _limit_output_ports.get_active();
965 }
966 
967 int
969 {
970  return _output_limit_count.get_value_as_int();
971 }
972 
973 bool
975 {
976  return _connect_outputs_to_master.get_active();
977 }
978 
979 bool
981 {
982  return _connect_outputs_to_physical.get_active();
983 }
984 
985 void
987 {
988  _limit_input_ports.set_sensitive(_connect_inputs.get_active());
989 
990  if (_connect_inputs.get_active() && _limit_input_ports.get_active()) {
991  _input_limit_count.set_sensitive(true);
992  } else {
993  _input_limit_count.set_sensitive(false);
994  }
995 }
996 
997 void
999 {
1000  bool const co = _connect_outputs.get_active ();
1001  _limit_output_ports.set_sensitive(co);
1002  _connect_outputs_to_master.set_sensitive(co);
1003  _connect_outputs_to_physical.set_sensitive(co);
1004 
1005  if (co && _limit_output_ports.get_active()) {
1006  _output_limit_count.set_sensitive(true);
1007  } else {
1008  _output_limit_count.set_sensitive(false);
1009  }
1010 }
1011 
1012 void
1014 {
1015  _input_limit_count.set_sensitive(_limit_input_ports.get_active());
1016 }
1017 
1018 void
1020 {
1021  _output_limit_count.set_sensitive(_limit_output_ports.get_active());
1022 }
1023 
1024 void
1026 {
1027  bool const yn = _create_master_bus.get_active();
1028 
1029  _master_bus_channel_count.set_sensitive(yn);
1030  _connect_outputs_to_master.set_sensitive(yn);
1031 }
1032 
1033 void
1034 SessionDialog::recent_row_activated (const Gtk::TreePath&, Gtk::TreeViewColumn*)
1035 {
1036  response (RESPONSE_ACCEPT);
1037 }
1038 
1039 void
1041 {
1043  recent_session_display.get_selection()->unselect_all();
1044  /* mark this sensitive in case we come back here after a failed open
1045  * attempt and the user has hacked up the fix. sigh.
1046  */
1047  open_button->set_sensitive (true);
1048  response (RESPONSE_ACCEPT);
1049 }
1050 
1051 void
1053 {
1054  //now open a browser window so user can see more
1055  PBD::open_uri (Config->get_updates_url());
1056 }
1057 
1058 bool
1060 {
1062 
1063  char buf[512];
1064  snprintf (buf, std::min(info_scroller_count,sizeof(buf)-1), "%s", ARDOUR_UI::instance()->announce_string().c_str() );
1065  buf[info_scroller_count] = 0;
1066  info_scroller_label.set_text (buf);
1067  info_scroller_label.show();
1068 
1069  if (info_scroller_count > ARDOUR_UI::instance()->announce_string().length()) {
1070  info_scroller_connection.disconnect();
1071  }
1072 
1073  return true;
1074 }
1075 
1076 bool
1078 {
1079  response (RESPONSE_CANCEL);
1080  return ArdourDialog::on_delete_event (ev);
1081 }
1082 
bool use_session_template()
Gtk::Button * open_button
bool limit_inputs_used_for_connection() const
Gtk::ComboBox template_chooser
bool _existing_session_chooser_used
set to true when the existing session chooser has been used
Gtk::TreeModelColumn< std::string > tip
Gtk::TreeModelColumn< std::string > path
Gtk::ScrolledWindow recent_scroller
bool create_master_bus() const
Gtk::Label chan_count_label_1
LIBARDOUR_API std::string legalize_for_path(const std::string &str)
Gtk::Frame bus_frame
std::string _provided_session_name
Gtk::Label chan_count_label_4
Definition: ardour_ui.h:130
static ARDOUR_UI * instance()
Definition: ardour_ui.h:187
void session_selected()
Gtk::Label output_label
bool connect_outs_to_master() const
std::deque< std::pair< std::string, std::string > > RecentSessions
Gtk::Label chan_count_label_3
void new_name_changed()
SessionTemplateColumns session_template_columns
Gtk::Label bus_label
int output_limit_count() const
Definition: Beats.hpp:239
void master_bus_button_clicked()
Gtk::FileChooserButton new_folder_chooser
Gtk::HBox input_port_limit_hbox
Gtk::Label input_label
void connect_inputs_clicked()
Gtk::Frame output_frame
Gtk::Entry new_name_entry
LIBPBD_API void strip_whitespace_edges(std::string &str)
void limit_outputs_clicked()
Gtk::Label info_scroller_label
bool find_file(const Searchpath &search_path, const string &filename, std::string &result)
Definition: file_utils.cc:187
Gtk::VBox input_port_vbox
Gtk::VBox output_port_vbox
void recent_session_row_selected()
SessionDialog(bool require_new, const std::string &session_name, const std::string &session_path, const std::string &template_name, bool cancel_not_quit)
Glib::RefPtr< Gtk::TreeStore > recent_session_model
#define _(Text)
Definition: i18n.h:11
Gtk::SpinButton _input_limit_count
bool connect_outs_to_physical() const
Gtk::FileChooserButton existing_session_chooser
#define X_(Text)
Definition: i18n.h:13
void existing_session_selected()
Gtk::VBox ic_vbox
Gtk::Frame info_frame
bool limit_outputs_used_for_connection() const
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
Gtk::CheckButton _create_master_bus
int input_limit_count() const
Gtk::VBox session_new_vbox
void setup_more_options_box()
Gtk::VBox more_options_vbox
Gtk::SpinButton _output_limit_count
std::string load_template_override
Gtk::Adjustment _output_limit_count_adj
Gtk::TreeModelColumn< std::string > sample_rate
Gtk::TreeModelColumn< std::string > visible_name
Gtk::CheckButton use_template_button
int master_channel_count() const
bool back_button_pressed(GdkEventButton *)
Definition: amp.h:29
LIBARDOUR_API std::string user_template_directory()
Gtk::HBox input_hbox
void recent_row_activated(const Gtk::TreePath &path, Gtk::TreeViewColumn *col)
Gtk::Button * back_button
bool on_delete_event(GdkEventAny *)
void limit_inputs_clicked()
bool connect_outputs() const
Gtk::CheckButton _connect_inputs
Gtk::Label recent_label
Gtk::Button ic_new_session_button
std::string rate_as_string(float r)
Definition: utils.cc:914
void setup_initial_choice_box()
Gtk::RadioButtonGroup connect_outputs_group
LIBPBD_API std::string poor_mans_glob(std::string path)
Definition: strreplace.cc:41
bool connect_inputs() const
Gtk::HBox output_port_limit_hbox
Gtk::Tooltips & tooltips()
Definition: ardour_ui.h:199
Gtk::Table advanced_table
Gtk::Adjustment _master_bus_channel_count_adj
Gtk::Adjustment _input_limit_count_adj
LIBARDOUR_API std::vector< std::string > get_file_names_no_extension(const std::vector< std::string > &file_paths)
std::string _provided_session_path
LIBPBD_API bool open_uri(const char *)
Definition: openuri.cc:41
Gtk::CheckButton _limit_output_ports
Gtk::RadioButton _connect_outputs_to_master
LIBARDOUR_API const char *const statefile_suffix
LIBARDOUR_API const char *const template_suffix
RecentSessionModelColumns recent_session_columns
Gtk::Table input_table
std::string::size_type info_scroller_count
Gtk::Frame input_frame
SampleFormat
Definition: types.h:460
Gtk::RadioButton _connect_outputs_to_physical
LIBARDOUR_API int read_recent_sessions(RecentSessions &rs)
Gtk::HBox output_hbox
Gtk::Table bus_table
LIBARDOUR_API void get_state_files_in_directory(const std::string &directory_path, std::vector< std::string > &result)
Gtk::VBox output_vbox
Gtk::TreeModelColumn< std::string > fullpath
Gtk::Expander more_new_session_options_button
void connect_outputs_clicked()
Gtk::Button * cancel_button
Gtk::VBox output_conn_vbox
int redisplay_recent_sessions()
Definition: debug.h:30
std::string session_name
Definition: opts.cc:34
bool on_delete_event(GdkEventAny *)
sigc::connection info_scroller_connection
void populate_session_templates()
std::string session_folder()
Glib::RefPtr< Gtk::ListStore > template_model
Gtk::TreeView recent_session_display
LIBARDOUR_API void find_session_templates(std::vector< TemplateInfo > &template_names)
void new_name_activated()
Gtk::CheckButton _limit_input_ports
void updates_button_clicked()
LIBARDOUR_API PBD::Searchpath ardour_data_search_path()
Gtk::TreeModelColumn< std::string > disk_format
std::string session_name(bool &should_be_new)
Gtk::SpinButton _master_bus_channel_count
void new_session_button_clicked()
bool info_scroller_update()
void setup_new_session_page()
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
Gtk::HBox bus_hbox
Gtk::TreeModelColumn< std::string > name
Gtk::CheckButton _connect_outputs
LIBARDOUR_API PBD::PropertyDescriptor< framecnt_t > length
Definition: region.cc:64
std::string session_template_name()