2 Copyright (C) 1999-2013 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.
22 #include "libardour-config.h"
31 #include <cstdio> /* snprintf(3) ... grrr */
44 #include <sys/param.h>
45 #include <sys/mount.h>
48 #ifdef HAVE_SYS_STATVFS_H
49 #include <sys/statvfs.h>
53 #include <glib/gstdio.h>
56 #include <glibmm/threads.h>
57 #include <glibmm/fileutils.h>
59 #include <boost/algorithm/string.hpp>
61 #include "midi++/mmc.h"
62 #include "midi++/port.h"
64 #include "evoral/SMF.hpp"
66 #include "pbd/boost_debug.h"
67 #include "pbd/basename.h"
68 #include "pbd/controllable_descriptor.h"
69 #include "pbd/debug.h"
70 #include "pbd/enumwriter.h"
71 #include "pbd/error.h"
72 #include "pbd/file_utils.h"
73 #include "pbd/pathexpand.h"
74 #include "pbd/pthread_utils.h"
75 #include "pbd/stacktrace.h"
76 #include "pbd/convert.h"
77 #include "pbd/localtime_r.h"
79 #include "ardour/amp.h"
80 #include "ardour/async_midi_port.h"
81 #include "ardour/audio_diskstream.h"
82 #include "ardour/audio_track.h"
83 #include "ardour/audioengine.h"
84 #include "ardour/audiofilesource.h"
85 #include "ardour/audioregion.h"
86 #include "ardour/automation_control.h"
87 #include "ardour/butler.h"
88 #include "ardour/control_protocol_manager.h"
89 #include "ardour/directory_names.h"
90 #include "ardour/filename_extensions.h"
91 #include "ardour/graph.h"
92 #include "ardour/location.h"
93 #include "ardour/midi_model.h"
94 #include "ardour/midi_patch_manager.h"
95 #include "ardour/midi_region.h"
96 #include "ardour/midi_scene_changer.h"
97 #include "ardour/midi_source.h"
98 #include "ardour/midi_track.h"
99 #include "ardour/pannable.h"
100 #include "ardour/playlist_factory.h"
101 #include "ardour/playlist_source.h"
102 #include "ardour/port.h"
103 #include "ardour/processor.h"
104 #include "ardour/profile.h"
105 #include "ardour/proxy_controllable.h"
106 #include "ardour/recent_sessions.h"
107 #include "ardour/region_factory.h"
108 #include "ardour/route_group.h"
109 #include "ardour/send.h"
110 #include "ardour/session.h"
111 #include "ardour/session_directory.h"
112 #include "ardour/session_metadata.h"
113 #include "ardour/session_playlists.h"
114 #include "ardour/session_state_utils.h"
115 #include "ardour/silentfilesource.h"
116 #include "ardour/sndfilesource.h"
117 #include "ardour/source_factory.h"
118 #include "ardour/speakers.h"
119 #include "ardour/template_utils.h"
120 #include "ardour/tempo.h"
121 #include "ardour/ticker.h"
122 #include "ardour/user_bundle.h"
124 #include "control_protocol/control_protocol.h"
130 using namespace ARDOUR;
133 #define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg));
136 Session::pre_engine_init (string fullpath)
138 if (fullpath.empty()) {
140 throw failed_constructor();
143 /* discover canonical fullpath */
145 _path = canonical_path(fullpath);
148 if (Profile->get_trx() ) {
149 // Waves TracksLive has a usecase of session replacement with a new one.
150 // We should check session state file (<session_name>.ardour) existance
151 // to determine if the session is new or not
153 string full_session_name = Glib::build_filename( fullpath, _name );
154 full_session_name += statefile_suffix;
156 _is_new = !Glib::file_test (full_session_name, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
158 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
161 /* finish initialization that can't be done in a normal C++ constructor
165 timerclear (&last_mmc_step);
166 g_atomic_int_set (&processing_prohibited, 0);
167 g_atomic_int_set (&_record_status, Disabled);
168 g_atomic_int_set (&_playback_load, 100);
169 g_atomic_int_set (&_capture_load, 100);
171 _all_route_group->set_active (true, this);
172 interpolation.add_channel_to (0, 0);
174 if (config.get_use_video_sync()) {
175 waiting_for_sync_offset = true;
177 waiting_for_sync_offset = false;
180 last_rr_session_dir = session_dirs.begin();
182 set_history_depth (Config->get_history_depth());
184 /* default: assume simple stereo speaker configuration */
186 _speakers->setup_default_speakers (2);
188 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
189 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
190 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
191 add_controllable (_solo_cut_control);
193 /* These are all static "per-class" signals */
195 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
196 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
197 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
198 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
199 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
201 /* stop IO objects from doing stuff until we're ready for them */
203 Delivery::disable_panners ();
204 IO::disable_connecting ();
208 Session::post_engine_init ()
210 BootMessage (_("Set block size and sample rate"));
212 set_block_size (_engine.samples_per_cycle());
213 set_frame_rate (_engine.sample_rate());
215 BootMessage (_("Using configuration"));
217 _midi_ports = new MidiPortManager;
219 MIDISceneChanger* msc;
221 _scene_changer = msc = new MIDISceneChanger (*this);
222 msc->set_input_port (scene_input_port());
223 msc->set_output_port (scene_out());
225 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
226 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
228 setup_midi_machine_control ();
230 if (_butler->start_thread()) {
234 if (start_midi_thread ()) {
238 setup_click_sounds (0);
239 setup_midi_control ();
241 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
242 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
245 /* tempo map requires sample rate knowledge */
248 _tempo_map = new TempoMap (_current_frame_rate);
249 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
251 /* MidiClock requires a tempo map */
253 midi_clock = new MidiClockTicker ();
254 midi_clock->set_session (this);
256 /* crossfades require sample rate knowledge */
258 SndFileSource::setup_standard_crossfades (*this, frame_rate());
259 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
261 AudioDiskstream::allocate_working_buffers();
262 refresh_disk_space ();
264 /* we're finally ready to call set_state() ... all objects have
265 * been created, the engine is running.
269 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
273 // set_state() will call setup_raid_path(), but if it's a new session we need
274 // to call setup_raid_path() here.
275 setup_raid_path (_path);
280 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
281 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
283 Config->map_parameters (ff);
284 config.map_parameters (ft);
285 _butler->map_parameters ();
287 /* Reset all panners */
289 Delivery::reset_panners ();
291 /* this will cause the CPM to instantiate any protocols that are in use
292 * (or mandatory), which will pass it this Session, and then call
293 * set_state() on each instantiated protocol to match stored state.
296 ControlProtocolManager::instance().set_session (this);
298 /* This must be done after the ControlProtocolManager set_session above,
299 as it will set states for ports which the ControlProtocolManager creates.
302 // XXX set state of MIDI::Port's
303 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
305 /* And this must be done after the MIDI::Manager::set_port_states as
306 * it will try to make connections whose details are loaded by set_port_states.
311 /* Let control protocols know that we are now all connected, so they
312 * could start talking to surfaces if they want to.
315 ControlProtocolManager::instance().midi_connectivity_established ();
317 if (_is_new && !no_auto_connect()) {
318 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
319 auto_connect_master_bus ();
322 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
324 /* update latencies */
326 initialize_latencies ();
328 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
329 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
330 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
332 } catch (AudioEngine::PortRegistrationFailure& err) {
333 /* handle this one in a different way than all others, so that its clear what happened */
334 error << err.what() << endmsg;
340 BootMessage (_("Reset Remote Controls"));
342 // send_full_time_code (0);
343 _engine.transport_locate (0);
345 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
346 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
348 MIDI::Name::MidiPatchManager::instance().set_session (this);
351 /* initial program change will be delivered later; see ::config_changed() */
353 _state_of_the_state = Clean;
355 Port::set_connecting_blocked (false);
357 DirtyChanged (); /* EMIT SIGNAL */
361 } else if (state_was_pending) {
363 remove_pending_capture_state ();
364 state_was_pending = false;
367 /* Now, finally, we can fill the playback buffers */
369 BootMessage (_("Filling playback buffers"));
371 boost::shared_ptr<RouteList> rl = routes.reader();
372 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
373 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
374 if (trk && !trk->hidden()) {
375 trk->seek (_transport_frame, true);
383 Session::session_loaded ()
387 _state_of_the_state = Clean;
389 DirtyChanged (); /* EMIT SIGNAL */
393 } else if (state_was_pending) {
395 remove_pending_capture_state ();
396 state_was_pending = false;
399 /* Now, finally, we can fill the playback buffers */
401 BootMessage (_("Filling playback buffers"));
402 force_locate (_transport_frame, false);
406 Session::raid_path () const
408 Searchpath raid_search_path;
410 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
411 raid_search_path += (*i).path;
414 return raid_search_path.to_string ();
418 Session::setup_raid_path (string path)
427 session_dirs.clear ();
429 Searchpath search_path(path);
430 Searchpath sound_search_path;
431 Searchpath midi_search_path;
433 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
435 sp.blocks = 0; // not needed
436 session_dirs.push_back (sp);
438 SessionDirectory sdir(sp.path);
440 sound_search_path += sdir.sound_path ();
441 midi_search_path += sdir.midi_path ();
444 // reset the round-robin soundfile path thingie
445 last_rr_session_dir = session_dirs.begin();
449 Session::path_is_within_session (const std::string& path)
451 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
452 if (PBD::path_is_within (i->path, path)) {
460 Session::ensure_subdirs ()
464 dir = session_directory().peak_path();
466 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
467 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
471 dir = session_directory().sound_path();
473 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
474 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
478 dir = session_directory().midi_path();
480 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
481 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
485 dir = session_directory().dead_path();
487 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
488 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
492 dir = session_directory().export_path();
494 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
495 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
499 dir = analysis_dir ();
501 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
502 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
506 dir = plugins_dir ();
508 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
509 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
513 dir = externals_dir ();
515 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
516 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
523 /** @param session_template directory containing session template, or empty.
524 * Caller must not hold process lock.
527 Session::create (const string& session_template, BusProfile* bus_profile)
529 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
530 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
534 if (ensure_subdirs ()) {
538 _writable = exists_and_writable (_path);
540 if (!session_template.empty()) {
541 std::string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
543 ifstream in(in_path.c_str());
546 /* no need to call legalize_for_path() since the string
547 * in session_template is already a legal path name
549 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
551 ofstream out(out_path.c_str());
557 if (!ARDOUR::Profile->get_trx()) {
558 /* Copy plugin state files from template to new session */
559 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
560 copy_recurse (template_plugins, plugins_dir ());
566 error << string_compose (_("Could not open %1 for writing session template"), out_path)
572 error << string_compose (_("Could not open session template %1 for reading"), in_path)
579 if (Profile->get_trx()) {
581 /* set initial start + end point : ARDOUR::Session::session_end_shift long.
582 Remember that this is a brand new session. Sessions
583 loaded from saved state will get this range from the saved state.
586 set_session_range_location (0, 0);
588 /* Initial loop location, from absolute zero, length 10 seconds */
590 Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
591 _locations->add (loc, true);
592 set_auto_loop_location (loc);
595 _state_of_the_state = Clean;
597 /* set up Master Out and Control Out if necessary */
602 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
604 // Waves Tracks: always create master bus for Tracks
605 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
606 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
610 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
611 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
614 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
615 r->input()->ensure_io (count, false, this);
616 r->output()->ensure_io (count, false, this);
622 /* prohibit auto-connect to master, because there isn't one */
623 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
627 add_routes (rl, false, false, false);
630 // Waves Tracks: Skip this. Always use autoconnection for Tracks
631 if (!ARDOUR::Profile->get_trx()) {
633 /* this allows the user to override settings with an environment variable.
636 if (no_auto_connect()) {
637 bus_profile->input_ac = AutoConnectOption (0);
638 bus_profile->output_ac = AutoConnectOption (0);
641 Config->set_input_auto_connect (bus_profile->input_ac);
642 Config->set_output_auto_connect (bus_profile->output_ac);
646 if (Config->get_use_monitor_bus() && bus_profile) {
647 add_monitor_section ();
654 Session::maybe_write_autosave()
656 if (dirty() && record_status() != Recording) {
657 save_state("", true);
662 Session::remove_pending_capture_state ()
664 std::string pending_state_file_path(_session_dir->root_path());
666 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
668 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
670 if (g_remove (pending_state_file_path.c_str()) != 0) {
671 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
672 pending_state_file_path, g_strerror (errno)) << endmsg;
676 /** Rename a state file.
677 * @param old_name Old snapshot name.
678 * @param new_name New snapshot name.
681 Session::rename_state (string old_name, string new_name)
683 if (old_name == _current_snapshot_name || old_name == _name) {
684 /* refuse to rename the current snapshot or the "main" one */
688 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
689 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
691 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
692 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
694 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
695 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
696 old_name, new_name, g_strerror(errno)) << endmsg;
700 /** Remove a state file.
701 * @param snapshot_name Snapshot name.
704 Session::remove_state (string snapshot_name)
706 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
707 // refuse to remove the current snapshot or the "main" one
711 std::string xml_path(_session_dir->root_path());
713 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
715 if (!create_backup_file (xml_path)) {
716 // don't remove it if a backup can't be made
717 // create_backup_file will log the error.
722 if (g_remove (xml_path.c_str()) != 0) {
723 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
724 xml_path, g_strerror (errno)) << endmsg;
728 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
730 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
733 std::string xml_path(_session_dir->root_path());
735 /* prevent concurrent saves from different threads */
737 Glib::Threads::Mutex::Lock lm (save_state_lock);
739 if (!_writable || (_state_of_the_state & CannotSave)) {
743 if (g_atomic_int_get(&_suspend_save)) {
747 _save_queued = false;
749 if (!_engine.connected ()) {
750 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
756 /* tell sources we're saving first, in case they write out to a new file
757 * which should be saved with the state rather than the old one */
758 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
760 i->second->session_saved();
761 } catch (Evoral::SMF::FileError& e) {
762 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
766 SessionSaveUnderway (); /* EMIT SIGNAL */
769 tree.set_root (&get_template());
771 tree.set_root (&get_state());
774 if (snapshot_name.empty()) {
775 snapshot_name = _current_snapshot_name;
776 } else if (switch_to_snapshot) {
777 _current_snapshot_name = snapshot_name;
782 /* proper save: use statefile_suffix (.ardour in English) */
784 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
786 /* make a backup copy of the old file */
788 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
789 // create_backup_file will log the error
795 /* pending save: use pending_suffix (.pending in English) */
796 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
799 std::string tmp_path(_session_dir->root_path());
800 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
802 cerr << "actually writing state to " << tmp_path << endl;
804 if (!tree.write (tmp_path)) {
805 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
806 if (g_remove (tmp_path.c_str()) != 0) {
807 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
808 tmp_path, g_strerror (errno)) << endmsg;
814 cerr << "renaming state to " << xml_path << endl;
816 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
817 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
818 tmp_path, xml_path, g_strerror(errno)) << endmsg;
819 if (g_remove (tmp_path.c_str()) != 0) {
820 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
821 tmp_path, g_strerror (errno)) << endmsg;
829 save_history (snapshot_name);
831 bool was_dirty = dirty();
833 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
836 DirtyChanged (); /* EMIT SIGNAL */
839 StateSaved (snapshot_name); /* EMIT SIGNAL */
846 Session::restore_state (string snapshot_name)
848 if (load_state (snapshot_name) == 0) {
849 set_state (*state_tree->root(), Stateful::loading_state_version);
856 Session::load_state (string snapshot_name)
861 state_was_pending = false;
863 /* check for leftover pending state from a crashed capture attempt */
865 std::string xmlpath(_session_dir->root_path());
866 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
868 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
870 /* there is pending state from a crashed capture attempt */
872 boost::optional<int> r = AskAboutPendingState();
873 if (r.get_value_or (1)) {
874 state_was_pending = true;
878 if (!state_was_pending) {
879 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
882 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
883 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
884 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
885 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
890 state_tree = new XMLTree;
894 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
896 if (!state_tree->read (xmlpath)) {
897 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
903 XMLNode& root (*state_tree->root());
905 if (root.name() != X_("Session")) {
906 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
912 const XMLProperty* prop;
914 if ((prop = root.property ("version")) == 0) {
915 /* no version implies very old version of Ardour */
916 Stateful::loading_state_version = 1000;
918 if (prop->value().find ('.') != string::npos) {
919 /* old school version format */
920 if (prop->value()[0] == '2') {
921 Stateful::loading_state_version = 2000;
923 Stateful::loading_state_version = 3000;
926 Stateful::loading_state_version = atoi (prop->value());
930 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
932 std::string backup_path(_session_dir->root_path());
933 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
934 backup_path = Glib::build_filename (backup_path, backup_filename);
936 // only create a backup for a given statefile version once
938 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
940 VersionMismatch (xmlpath, backup_path);
942 if (!copy_file (xmlpath, backup_path)) {;
952 Session::load_options (const XMLNode& node)
954 LocaleGuard lg (X_("C"));
955 config.set_variables (node);
960 Session::save_default_options ()
962 return config.save_state();
972 Session::get_template()
974 /* if we don't disable rec-enable, diskstreams
975 will believe they need to store their capture
976 sources in their state node.
979 disable_record (false);
985 Session::state (bool full_state)
987 XMLNode* node = new XMLNode("Session");
991 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
992 node->add_property("version", buf);
994 /* store configuration settings */
998 node->add_property ("name", _name);
999 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
1000 node->add_property ("sample-rate", buf);
1002 if (session_dirs.size() > 1) {
1006 vector<space_and_path>::iterator i = session_dirs.begin();
1007 vector<space_and_path>::iterator next;
1009 ++i; /* skip the first one */
1013 while (i != session_dirs.end()) {
1017 if (next != session_dirs.end()) {
1018 p += G_SEARCHPATH_SEPARATOR;
1027 child = node->add_child ("Path");
1028 child->add_content (p);
1032 /* save the ID counter */
1034 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1035 node->add_property ("id-counter", buf);
1037 /* save the event ID counter */
1039 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1040 node->add_property ("event-counter", buf);
1042 /* various options */
1044 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1045 if (!midi_port_nodes.empty()) {
1046 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1047 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1048 midi_port_stuff->add_child_nocopy (**n);
1050 node->add_child_nocopy (*midi_port_stuff);
1053 node->add_child_nocopy (config.get_variables ());
1055 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1057 child = node->add_child ("Sources");
1060 Glib::Threads::Mutex::Lock sl (source_lock);
1062 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1064 /* Don't save information about non-file Sources, or
1065 * about non-destructive file sources that are empty
1066 * and unused by any regions.
1069 boost::shared_ptr<FileSource> fs;
1071 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1073 if (!fs->destructive()) {
1074 if (fs->empty() && !fs->used()) {
1079 child->add_child_nocopy (siter->second->get_state());
1084 child = node->add_child ("Regions");
1087 Glib::Threads::Mutex::Lock rl (region_lock);
1088 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1089 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1090 boost::shared_ptr<Region> r = i->second;
1091 /* only store regions not attached to playlists */
1092 if (r->playlist() == 0) {
1093 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1094 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1096 child->add_child_nocopy (r->get_state ());
1101 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1103 if (!cassocs.empty()) {
1104 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1106 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1108 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1109 i->first->id().print (buf, sizeof (buf));
1110 can->add_property (X_("copy"), buf);
1111 i->second->id().print (buf, sizeof (buf));
1112 can->add_property (X_("original"), buf);
1113 ca->add_child_nocopy (*can);
1123 node->add_child_nocopy (_locations->get_state());
1126 Locations loc (*this);
1127 // for a template, just create a new Locations, populate it
1128 // with the default start and end, and get the state for that.
1129 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1130 range->set (max_framepos, 0);
1132 XMLNode& locations_state = loc.get_state();
1134 if (ARDOUR::Profile->get_trx() && _locations) {
1135 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1136 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1137 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1138 locations_state.add_child_nocopy ((*i)->get_state ());
1142 node->add_child_nocopy (locations_state);
1145 child = node->add_child ("Bundles");
1147 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1148 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1149 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1151 child->add_child_nocopy (b->get_state());
1156 child = node->add_child ("Routes");
1158 boost::shared_ptr<RouteList> r = routes.reader ();
1160 RoutePublicOrderSorter cmp;
1161 RouteList public_order (*r);
1162 public_order.sort (cmp);
1164 /* the sort should have put control outs first */
1167 assert (_monitor_out == public_order.front());
1170 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1171 if (!(*i)->is_auditioner()) {
1173 child->add_child_nocopy ((*i)->get_state());
1175 child->add_child_nocopy ((*i)->get_template());
1181 playlists->add_state (node, full_state);
1183 child = node->add_child ("RouteGroups");
1184 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1185 child->add_child_nocopy ((*i)->get_state());
1189 XMLNode* gain_child = node->add_child ("Click");
1190 gain_child->add_child_nocopy (_click_io->state (full_state));
1191 gain_child->add_child_nocopy (_click_gain->state (full_state));
1195 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1196 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1200 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1201 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1204 node->add_child_nocopy (_speakers->get_state());
1205 node->add_child_nocopy (_tempo_map->get_state());
1206 node->add_child_nocopy (get_control_protocol_state());
1209 node->add_child_copy (*_extra_xml);
1216 Session::get_control_protocol_state ()
1218 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1219 return cpm.get_state();
1223 Session::set_state (const XMLNode& node, int version)
1227 const XMLProperty* prop;
1230 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1232 if (node.name() != X_("Session")) {
1233 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1237 if ((prop = node.property ("name")) != 0) {
1238 _name = prop->value ();
1241 if ((prop = node.property (X_("sample-rate"))) != 0) {
1243 _nominal_frame_rate = atoi (prop->value());
1245 if (_nominal_frame_rate != _current_frame_rate) {
1246 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1247 if (r.get_value_or (0)) {
1253 setup_raid_path(_session_dir->root_path());
1255 if ((prop = node.property (X_("id-counter"))) != 0) {
1257 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1258 ID::init_counter (x);
1260 /* old sessions used a timebased counter, so fake
1261 the startup ID counter based on a standard
1266 ID::init_counter (now);
1269 if ((prop = node.property (X_("event-counter"))) != 0) {
1270 Evoral::init_event_id_counter (atoi (prop->value()));
1274 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1275 _midi_ports->set_midi_port_states (child->children());
1278 IO::disable_connecting ();
1280 Stateful::save_extra_xml (node);
1282 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1283 load_options (*child);
1284 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1285 load_options (*child);
1287 error << _("Session: XML state has no options section") << endmsg;
1290 if (version >= 3000) {
1291 if ((child = find_named_node (node, "Metadata")) == 0) {
1292 warning << _("Session: XML state has no metadata section") << endmsg;
1293 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1298 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1299 _speakers->set_state (*child, version);
1302 if ((child = find_named_node (node, "Sources")) == 0) {
1303 error << _("Session: XML state has no sources section") << endmsg;
1305 } else if (load_sources (*child)) {
1309 if ((child = find_named_node (node, "TempoMap")) == 0) {
1310 error << _("Session: XML state has no Tempo Map section") << endmsg;
1312 } else if (_tempo_map->set_state (*child, version)) {
1316 if ((child = find_named_node (node, "Locations")) == 0) {
1317 error << _("Session: XML state has no locations section") << endmsg;
1319 } else if (_locations->set_state (*child, version)) {
1323 locations_changed ();
1325 if (_session_range_location) {
1326 AudioFileSource::set_header_position_offset (_session_range_location->start());
1329 if ((child = find_named_node (node, "Regions")) == 0) {
1330 error << _("Session: XML state has no Regions section") << endmsg;
1332 } else if (load_regions (*child)) {
1336 if ((child = find_named_node (node, "Playlists")) == 0) {
1337 error << _("Session: XML state has no playlists section") << endmsg;
1339 } else if (playlists->load (*this, *child)) {
1343 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1345 } else if (playlists->load_unused (*this, *child)) {
1349 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1350 if (load_compounds (*child)) {
1355 if (version >= 3000) {
1356 if ((child = find_named_node (node, "Bundles")) == 0) {
1357 warning << _("Session: XML state has no bundles section") << endmsg;
1360 /* We can't load Bundles yet as they need to be able
1361 to convert from port names to Port objects, which can't happen until
1363 _bundle_xml_node = new XMLNode (*child);
1367 if (version < 3000) {
1368 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1369 error << _("Session: XML state has no diskstreams section") << endmsg;
1371 } else if (load_diskstreams_2X (*child, version)) {
1376 if ((child = find_named_node (node, "Routes")) == 0) {
1377 error << _("Session: XML state has no routes section") << endmsg;
1379 } else if (load_routes (*child, version)) {
1383 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1384 _diskstreams_2X.clear ();
1386 if (version >= 3000) {
1388 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1389 error << _("Session: XML state has no route groups section") << endmsg;
1391 } else if (load_route_groups (*child, version)) {
1395 } else if (version < 3000) {
1397 if ((child = find_named_node (node, "EditGroups")) == 0) {
1398 error << _("Session: XML state has no edit groups section") << endmsg;
1400 } else if (load_route_groups (*child, version)) {
1404 if ((child = find_named_node (node, "MixGroups")) == 0) {
1405 error << _("Session: XML state has no mix groups section") << endmsg;
1407 } else if (load_route_groups (*child, version)) {
1412 if ((child = find_named_node (node, "Click")) == 0) {
1413 warning << _("Session: XML state has no click section") << endmsg;
1414 } else if (_click_io) {
1415 setup_click_state (&node);
1418 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1419 ControlProtocolManager::instance().set_state (*child, version);
1422 update_route_record_state ();
1424 /* here beginneth the second phase ... */
1426 StateReady (); /* EMIT SIGNAL */
1439 Session::load_routes (const XMLNode& node, int version)
1442 XMLNodeConstIterator niter;
1443 RouteList new_routes;
1445 nlist = node.children();
1449 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1451 boost::shared_ptr<Route> route;
1452 if (version < 3000) {
1453 route = XMLRouteFactory_2X (**niter, version);
1455 route = XMLRouteFactory (**niter, version);
1459 error << _("Session: cannot create Route from XML description.") << endmsg;
1463 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1465 new_routes.push_back (route);
1468 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1470 add_routes (new_routes, false, false, false);
1472 BootMessage (_("Finished adding tracks/busses"));
1477 boost::shared_ptr<Route>
1478 Session::XMLRouteFactory (const XMLNode& node, int version)
1480 boost::shared_ptr<Route> ret;
1482 if (node.name() != "Route") {
1486 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1488 DataType type = DataType::AUDIO;
1489 const XMLProperty* prop = node.property("default-type");
1492 type = DataType (prop->value());
1495 assert (type != DataType::NIL);
1499 boost::shared_ptr<Track> track;
1501 if (type == DataType::AUDIO) {
1502 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1504 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1507 if (track->init()) {
1511 if (track->set_state (node, version)) {
1515 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1516 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1521 enum Route::Flag flags = Route::Flag(0);
1522 const XMLProperty* prop = node.property("flags");
1524 flags = Route::Flag (string_2_enum (prop->value(), flags));
1527 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1529 if (r->init () == 0 && r->set_state (node, version) == 0) {
1530 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1531 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1540 boost::shared_ptr<Route>
1541 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1543 boost::shared_ptr<Route> ret;
1545 if (node.name() != "Route") {
1549 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1551 ds_prop = node.property (X_("diskstream"));
1554 DataType type = DataType::AUDIO;
1555 const XMLProperty* prop = node.property("default-type");
1558 type = DataType (prop->value());
1561 assert (type != DataType::NIL);
1565 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1566 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1570 if (i == _diskstreams_2X.end()) {
1571 error << _("Could not find diskstream for route") << endmsg;
1572 return boost::shared_ptr<Route> ();
1575 boost::shared_ptr<Track> track;
1577 if (type == DataType::AUDIO) {
1578 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1580 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1583 if (track->init()) {
1587 if (track->set_state (node, version)) {
1591 track->set_diskstream (*i);
1593 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1594 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1599 enum Route::Flag flags = Route::Flag(0);
1600 const XMLProperty* prop = node.property("flags");
1602 flags = Route::Flag (string_2_enum (prop->value(), flags));
1605 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1607 if (r->init () == 0 && r->set_state (node, version) == 0) {
1608 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1609 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1619 Session::load_regions (const XMLNode& node)
1622 XMLNodeConstIterator niter;
1623 boost::shared_ptr<Region> region;
1625 nlist = node.children();
1629 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1630 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1631 error << _("Session: cannot create Region from XML description.");
1632 const XMLProperty *name = (**niter).property("name");
1635 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1646 Session::load_compounds (const XMLNode& node)
1648 XMLNodeList calist = node.children();
1649 XMLNodeConstIterator caiter;
1650 XMLProperty *caprop;
1652 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1653 XMLNode* ca = *caiter;
1657 if ((caprop = ca->property (X_("original"))) == 0) {
1660 orig_id = caprop->value();
1662 if ((caprop = ca->property (X_("copy"))) == 0) {
1665 copy_id = caprop->value();
1667 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1668 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1670 if (!orig || !copy) {
1671 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1677 RegionFactory::add_compound_association (orig, copy);
1684 Session::load_nested_sources (const XMLNode& node)
1687 XMLNodeConstIterator niter;
1689 nlist = node.children();
1691 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1692 if ((*niter)->name() == "Source") {
1694 /* it may already exist, so don't recreate it unnecessarily
1697 XMLProperty* prop = (*niter)->property (X_("id"));
1699 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1703 ID source_id (prop->value());
1705 if (!source_by_id (source_id)) {
1708 SourceFactory::create (*this, **niter, true);
1710 catch (failed_constructor& err) {
1711 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1718 boost::shared_ptr<Region>
1719 Session::XMLRegionFactory (const XMLNode& node, bool full)
1721 const XMLProperty* type = node.property("type");
1725 const XMLNodeList& nlist = node.children();
1727 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1728 XMLNode *child = (*niter);
1729 if (child->name() == "NestedSource") {
1730 load_nested_sources (*child);
1734 if (!type || type->value() == "audio") {
1735 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1736 } else if (type->value() == "midi") {
1737 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1740 } catch (failed_constructor& err) {
1741 return boost::shared_ptr<Region> ();
1744 return boost::shared_ptr<Region> ();
1747 boost::shared_ptr<AudioRegion>
1748 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1750 const XMLProperty* prop;
1751 boost::shared_ptr<Source> source;
1752 boost::shared_ptr<AudioSource> as;
1754 SourceList master_sources;
1755 uint32_t nchans = 1;
1758 if (node.name() != X_("Region")) {
1759 return boost::shared_ptr<AudioRegion>();
1762 if ((prop = node.property (X_("channels"))) != 0) {
1763 nchans = atoi (prop->value().c_str());
1766 if ((prop = node.property ("name")) == 0) {
1767 cerr << "no name for this region\n";
1771 if ((prop = node.property (X_("source-0"))) == 0) {
1772 if ((prop = node.property ("source")) == 0) {
1773 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1774 return boost::shared_ptr<AudioRegion>();
1778 PBD::ID s_id (prop->value());
1780 if ((source = source_by_id (s_id)) == 0) {
1781 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1782 return boost::shared_ptr<AudioRegion>();
1785 as = boost::dynamic_pointer_cast<AudioSource>(source);
1787 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1788 return boost::shared_ptr<AudioRegion>();
1791 sources.push_back (as);
1793 /* pickup other channels */
1795 for (uint32_t n=1; n < nchans; ++n) {
1796 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1797 if ((prop = node.property (buf)) != 0) {
1799 PBD::ID id2 (prop->value());
1801 if ((source = source_by_id (id2)) == 0) {
1802 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1803 return boost::shared_ptr<AudioRegion>();
1806 as = boost::dynamic_pointer_cast<AudioSource>(source);
1808 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1809 return boost::shared_ptr<AudioRegion>();
1811 sources.push_back (as);
1815 for (uint32_t n = 0; n < nchans; ++n) {
1816 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1817 if ((prop = node.property (buf)) != 0) {
1819 PBD::ID id2 (prop->value());
1821 if ((source = source_by_id (id2)) == 0) {
1822 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1823 return boost::shared_ptr<AudioRegion>();
1826 as = boost::dynamic_pointer_cast<AudioSource>(source);
1828 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1829 return boost::shared_ptr<AudioRegion>();
1831 master_sources.push_back (as);
1836 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1838 /* a final detail: this is the one and only place that we know how long missing files are */
1840 if (region->whole_file()) {
1841 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1842 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1844 sfp->set_length (region->length());
1849 if (!master_sources.empty()) {
1850 if (master_sources.size() != nchans) {
1851 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1853 region->set_master_sources (master_sources);
1861 catch (failed_constructor& err) {
1862 return boost::shared_ptr<AudioRegion>();
1866 boost::shared_ptr<MidiRegion>
1867 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1869 const XMLProperty* prop;
1870 boost::shared_ptr<Source> source;
1871 boost::shared_ptr<MidiSource> ms;
1874 if (node.name() != X_("Region")) {
1875 return boost::shared_ptr<MidiRegion>();
1878 if ((prop = node.property ("name")) == 0) {
1879 cerr << "no name for this region\n";
1883 if ((prop = node.property (X_("source-0"))) == 0) {
1884 if ((prop = node.property ("source")) == 0) {
1885 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1886 return boost::shared_ptr<MidiRegion>();
1890 PBD::ID s_id (prop->value());
1892 if ((source = source_by_id (s_id)) == 0) {
1893 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1894 return boost::shared_ptr<MidiRegion>();
1897 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1899 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1900 return boost::shared_ptr<MidiRegion>();
1903 sources.push_back (ms);
1906 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1907 /* a final detail: this is the one and only place that we know how long missing files are */
1909 if (region->whole_file()) {
1910 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1911 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1913 sfp->set_length (region->length());
1921 catch (failed_constructor& err) {
1922 return boost::shared_ptr<MidiRegion>();
1927 Session::get_sources_as_xml ()
1930 XMLNode* node = new XMLNode (X_("Sources"));
1931 Glib::Threads::Mutex::Lock lm (source_lock);
1933 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1934 node->add_child_nocopy (i->second->get_state());
1941 Session::reset_write_sources (bool mark_write_complete, bool force)
1943 boost::shared_ptr<RouteList> rl = routes.reader();
1944 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1945 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1947 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
1948 tr->reset_write_sources(mark_write_complete, force);
1949 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1955 Session::load_sources (const XMLNode& node)
1958 XMLNodeConstIterator niter;
1959 boost::shared_ptr<Source> source; /* don't need this but it stops some
1960 * versions of gcc complaining about
1961 * discarded return values.
1964 nlist = node.children();
1968 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1971 if ((source = XMLSourceFactory (**niter)) == 0) {
1972 error << _("Session: cannot create Source from XML description.") << endmsg;
1975 } catch (MissingSource& err) {
1979 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
1980 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
1981 PROGRAM_NAME) << endmsg;
1985 if (!no_questions_about_missing_files) {
1986 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1991 switch (user_choice) {
1993 /* user added a new search location, so try again */
1998 /* user asked to quit the entire session load
2003 no_questions_about_missing_files = true;
2007 no_questions_about_missing_files = true;
2014 case DataType::AUDIO:
2015 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2018 case DataType::MIDI:
2019 /* The MIDI file is actually missing so
2020 * just create a new one in the same
2021 * location. Do not announce its
2025 if (!Glib::path_is_absolute (err.path)) {
2026 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2028 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2033 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2034 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2035 /* reset ID to match the missing one */
2036 source->set_id (**niter);
2037 /* Now we can announce it */
2038 SourceFactory::SourceCreated (source);
2049 boost::shared_ptr<Source>
2050 Session::XMLSourceFactory (const XMLNode& node)
2052 if (node.name() != "Source") {
2053 return boost::shared_ptr<Source>();
2057 /* note: do peak building in another thread when loading session state */
2058 return SourceFactory::create (*this, node, true);
2061 catch (failed_constructor& err) {
2062 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2063 return boost::shared_ptr<Source>();
2068 Session::save_template (string template_name)
2070 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2074 bool absolute_path = Glib::path_is_absolute (template_name);
2076 /* directory to put the template in */
2077 std::string template_dir_path;
2079 if (!absolute_path) {
2080 std::string user_template_dir(user_template_directory());
2082 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2083 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2084 user_template_dir, g_strerror (errno)) << endmsg;
2088 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2090 template_dir_path = template_name;
2093 if (!ARDOUR::Profile->get_trx()) {
2094 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2095 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2096 template_dir_path) << endmsg;
2100 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2101 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2102 template_dir_path, g_strerror (errno)) << endmsg;
2108 std::string template_file_path;
2110 if (ARDOUR::Profile->get_trx()) {
2111 template_file_path = template_name;
2113 if (absolute_path) {
2114 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2116 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2120 SessionSaveUnderway (); /* EMIT SIGNAL */
2124 tree.set_root (&get_template());
2125 if (!tree.write (template_file_path)) {
2126 error << _("template not saved") << endmsg;
2130 if (!ARDOUR::Profile->get_trx()) {
2131 /* copy plugin state directory */
2133 std::string template_plugin_state_path (Glib::build_filename (template_dir_path, X_("plugins")));
2135 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2136 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2137 template_plugin_state_path, g_strerror (errno)) << endmsg;
2140 copy_files (plugins_dir(), template_plugin_state_path);
2143 store_recent_templates (template_file_path);
2149 Session::refresh_disk_space ()
2151 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2153 Glib::Threads::Mutex::Lock lm (space_lock);
2155 /* get freespace on every FS that is part of the session path */
2157 _total_free_4k_blocks = 0;
2158 _total_free_4k_blocks_uncertain = false;
2160 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2162 struct statfs statfsbuf;
2163 statfs (i->path.c_str(), &statfsbuf);
2165 double const scale = statfsbuf.f_bsize / 4096.0;
2167 /* See if this filesystem is read-only */
2168 struct statvfs statvfsbuf;
2169 statvfs (i->path.c_str(), &statvfsbuf);
2171 /* f_bavail can be 0 if it is undefined for whatever
2172 filesystem we are looking at; Samba shares mounted
2173 via GVFS are an example of this.
2175 if (statfsbuf.f_bavail == 0) {
2176 /* block count unknown */
2178 i->blocks_unknown = true;
2179 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2180 /* read-only filesystem */
2182 i->blocks_unknown = false;
2184 /* read/write filesystem with known space */
2185 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2186 i->blocks_unknown = false;
2189 _total_free_4k_blocks += i->blocks;
2190 if (i->blocks_unknown) {
2191 _total_free_4k_blocks_uncertain = true;
2194 #elif defined PLATFORM_WINDOWS
2195 vector<string> scanned_volumes;
2196 vector<string>::iterator j;
2197 vector<space_and_path>::iterator i;
2198 DWORD nSectorsPerCluster, nBytesPerSector,
2199 nFreeClusters, nTotalClusters;
2203 _total_free_4k_blocks = 0;
2205 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2206 strncpy (disk_drive, (*i).path.c_str(), 3);
2210 volume_found = false;
2211 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2213 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2214 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2215 i->blocks = (uint32_t)(nFreeBytes / 4096);
2217 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2218 if (0 == j->compare(disk_drive)) {
2219 volume_found = true;
2224 if (!volume_found) {
2225 scanned_volumes.push_back(disk_drive);
2226 _total_free_4k_blocks += i->blocks;
2231 if (0 == _total_free_4k_blocks) {
2232 strncpy (disk_drive, path().c_str(), 3);
2235 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2237 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2238 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2239 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2246 Session::get_best_session_directory_for_new_audio ()
2248 vector<space_and_path>::iterator i;
2249 string result = _session_dir->root_path();
2251 /* handle common case without system calls */
2253 if (session_dirs.size() == 1) {
2257 /* OK, here's the algorithm we're following here:
2259 We want to select which directory to use for
2260 the next file source to be created. Ideally,
2261 we'd like to use a round-robin process so as to
2262 get maximum performance benefits from splitting
2263 the files across multiple disks.
2265 However, in situations without much diskspace, an
2266 RR approach may end up filling up a filesystem
2267 with new files while others still have space.
2268 Its therefore important to pay some attention to
2269 the freespace in the filesystem holding each
2270 directory as well. However, if we did that by
2271 itself, we'd keep creating new files in the file
2272 system with the most space until it was as full
2273 as all others, thus negating any performance
2274 benefits of this RAID-1 like approach.
2276 So, we use a user-configurable space threshold. If
2277 there are at least 2 filesystems with more than this
2278 much space available, we use RR selection between them.
2279 If not, then we pick the filesystem with the most space.
2281 This gets a good balance between the two
2285 refresh_disk_space ();
2287 int free_enough = 0;
2289 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2290 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2295 if (free_enough >= 2) {
2296 /* use RR selection process, ensuring that the one
2300 i = last_rr_session_dir;
2303 if (++i == session_dirs.end()) {
2304 i = session_dirs.begin();
2307 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2308 SessionDirectory sdir(i->path);
2309 if (sdir.create ()) {
2311 last_rr_session_dir = i;
2316 } while (i != last_rr_session_dir);
2320 /* pick FS with the most freespace (and that
2321 seems to actually work ...)
2324 vector<space_and_path> sorted;
2325 space_and_path_ascending_cmp cmp;
2327 sorted = session_dirs;
2328 sort (sorted.begin(), sorted.end(), cmp);
2330 for (i = sorted.begin(); i != sorted.end(); ++i) {
2331 SessionDirectory sdir(i->path);
2332 if (sdir.create ()) {
2334 last_rr_session_dir = i;
2344 Session::automation_dir () const
2346 return Glib::build_filename (_path, automation_dir_name);
2350 Session::analysis_dir () const
2352 return Glib::build_filename (_path, analysis_dir_name);
2356 Session::plugins_dir () const
2358 return Glib::build_filename (_path, plugins_dir_name);
2362 Session::externals_dir () const
2364 return Glib::build_filename (_path, externals_dir_name);
2368 Session::load_bundles (XMLNode const & node)
2370 XMLNodeList nlist = node.children();
2371 XMLNodeConstIterator niter;
2375 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2376 if ((*niter)->name() == "InputBundle") {
2377 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2378 } else if ((*niter)->name() == "OutputBundle") {
2379 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2381 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2390 Session::load_route_groups (const XMLNode& node, int version)
2392 XMLNodeList nlist = node.children();
2393 XMLNodeConstIterator niter;
2397 if (version >= 3000) {
2399 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2400 if ((*niter)->name() == "RouteGroup") {
2401 RouteGroup* rg = new RouteGroup (*this, "");
2402 add_route_group (rg);
2403 rg->set_state (**niter, version);
2407 } else if (version < 3000) {
2409 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2410 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2411 RouteGroup* rg = new RouteGroup (*this, "");
2412 add_route_group (rg);
2413 rg->set_state (**niter, version);
2422 state_file_filter (const string &str, void* /*arg*/)
2424 return (str.length() > strlen(statefile_suffix) &&
2425 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2429 remove_end(string state)
2431 string statename(state);
2433 string::size_type start,end;
2434 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2435 statename = statename.substr (start+1);
2438 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2439 end = statename.length();
2442 return string(statename.substr (0, end));
2446 Session::possible_states (string path)
2448 vector<string> states;
2449 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2451 transform(states.begin(), states.end(), states.begin(), remove_end);
2453 sort (states.begin(), states.end());
2459 Session::possible_states () const
2461 return possible_states(_path);
2465 Session::add_route_group (RouteGroup* g)
2467 _route_groups.push_back (g);
2468 route_group_added (g); /* EMIT SIGNAL */
2470 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2471 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2472 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2478 Session::remove_route_group (RouteGroup& rg)
2480 list<RouteGroup*>::iterator i;
2482 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2483 _route_groups.erase (i);
2486 route_group_removed (); /* EMIT SIGNAL */
2490 /** Set a new order for our route groups, without adding or removing any.
2491 * @param groups Route group list in the new order.
2494 Session::reorder_route_groups (list<RouteGroup*> groups)
2496 _route_groups = groups;
2498 route_groups_reordered (); /* EMIT SIGNAL */
2504 Session::route_group_by_name (string name)
2506 list<RouteGroup *>::iterator i;
2508 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2509 if ((*i)->name() == name) {
2517 Session::all_route_group() const
2519 return *_all_route_group;
2523 Session::add_commands (vector<Command*> const & cmds)
2525 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2531 Session::add_command (Command* const cmd)
2533 assert (_current_trans);
2534 DEBUG_UNDO_HISTORY (
2535 string_compose ("Current Undo Transaction %1, adding command: %2",
2536 _current_trans->name (),
2538 _current_trans->add_command (cmd);
2541 Session::begin_reversible_command (const string& name)
2543 begin_reversible_command (g_quark_from_string (name.c_str ()));
2546 /** Begin a reversible command using a GQuark to identify it.
2547 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2548 * but there must be as many begin...()s as there are commit...()s.
2551 Session::begin_reversible_command (GQuark q)
2553 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2554 to hold all the commands that are committed. This keeps the order of
2555 commands correct in the history.
2558 if (_current_trans == 0) {
2559 DEBUG_UNDO_HISTORY (string_compose (
2560 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2562 /* start a new transaction */
2563 assert (_current_trans_quarks.empty ());
2564 _current_trans = new UndoTransaction();
2565 _current_trans->set_name (g_quark_to_string (q));
2567 DEBUG_UNDO_HISTORY (
2568 string_compose ("Begin Reversible Command, current transaction: %1",
2569 _current_trans->name ()));
2572 _current_trans_quarks.push_front (q);
2576 Session::abort_reversible_command ()
2578 if (_current_trans != 0) {
2579 DEBUG_UNDO_HISTORY (
2580 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2581 _current_trans->clear();
2582 delete _current_trans;
2584 _current_trans_quarks.clear();
2589 Session::commit_reversible_command (Command *cmd)
2591 assert (_current_trans);
2592 assert (!_current_trans_quarks.empty ());
2597 DEBUG_UNDO_HISTORY (
2598 string_compose ("Current Undo Transaction %1, adding command: %2",
2599 _current_trans->name (),
2601 _current_trans->add_command (cmd);
2604 DEBUG_UNDO_HISTORY (
2605 string_compose ("Commit Reversible Command, current transaction: %1",
2606 _current_trans->name ()));
2608 _current_trans_quarks.pop_front ();
2610 if (!_current_trans_quarks.empty ()) {
2611 DEBUG_UNDO_HISTORY (
2612 string_compose ("Commit Reversible Command, transaction is not "
2613 "top-level, current transaction: %1",
2614 _current_trans->name ()));
2615 /* the transaction we're committing is not the top-level one */
2619 if (_current_trans->empty()) {
2620 /* no commands were added to the transaction, so just get rid of it */
2621 DEBUG_UNDO_HISTORY (
2622 string_compose ("Commit Reversible Command, No commands were "
2623 "added to current transaction: %1",
2624 _current_trans->name ()));
2625 delete _current_trans;
2630 gettimeofday (&now, 0);
2631 _current_trans->set_timestamp (now);
2633 _history.add (_current_trans);
2638 accept_all_audio_files (const string& path, void* /*arg*/)
2640 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2644 if (!AudioFileSource::safe_audio_file_extension (path)) {
2652 accept_all_midi_files (const string& path, void* /*arg*/)
2654 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2658 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2659 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2660 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2664 accept_all_state_files (const string& path, void* /*arg*/)
2666 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2670 std::string const statefile_ext (statefile_suffix);
2671 if (path.length() >= statefile_ext.length()) {
2672 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2679 Session::find_all_sources (string path, set<string>& result)
2684 if (!tree.read (path)) {
2688 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2693 XMLNodeConstIterator niter;
2695 nlist = node->children();
2699 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2703 if ((prop = (*niter)->property (X_("type"))) == 0) {
2707 DataType type (prop->value());
2709 if ((prop = (*niter)->property (X_("name"))) == 0) {
2713 if (Glib::path_is_absolute (prop->value())) {
2714 /* external file, ignore */
2722 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2723 result.insert (found_path);
2731 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2733 vector<string> state_files;
2735 string this_snapshot_path;
2741 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2742 ripped = ripped.substr (0, ripped.length() - 1);
2745 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2747 if (state_files.empty()) {
2752 this_snapshot_path = _path;
2753 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2754 this_snapshot_path += statefile_suffix;
2756 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2758 if (exclude_this_snapshot && *i == this_snapshot_path) {
2762 if (find_all_sources (*i, result) < 0) {
2770 struct RegionCounter {
2771 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2772 AudioSourceList::iterator iter;
2773 boost::shared_ptr<Region> region;
2776 RegionCounter() : count (0) {}
2780 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2782 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2783 return r.get_value_or (1);
2787 Session::cleanup_regions ()
2789 bool removed = false;
2790 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2792 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2794 uint32_t used = playlists->region_use_count (i->second);
2796 if (used == 0 && !i->second->automatic ()) {
2798 RegionFactory::map_remove (i->second);
2803 // re-check to remove parent references of compound regions
2804 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2805 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2808 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2809 if (0 == playlists->region_use_count (i->second)) {
2810 RegionFactory::map_remove (i->second);
2815 /* dump the history list */
2822 Session::cleanup_sources (CleanupReport& rep)
2824 // FIXME: needs adaptation to midi
2826 vector<boost::shared_ptr<Source> > dead_sources;
2829 vector<string> candidates;
2830 vector<string> unused;
2831 set<string> all_sources;
2840 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2842 /* consider deleting all unused playlists */
2844 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2849 /* sync the "all regions" property of each playlist with its current state
2852 playlists->sync_all_regions_with_regions ();
2854 /* find all un-used sources */
2859 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2861 SourceMap::iterator tmp;
2866 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2870 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2871 dead_sources.push_back (i->second);
2872 i->second->drop_references ();
2878 /* build a list of all the possible audio directories for the session */
2880 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2881 SessionDirectory sdir ((*i).path);
2882 asp += sdir.sound_path();
2884 audio_path += asp.to_string();
2887 /* build a list of all the possible midi directories for the session */
2889 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2890 SessionDirectory sdir ((*i).path);
2891 msp += sdir.midi_path();
2893 midi_path += msp.to_string();
2895 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2896 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2898 /* find all sources, but don't use this snapshot because the
2899 state file on disk still references sources we may have already
2903 find_all_sources_across_snapshots (all_sources, true);
2905 /* add our current source list
2908 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2909 boost::shared_ptr<FileSource> fs;
2910 SourceMap::iterator tmp = i;
2913 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2915 if (!fs->is_stub()) {
2917 if (playlists->source_use_count (fs) != 0) {
2918 all_sources.insert (fs->path());
2921 /* we might not remove this source from disk, because it may be used
2922 by other snapshots, but its not being used in this version
2923 so lets get rid of it now, along with any representative regions
2927 RegionFactory::remove_regions_using_source (i->second);
2929 // also remove source from all_sources
2931 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
2932 spath = Glib::path_get_basename (*j);
2933 if (spath == i->second->name()) {
2934 all_sources.erase (j);
2947 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2952 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2954 tmppath1 = canonical_path (spath);
2955 tmppath2 = canonical_path ((*i));
2957 if (tmppath1 == tmppath2) {
2964 unused.push_back (spath);
2968 /* now try to move all unused files into the "dead" directory(ies) */
2970 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2971 struct stat statbuf;
2975 /* don't move the file across filesystems, just
2976 stick it in the `dead_dir_name' directory
2977 on whichever filesystem it was already on.
2980 if ((*x).find ("/sounds/") != string::npos) {
2982 /* old school, go up 1 level */
2984 newpath = Glib::path_get_dirname (*x); // "sounds"
2985 newpath = Glib::path_get_dirname (newpath); // "session-name"
2989 /* new school, go up 4 levels */
2991 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2992 newpath = Glib::path_get_dirname (newpath); // "session-name"
2993 newpath = Glib::path_get_dirname (newpath); // "interchange"
2994 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2997 newpath = Glib::build_filename (newpath, dead_dir_name);
2999 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3000 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3004 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3006 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3008 /* the new path already exists, try versioning */
3010 char buf[PATH_MAX+1];
3014 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3017 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3018 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3022 if (version == 999) {
3023 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3027 newpath = newpath_v;
3032 /* it doesn't exist, or we can't read it or something */
3036 stat ((*x).c_str(), &statbuf);
3038 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3039 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3040 (*x), newpath, strerror (errno))
3045 /* see if there an easy to find peakfile for this file, and remove it.
3048 string base = Glib::path_get_basename (*x);
3049 base += "%A"; /* this is what we add for the channel suffix of all native files,
3050 or for the first channel of embedded files. it will miss
3051 some peakfiles for other channels
3053 string peakpath = construct_peak_filepath (base);
3055 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3056 if (::g_unlink (peakpath.c_str()) != 0) {
3057 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3058 peakpath, _path, strerror (errno))
3060 /* try to back out */
3061 ::rename (newpath.c_str(), _path.c_str());
3066 rep.paths.push_back (*x);
3067 rep.space += statbuf.st_size;
3070 /* dump the history list */
3074 /* save state so we don't end up a session file
3075 referring to non-existent sources.
3082 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3088 Session::cleanup_trash_sources (CleanupReport& rep)
3090 // FIXME: needs adaptation for MIDI
3092 vector<space_and_path>::iterator i;
3098 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3100 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3102 clear_directory (dead_dir, &rep.space, &rep.paths);
3109 Session::set_dirty ()
3111 /* never mark session dirty during loading */
3113 if (_state_of_the_state & Loading) {
3117 bool was_dirty = dirty();
3119 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3123 DirtyChanged(); /* EMIT SIGNAL */
3129 Session::set_clean ()
3131 bool was_dirty = dirty();
3133 _state_of_the_state = Clean;
3137 DirtyChanged(); /* EMIT SIGNAL */
3142 Session::set_deletion_in_progress ()
3144 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3148 Session::clear_deletion_in_progress ()
3150 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3154 Session::add_controllable (boost::shared_ptr<Controllable> c)
3156 /* this adds a controllable to the list managed by the Session.
3157 this is a subset of those managed by the Controllable class
3158 itself, and represents the only ones whose state will be saved
3159 as part of the session.
3162 Glib::Threads::Mutex::Lock lm (controllables_lock);
3163 controllables.insert (c);
3166 struct null_deleter { void operator()(void const *) const {} };
3169 Session::remove_controllable (Controllable* c)
3171 if (_state_of_the_state & Deletion) {
3175 Glib::Threads::Mutex::Lock lm (controllables_lock);
3177 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3179 if (x != controllables.end()) {
3180 controllables.erase (x);
3184 boost::shared_ptr<Controllable>
3185 Session::controllable_by_id (const PBD::ID& id)
3187 Glib::Threads::Mutex::Lock lm (controllables_lock);
3189 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3190 if ((*i)->id() == id) {
3195 return boost::shared_ptr<Controllable>();
3198 boost::shared_ptr<Controllable>
3199 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3201 boost::shared_ptr<Controllable> c;
3202 boost::shared_ptr<Route> r;
3204 switch (desc.top_level_type()) {
3205 case ControllableDescriptor::NamedRoute:
3207 std::string str = desc.top_level_name();
3208 if (str == "Master" || str == "master") {
3210 } else if (str == "control" || str == "listen") {
3213 r = route_by_name (desc.top_level_name());
3218 case ControllableDescriptor::RemoteControlID:
3219 r = route_by_remote_id (desc.rid());
3227 switch (desc.subtype()) {
3228 case ControllableDescriptor::Gain:
3229 c = r->gain_control ();
3232 case ControllableDescriptor::Trim:
3233 c = r->trim()->gain_control ();
3236 case ControllableDescriptor::Solo:
3237 c = r->solo_control();
3240 case ControllableDescriptor::Mute:
3241 c = r->mute_control();
3244 case ControllableDescriptor::Recenable:
3246 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3249 c = t->rec_enable_control ();
3254 case ControllableDescriptor::PanDirection:
3256 c = r->pannable()->pan_azimuth_control;
3260 case ControllableDescriptor::PanWidth:
3262 c = r->pannable()->pan_width_control;
3266 case ControllableDescriptor::PanElevation:
3268 c = r->pannable()->pan_elevation_control;
3272 case ControllableDescriptor::Balance:
3273 /* XXX simple pan control */
3276 case ControllableDescriptor::PluginParameter:
3278 uint32_t plugin = desc.target (0);
3279 uint32_t parameter_index = desc.target (1);
3281 /* revert to zero based counting */
3287 if (parameter_index > 0) {
3291 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3294 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3295 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3300 case ControllableDescriptor::SendGain:
3302 uint32_t send = desc.target (0);
3304 /* revert to zero-based counting */
3310 boost::shared_ptr<Processor> p = r->nth_send (send);
3313 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3314 boost::shared_ptr<Amp> a = s->amp();
3317 c = s->amp()->gain_control();
3324 /* relax and return a null pointer */
3332 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3335 Stateful::add_instant_xml (node, _path);
3338 if (write_to_config) {
3339 Config->add_instant_xml (node);
3344 Session::instant_xml (const string& node_name)
3346 return Stateful::instant_xml (node_name, _path);
3350 Session::save_history (string snapshot_name)
3358 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3359 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3363 if (snapshot_name.empty()) {
3364 snapshot_name = _current_snapshot_name;
3367 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3368 const string backup_filename = history_filename + backup_suffix;
3369 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3370 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3372 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3373 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3374 error << _("could not backup old history file, current history not saved") << endmsg;
3379 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3381 if (!tree.write (xml_path))
3383 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3385 if (g_remove (xml_path.c_str()) != 0) {
3386 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3387 xml_path, g_strerror (errno)) << endmsg;
3389 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3390 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3391 backup_path, g_strerror (errno)) << endmsg;
3401 Session::restore_history (string snapshot_name)
3405 if (snapshot_name.empty()) {
3406 snapshot_name = _current_snapshot_name;
3409 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3410 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3412 info << "Loading history from " << xml_path << endmsg;
3414 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3415 info << string_compose (_("%1: no history file \"%2\" for this session."),
3416 _name, xml_path) << endmsg;
3420 if (!tree.read (xml_path)) {
3421 error << string_compose (_("Could not understand session history file \"%1\""),
3422 xml_path) << endmsg;
3429 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3432 UndoTransaction* ut = new UndoTransaction ();
3435 ut->set_name(t->property("name")->value());
3436 stringstream ss(t->property("tv-sec")->value());
3438 ss.str(t->property("tv-usec")->value());
3440 ut->set_timestamp(tv);
3442 for (XMLNodeConstIterator child_it = t->children().begin();
3443 child_it != t->children().end(); child_it++)
3445 XMLNode *n = *child_it;
3448 if (n->name() == "MementoCommand" ||
3449 n->name() == "MementoUndoCommand" ||
3450 n->name() == "MementoRedoCommand") {
3452 if ((c = memento_command_factory(n))) {
3456 } else if (n->name() == "NoteDiffCommand") {
3457 PBD::ID id (n->property("midi-source")->value());
3458 boost::shared_ptr<MidiSource> midi_source =
3459 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3461 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3463 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3466 } else if (n->name() == "SysExDiffCommand") {
3468 PBD::ID id (n->property("midi-source")->value());
3469 boost::shared_ptr<MidiSource> midi_source =
3470 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3472 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3474 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3477 } else if (n->name() == "PatchChangeDiffCommand") {
3479 PBD::ID id (n->property("midi-source")->value());
3480 boost::shared_ptr<MidiSource> midi_source =
3481 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3483 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3485 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3488 } else if (n->name() == "StatefulDiffCommand") {
3489 if ((c = stateful_diff_command_factory (n))) {
3490 ut->add_command (c);
3493 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3504 Session::config_changed (std::string p, bool ours)
3510 if (p == "seamless-loop") {
3512 } else if (p == "rf-speed") {
3514 } else if (p == "auto-loop") {
3516 } else if (p == "auto-input") {
3518 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3519 /* auto-input only makes a difference if we're rolling */
3520 set_track_monitor_input_status (!config.get_auto_input());
3523 } else if (p == "punch-in") {
3527 if ((location = _locations->auto_punch_location()) != 0) {
3529 if (config.get_punch_in ()) {
3530 replace_event (SessionEvent::PunchIn, location->start());
3532 remove_event (location->start(), SessionEvent::PunchIn);
3536 } else if (p == "punch-out") {
3540 if ((location = _locations->auto_punch_location()) != 0) {
3542 if (config.get_punch_out()) {
3543 replace_event (SessionEvent::PunchOut, location->end());
3545 clear_events (SessionEvent::PunchOut);
3549 } else if (p == "edit-mode") {
3551 Glib::Threads::Mutex::Lock lm (playlists->lock);
3553 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3554 (*i)->set_edit_mode (Config->get_edit_mode ());
3557 } else if (p == "use-video-sync") {
3559 waiting_for_sync_offset = config.get_use_video_sync();
3561 } else if (p == "mmc-control") {
3563 //poke_midi_thread ();
3565 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3567 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3569 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3571 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3573 } else if (p == "midi-control") {
3575 //poke_midi_thread ();
3577 } else if (p == "raid-path") {
3579 setup_raid_path (config.get_raid_path());
3581 } else if (p == "timecode-format") {
3585 } else if (p == "video-pullup") {
3589 } else if (p == "seamless-loop") {
3591 if (play_loop && transport_rolling()) {
3592 // to reset diskstreams etc
3593 request_play_loop (true);
3596 } else if (p == "rf-speed") {
3598 cumulative_rf_motion = 0;
3601 } else if (p == "click-sound") {
3603 setup_click_sounds (1);
3605 } else if (p == "click-emphasis-sound") {
3607 setup_click_sounds (-1);
3609 } else if (p == "clicking") {
3611 if (Config->get_clicking()) {
3612 if (_click_io && click_data) { // don't require emphasis data
3619 } else if (p == "click-gain") {
3622 _click_gain->set_gain (Config->get_click_gain(), this);
3625 } else if (p == "send-mtc") {
3627 if (Config->get_send_mtc ()) {
3628 /* mark us ready to send */
3629 next_quarter_frame_to_send = 0;
3632 } else if (p == "send-mmc") {
3634 _mmc->enable_send (Config->get_send_mmc ());
3636 } else if (p == "midi-feedback") {
3638 session_midi_feedback = Config->get_midi_feedback();
3640 } else if (p == "jack-time-master") {
3642 engine().reset_timebase ();
3644 } else if (p == "native-file-header-format") {
3646 if (!first_file_header_format_reset) {
3647 reset_native_file_format ();
3650 first_file_header_format_reset = false;
3652 } else if (p == "native-file-data-format") {
3654 if (!first_file_data_format_reset) {
3655 reset_native_file_format ();
3658 first_file_data_format_reset = false;
3660 } else if (p == "external-sync") {
3661 if (!config.get_external_sync()) {
3662 drop_sync_source ();
3664 switch_to_sync_source (Config->get_sync_source());
3666 } else if (p == "denormal-model") {
3668 } else if (p == "history-depth") {
3669 set_history_depth (Config->get_history_depth());
3670 } else if (p == "remote-model") {
3671 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3674 } else if (p == "initial-program-change") {
3676 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3679 buf[0] = MIDI::program; // channel zero by default
3680 buf[1] = (Config->get_initial_program_change() & 0x7f);
3682 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3684 } else if (p == "solo-mute-override") {
3685 // catch_up_on_solo_mute_override ();
3686 } else if (p == "listen-position" || p == "pfl-position") {
3687 listen_position_changed ();
3688 } else if (p == "solo-control-is-listen-control") {
3689 solo_control_mode_changed ();
3690 } else if (p == "solo-mute-gain") {
3691 _solo_cut_control->Changed();
3692 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3693 last_timecode_valid = false;
3694 } else if (p == "playback-buffer-seconds") {
3695 AudioSource::allocate_working_buffers (frame_rate());
3696 } else if (p == "ltc-source-port") {
3697 reconnect_ltc_input ();
3698 } else if (p == "ltc-sink-port") {
3699 reconnect_ltc_output ();
3700 } else if (p == "timecode-generator-offset") {
3701 ltc_tx_parse_offset();
3702 } else if (p == "auto-return-target-list") {
3703 follow_playhead_priority ();
3710 Session::set_history_depth (uint32_t d)
3712 _history.set_depth (d);
3716 Session::load_diskstreams_2X (XMLNode const & node, int)
3719 XMLNodeConstIterator citer;
3721 clist = node.children();
3723 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3726 /* diskstreams added automatically by DiskstreamCreated handler */
3727 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3728 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3729 _diskstreams_2X.push_back (dsp);
3731 error << _("Session: unknown diskstream type in XML") << endmsg;
3735 catch (failed_constructor& err) {
3736 error << _("Session: could not load diskstream via XML state") << endmsg;
3744 /** Connect things to the MMC object */
3746 Session::setup_midi_machine_control ()
3748 _mmc = new MIDI::MachineControl;
3749 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3751 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3752 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3753 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3754 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3755 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3756 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3757 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3758 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3759 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3760 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3761 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3762 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3763 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3765 /* also handle MIDI SPP because its so common */
3767 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3768 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3769 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3772 boost::shared_ptr<Controllable>
3773 Session::solo_cut_control() const
3775 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3776 controls in Ardour that currently get presented to the user in the GUI that require
3777 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3779 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3780 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3784 return _solo_cut_control;
3788 Session::rename (const std::string& new_name)
3790 string legal_name = legalize_for_path (new_name);
3796 string const old_sources_root = _session_dir->sources_root();
3798 if (!_writable || (_state_of_the_state & CannotSave)) {
3799 error << _("Cannot rename read-only session.") << endmsg;
3800 return 0; // don't show "messed up" warning
3802 if (record_status() == Recording) {
3803 error << _("Cannot rename session while recording") << endmsg;
3804 return 0; // don't show "messed up" warning
3807 StateProtector stp (this);
3812 * interchange subdirectory
3816 * Backup files are left unchanged and not renamed.
3819 /* Windows requires that we close all files before attempting the
3820 * rename. This works on other platforms, but isn't necessary there.
3821 * Leave it in place for all platforms though, since it may help
3822 * catch issues that could arise if the way Source files work ever
3823 * change (since most developers are not using Windows).
3826 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3827 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3833 /* pass one: not 100% safe check that the new directory names don't
3837 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3841 /* this is a stupid hack because Glib::path_get_dirname() is
3842 * lexical-only, and so passing it /a/b/c/ gives a different
3843 * result than passing it /a/b/c ...
3846 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3847 oldstr = oldstr.substr (0, oldstr.length() - 1);
3850 string base = Glib::path_get_dirname (oldstr);
3852 newstr = Glib::build_filename (base, legal_name);
3854 cerr << "Looking for " << newstr << endl;
3856 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3857 cerr << " exists\n";
3866 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3872 /* this is a stupid hack because Glib::path_get_dirname() is
3873 * lexical-only, and so passing it /a/b/c/ gives a different
3874 * result than passing it /a/b/c ...
3877 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3878 oldstr = oldstr.substr (0, oldstr.length() - 1);
3881 string base = Glib::path_get_dirname (oldstr);
3882 newstr = Glib::build_filename (base, legal_name);
3884 cerr << "for " << oldstr << " new dir = " << newstr << endl;
3886 cerr << "Rename " << oldstr << " => " << newstr << endl;
3887 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3888 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3889 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3893 /* Reset path in "session dirs" */
3898 /* reset primary SessionDirectory object */
3901 (*_session_dir) = newstr;
3906 /* now rename directory below session_dir/interchange */
3908 string old_interchange_dir;
3909 string new_interchange_dir;
3911 /* use newstr here because we renamed the path
3912 * (folder/directory) that used to be oldstr to newstr above
3915 v.push_back (newstr);
3916 v.push_back (interchange_dir_name);
3917 v.push_back (Glib::path_get_basename (oldstr));
3919 old_interchange_dir = Glib::build_filename (v);
3922 v.push_back (newstr);
3923 v.push_back (interchange_dir_name);
3924 v.push_back (legal_name);
3926 new_interchange_dir = Glib::build_filename (v);
3928 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
3930 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
3931 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
3932 old_interchange_dir, new_interchange_dir,
3935 error << string_compose (_("renaming %s as %2 failed (%3)"),
3936 old_interchange_dir, new_interchange_dir,
3945 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
3946 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
3948 cerr << "Rename " << oldstr << " => " << newstr << endl;
3950 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3951 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3952 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3958 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
3960 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3961 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
3963 cerr << "Rename " << oldstr << " => " << newstr << endl;
3965 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3966 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3967 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3972 /* remove old name from recent sessions */
3973 remove_recent_sessions (_path);
3976 /* update file source paths */
3978 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3979 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3981 string p = fs->path ();
3982 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3984 SourceFactory::setup_peakfile(i->second, true);
3988 _current_snapshot_name = new_name;
3993 /* save state again to get everything just right */
3995 save_state (_current_snapshot_name);
3997 /* add to recent sessions */
3999 store_recent_sessions (new_name, _path);
4005 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4007 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4011 if (!tree.read (xmlpath)) {
4019 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4022 bool found_sr = false;
4023 bool found_data_format = false;
4025 if (get_session_info_from_path (tree, xmlpath)) {
4031 const XMLProperty* prop;
4032 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
4033 sample_rate = atoi (prop->value());
4037 const XMLNodeList& children (tree.root()->children());
4038 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4039 const XMLNode* child = *c;
4040 if (child->name() == "Config") {
4041 const XMLNodeList& options (child->children());
4042 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4043 const XMLNode* option = *oc;
4044 const XMLProperty* name = option->property("name");
4050 if (name->value() == "native-file-data-format") {
4051 const XMLProperty* value = option->property ("value");
4053 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4055 found_data_format = true;
4061 if (found_data_format) {
4066 return !(found_sr && found_data_format); // zero if they are both found
4069 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4070 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4073 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4077 SourcePathMap source_path_map;
4079 boost::shared_ptr<AudioFileSource> afs;
4084 Glib::Threads::Mutex::Lock lm (source_lock);
4086 cerr << " total sources = " << sources.size();
4088 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4089 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4095 if (fs->within_session()) {
4099 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4100 source_path_map[fs->path()].push_back (fs);
4102 SeveralFileSources v;
4104 source_path_map.insert (make_pair (fs->path(), v));
4110 cerr << " fsources = " << total << endl;
4112 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4114 /* tell caller where we are */
4116 string old_path = i->first;
4118 callback (n, total, old_path);
4120 cerr << old_path << endl;
4124 switch (i->second.front()->type()) {
4125 case DataType::AUDIO:
4126 new_path = new_audio_source_path_for_embedded (old_path);
4129 case DataType::MIDI:
4130 /* XXX not implemented yet */
4134 if (new_path.empty()) {
4138 cerr << "Move " << old_path << " => " << new_path << endl;
4140 if (!copy_file (old_path, new_path)) {
4141 cerr << "failed !\n";
4145 /* make sure we stop looking in the external
4146 dir/folder. Remember, this is an all-or-nothing
4147 operations, it doesn't merge just some files.
4149 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4151 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4152 (*f)->set_path (new_path);
4157 save_state ("", false, false);
4163 bool accept_all_files (string const &, void *)
4169 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4171 /* It would be good if this did something useful vis-a-vis save-as, but the arguments doesn't provide the correct information right now to do this.
4176 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4178 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4180 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4182 v.push_back (new_session_folder); /* full path */
4183 v.push_back (interchange_dir_name);
4184 v.push_back (new_session_path); /* just one directory/folder */
4185 v.push_back (typedir);
4186 v.push_back (Glib::path_get_basename (old_path));
4188 return Glib::build_filename (v);
4192 Session::save_as (SaveAs& saveas)
4194 vector<string> files;
4195 string current_folder = Glib::path_get_dirname (_path);
4196 string new_folder = legalize_for_path (saveas.new_name);
4197 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4198 int64_t total_bytes = 0;
4202 int32_t internal_file_cnt = 0;
4204 vector<string> do_not_copy_extensions;
4205 do_not_copy_extensions.push_back (statefile_suffix);
4206 do_not_copy_extensions.push_back (pending_suffix);
4207 do_not_copy_extensions.push_back (backup_suffix);
4208 do_not_copy_extensions.push_back (temp_suffix);
4209 do_not_copy_extensions.push_back (history_suffix);
4211 /* get total size */
4213 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4215 /* need to clear this because
4216 * find_files_matching_filter() is cumulative
4221 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4223 all += files.size();
4225 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4227 g_stat ((*i).c_str(), &gsb);
4228 total_bytes += gsb.st_size;
4232 /* save old values so we can switch back if we are not switching to the new session */
4234 string old_path = _path;
4235 string old_name = _name;
4236 string old_snapshot = _current_snapshot_name;
4237 string old_sd = _session_dir->root_path();
4238 vector<string> old_search_path[DataType::num_types];
4239 string old_config_search_path[DataType::num_types];
4241 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4242 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4243 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4244 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4246 /* switch session directory */
4248 (*_session_dir) = to_dir;
4250 /* create new tree */
4252 if (!_session_dir->create()) {
4253 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4258 /* copy all relevant files. Find each location in session_dirs,
4259 * and copy files from there to target.
4262 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4264 /* need to clear this because
4265 * find_files_matching_filter() is cumulative
4270 const size_t prefix_len = (*sd).path.size();
4272 /* Work just on the files within this session dir */
4274 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4276 /* add dir separator to protect against collisions with
4277 * track names (e.g. track named "audiofiles" or
4281 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4282 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4283 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4285 /* copy all the files. Handling is different for media files
4286 than others because of the *silly* subtree we have below the interchange
4287 folder. That really was a bad idea, but I'm not fixing it as part of
4288 implementing ::save_as().
4291 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4293 std::string from = *i;
4296 string filename = Glib::path_get_basename (from);
4297 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4298 if (filename == ".DS_STORE") {
4303 if (from.find (audiofile_dir_string) != string::npos) {
4305 /* audio file: only copy if asked */
4307 if (saveas.include_media && saveas.copy_media) {
4309 string to = make_new_media_path (*i, to_dir, new_folder);
4311 info << "media file copying from " << from << " to " << to << endmsg;
4313 if (!copy_file (from, to)) {
4314 throw Glib::FileError (Glib::FileError::IO_ERROR,
4315 string_compose(_("\ncopying \"%1\" failed !"), from));
4319 /* we found media files inside the session folder */
4321 internal_file_cnt++;
4323 } else if (from.find (midifile_dir_string) != string::npos) {
4325 /* midi file: always copy unless
4326 * creating an empty new session
4329 if (saveas.include_media) {
4331 string to = make_new_media_path (*i, to_dir, new_folder);
4333 info << "media file copying from " << from << " to " << to << endmsg;
4335 if (!copy_file (from, to)) {
4336 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4340 /* we found media files inside the session folder */
4342 internal_file_cnt++;
4344 } else if (from.find (analysis_dir_string) != string::npos) {
4346 /* make sure analysis dir exists in
4347 * new session folder, but we're not
4348 * copying analysis files here, see
4352 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4357 /* normal non-media file. Don't copy state, history, etc.
4360 bool do_copy = true;
4362 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4363 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4364 /* end of filename matches extension, do not copy file */
4370 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4371 /* don't copy peakfiles if
4372 * we're not copying media
4378 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4380 info << "attempting to make directory/folder " << to << endmsg;
4382 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4383 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4386 info << "attempting to copy " << from << " to " << to << endmsg;
4388 if (!copy_file (from, to)) {
4389 throw Glib::FileError (Glib::FileError::IO_ERROR,
4390 string_compose(_("\ncopying \"%1\" failed !"), from));
4395 /* measure file size even if we're not going to copy so that our Progress
4396 signals are correct, since we included these do-not-copy files
4397 in the computation of the total size and file count.
4401 g_stat (from.c_str(), &gsb);
4402 copied += gsb.st_size;
4405 double fraction = (double) copied / total_bytes;
4407 bool keep_going = true;
4409 if (saveas.copy_media) {
4411 /* no need or expectation of this if
4412 * media is not being copied, because
4413 * it will be fast(ish).
4416 /* tell someone "X percent, file M of N"; M is one-based */
4418 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4426 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4432 /* copy optional folders, if any */
4434 string old = plugins_dir ();
4435 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4436 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4437 copy_files (old, newdir);
4440 old = externals_dir ();
4441 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4442 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4443 copy_files (old, newdir);
4446 old = automation_dir ();
4447 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4448 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4449 copy_files (old, newdir);
4452 if (saveas.include_media) {
4454 if (saveas.copy_media) {
4455 #ifndef PLATFORM_WINDOWS
4456 /* There are problems with analysis files on
4457 * Windows, because they used a colon in their
4458 * names as late as 4.0. Colons are not legal
4459 * under Windows even if NTFS allows them.
4461 * This is a tricky problem to solve so for
4462 * just don't copy these files. They will be
4463 * regenerated as-needed anyway, subject to the
4464 * existing issue that the filenames will be
4465 * rejected by Windows, which is a separate
4466 * problem (though related).
4469 /* only needed if we are copying media, since the
4470 * analysis data refers to media data
4473 old = analysis_dir ();
4474 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4475 string newdir = Glib::build_filename (to_dir, "analysis");
4476 copy_files (old, newdir);
4478 #endif /* PLATFORM_WINDOWS */
4484 _current_snapshot_name = saveas.new_name;
4485 _name = saveas.new_name;
4487 if (saveas.include_media && !saveas.copy_media) {
4489 /* reset search paths of the new session (which we're pretending to be right now) to
4490 include the original session search path, so we can still find all audio.
4493 if (internal_file_cnt) {
4494 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4495 ensure_search_path_includes (*s, DataType::AUDIO);
4496 cerr << "be sure to include " << *s << " for audio" << endl;
4499 /* we do not do this for MIDI because we copy
4500 all MIDI files if saveas.include_media is
4506 bool was_dirty = dirty ();
4508 save_state ("", false, false, !saveas.include_media);
4509 save_default_options ();
4511 if (saveas.copy_media && saveas.copy_external) {
4512 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4513 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4517 saveas.final_session_folder_name = _path;
4519 store_recent_sessions (_name, _path);
4521 if (!saveas.switch_to) {
4523 /* switch back to the way things were */
4527 _current_snapshot_name = old_snapshot;
4529 (*_session_dir) = old_sd;
4535 if (internal_file_cnt) {
4536 /* reset these to their original values */
4537 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4538 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4543 /* prune session dirs, and update disk space statistics
4548 session_dirs.clear ();
4549 session_dirs.push_back (sp);
4550 refresh_disk_space ();
4552 /* ensure that all existing tracks reset their current capture source paths
4554 reset_write_sources (true, true);
4556 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4557 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4560 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4561 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4567 if (fs->within_session()) {
4568 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4569 fs->set_path (newpath);
4574 } catch (Glib::FileError& e) {
4576 saveas.failure_message = e.what();
4578 /* recursively remove all the directories */
4580 remove_directory (to_dir);
4588 saveas.failure_message = _("unknown reason");
4590 /* recursively remove all the directories */
4592 remove_directory (to_dir);