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.") << endmsg;
1408 boost::shared_ptr<Region>
1409 Session::XMLRegionFactory (const XMLNode& node, bool full)
1411 const XMLProperty* type = node.property("type");
1415 if ( !type || type->value() == "audio" ) {
1417 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1419 } else if (type->value() == "midi") {
1421 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1425 } catch (failed_constructor& err) {
1426 return boost::shared_ptr<Region> ();
1429 return boost::shared_ptr<Region> ();
1432 boost::shared_ptr<AudioRegion>
1433 Session::XMLAudioRegionFactory (const XMLNode& node, bool full)
1435 const XMLProperty* prop;
1436 boost::shared_ptr<Source> source;
1437 boost::shared_ptr<AudioSource> as;
1439 SourceList master_sources;
1440 uint32_t nchans = 1;
1443 if (node.name() != X_("Region")) {
1444 return boost::shared_ptr<AudioRegion>();
1447 if ((prop = node.property (X_("channels"))) != 0) {
1448 nchans = atoi (prop->value().c_str());
1451 if ((prop = node.property ("name")) == 0) {
1452 cerr << "no name for this region\n";
1456 if ((prop = node.property (X_("source-0"))) == 0) {
1457 if ((prop = node.property ("source")) == 0) {
1458 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1459 return boost::shared_ptr<AudioRegion>();
1463 PBD::ID s_id (prop->value());
1465 if ((source = source_by_id (s_id)) == 0) {
1466 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1467 return boost::shared_ptr<AudioRegion>();
1470 as = boost::dynamic_pointer_cast<AudioSource>(source);
1472 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1473 return boost::shared_ptr<AudioRegion>();
1476 sources.push_back (as);
1478 /* pickup other channels */
1480 for (uint32_t n=1; n < nchans; ++n) {
1481 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1482 if ((prop = node.property (buf)) != 0) {
1484 PBD::ID id2 (prop->value());
1486 if ((source = source_by_id (id2)) == 0) {
1487 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1488 return boost::shared_ptr<AudioRegion>();
1491 as = boost::dynamic_pointer_cast<AudioSource>(source);
1493 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1494 return boost::shared_ptr<AudioRegion>();
1496 sources.push_back (as);
1500 for (uint32_t n=1; n < nchans; ++n) {
1501 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1502 if ((prop = node.property (buf)) != 0) {
1504 PBD::ID id2 (prop->value());
1506 if ((source = source_by_id (id2)) == 0) {
1507 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1508 return boost::shared_ptr<AudioRegion>();
1511 as = boost::dynamic_pointer_cast<AudioSource>(source);
1513 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1514 return boost::shared_ptr<AudioRegion>();
1516 master_sources.push_back (as);
1521 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1523 /* a final detail: this is the one and only place that we know how long missing files are */
1525 if (region->whole_file()) {
1526 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1527 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1529 sfp->set_length (region->length());
1534 if (!master_sources.empty()) {
1535 if (master_sources.size() == nchans) {
1536 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1538 region->set_master_sources (master_sources);
1546 catch (failed_constructor& err) {
1547 return boost::shared_ptr<AudioRegion>();
1551 boost::shared_ptr<MidiRegion>
1552 Session::XMLMidiRegionFactory (const XMLNode& node, bool full)
1554 const XMLProperty* prop;
1555 boost::shared_ptr<Source> source;
1556 boost::shared_ptr<MidiSource> ms;
1558 uint32_t nchans = 1;
1560 if (node.name() != X_("Region")) {
1561 return boost::shared_ptr<MidiRegion>();
1564 if ((prop = node.property (X_("channels"))) != 0) {
1565 nchans = atoi (prop->value().c_str());
1568 if ((prop = node.property ("name")) == 0) {
1569 cerr << "no name for this region\n";
1573 // Multiple midi channels? that's just crazy talk
1574 assert(nchans == 1);
1576 if ((prop = node.property (X_("source-0"))) == 0) {
1577 if ((prop = node.property ("source")) == 0) {
1578 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1579 return boost::shared_ptr<MidiRegion>();
1583 PBD::ID s_id (prop->value());
1585 if ((source = source_by_id (s_id)) == 0) {
1586 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1587 return boost::shared_ptr<MidiRegion>();
1590 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1592 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1593 return boost::shared_ptr<MidiRegion>();
1596 sources.push_back (ms);
1599 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1600 /* a final detail: this is the one and only place that we know how long missing files are */
1602 if (region->whole_file()) {
1603 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1604 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1606 sfp->set_length (region->length());
1614 catch (failed_constructor& err) {
1615 return boost::shared_ptr<MidiRegion>();
1620 Session::get_sources_as_xml ()
1623 XMLNode* node = new XMLNode (X_("Sources"));
1624 Glib::Mutex::Lock lm (source_lock);
1626 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1627 node->add_child_nocopy (i->second->get_state());
1634 Session::path_from_region_name (DataType type, string name, string identifier)
1636 char buf[PATH_MAX+1];
1638 SessionDirectory sdir(get_best_session_directory_for_new_source());
1639 sys::path source_dir = ((type == DataType::AUDIO)
1640 ? sdir.sound_path() : sdir.midi_path());
1642 string ext = ((type == DataType::AUDIO) ? ".wav" : ".mid");
1644 for (n = 0; n < 999999; ++n) {
1645 if (identifier.length()) {
1646 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1647 identifier.c_str(), n, ext.c_str());
1649 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1653 sys::path source_path = source_dir / buf;
1655 if (!sys::exists (source_path)) {
1656 return source_path.to_string();
1660 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1669 Session::load_sources (const XMLNode& node)
1672 XMLNodeConstIterator niter;
1673 boost::shared_ptr<Source> source;
1675 nlist = node.children();
1679 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1682 if ((source = XMLSourceFactory (**niter)) == 0) {
1683 error << _("Session: cannot create Source from XML description.") << endmsg;
1687 catch (non_existent_source& err) {
1688 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1689 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1696 boost::shared_ptr<Source>
1697 Session::XMLSourceFactory (const XMLNode& node)
1699 if (node.name() != "Source") {
1700 return boost::shared_ptr<Source>();
1704 return SourceFactory::create (*this, node);
1707 catch (failed_constructor& err) {
1708 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1709 return boost::shared_ptr<Source>();
1714 Session::save_template (string template_name)
1718 if (_state_of_the_state & CannotSave) {
1722 sys::path user_template_dir(user_template_directory());
1726 sys::create_directories (user_template_dir);
1728 catch(sys::filesystem_error& ex)
1730 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1731 user_template_dir.to_string(), ex.what()) << endmsg;
1735 tree.set_root (&get_template());
1737 sys::path template_file_path(user_template_dir);
1738 template_file_path /= template_name + template_suffix;
1740 if (sys::exists (template_file_path))
1742 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1743 template_file_path.to_string()) << endmsg;
1747 if (!tree.write (template_file_path.to_string())) {
1748 error << _("mix template not saved") << endmsg;
1756 Session::refresh_disk_space ()
1759 struct statfs statfsbuf;
1760 vector<space_and_path>::iterator i;
1761 Glib::Mutex::Lock lm (space_lock);
1764 /* get freespace on every FS that is part of the session path */
1766 _total_free_4k_blocks = 0;
1768 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1769 statfs ((*i).path.c_str(), &statfsbuf);
1771 scale = statfsbuf.f_bsize/4096.0;
1773 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1774 _total_free_4k_blocks += (*i).blocks;
1780 Session::get_best_session_directory_for_new_source ()
1782 vector<space_and_path>::iterator i;
1783 string result = _session_dir->root_path().to_string();
1785 /* handle common case without system calls */
1787 if (session_dirs.size() == 1) {
1791 /* OK, here's the algorithm we're following here:
1793 We want to select which directory to use for
1794 the next file source to be created. Ideally,
1795 we'd like to use a round-robin process so as to
1796 get maximum performance benefits from splitting
1797 the files across multiple disks.
1799 However, in situations without much diskspace, an
1800 RR approach may end up filling up a filesystem
1801 with new files while others still have space.
1802 Its therefore important to pay some attention to
1803 the freespace in the filesystem holding each
1804 directory as well. However, if we did that by
1805 itself, we'd keep creating new files in the file
1806 system with the most space until it was as full
1807 as all others, thus negating any performance
1808 benefits of this RAID-1 like approach.
1810 So, we use a user-configurable space threshold. If
1811 there are at least 2 filesystems with more than this
1812 much space available, we use RR selection between them.
1813 If not, then we pick the filesystem with the most space.
1815 This gets a good balance between the two
1819 refresh_disk_space ();
1821 int free_enough = 0;
1823 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1824 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1829 if (free_enough >= 2) {
1830 /* use RR selection process, ensuring that the one
1834 i = last_rr_session_dir;
1837 if (++i == session_dirs.end()) {
1838 i = session_dirs.begin();
1841 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1842 if (create_session_directory ((*i).path)) {
1844 last_rr_session_dir = i;
1849 } while (i != last_rr_session_dir);
1853 /* pick FS with the most freespace (and that
1854 seems to actually work ...)
1857 vector<space_and_path> sorted;
1858 space_and_path_ascending_cmp cmp;
1860 sorted = session_dirs;
1861 sort (sorted.begin(), sorted.end(), cmp);
1863 for (i = sorted.begin(); i != sorted.end(); ++i) {
1864 if (create_session_directory ((*i).path)) {
1866 last_rr_session_dir = i;
1876 Session::load_playlists (const XMLNode& node)
1879 XMLNodeConstIterator niter;
1880 boost::shared_ptr<Playlist> playlist;
1882 nlist = node.children();
1886 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1888 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1889 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1897 Session::load_unused_playlists (const XMLNode& node)
1900 XMLNodeConstIterator niter;
1901 boost::shared_ptr<Playlist> playlist;
1903 nlist = node.children();
1907 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1909 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1910 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1914 // now manually untrack it
1916 track_playlist (false, boost::weak_ptr<Playlist> (playlist));
1922 boost::shared_ptr<Playlist>
1923 Session::XMLPlaylistFactory (const XMLNode& node)
1926 return PlaylistFactory::create (*this, node);
1929 catch (failed_constructor& err) {
1930 return boost::shared_ptr<Playlist>();
1935 Session::load_named_selections (const XMLNode& node)
1938 XMLNodeConstIterator niter;
1941 nlist = node.children();
1945 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1947 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
1948 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
1956 Session::XMLNamedSelectionFactory (const XMLNode& node)
1959 return new NamedSelection (*this, node);
1962 catch (failed_constructor& err) {
1968 Session::automation_dir () const
1971 res += "automation/";
1976 Session::load_bundles (XMLNode const & node)
1978 XMLNodeList nlist = node.children();
1979 XMLNodeConstIterator niter;
1983 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1984 if ((*niter)->name() == "InputBundle") {
1985 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
1986 } else if ((*niter)->name() == "OutputBundle") {
1987 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
1989 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
1998 Session::load_edit_groups (const XMLNode& node)
2000 return load_route_groups (node, true);
2004 Session::load_mix_groups (const XMLNode& node)
2006 return load_route_groups (node, false);
2010 Session::load_route_groups (const XMLNode& node, bool edit)
2012 XMLNodeList nlist = node.children();
2013 XMLNodeConstIterator niter;
2018 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2019 if ((*niter)->name() == "RouteGroup") {
2021 rg = add_edit_group ("");
2022 rg->set_state (**niter);
2024 rg = add_mix_group ("");
2025 rg->set_state (**niter);
2034 Session::auto_save()
2036 save_state (_current_snapshot_name);
2040 Session::add_edit_group (string name)
2042 RouteGroup* rg = new RouteGroup (*this, name);
2043 edit_groups.push_back (rg);
2044 edit_group_added (rg); /* EMIT SIGNAL */
2050 Session::add_mix_group (string name)
2052 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2053 mix_groups.push_back (rg);
2054 mix_group_added (rg); /* EMIT SIGNAL */
2060 Session::remove_edit_group (RouteGroup& rg)
2062 list<RouteGroup*>::iterator i;
2064 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2065 (*i)->apply (&Route::drop_edit_group, this);
2066 edit_groups.erase (i);
2067 edit_group_removed (); /* EMIT SIGNAL */
2074 Session::remove_mix_group (RouteGroup& rg)
2076 list<RouteGroup*>::iterator i;
2078 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2079 (*i)->apply (&Route::drop_mix_group, this);
2080 mix_groups.erase (i);
2081 mix_group_removed (); /* EMIT SIGNAL */
2088 Session::mix_group_by_name (string name)
2090 list<RouteGroup *>::iterator i;
2092 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2093 if ((*i)->name() == name) {
2101 Session::edit_group_by_name (string name)
2103 list<RouteGroup *>::iterator i;
2105 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2106 if ((*i)->name() == name) {
2114 Session::begin_reversible_command (const string& name)
2116 current_trans = new UndoTransaction;
2117 current_trans->set_name (name);
2121 Session::commit_reversible_command (Command *cmd)
2126 current_trans->add_command (cmd);
2129 if (current_trans->empty()) {
2133 gettimeofday (&now, 0);
2134 current_trans->set_timestamp (now);
2136 _history.add (current_trans);
2139 Session::GlobalRouteBooleanState
2140 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2142 GlobalRouteBooleanState s;
2143 boost::shared_ptr<RouteList> r = routes.reader ();
2145 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2146 if (!(*i)->is_hidden()) {
2147 RouteBooleanState v;
2150 Route* r = (*i).get();
2151 v.second = (r->*method)();
2160 Session::GlobalRouteMeterState
2161 Session::get_global_route_metering ()
2163 GlobalRouteMeterState s;
2164 boost::shared_ptr<RouteList> r = routes.reader ();
2166 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2167 if (!(*i)->is_hidden()) {
2171 v.second = (*i)->meter_point();
2181 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2183 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2185 boost::shared_ptr<Route> r = (i->first.lock());
2188 r->set_meter_point (i->second, arg);
2194 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2196 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2198 boost::shared_ptr<Route> r = (i->first.lock());
2201 Route* rp = r.get();
2202 (rp->*method) (i->second, arg);
2208 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2210 set_global_route_boolean (s, &Route::set_mute, src);
2214 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2216 set_global_route_boolean (s, &Route::set_solo, src);
2220 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2222 set_global_route_boolean (s, &Route::set_record_enable, src);
2227 Session::global_mute_memento (void* src)
2229 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2233 Session::global_metering_memento (void* src)
2235 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2239 Session::global_solo_memento (void* src)
2241 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2245 Session::global_record_enable_memento (void* src)
2247 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2252 accept_all_non_peak_files (const string& path, void *arg)
2254 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2258 accept_all_state_files (const string& path, void *arg)
2260 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2264 Session::find_all_sources (string path, set<string>& result)
2269 if (!tree.read (path)) {
2273 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2278 XMLNodeConstIterator niter;
2280 nlist = node->children();
2284 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2288 if ((prop = (*niter)->property (X_("name"))) == 0) {
2292 if (prop->value()[0] == '/') {
2293 /* external file, ignore */
2297 sys::path source_path = _session_dir->sound_path ();
2299 source_path /= prop->value ();
2301 result.insert (source_path.to_string ());
2308 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2310 PathScanner scanner;
2311 vector<string*>* state_files;
2313 string this_snapshot_path;
2319 if (ripped[ripped.length()-1] == '/') {
2320 ripped = ripped.substr (0, ripped.length() - 1);
2323 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2325 if (state_files == 0) {
2330 this_snapshot_path = _path;
2331 this_snapshot_path += _current_snapshot_name;
2332 this_snapshot_path += statefile_suffix;
2334 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2336 if (exclude_this_snapshot && **i == this_snapshot_path) {
2340 if (find_all_sources (**i, result) < 0) {
2348 struct RegionCounter {
2349 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2350 AudioSourceList::iterator iter;
2351 boost::shared_ptr<Region> region;
2354 RegionCounter() : count (0) {}
2358 Session::cleanup_sources (Session::cleanup_report& rep)
2360 // FIXME: needs adaptation to midi
2362 vector<boost::shared_ptr<Source> > dead_sources;
2363 vector<boost::shared_ptr<Playlist> > playlists_tbd;
2364 PathScanner scanner;
2366 vector<space_and_path>::iterator i;
2367 vector<space_and_path>::iterator nexti;
2368 vector<string*>* soundfiles;
2369 vector<string> unused;
2370 set<string> all_sources;
2375 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2378 /* step 1: consider deleting all unused playlists */
2380 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2383 status = AskAboutPlaylistDeletion (*x);
2392 playlists_tbd.push_back (*x);
2396 /* leave it alone */
2401 /* now delete any that were marked for deletion */
2403 for (vector<boost::shared_ptr<Playlist> >::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2404 (*x)->drop_references ();
2407 playlists_tbd.clear ();
2409 /* step 2: find all un-used sources */
2414 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2416 SourceMap::iterator tmp;
2421 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2425 if (!i->second->used() && i->second->length() > 0) {
2426 dead_sources.push_back (i->second);
2427 i->second->GoingAway();
2433 /* build a list of all the possible sound directories for the session */
2435 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2440 SessionDirectory sdir ((*i).path);
2441 sound_path += sdir.sound_path().to_string();
2443 if (nexti != session_dirs.end()) {
2450 /* now do the same thing for the files that ended up in the sounds dir(s)
2451 but are not referenced as sources in any snapshot.
2454 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2456 if (soundfiles == 0) {
2460 /* find all sources, but don't use this snapshot because the
2461 state file on disk still references sources we may have already
2465 find_all_sources_across_snapshots (all_sources, true);
2467 /* add our current source list
2470 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2471 boost::shared_ptr<AudioFileSource> fs;
2473 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (i->second)) != 0) {
2474 all_sources.insert (fs->path());
2478 char tmppath1[PATH_MAX+1];
2479 char tmppath2[PATH_MAX+1];
2481 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2486 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2488 realpath(spath.c_str(), tmppath1);
2489 realpath((*i).c_str(), tmppath2);
2491 if (strcmp(tmppath1, tmppath2) == 0) {
2498 unused.push_back (spath);
2502 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2504 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2505 struct stat statbuf;
2507 rep.paths.push_back (*x);
2508 if (stat ((*x).c_str(), &statbuf) == 0) {
2509 rep.space += statbuf.st_size;
2514 /* don't move the file across filesystems, just
2515 stick it in the `dead_sound_dir_name' directory
2516 on whichever filesystem it was already on.
2519 if ((*x).find ("/sounds/") != string::npos) {
2521 /* old school, go up 1 level */
2523 newpath = Glib::path_get_dirname (*x); // "sounds"
2524 newpath = Glib::path_get_dirname (newpath); // "session-name"
2528 /* new school, go up 4 levels */
2530 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2531 newpath = Glib::path_get_dirname (newpath); // "session-name"
2532 newpath = Glib::path_get_dirname (newpath); // "interchange"
2533 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2537 newpath += dead_sound_dir_name;
2539 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2540 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2545 newpath += Glib::path_get_basename ((*x));
2547 if (access (newpath.c_str(), F_OK) == 0) {
2549 /* the new path already exists, try versioning */
2551 char buf[PATH_MAX+1];
2555 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2558 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2559 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2563 if (version == 999) {
2564 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2568 newpath = newpath_v;
2573 /* it doesn't exist, or we can't read it or something */
2577 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2578 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2579 (*x), newpath, strerror (errno))
2584 /* see if there an easy to find peakfile for this file, and remove it.
2587 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2588 peakpath += peakfile_suffix;
2590 if (access (peakpath.c_str(), W_OK) == 0) {
2591 if (::unlink (peakpath.c_str()) != 0) {
2592 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2593 peakpath, _path, strerror (errno))
2595 /* try to back out */
2596 rename (newpath.c_str(), _path.c_str());
2604 /* dump the history list */
2608 /* save state so we don't end up a session file
2609 referring to non-existent sources.
2615 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2621 Session::cleanup_trash_sources (Session::cleanup_report& rep)
2623 // FIXME: needs adaptation for MIDI
2625 vector<space_and_path>::iterator i;
2626 string dead_sound_dir;
2627 struct dirent* dentry;
2628 struct stat statbuf;
2634 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2636 dead_sound_dir = (*i).path;
2637 dead_sound_dir += dead_sound_dir_name;
2639 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2643 while ((dentry = readdir (dead)) != 0) {
2645 /* avoid '.' and '..' */
2647 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2648 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2654 fullpath = dead_sound_dir;
2656 fullpath += dentry->d_name;
2658 if (stat (fullpath.c_str(), &statbuf)) {
2662 if (!S_ISREG (statbuf.st_mode)) {
2666 if (unlink (fullpath.c_str())) {
2667 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2668 fullpath, strerror (errno))
2672 rep.paths.push_back (dentry->d_name);
2673 rep.space += statbuf.st_size;
2684 Session::set_dirty ()
2686 bool was_dirty = dirty();
2688 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2692 DirtyChanged(); /* EMIT SIGNAL */
2698 Session::set_clean ()
2700 bool was_dirty = dirty();
2702 _state_of_the_state = Clean;
2706 DirtyChanged(); /* EMIT SIGNAL */
2711 Session::set_deletion_in_progress ()
2713 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2718 Session::add_controllable (boost::shared_ptr<Controllable> c)
2720 /* this adds a controllable to the list managed by the Session.
2721 this is a subset of those managed by the Controllable class
2722 itself, and represents the only ones whose state will be saved
2723 as part of the session.
2726 Glib::Mutex::Lock lm (controllables_lock);
2727 controllables.insert (c);
2730 struct null_deleter { void operator()(void const *) const {} };
2733 Session::remove_controllable (Controllable* c)
2735 if (_state_of_the_state | Deletion) {
2739 Glib::Mutex::Lock lm (controllables_lock);
2741 Controllables::iterator x = controllables.find(
2742 boost::shared_ptr<Controllable>(c, null_deleter()));
2744 if (x != controllables.end()) {
2745 controllables.erase (x);
2749 boost::shared_ptr<Controllable>
2750 Session::controllable_by_id (const PBD::ID& id)
2752 Glib::Mutex::Lock lm (controllables_lock);
2754 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2755 if ((*i)->id() == id) {
2760 return boost::shared_ptr<Controllable>();
2764 Session::add_instant_xml (XMLNode& node)
2766 Stateful::add_instant_xml (node, _path);
2767 Config->add_instant_xml (node);
2771 Session::instant_xml (const string& node_name)
2773 return Stateful::instant_xml (node_name, _path);
2777 Session::save_history (string snapshot_name)
2781 if (snapshot_name.empty()) {
2782 snapshot_name = _current_snapshot_name;
2785 const string history_filename = snapshot_name + history_suffix;
2786 const string backup_filename = history_filename + backup_suffix;
2787 const sys::path xml_path = _session_dir->root_path() / history_filename;
2788 const sys::path backup_path = _session_dir->root_path() / backup_filename;
2790 if (sys::exists (xml_path)) {
2793 sys::rename (xml_path, backup_path);
2795 catch (const sys::filesystem_error& err)
2797 error << _("could not backup old history file, current history not saved") << endmsg;
2803 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
2807 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
2809 if (!tree.write (xml_path.to_string()))
2811 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
2815 sys::remove (xml_path);
2816 sys::rename (backup_path, xml_path);
2818 catch (const sys::filesystem_error& err)
2820 error << string_compose (_("could not restore history file from backup %1 (%2)"),
2821 backup_path.to_string(), err.what()) << endmsg;
2831 Session::restore_history (string snapshot_name)
2835 if (snapshot_name.empty()) {
2836 snapshot_name = _current_snapshot_name;
2839 const string xml_filename = snapshot_name + history_suffix;
2840 const sys::path xml_path = _session_dir->root_path() / xml_filename;
2842 cerr << "Loading history from " << xml_path.to_string() << endmsg;
2844 if (!sys::exists (xml_path)) {
2845 info << string_compose (_("%1: no history file \"%2\" for this session."),
2846 _name, xml_path.to_string()) << endmsg;
2850 if (!tree.read (xml_path.to_string())) {
2851 error << string_compose (_("Could not understand session history file \"%1\""),
2852 xml_path.to_string()) << endmsg;
2859 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
2862 UndoTransaction* ut = new UndoTransaction ();
2865 ut->set_name(t->property("name")->value());
2866 stringstream ss(t->property("tv_sec")->value());
2868 ss.str(t->property("tv_usec")->value());
2870 ut->set_timestamp(tv);
2872 for (XMLNodeConstIterator child_it = t->children().begin();
2873 child_it != t->children().end();
2876 XMLNode *n = *child_it;
2879 if (n->name() == "MementoCommand" ||
2880 n->name() == "MementoUndoCommand" ||
2881 n->name() == "MementoRedoCommand") {
2883 if ((c = memento_command_factory(n))) {
2887 } else if (n->name() == X_("GlobalRouteStateCommand")) {
2889 if ((c = global_state_command_factory (*n))) {
2890 ut->add_command (c);
2895 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
2906 Session::config_changed (const char* parameter_name)
2908 #define PARAM_IS(x) (!strcmp (parameter_name, (x)))
2910 if (PARAM_IS ("seamless-loop")) {
2912 } else if (PARAM_IS ("rf-speed")) {
2914 } else if (PARAM_IS ("auto-loop")) {
2916 } else if (PARAM_IS ("auto-input")) {
2918 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
2919 /* auto-input only makes a difference if we're rolling */
2921 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2923 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2924 if ((*i)->record_enabled ()) {
2925 (*i)->monitor_input (!Config->get_auto_input());
2930 } else if (PARAM_IS ("punch-in")) {
2934 if ((location = _locations.auto_punch_location()) != 0) {
2936 if (Config->get_punch_in ()) {
2937 replace_event (Event::PunchIn, location->start());
2939 remove_event (location->start(), Event::PunchIn);
2943 } else if (PARAM_IS ("punch-out")) {
2947 if ((location = _locations.auto_punch_location()) != 0) {
2949 if (Config->get_punch_out()) {
2950 replace_event (Event::PunchOut, location->end());
2952 clear_events (Event::PunchOut);
2956 } else if (PARAM_IS ("edit-mode")) {
2958 Glib::Mutex::Lock lm (playlist_lock);
2960 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2961 (*i)->set_edit_mode (Config->get_edit_mode ());
2964 } else if (PARAM_IS ("use-video-sync")) {
2966 waiting_for_sync_offset = Config->get_use_video_sync();
2968 } else if (PARAM_IS ("mmc-control")) {
2970 //poke_midi_thread ();
2972 } else if (PARAM_IS ("mmc-device-id") || PARAM_IS ("mmc-receive-id")) {
2975 mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
2978 } else if (PARAM_IS ("mmc-send-id")) {
2981 mmc->set_send_device_id (Config->get_mmc_send_device_id());
2984 } else if (PARAM_IS ("midi-control")) {
2986 //poke_midi_thread ();
2988 } else if (PARAM_IS ("raid-path")) {
2990 setup_raid_path (Config->get_raid_path());
2992 } else if (PARAM_IS ("smpte-format")) {
2996 } else if (PARAM_IS ("video-pullup")) {
3000 } else if (PARAM_IS ("seamless-loop")) {
3002 if (play_loop && transport_rolling()) {
3003 // to reset diskstreams etc
3004 request_play_loop (true);
3007 } else if (PARAM_IS ("rf-speed")) {
3009 cumulative_rf_motion = 0;
3012 } else if (PARAM_IS ("click-sound")) {
3014 setup_click_sounds (1);
3016 } else if (PARAM_IS ("click-emphasis-sound")) {
3018 setup_click_sounds (-1);
3020 } else if (PARAM_IS ("clicking")) {
3022 if (Config->get_clicking()) {
3023 if (_click_io && click_data) { // don't require emphasis data
3030 } else if (PARAM_IS ("send-mtc")) {
3032 /* only set the internal flag if we have
3036 if (_mtc_port != 0) {
3037 session_send_mtc = Config->get_send_mtc();
3038 if (session_send_mtc) {
3039 /* mark us ready to send */
3040 next_quarter_frame_to_send = 0;
3043 session_send_mtc = false;
3046 } else if (PARAM_IS ("send-mmc")) {
3048 /* only set the internal flag if we have
3052 if (_mmc_port != 0) {
3053 session_send_mmc = Config->get_send_mmc();
3056 session_send_mmc = false;
3059 } else if (PARAM_IS ("midi-feedback")) {
3061 /* only set the internal flag if we have
3065 if (_mtc_port != 0) {
3066 session_midi_feedback = Config->get_midi_feedback();
3069 } else if (PARAM_IS ("jack-time-master")) {
3071 engine().reset_timebase ();
3073 } else if (PARAM_IS ("native-file-header-format")) {
3075 if (!first_file_header_format_reset) {
3076 reset_native_file_format ();
3079 first_file_header_format_reset = false;
3081 } else if (PARAM_IS ("native-file-data-format")) {
3083 if (!first_file_data_format_reset) {
3084 reset_native_file_format ();
3087 first_file_data_format_reset = false;
3089 } else if (PARAM_IS ("slave-source")) {
3090 set_slave_source (Config->get_slave_source());
3091 } else if (PARAM_IS ("remote-model")) {
3092 set_remote_control_ids ();
3093 } else if (PARAM_IS ("denormal-model")) {
3095 } else if (PARAM_IS ("history-depth")) {
3096 set_history_depth (Config->get_history_depth());
3097 } else if (PARAM_IS ("sync-all-route-ordering")) {
3108 Session::set_history_depth (uint32_t d)
3110 _history.set_depth (d);