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>
50 #include <glibmm/thread.h>
52 #include <midi++/mmc.h>
53 #include <midi++/port.h>
55 #include <pbd/error.h>
56 #include <pbd/pathscanner.h>
57 #include <pbd/pthread_utils.h>
58 #include <pbd/search_path.h>
59 #include <pbd/stacktrace.h>
61 #include <ardour/audioengine.h>
62 #include <ardour/configuration.h>
63 #include <ardour/session.h>
64 #include <ardour/session_directory.h>
65 #include <ardour/session_utils.h>
66 #include <ardour/session_state_utils.h>
67 #include <ardour/buffer.h>
68 #include <ardour/audio_diskstream.h>
69 #include <ardour/midi_diskstream.h>
70 #include <ardour/utils.h>
71 #include <ardour/audioplaylist.h>
72 #include <ardour/midi_playlist.h>
73 #include <ardour/smf_source.h>
74 #include <ardour/audiofilesource.h>
75 #include <ardour/silentfilesource.h>
76 #include <ardour/sndfilesource.h>
77 #include <ardour/midi_source.h>
78 #include <ardour/sndfile_helpers.h>
79 #include <ardour/auditioner.h>
80 #include <ardour/export.h>
81 #include <ardour/io_processor.h>
82 #include <ardour/send.h>
83 #include <ardour/processor.h>
84 #include <ardour/bundle.h>
85 #include <ardour/slave.h>
86 #include <ardour/tempo.h>
87 #include <ardour/audio_track.h>
88 #include <ardour/midi_track.h>
89 #include <ardour/cycle_timer.h>
90 #include <ardour/utils.h>
91 #include <ardour/named_selection.h>
92 #include <ardour/version.h>
93 #include <ardour/location.h>
94 #include <ardour/audioregion.h>
95 #include <ardour/midi_region.h>
96 #include <ardour/crossfade.h>
97 #include <ardour/control_protocol_manager.h>
98 #include <ardour/region_factory.h>
99 #include <ardour/source_factory.h>
100 #include <ardour/playlist_factory.h>
101 #include <ardour/filename_extensions.h>
102 #include <ardour/directory_names.h>
103 #include <ardour/template_utils.h>
105 #include <control_protocol/control_protocol.h>
111 using namespace ARDOUR;
115 Session::first_stage_init (string fullpath, string snapshot_name)
117 if (fullpath.length() == 0) {
119 throw failed_constructor();
122 char buf[PATH_MAX+1];
123 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
124 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
126 throw failed_constructor();
131 if (_path[_path.length()-1] != '/') {
135 /* these two are just provisional settings. set_state()
136 will likely override them.
139 _name = _current_snapshot_name = snapshot_name;
141 set_history_depth (Config->get_history_depth());
143 _current_frame_rate = _engine.frame_rate ();
144 _tempo_map = new TempoMap (_current_frame_rate);
145 _tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
149 g_atomic_int_set (&processing_prohibited, 0);
151 _transport_speed = 0;
152 _last_transport_speed = 0;
153 auto_play_legal = false;
154 transport_sub_state = 0;
155 _transport_frame = 0;
157 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
158 start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
159 _end_location_is_free = true;
160 g_atomic_int_set (&_record_status, Disabled);
161 loop_changing = false;
163 _last_roll_location = 0;
164 _last_record_location = 0;
165 pending_locate_frame = 0;
166 pending_locate_roll = false;
167 pending_locate_flush = false;
168 dstream_buffer_size = 0;
170 state_was_pending = false;
172 outbound_mtc_smpte_frame = 0;
173 next_quarter_frame_to_send = -1;
174 current_block_size = 0;
175 solo_update_disabled = false;
176 currently_soloing = false;
177 _have_captured = false;
178 _worst_output_latency = 0;
179 _worst_input_latency = 0;
180 _worst_track_latency = 0;
181 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
184 butler_mixdown_buffer = 0;
185 butler_gain_buffer = 0;
187 session_send_mmc = false;
188 session_send_mtc = false;
189 post_transport_work = PostTransportWork (0);
190 g_atomic_int_set (&butler_should_do_transport_work, 0);
191 g_atomic_int_set (&butler_active, 0);
192 g_atomic_int_set (&_playback_load, 100);
193 g_atomic_int_set (&_capture_load, 100);
194 g_atomic_int_set (&_playback_load_min, 100);
195 g_atomic_int_set (&_capture_load_min, 100);
197 waiting_to_start = false;
199 _gain_automation_buffer = 0;
200 _pan_automation_buffer = 0;
202 pending_abort = false;
203 destructive_index = 0;
205 first_file_data_format_reset = true;
206 first_file_header_format_reset = true;
207 butler_thread = (pthread_t) 0;
208 //midi_thread = (pthread_t) 0;
210 AudioDiskstream::allocate_working_buffers();
212 /* default short fade = 15ms */
214 Crossfade::set_short_xfade_length ((nframes_t) floor (Config->get_short_xfade_seconds() * frame_rate()));
215 SndFileSource::setup_standard_crossfades (frame_rate());
217 last_mmc_step.tv_sec = 0;
218 last_mmc_step.tv_usec = 0;
221 /* click sounds are unset by default, which causes us to internal
222 waveforms for clicks.
226 click_emphasis_data = 0;
228 click_emphasis_length = 0;
231 process_function = &Session::process_with_events;
233 if (Config->get_use_video_sync()) {
234 waiting_for_sync_offset = true;
236 waiting_for_sync_offset = false;
239 _current_frame_rate = 48000;
240 _base_frame_rate = 48000;
244 _smpte_offset_negative = true;
245 last_smpte_valid = false;
249 last_rr_session_dir = session_dirs.begin();
250 refresh_disk_space ();
252 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
256 average_slave_delta = 1800;
257 have_first_delta_accumulator = false;
258 delta_accumulator_cnt = 0;
259 slave_state = Stopped;
261 _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
263 /* These are all static "per-class" signals */
265 RegionFactory::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
266 SourceFactory::SourceCreated.connect (mem_fun (*this, &Session::add_source));
267 PlaylistFactory::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
268 Processor::ProcessorCreated.connect (mem_fun (*this, &Session::add_processor));
269 NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
270 AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
272 Controllable::Destroyed.connect (mem_fun (*this, &Session::remove_controllable));
274 IO::PortCountChanged.connect (mem_fun (*this, &Session::ensure_buffers));
276 /* stop IO objects from doing stuff until we're ready for them */
278 IO::disable_panners ();
279 IO::disable_ports ();
280 IO::disable_connecting ();
284 Session::second_stage_init (bool new_session)
286 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
289 if (load_state (_current_snapshot_name)) {
292 remove_empty_sounds ();
295 if (start_butler_thread()) {
299 /*if (start_midi_thread ()) {
303 // set_state() will call setup_raid_path(), but if it's a new session we need
304 // to call setup_raid_path() here.
307 if (set_state (*state_tree->root())) {
311 setup_raid_path(_path);
314 /* we can't save till after ::when_engine_running() is called,
315 because otherwise we save state with no connections made.
316 therefore, we reset _state_of_the_state because ::set_state()
317 will have cleared it.
319 we also have to include Loading so that any events that get
320 generated between here and the end of ::when_engine_running()
321 will be processed directly rather than queued.
324 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
327 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
328 _locations.added.connect (mem_fun (this, &Session::locations_added));
329 setup_click_sounds (0);
330 setup_midi_control ();
332 /* Pay attention ... */
334 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
335 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
338 when_engine_running();
341 /* handle this one in a different way than all others, so that its clear what happened */
343 catch (AudioEngine::PortRegistrationFailure& err) {
344 error << _("Unable to create all required ports")
353 //send_full_time_code ();
354 _engine.transport_locate (0);
355 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
356 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
358 ControlProtocolManager::instance().set_session (*this);
361 _end_location_is_free = true;
363 _end_location_is_free = false;
366 _state_of_the_state = Clean;
369 DirtyChanged (); /* EMIT SIGNAL */
371 if (state_was_pending) {
372 save_state (_current_snapshot_name);
373 remove_pending_capture_state ();
374 state_was_pending = false;
381 Session::raid_path () const
383 SearchPath raid_search_path;
385 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
386 raid_search_path += sys::path((*i).path);
389 return raid_search_path.to_string ();
393 Session::setup_raid_path (string path)
402 session_dirs.clear ();
404 SearchPath search_path(path);
405 SearchPath sound_search_path;
406 SearchPath midi_search_path;
409 SearchPath::const_iterator i = search_path.begin();
410 i != search_path.end();
414 sp.path = (*i).to_string ();
415 sp.blocks = 0; // not needed
416 session_dirs.push_back (sp);
418 SessionDirectory sdir(sp.path);
420 sound_search_path += sdir.sound_path ();
421 midi_search_path += sdir.midi_path ();
424 // set the AudioFileSource and SMFSource search path
426 AudioFileSource::set_search_path (sound_search_path.to_string ());
427 SMFSource::set_search_path (midi_search_path.to_string ());
429 // reset the round-robin soundfile path thingie
431 last_rr_session_dir = session_dirs.begin();
435 Session::create (bool& new_session, const string& mix_template, nframes_t initial_length)
439 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
440 error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
444 dir = session_directory().peak_path().to_string();
446 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
447 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
451 dir = session_directory().sound_path().to_string();
453 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
454 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
458 dir = session_directory().midi_path().to_string();
460 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
461 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
465 dir = session_directory().dead_sound_path().to_string();
467 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
468 error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
472 dir = session_directory().export_path().to_string();
474 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
475 error << string_compose(_("Session: cannot create session export dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
480 /* check new_session so we don't overwrite an existing one */
482 if (!mix_template.empty()) {
483 std::string in_path = mix_template;
485 ifstream in(in_path.c_str());
488 string out_path = _path;
490 out_path += statefile_suffix;
492 ofstream out(out_path.c_str());
497 // okay, session is set up. Treat like normal saved
498 // session from now on.
504 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
510 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
517 /* set initial start + end point */
519 start_location->set_end (0);
520 _locations.add (start_location);
522 end_location->set_end (initial_length);
523 _locations.add (end_location);
525 _state_of_the_state = Clean;
535 Session::load_diskstreams (const XMLNode& node)
538 XMLNodeConstIterator citer;
540 clist = node.children();
542 for (citer = clist.begin(); citer != clist.end(); ++citer) {
545 /* diskstreams added automatically by DiskstreamCreated handler */
546 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
547 boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
548 add_diskstream (dstream);
549 } else if ((*citer)->name() == "MidiDiskstream") {
550 boost::shared_ptr<MidiDiskstream> dstream (new MidiDiskstream (*this, **citer));
551 add_diskstream (dstream);
553 error << _("Session: unknown diskstream type in XML") << endmsg;
557 catch (failed_constructor& err) {
558 error << _("Session: could not load diskstream via XML state") << endmsg;
567 Session::maybe_write_autosave()
569 if (dirty() && record_status() != Recording) {
570 save_state("", true);
575 Session::remove_pending_capture_state ()
577 sys::path pending_state_file_path(_session_dir->root_path());
579 pending_state_file_path /= _current_snapshot_name + pending_suffix;
583 sys::remove (pending_state_file_path);
585 catch(sys::filesystem_error& ex)
587 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
588 pending_state_file_path.to_string(), ex.what()) << endmsg;
592 /** Rename a state file.
593 * @param snapshot_name Snapshot name.
596 Session::rename_state (string old_name, string new_name)
598 if (old_name == _current_snapshot_name || old_name == _name) {
599 /* refuse to rename the current snapshot or the "main" one */
603 const string old_xml_filename = old_name + statefile_suffix;
604 const string new_xml_filename = new_name + statefile_suffix;
606 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
607 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
611 sys::rename (old_xml_path, new_xml_path);
613 catch (const sys::filesystem_error& err)
615 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
616 old_name, new_name, err.what()) << endmsg;
620 /** Remove a state file.
621 * @param snapshot_name Snapshot name.
624 Session::remove_state (string snapshot_name)
626 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
627 // refuse to remove the current snapshot or the "main" one
631 sys::path xml_path(_session_dir->root_path());
633 xml_path /= snapshot_name + statefile_suffix;
635 if (!create_backup_file (xml_path)) {
636 // don't remove it if a backup can't be made
637 // create_backup_file will log the error.
642 sys::remove (xml_path);
646 Session::save_state (string snapshot_name, bool pending)
649 sys::path xml_path(_session_dir->root_path());
651 if (_state_of_the_state & CannotSave) {
655 if (!_engine.connected ()) {
656 error << _("Ardour's audio engine is not connected and state saving would lose all I/O connections. Session not saved")
661 /* tell sources we're saving first, in case they write out to a new file
662 * which should be saved with the state rather than the old one */
663 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i)
664 i->second->session_saved();
666 tree.set_root (&get_state());
668 if (snapshot_name.empty()) {
669 snapshot_name = _current_snapshot_name;
674 /* proper save: use statefile_suffix (.ardour in English) */
676 xml_path /= snapshot_name + statefile_suffix;
678 /* make a backup copy of the old file */
680 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
681 // create_backup_file will log the error
687 /* pending save: use pending_suffix (.pending in English) */
688 xml_path /= snapshot_name + pending_suffix;
691 sys::path tmp_path(_session_dir->root_path());
693 tmp_path /= snapshot_name + temp_suffix;
695 // cerr << "actually writing state to " << xml_path.to_string() << endl;
697 if (!tree.write (tmp_path.to_string())) {
698 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
699 sys::remove (tmp_path);
704 if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
705 error << string_compose (_("could not rename temporary session file %1 to %2"),
706 tmp_path.to_string(), xml_path.to_string()) << endmsg;
707 sys::remove (tmp_path);
714 save_history (snapshot_name);
716 bool was_dirty = dirty();
718 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
721 DirtyChanged (); /* EMIT SIGNAL */
724 StateSaved (snapshot_name); /* EMIT SIGNAL */
731 Session::restore_state (string snapshot_name)
733 if (load_state (snapshot_name) == 0) {
734 set_state (*state_tree->root());
741 Session::load_state (string snapshot_name)
748 state_was_pending = false;
750 /* check for leftover pending state from a crashed capture attempt */
752 sys::path xmlpath(_session_dir->root_path());
753 xmlpath /= snapshot_name + pending_suffix;
755 if (sys::exists (xmlpath)) {
757 /* there is pending state from a crashed capture attempt */
759 if (AskAboutPendingState()) {
760 state_was_pending = true;
764 if (!state_was_pending) {
765 xmlpath = _session_dir->root_path();
766 xmlpath /= snapshot_name + statefile_suffix;
769 if (!sys::exists (xmlpath)) {
770 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
774 state_tree = new XMLTree;
778 if (!state_tree->read (xmlpath.to_string())) {
779 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
785 XMLNode& root (*state_tree->root());
787 if (root.name() != X_("Session")) {
788 error << string_compose (_("Session file %1 is not an Ardour session"), xmlpath.to_string()) << endmsg;
794 const XMLProperty* prop;
797 if ((prop = root.property ("version")) == 0) {
798 /* no version implies very old version of Ardour */
802 major_version = atoi (prop->value().c_str()); // grab just the first number before the period
803 if (major_version < 2) {
810 sys::path backup_path(_session_dir->root_path());
812 backup_path /= snapshot_name + "-1" + statefile_suffix;
814 // only create a backup once
815 if (sys::exists (backup_path)) {
819 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with Ardour versions before 2.0 from now on"),
820 xmlpath.to_string(), backup_path.to_string())
825 sys::copy_file (xmlpath, backup_path);
827 catch(sys::filesystem_error& ex)
829 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
830 xmlpath.to_string(), ex.what())
840 Session::load_options (const XMLNode& node)
844 LocaleGuard lg (X_("POSIX"));
846 Config->set_variables (node, ConfigVariableBase::Session);
848 if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
849 if ((prop = child->property ("val")) != 0) {
850 _end_location_is_free = (prop->value() == "yes");
858 Session::save_config_options_predicate (ConfigVariableBase::Owner owner) const
860 const ConfigVariableBase::Owner modified_by_session_or_user = (ConfigVariableBase::Owner)
861 (ConfigVariableBase::Session|ConfigVariableBase::Interface);
863 return owner & modified_by_session_or_user;
867 Session::get_options () const
870 LocaleGuard lg (X_("POSIX"));
872 XMLNode& option_root = Config->get_variables (mem_fun (*this, &Session::save_config_options_predicate));
874 child = option_root.add_child ("end-marker-is-free");
875 child->add_property ("val", _end_location_is_free ? "yes" : "no");
887 Session::get_template()
889 /* if we don't disable rec-enable, diskstreams
890 will believe they need to store their capture
891 sources in their state node.
894 disable_record (false);
900 Session::state(bool full_state)
902 XMLNode* node = new XMLNode("Session");
905 // store libardour version, just in case
907 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
908 libardour_major_version, libardour_minor_version, libardour_micro_version);
909 node->add_property("version", string(buf));
911 /* store configuration settings */
916 node->add_property ("name", _name);
918 if (session_dirs.size() > 1) {
922 vector<space_and_path>::iterator i = session_dirs.begin();
923 vector<space_and_path>::iterator next;
925 ++i; /* skip the first one */
929 while (i != session_dirs.end()) {
933 if (next != session_dirs.end()) {
943 child = node->add_child ("Path");
944 child->add_content (p);
948 /* save the ID counter */
950 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
951 node->add_property ("id-counter", buf);
953 /* various options */
955 node->add_child_nocopy (get_options());
957 child = node->add_child ("Sources");
960 Glib::Mutex::Lock sl (source_lock);
962 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
964 /* Don't save information about AudioFileSources that are empty */
966 boost::shared_ptr<AudioFileSource> fs;
968 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
970 /* Don't save sources that are empty, unless they're destructive (which are OK
971 if they are empty, because we will re-use them every time.)
974 if (!fs->destructive()) {
975 if (fs->length() == 0) {
981 child->add_child_nocopy (siter->second->get_state());
985 child = node->add_child ("Regions");
988 Glib::Mutex::Lock rl (region_lock);
990 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
992 /* only store regions not attached to playlists */
994 if (i->second->playlist() == 0) {
995 child->add_child_nocopy (i->second->state (true));
1000 child = node->add_child ("DiskStreams");
1003 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1004 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1005 if (!(*i)->hidden()) {
1006 child->add_child_nocopy ((*i)->get_state());
1012 node->add_child_nocopy (_locations.get_state());
1014 // for a template, just create a new Locations, populate it
1015 // with the default start and end, and get the state for that.
1017 Location* start = new Location(0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
1018 Location* end = new Location(0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
1021 end->set_end(compute_initial_length());
1023 node->add_child_nocopy (loc.get_state());
1026 child = node->add_child ("Bundles");
1028 Glib::Mutex::Lock lm (bundle_lock);
1029 for (BundleList::iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
1030 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1032 child->add_child_nocopy (b->get_state());
1037 child = node->add_child ("Routes");
1039 boost::shared_ptr<RouteList> r = routes.reader ();
1041 RoutePublicOrderSorter cmp;
1042 RouteList public_order (*r);
1043 public_order.sort (cmp);
1045 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1046 if (!(*i)->is_hidden()) {
1048 child->add_child_nocopy ((*i)->get_state());
1050 child->add_child_nocopy ((*i)->get_template());
1057 child = node->add_child ("EditGroups");
1058 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1059 child->add_child_nocopy ((*i)->get_state());
1062 child = node->add_child ("MixGroups");
1063 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1064 child->add_child_nocopy ((*i)->get_state());
1067 child = node->add_child ("Playlists");
1068 for (PlaylistList::iterator i = playlists.begin(); i != 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());
1080 child = node->add_child ("UnusedPlaylists");
1081 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1082 if (!(*i)->hidden()) {
1083 if (!(*i)->empty()) {
1085 child->add_child_nocopy ((*i)->get_state());
1087 child->add_child_nocopy ((*i)->get_template());
1095 child = node->add_child ("Click");
1096 child->add_child_nocopy (_click_io->state (full_state));
1100 child = node->add_child ("NamedSelections");
1101 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1103 child->add_child_nocopy ((*i)->get_state());
1108 node->add_child_nocopy (_tempo_map->get_state());
1110 node->add_child_nocopy (get_control_protocol_state());
1113 node->add_child_copy (*_extra_xml);
1120 Session::get_control_protocol_state ()
1122 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1123 return cpm.get_state();
1127 Session::set_state (const XMLNode& node)
1131 const XMLProperty* prop;
1134 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1137 if (node.name() != X_("Session")){
1138 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1142 if ((prop = node.property ("name")) != 0) {
1143 _name = prop->value ();
1146 setup_raid_path(_session_dir->root_path().to_string());
1148 if ((prop = node.property (X_("id-counter"))) != 0) {
1150 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1151 ID::init_counter (x);
1153 /* old sessions used a timebased counter, so fake
1154 the startup ID counter based on a standard
1159 ID::init_counter (now);
1163 IO::disable_ports ();
1164 IO::disable_connecting ();
1166 /* Object loading order:
1184 if (use_config_midi_ports ()) {
1187 if ((child = find_named_node (node, "extra")) != 0) {
1188 _extra_xml = new XMLNode (*child);
1191 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1192 load_options (*child);
1193 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1194 load_options (*child);
1196 error << _("Session: XML state has no options section") << endmsg;
1199 if ((child = find_named_node (node, "Locations")) == 0) {
1200 error << _("Session: XML state has no locations section") << endmsg;
1202 } else if (_locations.set_state (*child)) {
1208 if ((location = _locations.auto_loop_location()) != 0) {
1209 set_auto_loop_location (location);
1212 if ((location = _locations.auto_punch_location()) != 0) {
1213 set_auto_punch_location (location);
1216 if ((location = _locations.end_location()) == 0) {
1217 _locations.add (end_location);
1219 delete end_location;
1220 end_location = location;
1223 if ((location = _locations.start_location()) == 0) {
1224 _locations.add (start_location);
1226 delete start_location;
1227 start_location = location;
1230 AudioFileSource::set_header_position_offset (start_location->start());
1232 if ((child = find_named_node (node, "Sources")) == 0) {
1233 error << _("Session: XML state has no sources section") << endmsg;
1235 } else if (load_sources (*child)) {
1239 if ((child = find_named_node (node, "Regions")) == 0) {
1240 error << _("Session: XML state has no Regions section") << endmsg;
1242 } else if (load_regions (*child)) {
1246 if ((child = find_named_node (node, "Playlists")) == 0) {
1247 error << _("Session: XML state has no playlists section") << endmsg;
1249 } else if (load_playlists (*child)) {
1253 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1255 } else if (load_unused_playlists (*child)) {
1259 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1260 if (load_named_selections (*child)) {
1265 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1266 error << _("Session: XML state has no diskstreams section") << endmsg;
1268 } else if (load_diskstreams (*child)) {
1272 if ((child = find_named_node (node, "Bundles")) == 0) {
1273 warning << _("Session: XML state has no bundles section (2.0 session?)") << endmsg;
1276 /* We can't load Bundles yet as they need to be able
1277 to convert from port names to Port objects, which can't happen until
1279 _bundle_xml_node = new XMLNode (*child);
1282 if ((child = find_named_node (node, "EditGroups")) == 0) {
1283 error << _("Session: XML state has no edit groups section") << endmsg;
1285 } else if (load_edit_groups (*child)) {
1289 if ((child = find_named_node (node, "MixGroups")) == 0) {
1290 error << _("Session: XML state has no mix groups section") << endmsg;
1292 } else if (load_mix_groups (*child)) {
1296 if ((child = find_named_node (node, "TempoMap")) == 0) {
1297 error << _("Session: XML state has no Tempo Map section") << endmsg;
1299 } else if (_tempo_map->set_state (*child)) {
1303 if ((child = find_named_node (node, "Routes")) == 0) {
1304 error << _("Session: XML state has no routes section") << endmsg;
1306 } else if (load_routes (*child)) {
1310 if ((child = find_named_node (node, "Click")) == 0) {
1311 warning << _("Session: XML state has no click section") << endmsg;
1312 } else if (_click_io) {
1313 _click_io->set_state (*child);
1316 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1317 ControlProtocolManager::instance().set_protocol_states (*child);
1320 /* here beginneth the second phase ... */
1322 StateReady (); /* EMIT SIGNAL */
1331 Session::load_routes (const XMLNode& node)
1334 XMLNodeConstIterator niter;
1335 RouteList new_routes;
1337 nlist = node.children();
1341 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1343 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1346 error << _("Session: cannot create Route from XML description.") << endmsg;
1350 new_routes.push_back (route);
1353 add_routes (new_routes, false);
1358 boost::shared_ptr<Route>
1359 Session::XMLRouteFactory (const XMLNode& node)
1361 if (node.name() != "Route") {
1362 return boost::shared_ptr<Route> ((Route*) 0);
1365 bool has_diskstream = (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0);
1367 DataType type = DataType::AUDIO;
1368 const XMLProperty* prop = node.property("default-type");
1370 type = DataType(prop->value());
1372 assert(type != DataType::NIL);
1374 if (has_diskstream) {
1375 if (type == DataType::AUDIO) {
1376 boost::shared_ptr<Route> ret (new AudioTrack (*this, node));
1379 boost::shared_ptr<Route> ret (new MidiTrack (*this, node));
1383 boost::shared_ptr<Route> ret (new Route (*this, node));
1389 Session::load_regions (const XMLNode& node)
1392 XMLNodeConstIterator niter;
1393 boost::shared_ptr<Region> region;
1395 nlist = node.children();
1399 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1400 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1401 error << _("Session: cannot create Region from XML description.");
1402 const XMLProperty *name = (**niter).property("name");
1405 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1415 boost::shared_ptr<Region>
1416 Session::XMLRegionFactory (const XMLNode& node, bool full)
1418 const XMLProperty* type = node.property("type");
1422 if ( !type || type->value() == "audio" ) {
1424 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1426 } else if (type->value() == "midi") {
1428 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1432 } catch (failed_constructor& err) {
1433 return boost::shared_ptr<Region> ();
1436 return boost::shared_ptr<Region> ();
1439 boost::shared_ptr<AudioRegion>
1440 Session::XMLAudioRegionFactory (const XMLNode& node, bool full)
1442 const XMLProperty* prop;
1443 boost::shared_ptr<Source> source;
1444 boost::shared_ptr<AudioSource> as;
1446 SourceList master_sources;
1447 uint32_t nchans = 1;
1450 if (node.name() != X_("Region")) {
1451 return boost::shared_ptr<AudioRegion>();
1454 if ((prop = node.property (X_("channels"))) != 0) {
1455 nchans = atoi (prop->value().c_str());
1458 if ((prop = node.property ("name")) == 0) {
1459 cerr << "no name for this region\n";
1463 if ((prop = node.property (X_("source-0"))) == 0) {
1464 if ((prop = node.property ("source")) == 0) {
1465 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1466 return boost::shared_ptr<AudioRegion>();
1470 PBD::ID s_id (prop->value());
1472 if ((source = source_by_id (s_id)) == 0) {
1473 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1474 return boost::shared_ptr<AudioRegion>();
1477 as = boost::dynamic_pointer_cast<AudioSource>(source);
1479 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1480 return boost::shared_ptr<AudioRegion>();
1483 sources.push_back (as);
1485 /* pickup other channels */
1487 for (uint32_t n=1; n < nchans; ++n) {
1488 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1489 if ((prop = node.property (buf)) != 0) {
1491 PBD::ID id2 (prop->value());
1493 if ((source = source_by_id (id2)) == 0) {
1494 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1495 return boost::shared_ptr<AudioRegion>();
1498 as = boost::dynamic_pointer_cast<AudioSource>(source);
1500 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1501 return boost::shared_ptr<AudioRegion>();
1503 sources.push_back (as);
1507 for (uint32_t n=1; n < nchans; ++n) {
1508 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1509 if ((prop = node.property (buf)) != 0) {
1511 PBD::ID id2 (prop->value());
1513 if ((source = source_by_id (id2)) == 0) {
1514 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1515 return boost::shared_ptr<AudioRegion>();
1518 as = boost::dynamic_pointer_cast<AudioSource>(source);
1520 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1521 return boost::shared_ptr<AudioRegion>();
1523 master_sources.push_back (as);
1528 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1530 /* a final detail: this is the one and only place that we know how long missing files are */
1532 if (region->whole_file()) {
1533 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1534 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1536 sfp->set_length (region->length());
1541 if (!master_sources.empty()) {
1542 if (master_sources.size() == nchans) {
1543 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1545 region->set_master_sources (master_sources);
1553 catch (failed_constructor& err) {
1554 return boost::shared_ptr<AudioRegion>();
1558 boost::shared_ptr<MidiRegion>
1559 Session::XMLMidiRegionFactory (const XMLNode& node, bool full)
1561 const XMLProperty* prop;
1562 boost::shared_ptr<Source> source;
1563 boost::shared_ptr<MidiSource> ms;
1565 uint32_t nchans = 1;
1567 if (node.name() != X_("Region")) {
1568 return boost::shared_ptr<MidiRegion>();
1571 if ((prop = node.property (X_("channels"))) != 0) {
1572 nchans = atoi (prop->value().c_str());
1575 if ((prop = node.property ("name")) == 0) {
1576 cerr << "no name for this region\n";
1580 // Multiple midi channels? that's just crazy talk
1581 assert(nchans == 1);
1583 if ((prop = node.property (X_("source-0"))) == 0) {
1584 if ((prop = node.property ("source")) == 0) {
1585 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1586 return boost::shared_ptr<MidiRegion>();
1590 PBD::ID s_id (prop->value());
1592 if ((source = source_by_id (s_id)) == 0) {
1593 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1594 return boost::shared_ptr<MidiRegion>();
1597 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1599 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1600 return boost::shared_ptr<MidiRegion>();
1603 sources.push_back (ms);
1606 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1607 /* a final detail: this is the one and only place that we know how long missing files are */
1609 if (region->whole_file()) {
1610 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1611 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1613 sfp->set_length (region->length());
1621 catch (failed_constructor& err) {
1622 return boost::shared_ptr<MidiRegion>();
1627 Session::get_sources_as_xml ()
1630 XMLNode* node = new XMLNode (X_("Sources"));
1631 Glib::Mutex::Lock lm (source_lock);
1633 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1634 node->add_child_nocopy (i->second->get_state());
1641 Session::path_from_region_name (DataType type, string name, string identifier)
1643 char buf[PATH_MAX+1];
1645 SessionDirectory sdir(get_best_session_directory_for_new_source());
1646 sys::path source_dir = ((type == DataType::AUDIO)
1647 ? sdir.sound_path() : sdir.midi_path());
1649 string ext = ((type == DataType::AUDIO) ? ".wav" : ".mid");
1651 for (n = 0; n < 999999; ++n) {
1652 if (identifier.length()) {
1653 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1654 identifier.c_str(), n, ext.c_str());
1656 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1660 sys::path source_path = source_dir / buf;
1662 if (!sys::exists (source_path)) {
1663 return source_path.to_string();
1667 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1676 Session::load_sources (const XMLNode& node)
1679 XMLNodeConstIterator niter;
1680 boost::shared_ptr<Source> source;
1682 nlist = node.children();
1686 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1689 if ((source = XMLSourceFactory (**niter)) == 0) {
1690 error << _("Session: cannot create Source from XML description.") << endmsg;
1694 catch (non_existent_source& err) {
1695 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1696 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1703 boost::shared_ptr<Source>
1704 Session::XMLSourceFactory (const XMLNode& node)
1706 if (node.name() != "Source") {
1707 return boost::shared_ptr<Source>();
1711 return SourceFactory::create (*this, node);
1714 catch (failed_constructor& err) {
1715 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1716 return boost::shared_ptr<Source>();
1721 Session::save_template (string template_name)
1725 if (_state_of_the_state & CannotSave) {
1729 sys::path user_template_dir(user_template_directory());
1733 sys::create_directories (user_template_dir);
1735 catch(sys::filesystem_error& ex)
1737 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1738 user_template_dir.to_string(), ex.what()) << endmsg;
1742 tree.set_root (&get_template());
1744 sys::path template_file_path(user_template_dir);
1745 template_file_path /= template_name + template_suffix;
1747 if (sys::exists (template_file_path))
1749 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1750 template_file_path.to_string()) << endmsg;
1754 if (!tree.write (template_file_path.to_string())) {
1755 error << _("mix template not saved") << endmsg;
1763 Session::refresh_disk_space ()
1766 struct statfs statfsbuf;
1767 vector<space_and_path>::iterator i;
1768 Glib::Mutex::Lock lm (space_lock);
1771 /* get freespace on every FS that is part of the session path */
1773 _total_free_4k_blocks = 0;
1775 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1776 statfs ((*i).path.c_str(), &statfsbuf);
1778 scale = statfsbuf.f_bsize/4096.0;
1780 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1781 _total_free_4k_blocks += (*i).blocks;
1787 Session::get_best_session_directory_for_new_source ()
1789 vector<space_and_path>::iterator i;
1790 string result = _session_dir->root_path().to_string();
1792 /* handle common case without system calls */
1794 if (session_dirs.size() == 1) {
1798 /* OK, here's the algorithm we're following here:
1800 We want to select which directory to use for
1801 the next file source to be created. Ideally,
1802 we'd like to use a round-robin process so as to
1803 get maximum performance benefits from splitting
1804 the files across multiple disks.
1806 However, in situations without much diskspace, an
1807 RR approach may end up filling up a filesystem
1808 with new files while others still have space.
1809 Its therefore important to pay some attention to
1810 the freespace in the filesystem holding each
1811 directory as well. However, if we did that by
1812 itself, we'd keep creating new files in the file
1813 system with the most space until it was as full
1814 as all others, thus negating any performance
1815 benefits of this RAID-1 like approach.
1817 So, we use a user-configurable space threshold. If
1818 there are at least 2 filesystems with more than this
1819 much space available, we use RR selection between them.
1820 If not, then we pick the filesystem with the most space.
1822 This gets a good balance between the two
1826 refresh_disk_space ();
1828 int free_enough = 0;
1830 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1831 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1836 if (free_enough >= 2) {
1837 /* use RR selection process, ensuring that the one
1841 i = last_rr_session_dir;
1844 if (++i == session_dirs.end()) {
1845 i = session_dirs.begin();
1848 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1849 if (create_session_directory ((*i).path)) {
1851 last_rr_session_dir = i;
1856 } while (i != last_rr_session_dir);
1860 /* pick FS with the most freespace (and that
1861 seems to actually work ...)
1864 vector<space_and_path> sorted;
1865 space_and_path_ascending_cmp cmp;
1867 sorted = session_dirs;
1868 sort (sorted.begin(), sorted.end(), cmp);
1870 for (i = sorted.begin(); i != sorted.end(); ++i) {
1871 if (create_session_directory ((*i).path)) {
1873 last_rr_session_dir = i;
1883 Session::load_playlists (const XMLNode& node)
1886 XMLNodeConstIterator niter;
1887 boost::shared_ptr<Playlist> playlist;
1889 nlist = node.children();
1893 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1895 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1896 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1904 Session::load_unused_playlists (const XMLNode& node)
1907 XMLNodeConstIterator niter;
1908 boost::shared_ptr<Playlist> playlist;
1910 nlist = node.children();
1914 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1916 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1917 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1921 // now manually untrack it
1923 track_playlist (false, boost::weak_ptr<Playlist> (playlist));
1929 boost::shared_ptr<Playlist>
1930 Session::XMLPlaylistFactory (const XMLNode& node)
1933 return PlaylistFactory::create (*this, node);
1936 catch (failed_constructor& err) {
1937 return boost::shared_ptr<Playlist>();
1942 Session::load_named_selections (const XMLNode& node)
1945 XMLNodeConstIterator niter;
1948 nlist = node.children();
1952 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1954 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
1955 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
1963 Session::XMLNamedSelectionFactory (const XMLNode& node)
1966 return new NamedSelection (*this, node);
1969 catch (failed_constructor& err) {
1975 Session::automation_dir () const
1978 res += "automation/";
1983 Session::load_bundles (XMLNode const & node)
1985 XMLNodeList nlist = node.children();
1986 XMLNodeConstIterator niter;
1990 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1991 if ((*niter)->name() == "InputBundle") {
1992 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
1993 } else if ((*niter)->name() == "OutputBundle") {
1994 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
1996 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2005 Session::load_edit_groups (const XMLNode& node)
2007 return load_route_groups (node, true);
2011 Session::load_mix_groups (const XMLNode& node)
2013 return load_route_groups (node, false);
2017 Session::load_route_groups (const XMLNode& node, bool edit)
2019 XMLNodeList nlist = node.children();
2020 XMLNodeConstIterator niter;
2025 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2026 if ((*niter)->name() == "RouteGroup") {
2028 rg = add_edit_group ("");
2029 rg->set_state (**niter);
2031 rg = add_mix_group ("");
2032 rg->set_state (**niter);
2041 Session::auto_save()
2043 save_state (_current_snapshot_name);
2047 Session::add_edit_group (string name)
2049 RouteGroup* rg = new RouteGroup (*this, name);
2050 edit_groups.push_back (rg);
2051 edit_group_added (rg); /* EMIT SIGNAL */
2057 Session::add_mix_group (string name)
2059 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2060 mix_groups.push_back (rg);
2061 mix_group_added (rg); /* EMIT SIGNAL */
2067 Session::remove_edit_group (RouteGroup& rg)
2069 list<RouteGroup*>::iterator i;
2071 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2072 (*i)->apply (&Route::drop_edit_group, this);
2073 edit_groups.erase (i);
2074 edit_group_removed (); /* EMIT SIGNAL */
2081 Session::remove_mix_group (RouteGroup& rg)
2083 list<RouteGroup*>::iterator i;
2085 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2086 (*i)->apply (&Route::drop_mix_group, this);
2087 mix_groups.erase (i);
2088 mix_group_removed (); /* EMIT SIGNAL */
2095 Session::mix_group_by_name (string name)
2097 list<RouteGroup *>::iterator i;
2099 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2100 if ((*i)->name() == name) {
2108 Session::edit_group_by_name (string name)
2110 list<RouteGroup *>::iterator i;
2112 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2113 if ((*i)->name() == name) {
2121 Session::begin_reversible_command (const string& name)
2123 current_trans = new UndoTransaction;
2124 current_trans->set_name (name);
2128 Session::commit_reversible_command (Command *cmd)
2133 current_trans->add_command (cmd);
2136 if (current_trans->empty()) {
2140 gettimeofday (&now, 0);
2141 current_trans->set_timestamp (now);
2143 _history.add (current_trans);
2146 Session::GlobalRouteBooleanState
2147 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2149 GlobalRouteBooleanState s;
2150 boost::shared_ptr<RouteList> r = routes.reader ();
2152 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2153 if (!(*i)->is_hidden()) {
2154 RouteBooleanState v;
2157 Route* r = (*i).get();
2158 v.second = (r->*method)();
2167 Session::GlobalRouteMeterState
2168 Session::get_global_route_metering ()
2170 GlobalRouteMeterState s;
2171 boost::shared_ptr<RouteList> r = routes.reader ();
2173 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2174 if (!(*i)->is_hidden()) {
2178 v.second = (*i)->meter_point();
2188 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2190 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2192 boost::shared_ptr<Route> r = (i->first.lock());
2195 r->set_meter_point (i->second, arg);
2201 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2203 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2205 boost::shared_ptr<Route> r = (i->first.lock());
2208 Route* rp = r.get();
2209 (rp->*method) (i->second, arg);
2215 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2217 set_global_route_boolean (s, &Route::set_mute, src);
2221 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2223 set_global_route_boolean (s, &Route::set_solo, src);
2227 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2229 set_global_route_boolean (s, &Route::set_record_enable, src);
2234 Session::global_mute_memento (void* src)
2236 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2240 Session::global_metering_memento (void* src)
2242 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2246 Session::global_solo_memento (void* src)
2248 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2252 Session::global_record_enable_memento (void* src)
2254 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2259 accept_all_non_peak_files (const string& path, void *arg)
2261 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2265 accept_all_state_files (const string& path, void *arg)
2267 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2271 Session::find_all_sources (string path, set<string>& result)
2276 if (!tree.read (path)) {
2280 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2285 XMLNodeConstIterator niter;
2287 nlist = node->children();
2291 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2295 if ((prop = (*niter)->property (X_("name"))) == 0) {
2299 if (prop->value()[0] == '/') {
2300 /* external file, ignore */
2304 sys::path source_path = _session_dir->sound_path ();
2306 source_path /= prop->value ();
2308 result.insert (source_path.to_string ());
2315 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2317 PathScanner scanner;
2318 vector<string*>* state_files;
2320 string this_snapshot_path;
2326 if (ripped[ripped.length()-1] == '/') {
2327 ripped = ripped.substr (0, ripped.length() - 1);
2330 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2332 if (state_files == 0) {
2337 this_snapshot_path = _path;
2338 this_snapshot_path += _current_snapshot_name;
2339 this_snapshot_path += statefile_suffix;
2341 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2343 if (exclude_this_snapshot && **i == this_snapshot_path) {
2347 if (find_all_sources (**i, result) < 0) {
2355 struct RegionCounter {
2356 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2357 AudioSourceList::iterator iter;
2358 boost::shared_ptr<Region> region;
2361 RegionCounter() : count (0) {}
2365 Session::cleanup_sources (Session::cleanup_report& rep)
2367 // FIXME: needs adaptation to midi
2369 vector<boost::shared_ptr<Source> > dead_sources;
2370 vector<boost::shared_ptr<Playlist> > playlists_tbd;
2371 PathScanner scanner;
2373 vector<space_and_path>::iterator i;
2374 vector<space_and_path>::iterator nexti;
2375 vector<string*>* soundfiles;
2376 vector<string> unused;
2377 set<string> all_sources;
2382 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2385 /* step 1: consider deleting all unused playlists */
2387 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2390 status = AskAboutPlaylistDeletion (*x);
2399 playlists_tbd.push_back (*x);
2403 /* leave it alone */
2408 /* now delete any that were marked for deletion */
2410 for (vector<boost::shared_ptr<Playlist> >::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2411 (*x)->drop_references ();
2414 playlists_tbd.clear ();
2416 /* step 2: find all un-used sources */
2421 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2423 SourceMap::iterator tmp;
2428 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2432 if (!i->second->used() && i->second->length() > 0) {
2433 dead_sources.push_back (i->second);
2434 i->second->GoingAway();
2440 /* build a list of all the possible sound directories for the session */
2442 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2447 SessionDirectory sdir ((*i).path);
2448 sound_path += sdir.sound_path().to_string();
2450 if (nexti != session_dirs.end()) {
2457 /* now do the same thing for the files that ended up in the sounds dir(s)
2458 but are not referenced as sources in any snapshot.
2461 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2463 if (soundfiles == 0) {
2467 /* find all sources, but don't use this snapshot because the
2468 state file on disk still references sources we may have already
2472 find_all_sources_across_snapshots (all_sources, true);
2474 /* add our current source list
2477 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2478 boost::shared_ptr<AudioFileSource> fs;
2480 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (i->second)) != 0) {
2481 all_sources.insert (fs->path());
2485 char tmppath1[PATH_MAX+1];
2486 char tmppath2[PATH_MAX+1];
2488 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2493 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2495 realpath(spath.c_str(), tmppath1);
2496 realpath((*i).c_str(), tmppath2);
2498 if (strcmp(tmppath1, tmppath2) == 0) {
2505 unused.push_back (spath);
2509 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2511 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2512 struct stat statbuf;
2514 rep.paths.push_back (*x);
2515 if (stat ((*x).c_str(), &statbuf) == 0) {
2516 rep.space += statbuf.st_size;
2521 /* don't move the file across filesystems, just
2522 stick it in the `dead_sound_dir_name' directory
2523 on whichever filesystem it was already on.
2526 if ((*x).find ("/sounds/") != string::npos) {
2528 /* old school, go up 1 level */
2530 newpath = Glib::path_get_dirname (*x); // "sounds"
2531 newpath = Glib::path_get_dirname (newpath); // "session-name"
2535 /* new school, go up 4 levels */
2537 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2538 newpath = Glib::path_get_dirname (newpath); // "session-name"
2539 newpath = Glib::path_get_dirname (newpath); // "interchange"
2540 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2544 newpath += dead_sound_dir_name;
2546 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2547 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2552 newpath += Glib::path_get_basename ((*x));
2554 if (access (newpath.c_str(), F_OK) == 0) {
2556 /* the new path already exists, try versioning */
2558 char buf[PATH_MAX+1];
2562 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2565 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2566 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2570 if (version == 999) {
2571 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2575 newpath = newpath_v;
2580 /* it doesn't exist, or we can't read it or something */
2584 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2585 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2586 (*x), newpath, strerror (errno))
2591 /* see if there an easy to find peakfile for this file, and remove it.
2594 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2595 peakpath += peakfile_suffix;
2597 if (access (peakpath.c_str(), W_OK) == 0) {
2598 if (::unlink (peakpath.c_str()) != 0) {
2599 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2600 peakpath, _path, strerror (errno))
2602 /* try to back out */
2603 rename (newpath.c_str(), _path.c_str());
2611 /* dump the history list */
2615 /* save state so we don't end up a session file
2616 referring to non-existent sources.
2622 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2628 Session::cleanup_trash_sources (Session::cleanup_report& rep)
2630 // FIXME: needs adaptation for MIDI
2632 vector<space_and_path>::iterator i;
2633 string dead_sound_dir;
2634 struct dirent* dentry;
2635 struct stat statbuf;
2641 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2643 dead_sound_dir = (*i).path;
2644 dead_sound_dir += dead_sound_dir_name;
2646 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2650 while ((dentry = readdir (dead)) != 0) {
2652 /* avoid '.' and '..' */
2654 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2655 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2661 fullpath = dead_sound_dir;
2663 fullpath += dentry->d_name;
2665 if (stat (fullpath.c_str(), &statbuf)) {
2669 if (!S_ISREG (statbuf.st_mode)) {
2673 if (unlink (fullpath.c_str())) {
2674 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2675 fullpath, strerror (errno))
2679 rep.paths.push_back (dentry->d_name);
2680 rep.space += statbuf.st_size;
2691 Session::set_dirty ()
2693 bool was_dirty = dirty();
2695 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2699 DirtyChanged(); /* EMIT SIGNAL */
2705 Session::set_clean ()
2707 bool was_dirty = dirty();
2709 _state_of_the_state = Clean;
2713 DirtyChanged(); /* EMIT SIGNAL */
2718 Session::set_deletion_in_progress ()
2720 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2725 Session::add_controllable (boost::shared_ptr<Controllable> c)
2727 /* this adds a controllable to the list managed by the Session.
2728 this is a subset of those managed by the Controllable class
2729 itself, and represents the only ones whose state will be saved
2730 as part of the session.
2733 Glib::Mutex::Lock lm (controllables_lock);
2734 controllables.insert (c);
2737 struct null_deleter { void operator()(void const *) const {} };
2740 Session::remove_controllable (Controllable* c)
2742 if (_state_of_the_state | Deletion) {
2746 Glib::Mutex::Lock lm (controllables_lock);
2748 Controllables::iterator x = controllables.find(
2749 boost::shared_ptr<Controllable>(c, null_deleter()));
2751 if (x != controllables.end()) {
2752 controllables.erase (x);
2756 boost::shared_ptr<Controllable>
2757 Session::controllable_by_id (const PBD::ID& id)
2759 Glib::Mutex::Lock lm (controllables_lock);
2761 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2762 if ((*i)->id() == id) {
2767 return boost::shared_ptr<Controllable>();
2771 Session::add_instant_xml (XMLNode& node)
2773 Stateful::add_instant_xml (node, _path);
2774 Config->add_instant_xml (node);
2778 Session::instant_xml (const string& node_name)
2780 return Stateful::instant_xml (node_name, _path);
2784 Session::save_history (string snapshot_name)
2788 if (snapshot_name.empty()) {
2789 snapshot_name = _current_snapshot_name;
2792 const string history_filename = snapshot_name + history_suffix;
2793 const string backup_filename = history_filename + backup_suffix;
2794 const sys::path xml_path = _session_dir->root_path() / history_filename;
2795 const sys::path backup_path = _session_dir->root_path() / backup_filename;
2797 if (sys::exists (xml_path)) {
2800 sys::rename (xml_path, backup_path);
2802 catch (const sys::filesystem_error& err)
2804 error << _("could not backup old history file, current history not saved") << endmsg;
2810 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
2814 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
2816 if (!tree.write (xml_path.to_string()))
2818 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
2822 sys::remove (xml_path);
2823 sys::rename (backup_path, xml_path);
2825 catch (const sys::filesystem_error& err)
2827 error << string_compose (_("could not restore history file from backup %1 (%2)"),
2828 backup_path.to_string(), err.what()) << endmsg;
2838 Session::restore_history (string snapshot_name)
2842 if (snapshot_name.empty()) {
2843 snapshot_name = _current_snapshot_name;
2846 const string xml_filename = snapshot_name + history_suffix;
2847 const sys::path xml_path = _session_dir->root_path() / xml_filename;
2849 cerr << "Loading history from " << xml_path.to_string() << endmsg;
2851 if (!sys::exists (xml_path)) {
2852 info << string_compose (_("%1: no history file \"%2\" for this session."),
2853 _name, xml_path.to_string()) << endmsg;
2857 if (!tree.read (xml_path.to_string())) {
2858 error << string_compose (_("Could not understand session history file \"%1\""),
2859 xml_path.to_string()) << endmsg;
2866 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
2869 UndoTransaction* ut = new UndoTransaction ();
2872 ut->set_name(t->property("name")->value());
2873 stringstream ss(t->property("tv_sec")->value());
2875 ss.str(t->property("tv_usec")->value());
2877 ut->set_timestamp(tv);
2879 for (XMLNodeConstIterator child_it = t->children().begin();
2880 child_it != t->children().end();
2883 XMLNode *n = *child_it;
2886 if (n->name() == "MementoCommand" ||
2887 n->name() == "MementoUndoCommand" ||
2888 n->name() == "MementoRedoCommand") {
2890 if ((c = memento_command_factory(n))) {
2894 } else if (n->name() == X_("GlobalRouteStateCommand")) {
2896 if ((c = global_state_command_factory (*n))) {
2897 ut->add_command (c);
2902 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
2913 Session::config_changed (const char* parameter_name)
2915 #define PARAM_IS(x) (!strcmp (parameter_name, (x)))
2917 if (PARAM_IS ("seamless-loop")) {
2919 } else if (PARAM_IS ("rf-speed")) {
2921 } else if (PARAM_IS ("auto-loop")) {
2923 } else if (PARAM_IS ("auto-input")) {
2925 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
2926 /* auto-input only makes a difference if we're rolling */
2928 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2930 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2931 if ((*i)->record_enabled ()) {
2932 (*i)->monitor_input (!Config->get_auto_input());
2937 } else if (PARAM_IS ("punch-in")) {
2941 if ((location = _locations.auto_punch_location()) != 0) {
2943 if (Config->get_punch_in ()) {
2944 replace_event (Event::PunchIn, location->start());
2946 remove_event (location->start(), Event::PunchIn);
2950 } else if (PARAM_IS ("punch-out")) {
2954 if ((location = _locations.auto_punch_location()) != 0) {
2956 if (Config->get_punch_out()) {
2957 replace_event (Event::PunchOut, location->end());
2959 clear_events (Event::PunchOut);
2963 } else if (PARAM_IS ("edit-mode")) {
2965 Glib::Mutex::Lock lm (playlist_lock);
2967 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2968 (*i)->set_edit_mode (Config->get_edit_mode ());
2971 } else if (PARAM_IS ("use-video-sync")) {
2973 waiting_for_sync_offset = Config->get_use_video_sync();
2975 } else if (PARAM_IS ("mmc-control")) {
2977 //poke_midi_thread ();
2979 } else if (PARAM_IS ("mmc-device-id") || PARAM_IS ("mmc-receive-id")) {
2982 mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
2985 } else if (PARAM_IS ("mmc-send-id")) {
2988 mmc->set_send_device_id (Config->get_mmc_send_device_id());
2991 } else if (PARAM_IS ("midi-control")) {
2993 //poke_midi_thread ();
2995 } else if (PARAM_IS ("raid-path")) {
2997 setup_raid_path (Config->get_raid_path());
2999 } else if (PARAM_IS ("smpte-format")) {
3003 } else if (PARAM_IS ("video-pullup")) {
3007 } else if (PARAM_IS ("seamless-loop")) {
3009 if (play_loop && transport_rolling()) {
3010 // to reset diskstreams etc
3011 request_play_loop (true);
3014 } else if (PARAM_IS ("rf-speed")) {
3016 cumulative_rf_motion = 0;
3019 } else if (PARAM_IS ("click-sound")) {
3021 setup_click_sounds (1);
3023 } else if (PARAM_IS ("click-emphasis-sound")) {
3025 setup_click_sounds (-1);
3027 } else if (PARAM_IS ("clicking")) {
3029 if (Config->get_clicking()) {
3030 if (_click_io && click_data) { // don't require emphasis data
3037 } else if (PARAM_IS ("send-mtc")) {
3039 /* only set the internal flag if we have
3043 if (_mtc_port != 0) {
3044 session_send_mtc = Config->get_send_mtc();
3045 if (session_send_mtc) {
3046 /* mark us ready to send */
3047 next_quarter_frame_to_send = 0;
3050 session_send_mtc = false;
3053 } else if (PARAM_IS ("send-mmc")) {
3055 /* only set the internal flag if we have
3059 if (_mmc_port != 0) {
3060 session_send_mmc = Config->get_send_mmc();
3063 session_send_mmc = false;
3066 } else if (PARAM_IS ("midi-feedback")) {
3068 /* only set the internal flag if we have
3072 if (_mtc_port != 0) {
3073 session_midi_feedback = Config->get_midi_feedback();
3076 } else if (PARAM_IS ("jack-time-master")) {
3078 engine().reset_timebase ();
3080 } else if (PARAM_IS ("native-file-header-format")) {
3082 if (!first_file_header_format_reset) {
3083 reset_native_file_format ();
3086 first_file_header_format_reset = false;
3088 } else if (PARAM_IS ("native-file-data-format")) {
3090 if (!first_file_data_format_reset) {
3091 reset_native_file_format ();
3094 first_file_data_format_reset = false;
3096 } else if (PARAM_IS ("slave-source")) {
3097 set_slave_source (Config->get_slave_source());
3098 } else if (PARAM_IS ("remote-model")) {
3099 set_remote_control_ids ();
3100 } else if (PARAM_IS ("denormal-model")) {
3102 } else if (PARAM_IS ("history-depth")) {
3103 set_history_depth (Config->get_history_depth());
3104 } else if (PARAM_IS ("sync-all-route-ordering")) {
3115 Session::set_history_depth (uint32_t d)
3117 _history.set_depth (d);