2 Copyright (C) 1999-2002 Paul Davis
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.
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.
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.
20 #define __STDC_FORMAT_MACROS 1
28 #include <sigc++/bind.h>
30 #include <cstdio> /* snprintf(3) ... grrr */
45 #include <sys/param.h>
46 #include <sys/mount.h>
51 #include <midi++/mmc.h>
52 #include <midi++/port.h>
53 #include <pbd/error.h>
55 #include <glibmm/thread.h>
56 #include <pbd/pathscanner.h>
57 #include <pbd/pthread_utils.h>
58 #include <pbd/strsplit.h>
59 #include <pbd/stacktrace.h>
60 #include <pbd/copyfile.h>
62 #include <ardour/audioengine.h>
63 #include <ardour/configuration.h>
64 #include <ardour/session.h>
65 #include <ardour/buffer.h>
66 #include <ardour/audio_diskstream.h>
67 #include <ardour/midi_diskstream.h>
68 #include <ardour/utils.h>
69 #include <ardour/audioplaylist.h>
70 #include <ardour/midi_playlist.h>
71 #include <ardour/smf_source.h>
72 #include <ardour/audiofilesource.h>
73 #include <ardour/silentfilesource.h>
74 #include <ardour/sndfilesource.h>
75 #include <ardour/midi_source.h>
76 #include <ardour/sndfile_helpers.h>
77 #include <ardour/auditioner.h>
78 #include <ardour/export.h>
79 #include <ardour/redirect.h>
80 #include <ardour/send.h>
81 #include <ardour/insert.h>
82 #include <ardour/connection.h>
83 #include <ardour/slave.h>
84 #include <ardour/tempo.h>
85 #include <ardour/audio_track.h>
86 #include <ardour/midi_track.h>
87 #include <ardour/cycle_timer.h>
88 #include <ardour/utils.h>
89 #include <ardour/named_selection.h>
90 #include <ardour/version.h>
91 #include <ardour/location.h>
92 #include <ardour/audioregion.h>
93 #include <ardour/midi_region.h>
94 #include <ardour/crossfade.h>
95 #include <ardour/control_protocol_manager.h>
96 #include <ardour/region_factory.h>
97 #include <ardour/source_factory.h>
98 #include <ardour/playlist_factory.h>
99 #include <ardour/filename_extensions.h>
100 #include <control_protocol/control_protocol.h>
106 using namespace ARDOUR;
110 Session::first_stage_init (string fullpath, string snapshot_name)
112 if (fullpath.length() == 0) {
114 throw failed_constructor();
117 char buf[PATH_MAX+1];
118 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
119 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
121 throw failed_constructor();
126 if (_path[_path.length()-1] != '/') {
130 /* these two are just provisional settings. set_state()
131 will likely override them.
134 _name = _current_snapshot_name = snapshot_name;
136 _current_frame_rate = _engine.frame_rate ();
137 _tempo_map = new TempoMap (_current_frame_rate);
138 _tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
140 g_atomic_int_set (&processing_prohibited, 0);
142 _transport_speed = 0;
143 _last_transport_speed = 0;
144 auto_play_legal = false;
145 transport_sub_state = 0;
146 _transport_frame = 0;
148 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
149 start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
150 _end_location_is_free = true;
151 g_atomic_int_set (&_record_status, Disabled);
152 loop_changing = false;
154 _last_roll_location = 0;
155 _last_record_location = 0;
156 pending_locate_frame = 0;
157 pending_locate_roll = false;
158 pending_locate_flush = false;
159 dstream_buffer_size = 0;
161 state_was_pending = false;
163 outbound_mtc_smpte_frame = 0;
164 next_quarter_frame_to_send = -1;
165 current_block_size = 0;
166 solo_update_disabled = false;
167 currently_soloing = false;
168 _have_captured = false;
169 _worst_output_latency = 0;
170 _worst_input_latency = 0;
171 _worst_track_latency = 0;
172 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading|Deletion);
174 butler_mixdown_buffer = 0;
175 butler_gain_buffer = 0;
177 session_send_mmc = false;
178 session_send_mtc = false;
179 post_transport_work = PostTransportWork (0);
180 g_atomic_int_set (&butler_should_do_transport_work, 0);
181 g_atomic_int_set (&butler_active, 0);
182 g_atomic_int_set (&_playback_load, 100);
183 g_atomic_int_set (&_capture_load, 100);
184 g_atomic_int_set (&_playback_load_min, 100);
185 g_atomic_int_set (&_capture_load_min, 100);
187 waiting_to_start = false;
189 _gain_automation_buffer = 0;
190 _pan_automation_buffer = 0;
192 pending_abort = false;
193 destructive_index = 0;
195 first_file_data_format_reset = true;
196 first_file_header_format_reset = true;
197 butler_thread = (pthread_t) 0;
198 //midi_thread = (pthread_t) 0;
200 AudioDiskstream::allocate_working_buffers();
202 /* default short fade = 15ms */
204 Crossfade::set_short_xfade_length ((nframes_t) floor (Config->get_short_xfade_seconds() * frame_rate()));
205 SndFileSource::setup_standard_crossfades (frame_rate());
207 last_mmc_step.tv_sec = 0;
208 last_mmc_step.tv_usec = 0;
211 /* click sounds are unset by default, which causes us to internal
212 waveforms for clicks.
216 click_emphasis_data = 0;
218 click_emphasis_length = 0;
221 process_function = &Session::process_with_events;
223 if (Config->get_use_video_sync()) {
224 waiting_for_sync_offset = true;
226 waiting_for_sync_offset = false;
229 _current_frame_rate = 48000;
230 _base_frame_rate = 48000;
234 _smpte_offset_negative = true;
235 last_smpte_valid = false;
239 last_rr_session_dir = session_dirs.begin();
240 refresh_disk_space ();
242 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
246 average_slave_delta = 1800;
247 have_first_delta_accumulator = false;
248 delta_accumulator_cnt = 0;
249 slave_state = Stopped;
251 _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
253 /* These are all static "per-class" signals */
255 RegionFactory::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
256 SourceFactory::SourceCreated.connect (mem_fun (*this, &Session::add_source));
257 PlaylistFactory::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
258 Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
259 NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
260 AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
262 Controllable::Destroyed.connect (mem_fun (*this, &Session::remove_controllable));
264 IO::MoreChannels.connect (mem_fun (*this, &Session::ensure_buffers));
266 /* stop IO objects from doing stuff until we're ready for them */
268 IO::disable_panners ();
269 IO::disable_ports ();
270 IO::disable_connecting ();
274 Session::second_stage_init (bool new_session)
276 AudioFileSource::set_peak_dir (peak_dir());
279 if (load_state (_current_snapshot_name)) {
282 remove_empty_sounds ();
285 if (start_butler_thread()) {
289 /*if (start_midi_thread ()) {
293 // set_state() will call setup_raid_path(), but if it's a new session we need
294 // to call setup_raid_path() here.
296 if (set_state (*state_tree->root())) {
300 setup_raid_path(_path);
303 /* we can't save till after ::when_engine_running() is called,
304 because otherwise we save state with no connections made.
305 therefore, we reset _state_of_the_state because ::set_state()
306 will have cleared it.
308 we also have to include Loading so that any events that get
309 generated between here and the end of ::when_engine_running()
310 will be processed directly rather than queued.
313 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
315 // set_auto_input (true);
316 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
317 _locations.added.connect (mem_fun (this, &Session::locations_added));
318 setup_click_sounds (0);
319 setup_midi_control ();
321 /* Pay attention ... */
323 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
324 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
327 when_engine_running();
330 /* handle this one in a different way than all others, so that its clear what happened */
332 catch (AudioEngine::PortRegistrationFailure& err) {
333 error << _("Unable to create all required ports")
342 //send_full_time_code ();
343 _engine.transport_locate (0);
344 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
345 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
347 ControlProtocolManager::instance().set_session (*this);
350 _end_location_is_free = true;
352 _end_location_is_free = false;
359 Session::raid_path () const
363 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
368 return path.substr (0, path.length() - 1); // drop final colon
372 Session::setup_raid_path (string path)
374 string::size_type colon;
378 string::size_type len = path.length();
383 if (path.length() == 0) {
387 session_dirs.clear ();
389 for (string::size_type n = 0; n < len; ++n) {
390 if (path[n] == ':') {
397 /* no multiple search path, just one location (common case) */
401 session_dirs.push_back (sp);
408 if (fspath[fspath.length()-1] != '/') {
412 fspath += sound_dir (false);
414 AudioFileSource::set_search_path (fspath);
415 SMFSource::set_search_path (fspath); // FIXME: should be different
422 while ((colon = remaining.find_first_of (':')) != string::npos) {
425 sp.path = remaining.substr (0, colon);
426 session_dirs.push_back (sp);
428 /* add sounds to file search path */
431 if (fspath[fspath.length()-1] != '/') {
434 fspath += sound_dir (false);
437 remaining = remaining.substr (colon+1);
440 if (remaining.length()) {
447 if (fspath[fspath.length()-1] != '/') {
450 fspath += sound_dir (false);
453 session_dirs.push_back (sp);
456 /* set the AudioFileSource search path */
458 AudioFileSource::set_search_path (fspath);
459 SMFSource::set_search_path (fspath); // FIXME: should be different
461 /* reset the round-robin soundfile path thingie */
463 last_rr_session_dir = session_dirs.begin();
467 Session::initialize_start_and_end_locations(nframes_t start, nframes_t end)
469 start_location->set_end (start);
470 _locations.add (start_location);
472 end_location->set_end (end);
473 _locations.add (end_location);
477 Session::create (bool& new_session, string* mix_template, nframes_t initial_length)
481 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
482 error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
488 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
489 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
493 /* if this is is an existing session with an old "sounds" directory, just use it. see Session::sound_dir() for more details */
495 if (!Glib::file_test (old_sound_dir(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
499 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
500 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
505 dir = dead_sound_dir ();
507 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
508 error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
514 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
515 error << string_compose(_("Session: cannot create session export dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
520 /* check new_session so we don't overwrite an existing one */
524 string out_path = _path + _name + statefile_suffix;
526 if(!copy_file (*mix_template, out_path)) {
527 error << string_compose (_("Could not use session template %1 to create new session."), *mix_template)
536 initialize_start_and_end_locations(0, initial_length);
538 _state_of_the_state = Clean;
540 if (save_state (_current_snapshot_name)) {
548 Session::load_diskstreams (const XMLNode& node)
551 XMLNodeConstIterator citer;
553 clist = node.children();
555 for (citer = clist.begin(); citer != clist.end(); ++citer) {
558 /* diskstreams added automatically by DiskstreamCreated handler */
559 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
560 boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
561 add_diskstream (dstream);
562 } else if ((*citer)->name() == "MidiDiskstream") {
563 boost::shared_ptr<MidiDiskstream> dstream (new MidiDiskstream (*this, **citer));
564 add_diskstream (dstream);
566 error << _("Session: unknown diskstream type in XML") << endmsg;
570 catch (failed_constructor& err) {
571 error << _("Session: could not load diskstream via XML state") << endmsg;
580 Session::maybe_write_autosave()
582 if (dirty() && record_status() != Recording) {
583 save_state("", true);
588 Session::remove_pending_capture_state ()
593 xml_path += _current_snapshot_name;
594 xml_path += pending_suffix;
596 unlink (xml_path.c_str());
599 /** Rename a state file.
600 * @param snapshot_name Snapshot name.
603 Session::rename_state (string old_name, string new_name)
605 if (old_name == _current_snapshot_name || old_name == _name) {
606 /* refuse to rename the current snapshot or the "main" one */
610 const string old_xml_path = _path + old_name + statefile_suffix;
611 const string new_xml_path = _path + new_name + statefile_suffix;
613 if (rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
614 error << string_compose(_("could not rename snapshot %1 to %2"), old_name, new_name) << endmsg;
618 /** Remove a state file.
619 * @param snapshot_name Snapshot name.
622 Session::remove_state (string snapshot_name)
624 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
625 /* refuse to remove the current snapshot or the "main" one */
629 const string xml_path = _path + snapshot_name + statefile_suffix;
631 /* make a backup copy of the state file */
632 const string bak_path = xml_path + ".bak";
633 if (g_file_test (xml_path.c_str(), G_FILE_TEST_EXISTS)) {
634 copy_file (xml_path, bak_path);
638 unlink (xml_path.c_str());
642 Session::save_state (string snapshot_name, bool pending)
648 if (_state_of_the_state & CannotSave) {
652 if (!_engine.connected ()) {
653 error << _("Ardour's audio engine is not connected and state saving would lose all I/O connections. Session not saved")
658 tree.set_root (&get_state());
660 if (snapshot_name.empty()) {
661 snapshot_name = _current_snapshot_name;
666 /* proper save: use statefile_suffix (.ardour in English) */
668 xml_path += snapshot_name;
669 xml_path += statefile_suffix;
671 /* make a backup copy of the old file */
675 if (g_file_test (xml_path.c_str(), G_FILE_TEST_EXISTS)) {
676 copy_file (xml_path, bak_path);
681 /* pending save: use pending_suffix (.pending in English) */
683 xml_path += snapshot_name;
684 xml_path += pending_suffix;
691 tmp_path += snapshot_name;
694 // cerr << "actually writing state to " << xml_path << endl;
696 if (!tree.write (tmp_path)) {
697 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
698 unlink (tmp_path.c_str());
703 if (rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
704 error << string_compose (_("could not rename temporary session file %1 to %2"), tmp_path, xml_path) << endmsg;
705 unlink (tmp_path.c_str());
712 save_history (snapshot_name);
714 bool was_dirty = dirty();
716 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
719 DirtyChanged (); /* EMIT SIGNAL */
722 StateSaved (snapshot_name); /* EMIT SIGNAL */
729 Session::restore_state (string snapshot_name)
731 if (load_state (snapshot_name) == 0) {
732 set_state (*state_tree->root());
739 Session::load_state (string snapshot_name)
748 state_was_pending = false;
750 /* check for leftover pending state from a crashed capture attempt */
753 xmlpath += snapshot_name;
754 xmlpath += pending_suffix;
756 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
758 /* there is pending state from a crashed capture attempt */
760 if (AskAboutPendingState()) {
761 state_was_pending = true;
765 if (!state_was_pending) {
768 xmlpath += snapshot_name;
769 xmlpath += statefile_suffix;
772 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
773 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
777 state_tree = new XMLTree;
781 if (!state_tree->read (xmlpath)) {
782 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
788 XMLNode& root (*state_tree->root());
790 if (root.name() != X_("Session")) {
791 error << string_compose (_("Session file %1 is not an Ardour session"), xmlpath) << endmsg;
797 const XMLProperty* prop;
800 if ((prop = root.property ("version")) == 0) {
801 /* no version implies very old version of Ardour */
805 major_version = atoi (prop->value()); // grab just the first number before the period
806 if (major_version < 2) {
815 backup_path += snapshot_name;
817 backup_path += statefile_suffix;
819 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with Ardour versions before 2.0 from now on"),
820 xmlpath, backup_path)
823 copy_file (xmlpath, backup_path);
825 /* if it fails, don't worry. right? */
832 Session::load_options (const XMLNode& node)
836 LocaleGuard lg (X_("POSIX"));
838 Config->set_variables (node, ConfigVariableBase::Session);
840 if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
841 if ((prop = child->property ("val")) != 0) {
842 _end_location_is_free = (prop->value() == "yes");
850 Session::save_config_options_predicate (ConfigVariableBase::Owner owner) const
852 const ConfigVariableBase::Owner modified_by_session_or_user = (ConfigVariableBase::Owner)
853 (ConfigVariableBase::Session|ConfigVariableBase::Interface);
855 return owner & modified_by_session_or_user;
859 Session::get_options () const
862 LocaleGuard lg (X_("POSIX"));
864 XMLNode& option_root = Config->get_variables (mem_fun (*this, &Session::save_config_options_predicate));
866 child = option_root.add_child ("end-marker-is-free");
867 child->add_property ("val", _end_location_is_free ? "yes" : "no");
879 Session::get_template()
881 /* if we don't disable rec-enable, diskstreams
882 will believe they need to store their capture
883 sources in their state node.
886 disable_record (false);
892 Session::state(bool full_state)
894 XMLNode* node = new XMLNode("Session");
897 // store libardour version, just in case
899 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
900 libardour_major_version, libardour_minor_version, libardour_micro_version);
901 node->add_property("version", string(buf));
903 /* store configuration settings */
908 node->add_property ("name", _name);
910 if (session_dirs.size() > 1) {
914 vector<space_and_path>::iterator i = session_dirs.begin();
915 vector<space_and_path>::iterator next;
917 ++i; /* skip the first one */
921 while (i != session_dirs.end()) {
925 if (next != session_dirs.end()) {
935 child = node->add_child ("Path");
936 child->add_content (p);
940 /* save the ID counter */
942 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
943 node->add_property ("id-counter", buf);
945 /* various options */
947 node->add_child_nocopy (get_options());
949 child = node->add_child ("Sources");
952 Glib::Mutex::Lock sl (source_lock);
954 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
956 /* Don't save information about AudioFileSources that are empty */
958 boost::shared_ptr<AudioFileSource> fs;
960 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
962 /* Don't save sources that are empty, unless they're destructive (which are OK
963 if they are empty, because we will re-use them every time.)
966 if (!fs->destructive()) {
967 if (fs->length() == 0) {
973 child->add_child_nocopy (siter->second->get_state());
977 child = node->add_child ("Regions");
980 Glib::Mutex::Lock rl (region_lock);
982 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
984 /* only store regions not attached to playlists */
986 if (i->second->playlist() == 0) {
987 child->add_child_nocopy (i->second->state (true));
992 child = node->add_child ("DiskStreams");
995 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
996 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
997 if (!(*i)->hidden()) {
998 child->add_child_nocopy ((*i)->get_state());
1004 node->add_child_nocopy (_locations.get_state());
1006 // for a template, just create a new Locations, populate it
1007 // with the default start and end, and get the state for that.
1009 Location* start = new Location(0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
1010 Location* end = new Location(0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
1013 end->set_end(compute_initial_length());
1015 node->add_child_nocopy (loc.get_state());
1018 child = node->add_child ("Connections");
1020 Glib::Mutex::Lock lm (connection_lock);
1021 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1022 if (!(*i)->system_dependent()) {
1023 child->add_child_nocopy ((*i)->get_state());
1028 child = node->add_child ("Routes");
1030 boost::shared_ptr<RouteList> r = routes.reader ();
1032 RoutePublicOrderSorter cmp;
1033 RouteList public_order (*r);
1034 public_order.sort (cmp);
1036 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1037 if (!(*i)->hidden()) {
1039 child->add_child_nocopy ((*i)->get_state());
1041 child->add_child_nocopy ((*i)->get_template());
1048 child = node->add_child ("EditGroups");
1049 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1050 child->add_child_nocopy ((*i)->get_state());
1053 child = node->add_child ("MixGroups");
1054 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1055 child->add_child_nocopy ((*i)->get_state());
1058 child = node->add_child ("Playlists");
1059 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1060 if (!(*i)->hidden()) {
1061 if (!(*i)->empty()) {
1063 child->add_child_nocopy ((*i)->get_state());
1065 child->add_child_nocopy ((*i)->get_template());
1071 child = node->add_child ("UnusedPlaylists");
1072 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1073 if (!(*i)->hidden()) {
1074 if (!(*i)->empty()) {
1076 child->add_child_nocopy ((*i)->get_state());
1078 child->add_child_nocopy ((*i)->get_template());
1086 child = node->add_child ("Click");
1087 child->add_child_nocopy (_click_io->state (full_state));
1091 child = node->add_child ("NamedSelections");
1092 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1094 child->add_child_nocopy ((*i)->get_state());
1099 node->add_child_nocopy (_tempo_map->get_state());
1101 node->add_child_nocopy (get_control_protocol_state());
1104 node->add_child_copy (*_extra_xml);
1111 Session::get_control_protocol_state ()
1113 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1114 return cpm.get_state();
1118 Session::set_state (const XMLNode& node)
1122 const XMLProperty* prop;
1125 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1127 if (node.name() != X_("Session")){
1128 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1132 if ((prop = node.property ("name")) != 0) {
1133 _name = prop->value ();
1136 setup_raid_path(_path);
1138 if ((prop = node.property (X_("id-counter"))) != 0) {
1140 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1141 ID::init_counter (x);
1143 /* old sessions used a timebased counter, so fake
1144 the startup ID counter based on a standard
1149 ID::init_counter (now);
1153 IO::disable_ports ();
1154 IO::disable_connecting ();
1156 /* Object loading order:
1174 if (use_config_midi_ports ()) {
1177 if ((child = find_named_node (node, "extra")) != 0) {
1178 _extra_xml = new XMLNode (*child);
1181 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1182 load_options (*child);
1183 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1184 load_options (*child);
1186 error << _("Session: XML state has no options section") << endmsg;
1189 if ((child = find_named_node (node, "Locations")) == 0) {
1190 error << _("Session: XML state has no locations section") << endmsg;
1192 } else if (_locations.set_state (*child)) {
1198 if ((location = _locations.auto_loop_location()) != 0) {
1199 set_auto_loop_location (location);
1202 if ((location = _locations.auto_punch_location()) != 0) {
1203 set_auto_punch_location (location);
1206 if ((location = _locations.end_location()) == 0) {
1207 _locations.add (end_location);
1209 delete end_location;
1210 end_location = location;
1213 if ((location = _locations.start_location()) == 0) {
1214 _locations.add (start_location);
1216 delete start_location;
1217 start_location = location;
1220 AudioFileSource::set_header_position_offset (start_location->start());
1222 if ((child = find_named_node (node, "Sources")) == 0) {
1223 error << _("Session: XML state has no sources section") << endmsg;
1225 } else if (load_sources (*child)) {
1229 if ((child = find_named_node (node, "Regions")) == 0) {
1230 error << _("Session: XML state has no Regions section") << endmsg;
1232 } else if (load_regions (*child)) {
1236 if ((child = find_named_node (node, "Playlists")) == 0) {
1237 error << _("Session: XML state has no playlists section") << endmsg;
1239 } else if (load_playlists (*child)) {
1243 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1245 } else if (load_unused_playlists (*child)) {
1249 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1250 if (load_named_selections (*child)) {
1255 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1256 error << _("Session: XML state has no diskstreams section") << endmsg;
1258 } else if (load_diskstreams (*child)) {
1262 if ((child = find_named_node (node, "Connections")) == 0) {
1263 error << _("Session: XML state has no connections section") << endmsg;
1265 } else if (load_connections (*child)) {
1269 if ((child = find_named_node (node, "EditGroups")) == 0) {
1270 error << _("Session: XML state has no edit groups section") << endmsg;
1272 } else if (load_edit_groups (*child)) {
1276 if ((child = find_named_node (node, "MixGroups")) == 0) {
1277 error << _("Session: XML state has no mix groups section") << endmsg;
1279 } else if (load_mix_groups (*child)) {
1283 if ((child = find_named_node (node, "TempoMap")) == 0) {
1284 error << _("Session: XML state has no Tempo Map section") << endmsg;
1286 } else if (_tempo_map->set_state (*child)) {
1290 if ((child = find_named_node (node, "Routes")) == 0) {
1291 error << _("Session: XML state has no routes section") << endmsg;
1293 } else if (load_routes (*child)) {
1297 if ((child = find_named_node (node, "Click")) == 0) {
1298 warning << _("Session: XML state has no click section") << endmsg;
1299 } else if (_click_io) {
1300 _click_io->set_state (*child);
1303 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1304 ControlProtocolManager::instance().set_protocol_states (*child);
1307 /* here beginneth the second phase ... */
1309 StateReady (); /* EMIT SIGNAL */
1311 _state_of_the_state = Clean;
1313 if (state_was_pending) {
1314 save_state (_current_snapshot_name);
1315 remove_pending_capture_state ();
1316 state_was_pending = false;
1326 Session::load_routes (const XMLNode& node)
1329 XMLNodeConstIterator niter;
1330 RouteList new_routes;
1332 nlist = node.children();
1336 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1338 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1341 error << _("Session: cannot create Route from XML description.") << endmsg;
1345 new_routes.push_back (route);
1348 add_routes (new_routes);
1353 boost::shared_ptr<Route>
1354 Session::XMLRouteFactory (const XMLNode& node)
1356 if (node.name() != "Route") {
1357 return boost::shared_ptr<Route> ((Route*) 0);
1360 bool has_diskstream = (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0);
1362 DataType type = DataType::AUDIO;
1363 const XMLProperty* prop = node.property("default-type");
1365 type = DataType(prop->value());
1367 assert(type != DataType::NIL);
1369 if (has_diskstream) {
1370 if (type == DataType::AUDIO) {
1371 boost::shared_ptr<Route> ret (new AudioTrack (*this, node));
1374 boost::shared_ptr<Route> ret (new MidiTrack (*this, node));
1378 boost::shared_ptr<Route> ret (new Route (*this, node));
1384 Session::load_regions (const XMLNode& node)
1387 XMLNodeConstIterator niter;
1388 boost::shared_ptr<Region> region;
1390 nlist = node.children();
1394 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1395 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1396 error << _("Session: cannot create Region from XML description.") << endmsg;
1403 boost::shared_ptr<Region>
1404 Session::XMLRegionFactory (const XMLNode& node, bool full)
1406 const XMLProperty* type = node.property("type");
1410 if ( !type || type->value() == "audio" ) {
1412 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1414 } else if (type->value() == "midi") {
1416 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1420 } catch (failed_constructor& err) {
1421 return boost::shared_ptr<Region> ();
1424 return boost::shared_ptr<Region> ();
1427 boost::shared_ptr<AudioRegion>
1428 Session::XMLAudioRegionFactory (const XMLNode& node, bool full)
1430 const XMLProperty* prop;
1431 boost::shared_ptr<Source> source;
1432 boost::shared_ptr<AudioSource> as;
1434 uint32_t nchans = 1;
1437 if (node.name() != X_("Region")) {
1438 return boost::shared_ptr<AudioRegion>();
1441 if ((prop = node.property (X_("channels"))) != 0) {
1442 nchans = atoi (prop->value().c_str());
1446 if ((prop = node.property ("name")) == 0) {
1447 cerr << "no name for this region\n";
1451 if ((prop = node.property (X_("source-0"))) == 0) {
1452 if ((prop = node.property ("source")) == 0) {
1453 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1454 return boost::shared_ptr<AudioRegion>();
1458 PBD::ID s_id (prop->value());
1460 if ((source = source_by_id (s_id)) == 0) {
1461 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1462 return boost::shared_ptr<AudioRegion>();
1465 as = boost::dynamic_pointer_cast<AudioSource>(source);
1467 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1468 return boost::shared_ptr<AudioRegion>();
1471 sources.push_back (as);
1473 /* pickup other channels */
1475 for (uint32_t n=1; n < nchans; ++n) {
1476 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1477 if ((prop = node.property (buf)) != 0) {
1479 PBD::ID id2 (prop->value());
1481 if ((source = source_by_id (id2)) == 0) {
1482 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1483 return boost::shared_ptr<AudioRegion>();
1486 as = boost::dynamic_pointer_cast<AudioSource>(source);
1488 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1489 return boost::shared_ptr<AudioRegion>();
1491 sources.push_back (as);
1496 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1498 /* a final detail: this is the one and only place that we know how long missing files are */
1500 if (region->whole_file()) {
1501 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1502 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1504 sfp->set_length (region->length());
1514 catch (failed_constructor& err) {
1515 return boost::shared_ptr<AudioRegion>();
1519 boost::shared_ptr<MidiRegion>
1520 Session::XMLMidiRegionFactory (const XMLNode& node, bool full)
1522 const XMLProperty* prop;
1523 boost::shared_ptr<Source> source;
1524 boost::shared_ptr<MidiSource> ms;
1525 MidiRegion::SourceList sources;
1526 uint32_t nchans = 1;
1528 if (node.name() != X_("Region")) {
1529 return boost::shared_ptr<MidiRegion>();
1532 if ((prop = node.property (X_("channels"))) != 0) {
1533 nchans = atoi (prop->value().c_str());
1536 // Multiple midi channels? that's just crazy talk
1537 assert(nchans == 1);
1539 if ((prop = node.property (X_("source-0"))) == 0) {
1540 if ((prop = node.property ("source")) == 0) {
1541 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1542 return boost::shared_ptr<MidiRegion>();
1546 PBD::ID s_id (prop->value());
1548 if ((source = source_by_id (s_id)) == 0) {
1549 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1550 return boost::shared_ptr<MidiRegion>();
1553 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1555 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1556 return boost::shared_ptr<MidiRegion>();
1559 sources.push_back (ms);
1562 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1566 catch (failed_constructor& err) {
1567 return boost::shared_ptr<MidiRegion>();
1572 Session::get_sources_as_xml ()
1575 XMLNode* node = new XMLNode (X_("Sources"));
1576 Glib::Mutex::Lock lm (source_lock);
1578 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1579 node->add_child_nocopy (i->second->get_state());
1582 /* XXX get MIDI and other sources here */
1588 Session::path_from_region_name (string name, string identifier)
1590 char buf[PATH_MAX+1];
1592 string dir = discover_best_sound_dir ();
1594 for (n = 0; n < 999999; ++n) {
1595 if (identifier.length()) {
1596 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1597 identifier.c_str(), n);
1599 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1602 if (!Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
1607 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1616 Session::load_sources (const XMLNode& node)
1619 XMLNodeConstIterator niter;
1620 boost::shared_ptr<Source> source;
1622 nlist = node.children();
1626 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1629 if ((source = XMLSourceFactory (**niter)) == 0) {
1630 error << _("Session: cannot create Source from XML description.") << endmsg;
1634 catch (non_existent_source& err) {
1635 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1636 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1643 boost::shared_ptr<Source>
1644 Session::XMLSourceFactory (const XMLNode& node)
1646 if (node.name() != "Source") {
1647 return boost::shared_ptr<Source>();
1651 return SourceFactory::create (*this, node);
1654 catch (failed_constructor& err) {
1655 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1656 return boost::shared_ptr<Source>();
1661 Session::save_template (string template_name)
1664 string xml_path, bak_path, template_path;
1666 if (_state_of_the_state & CannotSave) {
1671 string dir = template_dir();
1673 if ((dp = opendir (dir.c_str()))) {
1676 if (g_mkdir_with_parents (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
1677 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1682 tree.set_root (&get_template());
1685 xml_path += template_name;
1686 xml_path += template_suffix;
1688 ifstream in(xml_path.c_str());
1691 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1697 if (!tree.write (xml_path)) {
1698 error << _("mix template not saved") << endmsg;
1706 Session::rename_template (string old_name, string new_name)
1708 string old_path = template_dir() + old_name + template_suffix;
1709 string new_path = template_dir() + new_name + template_suffix;
1711 return rename (old_path.c_str(), new_path.c_str());
1715 Session::delete_template (string name)
1717 string template_path = template_dir();
1718 template_path += name;
1719 template_path += template_suffix;
1721 return remove (template_path.c_str());
1725 Session::refresh_disk_space ()
1728 struct statfs statfsbuf;
1729 vector<space_and_path>::iterator i;
1730 Glib::Mutex::Lock lm (space_lock);
1733 /* get freespace on every FS that is part of the session path */
1735 _total_free_4k_blocks = 0;
1737 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1738 statfs ((*i).path.c_str(), &statfsbuf);
1740 scale = statfsbuf.f_bsize/4096.0;
1742 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1743 _total_free_4k_blocks += (*i).blocks;
1749 Session::ensure_sound_dir (string path, string& result)
1754 /* Ensure that the parent directory exists */
1756 if (g_mkdir_with_parents (path.c_str(), 0775)) {
1757 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
1761 /* Ensure that the sounds directory exists */
1765 result += sound_dir_name;
1767 if (g_mkdir_with_parents (result.c_str(), 0775)) {
1768 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
1774 dead += dead_sound_dir_name;
1776 if (g_mkdir_with_parents (dead.c_str(), 0775)) {
1777 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
1783 peak += peak_dir_name;
1785 if (g_mkdir_with_parents (peak.c_str(), 0775)) {
1786 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
1790 /* callers expect this to be terminated ... */
1797 Session::discover_best_sound_dir (bool destructive)
1799 vector<space_and_path>::iterator i;
1802 /* handle common case without system calls */
1804 if (session_dirs.size() == 1) {
1808 /* OK, here's the algorithm we're following here:
1810 We want to select which directory to use for
1811 the next file source to be created. Ideally,
1812 we'd like to use a round-robin process so as to
1813 get maximum performance benefits from splitting
1814 the files across multiple disks.
1816 However, in situations without much diskspace, an
1817 RR approach may end up filling up a filesystem
1818 with new files while others still have space.
1819 Its therefore important to pay some attention to
1820 the freespace in the filesystem holding each
1821 directory as well. However, if we did that by
1822 itself, we'd keep creating new files in the file
1823 system with the most space until it was as full
1824 as all others, thus negating any performance
1825 benefits of this RAID-1 like approach.
1827 So, we use a user-configurable space threshold. If
1828 there are at least 2 filesystems with more than this
1829 much space available, we use RR selection between them.
1830 If not, then we pick the filesystem with the most space.
1832 This gets a good balance between the two
1836 refresh_disk_space ();
1838 int free_enough = 0;
1840 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1841 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1846 if (free_enough >= 2) {
1848 bool found_it = false;
1850 /* use RR selection process, ensuring that the one
1854 i = last_rr_session_dir;
1857 if (++i == session_dirs.end()) {
1858 i = session_dirs.begin();
1861 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1862 if (ensure_sound_dir ((*i).path, result) == 0) {
1863 last_rr_session_dir = i;
1869 } while (i != last_rr_session_dir);
1872 result = sound_dir();
1877 /* pick FS with the most freespace (and that
1878 seems to actually work ...)
1881 vector<space_and_path> sorted;
1882 space_and_path_ascending_cmp cmp;
1884 sorted = session_dirs;
1885 sort (sorted.begin(), sorted.end(), cmp);
1887 for (i = sorted.begin(); i != sorted.end(); ++i) {
1888 if (ensure_sound_dir ((*i).path, result) == 0) {
1889 last_rr_session_dir = i;
1894 /* if the above fails, fall back to the most simplistic solution */
1896 if (i == sorted.end()) {
1905 Session::load_playlists (const XMLNode& node)
1908 XMLNodeConstIterator niter;
1909 boost::shared_ptr<Playlist> playlist;
1911 nlist = node.children();
1915 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1917 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1918 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1926 Session::load_unused_playlists (const XMLNode& node)
1929 XMLNodeConstIterator niter;
1930 boost::shared_ptr<Playlist> playlist;
1932 nlist = node.children();
1936 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1938 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1939 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1943 // now manually untrack it
1945 track_playlist (false, boost::weak_ptr<Playlist> (playlist));
1951 boost::shared_ptr<Playlist>
1952 Session::XMLPlaylistFactory (const XMLNode& node)
1955 return PlaylistFactory::create (*this, node);
1958 catch (failed_constructor& err) {
1959 return boost::shared_ptr<Playlist>();
1964 Session::load_named_selections (const XMLNode& node)
1967 XMLNodeConstIterator niter;
1970 nlist = node.children();
1974 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1976 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
1977 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
1985 Session::XMLNamedSelectionFactory (const XMLNode& node)
1988 return new NamedSelection (*this, node);
1991 catch (failed_constructor& err) {
1997 Session::dead_sound_dir () const
2000 res += dead_sound_dir_name;
2006 Session::old_sound_dir (bool with_path) const
2014 res += old_sound_dir_name;
2020 Session::sound_dir (bool with_path) const
2031 res += interchange_dir_name;
2033 res += legalize_for_path (_name);
2035 res += sound_dir_name;
2043 /* if this already exists, don't check for the old session sound directory */
2045 if (Glib::file_test (full, Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
2049 /* possibly support old session structure */
2052 string old_withpath;
2054 old_nopath += old_sound_dir_name;
2057 old_withpath = _path;
2058 old_withpath += old_sound_dir_name;
2060 if (Glib::file_test (old_withpath.c_str(), Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
2062 return old_withpath;
2067 /* ok, old "sounds" directory isn't there, return the new path */
2073 Session::peak_dir () const
2076 res += peak_dir_name;
2082 Session::automation_dir () const
2085 res += "automation/";
2090 Session::template_dir ()
2092 string path = get_user_ardour_path();
2093 path += "templates/";
2099 Session::export_dir () const
2102 res += export_dir_name;
2108 Session::suffixed_search_path (string suffix, bool data)
2112 path += get_user_ardour_path();
2113 if (path[path.length()-1] != ':') {
2118 path += get_system_data_path();
2120 path += get_system_module_path();
2123 vector<string> split_path;
2125 split (path, split_path, ':');
2128 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2133 if (distance (i, split_path.end()) != 1) {
2142 Session::template_path ()
2144 return suffixed_search_path (X_("templates"), true);
2148 Session::control_protocol_path ()
2150 return suffixed_search_path (X_("surfaces"), false);
2154 Session::load_connections (const XMLNode& node)
2156 XMLNodeList nlist = node.children();
2157 XMLNodeConstIterator niter;
2161 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2162 if ((*niter)->name() == "InputConnection") {
2163 add_connection (new ARDOUR::InputConnection (**niter));
2164 } else if ((*niter)->name() == "OutputConnection") {
2165 add_connection (new ARDOUR::OutputConnection (**niter));
2167 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2176 Session::load_edit_groups (const XMLNode& node)
2178 return load_route_groups (node, true);
2182 Session::load_mix_groups (const XMLNode& node)
2184 return load_route_groups (node, false);
2188 Session::load_route_groups (const XMLNode& node, bool edit)
2190 XMLNodeList nlist = node.children();
2191 XMLNodeConstIterator niter;
2196 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2197 if ((*niter)->name() == "RouteGroup") {
2199 rg = add_edit_group ("");
2200 rg->set_state (**niter);
2202 rg = add_mix_group ("");
2203 rg->set_state (**niter);
2212 state_file_filter (const string &str, void *arg)
2214 return (str.length() > strlen(statefile_suffix) &&
2215 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2219 bool operator()(const string* a, const string* b) {
2225 remove_end(string* state)
2227 string statename(*state);
2229 string::size_type start,end;
2230 if ((start = statename.find_last_of ('/')) != string::npos) {
2231 statename = statename.substr (start+1);
2234 if ((end = statename.rfind(".ardour")) == string::npos) {
2235 end = statename.length();
2238 return new string(statename.substr (0, end));
2242 Session::possible_states (string path)
2244 PathScanner scanner;
2245 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2247 transform(states->begin(), states->end(), states->begin(), remove_end);
2250 sort (states->begin(), states->end(), cmp);
2256 Session::possible_states () const
2258 return possible_states(_path);
2262 Session::auto_save()
2264 save_state (_current_snapshot_name);
2268 Session::add_edit_group (string name)
2270 RouteGroup* rg = new RouteGroup (*this, name);
2271 edit_groups.push_back (rg);
2272 edit_group_added (rg); /* EMIT SIGNAL */
2278 Session::add_mix_group (string name)
2280 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2281 mix_groups.push_back (rg);
2282 mix_group_added (rg); /* EMIT SIGNAL */
2288 Session::remove_edit_group (RouteGroup& rg)
2290 list<RouteGroup*>::iterator i;
2292 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2293 (*i)->apply (&Route::drop_edit_group, this);
2294 edit_groups.erase (i);
2295 edit_group_removed (); /* EMIT SIGNAL */
2302 Session::remove_mix_group (RouteGroup& rg)
2304 list<RouteGroup*>::iterator i;
2306 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2307 (*i)->apply (&Route::drop_mix_group, this);
2308 mix_groups.erase (i);
2309 mix_group_removed (); /* EMIT SIGNAL */
2316 Session::mix_group_by_name (string name)
2318 list<RouteGroup *>::iterator i;
2320 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2321 if ((*i)->name() == name) {
2329 Session::edit_group_by_name (string name)
2331 list<RouteGroup *>::iterator i;
2333 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2334 if ((*i)->name() == name) {
2342 Session::begin_reversible_command (string name)
2344 current_trans = new UndoTransaction;
2345 current_trans->set_name (name);
2349 Session::commit_reversible_command (Command *cmd)
2354 current_trans->add_command (cmd);
2357 gettimeofday (&now, 0);
2358 current_trans->set_timestamp (now);
2360 _history.add (current_trans);
2363 Session::GlobalRouteBooleanState
2364 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2366 GlobalRouteBooleanState s;
2367 boost::shared_ptr<RouteList> r = routes.reader ();
2369 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2370 if (!(*i)->hidden()) {
2371 RouteBooleanState v;
2374 Route* r = (*i).get();
2375 v.second = (r->*method)();
2384 Session::GlobalRouteMeterState
2385 Session::get_global_route_metering ()
2387 GlobalRouteMeterState s;
2388 boost::shared_ptr<RouteList> r = routes.reader ();
2390 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2391 if (!(*i)->hidden()) {
2395 v.second = (*i)->meter_point();
2405 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2407 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2409 boost::shared_ptr<Route> r = (i->first.lock());
2412 r->set_meter_point (i->second, arg);
2418 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2420 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2422 boost::shared_ptr<Route> r = (i->first.lock());
2425 Route* rp = r.get();
2426 (rp->*method) (i->second, arg);
2432 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2434 set_global_route_boolean (s, &Route::set_mute, src);
2438 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2440 set_global_route_boolean (s, &Route::set_solo, src);
2444 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2446 set_global_route_boolean (s, &Route::set_record_enable, src);
2451 Session::global_mute_memento (void* src)
2453 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2457 Session::global_metering_memento (void* src)
2459 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2463 Session::global_solo_memento (void* src)
2465 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2469 Session::global_record_enable_memento (void* src)
2471 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2476 template_filter (const string &str, void *arg)
2478 return (str.length() > strlen(template_suffix) &&
2479 str.find (template_suffix) == (str.length() - strlen (template_suffix)));
2483 Session::get_template_list (list<string> &template_names)
2485 vector<string *> *templates;
2486 PathScanner scanner;
2489 path = template_path ();
2491 templates = scanner (path, template_filter, 0, false, true);
2493 vector<string*>::iterator i;
2494 for (i = templates->begin(); i != templates->end(); ++i) {
2495 string fullpath = *(*i);
2498 start = fullpath.find_last_of ('/') + 1;
2499 if ((end = fullpath.find_last_of ('.')) <0) {
2500 end = fullpath.length();
2503 template_names.push_back(fullpath.substr(start, (end-start)));
2508 Session::read_favorite_dirs (FavoriteDirs & favs)
2510 string path = get_user_ardour_path();
2511 path += "/favorite_dirs";
2513 ifstream fav (path.c_str());
2518 if (errno != ENOENT) {
2519 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2530 getline(fav, newfav);
2536 favs.push_back (newfav);
2543 Session::write_favorite_dirs (FavoriteDirs & favs)
2545 string path = get_user_ardour_path();
2546 path += "/favorite_dirs";
2548 ofstream fav (path.c_str());
2554 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2555 fav << (*i) << endl;
2562 accept_all_non_peak_files (const string& path, void *arg)
2564 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2568 accept_all_state_files (const string& path, void *arg)
2570 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2574 Session::find_all_sources (string path, set<string>& result)
2579 if (!tree.read (path)) {
2583 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2588 XMLNodeConstIterator niter;
2590 nlist = node->children();
2594 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2598 if ((prop = (*niter)->property (X_("name"))) == 0) {
2602 if (prop->value()[0] == '/') {
2603 /* external file, ignore */
2607 string path = _path; /* /-terminated */
2608 path += sound_dir_name;
2610 path += prop->value();
2612 result.insert (path);
2619 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2621 PathScanner scanner;
2622 vector<string*>* state_files;
2624 string this_snapshot_path;
2630 if (ripped[ripped.length()-1] == '/') {
2631 ripped = ripped.substr (0, ripped.length() - 1);
2634 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2636 if (state_files == 0) {
2641 this_snapshot_path = _path;
2642 this_snapshot_path += _current_snapshot_name;
2643 this_snapshot_path += statefile_suffix;
2645 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2647 if (exclude_this_snapshot && **i == this_snapshot_path) {
2651 if (find_all_sources (**i, result) < 0) {
2659 struct RegionCounter {
2660 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2661 AudioSourceList::iterator iter;
2662 boost::shared_ptr<Region> region;
2665 RegionCounter() : count (0) {}
2669 Session::cleanup_sources (Session::cleanup_report& rep)
2671 vector<boost::shared_ptr<Source> > dead_sources;
2672 vector<boost::shared_ptr<Playlist> > playlists_tbd;
2673 PathScanner scanner;
2675 vector<space_and_path>::iterator i;
2676 vector<space_and_path>::iterator nexti;
2677 vector<string*>* soundfiles;
2678 vector<string> unused;
2679 set<string> all_sources;
2684 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2686 /* step 1: consider deleting all unused playlists */
2688 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2691 status = AskAboutPlaylistDeletion (*x);
2700 playlists_tbd.push_back (*x);
2704 /* leave it alone */
2709 /* now delete any that were marked for deletion */
2711 for (vector<boost::shared_ptr<Playlist> >::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2712 (*x)->drop_references ();
2715 playlists_tbd.clear ();
2717 /* step 2: find all un-used sources */
2722 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2724 SourceMap::iterator tmp;
2729 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2733 if (!i->second->used() && i->second->length() > 0) {
2734 dead_sources.push_back (i->second);
2735 i->second->GoingAway();
2741 /* build a list of all the possible sound directories for the session */
2743 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2748 sound_path += (*i).path;
2749 sound_path += sound_dir (false);
2751 if (nexti != session_dirs.end()) {
2758 /* now do the same thing for the files that ended up in the sounds dir(s)
2759 but are not referenced as sources in any snapshot.
2762 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2764 if (soundfiles == 0) {
2768 /* find all sources, but don't use this snapshot because the
2769 state file on disk still references sources we may have already
2773 find_all_sources_across_snapshots (all_sources, true);
2775 /* add our current source list
2778 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2779 boost::shared_ptr<AudioFileSource> fs;
2781 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (i->second)) != 0) {
2782 all_sources.insert (fs->path());
2786 char tmppath1[PATH_MAX+1];
2787 char tmppath2[PATH_MAX+1];
2789 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2794 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2796 realpath(spath.c_str(), tmppath1);
2797 realpath((*i).c_str(), tmppath2);
2799 if (strcmp(tmppath1, tmppath2) == 0) {
2806 unused.push_back (spath);
2810 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2812 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2813 struct stat statbuf;
2815 rep.paths.push_back (*x);
2816 if (stat ((*x).c_str(), &statbuf) == 0) {
2817 rep.space += statbuf.st_size;
2822 /* don't move the file across filesystems, just
2823 stick it in the `dead_sound_dir_name' directory
2824 on whichever filesystem it was already on.
2827 if ((*x).find ("/sounds/") != string::npos) {
2829 /* old school, go up 1 level */
2831 newpath = Glib::path_get_dirname (*x); // "sounds"
2832 newpath = Glib::path_get_dirname (newpath); // "session-name"
2836 /* new school, go up 4 levels */
2838 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2839 newpath = Glib::path_get_dirname (newpath); // "session-name"
2840 newpath = Glib::path_get_dirname (newpath); // "interchange"
2841 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2845 newpath += dead_sound_dir_name;
2847 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2848 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2853 newpath += Glib::path_get_basename ((*x));
2855 if (access (newpath.c_str(), F_OK) == 0) {
2857 /* the new path already exists, try versioning */
2859 char buf[PATH_MAX+1];
2863 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2866 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2867 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2871 if (version == 999) {
2872 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2876 newpath = newpath_v;
2881 /* it doesn't exist, or we can't read it or something */
2885 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2886 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2887 (*x), newpath, strerror (errno))
2892 /* see if there an easy to find peakfile for this file, and remove it.
2895 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2896 peakpath += ".peak";
2898 if (access (peakpath.c_str(), W_OK) == 0) {
2899 if (::unlink (peakpath.c_str()) != 0) {
2900 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2901 peakpath, _path, strerror (errno))
2903 /* try to back out */
2904 rename (newpath.c_str(), _path.c_str());
2912 /* dump the history list */
2916 /* save state so we don't end up a session file
2917 referring to non-existent sources.
2923 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2928 Session::cleanup_trash_sources (Session::cleanup_report& rep)
2930 vector<space_and_path>::iterator i;
2931 string dead_sound_dir;
2932 struct dirent* dentry;
2933 struct stat statbuf;
2939 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2941 dead_sound_dir = (*i).path;
2942 dead_sound_dir += dead_sound_dir_name;
2944 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2948 while ((dentry = readdir (dead)) != 0) {
2950 /* avoid '.' and '..' */
2952 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2953 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2959 fullpath = dead_sound_dir;
2961 fullpath += dentry->d_name;
2963 if (stat (fullpath.c_str(), &statbuf)) {
2967 if (!S_ISREG (statbuf.st_mode)) {
2971 if (unlink (fullpath.c_str())) {
2972 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2973 fullpath, strerror (errno))
2977 rep.paths.push_back (dentry->d_name);
2978 rep.space += statbuf.st_size;
2989 Session::set_dirty ()
2991 bool was_dirty = dirty();
2993 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2996 DirtyChanged(); /* EMIT SIGNAL */
3002 Session::set_clean ()
3004 bool was_dirty = dirty();
3006 _state_of_the_state = Clean;
3009 DirtyChanged(); /* EMIT SIGNAL */
3014 Session::set_deletion_in_progress ()
3016 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3020 Session::add_controllable (Controllable* c)
3022 /* this adds a controllable to the list managed by the Session.
3023 this is a subset of those managed by the Controllable class
3024 itself, and represents the only ones whose state will be saved
3025 as part of the session.
3028 Glib::Mutex::Lock lm (controllables_lock);
3029 controllables.insert (c);
3033 Session::remove_controllable (Controllable* c)
3035 if (_state_of_the_state | Deletion) {
3039 Glib::Mutex::Lock lm (controllables_lock);
3041 Controllables::iterator x = controllables.find (c);
3043 if (x != controllables.end()) {
3044 controllables.erase (x);
3049 Session::controllable_by_id (const PBD::ID& id)
3051 Glib::Mutex::Lock lm (controllables_lock);
3053 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3054 if ((*i)->id() == id) {
3063 Session::add_instant_xml (XMLNode& node, const std::string& dir)
3065 Stateful::add_instant_xml (node, dir);
3066 Config->add_instant_xml (node, get_user_ardour_path());
3071 Session::save_history (string snapshot_name)
3077 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3079 if (snapshot_name.empty()) {
3080 snapshot_name = _current_snapshot_name;
3083 xml_path = _path + snapshot_name + ".history";
3085 bak_path = xml_path + ".bak";
3087 if ((access (xml_path.c_str(), F_OK) == 0) &&
3088 (rename (xml_path.c_str(), bak_path.c_str())))
3090 error << _("could not backup old history file, current history not saved.") << endmsg;
3094 if (!tree.write (xml_path))
3096 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3098 /* don't leave a corrupt file lying around if it is
3102 if (unlink (xml_path.c_str())) {
3103 error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
3105 if (rename (bak_path.c_str(), xml_path.c_str()))
3107 error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;
3118 Session::restore_history (string snapshot_name)
3123 if (snapshot_name.empty()) {
3124 snapshot_name = _current_snapshot_name;
3128 xmlpath = _path + snapshot_name + ".history";
3129 cerr << string_compose(_("Loading history from '%1'."), xmlpath) << endmsg;
3131 if (access (xmlpath.c_str(), F_OK)) {
3132 info << string_compose (_("%1: no history file \"%2\" for this session."), _name, xmlpath) << endmsg;
3136 if (!tree.read (xmlpath)) {
3137 error << string_compose (_("Could not understand session history file \"%1\""), xmlpath) << endmsg;
3141 /* replace history */
3144 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3147 UndoTransaction* ut = new UndoTransaction ();
3150 ut->set_name(t->property("name")->value());
3151 stringstream ss(t->property("tv_sec")->value());
3153 ss.str(t->property("tv_usec")->value());
3155 ut->set_timestamp(tv);
3157 for (XMLNodeConstIterator child_it = t->children().begin();
3158 child_it != t->children().end();
3161 XMLNode *n = *child_it;
3164 if (n->name() == "MementoCommand" ||
3165 n->name() == "MementoUndoCommand" ||
3166 n->name() == "MementoRedoCommand") {
3168 if ((c = memento_command_factory(n))) {
3172 } else if (n->name() == X_("GlobalRouteStateCommand")) {
3174 if ((c = global_state_command_factory (*n))) {
3175 ut->add_command (c);
3180 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3191 Session::config_changed (const char* parameter_name)
3193 #define PARAM_IS(x) (!strcmp (parameter_name, (x)))
3195 if (PARAM_IS ("seamless-loop")) {
3197 } else if (PARAM_IS ("rf-speed")) {
3199 } else if (PARAM_IS ("auto-loop")) {
3201 } else if (PARAM_IS ("auto-input")) {
3203 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3204 /* auto-input only makes a difference if we're rolling */
3206 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3208 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3209 if ((*i)->record_enabled ()) {
3210 (*i)->monitor_input (!Config->get_auto_input());
3215 } else if (PARAM_IS ("punch-in")) {
3219 if ((location = _locations.auto_punch_location()) != 0) {
3221 if (Config->get_punch_in ()) {
3222 replace_event (Event::PunchIn, location->start());
3224 remove_event (location->start(), Event::PunchIn);
3228 } else if (PARAM_IS ("punch-out")) {
3232 if ((location = _locations.auto_punch_location()) != 0) {
3234 if (Config->get_punch_out()) {
3235 replace_event (Event::PunchOut, location->end());
3237 clear_events (Event::PunchOut);
3241 } else if (PARAM_IS ("edit-mode")) {
3243 Glib::Mutex::Lock lm (playlist_lock);
3245 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3246 (*i)->set_edit_mode (Config->get_edit_mode ());
3249 } else if (PARAM_IS ("use-video-sync")) {
3251 waiting_for_sync_offset = Config->get_use_video_sync();
3253 } else if (PARAM_IS ("mmc-control")) {
3255 //poke_midi_thread ();
3257 } else if (PARAM_IS ("mmc-device-id")) {
3260 mmc->set_device_id (Config->get_mmc_device_id());
3263 } else if (PARAM_IS ("midi-control")) {
3265 //poke_midi_thread ();
3267 } else if (PARAM_IS ("raid-path")) {
3269 setup_raid_path (Config->get_raid_path());
3271 } else if (PARAM_IS ("smpte-format")) {
3275 } else if (PARAM_IS ("video-pullup")) {
3279 } else if (PARAM_IS ("seamless-loop")) {
3281 if (play_loop && transport_rolling()) {
3282 // to reset diskstreams etc
3283 request_play_loop (true);
3286 } else if (PARAM_IS ("rf-speed")) {
3288 cumulative_rf_motion = 0;
3291 } else if (PARAM_IS ("click-sound")) {
3293 setup_click_sounds (1);
3295 } else if (PARAM_IS ("click-emphasis-sound")) {
3297 setup_click_sounds (-1);
3299 } else if (PARAM_IS ("clicking")) {
3301 if (Config->get_clicking()) {
3302 if (_click_io && click_data) { // don't require emphasis data
3309 } else if (PARAM_IS ("send-mtc")) {
3311 /* only set the internal flag if we have
3315 if (_mtc_port != 0) {
3316 session_send_mtc = Config->get_send_mtc();
3317 if (session_send_mtc) {
3318 /* mark us ready to send */
3319 next_quarter_frame_to_send = 0;
3322 session_send_mtc = false;
3325 } else if (PARAM_IS ("send-mmc")) {
3327 /* only set the internal flag if we have
3331 if (_mmc_port != 0) {
3332 session_send_mmc = Config->get_send_mmc();
3335 session_send_mmc = false;
3338 } else if (PARAM_IS ("midi-feedback")) {
3340 /* only set the internal flag if we have
3344 if (_mtc_port != 0) {
3345 session_midi_feedback = Config->get_midi_feedback();
3348 } else if (PARAM_IS ("jack-time-master")) {
3350 engine().reset_timebase ();
3352 } else if (PARAM_IS ("native-file-header-format")) {
3354 if (!first_file_header_format_reset) {
3355 reset_native_file_format ();
3358 first_file_header_format_reset = false;
3360 } else if (PARAM_IS ("native-file-data-format")) {
3362 if (!first_file_data_format_reset) {
3363 reset_native_file_format ();
3366 first_file_data_format_reset = false;
3368 } else if (PARAM_IS ("slave-source")) {
3369 set_slave_source (Config->get_slave_source());
3370 } else if (PARAM_IS ("remote-model")) {
3371 set_remote_control_ids ();