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::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 */
514 string out_path = _path + _name + statefile_suffix;
516 if(!copy_file (*mix_template, out_path)) {
517 error << string_compose (_("Could not use session template %1 to create new session."), *mix_template)
526 /* set initial start + end point */
528 start_location->set_end (0);
529 _locations.add (start_location);
531 end_location->set_end (initial_length);
532 _locations.add (end_location);
534 _state_of_the_state = Clean;
536 if (save_state (_current_snapshot_name)) {
544 Session::load_diskstreams (const XMLNode& node)
547 XMLNodeConstIterator citer;
549 clist = node.children();
551 for (citer = clist.begin(); citer != clist.end(); ++citer) {
554 /* diskstreams added automatically by DiskstreamCreated handler */
555 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
556 boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
557 add_diskstream (dstream);
558 } else if ((*citer)->name() == "MidiDiskstream") {
559 boost::shared_ptr<MidiDiskstream> dstream (new MidiDiskstream (*this, **citer));
560 add_diskstream (dstream);
562 error << _("Session: unknown diskstream type in XML") << endmsg;
566 catch (failed_constructor& err) {
567 error << _("Session: could not load diskstream via XML state") << endmsg;
576 Session::maybe_write_autosave()
578 if (dirty() && record_status() != Recording) {
579 save_state("", true);
584 Session::remove_pending_capture_state ()
589 xml_path += _current_snapshot_name;
590 xml_path += pending_suffix;
592 unlink (xml_path.c_str());
595 /** Rename a state file.
596 * @param snapshot_name Snapshot name.
599 Session::rename_state (string old_name, string new_name)
601 if (old_name == _current_snapshot_name || old_name == _name) {
602 /* refuse to rename the current snapshot or the "main" one */
606 const string old_xml_path = _path + old_name + statefile_suffix;
607 const string new_xml_path = _path + new_name + statefile_suffix;
609 if (rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
610 error << string_compose(_("could not rename snapshot %1 to %2"), old_name, new_name) << endmsg;
614 /** Remove a state file.
615 * @param snapshot_name Snapshot name.
618 Session::remove_state (string snapshot_name)
620 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
621 /* refuse to remove the current snapshot or the "main" one */
625 const string xml_path = _path + snapshot_name + statefile_suffix;
627 /* make a backup copy of the state file */
628 const string bak_path = xml_path + ".bak";
629 if (g_file_test (xml_path.c_str(), G_FILE_TEST_EXISTS)) {
630 copy_file (xml_path, bak_path);
634 unlink (xml_path.c_str());
638 Session::save_state (string snapshot_name, bool pending)
644 if (_state_of_the_state & CannotSave) {
648 if (!_engine.connected ()) {
649 error << _("Ardour's audio engine is not connected and state saving would lose all I/O connections. Session not saved")
654 tree.set_root (&get_state());
656 if (snapshot_name.empty()) {
657 snapshot_name = _current_snapshot_name;
662 /* proper save: use statefile_suffix (.ardour in English) */
664 xml_path += snapshot_name;
665 xml_path += statefile_suffix;
667 /* make a backup copy of the old file */
671 if (g_file_test (xml_path.c_str(), G_FILE_TEST_EXISTS)) {
672 copy_file (xml_path, bak_path);
677 /* pending save: use pending_suffix (.pending in English) */
679 xml_path += snapshot_name;
680 xml_path += pending_suffix;
687 tmp_path += snapshot_name;
690 // cerr << "actually writing state to " << xml_path << endl;
692 if (!tree.write (tmp_path)) {
693 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
694 unlink (tmp_path.c_str());
699 if (rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
700 error << string_compose (_("could not rename temporary session file %1 to %2"), tmp_path, xml_path) << endmsg;
701 unlink (tmp_path.c_str());
708 save_history (snapshot_name);
710 bool was_dirty = dirty();
712 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
715 DirtyChanged (); /* EMIT SIGNAL */
718 StateSaved (snapshot_name); /* EMIT SIGNAL */
725 Session::restore_state (string snapshot_name)
727 if (load_state (snapshot_name) == 0) {
728 set_state (*state_tree->root());
735 Session::load_state (string snapshot_name)
744 state_was_pending = false;
746 /* check for leftover pending state from a crashed capture attempt */
749 xmlpath += snapshot_name;
750 xmlpath += pending_suffix;
752 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
754 /* there is pending state from a crashed capture attempt */
756 if (AskAboutPendingState()) {
757 state_was_pending = true;
761 if (!state_was_pending) {
764 xmlpath += snapshot_name;
765 xmlpath += statefile_suffix;
768 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
769 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
773 state_tree = new XMLTree;
777 if (!state_tree->read (xmlpath)) {
778 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
784 XMLNode& root (*state_tree->root());
786 if (root.name() != X_("Session")) {
787 error << string_compose (_("Session file %1 is not an Ardour session"), xmlpath) << endmsg;
793 const XMLProperty* prop;
796 if ((prop = root.property ("version")) == 0) {
797 /* no version implies very old version of Ardour */
801 major_version = atoi (prop->value()); // grab just the first number before the period
802 if (major_version < 2) {
811 backup_path += snapshot_name;
813 backup_path += statefile_suffix;
815 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with Ardour versions before 2.0 from now on"),
816 xmlpath, backup_path)
819 copy_file (xmlpath, backup_path);
821 /* if it fails, don't worry. right? */
828 Session::load_options (const XMLNode& node)
832 LocaleGuard lg (X_("POSIX"));
834 Config->set_variables (node, ConfigVariableBase::Session);
836 if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
837 if ((prop = child->property ("val")) != 0) {
838 _end_location_is_free = (prop->value() == "yes");
846 Session::save_config_options_predicate (ConfigVariableBase::Owner owner) const
848 const ConfigVariableBase::Owner modified_by_session_or_user = (ConfigVariableBase::Owner)
849 (ConfigVariableBase::Session|ConfigVariableBase::Interface);
851 return owner & modified_by_session_or_user;
855 Session::get_options () const
858 LocaleGuard lg (X_("POSIX"));
860 XMLNode& option_root = Config->get_variables (mem_fun (*this, &Session::save_config_options_predicate));
862 child = option_root.add_child ("end-marker-is-free");
863 child->add_property ("val", _end_location_is_free ? "yes" : "no");
875 Session::get_template()
877 /* if we don't disable rec-enable, diskstreams
878 will believe they need to store their capture
879 sources in their state node.
882 disable_record (false);
888 Session::state(bool full_state)
890 XMLNode* node = new XMLNode("Session");
893 // store libardour version, just in case
895 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
896 libardour_major_version, libardour_minor_version, libardour_micro_version);
897 node->add_property("version", string(buf));
899 /* store configuration settings */
904 node->add_property ("name", _name);
906 if (session_dirs.size() > 1) {
910 vector<space_and_path>::iterator i = session_dirs.begin();
911 vector<space_and_path>::iterator next;
913 ++i; /* skip the first one */
917 while (i != session_dirs.end()) {
921 if (next != session_dirs.end()) {
931 child = node->add_child ("Path");
932 child->add_content (p);
936 /* save the ID counter */
938 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
939 node->add_property ("id-counter", buf);
941 /* various options */
943 node->add_child_nocopy (get_options());
945 child = node->add_child ("Sources");
948 Glib::Mutex::Lock sl (source_lock);
950 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
952 /* Don't save information about AudioFileSources that are empty */
954 boost::shared_ptr<AudioFileSource> fs;
956 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
958 /* Don't save sources that are empty, unless they're destructive (which are OK
959 if they are empty, because we will re-use them every time.)
962 if (!fs->destructive()) {
963 if (fs->length() == 0) {
969 child->add_child_nocopy (siter->second->get_state());
973 child = node->add_child ("Regions");
976 Glib::Mutex::Lock rl (region_lock);
978 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
980 /* only store regions not attached to playlists */
982 if (i->second->playlist() == 0) {
983 child->add_child_nocopy (i->second->state (true));
988 child = node->add_child ("DiskStreams");
991 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
992 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
993 if (!(*i)->hidden()) {
994 child->add_child_nocopy ((*i)->get_state());
1000 node->add_child_nocopy (_locations.get_state());
1002 // for a template, just create a new Locations, populate it
1003 // with the default start and end, and get the state for that.
1005 Location* start = new Location(0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
1006 Location* end = new Location(0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
1009 end->set_end(compute_initial_length());
1011 node->add_child_nocopy (loc.get_state());
1014 child = node->add_child ("Connections");
1016 Glib::Mutex::Lock lm (connection_lock);
1017 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1018 if (!(*i)->system_dependent()) {
1019 child->add_child_nocopy ((*i)->get_state());
1024 child = node->add_child ("Routes");
1026 boost::shared_ptr<RouteList> r = routes.reader ();
1028 RoutePublicOrderSorter cmp;
1029 RouteList public_order (*r);
1030 public_order.sort (cmp);
1032 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1033 if (!(*i)->hidden()) {
1035 child->add_child_nocopy ((*i)->get_state());
1037 child->add_child_nocopy ((*i)->get_template());
1044 child = node->add_child ("EditGroups");
1045 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1046 child->add_child_nocopy ((*i)->get_state());
1049 child = node->add_child ("MixGroups");
1050 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1051 child->add_child_nocopy ((*i)->get_state());
1054 child = node->add_child ("Playlists");
1055 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1056 if (!(*i)->hidden()) {
1057 if (!(*i)->empty()) {
1059 child->add_child_nocopy ((*i)->get_state());
1061 child->add_child_nocopy ((*i)->get_template());
1067 child = node->add_child ("UnusedPlaylists");
1068 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1069 if (!(*i)->hidden()) {
1070 if (!(*i)->empty()) {
1072 child->add_child_nocopy ((*i)->get_state());
1074 child->add_child_nocopy ((*i)->get_template());
1082 child = node->add_child ("Click");
1083 child->add_child_nocopy (_click_io->state (full_state));
1087 child = node->add_child ("NamedSelections");
1088 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1090 child->add_child_nocopy ((*i)->get_state());
1095 node->add_child_nocopy (_tempo_map->get_state());
1097 node->add_child_nocopy (get_control_protocol_state());
1100 node->add_child_copy (*_extra_xml);
1107 Session::get_control_protocol_state ()
1109 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1110 return cpm.get_state();
1114 Session::set_state (const XMLNode& node)
1118 const XMLProperty* prop;
1121 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1123 if (node.name() != X_("Session")){
1124 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1128 if ((prop = node.property ("name")) != 0) {
1129 _name = prop->value ();
1132 setup_raid_path(_path);
1134 if ((prop = node.property (X_("id-counter"))) != 0) {
1136 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1137 ID::init_counter (x);
1139 /* old sessions used a timebased counter, so fake
1140 the startup ID counter based on a standard
1145 ID::init_counter (now);
1149 IO::disable_ports ();
1150 IO::disable_connecting ();
1152 /* Object loading order:
1170 if (use_config_midi_ports ()) {
1173 if ((child = find_named_node (node, "extra")) != 0) {
1174 _extra_xml = new XMLNode (*child);
1177 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1178 load_options (*child);
1179 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1180 load_options (*child);
1182 error << _("Session: XML state has no options section") << endmsg;
1185 if ((child = find_named_node (node, "Locations")) == 0) {
1186 error << _("Session: XML state has no locations section") << endmsg;
1188 } else if (_locations.set_state (*child)) {
1194 if ((location = _locations.auto_loop_location()) != 0) {
1195 set_auto_loop_location (location);
1198 if ((location = _locations.auto_punch_location()) != 0) {
1199 set_auto_punch_location (location);
1202 if ((location = _locations.end_location()) == 0) {
1203 _locations.add (end_location);
1205 delete end_location;
1206 end_location = location;
1209 if ((location = _locations.start_location()) == 0) {
1210 _locations.add (start_location);
1212 delete start_location;
1213 start_location = location;
1216 AudioFileSource::set_header_position_offset (start_location->start());
1218 if ((child = find_named_node (node, "Sources")) == 0) {
1219 error << _("Session: XML state has no sources section") << endmsg;
1221 } else if (load_sources (*child)) {
1225 if ((child = find_named_node (node, "Regions")) == 0) {
1226 error << _("Session: XML state has no Regions section") << endmsg;
1228 } else if (load_regions (*child)) {
1232 if ((child = find_named_node (node, "Playlists")) == 0) {
1233 error << _("Session: XML state has no playlists section") << endmsg;
1235 } else if (load_playlists (*child)) {
1239 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1241 } else if (load_unused_playlists (*child)) {
1245 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1246 if (load_named_selections (*child)) {
1251 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1252 error << _("Session: XML state has no diskstreams section") << endmsg;
1254 } else if (load_diskstreams (*child)) {
1258 if ((child = find_named_node (node, "Connections")) == 0) {
1259 error << _("Session: XML state has no connections section") << endmsg;
1261 } else if (load_connections (*child)) {
1265 if ((child = find_named_node (node, "EditGroups")) == 0) {
1266 error << _("Session: XML state has no edit groups section") << endmsg;
1268 } else if (load_edit_groups (*child)) {
1272 if ((child = find_named_node (node, "MixGroups")) == 0) {
1273 error << _("Session: XML state has no mix groups section") << endmsg;
1275 } else if (load_mix_groups (*child)) {
1279 if ((child = find_named_node (node, "TempoMap")) == 0) {
1280 error << _("Session: XML state has no Tempo Map section") << endmsg;
1282 } else if (_tempo_map->set_state (*child)) {
1286 if ((child = find_named_node (node, "Routes")) == 0) {
1287 error << _("Session: XML state has no routes section") << endmsg;
1289 } else if (load_routes (*child)) {
1293 if ((child = find_named_node (node, "Click")) == 0) {
1294 warning << _("Session: XML state has no click section") << endmsg;
1295 } else if (_click_io) {
1296 _click_io->set_state (*child);
1299 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1300 ControlProtocolManager::instance().set_protocol_states (*child);
1303 /* here beginneth the second phase ... */
1305 StateReady (); /* EMIT SIGNAL */
1307 _state_of_the_state = Clean;
1309 if (state_was_pending) {
1310 save_state (_current_snapshot_name);
1311 remove_pending_capture_state ();
1312 state_was_pending = false;
1322 Session::load_routes (const XMLNode& node)
1325 XMLNodeConstIterator niter;
1326 RouteList new_routes;
1328 nlist = node.children();
1332 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1334 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1337 error << _("Session: cannot create Route from XML description.") << endmsg;
1341 new_routes.push_back (route);
1344 add_routes (new_routes);
1349 boost::shared_ptr<Route>
1350 Session::XMLRouteFactory (const XMLNode& node)
1352 if (node.name() != "Route") {
1353 return boost::shared_ptr<Route> ((Route*) 0);
1356 bool has_diskstream = (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0);
1358 DataType type = DataType::AUDIO;
1359 const XMLProperty* prop = node.property("default-type");
1361 type = DataType(prop->value());
1363 assert(type != DataType::NIL);
1365 if (has_diskstream) {
1366 if (type == DataType::AUDIO) {
1367 boost::shared_ptr<Route> ret (new AudioTrack (*this, node));
1370 boost::shared_ptr<Route> ret (new MidiTrack (*this, node));
1374 boost::shared_ptr<Route> ret (new Route (*this, node));
1380 Session::load_regions (const XMLNode& node)
1383 XMLNodeConstIterator niter;
1384 boost::shared_ptr<Region> region;
1386 nlist = node.children();
1390 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1391 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1392 error << _("Session: cannot create Region from XML description.") << endmsg;
1399 boost::shared_ptr<Region>
1400 Session::XMLRegionFactory (const XMLNode& node, bool full)
1402 const XMLProperty* type = node.property("type");
1406 if ( !type || type->value() == "audio" ) {
1408 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1410 } else if (type->value() == "midi") {
1412 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1416 } catch (failed_constructor& err) {
1417 return boost::shared_ptr<Region> ();
1420 return boost::shared_ptr<Region> ();
1423 boost::shared_ptr<AudioRegion>
1424 Session::XMLAudioRegionFactory (const XMLNode& node, bool full)
1426 const XMLProperty* prop;
1427 boost::shared_ptr<Source> source;
1428 boost::shared_ptr<AudioSource> as;
1430 uint32_t nchans = 1;
1433 if (node.name() != X_("Region")) {
1434 return boost::shared_ptr<AudioRegion>();
1437 if ((prop = node.property (X_("channels"))) != 0) {
1438 nchans = atoi (prop->value().c_str());
1442 if ((prop = node.property ("name")) == 0) {
1443 cerr << "no name for this region\n";
1447 if ((prop = node.property (X_("source-0"))) == 0) {
1448 if ((prop = node.property ("source")) == 0) {
1449 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1450 return boost::shared_ptr<AudioRegion>();
1454 PBD::ID s_id (prop->value());
1456 if ((source = source_by_id (s_id)) == 0) {
1457 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1458 return boost::shared_ptr<AudioRegion>();
1461 as = boost::dynamic_pointer_cast<AudioSource>(source);
1463 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1464 return boost::shared_ptr<AudioRegion>();
1467 sources.push_back (as);
1469 /* pickup other channels */
1471 for (uint32_t n=1; n < nchans; ++n) {
1472 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1473 if ((prop = node.property (buf)) != 0) {
1475 PBD::ID id2 (prop->value());
1477 if ((source = source_by_id (id2)) == 0) {
1478 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1479 return boost::shared_ptr<AudioRegion>();
1482 as = boost::dynamic_pointer_cast<AudioSource>(source);
1484 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1485 return boost::shared_ptr<AudioRegion>();
1487 sources.push_back (as);
1492 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1494 /* a final detail: this is the one and only place that we know how long missing files are */
1496 if (region->whole_file()) {
1497 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1498 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1500 sfp->set_length (region->length());
1510 catch (failed_constructor& err) {
1511 return boost::shared_ptr<AudioRegion>();
1515 boost::shared_ptr<MidiRegion>
1516 Session::XMLMidiRegionFactory (const XMLNode& node, bool full)
1518 const XMLProperty* prop;
1519 boost::shared_ptr<Source> source;
1520 boost::shared_ptr<MidiSource> ms;
1521 MidiRegion::SourceList sources;
1522 uint32_t nchans = 1;
1524 if (node.name() != X_("Region")) {
1525 return boost::shared_ptr<MidiRegion>();
1528 if ((prop = node.property (X_("channels"))) != 0) {
1529 nchans = atoi (prop->value().c_str());
1532 // Multiple midi channels? that's just crazy talk
1533 assert(nchans == 1);
1535 if ((prop = node.property (X_("source-0"))) == 0) {
1536 if ((prop = node.property ("source")) == 0) {
1537 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1538 return boost::shared_ptr<MidiRegion>();
1542 PBD::ID s_id (prop->value());
1544 if ((source = source_by_id (s_id)) == 0) {
1545 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1546 return boost::shared_ptr<MidiRegion>();
1549 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1551 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1552 return boost::shared_ptr<MidiRegion>();
1555 sources.push_back (ms);
1558 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1562 catch (failed_constructor& err) {
1563 return boost::shared_ptr<MidiRegion>();
1568 Session::get_sources_as_xml ()
1571 XMLNode* node = new XMLNode (X_("Sources"));
1572 Glib::Mutex::Lock lm (source_lock);
1574 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1575 node->add_child_nocopy (i->second->get_state());
1578 /* XXX get MIDI and other sources here */
1584 Session::path_from_region_name (string name, string identifier)
1586 char buf[PATH_MAX+1];
1588 string dir = discover_best_sound_dir ();
1590 for (n = 0; n < 999999; ++n) {
1591 if (identifier.length()) {
1592 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1593 identifier.c_str(), n);
1595 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1598 if (!Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
1603 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1612 Session::load_sources (const XMLNode& node)
1615 XMLNodeConstIterator niter;
1616 boost::shared_ptr<Source> source;
1618 nlist = node.children();
1622 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1625 if ((source = XMLSourceFactory (**niter)) == 0) {
1626 error << _("Session: cannot create Source from XML description.") << endmsg;
1630 catch (non_existent_source& err) {
1631 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1632 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1639 boost::shared_ptr<Source>
1640 Session::XMLSourceFactory (const XMLNode& node)
1642 if (node.name() != "Source") {
1643 return boost::shared_ptr<Source>();
1647 return SourceFactory::create (*this, node);
1650 catch (failed_constructor& err) {
1651 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1652 return boost::shared_ptr<Source>();
1657 Session::save_template (string template_name)
1660 string xml_path, bak_path, template_path;
1662 if (_state_of_the_state & CannotSave) {
1667 string dir = template_dir();
1669 if ((dp = opendir (dir.c_str()))) {
1672 if (g_mkdir_with_parents (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
1673 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1678 tree.set_root (&get_template());
1681 xml_path += template_name;
1682 xml_path += template_suffix;
1684 ifstream in(xml_path.c_str());
1687 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1693 if (!tree.write (xml_path)) {
1694 error << _("mix template not saved") << endmsg;
1702 Session::rename_template (string old_name, string new_name)
1704 string old_path = template_dir() + old_name + template_suffix;
1705 string new_path = template_dir() + new_name + template_suffix;
1707 return rename (old_path.c_str(), new_path.c_str());
1711 Session::delete_template (string name)
1713 string template_path = template_dir();
1714 template_path += name;
1715 template_path += template_suffix;
1717 return remove (template_path.c_str());
1721 Session::refresh_disk_space ()
1724 struct statfs statfsbuf;
1725 vector<space_and_path>::iterator i;
1726 Glib::Mutex::Lock lm (space_lock);
1729 /* get freespace on every FS that is part of the session path */
1731 _total_free_4k_blocks = 0;
1733 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1734 statfs ((*i).path.c_str(), &statfsbuf);
1736 scale = statfsbuf.f_bsize/4096.0;
1738 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1739 _total_free_4k_blocks += (*i).blocks;
1745 Session::ensure_sound_dir (string path, string& result)
1750 /* Ensure that the parent directory exists */
1752 if (g_mkdir_with_parents (path.c_str(), 0775)) {
1753 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
1757 /* Ensure that the sounds directory exists */
1761 result += sound_dir_name;
1763 if (g_mkdir_with_parents (result.c_str(), 0775)) {
1764 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
1770 dead += dead_sound_dir_name;
1772 if (g_mkdir_with_parents (dead.c_str(), 0775)) {
1773 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
1779 peak += peak_dir_name;
1781 if (g_mkdir_with_parents (peak.c_str(), 0775)) {
1782 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
1786 /* callers expect this to be terminated ... */
1793 Session::discover_best_sound_dir (bool destructive)
1795 vector<space_and_path>::iterator i;
1798 /* handle common case without system calls */
1800 if (session_dirs.size() == 1) {
1804 /* OK, here's the algorithm we're following here:
1806 We want to select which directory to use for
1807 the next file source to be created. Ideally,
1808 we'd like to use a round-robin process so as to
1809 get maximum performance benefits from splitting
1810 the files across multiple disks.
1812 However, in situations without much diskspace, an
1813 RR approach may end up filling up a filesystem
1814 with new files while others still have space.
1815 Its therefore important to pay some attention to
1816 the freespace in the filesystem holding each
1817 directory as well. However, if we did that by
1818 itself, we'd keep creating new files in the file
1819 system with the most space until it was as full
1820 as all others, thus negating any performance
1821 benefits of this RAID-1 like approach.
1823 So, we use a user-configurable space threshold. If
1824 there are at least 2 filesystems with more than this
1825 much space available, we use RR selection between them.
1826 If not, then we pick the filesystem with the most space.
1828 This gets a good balance between the two
1832 refresh_disk_space ();
1834 int free_enough = 0;
1836 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1837 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1842 if (free_enough >= 2) {
1844 bool found_it = false;
1846 /* use RR selection process, ensuring that the one
1850 i = last_rr_session_dir;
1853 if (++i == session_dirs.end()) {
1854 i = session_dirs.begin();
1857 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1858 if (ensure_sound_dir ((*i).path, result) == 0) {
1859 last_rr_session_dir = i;
1865 } while (i != last_rr_session_dir);
1868 result = sound_dir();
1873 /* pick FS with the most freespace (and that
1874 seems to actually work ...)
1877 vector<space_and_path> sorted;
1878 space_and_path_ascending_cmp cmp;
1880 sorted = session_dirs;
1881 sort (sorted.begin(), sorted.end(), cmp);
1883 for (i = sorted.begin(); i != sorted.end(); ++i) {
1884 if (ensure_sound_dir ((*i).path, result) == 0) {
1885 last_rr_session_dir = i;
1890 /* if the above fails, fall back to the most simplistic solution */
1892 if (i == sorted.end()) {
1901 Session::load_playlists (const XMLNode& node)
1904 XMLNodeConstIterator niter;
1905 boost::shared_ptr<Playlist> playlist;
1907 nlist = node.children();
1911 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1913 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1914 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1922 Session::load_unused_playlists (const XMLNode& node)
1925 XMLNodeConstIterator niter;
1926 boost::shared_ptr<Playlist> playlist;
1928 nlist = node.children();
1932 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1934 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1935 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1939 // now manually untrack it
1941 track_playlist (false, boost::weak_ptr<Playlist> (playlist));
1947 boost::shared_ptr<Playlist>
1948 Session::XMLPlaylistFactory (const XMLNode& node)
1951 return PlaylistFactory::create (*this, node);
1954 catch (failed_constructor& err) {
1955 return boost::shared_ptr<Playlist>();
1960 Session::load_named_selections (const XMLNode& node)
1963 XMLNodeConstIterator niter;
1966 nlist = node.children();
1970 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1972 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
1973 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
1981 Session::XMLNamedSelectionFactory (const XMLNode& node)
1984 return new NamedSelection (*this, node);
1987 catch (failed_constructor& err) {
1993 Session::dead_sound_dir () const
1996 res += dead_sound_dir_name;
2002 Session::old_sound_dir (bool with_path) const
2010 res += old_sound_dir_name;
2016 Session::sound_dir (bool with_path) const
2027 res += interchange_dir_name;
2029 res += legalize_for_path (_name);
2031 res += sound_dir_name;
2039 /* if this already exists, don't check for the old session sound directory */
2041 if (Glib::file_test (full, Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
2045 /* possibly support old session structure */
2048 string old_withpath;
2050 old_nopath += old_sound_dir_name;
2053 old_withpath = _path;
2054 old_withpath += old_sound_dir_name;
2056 if (Glib::file_test (old_withpath.c_str(), Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
2058 return old_withpath;
2063 /* ok, old "sounds" directory isn't there, return the new path */
2069 Session::peak_dir () const
2072 res += peak_dir_name;
2078 Session::automation_dir () const
2081 res += "automation/";
2086 Session::template_dir ()
2088 string path = get_user_ardour_path();
2089 path += "templates/";
2095 Session::export_dir () const
2098 res += export_dir_name;
2104 Session::suffixed_search_path (string suffix, bool data)
2108 path += get_user_ardour_path();
2109 if (path[path.length()-1] != ':') {
2114 path += get_system_data_path();
2116 path += get_system_module_path();
2119 vector<string> split_path;
2121 split (path, split_path, ':');
2124 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2129 if (distance (i, split_path.end()) != 1) {
2138 Session::template_path ()
2140 return suffixed_search_path (X_("templates"), true);
2144 Session::control_protocol_path ()
2146 return suffixed_search_path (X_("surfaces"), false);
2150 Session::load_connections (const XMLNode& node)
2152 XMLNodeList nlist = node.children();
2153 XMLNodeConstIterator niter;
2157 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2158 if ((*niter)->name() == "InputConnection") {
2159 add_connection (new ARDOUR::InputConnection (**niter));
2160 } else if ((*niter)->name() == "OutputConnection") {
2161 add_connection (new ARDOUR::OutputConnection (**niter));
2163 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2172 Session::load_edit_groups (const XMLNode& node)
2174 return load_route_groups (node, true);
2178 Session::load_mix_groups (const XMLNode& node)
2180 return load_route_groups (node, false);
2184 Session::load_route_groups (const XMLNode& node, bool edit)
2186 XMLNodeList nlist = node.children();
2187 XMLNodeConstIterator niter;
2192 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2193 if ((*niter)->name() == "RouteGroup") {
2195 rg = add_edit_group ("");
2196 rg->set_state (**niter);
2198 rg = add_mix_group ("");
2199 rg->set_state (**niter);
2208 state_file_filter (const string &str, void *arg)
2210 return (str.length() > strlen(statefile_suffix) &&
2211 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2215 bool operator()(const string* a, const string* b) {
2221 remove_end(string* state)
2223 string statename(*state);
2225 string::size_type start,end;
2226 if ((start = statename.find_last_of ('/')) != string::npos) {
2227 statename = statename.substr (start+1);
2230 if ((end = statename.rfind(".ardour")) == string::npos) {
2231 end = statename.length();
2234 return new string(statename.substr (0, end));
2238 Session::possible_states (string path)
2240 PathScanner scanner;
2241 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2243 transform(states->begin(), states->end(), states->begin(), remove_end);
2246 sort (states->begin(), states->end(), cmp);
2252 Session::possible_states () const
2254 return possible_states(_path);
2258 Session::auto_save()
2260 save_state (_current_snapshot_name);
2264 Session::add_edit_group (string name)
2266 RouteGroup* rg = new RouteGroup (*this, name);
2267 edit_groups.push_back (rg);
2268 edit_group_added (rg); /* EMIT SIGNAL */
2274 Session::add_mix_group (string name)
2276 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2277 mix_groups.push_back (rg);
2278 mix_group_added (rg); /* EMIT SIGNAL */
2284 Session::remove_edit_group (RouteGroup& rg)
2286 list<RouteGroup*>::iterator i;
2288 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2289 (*i)->apply (&Route::drop_edit_group, this);
2290 edit_groups.erase (i);
2291 edit_group_removed (); /* EMIT SIGNAL */
2298 Session::remove_mix_group (RouteGroup& rg)
2300 list<RouteGroup*>::iterator i;
2302 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2303 (*i)->apply (&Route::drop_mix_group, this);
2304 mix_groups.erase (i);
2305 mix_group_removed (); /* EMIT SIGNAL */
2312 Session::mix_group_by_name (string name)
2314 list<RouteGroup *>::iterator i;
2316 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2317 if ((*i)->name() == name) {
2325 Session::edit_group_by_name (string name)
2327 list<RouteGroup *>::iterator i;
2329 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2330 if ((*i)->name() == name) {
2338 Session::begin_reversible_command (string name)
2340 current_trans = new UndoTransaction;
2341 current_trans->set_name (name);
2345 Session::commit_reversible_command (Command *cmd)
2350 current_trans->add_command (cmd);
2353 gettimeofday (&now, 0);
2354 current_trans->set_timestamp (now);
2356 _history.add (current_trans);
2359 Session::GlobalRouteBooleanState
2360 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2362 GlobalRouteBooleanState s;
2363 boost::shared_ptr<RouteList> r = routes.reader ();
2365 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2366 if (!(*i)->hidden()) {
2367 RouteBooleanState v;
2370 Route* r = (*i).get();
2371 v.second = (r->*method)();
2380 Session::GlobalRouteMeterState
2381 Session::get_global_route_metering ()
2383 GlobalRouteMeterState s;
2384 boost::shared_ptr<RouteList> r = routes.reader ();
2386 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2387 if (!(*i)->hidden()) {
2391 v.second = (*i)->meter_point();
2401 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2403 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2405 boost::shared_ptr<Route> r = (i->first.lock());
2408 r->set_meter_point (i->second, arg);
2414 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2416 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2418 boost::shared_ptr<Route> r = (i->first.lock());
2421 Route* rp = r.get();
2422 (rp->*method) (i->second, arg);
2428 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2430 set_global_route_boolean (s, &Route::set_mute, src);
2434 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2436 set_global_route_boolean (s, &Route::set_solo, src);
2440 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2442 set_global_route_boolean (s, &Route::set_record_enable, src);
2447 Session::global_mute_memento (void* src)
2449 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2453 Session::global_metering_memento (void* src)
2455 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2459 Session::global_solo_memento (void* src)
2461 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2465 Session::global_record_enable_memento (void* src)
2467 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2472 template_filter (const string &str, void *arg)
2474 return (str.length() > strlen(template_suffix) &&
2475 str.find (template_suffix) == (str.length() - strlen (template_suffix)));
2479 Session::get_template_list (list<string> &template_names)
2481 vector<string *> *templates;
2482 PathScanner scanner;
2485 path = template_path ();
2487 templates = scanner (path, template_filter, 0, false, true);
2489 vector<string*>::iterator i;
2490 for (i = templates->begin(); i != templates->end(); ++i) {
2491 string fullpath = *(*i);
2494 start = fullpath.find_last_of ('/') + 1;
2495 if ((end = fullpath.find_last_of ('.')) <0) {
2496 end = fullpath.length();
2499 template_names.push_back(fullpath.substr(start, (end-start)));
2504 Session::read_favorite_dirs (FavoriteDirs & favs)
2506 string path = get_user_ardour_path();
2507 path += "/favorite_dirs";
2509 ifstream fav (path.c_str());
2514 if (errno != ENOENT) {
2515 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2526 getline(fav, newfav);
2532 favs.push_back (newfav);
2539 Session::write_favorite_dirs (FavoriteDirs & favs)
2541 string path = get_user_ardour_path();
2542 path += "/favorite_dirs";
2544 ofstream fav (path.c_str());
2550 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2551 fav << (*i) << endl;
2558 accept_all_non_peak_files (const string& path, void *arg)
2560 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2564 accept_all_state_files (const string& path, void *arg)
2566 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2570 Session::find_all_sources (string path, set<string>& result)
2575 if (!tree.read (path)) {
2579 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2584 XMLNodeConstIterator niter;
2586 nlist = node->children();
2590 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2594 if ((prop = (*niter)->property (X_("name"))) == 0) {
2598 if (prop->value()[0] == '/') {
2599 /* external file, ignore */
2603 string path = _path; /* /-terminated */
2604 path += sound_dir_name;
2606 path += prop->value();
2608 result.insert (path);
2615 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2617 PathScanner scanner;
2618 vector<string*>* state_files;
2620 string this_snapshot_path;
2626 if (ripped[ripped.length()-1] == '/') {
2627 ripped = ripped.substr (0, ripped.length() - 1);
2630 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2632 if (state_files == 0) {
2637 this_snapshot_path = _path;
2638 this_snapshot_path += _current_snapshot_name;
2639 this_snapshot_path += statefile_suffix;
2641 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2643 if (exclude_this_snapshot && **i == this_snapshot_path) {
2647 if (find_all_sources (**i, result) < 0) {
2655 struct RegionCounter {
2656 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2657 AudioSourceList::iterator iter;
2658 boost::shared_ptr<Region> region;
2661 RegionCounter() : count (0) {}
2665 Session::cleanup_sources (Session::cleanup_report& rep)
2667 vector<boost::shared_ptr<Source> > dead_sources;
2668 vector<boost::shared_ptr<Playlist> > playlists_tbd;
2669 PathScanner scanner;
2671 vector<space_and_path>::iterator i;
2672 vector<space_and_path>::iterator nexti;
2673 vector<string*>* soundfiles;
2674 vector<string> unused;
2675 set<string> all_sources;
2680 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2682 /* step 1: consider deleting all unused playlists */
2684 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2687 status = AskAboutPlaylistDeletion (*x);
2696 playlists_tbd.push_back (*x);
2700 /* leave it alone */
2705 /* now delete any that were marked for deletion */
2707 for (vector<boost::shared_ptr<Playlist> >::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2708 (*x)->drop_references ();
2711 playlists_tbd.clear ();
2713 /* step 2: find all un-used sources */
2718 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2720 SourceMap::iterator tmp;
2725 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2729 if (!i->second->used() && i->second->length() > 0) {
2730 dead_sources.push_back (i->second);
2731 i->second->GoingAway();
2737 /* build a list of all the possible sound directories for the session */
2739 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2744 sound_path += (*i).path;
2745 sound_path += sound_dir (false);
2747 if (nexti != session_dirs.end()) {
2754 /* now do the same thing for the files that ended up in the sounds dir(s)
2755 but are not referenced as sources in any snapshot.
2758 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2760 if (soundfiles == 0) {
2764 /* find all sources, but don't use this snapshot because the
2765 state file on disk still references sources we may have already
2769 find_all_sources_across_snapshots (all_sources, true);
2771 /* add our current source list
2774 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2775 boost::shared_ptr<AudioFileSource> fs;
2777 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (i->second)) != 0) {
2778 all_sources.insert (fs->path());
2782 char tmppath1[PATH_MAX+1];
2783 char tmppath2[PATH_MAX+1];
2785 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2790 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2792 realpath(spath.c_str(), tmppath1);
2793 realpath((*i).c_str(), tmppath2);
2795 if (strcmp(tmppath1, tmppath2) == 0) {
2802 unused.push_back (spath);
2806 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2808 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2809 struct stat statbuf;
2811 rep.paths.push_back (*x);
2812 if (stat ((*x).c_str(), &statbuf) == 0) {
2813 rep.space += statbuf.st_size;
2818 /* don't move the file across filesystems, just
2819 stick it in the `dead_sound_dir_name' directory
2820 on whichever filesystem it was already on.
2823 if ((*x).find ("/sounds/") != string::npos) {
2825 /* old school, go up 1 level */
2827 newpath = Glib::path_get_dirname (*x); // "sounds"
2828 newpath = Glib::path_get_dirname (newpath); // "session-name"
2832 /* new school, go up 4 levels */
2834 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2835 newpath = Glib::path_get_dirname (newpath); // "session-name"
2836 newpath = Glib::path_get_dirname (newpath); // "interchange"
2837 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2841 newpath += dead_sound_dir_name;
2843 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2844 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2849 newpath += Glib::path_get_basename ((*x));
2851 if (access (newpath.c_str(), F_OK) == 0) {
2853 /* the new path already exists, try versioning */
2855 char buf[PATH_MAX+1];
2859 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2862 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2863 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2867 if (version == 999) {
2868 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2872 newpath = newpath_v;
2877 /* it doesn't exist, or we can't read it or something */
2881 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2882 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2883 (*x), newpath, strerror (errno))
2888 /* see if there an easy to find peakfile for this file, and remove it.
2891 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2892 peakpath += ".peak";
2894 if (access (peakpath.c_str(), W_OK) == 0) {
2895 if (::unlink (peakpath.c_str()) != 0) {
2896 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2897 peakpath, _path, strerror (errno))
2899 /* try to back out */
2900 rename (newpath.c_str(), _path.c_str());
2908 /* dump the history list */
2912 /* save state so we don't end up a session file
2913 referring to non-existent sources.
2919 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2924 Session::cleanup_trash_sources (Session::cleanup_report& rep)
2926 vector<space_and_path>::iterator i;
2927 string dead_sound_dir;
2928 struct dirent* dentry;
2929 struct stat statbuf;
2935 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2937 dead_sound_dir = (*i).path;
2938 dead_sound_dir += dead_sound_dir_name;
2940 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2944 while ((dentry = readdir (dead)) != 0) {
2946 /* avoid '.' and '..' */
2948 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2949 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2955 fullpath = dead_sound_dir;
2957 fullpath += dentry->d_name;
2959 if (stat (fullpath.c_str(), &statbuf)) {
2963 if (!S_ISREG (statbuf.st_mode)) {
2967 if (unlink (fullpath.c_str())) {
2968 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2969 fullpath, strerror (errno))
2973 rep.paths.push_back (dentry->d_name);
2974 rep.space += statbuf.st_size;
2985 Session::set_dirty ()
2987 bool was_dirty = dirty();
2989 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2992 DirtyChanged(); /* EMIT SIGNAL */
2998 Session::set_clean ()
3000 bool was_dirty = dirty();
3002 _state_of_the_state = Clean;
3005 DirtyChanged(); /* EMIT SIGNAL */
3010 Session::set_deletion_in_progress ()
3012 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3016 Session::add_controllable (Controllable* c)
3018 /* this adds a controllable to the list managed by the Session.
3019 this is a subset of those managed by the Controllable class
3020 itself, and represents the only ones whose state will be saved
3021 as part of the session.
3024 Glib::Mutex::Lock lm (controllables_lock);
3025 controllables.insert (c);
3029 Session::remove_controllable (Controllable* c)
3031 if (_state_of_the_state | Deletion) {
3035 Glib::Mutex::Lock lm (controllables_lock);
3037 Controllables::iterator x = controllables.find (c);
3039 if (x != controllables.end()) {
3040 controllables.erase (x);
3045 Session::controllable_by_id (const PBD::ID& id)
3047 Glib::Mutex::Lock lm (controllables_lock);
3049 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3050 if ((*i)->id() == id) {
3059 Session::add_instant_xml (XMLNode& node, const std::string& dir)
3061 Stateful::add_instant_xml (node, dir);
3062 Config->add_instant_xml (node, get_user_ardour_path());
3067 Session::save_history (string snapshot_name)
3073 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3075 if (snapshot_name.empty()) {
3076 snapshot_name = _current_snapshot_name;
3079 xml_path = _path + snapshot_name + ".history";
3081 bak_path = xml_path + ".bak";
3083 if ((access (xml_path.c_str(), F_OK) == 0) &&
3084 (rename (xml_path.c_str(), bak_path.c_str())))
3086 error << _("could not backup old history file, current history not saved.") << endmsg;
3090 if (!tree.write (xml_path))
3092 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3094 /* don't leave a corrupt file lying around if it is
3098 if (unlink (xml_path.c_str())) {
3099 error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
3101 if (rename (bak_path.c_str(), xml_path.c_str()))
3103 error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;
3114 Session::restore_history (string snapshot_name)
3119 if (snapshot_name.empty()) {
3120 snapshot_name = _current_snapshot_name;
3124 xmlpath = _path + snapshot_name + ".history";
3125 cerr << string_compose(_("Loading history from '%1'."), xmlpath) << endmsg;
3127 if (access (xmlpath.c_str(), F_OK)) {
3128 info << string_compose (_("%1: no history file \"%2\" for this session."), _name, xmlpath) << endmsg;
3132 if (!tree.read (xmlpath)) {
3133 error << string_compose (_("Could not understand session history file \"%1\""), xmlpath) << endmsg;
3137 /* replace history */
3140 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3143 UndoTransaction* ut = new UndoTransaction ();
3146 ut->set_name(t->property("name")->value());
3147 stringstream ss(t->property("tv_sec")->value());
3149 ss.str(t->property("tv_usec")->value());
3151 ut->set_timestamp(tv);
3153 for (XMLNodeConstIterator child_it = t->children().begin();
3154 child_it != t->children().end();
3157 XMLNode *n = *child_it;
3160 if (n->name() == "MementoCommand" ||
3161 n->name() == "MementoUndoCommand" ||
3162 n->name() == "MementoRedoCommand") {
3164 if ((c = memento_command_factory(n))) {
3168 } else if (n->name() == X_("GlobalRouteStateCommand")) {
3170 if ((c = global_state_command_factory (*n))) {
3171 ut->add_command (c);
3176 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3187 Session::config_changed (const char* parameter_name)
3189 #define PARAM_IS(x) (!strcmp (parameter_name, (x)))
3191 if (PARAM_IS ("seamless-loop")) {
3193 } else if (PARAM_IS ("rf-speed")) {
3195 } else if (PARAM_IS ("auto-loop")) {
3197 } else if (PARAM_IS ("auto-input")) {
3199 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3200 /* auto-input only makes a difference if we're rolling */
3202 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3204 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3205 if ((*i)->record_enabled ()) {
3206 (*i)->monitor_input (!Config->get_auto_input());
3211 } else if (PARAM_IS ("punch-in")) {
3215 if ((location = _locations.auto_punch_location()) != 0) {
3217 if (Config->get_punch_in ()) {
3218 replace_event (Event::PunchIn, location->start());
3220 remove_event (location->start(), Event::PunchIn);
3224 } else if (PARAM_IS ("punch-out")) {
3228 if ((location = _locations.auto_punch_location()) != 0) {
3230 if (Config->get_punch_out()) {
3231 replace_event (Event::PunchOut, location->end());
3233 clear_events (Event::PunchOut);
3237 } else if (PARAM_IS ("edit-mode")) {
3239 Glib::Mutex::Lock lm (playlist_lock);
3241 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3242 (*i)->set_edit_mode (Config->get_edit_mode ());
3245 } else if (PARAM_IS ("use-video-sync")) {
3247 waiting_for_sync_offset = Config->get_use_video_sync();
3249 } else if (PARAM_IS ("mmc-control")) {
3251 //poke_midi_thread ();
3253 } else if (PARAM_IS ("mmc-device-id")) {
3256 mmc->set_device_id (Config->get_mmc_device_id());
3259 } else if (PARAM_IS ("midi-control")) {
3261 //poke_midi_thread ();
3263 } else if (PARAM_IS ("raid-path")) {
3265 setup_raid_path (Config->get_raid_path());
3267 } else if (PARAM_IS ("smpte-format")) {
3271 } else if (PARAM_IS ("video-pullup")) {
3275 } else if (PARAM_IS ("seamless-loop")) {
3277 if (play_loop && transport_rolling()) {
3278 // to reset diskstreams etc
3279 request_play_loop (true);
3282 } else if (PARAM_IS ("rf-speed")) {
3284 cumulative_rf_motion = 0;
3287 } else if (PARAM_IS ("click-sound")) {
3289 setup_click_sounds (1);
3291 } else if (PARAM_IS ("click-emphasis-sound")) {
3293 setup_click_sounds (-1);
3295 } else if (PARAM_IS ("clicking")) {
3297 if (Config->get_clicking()) {
3298 if (_click_io && click_data) { // don't require emphasis data
3305 } else if (PARAM_IS ("send-mtc")) {
3307 /* only set the internal flag if we have
3311 if (_mtc_port != 0) {
3312 session_send_mtc = Config->get_send_mtc();
3313 if (session_send_mtc) {
3314 /* mark us ready to send */
3315 next_quarter_frame_to_send = 0;
3318 session_send_mtc = false;
3321 } else if (PARAM_IS ("send-mmc")) {
3323 /* only set the internal flag if we have
3327 if (_mmc_port != 0) {
3328 session_send_mmc = Config->get_send_mmc();
3331 session_send_mmc = false;
3334 } else if (PARAM_IS ("midi-feedback")) {
3336 /* only set the internal flag if we have
3340 if (_mtc_port != 0) {
3341 session_midi_feedback = Config->get_midi_feedback();
3344 } else if (PARAM_IS ("jack-time-master")) {
3346 engine().reset_timebase ();
3348 } else if (PARAM_IS ("native-file-header-format")) {
3350 if (!first_file_header_format_reset) {
3351 reset_native_file_format ();
3354 first_file_header_format_reset = false;
3356 } else if (PARAM_IS ("native-file-data-format")) {
3358 if (!first_file_data_format_reset) {
3359 reset_native_file_format ();
3362 first_file_data_format_reset = false;
3364 } else if (PARAM_IS ("slave-source")) {
3365 set_slave_source (Config->get_slave_source());
3366 } else if (PARAM_IS ("remote-model")) {
3367 set_remote_control_ids ();