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>
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::create (bool& new_session, string* mix_template, nframes_t initial_length)
471 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
472 error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
478 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
479 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
483 /* if this is is an existing session with an old "sounds" directory, just use it. see Session::sound_dir() for more details */
485 if (!Glib::file_test (old_sound_dir(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
489 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
490 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
495 dir = dead_sound_dir ();
497 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
498 error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
504 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
505 error << string_compose(_("Session: cannot create session export dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
510 /* check new_session so we don't overwrite an existing one */
513 std::string in_path = *mix_template;
515 ifstream in(in_path.c_str());
518 string out_path = _path;
520 out_path += _statefile_suffix;
522 ofstream out(out_path.c_str());
527 // okay, session is set up. Treat like normal saved
528 // session from now on.
534 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
540 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
547 /* set initial start + end point */
549 start_location->set_end (0);
550 _locations.add (start_location);
552 end_location->set_end (initial_length);
553 _locations.add (end_location);
555 _state_of_the_state = Clean;
557 if (save_state (_current_snapshot_name)) {
565 Session::load_diskstreams (const XMLNode& node)
568 XMLNodeConstIterator citer;
570 clist = node.children();
572 for (citer = clist.begin(); citer != clist.end(); ++citer) {
575 /* diskstreams added automatically by DiskstreamCreated handler */
576 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
577 boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
578 add_diskstream (dstream);
579 } else if ((*citer)->name() == "MidiDiskstream") {
580 boost::shared_ptr<MidiDiskstream> dstream (new MidiDiskstream (*this, **citer));
581 add_diskstream (dstream);
583 error << _("Session: unknown diskstream type in XML") << endmsg;
587 catch (failed_constructor& err) {
588 error << _("Session: could not load diskstream via XML state") << endmsg;
597 Session::remove_pending_capture_state ()
602 xml_path += _current_snapshot_name;
603 xml_path += _pending_suffix;
605 unlink (xml_path.c_str());
608 /** Rename a state file.
609 * @param snapshot_name Snapshot name.
612 Session::rename_state (string old_name, string new_name)
614 if (old_name == _current_snapshot_name || old_name == _name) {
615 /* refuse to rename the current snapshot or the "main" one */
619 const string old_xml_path = _path + old_name + _statefile_suffix;
620 const string new_xml_path = _path + new_name + _statefile_suffix;
622 if (rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
623 error << string_compose(_("could not rename snapshot %1 to %2"), old_name, new_name) << endmsg;
627 /** Remove a state file.
628 * @param snapshot_name Snapshot name.
631 Session::remove_state (string snapshot_name)
633 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
634 /* refuse to remove the current snapshot or the "main" one */
638 const string xml_path = _path + snapshot_name + _statefile_suffix;
640 /* make a backup copy of the state file */
641 const string bak_path = xml_path + ".bak";
642 if (g_file_test (xml_path.c_str(), G_FILE_TEST_EXISTS)) {
643 copy_file (xml_path, bak_path);
647 unlink (xml_path.c_str());
651 Session::save_state (string snapshot_name, bool pending)
657 if (_state_of_the_state & CannotSave) {
661 if (!_engine.connected ()) {
662 error << _("Ardour's audio engine is not connected and state saving would lose all I/O connections. Session not saved")
667 tree.set_root (&get_state());
669 if (snapshot_name.empty()) {
670 snapshot_name = _current_snapshot_name;
675 /* proper save: use _statefile_suffix (.ardour in English) */
677 xml_path += snapshot_name;
678 xml_path += _statefile_suffix;
680 /* make a backup copy of the old file */
684 if (g_file_test (xml_path.c_str(), G_FILE_TEST_EXISTS)) {
685 copy_file (xml_path, bak_path);
690 /* pending save: use _pending_suffix (.pending in English) */
692 xml_path += snapshot_name;
693 xml_path += _pending_suffix;
700 tmp_path += snapshot_name;
703 cerr << "actually writing state\n";
705 if (!tree.write (tmp_path)) {
706 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
707 unlink (tmp_path.c_str());
712 if (rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
713 error << string_compose (_("could not rename temporary session file %1 to %2"), tmp_path, xml_path) << endmsg;
714 unlink (tmp_path.c_str());
721 save_history (snapshot_name);
723 bool was_dirty = dirty();
725 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
728 DirtyChanged (); /* EMIT SIGNAL */
731 StateSaved (snapshot_name); /* EMIT SIGNAL */
738 Session::restore_state (string snapshot_name)
740 if (load_state (snapshot_name) == 0) {
741 set_state (*state_tree->root());
748 Session::load_state (string snapshot_name)
757 state_was_pending = false;
759 /* check for leftover pending state from a crashed capture attempt */
762 xmlpath += snapshot_name;
763 xmlpath += _pending_suffix;
765 if (!access (xmlpath.c_str(), F_OK)) {
767 /* there is pending state from a crashed capture attempt */
769 if (AskAboutPendingState()) {
770 state_was_pending = true;
774 if (!state_was_pending) {
777 xmlpath += snapshot_name;
778 xmlpath += _statefile_suffix;
781 if (access (xmlpath.c_str(), F_OK)) {
782 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
786 state_tree = new XMLTree;
790 if (!state_tree->read (xmlpath)) {
791 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
797 XMLNode& root (*state_tree->root());
799 if (root.name() != X_("Session")) {
800 error << string_compose (_("Session file %1 is not an Ardour session"), xmlpath) << endmsg;
806 const XMLProperty* prop;
809 if ((prop = root.property ("version")) == 0) {
810 /* no version implies very old version of Ardour */
814 major_version = atoi (prop->value()); // grab just the first number before the period
815 if (major_version < 2) {
823 backup_path = xmlpath;
826 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with Ardour versions before 2.0 from now on"),
827 xmlpath, backup_path)
830 copy_file (xmlpath, backup_path);
832 /* if it fails, don't worry. right? */
839 Session::load_options (const XMLNode& node)
843 LocaleGuard lg (X_("POSIX"));
845 Config->set_variables (node, ConfigVariableBase::Session);
847 if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
848 if ((prop = child->property ("val")) != 0) {
849 _end_location_is_free = (prop->value() == "yes");
857 Session::save_config_options_predicate (ConfigVariableBase::Owner owner) const
859 const ConfigVariableBase::Owner modified_by_session_or_user = (ConfigVariableBase::Owner)
860 (ConfigVariableBase::Session|ConfigVariableBase::Interface);
862 return owner & modified_by_session_or_user;
866 Session::get_options () const
869 LocaleGuard lg (X_("POSIX"));
871 XMLNode& option_root = Config->get_variables (mem_fun (*this, &Session::save_config_options_predicate));
873 child = option_root.add_child ("end-marker-is-free");
874 child->add_property ("val", _end_location_is_free ? "yes" : "no");
886 Session::get_template()
888 /* if we don't disable rec-enable, diskstreams
889 will believe they need to store their capture
890 sources in their state node.
893 disable_record (false);
899 Session::state(bool full_state)
901 XMLNode* node = new XMLNode("Session");
904 // store libardour version, just in case
906 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
907 libardour_major_version, libardour_minor_version, libardour_micro_version);
908 node->add_property("version", string(buf));
910 /* store configuration settings */
915 node->add_property ("name", _name);
917 if (session_dirs.size() > 1) {
921 vector<space_and_path>::iterator i = session_dirs.begin();
922 vector<space_and_path>::iterator next;
924 ++i; /* skip the first one */
928 while (i != session_dirs.end()) {
932 if (next != session_dirs.end()) {
942 child = node->add_child ("Path");
943 child->add_content (p);
947 /* save the ID counter */
949 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
950 node->add_property ("id-counter", buf);
952 /* various options */
954 node->add_child_nocopy (get_options());
956 child = node->add_child ("Sources");
959 Glib::Mutex::Lock sl (source_lock);
961 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
963 /* Don't save information about AudioFileSources that are empty */
965 boost::shared_ptr<AudioFileSource> fs;
967 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
969 /* Don't save sources that are empty, unless they're destructive (which are OK
970 if they are empty, because we will re-use them every time.)
973 if (!fs->destructive()) {
974 if (fs->length() == 0) {
980 child->add_child_nocopy (siter->second->get_state());
984 child = node->add_child ("Regions");
987 Glib::Mutex::Lock rl (region_lock);
989 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
991 /* only store regions not attached to playlists */
993 if (i->second->playlist() == 0) {
994 child->add_child_nocopy (i->second->state (true));
999 child = node->add_child ("DiskStreams");
1002 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1003 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1004 if (!(*i)->hidden()) {
1005 child->add_child_nocopy ((*i)->get_state());
1011 node->add_child_nocopy (_locations.get_state());
1013 // for a template, just create a new Locations, populate it
1014 // with the default start and end, and get the state for that.
1016 Location* start = new Location(0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
1017 Location* end = new Location(0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
1020 end->set_end(compute_initial_length());
1022 node->add_child_nocopy (loc.get_state());
1025 child = node->add_child ("Connections");
1027 Glib::Mutex::Lock lm (connection_lock);
1028 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1029 if (!(*i)->system_dependent()) {
1030 child->add_child_nocopy ((*i)->get_state());
1035 child = node->add_child ("Routes");
1037 boost::shared_ptr<RouteList> r = routes.reader ();
1039 RoutePublicOrderSorter cmp;
1040 RouteList public_order (*r);
1041 public_order.sort (cmp);
1043 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1044 if (!(*i)->hidden()) {
1046 child->add_child_nocopy ((*i)->get_state());
1048 child->add_child_nocopy ((*i)->get_template());
1055 child = node->add_child ("EditGroups");
1056 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1057 child->add_child_nocopy ((*i)->get_state());
1060 child = node->add_child ("MixGroups");
1061 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1062 child->add_child_nocopy ((*i)->get_state());
1065 child = node->add_child ("Playlists");
1066 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1067 if (!(*i)->hidden()) {
1068 if (!(*i)->empty()) {
1070 child->add_child_nocopy ((*i)->get_state());
1072 child->add_child_nocopy ((*i)->get_template());
1078 child = node->add_child ("UnusedPlaylists");
1079 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1080 if (!(*i)->hidden()) {
1081 if (!(*i)->empty()) {
1083 child->add_child_nocopy ((*i)->get_state());
1085 child->add_child_nocopy ((*i)->get_template());
1093 child = node->add_child ("Click");
1094 child->add_child_nocopy (_click_io->state (full_state));
1098 child = node->add_child ("NamedSelections");
1099 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1101 child->add_child_nocopy ((*i)->get_state());
1106 node->add_child_nocopy (_tempo_map->get_state());
1108 node->add_child_nocopy (get_control_protocol_state());
1111 node->add_child_copy (*_extra_xml);
1118 Session::get_control_protocol_state ()
1120 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1121 return cpm.get_state();
1125 Session::set_state (const XMLNode& node)
1129 const XMLProperty* prop;
1132 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1134 if (node.name() != X_("Session")){
1135 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1139 if ((prop = node.property ("name")) != 0) {
1140 _name = prop->value ();
1143 setup_raid_path(_path);
1145 if ((prop = node.property (X_("id-counter"))) != 0) {
1147 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1148 ID::init_counter (x);
1150 /* old sessions used a timebased counter, so fake
1151 the startup ID counter based on a standard
1156 ID::init_counter (now);
1160 IO::disable_ports ();
1161 IO::disable_connecting ();
1163 /* Object loading order:
1181 if (use_config_midi_ports ()) {
1184 if ((child = find_named_node (node, "extra")) != 0) {
1185 _extra_xml = new XMLNode (*child);
1188 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1189 load_options (*child);
1190 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1191 load_options (*child);
1193 error << _("Session: XML state has no options section") << endmsg;
1196 if ((child = find_named_node (node, "Locations")) == 0) {
1197 error << _("Session: XML state has no locations section") << endmsg;
1199 } else if (_locations.set_state (*child)) {
1205 if ((location = _locations.auto_loop_location()) != 0) {
1206 set_auto_loop_location (location);
1209 if ((location = _locations.auto_punch_location()) != 0) {
1210 set_auto_punch_location (location);
1213 if ((location = _locations.end_location()) == 0) {
1214 _locations.add (end_location);
1216 delete end_location;
1217 end_location = location;
1220 if ((location = _locations.start_location()) == 0) {
1221 _locations.add (start_location);
1223 delete start_location;
1224 start_location = location;
1227 AudioFileSource::set_header_position_offset (start_location->start());
1229 if ((child = find_named_node (node, "Sources")) == 0) {
1230 error << _("Session: XML state has no sources section") << endmsg;
1232 } else if (load_sources (*child)) {
1236 if ((child = find_named_node (node, "Regions")) == 0) {
1237 error << _("Session: XML state has no Regions section") << endmsg;
1239 } else if (load_regions (*child)) {
1243 if ((child = find_named_node (node, "Playlists")) == 0) {
1244 error << _("Session: XML state has no playlists section") << endmsg;
1246 } else if (load_playlists (*child)) {
1250 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1252 } else if (load_unused_playlists (*child)) {
1256 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1257 if (load_named_selections (*child)) {
1262 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1263 error << _("Session: XML state has no diskstreams section") << endmsg;
1265 } else if (load_diskstreams (*child)) {
1269 if ((child = find_named_node (node, "Connections")) == 0) {
1270 error << _("Session: XML state has no connections section") << endmsg;
1272 } else if (load_connections (*child)) {
1276 if ((child = find_named_node (node, "EditGroups")) == 0) {
1277 error << _("Session: XML state has no edit groups section") << endmsg;
1279 } else if (load_edit_groups (*child)) {
1283 if ((child = find_named_node (node, "MixGroups")) == 0) {
1284 error << _("Session: XML state has no mix groups section") << endmsg;
1286 } else if (load_mix_groups (*child)) {
1290 if ((child = find_named_node (node, "TempoMap")) == 0) {
1291 error << _("Session: XML state has no Tempo Map section") << endmsg;
1293 } else if (_tempo_map->set_state (*child)) {
1297 if ((child = find_named_node (node, "Routes")) == 0) {
1298 error << _("Session: XML state has no routes section") << endmsg;
1300 } else if (load_routes (*child)) {
1304 if ((child = find_named_node (node, "Click")) == 0) {
1305 warning << _("Session: XML state has no click section") << endmsg;
1306 } else if (_click_io) {
1307 _click_io->set_state (*child);
1310 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1311 ControlProtocolManager::instance().set_protocol_states (*child);
1314 /* here beginneth the second phase ... */
1316 StateReady (); /* EMIT SIGNAL */
1318 _state_of_the_state = Clean;
1320 if (state_was_pending) {
1321 save_state (_current_snapshot_name);
1322 remove_pending_capture_state ();
1323 state_was_pending = false;
1333 Session::load_routes (const XMLNode& node)
1336 XMLNodeConstIterator niter;
1337 RouteList new_routes;
1339 nlist = node.children();
1343 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1345 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1348 error << _("Session: cannot create Route from XML description.") << endmsg;
1352 new_routes.push_back (route);
1355 add_routes (new_routes);
1360 boost::shared_ptr<Route>
1361 Session::XMLRouteFactory (const XMLNode& node)
1363 if (node.name() != "Route") {
1364 return boost::shared_ptr<Route> ((Route*) 0);
1367 bool has_diskstream = (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0);
1369 DataType type = DataType::AUDIO;
1370 const XMLProperty* prop = node.property("default-type");
1372 type = DataType(prop->value());
1374 assert(type != DataType::NIL);
1376 if (has_diskstream) {
1377 if (type == DataType::AUDIO) {
1378 boost::shared_ptr<Route> ret (new AudioTrack (*this, node));
1381 boost::shared_ptr<Route> ret (new MidiTrack (*this, node));
1385 boost::shared_ptr<Route> ret (new Route (*this, node));
1391 Session::load_regions (const XMLNode& node)
1394 XMLNodeConstIterator niter;
1395 boost::shared_ptr<Region> region;
1397 nlist = node.children();
1401 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1402 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1403 error << _("Session: cannot create Region from XML description.") << endmsg;
1410 boost::shared_ptr<Region>
1411 Session::XMLRegionFactory (const XMLNode& node, bool full)
1413 const XMLProperty* type = node.property("type");
1417 if ( !type || type->value() == "audio" ) {
1419 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1421 } else if (type->value() == "midi") {
1423 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1427 } catch (failed_constructor& err) {
1428 return boost::shared_ptr<Region> ();
1431 return boost::shared_ptr<Region> ();
1434 boost::shared_ptr<AudioRegion>
1435 Session::XMLAudioRegionFactory (const XMLNode& node, bool full)
1437 const XMLProperty* prop;
1438 boost::shared_ptr<Source> source;
1439 boost::shared_ptr<AudioSource> as;
1441 uint32_t nchans = 1;
1444 if (node.name() != X_("Region")) {
1445 return boost::shared_ptr<AudioRegion>();
1448 if ((prop = node.property (X_("channels"))) != 0) {
1449 nchans = atoi (prop->value().c_str());
1453 if ((prop = node.property ("name")) == 0) {
1454 cerr << "no name for this region\n";
1458 if ((prop = node.property (X_("source-0"))) == 0) {
1459 if ((prop = node.property ("source")) == 0) {
1460 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1461 return boost::shared_ptr<AudioRegion>();
1465 PBD::ID s_id (prop->value());
1467 if ((source = source_by_id (s_id)) == 0) {
1468 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1469 return boost::shared_ptr<AudioRegion>();
1472 as = boost::dynamic_pointer_cast<AudioSource>(source);
1474 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1475 return boost::shared_ptr<AudioRegion>();
1478 sources.push_back (as);
1480 /* pickup other channels */
1482 for (uint32_t n=1; n < nchans; ++n) {
1483 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1484 if ((prop = node.property (buf)) != 0) {
1486 PBD::ID id2 (prop->value());
1488 if ((source = source_by_id (id2)) == 0) {
1489 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1490 return boost::shared_ptr<AudioRegion>();
1493 as = boost::dynamic_pointer_cast<AudioSource>(source);
1495 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1496 return boost::shared_ptr<AudioRegion>();
1498 sources.push_back (as);
1503 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1505 /* a final detail: this is the one and only place that we know how long missing files are */
1507 if (region->whole_file()) {
1508 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1509 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1511 sfp->set_length (region->length());
1521 catch (failed_constructor& err) {
1522 return boost::shared_ptr<AudioRegion>();
1526 boost::shared_ptr<MidiRegion>
1527 Session::XMLMidiRegionFactory (const XMLNode& node, bool full)
1529 const XMLProperty* prop;
1530 boost::shared_ptr<Source> source;
1531 boost::shared_ptr<MidiSource> ms;
1532 MidiRegion::SourceList sources;
1533 uint32_t nchans = 1;
1535 if (node.name() != X_("Region")) {
1536 return boost::shared_ptr<MidiRegion>();
1539 if ((prop = node.property (X_("channels"))) != 0) {
1540 nchans = atoi (prop->value().c_str());
1543 // Multiple midi channels? that's just crazy talk
1544 assert(nchans == 1);
1546 if ((prop = node.property (X_("source-0"))) == 0) {
1547 if ((prop = node.property ("source")) == 0) {
1548 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1549 return boost::shared_ptr<MidiRegion>();
1553 PBD::ID s_id (prop->value());
1555 if ((source = source_by_id (s_id)) == 0) {
1556 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1557 return boost::shared_ptr<MidiRegion>();
1560 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1562 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1563 return boost::shared_ptr<MidiRegion>();
1566 sources.push_back (ms);
1569 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1573 catch (failed_constructor& err) {
1574 return boost::shared_ptr<MidiRegion>();
1579 Session::get_sources_as_xml ()
1582 XMLNode* node = new XMLNode (X_("Sources"));
1583 Glib::Mutex::Lock lm (source_lock);
1585 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1586 node->add_child_nocopy (i->second->get_state());
1589 /* XXX get MIDI and other sources here */
1595 Session::path_from_region_name (string name, string identifier)
1597 char buf[PATH_MAX+1];
1599 string dir = discover_best_sound_dir ();
1601 for (n = 0; n < 999999; ++n) {
1602 if (identifier.length()) {
1603 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1604 identifier.c_str(), n);
1606 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1609 if (!g_file_test (buf, G_FILE_TEST_EXISTS)) {
1614 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1623 Session::load_sources (const XMLNode& node)
1626 XMLNodeConstIterator niter;
1627 boost::shared_ptr<Source> source;
1629 nlist = node.children();
1633 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1636 if ((source = XMLSourceFactory (**niter)) == 0) {
1637 error << _("Session: cannot create Source from XML description.") << endmsg;
1641 catch (non_existent_source& err) {
1642 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1643 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1650 boost::shared_ptr<Source>
1651 Session::XMLSourceFactory (const XMLNode& node)
1653 if (node.name() != "Source") {
1654 return boost::shared_ptr<Source>();
1658 return SourceFactory::create (*this, node);
1661 catch (failed_constructor& err) {
1662 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1663 return boost::shared_ptr<Source>();
1668 Session::save_template (string template_name)
1671 string xml_path, bak_path, template_path;
1673 if (_state_of_the_state & CannotSave) {
1678 string dir = template_dir();
1680 if ((dp = opendir (dir.c_str()))) {
1683 if (g_mkdir_with_parents (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
1684 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1689 tree.set_root (&get_template());
1692 xml_path += template_name;
1693 xml_path += _template_suffix;
1695 ifstream in(xml_path.c_str());
1698 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1704 if (!tree.write (xml_path)) {
1705 error << _("mix template not saved") << endmsg;
1713 Session::rename_template (string old_name, string new_name)
1715 string old_path = template_dir() + old_name + _template_suffix;
1716 string new_path = template_dir() + new_name + _template_suffix;
1718 return rename (old_path.c_str(), new_path.c_str());
1722 Session::delete_template (string name)
1724 string template_path = template_dir();
1725 template_path += name;
1726 template_path += _template_suffix;
1728 return remove (template_path.c_str());
1732 Session::refresh_disk_space ()
1735 struct statfs statfsbuf;
1736 vector<space_and_path>::iterator i;
1737 Glib::Mutex::Lock lm (space_lock);
1740 /* get freespace on every FS that is part of the session path */
1742 _total_free_4k_blocks = 0;
1744 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1745 statfs ((*i).path.c_str(), &statfsbuf);
1747 scale = statfsbuf.f_bsize/4096.0;
1749 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1750 _total_free_4k_blocks += (*i).blocks;
1756 Session::ensure_sound_dir (string path, string& result)
1761 /* Ensure that the parent directory exists */
1763 if (g_mkdir_with_parents (path.c_str(), 0775)) {
1764 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
1768 /* Ensure that the sounds directory exists */
1772 result += sound_dir_name;
1774 if (g_mkdir_with_parents (result.c_str(), 0775)) {
1775 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
1781 dead += dead_sound_dir_name;
1783 if (g_mkdir_with_parents (dead.c_str(), 0775)) {
1784 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
1790 peak += peak_dir_name;
1792 if (g_mkdir_with_parents (peak.c_str(), 0775)) {
1793 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
1797 /* callers expect this to be terminated ... */
1804 Session::discover_best_sound_dir (bool destructive)
1806 vector<space_and_path>::iterator i;
1809 /* handle common case without system calls */
1811 if (session_dirs.size() == 1) {
1815 /* OK, here's the algorithm we're following here:
1817 We want to select which directory to use for
1818 the next file source to be created. Ideally,
1819 we'd like to use a round-robin process so as to
1820 get maximum performance benefits from splitting
1821 the files across multiple disks.
1823 However, in situations without much diskspace, an
1824 RR approach may end up filling up a filesystem
1825 with new files while others still have space.
1826 Its therefore important to pay some attention to
1827 the freespace in the filesystem holding each
1828 directory as well. However, if we did that by
1829 itself, we'd keep creating new files in the file
1830 system with the most space until it was as full
1831 as all others, thus negating any performance
1832 benefits of this RAID-1 like approach.
1834 So, we use a user-configurable space threshold. If
1835 there are at least 2 filesystems with more than this
1836 much space available, we use RR selection between them.
1837 If not, then we pick the filesystem with the most space.
1839 This gets a good balance between the two
1843 refresh_disk_space ();
1845 int free_enough = 0;
1847 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1848 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1853 if (free_enough >= 2) {
1855 bool found_it = false;
1857 /* use RR selection process, ensuring that the one
1861 i = last_rr_session_dir;
1864 if (++i == session_dirs.end()) {
1865 i = session_dirs.begin();
1868 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1869 if (ensure_sound_dir ((*i).path, result) == 0) {
1870 last_rr_session_dir = i;
1876 } while (i != last_rr_session_dir);
1879 result = sound_dir();
1884 /* pick FS with the most freespace (and that
1885 seems to actually work ...)
1888 vector<space_and_path> sorted;
1889 space_and_path_ascending_cmp cmp;
1891 sorted = session_dirs;
1892 sort (sorted.begin(), sorted.end(), cmp);
1894 for (i = sorted.begin(); i != sorted.end(); ++i) {
1895 if (ensure_sound_dir ((*i).path, result) == 0) {
1896 last_rr_session_dir = i;
1901 /* if the above fails, fall back to the most simplistic solution */
1903 if (i == sorted.end()) {
1912 Session::load_playlists (const XMLNode& node)
1915 XMLNodeConstIterator niter;
1916 boost::shared_ptr<Playlist> playlist;
1918 nlist = node.children();
1922 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1924 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1925 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1933 Session::load_unused_playlists (const XMLNode& node)
1936 XMLNodeConstIterator niter;
1937 boost::shared_ptr<Playlist> playlist;
1939 nlist = node.children();
1943 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1945 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1946 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1950 // now manually untrack it
1952 track_playlist (false, boost::weak_ptr<Playlist> (playlist));
1958 boost::shared_ptr<Playlist>
1959 Session::XMLPlaylistFactory (const XMLNode& node)
1962 return PlaylistFactory::create (*this, node);
1965 catch (failed_constructor& err) {
1966 return boost::shared_ptr<Playlist>();
1971 Session::load_named_selections (const XMLNode& node)
1974 XMLNodeConstIterator niter;
1977 nlist = node.children();
1981 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1983 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
1984 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
1992 Session::XMLNamedSelectionFactory (const XMLNode& node)
1995 return new NamedSelection (*this, node);
1998 catch (failed_constructor& err) {
2004 Session::dead_sound_dir () const
2007 res += dead_sound_dir_name;
2013 Session::old_sound_dir (bool with_path) const
2021 res += old_sound_dir_name;
2027 Session::sound_dir (bool with_path) const
2038 res += interchange_dir_name;
2040 res += legalize_for_path (_name);
2042 res += sound_dir_name;
2050 /* if this already exists, don't check for the old session sound directory */
2052 if (Glib::file_test (full, Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
2056 /* possibly support old session structure */
2059 string old_withpath;
2061 old_nopath += old_sound_dir_name;
2064 old_withpath = _path;
2065 old_withpath += old_sound_dir_name;
2067 if (Glib::file_test (old_withpath.c_str(), Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
2069 return old_withpath;
2074 /* ok, old "sounds" directory isn't there, return the new path */
2080 Session::peak_dir () const
2083 res += peak_dir_name;
2089 Session::automation_dir () const
2092 res += "automation/";
2097 Session::template_dir ()
2099 string path = get_user_ardour_path();
2100 path += "templates/";
2106 Session::export_dir () const
2109 res += export_dir_name;
2115 Session::suffixed_search_path (string suffix, bool data)
2119 path += get_user_ardour_path();
2120 if (path[path.length()-1] != ':') {
2125 path += get_system_data_path();
2127 path += get_system_module_path();
2130 vector<string> split_path;
2132 split (path, split_path, ':');
2135 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2140 if (distance (i, split_path.end()) != 1) {
2149 Session::template_path ()
2151 return suffixed_search_path (X_("templates"), true);
2155 Session::control_protocol_path ()
2157 return suffixed_search_path (X_("surfaces"), false);
2161 Session::load_connections (const XMLNode& node)
2163 XMLNodeList nlist = node.children();
2164 XMLNodeConstIterator niter;
2168 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2169 if ((*niter)->name() == "InputConnection") {
2170 add_connection (new ARDOUR::InputConnection (**niter));
2171 } else if ((*niter)->name() == "OutputConnection") {
2172 add_connection (new ARDOUR::OutputConnection (**niter));
2174 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2183 Session::load_edit_groups (const XMLNode& node)
2185 return load_route_groups (node, true);
2189 Session::load_mix_groups (const XMLNode& node)
2191 return load_route_groups (node, false);
2195 Session::load_route_groups (const XMLNode& node, bool edit)
2197 XMLNodeList nlist = node.children();
2198 XMLNodeConstIterator niter;
2203 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2204 if ((*niter)->name() == "RouteGroup") {
2206 rg = add_edit_group ("");
2207 rg->set_state (**niter);
2209 rg = add_mix_group ("");
2210 rg->set_state (**niter);
2219 state_file_filter (const string &str, void *arg)
2221 return (str.length() > strlen(Session::statefile_suffix()) &&
2222 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2226 bool operator()(const string* a, const string* b) {
2232 remove_end(string* state)
2234 string statename(*state);
2236 string::size_type start,end;
2237 if ((start = statename.find_last_of ('/')) != string::npos) {
2238 statename = statename.substr (start+1);
2241 if ((end = statename.rfind(".ardour")) == string::npos) {
2242 end = statename.length();
2245 return new string(statename.substr (0, end));
2249 Session::possible_states (string path)
2251 PathScanner scanner;
2252 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2254 transform(states->begin(), states->end(), states->begin(), remove_end);
2257 sort (states->begin(), states->end(), cmp);
2263 Session::possible_states () const
2265 return possible_states(_path);
2269 Session::auto_save()
2271 save_state (_current_snapshot_name);
2275 Session::add_edit_group (string name)
2277 RouteGroup* rg = new RouteGroup (*this, name);
2278 edit_groups.push_back (rg);
2279 edit_group_added (rg); /* EMIT SIGNAL */
2285 Session::add_mix_group (string name)
2287 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2288 mix_groups.push_back (rg);
2289 mix_group_added (rg); /* EMIT SIGNAL */
2295 Session::remove_edit_group (RouteGroup& rg)
2297 list<RouteGroup*>::iterator i;
2299 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2300 (*i)->apply (&Route::drop_edit_group, this);
2301 edit_groups.erase (i);
2302 edit_group_removed (); /* EMIT SIGNAL */
2309 Session::remove_mix_group (RouteGroup& rg)
2311 list<RouteGroup*>::iterator i;
2313 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2314 (*i)->apply (&Route::drop_mix_group, this);
2315 mix_groups.erase (i);
2316 mix_group_removed (); /* EMIT SIGNAL */
2323 Session::mix_group_by_name (string name)
2325 list<RouteGroup *>::iterator i;
2327 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2328 if ((*i)->name() == name) {
2336 Session::edit_group_by_name (string name)
2338 list<RouteGroup *>::iterator i;
2340 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2341 if ((*i)->name() == name) {
2349 Session::begin_reversible_command (string name)
2351 current_trans = new UndoTransaction;
2352 current_trans->set_name (name);
2356 Session::commit_reversible_command (Command *cmd)
2361 current_trans->add_command (cmd);
2364 gettimeofday (&now, 0);
2365 current_trans->set_timestamp (now);
2367 _history.add (current_trans);
2370 Session::GlobalRouteBooleanState
2371 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2373 GlobalRouteBooleanState s;
2374 boost::shared_ptr<RouteList> r = routes.reader ();
2376 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2377 if (!(*i)->hidden()) {
2378 RouteBooleanState v;
2381 Route* r = (*i).get();
2382 v.second = (r->*method)();
2391 Session::GlobalRouteMeterState
2392 Session::get_global_route_metering ()
2394 GlobalRouteMeterState s;
2395 boost::shared_ptr<RouteList> r = routes.reader ();
2397 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2398 if (!(*i)->hidden()) {
2402 v.second = (*i)->meter_point();
2412 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2414 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2416 boost::shared_ptr<Route> r = (i->first.lock());
2419 r->set_meter_point (i->second, arg);
2425 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2427 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2429 boost::shared_ptr<Route> r = (i->first.lock());
2432 Route* rp = r.get();
2433 (rp->*method) (i->second, arg);
2439 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2441 set_global_route_boolean (s, &Route::set_mute, src);
2445 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2447 set_global_route_boolean (s, &Route::set_solo, src);
2451 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2453 set_global_route_boolean (s, &Route::set_record_enable, src);
2458 Session::global_mute_memento (void* src)
2460 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2464 Session::global_metering_memento (void* src)
2466 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2470 Session::global_solo_memento (void* src)
2472 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2476 Session::global_record_enable_memento (void* src)
2478 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2483 template_filter (const string &str, void *arg)
2485 return (str.length() > strlen(Session::template_suffix()) &&
2486 str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
2490 Session::get_template_list (list<string> &template_names)
2492 vector<string *> *templates;
2493 PathScanner scanner;
2496 path = template_path ();
2498 templates = scanner (path, template_filter, 0, false, true);
2500 vector<string*>::iterator i;
2501 for (i = templates->begin(); i != templates->end(); ++i) {
2502 string fullpath = *(*i);
2505 start = fullpath.find_last_of ('/') + 1;
2506 if ((end = fullpath.find_last_of ('.')) <0) {
2507 end = fullpath.length();
2510 template_names.push_back(fullpath.substr(start, (end-start)));
2515 Session::read_favorite_dirs (FavoriteDirs & favs)
2517 string path = get_user_ardour_path();
2518 path += "/favorite_dirs";
2520 ifstream fav (path.c_str());
2525 if (errno != ENOENT) {
2526 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2537 getline(fav, newfav);
2543 favs.push_back (newfav);
2550 Session::write_favorite_dirs (FavoriteDirs & favs)
2552 string path = get_user_ardour_path();
2553 path += "/favorite_dirs";
2555 ofstream fav (path.c_str());
2561 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2562 fav << (*i) << endl;
2569 accept_all_non_peak_files (const string& path, void *arg)
2571 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2575 accept_all_state_files (const string& path, void *arg)
2577 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2581 Session::find_all_sources (string path, set<string>& result)
2586 if (!tree.read (path)) {
2590 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2595 XMLNodeConstIterator niter;
2597 nlist = node->children();
2601 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2605 if ((prop = (*niter)->property (X_("name"))) == 0) {
2609 if (prop->value()[0] == '/') {
2610 /* external file, ignore */
2614 string path = _path; /* /-terminated */
2615 path += sound_dir_name;
2617 path += prop->value();
2619 result.insert (path);
2626 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2628 PathScanner scanner;
2629 vector<string*>* state_files;
2631 string this_snapshot_path;
2637 if (ripped[ripped.length()-1] == '/') {
2638 ripped = ripped.substr (0, ripped.length() - 1);
2641 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2643 if (state_files == 0) {
2648 this_snapshot_path = _path;
2649 this_snapshot_path += _current_snapshot_name;
2650 this_snapshot_path += _statefile_suffix;
2652 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2654 if (exclude_this_snapshot && **i == this_snapshot_path) {
2658 if (find_all_sources (**i, result) < 0) {
2666 struct RegionCounter {
2667 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2668 AudioSourceList::iterator iter;
2669 boost::shared_ptr<Region> region;
2672 RegionCounter() : count (0) {}
2676 Session::cleanup_sources (Session::cleanup_report& rep)
2678 vector<boost::shared_ptr<Source> > dead_sources;
2679 vector<boost::shared_ptr<Playlist> > playlists_tbd;
2680 PathScanner scanner;
2682 vector<space_and_path>::iterator i;
2683 vector<space_and_path>::iterator nexti;
2684 vector<string*>* soundfiles;
2685 vector<string> unused;
2686 set<string> all_sources;
2691 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2693 /* step 1: consider deleting all unused playlists */
2695 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2698 status = AskAboutPlaylistDeletion (*x);
2707 playlists_tbd.push_back (*x);
2711 /* leave it alone */
2716 /* now delete any that were marked for deletion */
2718 for (vector<boost::shared_ptr<Playlist> >::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2719 (*x)->drop_references ();
2722 playlists_tbd.clear ();
2724 /* step 2: find all un-used sources */
2729 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2731 SourceMap::iterator tmp;
2736 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2740 if (!i->second->used() && i->second->length() > 0) {
2741 dead_sources.push_back (i->second);
2742 i->second->GoingAway();
2748 /* build a list of all the possible sound directories for the session */
2750 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2755 sound_path += (*i).path;
2756 sound_path += sound_dir (false);
2758 if (nexti != session_dirs.end()) {
2765 /* now do the same thing for the files that ended up in the sounds dir(s)
2766 but are not referenced as sources in any snapshot.
2769 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2771 if (soundfiles == 0) {
2775 /* find all sources, but don't use this snapshot because the
2776 state file on disk still references sources we may have already
2780 find_all_sources_across_snapshots (all_sources, true);
2782 /* add our current source list
2785 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2786 boost::shared_ptr<AudioFileSource> fs;
2788 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (i->second)) != 0) {
2789 all_sources.insert (fs->path());
2793 char tmppath1[PATH_MAX+1];
2794 char tmppath2[PATH_MAX+1];
2796 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2801 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2803 realpath(spath.c_str(), tmppath1);
2804 realpath((*i).c_str(), tmppath2);
2806 if (strcmp(tmppath1, tmppath2) == 0) {
2813 unused.push_back (spath);
2817 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2819 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2820 struct stat statbuf;
2822 rep.paths.push_back (*x);
2823 if (stat ((*x).c_str(), &statbuf) == 0) {
2824 rep.space += statbuf.st_size;
2829 /* don't move the file across filesystems, just
2830 stick it in the `dead_sound_dir_name' directory
2831 on whichever filesystem it was already on.
2834 if ((*x).find ("/sounds/") != string::npos) {
2836 /* old school, go up 1 level */
2838 newpath = Glib::path_get_dirname (*x); // "sounds"
2839 newpath = Glib::path_get_dirname (newpath); // "session-name"
2843 /* new school, go up 4 levels */
2845 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2846 newpath = Glib::path_get_dirname (newpath); // "session-name"
2847 newpath = Glib::path_get_dirname (newpath); // "interchange"
2848 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2852 newpath += dead_sound_dir_name;
2854 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2855 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2860 newpath += Glib::path_get_basename ((*x));
2862 if (access (newpath.c_str(), F_OK) == 0) {
2864 /* the new path already exists, try versioning */
2866 char buf[PATH_MAX+1];
2870 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2873 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2874 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2878 if (version == 999) {
2879 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2883 newpath = newpath_v;
2888 /* it doesn't exist, or we can't read it or something */
2892 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2893 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2894 (*x), newpath, strerror (errno))
2899 /* see if there an easy to find peakfile for this file, and remove it.
2902 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2903 peakpath += ".peak";
2905 if (access (peakpath.c_str(), W_OK) == 0) {
2906 if (::unlink (peakpath.c_str()) != 0) {
2907 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2908 peakpath, _path, strerror (errno))
2910 /* try to back out */
2911 rename (newpath.c_str(), _path.c_str());
2919 /* dump the history list */
2923 /* save state so we don't end up a session file
2924 referring to non-existent sources.
2930 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2935 Session::cleanup_trash_sources (Session::cleanup_report& rep)
2937 vector<space_and_path>::iterator i;
2938 string dead_sound_dir;
2939 struct dirent* dentry;
2940 struct stat statbuf;
2946 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2948 dead_sound_dir = (*i).path;
2949 dead_sound_dir += dead_sound_dir_name;
2951 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2955 while ((dentry = readdir (dead)) != 0) {
2957 /* avoid '.' and '..' */
2959 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2960 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2966 fullpath = dead_sound_dir;
2968 fullpath += dentry->d_name;
2970 if (stat (fullpath.c_str(), &statbuf)) {
2974 if (!S_ISREG (statbuf.st_mode)) {
2978 if (unlink (fullpath.c_str())) {
2979 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2980 fullpath, strerror (errno))
2984 rep.paths.push_back (dentry->d_name);
2985 rep.space += statbuf.st_size;
2996 Session::set_dirty ()
2998 bool was_dirty = dirty();
3000 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3003 DirtyChanged(); /* EMIT SIGNAL */
3009 Session::set_clean ()
3011 bool was_dirty = dirty();
3013 _state_of_the_state = Clean;
3016 DirtyChanged(); /* EMIT SIGNAL */
3021 Session::set_deletion_in_progress ()
3023 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3027 Session::add_controllable (Controllable* c)
3029 /* this adds a controllable to the list managed by the Session.
3030 this is a subset of those managed by the Controllable class
3031 itself, and represents the only ones whose state will be saved
3032 as part of the session.
3035 Glib::Mutex::Lock lm (controllables_lock);
3036 controllables.insert (c);
3040 Session::remove_controllable (Controllable* c)
3042 if (_state_of_the_state | Deletion) {
3046 Glib::Mutex::Lock lm (controllables_lock);
3048 Controllables::iterator x = controllables.find (c);
3050 if (x != controllables.end()) {
3051 controllables.erase (x);
3056 Session::controllable_by_id (const PBD::ID& id)
3058 Glib::Mutex::Lock lm (controllables_lock);
3060 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3061 if ((*i)->id() == id) {
3070 Session::add_instant_xml (XMLNode& node, const std::string& dir)
3072 Stateful::add_instant_xml (node, dir);
3073 Config->add_instant_xml (node, get_user_ardour_path());
3078 Session::save_history (string snapshot_name)
3084 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3086 if (snapshot_name.empty()) {
3087 snapshot_name = _current_snapshot_name;
3090 xml_path = _path + snapshot_name + ".history";
3092 bak_path = xml_path + ".bak";
3094 if ((access (xml_path.c_str(), F_OK) == 0) &&
3095 (rename (xml_path.c_str(), bak_path.c_str())))
3097 error << _("could not backup old history file, current history not saved.") << endmsg;
3101 if (!tree.write (xml_path))
3103 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3105 /* don't leave a corrupt file lying around if it is
3109 if (unlink (xml_path.c_str())) {
3110 error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
3112 if (rename (bak_path.c_str(), xml_path.c_str()))
3114 error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;
3125 Session::restore_history (string snapshot_name)
3130 if (snapshot_name.empty()) {
3131 snapshot_name = _current_snapshot_name;
3135 xmlpath = _path + snapshot_name + ".history";
3136 cerr << string_compose(_("Loading history from '%1'."), xmlpath) << endmsg;
3138 if (access (xmlpath.c_str(), F_OK)) {
3139 info << string_compose (_("%1: no history file \"%2\" for this session."), _name, xmlpath) << endmsg;
3143 if (!tree.read (xmlpath)) {
3144 error << string_compose (_("Could not understand session history file \"%1\""), xmlpath) << endmsg;
3148 /* replace history */
3151 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3154 UndoTransaction* ut = new UndoTransaction ();
3157 ut->set_name(t->property("name")->value());
3158 stringstream ss(t->property("tv_sec")->value());
3160 ss.str(t->property("tv_usec")->value());
3162 ut->set_timestamp(tv);
3164 for (XMLNodeConstIterator child_it = t->children().begin();
3165 child_it != t->children().end();
3168 XMLNode *n = *child_it;
3171 if (n->name() == "MementoCommand" ||
3172 n->name() == "MementoUndoCommand" ||
3173 n->name() == "MementoRedoCommand") {
3175 if ((c = memento_command_factory(n))) {
3179 } else if (n->name() == X_("GlobalRouteStateCommand")) {
3181 if ((c = global_state_command_factory (*n))) {
3182 ut->add_command (c);
3187 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3198 Session::config_changed (const char* parameter_name)
3200 #define PARAM_IS(x) (!strcmp (parameter_name, (x)))
3202 if (PARAM_IS ("seamless-loop")) {
3204 } else if (PARAM_IS ("rf-speed")) {
3206 } else if (PARAM_IS ("auto-loop")) {
3208 } else if (PARAM_IS ("auto-input")) {
3210 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3211 /* auto-input only makes a difference if we're rolling */
3213 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3215 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3216 if ((*i)->record_enabled ()) {
3217 (*i)->monitor_input (!Config->get_auto_input());
3222 } else if (PARAM_IS ("punch-in")) {
3226 if ((location = _locations.auto_punch_location()) != 0) {
3228 if (Config->get_punch_in ()) {
3229 replace_event (Event::PunchIn, location->start());
3231 remove_event (location->start(), Event::PunchIn);
3235 } else if (PARAM_IS ("punch-out")) {
3239 if ((location = _locations.auto_punch_location()) != 0) {
3241 if (Config->get_punch_out()) {
3242 replace_event (Event::PunchOut, location->end());
3244 clear_events (Event::PunchOut);
3248 } else if (PARAM_IS ("edit-mode")) {
3250 Glib::Mutex::Lock lm (playlist_lock);
3252 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3253 (*i)->set_edit_mode (Config->get_edit_mode ());
3256 } else if (PARAM_IS ("use-video-sync")) {
3258 if (transport_stopped()) {
3259 if (Config->get_use_video_sync()) {
3260 waiting_for_sync_offset = true;
3264 } else if (PARAM_IS ("mmc-control")) {
3266 //poke_midi_thread ();
3268 } else if (PARAM_IS ("mmc-device-id")) {
3271 mmc->set_device_id (Config->get_mmc_device_id());
3274 } else if (PARAM_IS ("midi-control")) {
3276 //poke_midi_thread ();
3278 } else if (PARAM_IS ("raid-path")) {
3280 setup_raid_path (Config->get_raid_path());
3282 } else if (PARAM_IS ("smpte-format")) {
3286 } else if (PARAM_IS ("video-pullup")) {
3290 } else if (PARAM_IS ("seamless-loop")) {
3292 if (play_loop && transport_rolling()) {
3293 // to reset diskstreams etc
3294 request_play_loop (true);
3297 } else if (PARAM_IS ("rf-speed")) {
3299 cumulative_rf_motion = 0;
3302 } else if (PARAM_IS ("click-sound")) {
3304 setup_click_sounds (1);
3306 } else if (PARAM_IS ("click-emphasis-sound")) {
3308 setup_click_sounds (-1);
3310 } else if (PARAM_IS ("clicking")) {
3312 if (Config->get_clicking()) {
3313 if (_click_io && click_data) { // don't require emphasis data
3320 } else if (PARAM_IS ("send-mtc")) {
3322 /* only set the internal flag if we have
3326 if (_mtc_port != 0) {
3327 session_send_mtc = Config->get_send_mtc();
3328 if (session_send_mtc) {
3329 /* mark us ready to send */
3330 next_quarter_frame_to_send = 0;
3333 session_send_mtc = false;
3336 } else if (PARAM_IS ("send-mmc")) {
3338 /* only set the internal flag if we have
3342 if (_mmc_port != 0) {
3343 session_send_mmc = Config->get_send_mmc();
3346 session_send_mmc = false;
3349 } else if (PARAM_IS ("midi-feedback")) {
3351 /* only set the internal flag if we have
3355 if (_mtc_port != 0) {
3356 session_midi_feedback = Config->get_midi_feedback();
3359 } else if (PARAM_IS ("jack-time-master")) {
3361 engine().reset_timebase ();
3363 } else if (PARAM_IS ("native-file-header-format")) {
3365 if (!first_file_header_format_reset) {
3366 reset_native_file_format ();
3369 first_file_header_format_reset = false;
3371 } else if (PARAM_IS ("native-file-data-format")) {
3373 if (!first_file_data_format_reset) {
3374 reset_native_file_format ();
3377 first_file_data_format_reset = false;
3379 } else if (PARAM_IS ("slave-source")) {
3380 set_slave_source (Config->get_slave_source());
3381 } else if (PARAM_IS ("remote-model")) {
3382 set_remote_control_ids ();