ardour
session_state.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 1999-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 
21 #ifdef WAF_BUILD
22 #include "libardour-config.h"
23 #endif
24 
25 #include <stdint.h>
26 
27 #include <algorithm>
28 #include <fstream>
29 #include <string>
30 #include <cerrno>
31 #include <cstdio> /* snprintf(3) ... grrr */
32 #include <cmath>
33 #include <unistd.h>
34 #include <sys/stat.h>
35 #include <climits>
36 #include <signal.h>
37 #include <sys/time.h>
38 
39 #ifdef HAVE_SYS_VFS_H
40 #include <sys/vfs.h>
41 #endif
42 
43 #ifdef __APPLE__
44 #include <sys/param.h>
45 #include <sys/mount.h>
46 #endif
47 
48 #ifdef HAVE_SYS_STATVFS_H
49 #include <sys/statvfs.h>
50 #endif
51 
52 #include <glib.h>
53 #include <glib/gstdio.h>
54 
55 #include <glibmm.h>
56 #include <glibmm/threads.h>
57 #include <glibmm/fileutils.h>
58 
59 #include <boost/algorithm/string.hpp>
60 
61 #include "midi++/mmc.h"
62 #include "midi++/port.h"
63 
64 #include "evoral/SMF.hpp"
65 
66 #include "pbd/boost_debug.h"
67 #include "pbd/basename.h"
69 #include "pbd/enumwriter.h"
70 #include "pbd/error.h"
71 #include "pbd/file_utils.h"
72 #include "pbd/pathexpand.h"
73 #include "pbd/pthread_utils.h"
74 #include "pbd/stacktrace.h"
75 #include "pbd/convert.h"
76 #include "pbd/localtime_r.h"
77 
78 #include "ardour/amp.h"
79 #include "ardour/async_midi_port.h"
81 #include "ardour/audio_track.h"
82 #include "ardour/audioengine.h"
83 #include "ardour/audiofilesource.h"
84 #include "ardour/audioregion.h"
86 #include "ardour/butler.h"
88 #include "ardour/directory_names.h"
90 #include "ardour/graph.h"
91 #include "ardour/location.h"
92 #include "ardour/midi_model.h"
94 #include "ardour/midi_region.h"
96 #include "ardour/midi_source.h"
97 #include "ardour/midi_track.h"
98 #include "ardour/pannable.h"
100 #include "ardour/playlist_source.h"
101 #include "ardour/port.h"
102 #include "ardour/processor.h"
104 #include "ardour/recent_sessions.h"
105 #include "ardour/region_factory.h"
106 #include "ardour/route_group.h"
107 #include "ardour/send.h"
108 #include "ardour/session.h"
110 #include "ardour/session_metadata.h"
113 #include "ardour/silentfilesource.h"
114 #include "ardour/sndfilesource.h"
115 #include "ardour/source_factory.h"
116 #include "ardour/speakers.h"
117 #include "ardour/template_utils.h"
118 #include "ardour/tempo.h"
119 #include "ardour/ticker.h"
120 #include "ardour/user_bundle.h"
121 
122 #include "control_protocol/control_protocol.h"
123 
124 #include "i18n.h"
125 #include <locale.h>
126 
127 using namespace std;
128 using namespace ARDOUR;
129 using namespace PBD;
130 
131 void
132 Session::pre_engine_init (string fullpath)
133 {
134  if (fullpath.empty()) {
135  destroy ();
136  throw failed_constructor();
137  }
138 
139  /* discover canonical fullpath */
140 
141  _path = canonical_path(fullpath);
142 
143  /* is it new ? */
144 
145  _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
146 
147  /* finish initialization that can't be done in a normal C++ constructor
148  definition.
149  */
150 
151  timerclear (&last_mmc_step);
152  g_atomic_int_set (&processing_prohibited, 0);
153  g_atomic_int_set (&_record_status, Disabled);
154  g_atomic_int_set (&_playback_load, 100);
155  g_atomic_int_set (&_capture_load, 100);
156  set_next_event ();
157  _all_route_group->set_active (true, this);
158  interpolation.add_channel_to (0, 0);
159 
160  if (config.get_use_video_sync()) {
161  waiting_for_sync_offset = true;
162  } else {
163  waiting_for_sync_offset = false;
164  }
165 
166  last_rr_session_dir = session_dirs.begin();
167 
168  set_history_depth (Config->get_history_depth());
169 
170  /* default: assume simple stereo speaker configuration */
171 
172  _speakers->setup_default_speakers (2);
173 
174  _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
175  boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
176  boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
177  add_controllable (_solo_cut_control);
178 
179  /* These are all static "per-class" signals */
180 
181  SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
182  PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
183  AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
184  Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
185  IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
186 
187  /* stop IO objects from doing stuff until we're ready for them */
188 
189  Delivery::disable_panners ();
190  IO::disable_connecting ();
191 
192  AudioFileSource::set_peak_dir (_session_dir->peak_path());
193 }
194 
195 int
196 Session::post_engine_init ()
197 {
198  BootMessage (_("Set block size and sample rate"));
199 
200  set_block_size (_engine.samples_per_cycle());
201  set_frame_rate (_engine.sample_rate());
202 
203  BootMessage (_("Using configuration"));
204 
205  _midi_ports = new MidiPortManager;
206 
207  MIDISceneChanger* msc;
208 
209  _scene_changer = msc = new MIDISceneChanger (*this);
210  msc->set_input_port (scene_input_port());
211  msc->set_output_port (scene_out());
212 
213  boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
214  boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
215 
216  setup_midi_machine_control ();
217 
218  if (_butler->start_thread()) {
219  return -1;
220  }
221 
222  if (start_midi_thread ()) {
223  return -1;
224  }
225 
226  setup_click_sounds (0);
227  setup_midi_control ();
228 
229  _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
230  _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
231 
232  try {
233  /* tempo map requires sample rate knowledge */
234 
235  delete _tempo_map;
236  _tempo_map = new TempoMap (_current_frame_rate);
237  _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
238 
239  /* MidiClock requires a tempo map */
240 
241  midi_clock = new MidiClockTicker ();
242  midi_clock->set_session (this);
243 
244  /* crossfades require sample rate knowledge */
245 
246  SndFileSource::setup_standard_crossfades (*this, frame_rate());
247  _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
248 
249  AudioDiskstream::allocate_working_buffers();
250  refresh_disk_space ();
251 
252  /* we're finally ready to call set_state() ... all objects have
253  * been created, the engine is running.
254  */
255 
256  if (state_tree) {
257  if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
258  return -1;
259  }
260  } else {
261  // set_state() will call setup_raid_path(), but if it's a new session we need
262  // to call setup_raid_path() here.
263  setup_raid_path (_path);
264  }
265 
266  /* ENGINE */
267 
268  boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
269  boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
270 
271  Config->map_parameters (ff);
272  config.map_parameters (ft);
273 
274  /* Reset all panners */
275 
276  Delivery::reset_panners ();
277 
278  /* this will cause the CPM to instantiate any protocols that are in use
279  * (or mandatory), which will pass it this Session, and then call
280  * set_state() on each instantiated protocol to match stored state.
281  */
282 
283  ControlProtocolManager::instance().set_session (this);
284 
285  /* This must be done after the ControlProtocolManager set_session above,
286  as it will set states for ports which the ControlProtocolManager creates.
287  */
288 
289  // XXX set state of MIDI::Port's
290  // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
291 
292  /* And this must be done after the MIDI::Manager::set_port_states as
293  * it will try to make connections whose details are loaded by set_port_states.
294  */
295 
296  hookup_io ();
297 
298  /* Let control protocols know that we are now all connected, so they
299  * could start talking to surfaces if they want to.
300  */
301 
302  ControlProtocolManager::instance().midi_connectivity_established ();
303 
304  if (_is_new && !no_auto_connect()) {
305  Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
306  auto_connect_master_bus ();
307  }
308 
309  _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
310 
311  /* update latencies */
312 
313  initialize_latencies ();
314 
315  _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
316  _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
317  _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
318 
319  } catch (AudioEngine::PortRegistrationFailure& err) {
320  /* handle this one in a different way than all others, so that its clear what happened */
321  error << err.what() << endmsg;
322  return -1;
323  } catch (...) {
324  return -1;
325  }
326 
327  BootMessage (_("Reset Remote Controls"));
328 
329  // send_full_time_code (0);
330  _engine.transport_locate (0);
331 
332  send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
333  send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
334 
336 
337  ltc_tx_initialize();
338  /* initial program change will be delivered later; see ::config_changed() */
339 
340  _state_of_the_state = Clean;
341 
342  Port::set_connecting_blocked (false);
343 
344  DirtyChanged (); /* EMIT SIGNAL */
345 
346  if (_is_new) {
347  save_state ("");
348  } else if (state_was_pending) {
349  save_state ("");
350  remove_pending_capture_state ();
351  state_was_pending = false;
352  }
353 
354  return 0;
355 }
356 
357 string
358 Session::raid_path () const
359 {
360  Searchpath raid_search_path;
361 
362  for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
363  raid_search_path += (*i).path;
364  }
365 
366  return raid_search_path.to_string ();
367 }
368 
369 void
370 Session::setup_raid_path (string path)
371 {
372  if (path.empty()) {
373  return;
374  }
375 
376  space_and_path sp;
377  string fspath;
378 
379  session_dirs.clear ();
380 
381  Searchpath search_path(path);
382  Searchpath sound_search_path;
383  Searchpath midi_search_path;
384 
385  for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
386  sp.path = *i;
387  sp.blocks = 0; // not needed
388  session_dirs.push_back (sp);
389 
390  SessionDirectory sdir(sp.path);
391 
392  sound_search_path += sdir.sound_path ();
393  midi_search_path += sdir.midi_path ();
394  }
395 
396  // reset the round-robin soundfile path thingie
397  last_rr_session_dir = session_dirs.begin();
398 }
399 
400 bool
401 Session::path_is_within_session (const std::string& path)
402 {
403  for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
404  if (PBD::path_is_within (i->path, path)) {
405  return true;
406  }
407  }
408  return false;
409 }
410 
411 int
412 Session::ensure_subdirs ()
413 {
414  string dir;
415 
416  dir = session_directory().peak_path();
417 
418  if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
419  error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
420  return -1;
421  }
422 
423  dir = session_directory().sound_path();
424 
425  if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
426  error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
427  return -1;
428  }
429 
430  dir = session_directory().midi_path();
431 
432  if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
433  error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
434  return -1;
435  }
436 
437  dir = session_directory().dead_path();
438 
439  if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
440  error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
441  return -1;
442  }
443 
444  dir = session_directory().export_path();
445 
446  if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
447  error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
448  return -1;
449  }
450 
451  dir = analysis_dir ();
452 
453  if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
454  error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
455  return -1;
456  }
457 
458  dir = plugins_dir ();
459 
460  if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
461  error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
462  return -1;
463  }
464 
465  dir = externals_dir ();
466 
467  if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
468  error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
469  return -1;
470  }
471 
472  return 0;
473 }
474 
478 int
479 Session::create (const string& session_template, BusProfile* bus_profile)
480 {
481  if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
482  error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
483  return -1;
484  }
485 
486  if (ensure_subdirs ()) {
487  return -1;
488  }
489 
490  _writable = exists_and_writable (_path);
491 
492  if (!session_template.empty()) {
493  std::string in_path = session_template_dir_to_file (session_template);
494 
495  ifstream in(in_path.c_str());
496 
497  if (in) {
498  /* no need to call legalize_for_path() since the string
499  * in session_template is already a legal path name
500  */
501  string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
502 
503  ofstream out(out_path.c_str());
504 
505  if (out) {
506  out << in.rdbuf();
507  _is_new = false;
508 
509  /* Copy plugin state files from template to new session */
510  std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
511  copy_recurse (template_plugins, plugins_dir ());
512 
513  return 0;
514 
515  } else {
516  error << string_compose (_("Could not open %1 for writing session template"), out_path)
517  << endmsg;
518  return -1;
519  }
520 
521  } else {
522  error << string_compose (_("Could not open session template %1 for reading"), in_path)
523  << endmsg;
524  return -1;
525  }
526 
527  }
528 
529  /* set initial start + end point */
530 
531  _state_of_the_state = Clean;
532 
533  /* set up Master Out and Control Out if necessary */
534 
535  if (bus_profile) {
536 
537  RouteList rl;
538  ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
539 
540  if (bus_profile->master_out_channels) {
541  boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
542  if (r->init ()) {
543  return -1;
544  }
545 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
546  // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
547 #endif
548  {
549  Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
550  r->input()->ensure_io (count, false, this);
551  r->output()->ensure_io (count, false, this);
552  }
553 
554  rl.push_back (r);
555 
556  } else {
557  /* prohibit auto-connect to master, because there isn't one */
558  bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
559  }
560 
561  if (!rl.empty()) {
562  add_routes (rl, false, false, false);
563  }
564 
565  /* this allows the user to override settings with an environment variable.
566  */
567 
568  if (no_auto_connect()) {
569  bus_profile->input_ac = AutoConnectOption (0);
570  bus_profile->output_ac = AutoConnectOption (0);
571  }
572 
573  Config->set_input_auto_connect (bus_profile->input_ac);
574  Config->set_output_auto_connect (bus_profile->output_ac);
575  }
576 
577  if (Config->get_use_monitor_bus() && bus_profile) {
578  add_monitor_section ();
579  }
580 
581  return 0;
582 }
583 
584 void
585 Session::maybe_write_autosave()
586 {
587  if (dirty() && record_status() != Recording) {
588  save_state("", true);
589  }
590 }
591 
592 void
593 Session::remove_pending_capture_state ()
594 {
595  std::string pending_state_file_path(_session_dir->root_path());
596 
597  pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
598 
599  if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
600 
601  if (g_remove (pending_state_file_path.c_str()) != 0) {
602  error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
603  pending_state_file_path, g_strerror (errno)) << endmsg;
604  }
605 }
606 
611 void
612 Session::rename_state (string old_name, string new_name)
613 {
614  if (old_name == _current_snapshot_name || old_name == _name) {
615  /* refuse to rename the current snapshot or the "main" one */
616  return;
617  }
618 
619  const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
620  const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
621 
622  const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
623  const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
624 
625  if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
626  error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
627  old_name, new_name, g_strerror(errno)) << endmsg;
628  }
629 }
630 
634 void
635 Session::remove_state (string snapshot_name)
636 {
637  if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
638  // refuse to remove the current snapshot or the "main" one
639  return;
640  }
641 
642  std::string xml_path(_session_dir->root_path());
643 
644  xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
645 
646  if (!create_backup_file (xml_path)) {
647  // don't remove it if a backup can't be made
648  // create_backup_file will log the error.
649  return;
650  }
651 
652  // and delete it
653  if (g_remove (xml_path.c_str()) != 0) {
654  error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
655  xml_path, g_strerror (errno)) << endmsg;
656  }
657 }
658 
660 int
661 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
662 {
663  XMLTree tree;
664  std::string xml_path(_session_dir->root_path());
665 
666  /* prevent concurrent saves from different threads */
667 
668  Glib::Threads::Mutex::Lock lm (save_state_lock);
669 
670  if (!_writable || (_state_of_the_state & CannotSave)) {
671  return 1;
672  }
673 
674  if (g_atomic_int_get(&_suspend_save)) {
675  _save_queued = true;
676  return 1;
677  }
678  _save_queued = false;
679 
680  if (!_engine.connected ()) {
681  error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
682  PROGRAM_NAME)
683  << endmsg;
684  return 1;
685  }
686 
687  /* tell sources we're saving first, in case they write out to a new file
688  * which should be saved with the state rather than the old one */
689  for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
690  try {
691  i->second->session_saved();
692  } catch (Evoral::SMF::FileError& e) {
693  error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
694  }
695  }
696 
697  SessionSaveUnderway (); /* EMIT SIGNAL */
698 
699  if (template_only) {
700  tree.set_root (&get_template());
701  } else {
702  tree.set_root (&get_state());
703  }
704 
705  if (snapshot_name.empty()) {
706  snapshot_name = _current_snapshot_name;
707  } else if (switch_to_snapshot) {
708  _current_snapshot_name = snapshot_name;
709  }
710 
711  if (!pending) {
712 
713  /* proper save: use statefile_suffix (.ardour in English) */
714 
715  xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
716 
717  /* make a backup copy of the old file */
718 
719  if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
720  // create_backup_file will log the error
721  return -1;
722  }
723 
724  } else {
725 
726  /* pending save: use pending_suffix (.pending in English) */
727  xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
728  }
729 
730  std::string tmp_path(_session_dir->root_path());
731  tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
732 
733  cerr << "actually writing state to " << tmp_path << endl;
734 
735  if (!tree.write (tmp_path)) {
736  error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
737  if (g_remove (tmp_path.c_str()) != 0) {
738  error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
739  tmp_path, g_strerror (errno)) << endmsg;
740  }
741  return -1;
742 
743  } else {
744 
745  cerr << "renaming state to " << xml_path << endl;
746 
747  if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
748  error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
749  tmp_path, xml_path, g_strerror(errno)) << endmsg;
750  if (g_remove (tmp_path.c_str()) != 0) {
751  error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
752  tmp_path, g_strerror (errno)) << endmsg;
753  }
754  return -1;
755  }
756  }
757 
758  if (!pending) {
759 
760  save_history (snapshot_name);
761 
762  bool was_dirty = dirty();
763 
764  _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
765 
766  if (was_dirty) {
767  DirtyChanged (); /* EMIT SIGNAL */
768  }
769 
770  StateSaved (snapshot_name); /* EMIT SIGNAL */
771  }
772 
773  return 0;
774 }
775 
776 int
777 Session::restore_state (string snapshot_name)
778 {
779  if (load_state (snapshot_name) == 0) {
780  set_state (*state_tree->root(), Stateful::loading_state_version);
781  }
782 
783  return 0;
784 }
785 
786 int
787 Session::load_state (string snapshot_name)
788 {
789  delete state_tree;
790  state_tree = 0;
791 
792  state_was_pending = false;
793 
794  /* check for leftover pending state from a crashed capture attempt */
795 
796  std::string xmlpath(_session_dir->root_path());
797  xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
798 
799  if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
800 
801  /* there is pending state from a crashed capture attempt */
802 
803  boost::optional<int> r = AskAboutPendingState();
804  if (r.get_value_or (1)) {
805  state_was_pending = true;
806  }
807  }
808 
809  if (!state_was_pending) {
810  xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
811  }
812 
813  if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
814  xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
815  if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
816  error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
817  return 1;
818  }
819  }
820 
821  state_tree = new XMLTree;
822 
823  set_dirty();
824 
825  _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
826 
827  if (!state_tree->read (xmlpath)) {
828  error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
829  delete state_tree;
830  state_tree = 0;
831  return -1;
832  }
833 
834  XMLNode& root (*state_tree->root());
835 
836  if (root.name() != X_("Session")) {
837  error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
838  delete state_tree;
839  state_tree = 0;
840  return -1;
841  }
842 
843  const XMLProperty* prop;
844 
845  if ((prop = root.property ("version")) == 0) {
846  /* no version implies very old version of Ardour */
847  Stateful::loading_state_version = 1000;
848  } else {
849  if (prop->value().find ('.') != string::npos) {
850  /* old school version format */
851  if (prop->value()[0] == '2') {
852  Stateful::loading_state_version = 2000;
853  } else {
854  Stateful::loading_state_version = 3000;
855  }
856  } else {
857  Stateful::loading_state_version = atoi (prop->value());
858  }
859  }
860 
861  if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
862 
863  std::string backup_path(_session_dir->root_path());
864  std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
865  backup_path = Glib::build_filename (backup_path, backup_filename);
866 
867  // only create a backup for a given statefile version once
868 
869  if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
870 
871  VersionMismatch (xmlpath, backup_path);
872 
873  if (!copy_file (xmlpath, backup_path)) {;
874  return -1;
875  }
876  }
877  }
878 
879  return 0;
880 }
881 
882 int
883 Session::load_options (const XMLNode& node)
884 {
885  LocaleGuard lg (X_("C"));
886  config.set_variables (node);
887  return 0;
888 }
889 
890 bool
891 Session::save_default_options ()
892 {
893  return config.save_state();
894 }
895 
896 XMLNode&
897 Session::get_state()
898 {
899  return state(true);
900 }
901 
902 XMLNode&
903 Session::get_template()
904 {
905  /* if we don't disable rec-enable, diskstreams
906  will believe they need to store their capture
907  sources in their state node.
908  */
909 
910  disable_record (false);
911 
912  return state(false);
913 }
914 
915 XMLNode&
916 Session::state (bool full_state)
917 {
918  XMLNode* node = new XMLNode("Session");
919  XMLNode* child;
920 
921  char buf[16];
922  snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
923  node->add_property("version", buf);
924 
925  /* store configuration settings */
926 
927  if (full_state) {
928 
929  node->add_property ("name", _name);
930  snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
931  node->add_property ("sample-rate", buf);
932 
933  if (session_dirs.size() > 1) {
934 
935  string p;
936 
937  vector<space_and_path>::iterator i = session_dirs.begin();
938  vector<space_and_path>::iterator next;
939 
940  ++i; /* skip the first one */
941  next = i;
942  ++next;
943 
944  while (i != session_dirs.end()) {
945 
946  p += (*i).path;
947 
948  if (next != session_dirs.end()) {
949  p += G_SEARCHPATH_SEPARATOR;
950  } else {
951  break;
952  }
953 
954  ++next;
955  ++i;
956  }
957 
958  child = node->add_child ("Path");
959  child->add_content (p);
960  }
961  }
962 
963  /* save the ID counter */
964 
965  snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
966  node->add_property ("id-counter", buf);
967 
968  /* save the event ID counter */
969 
970  snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
971  node->add_property ("event-counter", buf);
972 
973  /* various options */
974 
975  list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
976  if (!midi_port_nodes.empty()) {
977  XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
978  for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
979  midi_port_stuff->add_child_nocopy (**n);
980  }
981  node->add_child_nocopy (*midi_port_stuff);
982  }
983 
984  node->add_child_nocopy (config.get_variables ());
985 
987 
988  child = node->add_child ("Sources");
989 
990  if (full_state) {
991  Glib::Threads::Mutex::Lock sl (source_lock);
992 
993  for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
994 
995  /* Don't save information about non-file Sources, or
996  * about non-destructive file sources that are empty
997  * and unused by any regions.
998  */
999 
1001 
1002  if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1003 
1004  if (!fs->destructive()) {
1005  if (fs->empty() && !fs->used()) {
1006  continue;
1007  }
1008  }
1009 
1010  child->add_child_nocopy (siter->second->get_state());
1011  }
1012  }
1013  }
1014 
1015  child = node->add_child ("Regions");
1016 
1017  if (full_state) {
1018  Glib::Threads::Mutex::Lock rl (region_lock);
1019  const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1020  for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1021  boost::shared_ptr<Region> r = i->second;
1022  /* only store regions not attached to playlists */
1023  if (r->playlist() == 0) {
1024  if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1025  child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1026  } else {
1027  child->add_child_nocopy (r->get_state ());
1028  }
1029  }
1030  }
1031 
1032  RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1033 
1034  if (!cassocs.empty()) {
1035  XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1036 
1037  for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1038  char buf[64];
1039  XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1040  i->first->id().print (buf, sizeof (buf));
1041  can->add_property (X_("copy"), buf);
1042  i->second->id().print (buf, sizeof (buf));
1043  can->add_property (X_("original"), buf);
1044  ca->add_child_nocopy (*can);
1045  }
1046  }
1047  }
1048 
1049  if (full_state) {
1050  node->add_child_nocopy (_locations->get_state());
1051  } else {
1052  // for a template, just create a new Locations, populate it
1053  // with the default start and end, and get the state for that.
1054  Locations loc (*this);
1055  Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1056  range->set (max_framepos, 0);
1057  loc.add (range);
1058  node->add_child_nocopy (loc.get_state());
1059  }
1060 
1061  child = node->add_child ("Bundles");
1062  {
1063  boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1064  for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1066  if (b) {
1067  child->add_child_nocopy (b->get_state());
1068  }
1069  }
1070  }
1071 
1072  child = node->add_child ("Routes");
1073  {
1074  boost::shared_ptr<RouteList> r = routes.reader ();
1075 
1077  RouteList public_order (*r);
1078  public_order.sort (cmp);
1079 
1080  /* the sort should have put control outs first */
1081 
1082  if (_monitor_out) {
1083  assert (_monitor_out == public_order.front());
1084  }
1085 
1086  for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1087  if (!(*i)->is_auditioner()) {
1088  if (full_state) {
1089  child->add_child_nocopy ((*i)->get_state());
1090  } else {
1091  child->add_child_nocopy ((*i)->get_template());
1092  }
1093  }
1094  }
1095  }
1096 
1097  playlists->add_state (node, full_state);
1098 
1099  child = node->add_child ("RouteGroups");
1100  for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1101  child->add_child_nocopy ((*i)->get_state());
1102  }
1103 
1104  if (_click_io) {
1105  XMLNode* gain_child = node->add_child ("Click");
1106  gain_child->add_child_nocopy (_click_io->state (full_state));
1107  gain_child->add_child_nocopy (_click_gain->state (full_state));
1108  }
1109 
1110  if (_ltc_input) {
1111  XMLNode* ltc_input_child = node->add_child ("LTC-In");
1112  ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1113  }
1114 
1115  if (_ltc_input) {
1116  XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1117  ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1118  }
1119 
1120  node->add_child_nocopy (_speakers->get_state());
1121  node->add_child_nocopy (_tempo_map->get_state());
1122  node->add_child_nocopy (get_control_protocol_state());
1123 
1124  if (_extra_xml) {
1125  node->add_child_copy (*_extra_xml);
1126  }
1127 
1128  return *node;
1129 }
1130 
1131 XMLNode&
1132 Session::get_control_protocol_state ()
1133 {
1134  ControlProtocolManager& cpm (ControlProtocolManager::instance());
1135  return cpm.get_state();
1136 }
1137 
1138 int
1139 Session::set_state (const XMLNode& node, int version)
1140 {
1141  XMLNodeList nlist;
1142  XMLNode* child;
1143  const XMLProperty* prop;
1144  int ret = -1;
1145 
1146  _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1147 
1148  if (node.name() != X_("Session")) {
1149  fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1150  goto out;
1151  }
1152 
1153  if ((prop = node.property ("name")) != 0) {
1154  _name = prop->value ();
1155  }
1156 
1157  if ((prop = node.property (X_("sample-rate"))) != 0) {
1158 
1159  _nominal_frame_rate = atoi (prop->value());
1160 
1161  if (_nominal_frame_rate != _current_frame_rate) {
1162  boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1163  if (r.get_value_or (0)) {
1164  goto out;
1165  }
1166  }
1167  }
1168 
1169  setup_raid_path(_session_dir->root_path());
1170 
1171  if ((prop = node.property (X_("id-counter"))) != 0) {
1172  uint64_t x;
1173  sscanf (prop->value().c_str(), "%" PRIu64, &x);
1174  ID::init_counter (x);
1175  } else {
1176  /* old sessions used a timebased counter, so fake
1177  the startup ID counter based on a standard
1178  timestamp.
1179  */
1180  time_t now;
1181  time (&now);
1182  ID::init_counter (now);
1183  }
1184 
1185  if ((prop = node.property (X_("event-counter"))) != 0) {
1187  }
1188 
1189 
1190  if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1191  _midi_ports->set_midi_port_states (child->children());
1192  }
1193 
1194  IO::disable_connecting ();
1195 
1196  Stateful::save_extra_xml (node);
1197 
1198  if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1199  load_options (*child);
1200  } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1201  load_options (*child);
1202  } else {
1203  error << _("Session: XML state has no options section") << endmsg;
1204  }
1205 
1206  if (version >= 3000) {
1207  if ((child = find_named_node (node, "Metadata")) == 0) {
1208  warning << _("Session: XML state has no metadata section") << endmsg;
1209  } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1210  goto out;
1211  }
1212  }
1213 
1214  if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1215  _speakers->set_state (*child, version);
1216  }
1217 
1218  if ((child = find_named_node (node, "Sources")) == 0) {
1219  error << _("Session: XML state has no sources section") << endmsg;
1220  goto out;
1221  } else if (load_sources (*child)) {
1222  goto out;
1223  }
1224 
1225  if ((child = find_named_node (node, "TempoMap")) == 0) {
1226  error << _("Session: XML state has no Tempo Map section") << endmsg;
1227  goto out;
1228  } else if (_tempo_map->set_state (*child, version)) {
1229  goto out;
1230  }
1231 
1232  if ((child = find_named_node (node, "Locations")) == 0) {
1233  error << _("Session: XML state has no locations section") << endmsg;
1234  goto out;
1235  } else if (_locations->set_state (*child, version)) {
1236  goto out;
1237  }
1238 
1239  locations_changed ();
1240 
1241  if (_session_range_location) {
1242  AudioFileSource::set_header_position_offset (_session_range_location->start());
1243  }
1244 
1245  if ((child = find_named_node (node, "Regions")) == 0) {
1246  error << _("Session: XML state has no Regions section") << endmsg;
1247  goto out;
1248  } else if (load_regions (*child)) {
1249  goto out;
1250  }
1251 
1252  if ((child = find_named_node (node, "Playlists")) == 0) {
1253  error << _("Session: XML state has no playlists section") << endmsg;
1254  goto out;
1255  } else if (playlists->load (*this, *child)) {
1256  goto out;
1257  }
1258 
1259  if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1260  // this is OK
1261  } else if (playlists->load_unused (*this, *child)) {
1262  goto out;
1263  }
1264 
1265  if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1266  if (load_compounds (*child)) {
1267  goto out;
1268  }
1269  }
1270 
1271  if (version >= 3000) {
1272  if ((child = find_named_node (node, "Bundles")) == 0) {
1273  warning << _("Session: XML state has no bundles section") << endmsg;
1274  //goto out;
1275  } else {
1276  /* We can't load Bundles yet as they need to be able
1277  to convert from port names to Port objects, which can't happen until
1278  later */
1279  _bundle_xml_node = new XMLNode (*child);
1280  }
1281  }
1282 
1283  if (version < 3000) {
1284  if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1285  error << _("Session: XML state has no diskstreams section") << endmsg;
1286  goto out;
1287  } else if (load_diskstreams_2X (*child, version)) {
1288  goto out;
1289  }
1290  }
1291 
1292  if ((child = find_named_node (node, "Routes")) == 0) {
1293  error << _("Session: XML state has no routes section") << endmsg;
1294  goto out;
1295  } else if (load_routes (*child, version)) {
1296  goto out;
1297  }
1298 
1299  /* our diskstreams list is no longer needed as they are now all owned by their Route */
1300  _diskstreams_2X.clear ();
1301 
1302  if (version >= 3000) {
1303 
1304  if ((child = find_named_node (node, "RouteGroups")) == 0) {
1305  error << _("Session: XML state has no route groups section") << endmsg;
1306  goto out;
1307  } else if (load_route_groups (*child, version)) {
1308  goto out;
1309  }
1310 
1311  } else if (version < 3000) {
1312 
1313  if ((child = find_named_node (node, "EditGroups")) == 0) {
1314  error << _("Session: XML state has no edit groups section") << endmsg;
1315  goto out;
1316  } else if (load_route_groups (*child, version)) {
1317  goto out;
1318  }
1319 
1320  if ((child = find_named_node (node, "MixGroups")) == 0) {
1321  error << _("Session: XML state has no mix groups section") << endmsg;
1322  goto out;
1323  } else if (load_route_groups (*child, version)) {
1324  goto out;
1325  }
1326  }
1327 
1328  if ((child = find_named_node (node, "Click")) == 0) {
1329  warning << _("Session: XML state has no click section") << endmsg;
1330  } else if (_click_io) {
1331  setup_click_state (&node);
1332  }
1333 
1334  if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1335  ControlProtocolManager::instance().set_state (*child, version);
1336  }
1337 
1338  update_have_rec_enabled_track ();
1339 
1340  /* here beginneth the second phase ... */
1341 
1342  StateReady (); /* EMIT SIGNAL */
1343 
1344  delete state_tree;
1345  state_tree = 0;
1346  return 0;
1347 
1348  out:
1349  delete state_tree;
1350  state_tree = 0;
1351  return ret;
1352 }
1353 
1354 int
1355 Session::load_routes (const XMLNode& node, int version)
1356 {
1357  XMLNodeList nlist;
1358  XMLNodeConstIterator niter;
1359  RouteList new_routes;
1360 
1361  nlist = node.children();
1362 
1363  set_dirty();
1364 
1365  for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1366 
1368  if (version < 3000) {
1369  route = XMLRouteFactory_2X (**niter, version);
1370  } else {
1371  route = XMLRouteFactory (**niter, version);
1372  }
1373 
1374  if (route == 0) {
1375  error << _("Session: cannot create Route from XML description.") << endmsg;
1376  return -1;
1377  }
1378 
1379  BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1380 
1381  new_routes.push_back (route);
1382  }
1383 
1384  BootMessage (_("Tracks/busses loaded; Adding to Session"));
1385 
1386  add_routes (new_routes, false, false, false);
1387 
1388  BootMessage (_("Finished adding tracks/busses"));
1389 
1390  return 0;
1391 }
1392 
1394 Session::XMLRouteFactory (const XMLNode& node, int version)
1395 {
1397 
1398  if (node.name() != "Route") {
1399  return ret;
1400  }
1401 
1402  XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1403 
1404  DataType type = DataType::AUDIO;
1405  const XMLProperty* prop = node.property("default-type");
1406 
1407  if (prop) {
1408  type = DataType (prop->value());
1409  }
1410 
1411  assert (type != DataType::NIL);
1412 
1413  if (ds_child) {
1414 
1416 
1417  if (type == DataType::AUDIO) {
1418  track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1419  } else {
1420  track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1421  }
1422 
1423  if (track->init()) {
1424  return ret;
1425  }
1426 
1427  if (track->set_state (node, version)) {
1428  return ret;
1429  }
1430 
1431 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1432  // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1433 #endif
1434  ret = track;
1435 
1436  } else {
1437  enum Route::Flag flags = Route::Flag(0);
1438  const XMLProperty* prop = node.property("flags");
1439  if (prop) {
1440  flags = Route::Flag (string_2_enum (prop->value(), flags));
1441  }
1442 
1443  boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1444 
1445  if (r->init () == 0 && r->set_state (node, version) == 0) {
1446 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1447  // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1448 #endif
1449  ret = r;
1450  }
1451  }
1452 
1453  return ret;
1454 }
1455 
1457 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1458 {
1460 
1461  if (node.name() != "Route") {
1462  return ret;
1463  }
1464 
1465  XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1466  if (!ds_prop) {
1467  ds_prop = node.property (X_("diskstream"));
1468  }
1469 
1470  DataType type = DataType::AUDIO;
1471  const XMLProperty* prop = node.property("default-type");
1472 
1473  if (prop) {
1474  type = DataType (prop->value());
1475  }
1476 
1477  assert (type != DataType::NIL);
1478 
1479  if (ds_prop) {
1480 
1481  list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1482  while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1483  ++i;
1484  }
1485 
1486  if (i == _diskstreams_2X.end()) {
1487  error << _("Could not find diskstream for route") << endmsg;
1488  return boost::shared_ptr<Route> ();
1489  }
1490 
1492 
1493  if (type == DataType::AUDIO) {
1494  track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1495  } else {
1496  track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1497  }
1498 
1499  if (track->init()) {
1500  return ret;
1501  }
1502 
1503  if (track->set_state (node, version)) {
1504  return ret;
1505  }
1506 
1507  track->set_diskstream (*i);
1508 
1509 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1510  // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1511 #endif
1512  ret = track;
1513 
1514  } else {
1515  enum Route::Flag flags = Route::Flag(0);
1516  const XMLProperty* prop = node.property("flags");
1517  if (prop) {
1518  flags = Route::Flag (string_2_enum (prop->value(), flags));
1519  }
1520 
1521  boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1522 
1523  if (r->init () == 0 && r->set_state (node, version) == 0) {
1524 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1525  // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1526 #endif
1527  ret = r;
1528  }
1529  }
1530 
1531  return ret;
1532 }
1533 
1534 int
1535 Session::load_regions (const XMLNode& node)
1536 {
1537  XMLNodeList nlist;
1538  XMLNodeConstIterator niter;
1540 
1541  nlist = node.children();
1542 
1543  set_dirty();
1544 
1545  for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1546  if ((region = XMLRegionFactory (**niter, false)) == 0) {
1547  error << _("Session: cannot create Region from XML description.");
1548  const XMLProperty *name = (**niter).property("name");
1549 
1550  if (name) {
1551  error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1552  }
1553 
1554  error << endmsg;
1555  }
1556  }
1557 
1558  return 0;
1559 }
1560 
1561 int
1562 Session::load_compounds (const XMLNode& node)
1563 {
1564  XMLNodeList calist = node.children();
1565  XMLNodeConstIterator caiter;
1566  XMLProperty *caprop;
1567 
1568  for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1569  XMLNode* ca = *caiter;
1570  ID orig_id;
1571  ID copy_id;
1572 
1573  if ((caprop = ca->property (X_("original"))) == 0) {
1574  continue;
1575  }
1576  orig_id = caprop->value();
1577 
1578  if ((caprop = ca->property (X_("copy"))) == 0) {
1579  continue;
1580  }
1581  copy_id = caprop->value();
1582 
1583  boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1584  boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1585 
1586  if (!orig || !copy) {
1587  warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1588  orig_id, copy_id)
1589  << endmsg;
1590  continue;
1591  }
1592 
1593  RegionFactory::add_compound_association (orig, copy);
1594  }
1595 
1596  return 0;
1597 }
1598 
1599 void
1600 Session::load_nested_sources (const XMLNode& node)
1601 {
1602  XMLNodeList nlist;
1603  XMLNodeConstIterator niter;
1604 
1605  nlist = node.children();
1606 
1607  for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1608  if ((*niter)->name() == "Source") {
1609 
1610  /* it may already exist, so don't recreate it unnecessarily
1611  */
1612 
1613  XMLProperty* prop = (*niter)->property (X_("id"));
1614  if (!prop) {
1615  error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1616  continue;
1617  }
1618 
1619  ID source_id (prop->value());
1620 
1621  if (!source_by_id (source_id)) {
1622 
1623  try {
1624  SourceFactory::create (*this, **niter, true);
1625  }
1626  catch (failed_constructor& err) {
1627  error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1628  }
1629  }
1630  }
1631  }
1632 }
1633 
1635 Session::XMLRegionFactory (const XMLNode& node, bool full)
1636 {
1637  const XMLProperty* type = node.property("type");
1638 
1639  try {
1640 
1641  const XMLNodeList& nlist = node.children();
1642 
1643  for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1644  XMLNode *child = (*niter);
1645  if (child->name() == "NestedSource") {
1646  load_nested_sources (*child);
1647  }
1648  }
1649 
1650  if (!type || type->value() == "audio") {
1651  return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1652  } else if (type->value() == "midi") {
1653  return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1654  }
1655 
1656  } catch (failed_constructor& err) {
1657  return boost::shared_ptr<Region> ();
1658  }
1659 
1660  return boost::shared_ptr<Region> ();
1661 }
1662 
1664 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1665 {
1666  const XMLProperty* prop;
1669  SourceList sources;
1670  SourceList master_sources;
1671  uint32_t nchans = 1;
1672  char buf[128];
1673 
1674  if (node.name() != X_("Region")) {
1676  }
1677 
1678  if ((prop = node.property (X_("channels"))) != 0) {
1679  nchans = atoi (prop->value().c_str());
1680  }
1681 
1682  if ((prop = node.property ("name")) == 0) {
1683  cerr << "no name for this region\n";
1684  abort ();
1685  }
1686 
1687  if ((prop = node.property (X_("source-0"))) == 0) {
1688  if ((prop = node.property ("source")) == 0) {
1689  error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1691  }
1692  }
1693 
1694  PBD::ID s_id (prop->value());
1695 
1696  if ((source = source_by_id (s_id)) == 0) {
1697  error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1699  }
1700 
1702  if (!as) {
1703  error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1705  }
1706 
1707  sources.push_back (as);
1708 
1709  /* pickup other channels */
1710 
1711  for (uint32_t n=1; n < nchans; ++n) {
1712  snprintf (buf, sizeof(buf), X_("source-%d"), n);
1713  if ((prop = node.property (buf)) != 0) {
1714 
1715  PBD::ID id2 (prop->value());
1716 
1717  if ((source = source_by_id (id2)) == 0) {
1718  error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1720  }
1721 
1723  if (!as) {
1724  error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1726  }
1727  sources.push_back (as);
1728  }
1729  }
1730 
1731  for (uint32_t n = 0; n < nchans; ++n) {
1732  snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1733  if ((prop = node.property (buf)) != 0) {
1734 
1735  PBD::ID id2 (prop->value());
1736 
1737  if ((source = source_by_id (id2)) == 0) {
1738  error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1740  }
1741 
1743  if (!as) {
1744  error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1746  }
1747  master_sources.push_back (as);
1748  }
1749  }
1750 
1751  try {
1752  boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1753 
1754  /* a final detail: this is the one and only place that we know how long missing files are */
1755 
1756  if (region->whole_file()) {
1757  for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1759  if (sfp) {
1760  sfp->set_length (region->length());
1761  }
1762  }
1763  }
1764 
1765  if (!master_sources.empty()) {
1766  if (master_sources.size() != nchans) {
1767  error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1768  } else {
1769  region->set_master_sources (master_sources);
1770  }
1771  }
1772 
1773  return region;
1774 
1775  }
1776 
1777  catch (failed_constructor& err) {
1779  }
1780 }
1781 
1783 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1784 {
1785  const XMLProperty* prop;
1788  SourceList sources;
1789 
1790  if (node.name() != X_("Region")) {
1792  }
1793 
1794  if ((prop = node.property ("name")) == 0) {
1795  cerr << "no name for this region\n";
1796  abort ();
1797  }
1798 
1799  if ((prop = node.property (X_("source-0"))) == 0) {
1800  if ((prop = node.property ("source")) == 0) {
1801  error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1803  }
1804  }
1805 
1806  PBD::ID s_id (prop->value());
1807 
1808  if ((source = source_by_id (s_id)) == 0) {
1809  error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1811  }
1812 
1814  if (!ms) {
1815  error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1817  }
1818 
1819  sources.push_back (ms);
1820 
1821  try {
1822  boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1823  /* a final detail: this is the one and only place that we know how long missing files are */
1824 
1825  if (region->whole_file()) {
1826  for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1828  if (sfp) {
1829  sfp->set_length (region->length());
1830  }
1831  }
1832  }
1833 
1834  return region;
1835  }
1836 
1837  catch (failed_constructor& err) {
1839  }
1840 }
1841 
1842 XMLNode&
1843 Session::get_sources_as_xml ()
1844 
1845 {
1846  XMLNode* node = new XMLNode (X_("Sources"));
1847  Glib::Threads::Mutex::Lock lm (source_lock);
1848 
1849  for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1850  node->add_child_nocopy (i->second->get_state());
1851  }
1852 
1853  return *node;
1854 }
1855 
1856 void
1857 Session::reset_write_sources (bool mark_write_complete, bool force)
1858 {
1859  boost::shared_ptr<RouteList> rl = routes.reader();
1860  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1862  if (tr) {
1863 
1864  // block state saving
1865  _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
1866  tr->reset_write_sources(mark_write_complete, force);
1867  _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1868  }
1869  }
1870 }
1871 
1872 int
1873 Session::load_sources (const XMLNode& node)
1874 {
1875  XMLNodeList nlist;
1876  XMLNodeConstIterator niter;
1877  boost::shared_ptr<Source> source; /* don't need this but it stops some
1878  * versions of gcc complaining about
1879  * discarded return values.
1880  */
1881 
1882  nlist = node.children();
1883 
1884  set_dirty();
1885 
1886  for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1887  retry:
1888  try {
1889  if ((source = XMLSourceFactory (**niter)) == 0) {
1890  error << _("Session: cannot create Source from XML description.") << endmsg;
1891  }
1892 
1893  } catch (MissingSource& err) {
1894 
1895  int user_choice;
1896 
1897  if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
1898  error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
1899  PROGRAM_NAME) << endmsg;
1900  return -1;
1901  }
1902 
1903  if (!no_questions_about_missing_files) {
1904  user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1905  } else {
1906  user_choice = -2;
1907  }
1908 
1909  switch (user_choice) {
1910  case 0:
1911  /* user added a new search location, so try again */
1912  goto retry;
1913 
1914 
1915  case 1:
1916  /* user asked to quit the entire session load
1917  */
1918  return -1;
1919 
1920  case 2:
1921  no_questions_about_missing_files = true;
1922  goto retry;
1923 
1924  case 3:
1925  no_questions_about_missing_files = true;
1926  /* fallthru */
1927 
1928  case -1:
1929  default:
1930  switch (err.type) {
1931 
1932  case DataType::AUDIO:
1933  source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1934  break;
1935 
1936  case DataType::MIDI:
1937  /* The MIDI file is actually missing so
1938  * just create a new one in the same
1939  * location. Do not announce its
1940  */
1941  string fullpath;
1942 
1943  if (!Glib::path_is_absolute (err.path)) {
1944  fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
1945  } else {
1946  /* this should be an unrecoverable error: we would be creating a MIDI file outside
1947  the session tree.
1948  */
1949  return -1;
1950  }
1951  /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
1952  source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
1953  /* reset ID to match the missing one */
1954  source->set_id (**niter);
1955  /* Now we can announce it */
1956  SourceFactory::SourceCreated (source);
1957  break;
1958  }
1959  break;
1960  }
1961  }
1962  }
1963 
1964  return 0;
1965 }
1966 
1968 Session::XMLSourceFactory (const XMLNode& node)
1969 {
1970  if (node.name() != "Source") {
1971  return boost::shared_ptr<Source>();
1972  }
1973 
1974  try {
1975  /* note: do peak building in another thread when loading session state */
1976  return SourceFactory::create (*this, node, true);
1977  }
1978 
1979  catch (failed_constructor& err) {
1980  error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
1981  return boost::shared_ptr<Source>();
1982  }
1983 }
1984 
1985 int
1986 Session::save_template (string template_name)
1987 {
1988  XMLTree tree;
1989 
1990  if (_state_of_the_state & CannotSave) {
1991  return -1;
1992  }
1993 
1994  std::string user_template_dir(user_template_directory());
1995 
1996  if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1997  error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1998  user_template_dir, g_strerror (errno)) << endmsg;
1999  return -1;
2000  }
2001 
2002  tree.set_root (&get_template());
2003 
2004  std::string template_dir_path(user_template_dir);
2005 
2006  /* directory to put the template in */
2007  template_dir_path = Glib::build_filename (template_dir_path, template_name);
2008 
2009  if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2010  warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2011  template_dir_path) << endmsg;
2012  return -1;
2013  }
2014 
2015  if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2016  error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2017  template_dir_path, g_strerror (errno)) << endmsg;
2018  return -1;
2019  }
2020 
2021  /* file to write */
2022  std::string template_file_path(template_dir_path);
2023  template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
2024 
2025  if (!tree.write (template_file_path)) {
2026  error << _("template not saved") << endmsg;
2027  return -1;
2028  }
2029 
2030  /* copy plugin state directory */
2031 
2032  std::string template_plugin_state_path(template_dir_path);
2033  template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2034 
2035  if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2036  error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2037  template_plugin_state_path, g_strerror (errno)) << endmsg;
2038  return -1;
2039  }
2040 
2041  copy_recurse (plugins_dir(), template_plugin_state_path);
2042 
2043  return 0;
2044 }
2045 
2046 void
2047 Session::refresh_disk_space ()
2048 {
2049 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2050 
2051  Glib::Threads::Mutex::Lock lm (space_lock);
2052 
2053  /* get freespace on every FS that is part of the session path */
2054 
2055  _total_free_4k_blocks = 0;
2056  _total_free_4k_blocks_uncertain = false;
2057 
2058  for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2059 
2060  struct statfs statfsbuf;
2061  statfs (i->path.c_str(), &statfsbuf);
2062 
2063  double const scale = statfsbuf.f_bsize / 4096.0;
2064 
2065  /* See if this filesystem is read-only */
2066  struct statvfs statvfsbuf;
2067  statvfs (i->path.c_str(), &statvfsbuf);
2068 
2069  /* f_bavail can be 0 if it is undefined for whatever
2070  filesystem we are looking at; Samba shares mounted
2071  via GVFS are an example of this.
2072  */
2073  if (statfsbuf.f_bavail == 0) {
2074  /* block count unknown */
2075  i->blocks = 0;
2076  i->blocks_unknown = true;
2077  } else if (statvfsbuf.f_flag & ST_RDONLY) {
2078  /* read-only filesystem */
2079  i->blocks = 0;
2080  i->blocks_unknown = false;
2081  } else {
2082  /* read/write filesystem with known space */
2083  i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2084  i->blocks_unknown = false;
2085  }
2086 
2087  _total_free_4k_blocks += i->blocks;
2088  if (i->blocks_unknown) {
2089  _total_free_4k_blocks_uncertain = true;
2090  }
2091  }
2092 #elif defined PLATFORM_WINDOWS
2093  vector<string> scanned_volumes;
2094  vector<string>::iterator j;
2095  vector<space_and_path>::iterator i;
2096  DWORD nSectorsPerCluster, nBytesPerSector,
2097  nFreeClusters, nTotalClusters;
2098  char disk_drive[4];
2099  bool volume_found;
2100 
2101  _total_free_4k_blocks = 0;
2102 
2103  for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2104  strncpy (disk_drive, (*i).path.c_str(), 3);
2105  disk_drive[3] = 0;
2106  strupr(disk_drive);
2107 
2108  volume_found = false;
2109  if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2110  {
2111  int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2112  int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2113  i->blocks = (uint32_t)(nFreeBytes / 4096);
2114 
2115  for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2116  if (0 == j->compare(disk_drive)) {
2117  volume_found = true;
2118  break;
2119  }
2120  }
2121 
2122  if (!volume_found) {
2123  scanned_volumes.push_back(disk_drive);
2124  _total_free_4k_blocks += i->blocks;
2125  }
2126  }
2127  }
2128 
2129  if (0 == _total_free_4k_blocks) {
2130  strncpy (disk_drive, path().c_str(), 3);
2131  disk_drive[3] = 0;
2132 
2133  if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2134  {
2135  int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2136  int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2137  _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2138  }
2139  }
2140 #endif
2141 }
2142 
2143 string
2144 Session::get_best_session_directory_for_new_audio ()
2145 {
2146  vector<space_and_path>::iterator i;
2147  string result = _session_dir->root_path();
2148 
2149  /* handle common case without system calls */
2150 
2151  if (session_dirs.size() == 1) {
2152  return result;
2153  }
2154 
2155  /* OK, here's the algorithm we're following here:
2156 
2157  We want to select which directory to use for
2158  the next file source to be created. Ideally,
2159  we'd like to use a round-robin process so as to
2160  get maximum performance benefits from splitting
2161  the files across multiple disks.
2162 
2163  However, in situations without much diskspace, an
2164  RR approach may end up filling up a filesystem
2165  with new files while others still have space.
2166  Its therefore important to pay some attention to
2167  the freespace in the filesystem holding each
2168  directory as well. However, if we did that by
2169  itself, we'd keep creating new files in the file
2170  system with the most space until it was as full
2171  as all others, thus negating any performance
2172  benefits of this RAID-1 like approach.
2173 
2174  So, we use a user-configurable space threshold. If
2175  there are at least 2 filesystems with more than this
2176  much space available, we use RR selection between them.
2177  If not, then we pick the filesystem with the most space.
2178 
2179  This gets a good balance between the two
2180  approaches.
2181  */
2182 
2183  refresh_disk_space ();
2184 
2185  int free_enough = 0;
2186 
2187  for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2188  if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2189  free_enough++;
2190  }
2191  }
2192 
2193  if (free_enough >= 2) {
2194  /* use RR selection process, ensuring that the one
2195  picked works OK.
2196  */
2197 
2198  i = last_rr_session_dir;
2199 
2200  do {
2201  if (++i == session_dirs.end()) {
2202  i = session_dirs.begin();
2203  }
2204 
2205  if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2206  SessionDirectory sdir(i->path);
2207  if (sdir.create ()) {
2208  result = (*i).path;
2209  last_rr_session_dir = i;
2210  return result;
2211  }
2212  }
2213 
2214  } while (i != last_rr_session_dir);
2215 
2216  } else {
2217 
2218  /* pick FS with the most freespace (and that
2219  seems to actually work ...)
2220  */
2221 
2222  vector<space_and_path> sorted;
2224 
2225  sorted = session_dirs;
2226  sort (sorted.begin(), sorted.end(), cmp);
2227 
2228  for (i = sorted.begin(); i != sorted.end(); ++i) {
2229  SessionDirectory sdir(i->path);
2230  if (sdir.create ()) {
2231  result = (*i).path;
2232  last_rr_session_dir = i;
2233  return result;
2234  }
2235  }
2236  }
2237 
2238  return result;
2239 }
2240 
2241 string
2242 Session::automation_dir () const
2243 {
2244  return Glib::build_filename (_path, "automation");
2245 }
2246 
2247 string
2248 Session::analysis_dir () const
2249 {
2250  return Glib::build_filename (_path, "analysis");
2251 }
2252 
2253 string
2254 Session::plugins_dir () const
2255 {
2256  return Glib::build_filename (_path, "plugins");
2257 }
2258 
2259 string
2260 Session::externals_dir () const
2261 {
2262  return Glib::build_filename (_path, "externals");
2263 }
2264 
2265 int
2266 Session::load_bundles (XMLNode const & node)
2267 {
2268  XMLNodeList nlist = node.children();
2269  XMLNodeConstIterator niter;
2270 
2271  set_dirty();
2272 
2273  for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2274  if ((*niter)->name() == "InputBundle") {
2275  add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2276  } else if ((*niter)->name() == "OutputBundle") {
2277  add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2278  } else {
2279  error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2280  return -1;
2281  }
2282  }
2283 
2284  return 0;
2285 }
2286 
2287 int
2288 Session::load_route_groups (const XMLNode& node, int version)
2289 {
2290  XMLNodeList nlist = node.children();
2291  XMLNodeConstIterator niter;
2292 
2293  set_dirty ();
2294 
2295  if (version >= 3000) {
2296 
2297  for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2298  if ((*niter)->name() == "RouteGroup") {
2299  RouteGroup* rg = new RouteGroup (*this, "");
2300  add_route_group (rg);
2301  rg->set_state (**niter, version);
2302  }
2303  }
2304 
2305  } else if (version < 3000) {
2306 
2307  for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2308  if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2309  RouteGroup* rg = new RouteGroup (*this, "");
2310  add_route_group (rg);
2311  rg->set_state (**niter, version);
2312  }
2313  }
2314  }
2315 
2316  return 0;
2317 }
2318 
2319 static bool
2320 state_file_filter (const string &str, void* /*arg*/)
2321 {
2322  return (str.length() > strlen(statefile_suffix) &&
2323  str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2324 }
2325 
2326 static string
2327 remove_end(string state)
2328 {
2329  string statename(state);
2330 
2331  string::size_type start,end;
2332  if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2333  statename = statename.substr (start+1);
2334  }
2335 
2336  if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2337  end = statename.length();
2338  }
2339 
2340  return string(statename.substr (0, end));
2341 }
2342 
2343 vector<string>
2344 Session::possible_states (string path)
2345 {
2346  vector<string> states;
2347  find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2348 
2349  transform(states.begin(), states.end(), states.begin(), remove_end);
2350 
2351  sort (states.begin(), states.end());
2352 
2353  return states;
2354 }
2355 
2356 vector<string>
2357 Session::possible_states () const
2358 {
2359  return possible_states(_path);
2360 }
2361 
2362 void
2363 Session::add_route_group (RouteGroup* g)
2364 {
2365  _route_groups.push_back (g);
2366  route_group_added (g); /* EMIT SIGNAL */
2367 
2368  g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2369  g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2370  g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2371 
2372  set_dirty ();
2373 }
2374 
2375 void
2376 Session::remove_route_group (RouteGroup& rg)
2377 {
2378  list<RouteGroup*>::iterator i;
2379 
2380  if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2381  _route_groups.erase (i);
2382  delete &rg;
2383 
2384  route_group_removed (); /* EMIT SIGNAL */
2385  }
2386 }
2387 
2391 void
2392 Session::reorder_route_groups (list<RouteGroup*> groups)
2393 {
2394  _route_groups = groups;
2395 
2396  route_groups_reordered (); /* EMIT SIGNAL */
2397  set_dirty ();
2398 }
2399 
2400 
2401 RouteGroup *
2402 Session::route_group_by_name (string name)
2403 {
2404  list<RouteGroup *>::iterator i;
2405 
2406  for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2407  if ((*i)->name() == name) {
2408  return* i;
2409  }
2410  }
2411  return 0;
2412 }
2413 
2414 RouteGroup&
2415 Session::all_route_group() const
2416 {
2417  return *_all_route_group;
2418 }
2419 
2420 void
2421 Session::add_commands (vector<Command*> const & cmds)
2422 {
2423  for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2424  add_command (*i);
2425  }
2426 }
2427 
2428 void
2429 Session::begin_reversible_command (const string& name)
2430 {
2431  begin_reversible_command (g_quark_from_string (name.c_str ()));
2432 }
2433 
2438 void
2439 Session::begin_reversible_command (GQuark q)
2440 {
2441  /* If nested begin/commit pairs are used, we create just one UndoTransaction
2442  to hold all the commands that are committed. This keeps the order of
2443  commands correct in the history.
2444  */
2445 
2446  if (_current_trans == 0) {
2447  /* start a new transaction */
2448  assert (_current_trans_quarks.empty ());
2449  _current_trans = new UndoTransaction();
2450  _current_trans->set_name (g_quark_to_string (q));
2451  }
2452 
2453  _current_trans_quarks.push_front (q);
2454 }
2455 
2456 void
2457 Session::abort_reversible_command ()
2458 {
2459  if (_current_trans != 0) {
2460  _current_trans->clear();
2461  delete _current_trans;
2462  _current_trans = 0;
2463  _current_trans_quarks.clear();
2464  }
2465 }
2466 
2467 void
2468 Session::commit_reversible_command (Command *cmd)
2469 {
2470  assert (_current_trans);
2471  assert (!_current_trans_quarks.empty ());
2472 
2473  struct timeval now;
2474 
2475  if (cmd) {
2476  _current_trans->add_command (cmd);
2477  }
2478 
2479  _current_trans_quarks.pop_front ();
2480 
2481  if (!_current_trans_quarks.empty ()) {
2482  /* the transaction we're committing is not the top-level one */
2483  return;
2484  }
2485 
2486  if (_current_trans->empty()) {
2487  /* no commands were added to the transaction, so just get rid of it */
2488  delete _current_trans;
2489  _current_trans = 0;
2490  return;
2491  }
2492 
2493  gettimeofday (&now, 0);
2494  _current_trans->set_timestamp (now);
2495 
2496  _history.add (_current_trans);
2497  _current_trans = 0;
2498 }
2499 
2500 static bool
2501 accept_all_audio_files (const string& path, void* /*arg*/)
2502 {
2503  if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2504  return false;
2505  }
2506 
2507  if (!AudioFileSource::safe_audio_file_extension (path)) {
2508  return false;
2509  }
2510 
2511  return true;
2512 }
2513 
2514 static bool
2515 accept_all_midi_files (const string& path, void* /*arg*/)
2516 {
2517  if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2518  return false;
2519  }
2520 
2521  return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2522  (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2523  (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2524 }
2525 
2526 static bool
2527 accept_all_state_files (const string& path, void* /*arg*/)
2528 {
2529  if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2530  return false;
2531  }
2532 
2533  std::string const statefile_ext (statefile_suffix);
2534  if (path.length() >= statefile_ext.length()) {
2535  return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2536  } else {
2537  return false;
2538  }
2539 }
2540 
2541 int
2542 Session::find_all_sources (string path, set<string>& result)
2543 {
2544  XMLTree tree;
2545  XMLNode* node;
2546 
2547  if (!tree.read (path)) {
2548  return -1;
2549  }
2550 
2551  if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2552  return -2;
2553  }
2554 
2555  XMLNodeList nlist;
2556  XMLNodeConstIterator niter;
2557 
2558  nlist = node->children();
2559 
2560  set_dirty();
2561 
2562  for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2563 
2564  XMLProperty* prop;
2565 
2566  if ((prop = (*niter)->property (X_("type"))) == 0) {
2567  continue;
2568  }
2569 
2570  DataType type (prop->value());
2571 
2572  if ((prop = (*niter)->property (X_("name"))) == 0) {
2573  continue;
2574  }
2575 
2576  if (Glib::path_is_absolute (prop->value())) {
2577  /* external file, ignore */
2578  continue;
2579  }
2580 
2581  string found_path;
2582  bool is_new;
2583  uint16_t chan;
2584 
2585  if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2586  result.insert (found_path);
2587  }
2588  }
2589 
2590  return 0;
2591 }
2592 
2593 int
2594 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2595 {
2596  vector<string> state_files;
2597  string ripped;
2598  string this_snapshot_path;
2599 
2600  result.clear ();
2601 
2602  ripped = _path;
2603 
2604  if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2605  ripped = ripped.substr (0, ripped.length() - 1);
2606  }
2607 
2608  find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2609 
2610  if (state_files.empty()) {
2611  /* impossible! */
2612  return 0;
2613  }
2614 
2615  this_snapshot_path = _path;
2616  this_snapshot_path += legalize_for_path (_current_snapshot_name);
2617  this_snapshot_path += statefile_suffix;
2618 
2619  for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2620 
2621  if (exclude_this_snapshot && *i == this_snapshot_path) {
2622  continue;
2623  }
2624 
2625  if (find_all_sources (*i, result) < 0) {
2626  return -1;
2627  }
2628  }
2629 
2630  return 0;
2631 }
2632 
2634  typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2635  AudioSourceList::iterator iter;
2637  uint32_t count;
2638 
2639  RegionCounter() : count (0) {}
2640 };
2641 
2642 int
2643 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2644 {
2645  boost::optional<int> r = AskAboutPlaylistDeletion (p);
2646  return r.get_value_or (1);
2647 }
2648 
2649 void
2650 Session::cleanup_regions ()
2651 {
2652  bool removed = false;
2654 
2655  for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2656 
2657  uint32_t used = playlists->region_use_count (i->second);
2658 
2659  if (used == 0 && !i->second->automatic ()) {
2660  removed = true;
2661  RegionFactory::map_remove (i->second);
2662  }
2663  }
2664 
2665  if (removed) {
2666  // re-check to remove parent references of compound regions
2667  for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2668  if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2669  continue;
2670  }
2671  assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2672  if (0 == playlists->region_use_count (i->second)) {
2673  RegionFactory::map_remove (i->second);
2674  }
2675  }
2676  }
2677 
2678  /* dump the history list */
2679  _history.clear ();
2680 
2681  save_state ("");
2682 }
2683 
2684 int
2685 Session::cleanup_sources (CleanupReport& rep)
2686 {
2687  // FIXME: needs adaptation to midi
2688 
2689  vector<boost::shared_ptr<Source> > dead_sources;
2690  string audio_path;
2691  string midi_path;
2692  vector<string> candidates;
2693  vector<string> unused;
2694  set<string> all_sources;
2695  bool used;
2696  string spath;
2697  int ret = -1;
2698  string tmppath1;
2699  string tmppath2;
2700  Searchpath asp;
2701  Searchpath msp;
2702 
2703  _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2704 
2705  /* consider deleting all unused playlists */
2706 
2707  if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2708  ret = 0;
2709  goto out;
2710  }
2711 
2712  /* sync the "all regions" property of each playlist with its current state
2713  */
2714 
2715  playlists->sync_all_regions_with_regions ();
2716 
2717  /* find all un-used sources */
2718 
2719  rep.paths.clear ();
2720  rep.space = 0;
2721 
2722  for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2723 
2724  SourceMap::iterator tmp;
2725 
2726  tmp = i;
2727  ++tmp;
2728 
2729  /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2730  capture files.
2731  */
2732 
2733  if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2734  dead_sources.push_back (i->second);
2735  i->second->drop_references ();
2736  }
2737 
2738  i = tmp;
2739  }
2740 
2741  /* build a list of all the possible audio directories for the session */
2742 
2743  for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2744  SessionDirectory sdir ((*i).path);
2745  asp += sdir.sound_path();
2746  }
2747  audio_path += asp.to_string();
2748 
2749 
2750  /* build a list of all the possible midi directories for the session */
2751 
2752  for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2753  SessionDirectory sdir ((*i).path);
2754  msp += sdir.midi_path();
2755  }
2756  midi_path += msp.to_string();
2757 
2758  find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2759  find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2760 
2761  /* find all sources, but don't use this snapshot because the
2762  state file on disk still references sources we may have already
2763  dropped.
2764  */
2765 
2766  find_all_sources_across_snapshots (all_sources, true);
2767 
2768  /* add our current source list
2769  */
2770 
2771  for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2773  SourceMap::iterator tmp = i;
2774  ++tmp;
2775 
2776  if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2777 
2778  if (!fs->is_stub()) {
2779 
2780  if (playlists->source_use_count (fs) != 0) {
2781  all_sources.insert (fs->path());
2782  } else {
2783 
2784  /* we might not remove this source from disk, because it may be used
2785  by other snapshots, but its not being used in this version
2786  so lets get rid of it now, along with any representative regions
2787  in the region list.
2788  */
2789 
2790  RegionFactory::remove_regions_using_source (i->second);
2791  sources.erase (i);
2792 
2793  // also remove source from all_sources
2794 
2795  for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
2796  spath = Glib::path_get_basename (*j);
2797  if ( spath == i->second->name () ) {
2798  all_sources.erase (j);
2799  break;
2800  }
2801  }
2802  }
2803  }
2804  }
2805 
2806  i = tmp;
2807  }
2808 
2809  for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2810 
2811  used = false;
2812  spath = *x;
2813 
2814  for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2815 
2816  tmppath1 = canonical_path (spath);
2817  tmppath2 = canonical_path ((*i));
2818 
2819  if (tmppath1 == tmppath2) {
2820  used = true;
2821  break;
2822  }
2823  }
2824 
2825  if (!used) {
2826  unused.push_back (spath);
2827  }
2828  }
2829 
2830  /* now try to move all unused files into the "dead" directory(ies) */
2831 
2832  for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2833  struct stat statbuf;
2834 
2835  string newpath;
2836 
2837  /* don't move the file across filesystems, just
2838  stick it in the `dead_dir_name' directory
2839  on whichever filesystem it was already on.
2840  */
2841 
2842  if ((*x).find ("/sounds/") != string::npos) {
2843 
2844  /* old school, go up 1 level */
2845 
2846  newpath = Glib::path_get_dirname (*x); // "sounds"
2847  newpath = Glib::path_get_dirname (newpath); // "session-name"
2848 
2849  } else {
2850 
2851  /* new school, go up 4 levels */
2852 
2853  newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2854  newpath = Glib::path_get_dirname (newpath); // "session-name"
2855  newpath = Glib::path_get_dirname (newpath); // "interchange"
2856  newpath = Glib::path_get_dirname (newpath); // "session-dir"
2857  }
2858 
2859  newpath = Glib::build_filename (newpath, dead_dir_name);
2860 
2861  if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2862  error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2863  return -1;
2864  }
2865 
2866  newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2867 
2868  if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2869 
2870  /* the new path already exists, try versioning */
2871 
2872  char buf[PATH_MAX+1];
2873  int version = 1;
2874  string newpath_v;
2875 
2876  snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2877  newpath_v = buf;
2878 
2879  while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2880  snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2881  newpath_v = buf;
2882  }
2883 
2884  if (version == 999) {
2885  error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2886  newpath)
2887  << endmsg;
2888  } else {
2889  newpath = newpath_v;
2890  }
2891 
2892  } else {
2893 
2894  /* it doesn't exist, or we can't read it or something */
2895 
2896  }
2897 
2898  stat ((*x).c_str(), &statbuf);
2899 
2900  if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2901  error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2902  (*x), newpath, strerror (errno))
2903  << endmsg;
2904  goto out;
2905  }
2906 
2907  /* see if there an easy to find peakfile for this file, and remove it.
2908  */
2909 
2910  string base = basename_nosuffix (*x);
2911  base += "%A"; /* this is what we add for the channel suffix of all native files,
2912  or for the first channel of embedded files. it will miss
2913  some peakfiles for other channels
2914  */
2915  string peakpath = peak_path (base);
2916 
2917  if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2918  if (::g_unlink (peakpath.c_str()) != 0) {
2919  error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2920  peakpath, _path, strerror (errno))
2921  << endmsg;
2922  /* try to back out */
2923  ::rename (newpath.c_str(), _path.c_str());
2924  goto out;
2925  }
2926  }
2927 
2928  rep.paths.push_back (*x);
2929  rep.space += statbuf.st_size;
2930  }
2931 
2932  /* dump the history list */
2933 
2934  _history.clear ();
2935 
2936  /* save state so we don't end up a session file
2937  referring to non-existent sources.
2938  */
2939 
2940  save_state ("");
2941  ret = 0;
2942 
2943  out:
2944  _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2945 
2946  return ret;
2947 }
2948 
2949 int
2950 Session::cleanup_trash_sources (CleanupReport& rep)
2951 {
2952  // FIXME: needs adaptation for MIDI
2953 
2954  vector<space_and_path>::iterator i;
2955  string dead_dir;
2956 
2957  rep.paths.clear ();
2958  rep.space = 0;
2959 
2960  for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2961 
2962  dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2963 
2964  clear_directory (dead_dir, &rep.space, &rep.paths);
2965  }
2966 
2967  return 0;
2968 }
2969 
2970 void
2971 Session::set_dirty ()
2972 {
2973  /* never mark session dirty during loading */
2974 
2975  if (_state_of_the_state & Loading) {
2976  return;
2977  }
2978 
2979  bool was_dirty = dirty();
2980 
2981  _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2982 
2983 
2984  if (!was_dirty) {
2985  DirtyChanged(); /* EMIT SIGNAL */
2986  }
2987 }
2988 
2989 
2990 void
2991 Session::set_clean ()
2992 {
2993  bool was_dirty = dirty();
2994 
2995  _state_of_the_state = Clean;
2996 
2997 
2998  if (was_dirty) {
2999  DirtyChanged(); /* EMIT SIGNAL */
3000  }
3001 }
3002 
3003 void
3004 Session::set_deletion_in_progress ()
3005 {
3006  _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3007 }
3008 
3009 void
3010 Session::clear_deletion_in_progress ()
3011 {
3012  _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3013 }
3014 
3015 void
3016 Session::add_controllable (boost::shared_ptr<Controllable> c)
3017 {
3018  /* this adds a controllable to the list managed by the Session.
3019  this is a subset of those managed by the Controllable class
3020  itself, and represents the only ones whose state will be saved
3021  as part of the session.
3022  */
3023 
3024  Glib::Threads::Mutex::Lock lm (controllables_lock);
3025  controllables.insert (c);
3026 }
3027 
3028 struct null_deleter { void operator()(void const *) const {} };
3029 
3030 void
3031 Session::remove_controllable (Controllable* c)
3032 {
3033  if (_state_of_the_state & Deletion) {
3034  return;
3035  }
3036 
3037  Glib::Threads::Mutex::Lock lm (controllables_lock);
3038 
3039  Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3040 
3041  if (x != controllables.end()) {
3042  controllables.erase (x);
3043  }
3044 }
3045 
3047 Session::controllable_by_id (const PBD::ID& id)
3048 {
3049  Glib::Threads::Mutex::Lock lm (controllables_lock);
3050 
3051  for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3052  if ((*i)->id() == id) {
3053  return *i;
3054  }
3055  }
3056 
3058 }
3059 
3061 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3062 {
3065 
3066  switch (desc.top_level_type()) {
3067  case ControllableDescriptor::NamedRoute:
3068  {
3069  std::string str = desc.top_level_name();
3070  if (str == "Master" || str == "master") {
3071  r = _master_out;
3072  } else if (str == "control" || str == "listen") {
3073  r = _monitor_out;
3074  } else {
3075  r = route_by_name (desc.top_level_name());
3076  }
3077  break;
3078  }
3079 
3080  case ControllableDescriptor::RemoteControlID:
3081  r = route_by_remote_id (desc.rid());
3082  break;
3083  }
3084 
3085  if (!r) {
3086  return c;
3087  }
3088 
3089  switch (desc.subtype()) {
3090  case ControllableDescriptor::Gain:
3091  c = r->gain_control ();
3092  break;
3093 
3095  c = r->trim()->gain_control ();
3096  break;
3097 
3099  c = r->solo_control();
3100  break;
3101 
3102  case ControllableDescriptor::Mute:
3103  c = r->mute_control();
3104  break;
3105 
3106  case ControllableDescriptor::Recenable:
3107  {
3109 
3110  if (t) {
3111  c = t->rec_enable_control ();
3112  }
3113  break;
3114  }
3115 
3116  case ControllableDescriptor::PanDirection:
3117  {
3118  c = r->pannable()->pan_azimuth_control;
3119  break;
3120  }
3121 
3122  case ControllableDescriptor::PanWidth:
3123  {
3124  c = r->pannable()->pan_width_control;
3125  break;
3126  }
3127 
3128  case ControllableDescriptor::PanElevation:
3129  {
3130  c = r->pannable()->pan_elevation_control;
3131  break;
3132  }
3133 
3134  case ControllableDescriptor::Balance:
3135  /* XXX simple pan control */
3136  break;
3137 
3138  case ControllableDescriptor::PluginParameter:
3139  {
3140  uint32_t plugin = desc.target (0);
3141  uint32_t parameter_index = desc.target (1);
3142 
3143  /* revert to zero based counting */
3144 
3145  if (plugin > 0) {
3146  --plugin;
3147  }
3148 
3149  if (parameter_index > 0) {
3150  --parameter_index;
3151  }
3152 
3153  boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3154 
3155  if (p) {
3157  p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3158  }
3159  break;
3160  }
3161 
3162  case ControllableDescriptor::SendGain:
3163  {
3164  uint32_t send = desc.target (0);
3165 
3166  /* revert to zero-based counting */
3167 
3168  if (send > 0) {
3169  --send;
3170  }
3171 
3172  boost::shared_ptr<Processor> p = r->nth_send (send);
3173 
3174  if (p) {
3176  boost::shared_ptr<Amp> a = s->amp();
3177 
3178  if (a) {
3179  c = s->amp()->gain_control();
3180  }
3181  }
3182  break;
3183  }
3184 
3185  default:
3186  /* relax and return a null pointer */
3187  break;
3188  }
3189 
3190  return c;
3191 }
3192 
3193 void
3194 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3195 {
3196  if (_writable) {
3197  Stateful::add_instant_xml (node, _path);
3198  }
3199 
3200  if (write_to_config) {
3201  Config->add_instant_xml (node);
3202  }
3203 }
3204 
3205 XMLNode*
3206 Session::instant_xml (const string& node_name)
3207 {
3208  return Stateful::instant_xml (node_name, _path);
3209 }
3210 
3211 int
3212 Session::save_history (string snapshot_name)
3213 {
3214  XMLTree tree;
3215 
3216  if (!_writable) {
3217  return 0;
3218  }
3219 
3220  if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3221  (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3222  return 0;
3223  }
3224 
3225  if (snapshot_name.empty()) {
3226  snapshot_name = _current_snapshot_name;
3227  }
3228 
3229  const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3230  const string backup_filename = history_filename + backup_suffix;
3231  const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3232  const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3233 
3234  if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3235  if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3236  error << _("could not backup old history file, current history not saved") << endmsg;
3237  return -1;
3238  }
3239  }
3240 
3241  tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3242 
3243  if (!tree.write (xml_path))
3244  {
3245  error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3246 
3247  if (g_remove (xml_path.c_str()) != 0) {
3248  error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3249  xml_path, g_strerror (errno)) << endmsg;
3250  }
3251  if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3252  error << string_compose (_("could not restore history file from backup %1 (%2)"),
3253  backup_path, g_strerror (errno)) << endmsg;
3254  }
3255 
3256  return -1;
3257  }
3258 
3259  return 0;
3260 }
3261 
3262 int
3263 Session::restore_history (string snapshot_name)
3264 {
3265  XMLTree tree;
3266 
3267  if (snapshot_name.empty()) {
3268  snapshot_name = _current_snapshot_name;
3269  }
3270 
3271  const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3272  const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3273 
3274  info << "Loading history from " << xml_path << endmsg;
3275 
3276  if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3277  info << string_compose (_("%1: no history file \"%2\" for this session."),
3278  _name, xml_path) << endmsg;
3279  return 1;
3280  }
3281 
3282  if (!tree.read (xml_path)) {
3283  error << string_compose (_("Could not understand session history file \"%1\""),
3284  xml_path) << endmsg;
3285  return -1;
3286  }
3287 
3288  // replace history
3289  _history.clear();
3290 
3291  for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3292 
3293  XMLNode *t = *it;
3294  UndoTransaction* ut = new UndoTransaction ();
3295  struct timeval tv;
3296 
3297  ut->set_name(t->property("name")->value());
3298  stringstream ss(t->property("tv-sec")->value());
3299  ss >> tv.tv_sec;
3300  ss.str(t->property("tv-usec")->value());
3301  ss >> tv.tv_usec;
3302  ut->set_timestamp(tv);
3303 
3304  for (XMLNodeConstIterator child_it = t->children().begin();
3305  child_it != t->children().end(); child_it++)
3306  {
3307  XMLNode *n = *child_it;
3308  Command *c;
3309 
3310  if (n->name() == "MementoCommand" ||
3311  n->name() == "MementoUndoCommand" ||
3312  n->name() == "MementoRedoCommand") {
3313 
3314  if ((c = memento_command_factory(n))) {
3315  ut->add_command(c);
3316  }
3317 
3318  } else if (n->name() == "NoteDiffCommand") {
3319  PBD::ID id (n->property("midi-source")->value());
3320  boost::shared_ptr<MidiSource> midi_source =
3321  boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3322  if (midi_source) {
3323  ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3324  } else {
3325  error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3326  }
3327 
3328  } else if (n->name() == "SysExDiffCommand") {
3329 
3330  PBD::ID id (n->property("midi-source")->value());
3331  boost::shared_ptr<MidiSource> midi_source =
3332  boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3333  if (midi_source) {
3334  ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3335  } else {
3336  error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3337  }
3338 
3339  } else if (n->name() == "PatchChangeDiffCommand") {
3340 
3341  PBD::ID id (n->property("midi-source")->value());
3342  boost::shared_ptr<MidiSource> midi_source =
3343  boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3344  if (midi_source) {
3345  ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3346  } else {
3347  error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3348  }
3349 
3350  } else if (n->name() == "StatefulDiffCommand") {
3351  if ((c = stateful_diff_command_factory (n))) {
3352  ut->add_command (c);
3353  }
3354  } else {
3355  error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3356  }
3357  }
3358 
3359  _history.add (ut);
3360  }
3361 
3362  return 0;
3363 }
3364 
3365 void
3366 Session::config_changed (std::string p, bool ours)
3367 {
3368  if (ours) {
3369  set_dirty ();
3370  }
3371 
3372  if (p == "seamless-loop") {
3373 
3374  } else if (p == "rf-speed") {
3375 
3376  } else if (p == "auto-loop") {
3377 
3378  } else if (p == "auto-input") {
3379 
3380  if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3381  /* auto-input only makes a difference if we're rolling */
3382  set_track_monitor_input_status (!config.get_auto_input());
3383  }
3384 
3385  } else if (p == "punch-in") {
3386 
3387  Location* location;
3388 
3389  if ((location = _locations->auto_punch_location()) != 0) {
3390 
3391  if (config.get_punch_in ()) {
3392  replace_event (SessionEvent::PunchIn, location->start());
3393  } else {
3394  remove_event (location->start(), SessionEvent::PunchIn);
3395  }
3396  }
3397 
3398  } else if (p == "punch-out") {
3399 
3400  Location* location;
3401 
3402  if ((location = _locations->auto_punch_location()) != 0) {
3403 
3404  if (config.get_punch_out()) {
3405  replace_event (SessionEvent::PunchOut, location->end());
3406  } else {
3407  clear_events (SessionEvent::PunchOut);
3408  }
3409  }
3410 
3411  } else if (p == "edit-mode") {
3412 
3413  Glib::Threads::Mutex::Lock lm (playlists->lock);
3414 
3415  for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3416  (*i)->set_edit_mode (Config->get_edit_mode ());
3417  }
3418 
3419  } else if (p == "use-video-sync") {
3420 
3421  waiting_for_sync_offset = config.get_use_video_sync();
3422 
3423  } else if (p == "mmc-control") {
3424 
3425  //poke_midi_thread ();
3426 
3427  } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3428 
3429  _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3430 
3431  } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3432 
3433  _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3434 
3435  } else if (p == "midi-control") {
3436 
3437  //poke_midi_thread ();
3438 
3439  } else if (p == "raid-path") {
3440 
3441  setup_raid_path (config.get_raid_path());
3442 
3443  } else if (p == "timecode-format") {
3444 
3445  sync_time_vars ();
3446 
3447  } else if (p == "video-pullup") {
3448 
3449  sync_time_vars ();
3450 
3451  } else if (p == "seamless-loop") {
3452 
3453  if (play_loop && transport_rolling()) {
3454  // to reset diskstreams etc
3455  request_play_loop (true);
3456  }
3457 
3458  } else if (p == "rf-speed") {
3459 
3460  cumulative_rf_motion = 0;
3461  reset_rf_scale (0);
3462 
3463  } else if (p == "click-sound") {
3464 
3465  setup_click_sounds (1);
3466 
3467  } else if (p == "click-emphasis-sound") {
3468 
3469  setup_click_sounds (-1);
3470 
3471  } else if (p == "clicking") {
3472 
3473  if (Config->get_clicking()) {
3474  if (_click_io && click_data) { // don't require emphasis data
3475  _clicking = true;
3476  }
3477  } else {
3478  _clicking = false;
3479  }
3480 
3481  } else if (p == "click-gain") {
3482 
3483  if (_click_gain) {
3484  _click_gain->set_gain (Config->get_click_gain(), this);
3485  }
3486 
3487  } else if (p == "send-mtc") {
3488 
3489  if (Config->get_send_mtc ()) {
3490  /* mark us ready to send */
3491  next_quarter_frame_to_send = 0;
3492  }
3493 
3494  } else if (p == "send-mmc") {
3495 
3496  _mmc->enable_send (Config->get_send_mmc ());
3497 
3498  } else if (p == "midi-feedback") {
3499 
3500  session_midi_feedback = Config->get_midi_feedback();
3501 
3502  } else if (p == "jack-time-master") {
3503 
3504  engine().reset_timebase ();
3505 
3506  } else if (p == "native-file-header-format") {
3507 
3508  if (!first_file_header_format_reset) {
3509  reset_native_file_format ();
3510  }
3511 
3512  first_file_header_format_reset = false;
3513 
3514  } else if (p == "native-file-data-format") {
3515 
3516  if (!first_file_data_format_reset) {
3517  reset_native_file_format ();
3518  }
3519 
3520  first_file_data_format_reset = false;
3521 
3522  } else if (p == "external-sync") {
3523  if (!config.get_external_sync()) {
3524  drop_sync_source ();
3525  } else {
3526  switch_to_sync_source (Config->get_sync_source());
3527  }
3528  } else if (p == "denormal-model") {
3529  setup_fpu ();
3530  } else if (p == "history-depth") {
3531  set_history_depth (Config->get_history_depth());
3532  } else if (p == "remote-model") {
3533  /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3534  TO SET REMOTE ID'S
3535  */
3536  } else if (p == "initial-program-change") {
3537 
3538  if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3539  MIDI::byte buf[2];
3540 
3541  buf[0] = MIDI::program; // channel zero by default
3542  buf[1] = (Config->get_initial_program_change() & 0x7f);
3543 
3544  _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3545  }
3546  } else if (p == "solo-mute-override") {
3547  // catch_up_on_solo_mute_override ();
3548  } else if (p == "listen-position" || p == "pfl-position") {
3549  listen_position_changed ();
3550  } else if (p == "solo-control-is-listen-control") {
3551  solo_control_mode_changed ();
3552  } else if (p == "solo-mute-gain") {
3553  _solo_cut_control->Changed();
3554  } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3555  last_timecode_valid = false;
3556  } else if (p == "playback-buffer-seconds") {
3557  AudioSource::allocate_working_buffers (frame_rate());
3558  } else if (p == "ltc-source-port") {
3559  reconnect_ltc_input ();
3560  } else if (p == "ltc-sink-port") {
3561  reconnect_ltc_output ();
3562  } else if (p == "timecode-generator-offset") {
3563  ltc_tx_parse_offset();
3564  }
3565 
3566  set_dirty ();
3567 }
3568 
3569 void
3570 Session::set_history_depth (uint32_t d)
3571 {
3572  _history.set_depth (d);
3573 }
3574 
3575 int
3576 Session::load_diskstreams_2X (XMLNode const & node, int)
3577 {
3578  XMLNodeList clist;
3579  XMLNodeConstIterator citer;
3580 
3581  clist = node.children();
3582 
3583  for (citer = clist.begin(); citer != clist.end(); ++citer) {
3584 
3585  try {
3586  /* diskstreams added automatically by DiskstreamCreated handler */
3587  if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3588  boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3589  _diskstreams_2X.push_back (dsp);
3590  } else {
3591  error << _("Session: unknown diskstream type in XML") << endmsg;
3592  }
3593  }
3594 
3595  catch (failed_constructor& err) {
3596  error << _("Session: could not load diskstream via XML state") << endmsg;
3597  return -1;
3598  }
3599  }
3600 
3601  return 0;
3602 }
3603 
3605 void
3606 Session::setup_midi_machine_control ()
3607 {
3608  _mmc = new MIDI::MachineControl;
3609  _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3610 
3611  _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3612  _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3613  _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3614  _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3615  _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3616  _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3617  _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3618  _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3619  _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3620  _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3621  _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3622  _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3623  _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3624 
3625  /* also handle MIDI SPP because its so common */
3626 
3627  _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3628  _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3629  _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3630 }
3631 
3633 Session::solo_cut_control() const
3634 {
3635  /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3636  controls in Ardour that currently get presented to the user in the GUI that require
3637  access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3638 
3639  its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3640  it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3641  parameter.
3642  */
3643 
3644  return _solo_cut_control;
3645 }
3646 
3647 int
3648 Session::rename (const std::string& new_name)
3649 {
3650  string legal_name = legalize_for_path (new_name);
3651  string new_path;
3652  string oldstr;
3653  string newstr;
3654  bool first = true;
3655 
3656  string const old_sources_root = _session_dir->sources_root();
3657 
3658  if (!_writable || (_state_of_the_state & CannotSave)) {
3659  error << _("Cannot rename read-only session.") << endmsg;
3660  return 0; // don't show "messed up" warning
3661  }
3662  if (record_status() == Recording) {
3663  error << _("Cannot rename session while recording") << endmsg;
3664  return 0; // don't show "messed up" warning
3665  }
3666 
3667  StateProtector stp (this);
3668 
3669  /* Rename:
3670 
3671  * session directory
3672  * interchange subdirectory
3673  * session file
3674  * session history
3675 
3676  * Backup files are left unchanged and not renamed.
3677  */
3678 
3679  /* pass one: not 100% safe check that the new directory names don't
3680  * already exist ...
3681  */
3682 
3683  for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3684 
3685  oldstr = (*i).path;
3686 
3687  /* this is a stupid hack because Glib::path_get_dirname() is
3688  * lexical-only, and so passing it /a/b/c/ gives a different
3689  * result than passing it /a/b/c ...
3690  */
3691 
3692  if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3693  oldstr = oldstr.substr (0, oldstr.length() - 1);
3694  }
3695 
3696  string base = Glib::path_get_dirname (oldstr);
3697 
3698  newstr = Glib::build_filename (base, legal_name);
3699 
3700  cerr << "Looking for " << newstr << endl;
3701 
3702  if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3703  cerr << " exists\n";
3704  return -1;
3705  }
3706  }
3707 
3708  /* Session dirs */
3709 
3710  first = true;
3711 
3712  for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3713 
3714  vector<string> v;
3715 
3716  oldstr = (*i).path;
3717 
3718  /* this is a stupid hack because Glib::path_get_dirname() is
3719  * lexical-only, and so passing it /a/b/c/ gives a different
3720  * result than passing it /a/b/c ...
3721  */
3722 
3723  if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3724  oldstr = oldstr.substr (0, oldstr.length() - 1);
3725  }
3726 
3727  string base = Glib::path_get_dirname (oldstr);
3728  newstr = Glib::build_filename (base, legal_name);
3729 
3730  cerr << "for " << oldstr << " new dir = " << newstr << endl;
3731 
3732  cerr << "Rename " << oldstr << " => " << newstr << endl;
3733  if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3734  cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3735  error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3736  return 1;
3737  }
3738 
3739  /* Reset path in "session dirs" */
3740 
3741  (*i).path = newstr;
3742  (*i).blocks = 0;
3743 
3744  /* reset primary SessionDirectory object */
3745 
3746  if (first) {
3747  (*_session_dir) = newstr;
3748  new_path = newstr;
3749  first = false;
3750  }
3751 
3752  /* now rename directory below session_dir/interchange */
3753 
3754  string old_interchange_dir;
3755  string new_interchange_dir;
3756 
3757  /* use newstr here because we renamed the path
3758  * (folder/directory) that used to be oldstr to newstr above
3759  */
3760 
3761  v.push_back (newstr);
3762  v.push_back (interchange_dir_name);
3763  v.push_back (Glib::path_get_basename (oldstr));
3764 
3765  old_interchange_dir = Glib::build_filename (v);
3766 
3767  v.clear ();
3768  v.push_back (newstr);
3769  v.push_back (interchange_dir_name);
3770  v.push_back (legal_name);
3771 
3772  new_interchange_dir = Glib::build_filename (v);
3773 
3774  cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
3775 
3776  if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
3777  cerr << string_compose (_("renaming %s as %2 failed (%3)"),
3778  old_interchange_dir, new_interchange_dir,
3779  g_strerror (errno))
3780  << endl;
3781  error << string_compose (_("renaming %s as %2 failed (%3)"),
3782  old_interchange_dir, new_interchange_dir,
3783  g_strerror (errno))
3784  << endmsg;
3785  return 1;
3786  }
3787  }
3788 
3789  /* state file */
3790 
3791  oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
3792  newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
3793 
3794  cerr << "Rename " << oldstr << " => " << newstr << endl;
3795 
3796  if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3797  cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3798  error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3799  return 1;
3800  }
3801 
3802  /* history file */
3803 
3804  oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
3805 
3806  if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3807  newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
3808 
3809  cerr << "Rename " << oldstr << " => " << newstr << endl;
3810 
3811  if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3812  cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3813  error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3814  return 1;
3815  }
3816  }
3817 
3818  /* remove old name from recent sessions */
3819  remove_recent_sessions (_path);
3820  _path = new_path;
3821 
3822  /* update file source paths */
3823 
3824  for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3826  if (fs) {
3827  string p = fs->path ();
3828  boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3829  fs->set_path (p);
3830  SourceFactory::setup_peakfile(i->second, true);
3831  }
3832  }
3833 
3834  _current_snapshot_name = new_name;
3835  _name = new_name;
3836 
3837  set_dirty ();
3838 
3839  /* save state again to get everything just right */
3840 
3841  save_state (_current_snapshot_name);
3842 
3843  /* add to recent sessions */
3844 
3845  store_recent_sessions (new_name, _path);
3846 
3847  return 0;
3848 }
3849 
3850 int
3851 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3852 {
3853  if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3854  return -1;
3855  }
3856 
3857  if (!tree.read (xmlpath)) {
3858  return -1;
3859  }
3860 
3861  return 0;
3862 }
3863 
3864 int
3865 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3866 {
3867  XMLTree tree;
3868  bool found_sr = false;
3869  bool found_data_format = false;
3870 
3871  if (get_session_info_from_path (tree, xmlpath)) {
3872  return -1;
3873  }
3874 
3875  /* sample rate */
3876 
3877  const XMLProperty* prop;
3878  if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3879  sample_rate = atoi (prop->value());
3880  found_sr = true;
3881  }
3882 
3883  const XMLNodeList& children (tree.root()->children());
3884  for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3885  const XMLNode* child = *c;
3886  if (child->name() == "Config") {
3887  const XMLNodeList& options (child->children());
3888  for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3889  const XMLNode* option = *oc;
3890  const XMLProperty* name = option->property("name");
3891 
3892  if (!name) {
3893  continue;
3894  }
3895 
3896  if (name->value() == "native-file-data-format") {
3897  const XMLProperty* value = option->property ("value");
3898  if (value) {
3899  SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3900  data_format = fmt;
3901  found_data_format = true;
3902  break;
3903  }
3904  }
3905  }
3906  }
3907  if (found_data_format) {
3908  break;
3909  }
3910  }
3911 
3912  return !(found_sr && found_data_format); // zero if they are both found
3913 }
3914 
3915 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
3916 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
3917 
3918 int
3919 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
3920 {
3921  uint32_t total = 0;
3922  uint32_t n = 0;
3923  SourcePathMap source_path_map;
3924  string new_path;
3926  int ret = 0;
3927 
3928  {
3929 
3930  Glib::Threads::Mutex::Lock lm (source_lock);
3931 
3932  cerr << " total sources = " << sources.size();
3933 
3934  for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3936 
3937  if (!fs) {
3938  continue;
3939  }
3940 
3941  if (fs->within_session()) {
3942  continue;
3943  }
3944 
3945  if (source_path_map.find (fs->path()) != source_path_map.end()) {
3946  source_path_map[fs->path()].push_back (fs);
3947  } else {
3948  SeveralFileSources v;
3949  v.push_back (fs);
3950  source_path_map.insert (make_pair (fs->path(), v));
3951  }
3952 
3953  total++;
3954  }
3955 
3956  cerr << " fsources = " << total << endl;
3957 
3958  for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
3959 
3960  /* tell caller where we are */
3961 
3962  string old_path = i->first;
3963 
3964  callback (n, total, old_path);
3965 
3966  cerr << old_path << endl;
3967 
3968  new_path.clear ();
3969 
3970  switch (i->second.front()->type()) {
3971  case DataType::AUDIO:
3972  new_path = new_audio_source_path_for_embedded (old_path);
3973  break;
3974 
3975  case DataType::MIDI:
3976  /* XXX not implemented yet */
3977  break;
3978  }
3979 
3980  if (new_path.empty()) {
3981  continue;
3982  }
3983 
3984  cerr << "Move " << old_path << " => " << new_path << endl;
3985 
3986  if (!copy_file (old_path, new_path)) {
3987  cerr << "failed !\n";
3988  ret = -1;
3989  }
3990 
3991  /* make sure we stop looking in the external
3992  dir/folder. Remember, this is an all-or-nothing
3993  operations, it doesn't merge just some files.
3994  */
3995  remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
3996 
3997  for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
3998  (*f)->set_path (new_path);
3999  }
4000  }
4001  }
4002 
4003  save_state ("", false, false);
4004 
4005  return ret;
4006 }
4007 
4008 static
4009 bool accept_all_files (string const &, void *)
4010 {
4011  return true;
4012 }
4013 
4014 void
4015 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4016 {
4017  /* It would be good if this did something useful vis-a-vis save-as, but the arguments doesn't provide the correct information right now to do this.
4018  */
4019 }
4020 
4021 static string
4022 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4023 {
4024  /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4025 
4026  string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4027  vector<string> v;
4028  v.push_back (new_session_folder); /* full path */
4029  v.push_back (interchange_dir_name);
4030  v.push_back (new_session_path); /* just one directory/folder */
4031  v.push_back (typedir);
4032  v.push_back (Glib::path_get_basename (old_path));
4033 
4034  return Glib::build_filename (v);
4035 }
4036 
4037 int
4038 Session::save_as (SaveAs& saveas)
4039 {
4040  vector<string> files;
4041  string current_folder = Glib::path_get_dirname (_path);
4042  string new_folder = legalize_for_path (saveas.new_name);
4043  string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4044  int64_t total_bytes = 0;
4045  int64_t copied = 0;
4046  int64_t cnt = 0;
4047  int64_t all = 0;
4048  int32_t internal_file_cnt = 0;
4049 
4050  vector<string> do_not_copy_extensions;
4051  do_not_copy_extensions.push_back (statefile_suffix);
4052  do_not_copy_extensions.push_back (pending_suffix);
4053  do_not_copy_extensions.push_back (backup_suffix);
4054  do_not_copy_extensions.push_back (temp_suffix);
4055  do_not_copy_extensions.push_back (history_suffix);
4056 
4057  /* get total size */
4058 
4059  for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4060 
4061  /* need to clear this because
4062  * find_files_matching_filter() is cumulative
4063  */
4064 
4065  files.clear ();
4066 
4067  find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4068 
4069  all += files.size();
4070 
4071  for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4072  GStatBuf gsb;
4073  g_stat ((*i).c_str(), &gsb);
4074  total_bytes += gsb.st_size;
4075  }
4076  }
4077 
4078  /* save old values so we can switch back if we are not switching to the new session */
4079 
4080  string old_path = _path;
4081  string old_name = _name;
4082  string old_snapshot = _current_snapshot_name;
4083  string old_sd = _session_dir->root_path();
4084  vector<string> old_search_path[DataType::num_types];
4085  string old_config_search_path[DataType::num_types];
4086 
4087  old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4088  old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4089  old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4090  old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4091 
4092  /* switch session directory */
4093 
4094  (*_session_dir) = to_dir;
4095 
4096  /* create new tree */
4097 
4098  if (!_session_dir->create()) {
4099  saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4100  return -1;
4101  }
4102 
4103  try {
4104  /* copy all media files. Find each location in
4105  * session_dirs, and copy files from there to
4106  * target.
4107  */
4108 
4109  for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4110 
4111  /* need to clear this because
4112  * find_files_matching_filter() is cumulative
4113  */
4114 
4115  files.clear ();
4116 
4117  const size_t prefix_len = (*sd).path.size();
4118 
4119  /* Work just on the files within this session dir */
4120 
4121  find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4122 
4123  /* copy all the files. Handling is different for media files
4124  than others because of the *silly* subtree we have below the interchange
4125  folder. That really was a bad idea, but I'm not fixing it as part of
4126  implementing ::save_as().
4127  */
4128 
4129  for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4130 
4131  std::string from = *i;
4132 
4133  if ((*i).find (interchange_dir_name) != string::npos) {
4134 
4135  /* media file */
4136 
4137  if (saveas.copy_media) {
4138 
4139  string to = make_new_media_path (*i, to_dir, new_folder);
4140 
4141  if (!copy_file (from, to)) {
4142  throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4143  }
4144  }
4145 
4146  /* we found media files inside the session folder */
4147 
4148  internal_file_cnt++;
4149 
4150  } else {
4151 
4152  /* normal non-media file. Don't copy state, history, etc.
4153  */
4154 
4155  bool do_copy = true;
4156 
4157  for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4158  if (((*i).length() > (*v).length()) && ((*i).find (*v) == (*i).length() - (*v).length())) {
4159  /* end of filename matches extension, do not copy file */
4160  do_copy = false;
4161  break;
4162  }
4163  }
4164 
4165  if (do_copy) {
4166  string to = Glib::build_filename (to_dir, (*i).substr (prefix_len));
4167 
4168  if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4169  throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4170  }
4171 
4172  if (!copy_file (from, to)) {
4173  throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4174  }
4175  }
4176  }
4177 
4178  /* measure file size even if we're not going to copy so that our Progress
4179  signals are correct, since we included these do-not-copy files
4180  in the computation of the total size and file count.
4181  */
4182 
4183  GStatBuf gsb;
4184  g_stat ((*i).c_str(), &gsb);
4185  copied += gsb.st_size;
4186  cnt++;
4187 
4188  double fraction = (double) copied / total_bytes;
4189 
4190  /* tell someone "X percent, file M of N"; M is one-based */
4191 
4192  boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4193  bool keep_going = true;
4194 
4195  if (res) {
4196  keep_going = *res;
4197  }
4198 
4199  if (!keep_going) {
4200  throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4201  }
4202  }
4203 
4204  }
4205 
4206  /* copy optional folders, if any */
4207 
4208  string old = plugins_dir ();
4209  if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4210  string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4211  copy_files (old, newdir);
4212  }
4213 
4214  old = externals_dir ();
4215  if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4216  string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4217  copy_files (old, newdir);
4218  }
4219 
4220  old = automation_dir ();
4221  if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4222  string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4223  copy_files (old, newdir);
4224  }
4225 
4226  if (saveas.include_media) {
4227 
4228  if (saveas.copy_media) {
4229 
4230  /* only needed if we are copying media, since the
4231  * analysis data refers to media data
4232  */
4233 
4234  old = analysis_dir ();
4235  if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4236  string newdir = Glib::build_filename (to_dir, "analysis");
4237  copy_files (old, newdir);
4238  }
4239  }
4240  }
4241 
4242 
4243  _path = to_dir;
4244  _current_snapshot_name = saveas.new_name;
4245  _name = saveas.new_name;
4246 
4247  if (saveas.include_media && !saveas.copy_media) {
4248 
4249  /* reset search paths of the new session (which we're pretending to be right now) to
4250  include the original session search path, so we can still find all audio.
4251  */
4252 
4253  if (internal_file_cnt) {
4254  for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4255  ensure_search_path_includes (*s, DataType::AUDIO);
4256  }
4257 
4258  for (vector<string>::iterator s = old_search_path[DataType::MIDI].begin(); s != old_search_path[DataType::MIDI].end(); ++s) {
4259  ensure_search_path_includes (*s, DataType::MIDI);
4260  }
4261  }
4262  }
4263 
4264  bool was_dirty = dirty ();
4265 
4266  save_state ("", false, false, !saveas.include_media);
4267  save_default_options ();
4268 
4269  if (saveas.copy_media && saveas.copy_external) {
4270  if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4271  throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4272  }
4273  }
4274 
4275  saveas.final_session_folder_name = _path;
4276 
4277  if (!saveas.switch_to) {
4278 
4279  /* switch back to the way things were */
4280 
4281  _path = old_path;
4282  _name = old_name;
4283  _current_snapshot_name = old_snapshot;
4284 
4285  (*_session_dir) = old_sd;
4286 
4287  if (was_dirty) {
4288  set_dirty ();
4289  }
4290 
4291  if (internal_file_cnt) {
4292  /* reset these to their original values */
4293  config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4294  config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4295  }
4296 
4297  } else {
4298 
4299  /* prune session dirs, and update disk space statistics
4300  */
4301 
4302  space_and_path sp;
4303  sp.path = _path;
4304  session_dirs.clear ();
4305  session_dirs.push_back (sp);
4306  refresh_disk_space ();
4307 
4308  /* ensure that all existing tracks reset their current capture source paths
4309  */
4310  reset_write_sources (true, true);
4311 
4312  /* the copying above was based on actually discovering files, not just iterating over the sources list.
4313  But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4314  */
4315 
4316  for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4318 
4319  if (!fs) {
4320  continue;
4321  }
4322 
4323  if (fs->within_session()) {
4324  string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4325  fs->set_path (newpath);
4326  }
4327  }
4328  }
4329 
4330  } catch (Glib::FileError& e) {
4331 
4332  saveas.failure_message = e.what();
4333 
4334  /* recursively remove all the directories */
4335 
4336  remove_directory (to_dir);
4337 
4338  /* return error */
4339 
4340  return -1;
4341 
4342  } catch (...) {
4343 
4344  saveas.failure_message = _("unknown reason");
4345 
4346  /* recursively remove all the directories */
4347 
4348  remove_directory (to_dir);
4349 
4350  /* return error */
4351 
4352  return -1;
4353  }
4354 
4355  return 0;
4356 }
std::map< PBD::ID, boost::shared_ptr< Region > > RegionMap
static bool accept_all_midi_files(const string &path, void *)
static bool accept_all_audio_files(const string &path, void *)
LIBPBD_API Transmitter fatal
int atoi(const string &s)
Definition: convert.cc:140
LIBARDOUR_API const char *const pending_suffix
std::map< std::string, SeveralFileSources > SourcePathMap
LIBARDOUR_API int remove_recent_sessions(const std::string &path)
XMLNode & get_state()
Definition: region.cc:1228
LIBARDOUR_API void setup_fpu()
Definition: globals.cc:561
const std::string & value() const
Definition: xml++.h:159
PBD::Signal1< void, const PropertyChange & > PropertyChanged
Definition: stateful.h:87
LIBEVORAL_API event_id_t event_id_counter()
Definition: Event.cpp:27
int set_state(const XMLNode &, int version)
Definition: route_group.cc:245
void set_input_port(MIDI::Port *)
bool write() const
Definition: xml++.cc:147
virtual int set_state(const XMLNode &, int version)
Definition: track.cc:108
const std::string & top_level_name() const
LIBARDOUR_API std::string legalize_for_path(const std::string &str)
AutoConnectOption output_ac
Definition: types.h:586
std::map< boost::shared_ptr< Region >, boost::shared_ptr< Region > > CompoundAssociations
void remove_directory(const std::string &dir)
Definition: file_utils.cc:465
bool path_is_within(std::string const &haystack, std::string needle)
Definition: file_utils.cc:375
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
virtual int init()
Definition: route.cc:122
const std::string & name() const
Definition: xml++.h:104
boost::shared_ptr< Pannable > pannable() const
Definition: route.cc:4023
LIBARDOUR_API int store_recent_sessions(std::string name, std::string path)
void reset_write_sources(bool, bool force=false)
Definition: track.cc:632
boost::shared_ptr< Control > control(const Parameter &id, bool create_if_missing=false)
Definition: ControlSet.cpp:73
void set_session(ARDOUR::Session *)
boost::shared_ptr< AutomationControl > gain_control() const
Definition: route.cc:4042
static bool accept_all_state_files(const string &path, void *)
JACK does monitoring.
Definition: types.h:381
tuple f
Definition: signals.py:35
XMLNode * add_child_copy(const XMLNode &)
Definition: xml++.cc:363
framepos_t end() const
Definition: location.h:72
Definition: Beats.hpp:239
LIBPBD_API Transmitter error
LIBPBD_API Transmitter warning
const XMLNodeList & children(const std::string &str=std::string()) const
Definition: xml++.cc:329
LIBEVORAL_API void init_event_id_counter(event_id_t n)
Definition: Event.cpp:33
bool is_stub() const
Definition: file_source.cc:564
PBD::Signal2< void, RouteGroup *, boost::weak_ptr< ARDOUR::Route > > RouteRemoved
Definition: route_group.h:131
bool whole_file() const
Definition: region.h:169
LIBARDOUR_API bool create_backup_file(const std::string &file_path)
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
virtual bool empty() const =0
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
Definition: region.cc:63
PBD::Signal3< bool, float, int64_t, int64_t > Progress
Definition: session.h:420
XMLNode * add_child(const char *)
Definition: xml++.cc:351
LIBARDOUR_API std::string session_template_dir_to_file(std::string const &)
boost::shared_ptr< AutomationControl > rec_enable_control()
Definition: track.h:107
LIBPBD_API int replace_all(std::string &str, const std::string &target, const std::string &replacement)
Definition: strreplace.cc:24
void operator()(void const *) const
Definition: xml++.h:55
int clear_directory(const string &dir, size_t *size, vector< string > *paths)
Definition: file_utils.cc:458
uint32_t blocks
4kB blocks
Definition: session.h:1542
Definition: id.h:32
boost::shared_ptr< Processor > nth_send(uint32_t n)
Definition: route.cc:4095
bool within_session() const
Definition: file_source.h:60
LIBARDOUR_API uint64_t TempoMap
Definition: debug.cc:60
std::list< XMLNode * > XMLNodeList
Definition: xml++.h:44
std::string new_name
Definition: session.h:401
boost::shared_ptr< Amp > trim() const
Definition: route.h:195
#define _(Text)
Definition: i18n.h:11
void set_timestamp(struct timeval &t)
Definition: undo.h:60
void set_length(framecnt_t len)
bool destructive() const
Definition: source.h:82
void copy_recurse(const std::string &from_path, const std::string &to_dir)
Definition: file_utils.cc:332
XMLNode & get_state()
Definition: user_bundle.cc:99
LIBARDOUR_API bool no_auto_connect()
Definition: globals.cc:555
Definition: getopt.h:74
static const char * state_node_name
Definition: chan_count.cc:26
#define PATH_MAX
Definition: lv2_plugin.h:34
bool copy_file(const std::string &from_path, const std::string &to_path)
Definition: file_utils.cc:282
#define X_(Text)
Definition: i18n.h:13
void set_master_sources(const SourceList &)
Definition: region.cc:1393
XMLProperty * property(const char *)
Definition: xml++.cc:413
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
int set(framepos_t start, framepos_t end, bool allow_bbt_recompute=true)
Definition: location.cc:321
#define string_2_enum(str, e)
Definition: enumwriter.h:98
XMLNode * set_root(XMLNode *n)
Definition: xml++.h:63
XMLNode * root() const
Definition: xml++.h:62
LIBARDOUR_API uint64_t Solo
Definition: debug.cc:48
Definition: amp.h:29
LIBARDOUR_API std::string user_template_directory()
std::string new_parent_folder
Definition: session.h:400
bool set_id(const XMLNode &)
Definition: stateful.cc:381
void add_command(Command *const)
Definition: undo.cc:79
boost::shared_ptr< Processor > nth_plugin(uint32_t n)
Definition: route.cc:4078
AutoConnectOption input_ac
Definition: types.h:585
LIBARDOUR_API const char *const backup_suffix
bool exists_and_writable(const std::string &p)
Definition: file_utils.cc:392
bool read()
Definition: xml++.h:71
boost::shared_ptr< Region > region
void set_output_port(boost::shared_ptr< MidiPort >)
std::map< PBD::ID, boost::shared_ptr< AudioSource > > AudioSourceList
const std::string sound_path() const
LIBARDOUR_API XMLNode * find_named_node(const XMLNode &node, std::string name)
LIBARDOUR_API PBD::PropertyDescriptor< bool > regions
Definition: playlist.cc:51
static SessionMetadata * Metadata()
static bool state_file_filter(const string &str, void *)
std::string file_name() const
Definition: SMF.hpp:47
LIBPBD_API Transmitter info
void copy_files(const std::string &from_path, const std::string &to_dir)
Definition: file_utils.cc:319
LIBARDOUR_API const char *const statefile_suffix
LIBARDOUR_API const char *const template_suffix
void map_parameters(boost::function< void(std::string)> &)
XMLProperty * add_property(const char *name, const std::string &value)
void add(Location *, bool make_current=false)
Definition: location.cc:953
LIBPBD_API Glib::ustring basename_nosuffix(Glib::ustring)
const std::string & path() const
Definition: file_source.h:49
static string make_new_media_path(string old_path, string new_session_folder, string new_session_path)
const char * name
LIBARDOUR_API const char *const interchange_dir_name
void add_child_nocopy(XMLNode &)
Definition: xml++.cc:357
virtual int set_state(const XMLNode &, int version)
Definition: route.cc:2243
XMLNode & get_state(void)
Definition: location.cc:1017
std::string final_session_folder_name
Definition: session.h:407
SampleFormat
Definition: types.h:460
boost::shared_ptr< Amp > amp() const
Definition: send.h:46
boost::shared_ptr< SoloControllable > solo_control() const
Definition: route.h:410
XMLNode * add_content(const std::string &s=std::string())
Definition: xml++.cc:407
std::vector< boost::shared_ptr< FileSource > > SeveralFileSources
Definition: xml++.h:95
std::string name() const
TopLevelType top_level_type() const
static bool accept_all_files(string const &, void *)
LIBARDOUR_API PBD::Signal1< void, std::string > BootMessage
Definition: globals.cc:135
LIBPBD_TEMPLATE_MEMBER_API const std::string to_string() const
Definition: search_path.cc:99
const std::string midi_path() const
PBD::Signal2< void, RouteGroup *, boost::weak_ptr< ARDOUR::Route > > RouteAdded
Definition: route_group.h:129
boost::shared_ptr< MuteControllable > mute_control() const
Definition: route.h:414
Definition: debug.h:30
boost::shared_ptr< IO > input() const
Definition: route.h:89
LIBARDOUR_API const char *const temp_suffix
bool used() const
Definition: source.h:111
uint32_t target(uint32_t n) const
uint32_t master_out_channels
Definition: types.h:587
virtual void set_path(const std::string &)
Definition: file_source.cc:545
int init()
Definition: track.cc:57
framepos_t start() const
Definition: location.h:71
framecnt_t length() const
Definition: region.h:114
static const framepos_t max_framepos
Definition: types.h:78
boost::shared_ptr< IO > output() const
Definition: route.h:90
static string remove_end(string state)
static const framecnt_t max_framecnt
Definition: types.h:79
void find_files_matching_filter(vector< string > &result, const Searchpath &paths, bool(*filter)(const string &, void *), void *arg, bool pass_fullpath, bool return_fullpath, bool recurse)
Definition: file_utils.cc:271
virtual void set_diskstream(boost::shared_ptr< Diskstream >)
Definition: track.cc:554
void add_instant_xml(XMLNode &)
LIBARDOUR_API const char *const history_suffix
std::list< boost::shared_ptr< Route > > RouteList
Definition: types.h:532
XMLNodeList::const_iterator XMLNodeConstIterator
Definition: xml++.h:49
AudioSourceList::iterator iter
static MidiPatchManager & instance()
std::vector< boost::shared_ptr< Source > > SourceList
Definition: types.h:520
AutoConnectOption
Definition: types.h:454
std::vector< std::string > paths
Definition: types.h:549
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
boost::shared_ptr< ARDOUR::Playlist > playlist() const
Definition: region.h:251
void set_name(const std::string &str)
Definition: command.h:38
LIBARDOUR_API const char *const dead_dir_name
LIBPBD_API std::string canonical_path(const std::string &path)
Definition: pathexpand.cc:90
std::string failure_message
Definition: session.h:424