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 ();
206 AudioFileSource::set_peak_dir (_session_dir->peak_path());
210 Session::post_engine_init ()
212 BootMessage (_("Set block size and sample rate"));
214 set_block_size (_engine.samples_per_cycle());
215 set_frame_rate (_engine.sample_rate());
217 BootMessage (_("Using configuration"));
219 _midi_ports = new MidiPortManager;
221 MIDISceneChanger* msc;
223 _scene_changer = msc = new MIDISceneChanger (*this);
224 msc->set_input_port (scene_input_port());
225 msc->set_output_port (scene_out());
227 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
228 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
230 setup_midi_machine_control ();
232 if (_butler->start_thread()) {
236 if (start_midi_thread ()) {
240 setup_click_sounds (0);
241 setup_midi_control ();
243 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
244 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
247 /* tempo map requires sample rate knowledge */
250 _tempo_map = new TempoMap (_current_frame_rate);
251 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
253 /* MidiClock requires a tempo map */
255 midi_clock = new MidiClockTicker ();
256 midi_clock->set_session (this);
258 /* crossfades require sample rate knowledge */
260 SndFileSource::setup_standard_crossfades (*this, frame_rate());
261 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
263 AudioDiskstream::allocate_working_buffers();
264 refresh_disk_space ();
266 /* we're finally ready to call set_state() ... all objects have
267 * been created, the engine is running.
271 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
275 // set_state() will call setup_raid_path(), but if it's a new session we need
276 // to call setup_raid_path() here.
277 setup_raid_path (_path);
282 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
283 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
285 Config->map_parameters (ff);
286 config.map_parameters (ft);
287 _butler->map_parameters ();
289 /* Reset all panners */
291 Delivery::reset_panners ();
293 /* this will cause the CPM to instantiate any protocols that are in use
294 * (or mandatory), which will pass it this Session, and then call
295 * set_state() on each instantiated protocol to match stored state.
298 ControlProtocolManager::instance().set_session (this);
300 /* This must be done after the ControlProtocolManager set_session above,
301 as it will set states for ports which the ControlProtocolManager creates.
304 // XXX set state of MIDI::Port's
305 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
307 /* And this must be done after the MIDI::Manager::set_port_states as
308 * it will try to make connections whose details are loaded by set_port_states.
313 /* Let control protocols know that we are now all connected, so they
314 * could start talking to surfaces if they want to.
317 ControlProtocolManager::instance().midi_connectivity_established ();
319 if (_is_new && !no_auto_connect()) {
320 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
321 auto_connect_master_bus ();
324 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
326 /* update latencies */
328 initialize_latencies ();
330 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
331 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
332 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
334 } catch (AudioEngine::PortRegistrationFailure& err) {
335 /* handle this one in a different way than all others, so that its clear what happened */
336 error << err.what() << endmsg;
342 BootMessage (_("Reset Remote Controls"));
344 // send_full_time_code (0);
345 _engine.transport_locate (0);
347 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
348 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
350 MIDI::Name::MidiPatchManager::instance().set_session (this);
353 /* initial program change will be delivered later; see ::config_changed() */
355 _state_of_the_state = Clean;
357 Port::set_connecting_blocked (false);
359 DirtyChanged (); /* EMIT SIGNAL */
363 } else if (state_was_pending) {
365 remove_pending_capture_state ();
366 state_was_pending = false;
369 /* Now, finally, we can fill the playback buffers */
371 BootMessage (_("Filling playback buffers"));
373 boost::shared_ptr<RouteList> rl = routes.reader();
374 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
375 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
376 if (trk && !trk->hidden()) {
377 trk->seek (_transport_frame, true);
385 Session::session_loaded ()
389 _state_of_the_state = Clean;
391 DirtyChanged (); /* EMIT SIGNAL */
395 } else if (state_was_pending) {
397 remove_pending_capture_state ();
398 state_was_pending = false;
401 /* Now, finally, we can fill the playback buffers */
403 BootMessage (_("Filling playback buffers"));
404 force_locate (_transport_frame, false);
408 Session::raid_path () const
410 Searchpath raid_search_path;
412 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
413 raid_search_path += (*i).path;
416 return raid_search_path.to_string ();
420 Session::setup_raid_path (string path)
429 session_dirs.clear ();
431 Searchpath search_path(path);
432 Searchpath sound_search_path;
433 Searchpath midi_search_path;
435 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
437 sp.blocks = 0; // not needed
438 session_dirs.push_back (sp);
440 SessionDirectory sdir(sp.path);
442 sound_search_path += sdir.sound_path ();
443 midi_search_path += sdir.midi_path ();
446 // reset the round-robin soundfile path thingie
447 last_rr_session_dir = session_dirs.begin();
451 Session::path_is_within_session (const std::string& path)
453 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
454 if (PBD::path_is_within (i->path, path)) {
462 Session::ensure_subdirs ()
466 dir = session_directory().peak_path();
468 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
469 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
473 dir = session_directory().sound_path();
475 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
476 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
480 dir = session_directory().midi_path();
482 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
483 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
487 dir = session_directory().dead_path();
489 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
490 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
494 dir = session_directory().export_path();
496 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
497 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
501 dir = analysis_dir ();
503 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
504 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
508 dir = plugins_dir ();
510 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
511 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
515 dir = externals_dir ();
517 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
518 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
525 /** @param session_template directory containing session template, or empty.
526 * Caller must not hold process lock.
529 Session::create (const string& session_template, BusProfile* bus_profile)
531 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
532 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
536 if (ensure_subdirs ()) {
540 _writable = exists_and_writable (_path);
542 if (!session_template.empty()) {
543 std::string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
545 ifstream in(in_path.c_str());
548 /* no need to call legalize_for_path() since the string
549 * in session_template is already a legal path name
551 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
553 ofstream out(out_path.c_str());
559 if (!ARDOUR::Profile->get_trx()) {
560 /* Copy plugin state files from template to new session */
561 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
562 copy_recurse (template_plugins, plugins_dir ());
568 error << string_compose (_("Could not open %1 for writing session template"), out_path)
574 error << string_compose (_("Could not open session template %1 for reading"), in_path)
581 if (Profile->get_trx()) {
583 /* set initial start + end point : ARDOUR::Session::session_end_shift long.
584 Remember that this is a brand new session. Sessions
585 loaded from saved state will get this range from the saved state.
588 set_session_range_location (0, 0);
590 /* Initial loop location, from absolute zero, length 10 seconds */
592 Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
593 _locations->add (loc, true);
594 set_auto_loop_location (loc);
597 _state_of_the_state = Clean;
599 /* set up Master Out and Control Out if necessary */
604 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
606 // Waves Tracks: always create master bus for Tracks
607 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
608 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
612 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
613 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
616 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
617 r->input()->ensure_io (count, false, this);
618 r->output()->ensure_io (count, false, this);
624 /* prohibit auto-connect to master, because there isn't one */
625 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
629 add_routes (rl, false, false, false);
632 // Waves Tracks: Skip this. Always use autoconnection for Tracks
633 if (!ARDOUR::Profile->get_trx()) {
635 /* this allows the user to override settings with an environment variable.
638 if (no_auto_connect()) {
639 bus_profile->input_ac = AutoConnectOption (0);
640 bus_profile->output_ac = AutoConnectOption (0);
643 Config->set_input_auto_connect (bus_profile->input_ac);
644 Config->set_output_auto_connect (bus_profile->output_ac);
648 if (Config->get_use_monitor_bus() && bus_profile) {
649 add_monitor_section ();
656 Session::maybe_write_autosave()
658 if (dirty() && record_status() != Recording) {
659 save_state("", true);
664 Session::remove_pending_capture_state ()
666 std::string pending_state_file_path(_session_dir->root_path());
668 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
670 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
672 if (g_remove (pending_state_file_path.c_str()) != 0) {
673 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
674 pending_state_file_path, g_strerror (errno)) << endmsg;
678 /** Rename a state file.
679 * @param old_name Old snapshot name.
680 * @param new_name New snapshot name.
683 Session::rename_state (string old_name, string new_name)
685 if (old_name == _current_snapshot_name || old_name == _name) {
686 /* refuse to rename the current snapshot or the "main" one */
690 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
691 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
693 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
694 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
696 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
697 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
698 old_name, new_name, g_strerror(errno)) << endmsg;
702 /** Remove a state file.
703 * @param snapshot_name Snapshot name.
706 Session::remove_state (string snapshot_name)
708 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
709 // refuse to remove the current snapshot or the "main" one
713 std::string xml_path(_session_dir->root_path());
715 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
717 if (!create_backup_file (xml_path)) {
718 // don't remove it if a backup can't be made
719 // create_backup_file will log the error.
724 if (g_remove (xml_path.c_str()) != 0) {
725 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
726 xml_path, g_strerror (errno)) << endmsg;
730 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
732 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
735 std::string xml_path(_session_dir->root_path());
737 /* prevent concurrent saves from different threads */
739 Glib::Threads::Mutex::Lock lm (save_state_lock);
741 if (!_writable || (_state_of_the_state & CannotSave)) {
745 if (g_atomic_int_get(&_suspend_save)) {
749 _save_queued = false;
751 if (!_engine.connected ()) {
752 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
758 /* tell sources we're saving first, in case they write out to a new file
759 * which should be saved with the state rather than the old one */
760 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
762 i->second->session_saved();
763 } catch (Evoral::SMF::FileError& e) {
764 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
768 SessionSaveUnderway (); /* EMIT SIGNAL */
771 tree.set_root (&get_template());
773 tree.set_root (&get_state());
776 if (snapshot_name.empty()) {
777 snapshot_name = _current_snapshot_name;
778 } else if (switch_to_snapshot) {
779 _current_snapshot_name = snapshot_name;
784 /* proper save: use statefile_suffix (.ardour in English) */
786 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
788 /* make a backup copy of the old file */
790 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
791 // create_backup_file will log the error
797 /* pending save: use pending_suffix (.pending in English) */
798 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
801 std::string tmp_path(_session_dir->root_path());
802 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
804 cerr << "actually writing state to " << tmp_path << endl;
806 if (!tree.write (tmp_path)) {
807 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
808 if (g_remove (tmp_path.c_str()) != 0) {
809 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
810 tmp_path, g_strerror (errno)) << endmsg;
816 cerr << "renaming state to " << xml_path << endl;
818 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
819 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
820 tmp_path, xml_path, g_strerror(errno)) << endmsg;
821 if (g_remove (tmp_path.c_str()) != 0) {
822 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
823 tmp_path, g_strerror (errno)) << endmsg;
831 save_history (snapshot_name);
833 bool was_dirty = dirty();
835 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
838 DirtyChanged (); /* EMIT SIGNAL */
841 StateSaved (snapshot_name); /* EMIT SIGNAL */
848 Session::restore_state (string snapshot_name)
850 if (load_state (snapshot_name) == 0) {
851 set_state (*state_tree->root(), Stateful::loading_state_version);
858 Session::load_state (string snapshot_name)
863 state_was_pending = false;
865 /* check for leftover pending state from a crashed capture attempt */
867 std::string xmlpath(_session_dir->root_path());
868 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
870 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
872 /* there is pending state from a crashed capture attempt */
874 boost::optional<int> r = AskAboutPendingState();
875 if (r.get_value_or (1)) {
876 state_was_pending = true;
880 if (!state_was_pending) {
881 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
884 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
885 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
886 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
887 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
892 state_tree = new XMLTree;
896 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
898 if (!state_tree->read (xmlpath)) {
899 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
905 XMLNode& root (*state_tree->root());
907 if (root.name() != X_("Session")) {
908 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
914 const XMLProperty* prop;
916 if ((prop = root.property ("version")) == 0) {
917 /* no version implies very old version of Ardour */
918 Stateful::loading_state_version = 1000;
920 if (prop->value().find ('.') != string::npos) {
921 /* old school version format */
922 if (prop->value()[0] == '2') {
923 Stateful::loading_state_version = 2000;
925 Stateful::loading_state_version = 3000;
928 Stateful::loading_state_version = atoi (prop->value());
932 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
934 std::string backup_path(_session_dir->root_path());
935 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
936 backup_path = Glib::build_filename (backup_path, backup_filename);
938 // only create a backup for a given statefile version once
940 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
942 VersionMismatch (xmlpath, backup_path);
944 if (!copy_file (xmlpath, backup_path)) {;
954 Session::load_options (const XMLNode& node)
956 LocaleGuard lg (X_("C"));
957 config.set_variables (node);
962 Session::save_default_options ()
964 return config.save_state();
974 Session::get_template()
976 /* if we don't disable rec-enable, diskstreams
977 will believe they need to store their capture
978 sources in their state node.
981 disable_record (false);
987 Session::state (bool full_state)
989 XMLNode* node = new XMLNode("Session");
993 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
994 node->add_property("version", buf);
996 /* store configuration settings */
1000 node->add_property ("name", _name);
1001 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
1002 node->add_property ("sample-rate", buf);
1004 if (session_dirs.size() > 1) {
1008 vector<space_and_path>::iterator i = session_dirs.begin();
1009 vector<space_and_path>::iterator next;
1011 ++i; /* skip the first one */
1015 while (i != session_dirs.end()) {
1019 if (next != session_dirs.end()) {
1020 p += G_SEARCHPATH_SEPARATOR;
1029 child = node->add_child ("Path");
1030 child->add_content (p);
1034 /* save the ID counter */
1036 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1037 node->add_property ("id-counter", buf);
1039 /* save the event ID counter */
1041 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1042 node->add_property ("event-counter", buf);
1044 /* various options */
1046 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1047 if (!midi_port_nodes.empty()) {
1048 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1049 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1050 midi_port_stuff->add_child_nocopy (**n);
1052 node->add_child_nocopy (*midi_port_stuff);
1055 node->add_child_nocopy (config.get_variables ());
1057 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1059 child = node->add_child ("Sources");
1062 Glib::Threads::Mutex::Lock sl (source_lock);
1064 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1066 /* Don't save information about non-file Sources, or
1067 * about non-destructive file sources that are empty
1068 * and unused by any regions.
1071 boost::shared_ptr<FileSource> fs;
1073 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1075 if (!fs->destructive()) {
1076 if (fs->empty() && !fs->used()) {
1081 child->add_child_nocopy (siter->second->get_state());
1086 child = node->add_child ("Regions");
1089 Glib::Threads::Mutex::Lock rl (region_lock);
1090 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1091 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1092 boost::shared_ptr<Region> r = i->second;
1093 /* only store regions not attached to playlists */
1094 if (r->playlist() == 0) {
1095 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1096 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1098 child->add_child_nocopy (r->get_state ());
1103 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1105 if (!cassocs.empty()) {
1106 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1108 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1110 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1111 i->first->id().print (buf, sizeof (buf));
1112 can->add_property (X_("copy"), buf);
1113 i->second->id().print (buf, sizeof (buf));
1114 can->add_property (X_("original"), buf);
1115 ca->add_child_nocopy (*can);
1125 node->add_child_nocopy (_locations->get_state());
1128 Locations loc (*this);
1129 // for a template, just create a new Locations, populate it
1130 // with the default start and end, and get the state for that.
1131 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1132 range->set (max_framepos, 0);
1134 XMLNode& locations_state = loc.get_state();
1136 if (ARDOUR::Profile->get_trx() && _locations) {
1137 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1138 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1139 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1140 locations_state.add_child_nocopy ((*i)->get_state ());
1144 node->add_child_nocopy (locations_state);
1147 child = node->add_child ("Bundles");
1149 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1150 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1151 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1153 child->add_child_nocopy (b->get_state());
1158 child = node->add_child ("Routes");
1160 boost::shared_ptr<RouteList> r = routes.reader ();
1162 RoutePublicOrderSorter cmp;
1163 RouteList public_order (*r);
1164 public_order.sort (cmp);
1166 /* the sort should have put control outs first */
1169 assert (_monitor_out == public_order.front());
1172 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1173 if (!(*i)->is_auditioner()) {
1175 child->add_child_nocopy ((*i)->get_state());
1177 child->add_child_nocopy ((*i)->get_template());
1183 playlists->add_state (node, full_state);
1185 child = node->add_child ("RouteGroups");
1186 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1187 child->add_child_nocopy ((*i)->get_state());
1191 XMLNode* gain_child = node->add_child ("Click");
1192 gain_child->add_child_nocopy (_click_io->state (full_state));
1193 gain_child->add_child_nocopy (_click_gain->state (full_state));
1197 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1198 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1202 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1203 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1206 node->add_child_nocopy (_speakers->get_state());
1207 node->add_child_nocopy (_tempo_map->get_state());
1208 node->add_child_nocopy (get_control_protocol_state());
1211 node->add_child_copy (*_extra_xml);
1218 Session::get_control_protocol_state ()
1220 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1221 return cpm.get_state();
1225 Session::set_state (const XMLNode& node, int version)
1229 const XMLProperty* prop;
1232 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1234 if (node.name() != X_("Session")) {
1235 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1239 if ((prop = node.property ("name")) != 0) {
1240 _name = prop->value ();
1243 if ((prop = node.property (X_("sample-rate"))) != 0) {
1245 _nominal_frame_rate = atoi (prop->value());
1247 if (_nominal_frame_rate != _current_frame_rate) {
1248 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1249 if (r.get_value_or (0)) {
1255 setup_raid_path(_session_dir->root_path());
1257 if ((prop = node.property (X_("id-counter"))) != 0) {
1259 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1260 ID::init_counter (x);
1262 /* old sessions used a timebased counter, so fake
1263 the startup ID counter based on a standard
1268 ID::init_counter (now);
1271 if ((prop = node.property (X_("event-counter"))) != 0) {
1272 Evoral::init_event_id_counter (atoi (prop->value()));
1276 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1277 _midi_ports->set_midi_port_states (child->children());
1280 IO::disable_connecting ();
1282 Stateful::save_extra_xml (node);
1284 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1285 load_options (*child);
1286 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1287 load_options (*child);
1289 error << _("Session: XML state has no options section") << endmsg;
1292 if (version >= 3000) {
1293 if ((child = find_named_node (node, "Metadata")) == 0) {
1294 warning << _("Session: XML state has no metadata section") << endmsg;
1295 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1300 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1301 _speakers->set_state (*child, version);
1304 if ((child = find_named_node (node, "Sources")) == 0) {
1305 error << _("Session: XML state has no sources section") << endmsg;
1307 } else if (load_sources (*child)) {
1311 if ((child = find_named_node (node, "TempoMap")) == 0) {
1312 error << _("Session: XML state has no Tempo Map section") << endmsg;
1314 } else if (_tempo_map->set_state (*child, version)) {
1318 if ((child = find_named_node (node, "Locations")) == 0) {
1319 error << _("Session: XML state has no locations section") << endmsg;
1321 } else if (_locations->set_state (*child, version)) {
1325 locations_changed ();
1327 if (_session_range_location) {
1328 AudioFileSource::set_header_position_offset (_session_range_location->start());
1331 if ((child = find_named_node (node, "Regions")) == 0) {
1332 error << _("Session: XML state has no Regions section") << endmsg;
1334 } else if (load_regions (*child)) {
1338 if ((child = find_named_node (node, "Playlists")) == 0) {
1339 error << _("Session: XML state has no playlists section") << endmsg;
1341 } else if (playlists->load (*this, *child)) {
1345 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1347 } else if (playlists->load_unused (*this, *child)) {
1351 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1352 if (load_compounds (*child)) {
1357 if (version >= 3000) {
1358 if ((child = find_named_node (node, "Bundles")) == 0) {
1359 warning << _("Session: XML state has no bundles section") << endmsg;
1362 /* We can't load Bundles yet as they need to be able
1363 to convert from port names to Port objects, which can't happen until
1365 _bundle_xml_node = new XMLNode (*child);
1369 if (version < 3000) {
1370 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1371 error << _("Session: XML state has no diskstreams section") << endmsg;
1373 } else if (load_diskstreams_2X (*child, version)) {
1378 if ((child = find_named_node (node, "Routes")) == 0) {
1379 error << _("Session: XML state has no routes section") << endmsg;
1381 } else if (load_routes (*child, version)) {
1385 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1386 _diskstreams_2X.clear ();
1388 if (version >= 3000) {
1390 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1391 error << _("Session: XML state has no route groups section") << endmsg;
1393 } else if (load_route_groups (*child, version)) {
1397 } else if (version < 3000) {
1399 if ((child = find_named_node (node, "EditGroups")) == 0) {
1400 error << _("Session: XML state has no edit groups section") << endmsg;
1402 } else if (load_route_groups (*child, version)) {
1406 if ((child = find_named_node (node, "MixGroups")) == 0) {
1407 error << _("Session: XML state has no mix groups section") << endmsg;
1409 } else if (load_route_groups (*child, version)) {
1414 if ((child = find_named_node (node, "Click")) == 0) {
1415 warning << _("Session: XML state has no click section") << endmsg;
1416 } else if (_click_io) {
1417 setup_click_state (&node);
1420 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1421 ControlProtocolManager::instance().set_state (*child, version);
1424 update_route_record_state ();
1426 /* here beginneth the second phase ... */
1428 StateReady (); /* EMIT SIGNAL */
1441 Session::load_routes (const XMLNode& node, int version)
1444 XMLNodeConstIterator niter;
1445 RouteList new_routes;
1447 nlist = node.children();
1451 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1453 boost::shared_ptr<Route> route;
1454 if (version < 3000) {
1455 route = XMLRouteFactory_2X (**niter, version);
1457 route = XMLRouteFactory (**niter, version);
1461 error << _("Session: cannot create Route from XML description.") << endmsg;
1465 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1467 new_routes.push_back (route);
1470 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1472 add_routes (new_routes, false, false, false);
1474 BootMessage (_("Finished adding tracks/busses"));
1479 boost::shared_ptr<Route>
1480 Session::XMLRouteFactory (const XMLNode& node, int version)
1482 boost::shared_ptr<Route> ret;
1484 if (node.name() != "Route") {
1488 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1490 DataType type = DataType::AUDIO;
1491 const XMLProperty* prop = node.property("default-type");
1494 type = DataType (prop->value());
1497 assert (type != DataType::NIL);
1501 boost::shared_ptr<Track> track;
1503 if (type == DataType::AUDIO) {
1504 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1506 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1509 if (track->init()) {
1513 if (track->set_state (node, version)) {
1517 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1518 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1523 enum Route::Flag flags = Route::Flag(0);
1524 const XMLProperty* prop = node.property("flags");
1526 flags = Route::Flag (string_2_enum (prop->value(), flags));
1529 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1531 if (r->init () == 0 && r->set_state (node, version) == 0) {
1532 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1533 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1542 boost::shared_ptr<Route>
1543 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1545 boost::shared_ptr<Route> ret;
1547 if (node.name() != "Route") {
1551 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1553 ds_prop = node.property (X_("diskstream"));
1556 DataType type = DataType::AUDIO;
1557 const XMLProperty* prop = node.property("default-type");
1560 type = DataType (prop->value());
1563 assert (type != DataType::NIL);
1567 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1568 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1572 if (i == _diskstreams_2X.end()) {
1573 error << _("Could not find diskstream for route") << endmsg;
1574 return boost::shared_ptr<Route> ();
1577 boost::shared_ptr<Track> track;
1579 if (type == DataType::AUDIO) {
1580 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1582 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1585 if (track->init()) {
1589 if (track->set_state (node, version)) {
1593 track->set_diskstream (*i);
1595 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1596 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1601 enum Route::Flag flags = Route::Flag(0);
1602 const XMLProperty* prop = node.property("flags");
1604 flags = Route::Flag (string_2_enum (prop->value(), flags));
1607 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1609 if (r->init () == 0 && r->set_state (node, version) == 0) {
1610 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1611 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1621 Session::load_regions (const XMLNode& node)
1624 XMLNodeConstIterator niter;
1625 boost::shared_ptr<Region> region;
1627 nlist = node.children();
1631 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1632 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1633 error << _("Session: cannot create Region from XML description.");
1634 const XMLProperty *name = (**niter).property("name");
1637 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1648 Session::load_compounds (const XMLNode& node)
1650 XMLNodeList calist = node.children();
1651 XMLNodeConstIterator caiter;
1652 XMLProperty *caprop;
1654 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1655 XMLNode* ca = *caiter;
1659 if ((caprop = ca->property (X_("original"))) == 0) {
1662 orig_id = caprop->value();
1664 if ((caprop = ca->property (X_("copy"))) == 0) {
1667 copy_id = caprop->value();
1669 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1670 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1672 if (!orig || !copy) {
1673 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1679 RegionFactory::add_compound_association (orig, copy);
1686 Session::load_nested_sources (const XMLNode& node)
1689 XMLNodeConstIterator niter;
1691 nlist = node.children();
1693 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1694 if ((*niter)->name() == "Source") {
1696 /* it may already exist, so don't recreate it unnecessarily
1699 XMLProperty* prop = (*niter)->property (X_("id"));
1701 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1705 ID source_id (prop->value());
1707 if (!source_by_id (source_id)) {
1710 SourceFactory::create (*this, **niter, true);
1712 catch (failed_constructor& err) {
1713 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1720 boost::shared_ptr<Region>
1721 Session::XMLRegionFactory (const XMLNode& node, bool full)
1723 const XMLProperty* type = node.property("type");
1727 const XMLNodeList& nlist = node.children();
1729 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1730 XMLNode *child = (*niter);
1731 if (child->name() == "NestedSource") {
1732 load_nested_sources (*child);
1736 if (!type || type->value() == "audio") {
1737 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1738 } else if (type->value() == "midi") {
1739 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1742 } catch (failed_constructor& err) {
1743 return boost::shared_ptr<Region> ();
1746 return boost::shared_ptr<Region> ();
1749 boost::shared_ptr<AudioRegion>
1750 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1752 const XMLProperty* prop;
1753 boost::shared_ptr<Source> source;
1754 boost::shared_ptr<AudioSource> as;
1756 SourceList master_sources;
1757 uint32_t nchans = 1;
1760 if (node.name() != X_("Region")) {
1761 return boost::shared_ptr<AudioRegion>();
1764 if ((prop = node.property (X_("channels"))) != 0) {
1765 nchans = atoi (prop->value().c_str());
1768 if ((prop = node.property ("name")) == 0) {
1769 cerr << "no name for this region\n";
1773 if ((prop = node.property (X_("source-0"))) == 0) {
1774 if ((prop = node.property ("source")) == 0) {
1775 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1776 return boost::shared_ptr<AudioRegion>();
1780 PBD::ID s_id (prop->value());
1782 if ((source = source_by_id (s_id)) == 0) {
1783 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1784 return boost::shared_ptr<AudioRegion>();
1787 as = boost::dynamic_pointer_cast<AudioSource>(source);
1789 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1790 return boost::shared_ptr<AudioRegion>();
1793 sources.push_back (as);
1795 /* pickup other channels */
1797 for (uint32_t n=1; n < nchans; ++n) {
1798 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1799 if ((prop = node.property (buf)) != 0) {
1801 PBD::ID id2 (prop->value());
1803 if ((source = source_by_id (id2)) == 0) {
1804 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1805 return boost::shared_ptr<AudioRegion>();
1808 as = boost::dynamic_pointer_cast<AudioSource>(source);
1810 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1811 return boost::shared_ptr<AudioRegion>();
1813 sources.push_back (as);
1817 for (uint32_t n = 0; n < nchans; ++n) {
1818 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1819 if ((prop = node.property (buf)) != 0) {
1821 PBD::ID id2 (prop->value());
1823 if ((source = source_by_id (id2)) == 0) {
1824 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1825 return boost::shared_ptr<AudioRegion>();
1828 as = boost::dynamic_pointer_cast<AudioSource>(source);
1830 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1831 return boost::shared_ptr<AudioRegion>();
1833 master_sources.push_back (as);
1838 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1840 /* a final detail: this is the one and only place that we know how long missing files are */
1842 if (region->whole_file()) {
1843 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1844 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1846 sfp->set_length (region->length());
1851 if (!master_sources.empty()) {
1852 if (master_sources.size() != nchans) {
1853 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1855 region->set_master_sources (master_sources);
1863 catch (failed_constructor& err) {
1864 return boost::shared_ptr<AudioRegion>();
1868 boost::shared_ptr<MidiRegion>
1869 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1871 const XMLProperty* prop;
1872 boost::shared_ptr<Source> source;
1873 boost::shared_ptr<MidiSource> ms;
1876 if (node.name() != X_("Region")) {
1877 return boost::shared_ptr<MidiRegion>();
1880 if ((prop = node.property ("name")) == 0) {
1881 cerr << "no name for this region\n";
1885 if ((prop = node.property (X_("source-0"))) == 0) {
1886 if ((prop = node.property ("source")) == 0) {
1887 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1888 return boost::shared_ptr<MidiRegion>();
1892 PBD::ID s_id (prop->value());
1894 if ((source = source_by_id (s_id)) == 0) {
1895 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1896 return boost::shared_ptr<MidiRegion>();
1899 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1901 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1902 return boost::shared_ptr<MidiRegion>();
1905 sources.push_back (ms);
1908 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1909 /* a final detail: this is the one and only place that we know how long missing files are */
1911 if (region->whole_file()) {
1912 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1913 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1915 sfp->set_length (region->length());
1923 catch (failed_constructor& err) {
1924 return boost::shared_ptr<MidiRegion>();
1929 Session::get_sources_as_xml ()
1932 XMLNode* node = new XMLNode (X_("Sources"));
1933 Glib::Threads::Mutex::Lock lm (source_lock);
1935 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1936 node->add_child_nocopy (i->second->get_state());
1943 Session::reset_write_sources (bool mark_write_complete, bool force)
1945 boost::shared_ptr<RouteList> rl = routes.reader();
1946 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1947 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1949 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
1950 tr->reset_write_sources(mark_write_complete, force);
1951 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1957 Session::load_sources (const XMLNode& node)
1960 XMLNodeConstIterator niter;
1961 boost::shared_ptr<Source> source; /* don't need this but it stops some
1962 * versions of gcc complaining about
1963 * discarded return values.
1966 nlist = node.children();
1970 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1973 if ((source = XMLSourceFactory (**niter)) == 0) {
1974 error << _("Session: cannot create Source from XML description.") << endmsg;
1977 } catch (MissingSource& err) {
1981 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
1982 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
1983 PROGRAM_NAME) << endmsg;
1987 if (!no_questions_about_missing_files) {
1988 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1993 switch (user_choice) {
1995 /* user added a new search location, so try again */
2000 /* user asked to quit the entire session load
2005 no_questions_about_missing_files = true;
2009 no_questions_about_missing_files = true;
2016 case DataType::AUDIO:
2017 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2020 case DataType::MIDI:
2021 /* The MIDI file is actually missing so
2022 * just create a new one in the same
2023 * location. Do not announce its
2027 if (!Glib::path_is_absolute (err.path)) {
2028 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2030 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2035 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2036 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2037 /* reset ID to match the missing one */
2038 source->set_id (**niter);
2039 /* Now we can announce it */
2040 SourceFactory::SourceCreated (source);
2051 boost::shared_ptr<Source>
2052 Session::XMLSourceFactory (const XMLNode& node)
2054 if (node.name() != "Source") {
2055 return boost::shared_ptr<Source>();
2059 /* note: do peak building in another thread when loading session state */
2060 return SourceFactory::create (*this, node, true);
2063 catch (failed_constructor& err) {
2064 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2065 return boost::shared_ptr<Source>();
2070 Session::save_template (string template_name)
2072 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2076 bool absolute_path = Glib::path_is_absolute (template_name);
2078 /* directory to put the template in */
2079 std::string template_dir_path;
2081 if (!absolute_path) {
2082 std::string user_template_dir(user_template_directory());
2084 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2085 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2086 user_template_dir, g_strerror (errno)) << endmsg;
2090 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2092 template_dir_path = template_name;
2095 if (!ARDOUR::Profile->get_trx()) {
2096 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2097 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2098 template_dir_path) << endmsg;
2102 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2103 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2104 template_dir_path, g_strerror (errno)) << endmsg;
2110 std::string template_file_path;
2112 if (ARDOUR::Profile->get_trx()) {
2113 template_file_path = template_name;
2115 if (absolute_path) {
2116 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2118 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2122 SessionSaveUnderway (); /* EMIT SIGNAL */
2126 tree.set_root (&get_template());
2127 if (!tree.write (template_file_path)) {
2128 error << _("template not saved") << endmsg;
2132 if (!ARDOUR::Profile->get_trx()) {
2133 /* copy plugin state directory */
2135 std::string template_plugin_state_path (Glib::build_filename (template_dir_path, X_("plugins")));
2137 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2138 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2139 template_plugin_state_path, g_strerror (errno)) << endmsg;
2142 copy_files (plugins_dir(), template_plugin_state_path);
2145 store_recent_templates (template_file_path);
2151 Session::refresh_disk_space ()
2153 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2155 Glib::Threads::Mutex::Lock lm (space_lock);
2157 /* get freespace on every FS that is part of the session path */
2159 _total_free_4k_blocks = 0;
2160 _total_free_4k_blocks_uncertain = false;
2162 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2164 struct statfs statfsbuf;
2165 statfs (i->path.c_str(), &statfsbuf);
2167 double const scale = statfsbuf.f_bsize / 4096.0;
2169 /* See if this filesystem is read-only */
2170 struct statvfs statvfsbuf;
2171 statvfs (i->path.c_str(), &statvfsbuf);
2173 /* f_bavail can be 0 if it is undefined for whatever
2174 filesystem we are looking at; Samba shares mounted
2175 via GVFS are an example of this.
2177 if (statfsbuf.f_bavail == 0) {
2178 /* block count unknown */
2180 i->blocks_unknown = true;
2181 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2182 /* read-only filesystem */
2184 i->blocks_unknown = false;
2186 /* read/write filesystem with known space */
2187 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2188 i->blocks_unknown = false;
2191 _total_free_4k_blocks += i->blocks;
2192 if (i->blocks_unknown) {
2193 _total_free_4k_blocks_uncertain = true;
2196 #elif defined PLATFORM_WINDOWS
2197 vector<string> scanned_volumes;
2198 vector<string>::iterator j;
2199 vector<space_and_path>::iterator i;
2200 DWORD nSectorsPerCluster, nBytesPerSector,
2201 nFreeClusters, nTotalClusters;
2205 _total_free_4k_blocks = 0;
2207 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2208 strncpy (disk_drive, (*i).path.c_str(), 3);
2212 volume_found = false;
2213 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2215 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2216 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2217 i->blocks = (uint32_t)(nFreeBytes / 4096);
2219 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2220 if (0 == j->compare(disk_drive)) {
2221 volume_found = true;
2226 if (!volume_found) {
2227 scanned_volumes.push_back(disk_drive);
2228 _total_free_4k_blocks += i->blocks;
2233 if (0 == _total_free_4k_blocks) {
2234 strncpy (disk_drive, path().c_str(), 3);
2237 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2239 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2240 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2241 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2248 Session::get_best_session_directory_for_new_audio ()
2250 vector<space_and_path>::iterator i;
2251 string result = _session_dir->root_path();
2253 /* handle common case without system calls */
2255 if (session_dirs.size() == 1) {
2259 /* OK, here's the algorithm we're following here:
2261 We want to select which directory to use for
2262 the next file source to be created. Ideally,
2263 we'd like to use a round-robin process so as to
2264 get maximum performance benefits from splitting
2265 the files across multiple disks.
2267 However, in situations without much diskspace, an
2268 RR approach may end up filling up a filesystem
2269 with new files while others still have space.
2270 Its therefore important to pay some attention to
2271 the freespace in the filesystem holding each
2272 directory as well. However, if we did that by
2273 itself, we'd keep creating new files in the file
2274 system with the most space until it was as full
2275 as all others, thus negating any performance
2276 benefits of this RAID-1 like approach.
2278 So, we use a user-configurable space threshold. If
2279 there are at least 2 filesystems with more than this
2280 much space available, we use RR selection between them.
2281 If not, then we pick the filesystem with the most space.
2283 This gets a good balance between the two
2287 refresh_disk_space ();
2289 int free_enough = 0;
2291 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2292 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2297 if (free_enough >= 2) {
2298 /* use RR selection process, ensuring that the one
2302 i = last_rr_session_dir;
2305 if (++i == session_dirs.end()) {
2306 i = session_dirs.begin();
2309 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2310 SessionDirectory sdir(i->path);
2311 if (sdir.create ()) {
2313 last_rr_session_dir = i;
2318 } while (i != last_rr_session_dir);
2322 /* pick FS with the most freespace (and that
2323 seems to actually work ...)
2326 vector<space_and_path> sorted;
2327 space_and_path_ascending_cmp cmp;
2329 sorted = session_dirs;
2330 sort (sorted.begin(), sorted.end(), cmp);
2332 for (i = sorted.begin(); i != sorted.end(); ++i) {
2333 SessionDirectory sdir(i->path);
2334 if (sdir.create ()) {
2336 last_rr_session_dir = i;
2346 Session::automation_dir () const
2348 return Glib::build_filename (_path, automation_dir_name);
2352 Session::analysis_dir () const
2354 return Glib::build_filename (_path, analysis_dir_name);
2358 Session::plugins_dir () const
2360 return Glib::build_filename (_path, plugins_dir_name);
2364 Session::externals_dir () const
2366 return Glib::build_filename (_path, externals_dir_name);
2370 Session::load_bundles (XMLNode const & node)
2372 XMLNodeList nlist = node.children();
2373 XMLNodeConstIterator niter;
2377 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2378 if ((*niter)->name() == "InputBundle") {
2379 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2380 } else if ((*niter)->name() == "OutputBundle") {
2381 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2383 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2392 Session::load_route_groups (const XMLNode& node, int version)
2394 XMLNodeList nlist = node.children();
2395 XMLNodeConstIterator niter;
2399 if (version >= 3000) {
2401 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2402 if ((*niter)->name() == "RouteGroup") {
2403 RouteGroup* rg = new RouteGroup (*this, "");
2404 add_route_group (rg);
2405 rg->set_state (**niter, version);
2409 } else if (version < 3000) {
2411 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2412 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2413 RouteGroup* rg = new RouteGroup (*this, "");
2414 add_route_group (rg);
2415 rg->set_state (**niter, version);
2424 state_file_filter (const string &str, void* /*arg*/)
2426 return (str.length() > strlen(statefile_suffix) &&
2427 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2431 remove_end(string state)
2433 string statename(state);
2435 string::size_type start,end;
2436 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2437 statename = statename.substr (start+1);
2440 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2441 end = statename.length();
2444 return string(statename.substr (0, end));
2448 Session::possible_states (string path)
2450 vector<string> states;
2451 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2453 transform(states.begin(), states.end(), states.begin(), remove_end);
2455 sort (states.begin(), states.end());
2461 Session::possible_states () const
2463 return possible_states(_path);
2467 Session::add_route_group (RouteGroup* g)
2469 _route_groups.push_back (g);
2470 route_group_added (g); /* EMIT SIGNAL */
2472 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2473 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2474 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2480 Session::remove_route_group (RouteGroup& rg)
2482 list<RouteGroup*>::iterator i;
2484 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2485 _route_groups.erase (i);
2488 route_group_removed (); /* EMIT SIGNAL */
2492 /** Set a new order for our route groups, without adding or removing any.
2493 * @param groups Route group list in the new order.
2496 Session::reorder_route_groups (list<RouteGroup*> groups)
2498 _route_groups = groups;
2500 route_groups_reordered (); /* EMIT SIGNAL */
2506 Session::route_group_by_name (string name)
2508 list<RouteGroup *>::iterator i;
2510 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2511 if ((*i)->name() == name) {
2519 Session::all_route_group() const
2521 return *_all_route_group;
2525 Session::add_commands (vector<Command*> const & cmds)
2527 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2533 Session::add_command (Command* const cmd)
2535 assert (_current_trans);
2536 DEBUG_UNDO_HISTORY (
2537 string_compose ("Current Undo Transaction %1, adding command: %2",
2538 _current_trans->name (),
2540 _current_trans->add_command (cmd);
2543 Session::begin_reversible_command (const string& name)
2545 begin_reversible_command (g_quark_from_string (name.c_str ()));
2548 /** Begin a reversible command using a GQuark to identify it.
2549 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2550 * but there must be as many begin...()s as there are commit...()s.
2553 Session::begin_reversible_command (GQuark q)
2555 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2556 to hold all the commands that are committed. This keeps the order of
2557 commands correct in the history.
2560 if (_current_trans == 0) {
2561 DEBUG_UNDO_HISTORY (string_compose (
2562 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2564 /* start a new transaction */
2565 assert (_current_trans_quarks.empty ());
2566 _current_trans = new UndoTransaction();
2567 _current_trans->set_name (g_quark_to_string (q));
2569 DEBUG_UNDO_HISTORY (
2570 string_compose ("Begin Reversible Command, current transaction: %1",
2571 _current_trans->name ()));
2574 _current_trans_quarks.push_front (q);
2578 Session::abort_reversible_command ()
2580 if (_current_trans != 0) {
2581 DEBUG_UNDO_HISTORY (
2582 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2583 _current_trans->clear();
2584 delete _current_trans;
2586 _current_trans_quarks.clear();
2591 Session::commit_reversible_command (Command *cmd)
2593 assert (_current_trans);
2594 assert (!_current_trans_quarks.empty ());
2599 DEBUG_UNDO_HISTORY (
2600 string_compose ("Current Undo Transaction %1, adding command: %2",
2601 _current_trans->name (),
2603 _current_trans->add_command (cmd);
2606 DEBUG_UNDO_HISTORY (
2607 string_compose ("Commit Reversible Command, current transaction: %1",
2608 _current_trans->name ()));
2610 _current_trans_quarks.pop_front ();
2612 if (!_current_trans_quarks.empty ()) {
2613 DEBUG_UNDO_HISTORY (
2614 string_compose ("Commit Reversible Command, transaction is not "
2615 "top-level, current transaction: %1",
2616 _current_trans->name ()));
2617 /* the transaction we're committing is not the top-level one */
2621 if (_current_trans->empty()) {
2622 /* no commands were added to the transaction, so just get rid of it */
2623 DEBUG_UNDO_HISTORY (
2624 string_compose ("Commit Reversible Command, No commands were "
2625 "added to current transaction: %1",
2626 _current_trans->name ()));
2627 delete _current_trans;
2632 gettimeofday (&now, 0);
2633 _current_trans->set_timestamp (now);
2635 _history.add (_current_trans);
2640 accept_all_audio_files (const string& path, void* /*arg*/)
2642 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2646 if (!AudioFileSource::safe_audio_file_extension (path)) {
2654 accept_all_midi_files (const string& path, void* /*arg*/)
2656 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2660 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2661 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2662 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2666 accept_all_state_files (const string& path, void* /*arg*/)
2668 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2672 std::string const statefile_ext (statefile_suffix);
2673 if (path.length() >= statefile_ext.length()) {
2674 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2681 Session::find_all_sources (string path, set<string>& result)
2686 if (!tree.read (path)) {
2690 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2695 XMLNodeConstIterator niter;
2697 nlist = node->children();
2701 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2705 if ((prop = (*niter)->property (X_("type"))) == 0) {
2709 DataType type (prop->value());
2711 if ((prop = (*niter)->property (X_("name"))) == 0) {
2715 if (Glib::path_is_absolute (prop->value())) {
2716 /* external file, ignore */
2724 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2725 result.insert (found_path);
2733 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2735 vector<string> state_files;
2737 string this_snapshot_path;
2743 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2744 ripped = ripped.substr (0, ripped.length() - 1);
2747 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2749 if (state_files.empty()) {
2754 this_snapshot_path = _path;
2755 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2756 this_snapshot_path += statefile_suffix;
2758 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2760 if (exclude_this_snapshot && *i == this_snapshot_path) {
2764 if (find_all_sources (*i, result) < 0) {
2772 struct RegionCounter {
2773 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2774 AudioSourceList::iterator iter;
2775 boost::shared_ptr<Region> region;
2778 RegionCounter() : count (0) {}
2782 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2784 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2785 return r.get_value_or (1);
2789 Session::cleanup_regions ()
2791 bool removed = false;
2792 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2794 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2796 uint32_t used = playlists->region_use_count (i->second);
2798 if (used == 0 && !i->second->automatic ()) {
2800 RegionFactory::map_remove (i->second);
2805 // re-check to remove parent references of compound regions
2806 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2807 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2810 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2811 if (0 == playlists->region_use_count (i->second)) {
2812 RegionFactory::map_remove (i->second);
2817 /* dump the history list */
2824 Session::cleanup_sources (CleanupReport& rep)
2826 // FIXME: needs adaptation to midi
2828 vector<boost::shared_ptr<Source> > dead_sources;
2831 vector<string> candidates;
2832 vector<string> unused;
2833 set<string> all_sources;
2842 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2844 /* consider deleting all unused playlists */
2846 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2851 /* sync the "all regions" property of each playlist with its current state
2854 playlists->sync_all_regions_with_regions ();
2856 /* find all un-used sources */
2861 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2863 SourceMap::iterator tmp;
2868 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2872 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2873 dead_sources.push_back (i->second);
2874 i->second->drop_references ();
2880 /* build a list of all the possible audio directories for the session */
2882 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2883 SessionDirectory sdir ((*i).path);
2884 asp += sdir.sound_path();
2886 audio_path += asp.to_string();
2889 /* build a list of all the possible midi directories for the session */
2891 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2892 SessionDirectory sdir ((*i).path);
2893 msp += sdir.midi_path();
2895 midi_path += msp.to_string();
2897 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2898 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2900 /* find all sources, but don't use this snapshot because the
2901 state file on disk still references sources we may have already
2905 find_all_sources_across_snapshots (all_sources, true);
2907 /* add our current source list
2910 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2911 boost::shared_ptr<FileSource> fs;
2912 SourceMap::iterator tmp = i;
2915 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2917 if (!fs->is_stub()) {
2919 if (playlists->source_use_count (fs) != 0) {
2920 all_sources.insert (fs->path());
2923 /* we might not remove this source from disk, because it may be used
2924 by other snapshots, but its not being used in this version
2925 so lets get rid of it now, along with any representative regions
2929 RegionFactory::remove_regions_using_source (i->second);
2931 // also remove source from all_sources
2933 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
2934 spath = Glib::path_get_basename (*j);
2935 if (spath == i->second->name()) {
2936 all_sources.erase (j);
2949 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2954 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2956 tmppath1 = canonical_path (spath);
2957 tmppath2 = canonical_path ((*i));
2959 if (tmppath1 == tmppath2) {
2966 unused.push_back (spath);
2970 /* now try to move all unused files into the "dead" directory(ies) */
2972 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2973 struct stat statbuf;
2977 /* don't move the file across filesystems, just
2978 stick it in the `dead_dir_name' directory
2979 on whichever filesystem it was already on.
2982 if ((*x).find ("/sounds/") != string::npos) {
2984 /* old school, go up 1 level */
2986 newpath = Glib::path_get_dirname (*x); // "sounds"
2987 newpath = Glib::path_get_dirname (newpath); // "session-name"
2991 /* new school, go up 4 levels */
2993 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2994 newpath = Glib::path_get_dirname (newpath); // "session-name"
2995 newpath = Glib::path_get_dirname (newpath); // "interchange"
2996 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2999 newpath = Glib::build_filename (newpath, dead_dir_name);
3001 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3002 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3006 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3008 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3010 /* the new path already exists, try versioning */
3012 char buf[PATH_MAX+1];
3016 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3019 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3020 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3024 if (version == 999) {
3025 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3029 newpath = newpath_v;
3034 /* it doesn't exist, or we can't read it or something */
3038 stat ((*x).c_str(), &statbuf);
3040 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3041 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3042 (*x), newpath, strerror (errno))
3047 /* see if there an easy to find peakfile for this file, and remove it.
3050 string base = basename_nosuffix (*x);
3051 base += "%A"; /* this is what we add for the channel suffix of all native files,
3052 or for the first channel of embedded files. it will miss
3053 some peakfiles for other channels
3055 string peakpath = peak_path (base);
3057 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3058 if (::g_unlink (peakpath.c_str()) != 0) {
3059 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3060 peakpath, _path, strerror (errno))
3062 /* try to back out */
3063 ::rename (newpath.c_str(), _path.c_str());
3068 rep.paths.push_back (*x);
3069 rep.space += statbuf.st_size;
3072 /* dump the history list */
3076 /* save state so we don't end up a session file
3077 referring to non-existent sources.
3084 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3090 Session::cleanup_trash_sources (CleanupReport& rep)
3092 // FIXME: needs adaptation for MIDI
3094 vector<space_and_path>::iterator i;
3100 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3102 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3104 clear_directory (dead_dir, &rep.space, &rep.paths);
3111 Session::set_dirty ()
3113 /* never mark session dirty during loading */
3115 if (_state_of_the_state & Loading) {
3119 bool was_dirty = dirty();
3121 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3125 DirtyChanged(); /* EMIT SIGNAL */
3131 Session::set_clean ()
3133 bool was_dirty = dirty();
3135 _state_of_the_state = Clean;
3139 DirtyChanged(); /* EMIT SIGNAL */
3144 Session::set_deletion_in_progress ()
3146 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3150 Session::clear_deletion_in_progress ()
3152 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3156 Session::add_controllable (boost::shared_ptr<Controllable> c)
3158 /* this adds a controllable to the list managed by the Session.
3159 this is a subset of those managed by the Controllable class
3160 itself, and represents the only ones whose state will be saved
3161 as part of the session.
3164 Glib::Threads::Mutex::Lock lm (controllables_lock);
3165 controllables.insert (c);
3168 struct null_deleter { void operator()(void const *) const {} };
3171 Session::remove_controllable (Controllable* c)
3173 if (_state_of_the_state & Deletion) {
3177 Glib::Threads::Mutex::Lock lm (controllables_lock);
3179 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3181 if (x != controllables.end()) {
3182 controllables.erase (x);
3186 boost::shared_ptr<Controllable>
3187 Session::controllable_by_id (const PBD::ID& id)
3189 Glib::Threads::Mutex::Lock lm (controllables_lock);
3191 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3192 if ((*i)->id() == id) {
3197 return boost::shared_ptr<Controllable>();
3200 boost::shared_ptr<Controllable>
3201 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3203 boost::shared_ptr<Controllable> c;
3204 boost::shared_ptr<Route> r;
3206 switch (desc.top_level_type()) {
3207 case ControllableDescriptor::NamedRoute:
3209 std::string str = desc.top_level_name();
3210 if (str == "Master" || str == "master") {
3212 } else if (str == "control" || str == "listen") {
3215 r = route_by_name (desc.top_level_name());
3220 case ControllableDescriptor::RemoteControlID:
3221 r = route_by_remote_id (desc.rid());
3229 switch (desc.subtype()) {
3230 case ControllableDescriptor::Gain:
3231 c = r->gain_control ();
3234 case ControllableDescriptor::Trim:
3235 c = r->trim()->gain_control ();
3238 case ControllableDescriptor::Solo:
3239 c = r->solo_control();
3242 case ControllableDescriptor::Mute:
3243 c = r->mute_control();
3246 case ControllableDescriptor::Recenable:
3248 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3251 c = t->rec_enable_control ();
3256 case ControllableDescriptor::PanDirection:
3258 c = r->pannable()->pan_azimuth_control;
3262 case ControllableDescriptor::PanWidth:
3264 c = r->pannable()->pan_width_control;
3268 case ControllableDescriptor::PanElevation:
3270 c = r->pannable()->pan_elevation_control;
3274 case ControllableDescriptor::Balance:
3275 /* XXX simple pan control */
3278 case ControllableDescriptor::PluginParameter:
3280 uint32_t plugin = desc.target (0);
3281 uint32_t parameter_index = desc.target (1);
3283 /* revert to zero based counting */
3289 if (parameter_index > 0) {
3293 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3296 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3297 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3302 case ControllableDescriptor::SendGain:
3304 uint32_t send = desc.target (0);
3306 /* revert to zero-based counting */
3312 boost::shared_ptr<Processor> p = r->nth_send (send);
3315 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3316 boost::shared_ptr<Amp> a = s->amp();
3319 c = s->amp()->gain_control();
3326 /* relax and return a null pointer */
3334 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3337 Stateful::add_instant_xml (node, _path);
3340 if (write_to_config) {
3341 Config->add_instant_xml (node);
3346 Session::instant_xml (const string& node_name)
3348 return Stateful::instant_xml (node_name, _path);
3352 Session::save_history (string snapshot_name)
3360 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3361 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3365 if (snapshot_name.empty()) {
3366 snapshot_name = _current_snapshot_name;
3369 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3370 const string backup_filename = history_filename + backup_suffix;
3371 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3372 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3374 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3375 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3376 error << _("could not backup old history file, current history not saved") << endmsg;
3381 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3383 if (!tree.write (xml_path))
3385 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3387 if (g_remove (xml_path.c_str()) != 0) {
3388 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3389 xml_path, g_strerror (errno)) << endmsg;
3391 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3392 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3393 backup_path, g_strerror (errno)) << endmsg;
3403 Session::restore_history (string snapshot_name)
3407 if (snapshot_name.empty()) {
3408 snapshot_name = _current_snapshot_name;
3411 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3412 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3414 info << "Loading history from " << xml_path << endmsg;
3416 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3417 info << string_compose (_("%1: no history file \"%2\" for this session."),
3418 _name, xml_path) << endmsg;
3422 if (!tree.read (xml_path)) {
3423 error << string_compose (_("Could not understand session history file \"%1\""),
3424 xml_path) << endmsg;
3431 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3434 UndoTransaction* ut = new UndoTransaction ();
3437 ut->set_name(t->property("name")->value());
3438 stringstream ss(t->property("tv-sec")->value());
3440 ss.str(t->property("tv-usec")->value());
3442 ut->set_timestamp(tv);
3444 for (XMLNodeConstIterator child_it = t->children().begin();
3445 child_it != t->children().end(); child_it++)
3447 XMLNode *n = *child_it;
3450 if (n->name() == "MementoCommand" ||
3451 n->name() == "MementoUndoCommand" ||
3452 n->name() == "MementoRedoCommand") {
3454 if ((c = memento_command_factory(n))) {
3458 } else if (n->name() == "NoteDiffCommand") {
3459 PBD::ID id (n->property("midi-source")->value());
3460 boost::shared_ptr<MidiSource> midi_source =
3461 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3463 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3465 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3468 } else if (n->name() == "SysExDiffCommand") {
3470 PBD::ID id (n->property("midi-source")->value());
3471 boost::shared_ptr<MidiSource> midi_source =
3472 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3474 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3476 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3479 } else if (n->name() == "PatchChangeDiffCommand") {
3481 PBD::ID id (n->property("midi-source")->value());
3482 boost::shared_ptr<MidiSource> midi_source =
3483 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3485 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3487 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3490 } else if (n->name() == "StatefulDiffCommand") {
3491 if ((c = stateful_diff_command_factory (n))) {
3492 ut->add_command (c);
3495 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3506 Session::config_changed (std::string p, bool ours)
3512 if (p == "seamless-loop") {
3514 } else if (p == "rf-speed") {
3516 } else if (p == "auto-loop") {
3518 } else if (p == "auto-input") {
3520 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3521 /* auto-input only makes a difference if we're rolling */
3522 set_track_monitor_input_status (!config.get_auto_input());
3525 } else if (p == "punch-in") {
3529 if ((location = _locations->auto_punch_location()) != 0) {
3531 if (config.get_punch_in ()) {
3532 replace_event (SessionEvent::PunchIn, location->start());
3534 remove_event (location->start(), SessionEvent::PunchIn);
3538 } else if (p == "punch-out") {
3542 if ((location = _locations->auto_punch_location()) != 0) {
3544 if (config.get_punch_out()) {
3545 replace_event (SessionEvent::PunchOut, location->end());
3547 clear_events (SessionEvent::PunchOut);
3551 } else if (p == "edit-mode") {
3553 Glib::Threads::Mutex::Lock lm (playlists->lock);
3555 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3556 (*i)->set_edit_mode (Config->get_edit_mode ());
3559 } else if (p == "use-video-sync") {
3561 waiting_for_sync_offset = config.get_use_video_sync();
3563 } else if (p == "mmc-control") {
3565 //poke_midi_thread ();
3567 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3569 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3571 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3573 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3575 } else if (p == "midi-control") {
3577 //poke_midi_thread ();
3579 } else if (p == "raid-path") {
3581 setup_raid_path (config.get_raid_path());
3583 } else if (p == "timecode-format") {
3587 } else if (p == "video-pullup") {
3591 } else if (p == "seamless-loop") {
3593 if (play_loop && transport_rolling()) {
3594 // to reset diskstreams etc
3595 request_play_loop (true);
3598 } else if (p == "rf-speed") {
3600 cumulative_rf_motion = 0;
3603 } else if (p == "click-sound") {
3605 setup_click_sounds (1);
3607 } else if (p == "click-emphasis-sound") {
3609 setup_click_sounds (-1);
3611 } else if (p == "clicking") {
3613 if (Config->get_clicking()) {
3614 if (_click_io && click_data) { // don't require emphasis data
3621 } else if (p == "click-gain") {
3624 _click_gain->set_gain (Config->get_click_gain(), this);
3627 } else if (p == "send-mtc") {
3629 if (Config->get_send_mtc ()) {
3630 /* mark us ready to send */
3631 next_quarter_frame_to_send = 0;
3634 } else if (p == "send-mmc") {
3636 _mmc->enable_send (Config->get_send_mmc ());
3638 } else if (p == "midi-feedback") {
3640 session_midi_feedback = Config->get_midi_feedback();
3642 } else if (p == "jack-time-master") {
3644 engine().reset_timebase ();
3646 } else if (p == "native-file-header-format") {
3648 if (!first_file_header_format_reset) {
3649 reset_native_file_format ();
3652 first_file_header_format_reset = false;
3654 } else if (p == "native-file-data-format") {
3656 if (!first_file_data_format_reset) {
3657 reset_native_file_format ();
3660 first_file_data_format_reset = false;
3662 } else if (p == "external-sync") {
3663 if (!config.get_external_sync()) {
3664 drop_sync_source ();
3666 switch_to_sync_source (Config->get_sync_source());
3668 } else if (p == "denormal-model") {
3670 } else if (p == "history-depth") {
3671 set_history_depth (Config->get_history_depth());
3672 } else if (p == "remote-model") {
3673 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3676 } else if (p == "initial-program-change") {
3678 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3681 buf[0] = MIDI::program; // channel zero by default
3682 buf[1] = (Config->get_initial_program_change() & 0x7f);
3684 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3686 } else if (p == "solo-mute-override") {
3687 // catch_up_on_solo_mute_override ();
3688 } else if (p == "listen-position" || p == "pfl-position") {
3689 listen_position_changed ();
3690 } else if (p == "solo-control-is-listen-control") {
3691 solo_control_mode_changed ();
3692 } else if (p == "solo-mute-gain") {
3693 _solo_cut_control->Changed();
3694 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3695 last_timecode_valid = false;
3696 } else if (p == "playback-buffer-seconds") {
3697 AudioSource::allocate_working_buffers (frame_rate());
3698 } else if (p == "ltc-source-port") {
3699 reconnect_ltc_input ();
3700 } else if (p == "ltc-sink-port") {
3701 reconnect_ltc_output ();
3702 } else if (p == "timecode-generator-offset") {
3703 ltc_tx_parse_offset();
3704 } else if (p == "auto-return-target-list") {
3705 follow_playhead_priority ();
3712 Session::set_history_depth (uint32_t d)
3714 _history.set_depth (d);
3718 Session::load_diskstreams_2X (XMLNode const & node, int)
3721 XMLNodeConstIterator citer;
3723 clist = node.children();
3725 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3728 /* diskstreams added automatically by DiskstreamCreated handler */
3729 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3730 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3731 _diskstreams_2X.push_back (dsp);
3733 error << _("Session: unknown diskstream type in XML") << endmsg;
3737 catch (failed_constructor& err) {
3738 error << _("Session: could not load diskstream via XML state") << endmsg;
3746 /** Connect things to the MMC object */
3748 Session::setup_midi_machine_control ()
3750 _mmc = new MIDI::MachineControl;
3751 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3753 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3754 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3755 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3756 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3757 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3758 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3759 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3760 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3761 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3762 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3763 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3764 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3765 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3767 /* also handle MIDI SPP because its so common */
3769 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3770 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3771 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3774 boost::shared_ptr<Controllable>
3775 Session::solo_cut_control() const
3777 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3778 controls in Ardour that currently get presented to the user in the GUI that require
3779 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3781 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3782 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3786 return _solo_cut_control;
3790 Session::rename (const std::string& new_name)
3792 string legal_name = legalize_for_path (new_name);
3798 string const old_sources_root = _session_dir->sources_root();
3800 if (!_writable || (_state_of_the_state & CannotSave)) {
3801 error << _("Cannot rename read-only session.") << endmsg;
3802 return 0; // don't show "messed up" warning
3804 if (record_status() == Recording) {
3805 error << _("Cannot rename session while recording") << endmsg;
3806 return 0; // don't show "messed up" warning
3809 StateProtector stp (this);
3814 * interchange subdirectory
3818 * Backup files are left unchanged and not renamed.
3821 /* Windows requires that we close all files before attempting the
3822 * rename. This works on other platforms, but isn't necessary there.
3823 * Leave it in place for all platforms though, since it may help
3824 * catch issues that could arise if the way Source files work ever
3825 * change (since most developers are not using Windows).
3828 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3829 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3835 /* pass one: not 100% safe check that the new directory names don't
3839 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3843 /* this is a stupid hack because Glib::path_get_dirname() is
3844 * lexical-only, and so passing it /a/b/c/ gives a different
3845 * result than passing it /a/b/c ...
3848 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3849 oldstr = oldstr.substr (0, oldstr.length() - 1);
3852 string base = Glib::path_get_dirname (oldstr);
3854 newstr = Glib::build_filename (base, legal_name);
3856 cerr << "Looking for " << newstr << endl;
3858 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3859 cerr << " exists\n";
3868 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3874 /* this is a stupid hack because Glib::path_get_dirname() is
3875 * lexical-only, and so passing it /a/b/c/ gives a different
3876 * result than passing it /a/b/c ...
3879 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3880 oldstr = oldstr.substr (0, oldstr.length() - 1);
3883 string base = Glib::path_get_dirname (oldstr);
3884 newstr = Glib::build_filename (base, legal_name);
3886 cerr << "for " << oldstr << " new dir = " << newstr << endl;
3888 cerr << "Rename " << oldstr << " => " << newstr << endl;
3889 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3890 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3891 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3895 /* Reset path in "session dirs" */
3900 /* reset primary SessionDirectory object */
3903 (*_session_dir) = newstr;
3908 /* now rename directory below session_dir/interchange */
3910 string old_interchange_dir;
3911 string new_interchange_dir;
3913 /* use newstr here because we renamed the path
3914 * (folder/directory) that used to be oldstr to newstr above
3917 v.push_back (newstr);
3918 v.push_back (interchange_dir_name);
3919 v.push_back (Glib::path_get_basename (oldstr));
3921 old_interchange_dir = Glib::build_filename (v);
3924 v.push_back (newstr);
3925 v.push_back (interchange_dir_name);
3926 v.push_back (legal_name);
3928 new_interchange_dir = Glib::build_filename (v);
3930 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
3932 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
3933 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
3934 old_interchange_dir, new_interchange_dir,
3937 error << string_compose (_("renaming %s as %2 failed (%3)"),
3938 old_interchange_dir, new_interchange_dir,
3947 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
3948 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
3950 cerr << "Rename " << oldstr << " => " << newstr << endl;
3952 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3953 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3954 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3960 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
3962 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3963 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
3965 cerr << "Rename " << oldstr << " => " << newstr << endl;
3967 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3968 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3969 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3974 /* remove old name from recent sessions */
3975 remove_recent_sessions (_path);
3978 /* update file source paths */
3980 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3981 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3983 string p = fs->path ();
3984 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3986 SourceFactory::setup_peakfile(i->second, true);
3990 _current_snapshot_name = new_name;
3995 /* save state again to get everything just right */
3997 save_state (_current_snapshot_name);
3999 /* add to recent sessions */
4001 store_recent_sessions (new_name, _path);
4007 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4009 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4013 if (!tree.read (xmlpath)) {
4021 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4024 bool found_sr = false;
4025 bool found_data_format = false;
4027 if (get_session_info_from_path (tree, xmlpath)) {
4033 const XMLProperty* prop;
4034 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
4035 sample_rate = atoi (prop->value());
4039 const XMLNodeList& children (tree.root()->children());
4040 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4041 const XMLNode* child = *c;
4042 if (child->name() == "Config") {
4043 const XMLNodeList& options (child->children());
4044 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4045 const XMLNode* option = *oc;
4046 const XMLProperty* name = option->property("name");
4052 if (name->value() == "native-file-data-format") {
4053 const XMLProperty* value = option->property ("value");
4055 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4057 found_data_format = true;
4063 if (found_data_format) {
4068 return !(found_sr && found_data_format); // zero if they are both found
4071 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4072 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4075 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4079 SourcePathMap source_path_map;
4081 boost::shared_ptr<AudioFileSource> afs;
4086 Glib::Threads::Mutex::Lock lm (source_lock);
4088 cerr << " total sources = " << sources.size();
4090 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4091 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4097 if (fs->within_session()) {
4101 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4102 source_path_map[fs->path()].push_back (fs);
4104 SeveralFileSources v;
4106 source_path_map.insert (make_pair (fs->path(), v));
4112 cerr << " fsources = " << total << endl;
4114 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4116 /* tell caller where we are */
4118 string old_path = i->first;
4120 callback (n, total, old_path);
4122 cerr << old_path << endl;
4126 switch (i->second.front()->type()) {
4127 case DataType::AUDIO:
4128 new_path = new_audio_source_path_for_embedded (old_path);
4131 case DataType::MIDI:
4132 /* XXX not implemented yet */
4136 if (new_path.empty()) {
4140 cerr << "Move " << old_path << " => " << new_path << endl;
4142 if (!copy_file (old_path, new_path)) {
4143 cerr << "failed !\n";
4147 /* make sure we stop looking in the external
4148 dir/folder. Remember, this is an all-or-nothing
4149 operations, it doesn't merge just some files.
4151 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4153 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4154 (*f)->set_path (new_path);
4159 save_state ("", false, false);
4165 bool accept_all_files (string const &, void *)
4171 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4173 /* 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.
4178 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4180 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4182 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4184 v.push_back (new_session_folder); /* full path */
4185 v.push_back (interchange_dir_name);
4186 v.push_back (new_session_path); /* just one directory/folder */
4187 v.push_back (typedir);
4188 v.push_back (Glib::path_get_basename (old_path));
4190 return Glib::build_filename (v);
4194 Session::save_as (SaveAs& saveas)
4196 vector<string> files;
4197 string current_folder = Glib::path_get_dirname (_path);
4198 string new_folder = legalize_for_path (saveas.new_name);
4199 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4200 int64_t total_bytes = 0;
4204 int32_t internal_file_cnt = 0;
4206 vector<string> do_not_copy_extensions;
4207 do_not_copy_extensions.push_back (statefile_suffix);
4208 do_not_copy_extensions.push_back (pending_suffix);
4209 do_not_copy_extensions.push_back (backup_suffix);
4210 do_not_copy_extensions.push_back (temp_suffix);
4211 do_not_copy_extensions.push_back (history_suffix);
4213 /* get total size */
4215 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4217 /* need to clear this because
4218 * find_files_matching_filter() is cumulative
4223 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4225 all += files.size();
4227 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4229 g_stat ((*i).c_str(), &gsb);
4230 total_bytes += gsb.st_size;
4234 /* save old values so we can switch back if we are not switching to the new session */
4236 string old_path = _path;
4237 string old_name = _name;
4238 string old_snapshot = _current_snapshot_name;
4239 string old_sd = _session_dir->root_path();
4240 vector<string> old_search_path[DataType::num_types];
4241 string old_config_search_path[DataType::num_types];
4243 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4244 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4245 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4246 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4248 /* switch session directory */
4250 (*_session_dir) = to_dir;
4252 /* create new tree */
4254 if (!_session_dir->create()) {
4255 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4260 /* copy all relevant files. Find each location in session_dirs,
4261 * and copy files from there to target.
4264 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4266 /* need to clear this because
4267 * find_files_matching_filter() is cumulative
4272 const size_t prefix_len = (*sd).path.size();
4274 /* Work just on the files within this session dir */
4276 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4278 /* add dir separator to protect against collisions with
4279 * track names (e.g. track named "audiofiles" or
4283 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4284 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4285 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4287 /* copy all the files. Handling is different for media files
4288 than others because of the *silly* subtree we have below the interchange
4289 folder. That really was a bad idea, but I'm not fixing it as part of
4290 implementing ::save_as().
4293 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4295 std::string from = *i;
4298 string filename = Glib::path_get_basename (from);
4299 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4300 if (filename == ".DS_STORE") {
4305 if (from.find (audiofile_dir_string) != string::npos) {
4307 /* audio file: only copy if asked */
4309 if (saveas.include_media && saveas.copy_media) {
4311 string to = make_new_media_path (*i, to_dir, new_folder);
4313 info << "media file copying from " << from << " to " << to << endmsg;
4315 if (!copy_file (from, to)) {
4316 throw Glib::FileError (Glib::FileError::IO_ERROR,
4317 string_compose(_("\ncopying \"%1\" failed !"), from));
4321 /* we found media files inside the session folder */
4323 internal_file_cnt++;
4325 } else if (from.find (midifile_dir_string) != string::npos) {
4327 /* midi file: always copy unless
4328 * creating an empty new session
4331 if (saveas.include_media) {
4333 string to = make_new_media_path (*i, to_dir, new_folder);
4335 info << "media file copying from " << from << " to " << to << endmsg;
4337 if (!copy_file (from, to)) {
4338 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4342 /* we found media files inside the session folder */
4344 internal_file_cnt++;
4346 } else if (from.find (analysis_dir_string) != string::npos) {
4348 /* make sure analysis dir exists in
4349 * new session folder, but we're not
4350 * copying analysis files here, see
4354 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4359 /* normal non-media file. Don't copy state, history, etc.
4362 bool do_copy = true;
4364 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4365 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4366 /* end of filename matches extension, do not copy file */
4372 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4373 /* don't copy peakfiles if
4374 * we're not copying media
4380 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4382 info << "attempting to make directory/folder " << to << endmsg;
4384 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4385 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4388 info << "attempting to copy " << from << " to " << to << endmsg;
4390 if (!copy_file (from, to)) {
4391 throw Glib::FileError (Glib::FileError::IO_ERROR,
4392 string_compose(_("\ncopying \"%1\" failed !"), from));
4397 /* measure file size even if we're not going to copy so that our Progress
4398 signals are correct, since we included these do-not-copy files
4399 in the computation of the total size and file count.
4403 g_stat (from.c_str(), &gsb);
4404 copied += gsb.st_size;
4407 double fraction = (double) copied / total_bytes;
4409 bool keep_going = true;
4411 if (saveas.copy_media) {
4413 /* no need or expectation of this if
4414 * media is not being copied, because
4415 * it will be fast(ish).
4418 /* tell someone "X percent, file M of N"; M is one-based */
4420 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4428 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4434 /* copy optional folders, if any */
4436 string old = plugins_dir ();
4437 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4438 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4439 copy_files (old, newdir);
4442 old = externals_dir ();
4443 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4444 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4445 copy_files (old, newdir);
4448 old = automation_dir ();
4449 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4450 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4451 copy_files (old, newdir);
4454 if (saveas.include_media) {
4456 if (saveas.copy_media) {
4457 #ifndef PLATFORM_WINDOWS
4458 /* There are problems with analysis files on
4459 * Windows, because they used a colon in their
4460 * names as late as 4.0. Colons are not legal
4461 * under Windows even if NTFS allows them.
4463 * This is a tricky problem to solve so for
4464 * just don't copy these files. They will be
4465 * regenerated as-needed anyway, subject to the
4466 * existing issue that the filenames will be
4467 * rejected by Windows, which is a separate
4468 * problem (though related).
4471 /* only needed if we are copying media, since the
4472 * analysis data refers to media data
4475 old = analysis_dir ();
4476 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4477 string newdir = Glib::build_filename (to_dir, "analysis");
4478 copy_files (old, newdir);
4480 #endif /* PLATFORM_WINDOWS */
4486 _current_snapshot_name = saveas.new_name;
4487 _name = saveas.new_name;
4489 if (saveas.include_media && !saveas.copy_media) {
4491 /* reset search paths of the new session (which we're pretending to be right now) to
4492 include the original session search path, so we can still find all audio.
4495 if (internal_file_cnt) {
4496 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4497 ensure_search_path_includes (*s, DataType::AUDIO);
4498 cerr << "be sure to include " << *s << " for audio" << endl;
4501 /* we do not do this for MIDI because we copy
4502 all MIDI files if saveas.include_media is
4508 bool was_dirty = dirty ();
4510 save_state ("", false, false, !saveas.include_media);
4511 save_default_options ();
4513 if (saveas.copy_media && saveas.copy_external) {
4514 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4515 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4519 saveas.final_session_folder_name = _path;
4521 store_recent_sessions (_name, _path);
4523 if (!saveas.switch_to) {
4525 /* switch back to the way things were */
4529 _current_snapshot_name = old_snapshot;
4531 (*_session_dir) = old_sd;
4537 if (internal_file_cnt) {
4538 /* reset these to their original values */
4539 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4540 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4545 /* prune session dirs, and update disk space statistics
4550 session_dirs.clear ();
4551 session_dirs.push_back (sp);
4552 refresh_disk_space ();
4554 /* ensure that all existing tracks reset their current capture source paths
4556 reset_write_sources (true, true);
4558 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4559 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4562 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4563 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4569 if (fs->within_session()) {
4570 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4571 fs->set_path (newpath);
4576 } catch (Glib::FileError& e) {
4578 saveas.failure_message = e.what();
4580 /* recursively remove all the directories */
4582 remove_directory (to_dir);
4590 saveas.failure_message = _("unknown reason");
4592 /* recursively remove all the directories */
4594 remove_directory (to_dir);