Move panner bypass state up to the PannerShell so that it is preserved even when...
[ardour2.git] / libs / ardour / session_state.cc
blobc8323047ebc05829baa361fa57aae6820bbbeb7f
1 /*
2 Copyright (C) 1999-2002 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #ifdef WAF_BUILD
22 #include "libardour-config.h"
23 #endif
25 #include <stdint.h>
27 #include <algorithm>
28 #include <fstream>
29 #include <string>
30 #include <cerrno>
33 #include <cstdio> /* snprintf(3) ... grrr */
34 #include <cmath>
35 #include <unistd.h>
36 #include <sys/stat.h>
37 #include <climits>
38 #include <fcntl.h>
39 #include <poll.h>
40 #include <signal.h>
41 #include <sys/mman.h>
42 #include <sys/time.h>
44 #ifdef HAVE_SYS_VFS_H
45 #include <sys/vfs.h>
46 #else
47 #include <sys/param.h>
48 #include <sys/mount.h>
49 #endif
51 #include <glib.h>
53 #include <glibmm.h>
54 #include <glibmm/thread.h>
56 #include "midi++/mmc.h"
57 #include "midi++/port.h"
58 #include "midi++/manager.h"
60 #include "pbd/boost_debug.h"
61 #include "pbd/basename.h"
62 #include "pbd/controllable_descriptor.h"
63 #include "pbd/enumwriter.h"
64 #include "pbd/error.h"
65 #include "pbd/pathscanner.h"
66 #include "pbd/pthread_utils.h"
67 #include "pbd/search_path.h"
68 #include "pbd/stacktrace.h"
69 #include "pbd/convert.h"
70 #include "pbd/clear_dir.h"
72 #include "ardour/amp.h"
73 #include "ardour/audio_diskstream.h"
74 #include "ardour/audio_playlist_source.h"
75 #include "ardour/audio_track.h"
76 #include "ardour/audioengine.h"
77 #include "ardour/audiofilesource.h"
78 #include "ardour/audioplaylist.h"
79 #include "ardour/audioregion.h"
80 #include "ardour/auditioner.h"
81 #include "ardour/automation_control.h"
82 #include "ardour/buffer.h"
83 #include "ardour/butler.h"
84 #include "ardour/configuration.h"
85 #include "ardour/control_protocol_manager.h"
86 #include "ardour/crossfade.h"
87 #include "ardour/cycle_timer.h"
88 #include "ardour/directory_names.h"
89 #include "ardour/filename_extensions.h"
90 #include "ardour/io_processor.h"
91 #include "ardour/location.h"
92 #include "ardour/midi_diskstream.h"
93 #include "ardour/midi_patch_manager.h"
94 #include "ardour/midi_playlist.h"
95 #include "ardour/midi_region.h"
96 #include "ardour/midi_source.h"
97 #include "ardour/midi_track.h"
98 #include "ardour/named_selection.h"
99 #include "ardour/pannable.h"
100 #include "ardour/processor.h"
101 #include "ardour/port.h"
102 #include "ardour/proxy_controllable.h"
103 #include "ardour/region_factory.h"
104 #include "ardour/route_group.h"
105 #include "ardour/send.h"
106 #include "ardour/session.h"
107 #include "ardour/session_directory.h"
108 #include "ardour/session_metadata.h"
109 #include "ardour/session_state_utils.h"
110 #include "ardour/session_playlists.h"
111 #include "ardour/session_utils.h"
112 #include "ardour/silentfilesource.h"
113 #include "ardour/slave.h"
114 #include "ardour/smf_source.h"
115 #include "ardour/sndfile_helpers.h"
116 #include "ardour/sndfilesource.h"
117 #include "ardour/source_factory.h"
118 #include "ardour/template_utils.h"
119 #include "ardour/tempo.h"
120 #include "ardour/ticker.h"
121 #include "ardour/user_bundle.h"
122 #include "ardour/utils.h"
123 #include "ardour/utils.h"
124 #include "ardour/version.h"
125 #include "ardour/playlist_factory.h"
127 #include "control_protocol/control_protocol.h"
129 #include "i18n.h"
130 #include <locale.h>
132 using namespace std;
133 using namespace ARDOUR;
134 using namespace PBD;
137 void
138 Session::first_stage_init (string fullpath, string snapshot_name)
140 if (fullpath.length() == 0) {
141 destroy ();
142 throw failed_constructor();
145 char buf[PATH_MAX+1];
146 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
147 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
148 destroy ();
149 throw failed_constructor();
152 _path = string(buf);
154 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
155 _path += G_DIR_SEPARATOR;
158 /* these two are just provisional settings. set_state()
159 will likely override them.
162 _name = _current_snapshot_name = snapshot_name;
164 set_history_depth (Config->get_history_depth());
166 _current_frame_rate = _engine.frame_rate ();
167 _nominal_frame_rate = _current_frame_rate;
168 _base_frame_rate = _current_frame_rate;
170 _tempo_map = new TempoMap (_current_frame_rate);
171 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
174 _non_soloed_outs_muted = false;
175 _listen_cnt = 0;
176 _solo_isolated_cnt = 0;
177 g_atomic_int_set (&processing_prohibited, 0);
178 _transport_speed = 0;
179 _last_transport_speed = 0;
180 _target_transport_speed = 0;
181 auto_play_legal = false;
182 transport_sub_state = 0;
183 _transport_frame = 0;
184 _requested_return_frame = -1;
185 _session_range_location = 0;
186 g_atomic_int_set (&_record_status, Disabled);
187 loop_changing = false;
188 play_loop = false;
189 have_looped = false;
190 _last_roll_location = 0;
191 _last_roll_or_reversal_location = 0;
192 _last_record_location = 0;
193 pending_locate_frame = 0;
194 pending_locate_roll = false;
195 pending_locate_flush = false;
196 state_was_pending = false;
197 set_next_event ();
198 outbound_mtc_timecode_frame = 0;
199 next_quarter_frame_to_send = -1;
200 current_block_size = 0;
201 solo_update_disabled = false;
202 _have_captured = false;
203 _worst_output_latency = 0;
204 _worst_input_latency = 0;
205 _worst_track_latency = 0;
206 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
207 _was_seamless = Config->get_seamless_loop ();
208 _slave = 0;
209 _send_qf_mtc = false;
210 _pframes_since_last_mtc = 0;
211 g_atomic_int_set (&_playback_load, 100);
212 g_atomic_int_set (&_capture_load, 100);
213 _play_range = false;
214 _exporting = false;
215 pending_abort = false;
216 destructive_index = 0;
217 first_file_data_format_reset = true;
218 first_file_header_format_reset = true;
219 post_export_sync = false;
220 midi_control_ui = 0;
221 _step_editors = 0;
222 no_questions_about_missing_files = false;
223 _speakers.reset (new Speakers);
225 AudioDiskstream::allocate_working_buffers();
227 /* default short fade = 15ms */
229 Crossfade::set_short_xfade_length ((framecnt_t) floor (config.get_short_xfade_seconds() * frame_rate()));
230 SndFileSource::setup_standard_crossfades (*this, frame_rate());
232 last_mmc_step.tv_sec = 0;
233 last_mmc_step.tv_usec = 0;
234 step_speed = 0.0;
236 /* click sounds are unset by default, which causes us to internal
237 waveforms for clicks.
240 click_length = 0;
241 click_emphasis_length = 0;
242 _clicking = false;
244 process_function = &Session::process_with_events;
246 if (config.get_use_video_sync()) {
247 waiting_for_sync_offset = true;
248 } else {
249 waiting_for_sync_offset = false;
252 last_timecode_when = 0;
253 last_timecode_valid = false;
255 sync_time_vars ();
257 last_rr_session_dir = session_dirs.begin();
258 refresh_disk_space ();
260 /* default: assume simple stereo speaker configuration */
262 _speakers->setup_default_speakers (2);
264 /* slave stuff */
266 average_slave_delta = 1800; // !!! why 1800 ????
267 have_first_delta_accumulator = false;
268 delta_accumulator_cnt = 0;
269 _slave_state = Stopped;
271 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
272 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
273 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
274 add_controllable (_solo_cut_control);
276 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
278 /* These are all static "per-class" signals */
280 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
281 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
282 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
283 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
284 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
286 /* stop IO objects from doing stuff until we're ready for them */
288 Delivery::disable_panners ();
289 IO::disable_connecting ();
293 Session::second_stage_init ()
295 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
297 if (!_is_new) {
298 if (load_state (_current_snapshot_name)) {
299 return -1;
303 if (_butler->start_thread()) {
304 return -1;
307 if (start_midi_thread ()) {
308 return -1;
311 setup_midi_machine_control ();
313 // set_state() will call setup_raid_path(), but if it's a new session we need
314 // to call setup_raid_path() here.
316 if (state_tree) {
317 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
318 return -1;
320 } else {
321 setup_raid_path(_path);
324 /* we can't save till after ::when_engine_running() is called,
325 because otherwise we save state with no connections made.
326 therefore, we reset _state_of_the_state because ::set_state()
327 will have cleared it.
329 we also have to include Loading so that any events that get
330 generated between here and the end of ::when_engine_running()
331 will be processed directly rather than queued.
334 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
336 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
337 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
338 setup_click_sounds (0);
339 setup_midi_control ();
341 /* Pay attention ... */
343 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
344 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
346 try {
347 when_engine_running ();
350 /* handle this one in a different way than all others, so that its clear what happened */
352 catch (AudioEngine::PortRegistrationFailure& err) {
353 error << err.what() << endmsg;
354 return -1;
357 catch (...) {
358 return -1;
361 BootMessage (_("Reset Remote Controls"));
363 send_full_time_code (0);
364 _engine.transport_locate (0);
366 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
367 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
369 MidiClockTicker::instance().set_session (this);
370 MIDI::Name::MidiPatchManager::instance().set_session (this);
372 /* initial program change will be delivered later; see ::config_changed() */
374 _state_of_the_state = Clean;
376 Port::set_connecting_blocked (false);
378 DirtyChanged (); /* EMIT SIGNAL */
380 if (state_was_pending) {
381 save_state (_current_snapshot_name);
382 remove_pending_capture_state ();
383 state_was_pending = false;
386 BootMessage (_("Session loading complete"));
388 return 0;
391 string
392 Session::raid_path () const
394 SearchPath raid_search_path;
396 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
397 raid_search_path += sys::path((*i).path);
400 return raid_search_path.to_string ();
403 void
404 Session::setup_raid_path (string path)
406 if (path.empty()) {
407 return;
410 space_and_path sp;
411 string fspath;
413 session_dirs.clear ();
415 SearchPath search_path(path);
416 SearchPath sound_search_path;
417 SearchPath midi_search_path;
419 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
420 sp.path = (*i).to_string ();
421 sp.blocks = 0; // not needed
422 session_dirs.push_back (sp);
424 SessionDirectory sdir(sp.path);
426 sound_search_path += sdir.sound_path ();
427 midi_search_path += sdir.midi_path ();
430 // reset the round-robin soundfile path thingie
431 last_rr_session_dir = session_dirs.begin();
434 bool
435 Session::path_is_within_session (const std::string& path)
437 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
438 if (path.find ((*i).path) == 0) {
439 return true;
442 return false;
446 Session::ensure_subdirs ()
448 string dir;
450 dir = session_directory().peak_path().to_string();
452 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
453 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
454 return -1;
457 dir = session_directory().sound_path().to_string();
459 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
460 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
461 return -1;
464 dir = session_directory().midi_path().to_string();
466 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
467 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
468 return -1;
471 dir = session_directory().dead_path().to_string();
473 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
474 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
475 return -1;
478 dir = session_directory().export_path().to_string();
480 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
481 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
482 return -1;
485 dir = analysis_dir ();
487 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
488 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
489 return -1;
492 dir = plugins_dir ();
494 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
495 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
496 return -1;
499 return 0;
502 /** Caller must not hold process lock */
504 Session::create (const string& mix_template, BusProfile* bus_profile)
506 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
507 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
508 return -1;
511 if (ensure_subdirs ()) {
512 return -1;
515 _writable = exists_and_writable (sys::path (_path));
517 if (!mix_template.empty()) {
518 std::string in_path = mix_template;
520 ifstream in(in_path.c_str());
522 if (in) {
523 string out_path = _path;
524 out_path += _name;
525 out_path += statefile_suffix;
527 ofstream out(out_path.c_str());
529 if (out) {
530 out << in.rdbuf();
531 _is_new = false;
532 return 0;
534 } else {
535 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
536 << endmsg;
537 return -1;
540 } else {
541 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
542 << endmsg;
543 return -1;
548 /* Instantiate metadata */
550 _metadata = new SessionMetadata ();
552 /* set initial start + end point */
554 _state_of_the_state = Clean;
556 /* set up Master Out and Control Out if necessary */
558 if (bus_profile) {
560 RouteList rl;
561 int control_id = 1;
562 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
564 if (bus_profile->master_out_channels) {
565 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
566 if (r->init ()) {
567 return -1;
569 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
570 boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
571 #endif
573 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
574 r->input()->ensure_io (count, false, this);
575 r->output()->ensure_io (count, false, this);
577 r->set_remote_control_id (control_id++);
579 rl.push_back (r);
581 if (Config->get_use_monitor_bus()) {
582 boost::shared_ptr<Route> r (new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO));
583 if (r->init ()) {
584 return -1;
586 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
587 boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
588 #endif
590 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
591 r->input()->ensure_io (count, false, this);
592 r->output()->ensure_io (count, false, this);
594 r->set_remote_control_id (control_id);
596 rl.push_back (r);
599 } else {
600 /* prohibit auto-connect to master, because there isn't one */
601 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
604 if (!rl.empty()) {
605 add_routes (rl, false, false);
608 /* this allows the user to override settings with an environment variable.
611 if (no_auto_connect()) {
612 bus_profile->input_ac = AutoConnectOption (0);
613 bus_profile->output_ac = AutoConnectOption (0);
616 Config->set_input_auto_connect (bus_profile->input_ac);
617 Config->set_output_auto_connect (bus_profile->output_ac);
620 save_state ("");
622 return 0;
625 void
626 Session::maybe_write_autosave()
628 if (dirty() && record_status() != Recording) {
629 save_state("", true);
633 void
634 Session::remove_pending_capture_state ()
636 sys::path pending_state_file_path(_session_dir->root_path());
638 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
642 sys::remove (pending_state_file_path);
644 catch(sys::filesystem_error& ex)
646 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
647 pending_state_file_path.to_string(), ex.what()) << endmsg;
651 /** Rename a state file.
652 * @param old_name Old snapshot name.
653 * @param new_name New snapshot name.
655 void
656 Session::rename_state (string old_name, string new_name)
658 if (old_name == _current_snapshot_name || old_name == _name) {
659 /* refuse to rename the current snapshot or the "main" one */
660 return;
663 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
664 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
666 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
667 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
671 sys::rename (old_xml_path, new_xml_path);
673 catch (const sys::filesystem_error& err)
675 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
676 old_name, new_name, err.what()) << endmsg;
680 /** Remove a state file.
681 * @param snapshot_name Snapshot name.
683 void
684 Session::remove_state (string snapshot_name)
686 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
687 // refuse to remove the current snapshot or the "main" one
688 return;
691 sys::path xml_path(_session_dir->root_path());
693 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
695 if (!create_backup_file (xml_path)) {
696 // don't remove it if a backup can't be made
697 // create_backup_file will log the error.
698 return;
701 // and delete it
702 sys::remove (xml_path);
705 #ifdef HAVE_JACK_SESSION
706 void
707 Session::jack_session_event (jack_session_event_t * event)
709 char timebuf[128];
710 time_t n;
711 struct tm local_time;
713 time (&n);
714 localtime_r (&n, &local_time);
715 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
717 if (event->type == JackSessionSaveTemplate)
719 if (save_template( timebuf )) {
720 event->flags = JackSessionSaveError;
721 } else {
722 string cmd ("ardour3 -P -U ");
723 cmd += event->client_uuid;
724 cmd += " -T ";
725 cmd += timebuf;
727 event->command_line = strdup (cmd.c_str());
730 else
732 if (save_state (timebuf)) {
733 event->flags = JackSessionSaveError;
734 } else {
735 sys::path xml_path (_session_dir->root_path());
736 xml_path /= legalize_for_path (timebuf) + statefile_suffix;
738 string cmd ("ardour3 -P -U ");
739 cmd += event->client_uuid;
740 cmd += " \"";
741 cmd += xml_path.to_string();
742 cmd += '\"';
744 event->command_line = strdup (cmd.c_str());
748 jack_session_reply (_engine.jack(), event);
750 if (event->type == JackSessionSaveAndQuit) {
751 Quit (); /* EMIT SIGNAL */
754 jack_session_event_free( event );
756 #endif
758 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
760 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
762 XMLTree tree;
763 sys::path xml_path(_session_dir->root_path());
765 if (!_writable || (_state_of_the_state & CannotSave)) {
766 return 1;
769 if (!_engine.connected ()) {
770 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
771 PROGRAM_NAME)
772 << endmsg;
773 return 1;
776 /* tell sources we're saving first, in case they write out to a new file
777 * which should be saved with the state rather than the old one */
778 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
779 i->second->session_saved();
782 tree.set_root (&get_state());
784 if (snapshot_name.empty()) {
785 snapshot_name = _current_snapshot_name;
786 } else if (switch_to_snapshot) {
787 _current_snapshot_name = snapshot_name;
790 if (!pending) {
792 /* proper save: use statefile_suffix (.ardour in English) */
794 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
796 /* make a backup copy of the old file */
798 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
799 // create_backup_file will log the error
800 return -1;
803 } else {
805 /* pending save: use pending_suffix (.pending in English) */
806 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
809 sys::path tmp_path(_session_dir->root_path());
811 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
813 // cerr << "actually writing state to " << xml_path.to_string() << endl;
815 if (!tree.write (tmp_path.to_string())) {
816 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
817 sys::remove (tmp_path);
818 return -1;
820 } else {
822 if (::rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
823 error << string_compose (_("could not rename temporary session file %1 to %2"),
824 tmp_path.to_string(), xml_path.to_string()) << endmsg;
825 sys::remove (tmp_path);
826 return -1;
830 if (!pending) {
832 save_history (snapshot_name);
834 bool was_dirty = dirty();
836 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
838 if (was_dirty) {
839 DirtyChanged (); /* EMIT SIGNAL */
842 StateSaved (snapshot_name); /* EMIT SIGNAL */
845 return 0;
849 Session::restore_state (string snapshot_name)
851 if (load_state (snapshot_name) == 0) {
852 set_state (*state_tree->root(), Stateful::loading_state_version);
855 return 0;
859 Session::load_state (string snapshot_name)
861 delete state_tree;
862 state_tree = 0;
864 state_was_pending = false;
866 /* check for leftover pending state from a crashed capture attempt */
868 sys::path xmlpath(_session_dir->root_path());
869 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
871 if (sys::exists (xmlpath)) {
873 /* there is pending state from a crashed capture attempt */
875 boost::optional<int> r = AskAboutPendingState();
876 if (r.get_value_or (1)) {
877 state_was_pending = true;
881 if (!state_was_pending) {
882 xmlpath = _session_dir->root_path();
883 xmlpath /= snapshot_name;
886 if (!sys::exists (xmlpath)) {
887 xmlpath = _session_dir->root_path();
888 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
889 if (!sys::exists (xmlpath)) {
890 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
891 return 1;
895 state_tree = new XMLTree;
897 set_dirty();
899 _writable = exists_and_writable (xmlpath);
901 if (!state_tree->read (xmlpath.to_string())) {
902 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
903 delete state_tree;
904 state_tree = 0;
905 return -1;
908 XMLNode& root (*state_tree->root());
910 if (root.name() != X_("Session")) {
911 error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg;
912 delete state_tree;
913 state_tree = 0;
914 return -1;
917 const XMLProperty* prop;
919 if ((prop = root.property ("version")) == 0) {
920 /* no version implies very old version of Ardour */
921 Stateful::loading_state_version = 1000;
922 } else {
923 int major;
924 int minor;
925 int micro;
927 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, &micro);
928 Stateful::loading_state_version = (major * 1000) + minor;
931 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
933 sys::path backup_path(_session_dir->root_path());
935 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
937 // only create a backup once
938 if (sys::exists (backup_path)) {
939 return 0;
942 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
943 xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME)
944 << endmsg;
948 sys::copy_file (xmlpath, backup_path);
950 catch(sys::filesystem_error& ex)
952 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
953 xmlpath.to_string(), ex.what())
954 << endmsg;
955 return -1;
959 return 0;
963 Session::load_options (const XMLNode& node)
965 LocaleGuard lg (X_("POSIX"));
966 config.set_variables (node);
967 return 0;
970 XMLNode&
971 Session::get_state()
973 return state(true);
976 XMLNode&
977 Session::get_template()
979 /* if we don't disable rec-enable, diskstreams
980 will believe they need to store their capture
981 sources in their state node.
984 disable_record (false);
986 return state(false);
989 XMLNode&
990 Session::state(bool full_state)
992 XMLNode* node = new XMLNode("Session");
993 XMLNode* child;
995 // store libardour version, just in case
996 char buf[16];
997 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
998 node->add_property("version", string(buf));
1000 /* store configuration settings */
1002 if (full_state) {
1004 node->add_property ("name", _name);
1005 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
1006 node->add_property ("sample-rate", buf);
1008 if (session_dirs.size() > 1) {
1010 string p;
1012 vector<space_and_path>::iterator i = session_dirs.begin();
1013 vector<space_and_path>::iterator next;
1015 ++i; /* skip the first one */
1016 next = i;
1017 ++next;
1019 while (i != session_dirs.end()) {
1021 p += (*i).path;
1023 if (next != session_dirs.end()) {
1024 p += ':';
1025 } else {
1026 break;
1029 ++next;
1030 ++i;
1033 child = node->add_child ("Path");
1034 child->add_content (p);
1038 /* save the ID counter */
1040 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1041 node->add_property ("id-counter", buf);
1043 /* save the event ID counter */
1045 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1046 node->add_property ("event-counter", buf);
1048 /* various options */
1050 node->add_child_nocopy (config.get_variables ());
1052 node->add_child_nocopy (_metadata->get_state());
1054 child = node->add_child ("Sources");
1056 if (full_state) {
1057 Glib::Mutex::Lock sl (source_lock);
1059 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1061 /* Don't save information about non-file Sources, or
1062 * about non-destructive file sources that are empty
1063 * and unused by any regions.
1066 boost::shared_ptr<FileSource> fs;
1068 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1070 if (!fs->destructive()) {
1071 if (fs->empty() && !fs->used()) {
1072 continue;
1076 child->add_child_nocopy (siter->second->get_state());
1081 child = node->add_child ("Regions");
1083 if (full_state) {
1084 Glib::Mutex::Lock rl (region_lock);
1085 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1086 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1087 boost::shared_ptr<Region> r = i->second;
1088 /* only store regions not attached to playlists */
1089 if (r->playlist() == 0) {
1090 child->add_child_nocopy (r->state ());
1094 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1096 if (!cassocs.empty()) {
1097 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1099 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1100 char buf[64];
1101 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1102 i->first->id().print (buf, sizeof (buf));
1103 can->add_property (X_("copy"), buf);
1104 i->second->id().print (buf, sizeof (buf));
1105 can->add_property (X_("original"), buf);
1106 ca->add_child_nocopy (*can);
1111 if (full_state) {
1112 node->add_child_nocopy (_locations->get_state());
1113 } else {
1114 // for a template, just create a new Locations, populate it
1115 // with the default start and end, and get the state for that.
1116 Locations loc (*this);
1117 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1118 range->set (max_framepos, 0);
1119 loc.add (range);
1120 node->add_child_nocopy (loc.get_state());
1123 child = node->add_child ("Bundles");
1125 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1126 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1127 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1128 if (b) {
1129 child->add_child_nocopy (b->get_state());
1134 child = node->add_child ("Routes");
1136 boost::shared_ptr<RouteList> r = routes.reader ();
1138 RoutePublicOrderSorter cmp;
1139 RouteList public_order (*r);
1140 public_order.sort (cmp);
1142 /* the sort should have put control outs first */
1144 if (_monitor_out) {
1145 assert (_monitor_out == public_order.front());
1148 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1149 if (!(*i)->is_hidden()) {
1150 if (full_state) {
1151 child->add_child_nocopy ((*i)->get_state());
1152 } else {
1153 child->add_child_nocopy ((*i)->get_template());
1159 playlists->add_state (node, full_state);
1161 child = node->add_child ("RouteGroups");
1162 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1163 child->add_child_nocopy ((*i)->get_state());
1166 if (_click_io) {
1167 child = node->add_child ("Click");
1168 child->add_child_nocopy (_click_io->state (full_state));
1171 if (full_state) {
1172 child = node->add_child ("NamedSelections");
1173 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1174 if (full_state) {
1175 child->add_child_nocopy ((*i)->get_state());
1180 node->add_child_nocopy (_speakers->get_state());
1181 node->add_child_nocopy (_tempo_map->get_state());
1182 node->add_child_nocopy (get_control_protocol_state());
1184 if (_extra_xml) {
1185 node->add_child_copy (*_extra_xml);
1188 return *node;
1191 XMLNode&
1192 Session::get_control_protocol_state ()
1194 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1195 return cpm.get_state();
1199 Session::set_state (const XMLNode& node, int version)
1201 XMLNodeList nlist;
1202 XMLNode* child;
1203 const XMLProperty* prop;
1204 int ret = -1;
1206 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1208 if (node.name() != X_("Session")) {
1209 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1210 return -1;
1213 if ((prop = node.property ("version")) != 0) {
1214 version = atoi (prop->value ()) * 1000;
1217 if ((prop = node.property ("name")) != 0) {
1218 _name = prop->value ();
1221 if ((prop = node.property (X_("sample-rate"))) != 0) {
1223 _nominal_frame_rate = atoi (prop->value());
1225 if (_nominal_frame_rate != _current_frame_rate) {
1226 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1227 if (r.get_value_or (0)) {
1228 return -1;
1233 setup_raid_path(_session_dir->root_path().to_string());
1235 if ((prop = node.property (X_("id-counter"))) != 0) {
1236 uint64_t x;
1237 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1238 ID::init_counter (x);
1239 } else {
1240 /* old sessions used a timebased counter, so fake
1241 the startup ID counter based on a standard
1242 timestamp.
1244 time_t now;
1245 time (&now);
1246 ID::init_counter (now);
1249 if ((prop = node.property (X_("event-counter"))) != 0) {
1250 Evoral::init_event_id_counter (atoi (prop->value()));
1253 IO::disable_connecting ();
1255 Stateful::save_extra_xml (node);
1257 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1258 load_options (*child);
1259 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1260 load_options (*child);
1261 } else {
1262 error << _("Session: XML state has no options section") << endmsg;
1265 if (version >= 3000) {
1266 if ((child = find_named_node (node, "Metadata")) == 0) {
1267 warning << _("Session: XML state has no metadata section") << endmsg;
1268 } else if (_metadata->set_state (*child, version)) {
1269 goto out;
1273 if ((child = find_named_node (node, "Locations")) == 0) {
1274 error << _("Session: XML state has no locations section") << endmsg;
1275 goto out;
1276 } else if (_locations->set_state (*child, version)) {
1277 goto out;
1280 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1281 _speakers->set_state (*child, version);
1284 Location* location;
1286 if ((location = _locations->auto_loop_location()) != 0) {
1287 set_auto_loop_location (location);
1290 if ((location = _locations->auto_punch_location()) != 0) {
1291 set_auto_punch_location (location);
1294 if ((location = _locations->session_range_location()) != 0) {
1295 delete _session_range_location;
1296 _session_range_location = location;
1299 if (_session_range_location) {
1300 AudioFileSource::set_header_position_offset (_session_range_location->start());
1303 if ((child = find_named_node (node, "Sources")) == 0) {
1304 error << _("Session: XML state has no sources section") << endmsg;
1305 goto out;
1306 } else if (load_sources (*child)) {
1307 goto out;
1310 if ((child = find_named_node (node, "TempoMap")) == 0) {
1311 error << _("Session: XML state has no Tempo Map section") << endmsg;
1312 goto out;
1313 } else if (_tempo_map->set_state (*child, version)) {
1314 goto out;
1317 if ((child = find_named_node (node, "Regions")) == 0) {
1318 error << _("Session: XML state has no Regions section") << endmsg;
1319 goto out;
1320 } else if (load_regions (*child)) {
1321 goto out;
1324 if ((child = find_named_node (node, "Playlists")) == 0) {
1325 error << _("Session: XML state has no playlists section") << endmsg;
1326 goto out;
1327 } else if (playlists->load (*this, *child)) {
1328 goto out;
1331 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1332 // this is OK
1333 } else if (playlists->load_unused (*this, *child)) {
1334 goto out;
1337 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1338 if (load_compounds (*child)) {
1339 goto out;
1343 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1344 if (load_named_selections (*child)) {
1345 goto out;
1349 if (version >= 3000) {
1350 if ((child = find_named_node (node, "Bundles")) == 0) {
1351 warning << _("Session: XML state has no bundles section") << endmsg;
1352 //goto out;
1353 } else {
1354 /* We can't load Bundles yet as they need to be able
1355 to convert from port names to Port objects, which can't happen until
1356 later */
1357 _bundle_xml_node = new XMLNode (*child);
1361 if (version < 3000) {
1362 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1363 error << _("Session: XML state has no diskstreams section") << endmsg;
1364 goto out;
1365 } else if (load_diskstreams_2X (*child, version)) {
1366 goto out;
1370 if ((child = find_named_node (node, "Routes")) == 0) {
1371 error << _("Session: XML state has no routes section") << endmsg;
1372 goto out;
1373 } else if (load_routes (*child, version)) {
1374 goto out;
1377 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1378 _diskstreams_2X.clear ();
1380 if (version >= 3000) {
1382 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1383 error << _("Session: XML state has no route groups section") << endmsg;
1384 goto out;
1385 } else if (load_route_groups (*child, version)) {
1386 goto out;
1389 } else if (version < 3000) {
1391 if ((child = find_named_node (node, "EditGroups")) == 0) {
1392 error << _("Session: XML state has no edit groups section") << endmsg;
1393 goto out;
1394 } else if (load_route_groups (*child, version)) {
1395 goto out;
1398 if ((child = find_named_node (node, "MixGroups")) == 0) {
1399 error << _("Session: XML state has no mix groups section") << endmsg;
1400 goto out;
1401 } else if (load_route_groups (*child, version)) {
1402 goto out;
1406 if ((child = find_named_node (node, "Click")) == 0) {
1407 warning << _("Session: XML state has no click section") << endmsg;
1408 } else if (_click_io) {
1409 _click_io->set_state (*child, version);
1412 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1413 ControlProtocolManager::instance().set_protocol_states (*child);
1416 /* here beginneth the second phase ... */
1418 StateReady (); /* EMIT SIGNAL */
1420 return 0;
1422 out:
1423 return ret;
1427 Session::load_routes (const XMLNode& node, int version)
1429 XMLNodeList nlist;
1430 XMLNodeConstIterator niter;
1431 RouteList new_routes;
1433 nlist = node.children();
1435 set_dirty();
1437 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1439 boost::shared_ptr<Route> route;
1440 if (version < 3000) {
1441 route = XMLRouteFactory_2X (**niter, version);
1442 } else {
1443 route = XMLRouteFactory (**niter, version);
1446 if (route == 0) {
1447 error << _("Session: cannot create Route from XML description.") << endmsg;
1448 return -1;
1451 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1453 new_routes.push_back (route);
1456 add_routes (new_routes, false, false);
1458 return 0;
1461 boost::shared_ptr<Route>
1462 Session::XMLRouteFactory (const XMLNode& node, int version)
1464 boost::shared_ptr<Route> ret;
1466 if (node.name() != "Route") {
1467 return ret;
1470 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1472 DataType type = DataType::AUDIO;
1473 const XMLProperty* prop = node.property("default-type");
1475 if (prop) {
1476 type = DataType (prop->value());
1479 assert (type != DataType::NIL);
1481 if (ds_child) {
1483 boost::shared_ptr<Track> track;
1485 if (type == DataType::AUDIO) {
1486 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1487 } else {
1488 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1491 if (track->init()) {
1492 return ret;
1495 if (track->set_state (node, version)) {
1496 return ret;
1499 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1500 boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1501 #endif
1502 ret = track;
1504 } else {
1505 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1507 if (r->init () == 0 && r->set_state (node, version) == 0) {
1508 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1509 boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1510 #endif
1511 ret = r;
1515 return ret;
1518 boost::shared_ptr<Route>
1519 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1521 boost::shared_ptr<Route> ret;
1523 if (node.name() != "Route") {
1524 return ret;
1527 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1528 if (!ds_prop) {
1529 ds_prop = node.property (X_("diskstream"));
1532 DataType type = DataType::AUDIO;
1533 const XMLProperty* prop = node.property("default-type");
1535 if (prop) {
1536 type = DataType (prop->value());
1539 assert (type != DataType::NIL);
1541 if (ds_prop) {
1543 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1544 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1545 ++i;
1548 if (i == _diskstreams_2X.end()) {
1549 error << _("Could not find diskstream for route") << endmsg;
1550 return boost::shared_ptr<Route> ();
1553 boost::shared_ptr<Track> track;
1555 if (type == DataType::AUDIO) {
1556 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1557 } else {
1558 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1561 if (track->init()) {
1562 return ret;
1565 if (track->set_state (node, version)) {
1566 return ret;
1569 track->set_diskstream (*i);
1571 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1572 boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1573 #endif
1574 ret = track;
1576 } else {
1577 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1579 if (r->init () == 0 && r->set_state (node, version) == 0) {
1580 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1581 boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1582 #endif
1583 ret = r;
1587 return ret;
1591 Session::load_regions (const XMLNode& node)
1593 XMLNodeList nlist;
1594 XMLNodeConstIterator niter;
1595 boost::shared_ptr<Region> region;
1597 nlist = node.children();
1599 set_dirty();
1601 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1602 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1603 error << _("Session: cannot create Region from XML description.");
1604 const XMLProperty *name = (**niter).property("name");
1606 if (name) {
1607 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1610 error << endmsg;
1614 return 0;
1618 Session::load_compounds (const XMLNode& node)
1620 XMLNodeList calist = node.children();
1621 XMLNodeConstIterator caiter;
1622 XMLProperty *caprop;
1624 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1625 XMLNode* ca = *caiter;
1626 ID orig_id;
1627 ID copy_id;
1629 if ((caprop = ca->property (X_("original"))) == 0) {
1630 continue;
1632 orig_id = caprop->value();
1634 if ((caprop = ca->property (X_("copy"))) == 0) {
1635 continue;
1637 copy_id = caprop->value();
1639 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1640 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1642 if (!orig || !copy) {
1643 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1644 orig_id, copy_id)
1645 << endmsg;
1646 continue;
1649 RegionFactory::add_compound_association (orig, copy);
1652 return 0;
1655 void
1656 Session::load_nested_sources (const XMLNode& node)
1658 XMLNodeList nlist;
1659 XMLNodeConstIterator niter;
1661 nlist = node.children();
1663 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1664 if ((*niter)->name() == "Source") {
1666 /* it may already exist, so don't recreate it unnecessarily
1669 XMLProperty* prop = (*niter)->property (X_("id"));
1670 if (!prop) {
1671 error << _("Nested source has no ID info in session state file! (ignored)") << endmsg;
1672 continue;
1675 ID source_id (prop->value());
1677 if (!source_by_id (source_id)) {
1679 try {
1680 SourceFactory::create (*this, **niter, true);
1682 catch (failed_constructor& err) {
1683 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1690 boost::shared_ptr<Region>
1691 Session::XMLRegionFactory (const XMLNode& node, bool full)
1693 const XMLProperty* type = node.property("type");
1695 try {
1697 const XMLNodeList& nlist = node.children();
1699 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1700 XMLNode *child = (*niter);
1701 if (child->name() == "NestedSource") {
1702 load_nested_sources (*child);
1706 if (!type || type->value() == "audio") {
1707 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1708 } else if (type->value() == "midi") {
1709 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1712 } catch (failed_constructor& err) {
1713 return boost::shared_ptr<Region> ();
1716 return boost::shared_ptr<Region> ();
1719 boost::shared_ptr<AudioRegion>
1720 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1722 const XMLProperty* prop;
1723 boost::shared_ptr<Source> source;
1724 boost::shared_ptr<AudioSource> as;
1725 SourceList sources;
1726 SourceList master_sources;
1727 uint32_t nchans = 1;
1728 char buf[128];
1730 if (node.name() != X_("Region")) {
1731 return boost::shared_ptr<AudioRegion>();
1734 if ((prop = node.property (X_("channels"))) != 0) {
1735 nchans = atoi (prop->value().c_str());
1738 if ((prop = node.property ("name")) == 0) {
1739 cerr << "no name for this region\n";
1740 abort ();
1743 if ((prop = node.property (X_("source-0"))) == 0) {
1744 if ((prop = node.property ("source")) == 0) {
1745 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1746 return boost::shared_ptr<AudioRegion>();
1750 PBD::ID s_id (prop->value());
1752 if ((source = source_by_id (s_id)) == 0) {
1753 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1754 return boost::shared_ptr<AudioRegion>();
1757 as = boost::dynamic_pointer_cast<AudioSource>(source);
1758 if (!as) {
1759 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1760 return boost::shared_ptr<AudioRegion>();
1763 sources.push_back (as);
1765 /* pickup other channels */
1767 for (uint32_t n=1; n < nchans; ++n) {
1768 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1769 if ((prop = node.property (buf)) != 0) {
1771 PBD::ID id2 (prop->value());
1773 if ((source = source_by_id (id2)) == 0) {
1774 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1775 return boost::shared_ptr<AudioRegion>();
1778 as = boost::dynamic_pointer_cast<AudioSource>(source);
1779 if (!as) {
1780 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1781 return boost::shared_ptr<AudioRegion>();
1783 sources.push_back (as);
1787 for (uint32_t n = 0; n < nchans; ++n) {
1788 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1789 if ((prop = node.property (buf)) != 0) {
1791 PBD::ID id2 (prop->value());
1793 if ((source = source_by_id (id2)) == 0) {
1794 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1795 return boost::shared_ptr<AudioRegion>();
1798 as = boost::dynamic_pointer_cast<AudioSource>(source);
1799 if (!as) {
1800 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1801 return boost::shared_ptr<AudioRegion>();
1803 master_sources.push_back (as);
1807 try {
1808 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1810 /* a final detail: this is the one and only place that we know how long missing files are */
1812 if (region->whole_file()) {
1813 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1814 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1815 if (sfp) {
1816 sfp->set_length (region->length());
1821 if (!master_sources.empty()) {
1822 if (master_sources.size() != nchans) {
1823 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1824 } else {
1825 region->set_master_sources (master_sources);
1829 return region;
1833 catch (failed_constructor& err) {
1834 return boost::shared_ptr<AudioRegion>();
1838 boost::shared_ptr<MidiRegion>
1839 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1841 const XMLProperty* prop;
1842 boost::shared_ptr<Source> source;
1843 boost::shared_ptr<MidiSource> ms;
1844 SourceList sources;
1846 if (node.name() != X_("Region")) {
1847 return boost::shared_ptr<MidiRegion>();
1850 if ((prop = node.property ("name")) == 0) {
1851 cerr << "no name for this region\n";
1852 abort ();
1855 if ((prop = node.property (X_("source-0"))) == 0) {
1856 if ((prop = node.property ("source")) == 0) {
1857 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1858 return boost::shared_ptr<MidiRegion>();
1862 PBD::ID s_id (prop->value());
1864 if ((source = source_by_id (s_id)) == 0) {
1865 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1866 return boost::shared_ptr<MidiRegion>();
1869 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1870 if (!ms) {
1871 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1872 return boost::shared_ptr<MidiRegion>();
1875 sources.push_back (ms);
1877 try {
1878 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1879 /* a final detail: this is the one and only place that we know how long missing files are */
1881 if (region->whole_file()) {
1882 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1883 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1884 if (sfp) {
1885 sfp->set_length (region->length());
1890 return region;
1893 catch (failed_constructor& err) {
1894 return boost::shared_ptr<MidiRegion>();
1898 XMLNode&
1899 Session::get_sources_as_xml ()
1902 XMLNode* node = new XMLNode (X_("Sources"));
1903 Glib::Mutex::Lock lm (source_lock);
1905 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1906 node->add_child_nocopy (i->second->get_state());
1909 return *node;
1912 string
1913 Session::path_from_region_name (DataType type, string name, string identifier)
1915 char buf[PATH_MAX+1];
1916 uint32_t n;
1917 SessionDirectory sdir(get_best_session_directory_for_new_source());
1918 sys::path source_dir = ((type == DataType::AUDIO)
1919 ? sdir.sound_path() : sdir.midi_path());
1921 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1923 for (n = 0; n < 999999; ++n) {
1924 if (identifier.length()) {
1925 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1926 identifier.c_str(), n, ext.c_str());
1927 } else {
1928 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1929 n, ext.c_str());
1932 sys::path source_path = source_dir / buf;
1934 if (!sys::exists (source_path)) {
1935 return source_path.to_string();
1939 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1940 name, identifier)
1941 << endmsg;
1943 return "";
1948 Session::load_sources (const XMLNode& node)
1950 XMLNodeList nlist;
1951 XMLNodeConstIterator niter;
1952 boost::shared_ptr<Source> source;
1954 nlist = node.children();
1956 set_dirty();
1958 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1959 retry:
1960 try {
1961 if ((source = XMLSourceFactory (**niter)) == 0) {
1962 error << _("Session: cannot create Source from XML description.") << endmsg;
1965 } catch (MissingSource& err) {
1967 int user_choice;
1969 if (!no_questions_about_missing_files) {
1970 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1971 } else {
1972 user_choice = -2;
1975 switch (user_choice) {
1976 case 0:
1977 /* user added a new search location, so try again */
1978 goto retry;
1981 case 1:
1982 /* user asked to quit the entire session load
1984 return -1;
1986 case 2:
1987 no_questions_about_missing_files = true;
1988 goto retry;
1990 case 3:
1991 no_questions_about_missing_files = true;
1992 /* fallthru */
1994 case -1:
1995 default:
1996 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1997 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1998 break;
2003 return 0;
2006 boost::shared_ptr<Source>
2007 Session::XMLSourceFactory (const XMLNode& node)
2009 if (node.name() != "Source") {
2010 return boost::shared_ptr<Source>();
2013 try {
2014 /* note: do peak building in another thread when loading session state */
2015 return SourceFactory::create (*this, node, true);
2018 catch (failed_constructor& err) {
2019 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
2020 return boost::shared_ptr<Source>();
2025 Session::save_template (string template_name)
2027 XMLTree tree;
2029 if (_state_of_the_state & CannotSave) {
2030 return -1;
2033 sys::path user_template_dir(user_template_directory());
2037 sys::create_directories (user_template_dir);
2039 catch(sys::filesystem_error& ex)
2041 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
2042 user_template_dir.to_string(), ex.what()) << endmsg;
2043 return -1;
2046 tree.set_root (&get_template());
2048 sys::path template_file_path(user_template_dir);
2049 template_file_path /= template_name + template_suffix;
2051 if (sys::exists (template_file_path))
2053 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2054 template_file_path.to_string()) << endmsg;
2055 return -1;
2058 if (!tree.write (template_file_path.to_string())) {
2059 error << _("template not saved") << endmsg;
2060 return -1;
2063 return 0;
2067 Session::rename_template (string old_name, string new_name)
2069 sys::path old_path (user_template_directory());
2070 old_path /= old_name + template_suffix;
2072 sys::path new_path(user_template_directory());
2073 new_path /= new_name + template_suffix;
2075 if (sys::exists (new_path)) {
2076 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
2077 new_path.to_string()) << endmsg;
2078 return -1;
2081 try {
2082 sys::rename (old_path, new_path);
2083 return 0;
2084 } catch (...) {
2085 return -1;
2090 Session::delete_template (string name)
2092 sys::path path = user_template_directory();
2093 path /= name + template_suffix;
2095 try {
2096 sys::remove (path);
2097 return 0;
2098 } catch (...) {
2099 return -1;
2103 void
2104 Session::refresh_disk_space ()
2106 #if HAVE_SYS_VFS_H
2107 struct statfs statfsbuf;
2108 vector<space_and_path>::iterator i;
2109 Glib::Mutex::Lock lm (space_lock);
2110 double scale;
2112 /* get freespace on every FS that is part of the session path */
2114 _total_free_4k_blocks = 0;
2116 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2117 statfs ((*i).path.c_str(), &statfsbuf);
2119 scale = statfsbuf.f_bsize/4096.0;
2121 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2122 _total_free_4k_blocks += (*i).blocks;
2124 #endif
2127 string
2128 Session::get_best_session_directory_for_new_source ()
2130 vector<space_and_path>::iterator i;
2131 string result = _session_dir->root_path().to_string();
2133 /* handle common case without system calls */
2135 if (session_dirs.size() == 1) {
2136 return result;
2139 /* OK, here's the algorithm we're following here:
2141 We want to select which directory to use for
2142 the next file source to be created. Ideally,
2143 we'd like to use a round-robin process so as to
2144 get maximum performance benefits from splitting
2145 the files across multiple disks.
2147 However, in situations without much diskspace, an
2148 RR approach may end up filling up a filesystem
2149 with new files while others still have space.
2150 Its therefore important to pay some attention to
2151 the freespace in the filesystem holding each
2152 directory as well. However, if we did that by
2153 itself, we'd keep creating new files in the file
2154 system with the most space until it was as full
2155 as all others, thus negating any performance
2156 benefits of this RAID-1 like approach.
2158 So, we use a user-configurable space threshold. If
2159 there are at least 2 filesystems with more than this
2160 much space available, we use RR selection between them.
2161 If not, then we pick the filesystem with the most space.
2163 This gets a good balance between the two
2164 approaches.
2167 refresh_disk_space ();
2169 int free_enough = 0;
2171 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2172 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2173 free_enough++;
2177 if (free_enough >= 2) {
2178 /* use RR selection process, ensuring that the one
2179 picked works OK.
2182 i = last_rr_session_dir;
2184 do {
2185 if (++i == session_dirs.end()) {
2186 i = session_dirs.begin();
2189 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2190 if (create_session_directory ((*i).path)) {
2191 result = (*i).path;
2192 last_rr_session_dir = i;
2193 return result;
2197 } while (i != last_rr_session_dir);
2199 } else {
2201 /* pick FS with the most freespace (and that
2202 seems to actually work ...)
2205 vector<space_and_path> sorted;
2206 space_and_path_ascending_cmp cmp;
2208 sorted = session_dirs;
2209 sort (sorted.begin(), sorted.end(), cmp);
2211 for (i = sorted.begin(); i != sorted.end(); ++i) {
2212 if (create_session_directory ((*i).path)) {
2213 result = (*i).path;
2214 last_rr_session_dir = i;
2215 return result;
2220 return result;
2224 Session::load_named_selections (const XMLNode& node)
2226 XMLNodeList nlist;
2227 XMLNodeConstIterator niter;
2228 NamedSelection *ns;
2230 nlist = node.children();
2232 set_dirty();
2234 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2236 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2237 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2241 return 0;
2244 NamedSelection *
2245 Session::XMLNamedSelectionFactory (const XMLNode& node)
2247 try {
2248 return new NamedSelection (*this, node);
2251 catch (failed_constructor& err) {
2252 return 0;
2256 string
2257 Session::automation_dir () const
2259 return Glib::build_filename (_path, "automation");
2262 string
2263 Session::analysis_dir () const
2265 return Glib::build_filename (_path, "analysis");
2268 string
2269 Session::plugins_dir () const
2271 return Glib::build_filename (_path, "plugins");
2275 Session::load_bundles (XMLNode const & node)
2277 XMLNodeList nlist = node.children();
2278 XMLNodeConstIterator niter;
2280 set_dirty();
2282 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2283 if ((*niter)->name() == "InputBundle") {
2284 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2285 } else if ((*niter)->name() == "OutputBundle") {
2286 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2287 } else {
2288 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2289 return -1;
2293 return 0;
2297 Session::load_route_groups (const XMLNode& node, int version)
2299 XMLNodeList nlist = node.children();
2300 XMLNodeConstIterator niter;
2302 set_dirty ();
2304 if (version >= 3000) {
2306 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2307 if ((*niter)->name() == "RouteGroup") {
2308 RouteGroup* rg = new RouteGroup (*this, "");
2309 add_route_group (rg);
2310 rg->set_state (**niter, version);
2314 } else if (version < 3000) {
2316 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2317 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2318 RouteGroup* rg = new RouteGroup (*this, "");
2319 add_route_group (rg);
2320 rg->set_state (**niter, version);
2325 return 0;
2328 void
2329 Session::auto_save()
2331 save_state (_current_snapshot_name);
2334 static bool
2335 state_file_filter (const string &str, void */*arg*/)
2337 return (str.length() > strlen(statefile_suffix) &&
2338 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2341 struct string_cmp {
2342 bool operator()(const string* a, const string* b) {
2343 return *a < *b;
2347 static string*
2348 remove_end(string* state)
2350 string statename(*state);
2352 string::size_type start,end;
2353 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2354 statename = statename.substr (start+1);
2357 if ((end = statename.rfind(".ardour")) == string::npos) {
2358 end = statename.length();
2361 return new string(statename.substr (0, end));
2364 vector<string *> *
2365 Session::possible_states (string path)
2367 PathScanner scanner;
2368 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2370 transform(states->begin(), states->end(), states->begin(), remove_end);
2372 string_cmp cmp;
2373 sort (states->begin(), states->end(), cmp);
2375 return states;
2378 vector<string *> *
2379 Session::possible_states () const
2381 return possible_states(_path);
2384 void
2385 Session::add_route_group (RouteGroup* g)
2387 _route_groups.push_back (g);
2388 route_group_added (g); /* EMIT SIGNAL */
2390 g->MembershipChanged.connect_same_thread (*this, boost::bind (&Session::route_group_changed, this));
2391 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_changed, this));
2393 set_dirty ();
2396 void
2397 Session::remove_route_group (RouteGroup& rg)
2399 list<RouteGroup*>::iterator i;
2401 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2402 _route_groups.erase (i);
2403 delete &rg;
2405 route_group_removed (); /* EMIT SIGNAL */
2409 /** Set a new order for our route groups, without adding or removing any.
2410 * @param groups Route group list in the new order.
2412 void
2413 Session::reorder_route_groups (list<RouteGroup*> groups)
2415 _route_groups = groups;
2417 route_groups_reordered (); /* EMIT SIGNAL */
2418 set_dirty ();
2422 RouteGroup *
2423 Session::route_group_by_name (string name)
2425 list<RouteGroup *>::iterator i;
2427 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2428 if ((*i)->name() == name) {
2429 return* i;
2432 return 0;
2435 RouteGroup&
2436 Session::all_route_group() const
2438 return *_all_route_group;
2441 void
2442 Session::add_commands (vector<Command*> const & cmds)
2444 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2445 add_command (*i);
2449 void
2450 Session::begin_reversible_command (const string& name)
2452 begin_reversible_command (g_quark_from_string (name.c_str ()));
2455 /** Begin a reversible command using a GQuark to identify it.
2456 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2457 * but there must be as many begin...()s as there are commit...()s.
2459 void
2460 Session::begin_reversible_command (GQuark q)
2462 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2463 to hold all the commands that are committed. This keeps the order of
2464 commands correct in the history.
2467 if (_current_trans == 0) {
2468 /* start a new transaction */
2469 assert (_current_trans_quarks.empty ());
2470 _current_trans = new UndoTransaction();
2471 _current_trans->set_name (g_quark_to_string (q));
2474 _current_trans_quarks.push_front (q);
2477 void
2478 Session::commit_reversible_command (Command *cmd)
2480 assert (_current_trans);
2481 assert (!_current_trans_quarks.empty ());
2483 struct timeval now;
2485 if (cmd) {
2486 _current_trans->add_command (cmd);
2489 _current_trans_quarks.pop_front ();
2491 if (!_current_trans_quarks.empty ()) {
2492 /* the transaction we're committing is not the top-level one */
2493 return;
2496 if (_current_trans->empty()) {
2497 /* no commands were added to the transaction, so just get rid of it */
2498 delete _current_trans;
2499 _current_trans = 0;
2500 return;
2503 gettimeofday (&now, 0);
2504 _current_trans->set_timestamp (now);
2506 _history.add (_current_trans);
2507 _current_trans = 0;
2510 static bool
2511 accept_all_audio_files (const string& path, void */*arg*/)
2513 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2514 return false;
2517 if (!AudioFileSource::safe_audio_file_extension (path)) {
2518 return false;
2521 return true;
2524 static bool
2525 accept_all_midi_files (const string& path, void */*arg*/)
2527 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2528 return false;
2531 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2532 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2533 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2536 static bool
2537 accept_all_state_files (const string& path, void */*arg*/)
2539 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2540 return false;
2543 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2547 Session::find_all_sources (string path, set<string>& result)
2549 XMLTree tree;
2550 XMLNode* node;
2552 if (!tree.read (path)) {
2553 return -1;
2556 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2557 return -2;
2560 XMLNodeList nlist;
2561 XMLNodeConstIterator niter;
2563 nlist = node->children();
2565 set_dirty();
2567 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2569 XMLProperty* prop;
2571 if ((prop = (*niter)->property (X_("type"))) == 0) {
2572 continue;
2575 DataType type (prop->value());
2577 if ((prop = (*niter)->property (X_("name"))) == 0) {
2578 continue;
2581 if (Glib::path_is_absolute (prop->value())) {
2582 /* external file, ignore */
2583 continue;
2586 string found_path;
2587 bool is_new;
2588 uint16_t chan;
2590 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2591 result.insert (found_path);
2595 return 0;
2599 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2601 PathScanner scanner;
2602 vector<string*>* state_files;
2603 string ripped;
2604 string this_snapshot_path;
2606 result.clear ();
2608 ripped = _path;
2610 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2611 ripped = ripped.substr (0, ripped.length() - 1);
2614 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2616 if (state_files == 0) {
2617 /* impossible! */
2618 return 0;
2621 this_snapshot_path = _path;
2622 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2623 this_snapshot_path += statefile_suffix;
2625 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2627 if (exclude_this_snapshot && **i == this_snapshot_path) {
2628 continue;
2631 if (find_all_sources (**i, result) < 0) {
2632 return -1;
2636 return 0;
2639 struct RegionCounter {
2640 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2641 AudioSourceList::iterator iter;
2642 boost::shared_ptr<Region> region;
2643 uint32_t count;
2645 RegionCounter() : count (0) {}
2649 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2651 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2652 return r.get_value_or (1);
2655 void
2656 Session::cleanup_regions ()
2658 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2660 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2662 boost::shared_ptr<AudioRegion> audio_region = boost::dynamic_pointer_cast<AudioRegion>( i->second);
2664 if (!audio_region) {
2665 continue;
2668 uint32_t used = playlists->region_use_count (audio_region);
2670 if (used == 0 && !audio_region->automatic()) {
2671 RegionFactory::map_remove(i->second);
2675 /* dump the history list */
2676 _history.clear ();
2678 save_state ("");
2682 Session::cleanup_sources (CleanupReport& rep)
2684 // FIXME: needs adaptation to midi
2686 vector<boost::shared_ptr<Source> > dead_sources;
2687 PathScanner scanner;
2688 string audio_path;
2689 string midi_path;
2690 vector<space_and_path>::iterator i;
2691 vector<space_and_path>::iterator nexti;
2692 vector<string*>* candidates;
2693 vector<string*>* candidates2;
2694 vector<string> unused;
2695 set<string> all_sources;
2696 bool used;
2697 string spath;
2698 int ret = -1;
2700 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2702 /* consider deleting all unused playlists */
2704 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2705 ret = 0;
2706 goto out;
2709 /* sync the "all regions" property of each playlist with its current state
2712 playlists->sync_all_regions_with_regions ();
2714 /* find all un-used sources */
2716 rep.paths.clear ();
2717 rep.space = 0;
2719 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2721 SourceMap::iterator tmp;
2723 tmp = i;
2724 ++tmp;
2726 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2727 capture files.
2730 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2731 dead_sources.push_back (i->second);
2732 i->second->drop_references ();
2735 i = tmp;
2738 /* build a list of all the possible audio directories for the session */
2740 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2742 nexti = i;
2743 ++nexti;
2745 SessionDirectory sdir ((*i).path);
2746 audio_path += sdir.sound_path().to_string();
2748 if (nexti != session_dirs.end()) {
2749 audio_path += ':';
2752 i = nexti;
2756 /* build a list of all the possible midi directories for the session */
2758 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2760 nexti = i;
2761 ++nexti;
2763 SessionDirectory sdir ((*i).path);
2764 midi_path += sdir.midi_path().to_string();
2766 if (nexti != session_dirs.end()) {
2767 midi_path += ':';
2770 i = nexti;
2773 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2774 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2776 /* merge them */
2778 if (candidates) {
2779 if (candidates2) {
2780 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2781 candidates->push_back (*i);
2783 delete candidates2;
2785 } else {
2786 candidates = candidates2; // might still be null
2789 /* find all sources, but don't use this snapshot because the
2790 state file on disk still references sources we may have already
2791 dropped.
2794 find_all_sources_across_snapshots (all_sources, true);
2796 /* add our current source list
2799 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2800 boost::shared_ptr<FileSource> fs;
2801 SourceMap::iterator tmp = i;
2802 ++tmp;
2804 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2805 if (playlists->source_use_count (fs) != 0) {
2806 all_sources.insert (fs->path());
2807 } else {
2809 /* we might not remove this source from disk, because it may be used
2810 by other snapshots, but its not being used in this version
2811 so lets get rid of it now, along with any representative regions
2812 in the region list.
2815 RegionFactory::remove_regions_using_source (i->second);
2816 sources.erase (i);
2820 i = tmp;
2823 char tmppath1[PATH_MAX+1];
2824 char tmppath2[PATH_MAX+1];
2826 if (candidates) {
2827 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2829 used = false;
2830 spath = **x;
2832 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2834 if (realpath(spath.c_str(), tmppath1) == 0) {
2835 error << string_compose (_("Cannot expand path %1 (%2)"),
2836 spath, strerror (errno)) << endmsg;
2837 continue;
2840 if (realpath((*i).c_str(), tmppath2) == 0) {
2841 error << string_compose (_("Cannot expand path %1 (%2)"),
2842 (*i), strerror (errno)) << endmsg;
2843 continue;
2846 if (strcmp(tmppath1, tmppath2) == 0) {
2847 used = true;
2848 break;
2852 if (!used) {
2853 unused.push_back (spath);
2856 delete *x;
2859 delete candidates;
2862 /* now try to move all unused files into the "dead" directory(ies) */
2864 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2865 struct stat statbuf;
2867 string newpath;
2869 /* don't move the file across filesystems, just
2870 stick it in the `dead_dir_name' directory
2871 on whichever filesystem it was already on.
2874 if ((*x).find ("/sounds/") != string::npos) {
2876 /* old school, go up 1 level */
2878 newpath = Glib::path_get_dirname (*x); // "sounds"
2879 newpath = Glib::path_get_dirname (newpath); // "session-name"
2881 } else {
2883 /* new school, go up 4 levels */
2885 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2886 newpath = Glib::path_get_dirname (newpath); // "session-name"
2887 newpath = Glib::path_get_dirname (newpath); // "interchange"
2888 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2891 newpath = Glib::build_filename (newpath, dead_dir_name);
2893 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2894 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2895 return -1;
2898 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2900 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2902 /* the new path already exists, try versioning */
2904 char buf[PATH_MAX+1];
2905 int version = 1;
2906 string newpath_v;
2908 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2909 newpath_v = buf;
2911 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2912 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2913 newpath_v = buf;
2916 if (version == 999) {
2917 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2918 newpath)
2919 << endmsg;
2920 } else {
2921 newpath = newpath_v;
2924 } else {
2926 /* it doesn't exist, or we can't read it or something */
2930 stat ((*x).c_str(), &statbuf);
2932 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2933 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2934 (*x), newpath, strerror (errno))
2935 << endmsg;
2936 goto out;
2939 /* see if there an easy to find peakfile for this file, and remove it.
2942 string base = basename_nosuffix (*x);
2943 base += "%A"; /* this is what we add for the channel suffix of all native files,
2944 or for the first channel of embedded files. it will miss
2945 some peakfiles for other channels
2947 string peakpath = peak_path (base);
2949 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2950 if (::unlink (peakpath.c_str()) != 0) {
2951 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2952 peakpath, _path, strerror (errno))
2953 << endmsg;
2954 /* try to back out */
2955 ::rename (newpath.c_str(), _path.c_str());
2956 goto out;
2960 rep.paths.push_back (*x);
2961 rep.space += statbuf.st_size;
2964 /* dump the history list */
2966 _history.clear ();
2968 /* save state so we don't end up a session file
2969 referring to non-existent sources.
2972 save_state ("");
2973 ret = 0;
2975 out:
2976 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2978 return ret;
2982 Session::cleanup_trash_sources (CleanupReport& rep)
2984 // FIXME: needs adaptation for MIDI
2986 vector<space_and_path>::iterator i;
2987 string dead_dir;
2989 rep.paths.clear ();
2990 rep.space = 0;
2992 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2994 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2996 clear_directory (dead_dir, &rep.space, &rep.paths);
2999 return 0;
3002 void
3003 Session::set_dirty ()
3005 bool was_dirty = dirty();
3007 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3010 if (!was_dirty) {
3011 DirtyChanged(); /* EMIT SIGNAL */
3016 void
3017 Session::set_clean ()
3019 bool was_dirty = dirty();
3021 _state_of_the_state = Clean;
3024 if (was_dirty) {
3025 DirtyChanged(); /* EMIT SIGNAL */
3029 void
3030 Session::set_deletion_in_progress ()
3032 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3035 void
3036 Session::clear_deletion_in_progress ()
3038 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3041 void
3042 Session::add_controllable (boost::shared_ptr<Controllable> c)
3044 /* this adds a controllable to the list managed by the Session.
3045 this is a subset of those managed by the Controllable class
3046 itself, and represents the only ones whose state will be saved
3047 as part of the session.
3050 Glib::Mutex::Lock lm (controllables_lock);
3051 controllables.insert (c);
3054 struct null_deleter { void operator()(void const *) const {} };
3056 void
3057 Session::remove_controllable (Controllable* c)
3059 if (_state_of_the_state | Deletion) {
3060 return;
3063 Glib::Mutex::Lock lm (controllables_lock);
3065 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3067 if (x != controllables.end()) {
3068 controllables.erase (x);
3072 boost::shared_ptr<Controllable>
3073 Session::controllable_by_id (const PBD::ID& id)
3075 Glib::Mutex::Lock lm (controllables_lock);
3077 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3078 if ((*i)->id() == id) {
3079 return *i;
3083 return boost::shared_ptr<Controllable>();
3086 boost::shared_ptr<Controllable>
3087 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3089 boost::shared_ptr<Controllable> c;
3090 boost::shared_ptr<Route> r;
3092 switch (desc.top_level_type()) {
3093 case ControllableDescriptor::NamedRoute:
3095 std::string str = desc.top_level_name();
3096 if (str == "master") {
3097 r = _master_out;
3098 } else if (str == "control" || str == "listen") {
3099 r = _monitor_out;
3100 } else {
3101 r = route_by_name (desc.top_level_name());
3103 break;
3106 case ControllableDescriptor::RemoteControlID:
3107 r = route_by_remote_id (desc.rid());
3108 break;
3111 if (!r) {
3112 return c;
3115 switch (desc.subtype()) {
3116 case ControllableDescriptor::Gain:
3117 c = r->gain_control ();
3118 break;
3120 case ControllableDescriptor::Solo:
3121 c = r->solo_control();
3122 break;
3124 case ControllableDescriptor::Mute:
3125 c = r->mute_control();
3126 break;
3128 case ControllableDescriptor::Recenable:
3130 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3132 if (t) {
3133 c = t->rec_enable_control ();
3135 break;
3138 case ControllableDescriptor::PanDirection:
3140 c = r->pannable()->pan_azimuth_control;
3141 break;
3144 case ControllableDescriptor::PanWidth:
3146 c = r->pannable()->pan_width_control;
3147 break;
3150 case ControllableDescriptor::PanElevation:
3152 c = r->pannable()->pan_elevation_control;
3153 break;
3156 case ControllableDescriptor::Balance:
3157 /* XXX simple pan control */
3158 break;
3160 case ControllableDescriptor::PluginParameter:
3162 uint32_t plugin = desc.target (0);
3163 uint32_t parameter_index = desc.target (1);
3165 /* revert to zero based counting */
3167 if (plugin > 0) {
3168 --plugin;
3171 if (parameter_index > 0) {
3172 --parameter_index;
3175 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3177 if (p) {
3178 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3179 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3181 break;
3184 case ControllableDescriptor::SendGain:
3186 uint32_t send = desc.target (0);
3188 /* revert to zero-based counting */
3190 if (send > 0) {
3191 --send;
3194 boost::shared_ptr<Processor> p = r->nth_send (send);
3196 if (p) {
3197 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3198 boost::shared_ptr<Amp> a = s->amp();
3200 if (a) {
3201 c = s->amp()->gain_control();
3204 break;
3207 default:
3208 /* relax and return a null pointer */
3209 break;
3212 return c;
3215 void
3216 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3218 if (_writable) {
3219 Stateful::add_instant_xml (node, _path);
3222 if (write_to_config) {
3223 Config->add_instant_xml (node);
3227 XMLNode*
3228 Session::instant_xml (const string& node_name)
3230 return Stateful::instant_xml (node_name, _path);
3234 Session::save_history (string snapshot_name)
3236 XMLTree tree;
3238 if (!_writable) {
3239 return 0;
3242 if (snapshot_name.empty()) {
3243 snapshot_name = _current_snapshot_name;
3246 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3247 const string backup_filename = history_filename + backup_suffix;
3248 const sys::path xml_path = _session_dir->root_path() / history_filename;
3249 const sys::path backup_path = _session_dir->root_path() / backup_filename;
3251 if (sys::exists (xml_path)) {
3254 sys::rename (xml_path, backup_path);
3256 catch (const sys::filesystem_error& err)
3258 error << _("could not backup old history file, current history not saved") << endmsg;
3259 return -1;
3263 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3264 return 0;
3267 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3269 if (!tree.write (xml_path.to_string()))
3271 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
3275 sys::remove (xml_path);
3276 sys::rename (backup_path, xml_path);
3278 catch (const sys::filesystem_error& err)
3280 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3281 backup_path.to_string(), err.what()) << endmsg;
3284 return -1;
3287 return 0;
3291 Session::restore_history (string snapshot_name)
3293 XMLTree tree;
3295 if (snapshot_name.empty()) {
3296 snapshot_name = _current_snapshot_name;
3299 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3300 const sys::path xml_path = _session_dir->root_path() / xml_filename;
3302 info << "Loading history from " << xml_path.to_string() << endmsg;
3304 if (!sys::exists (xml_path)) {
3305 info << string_compose (_("%1: no history file \"%2\" for this session."),
3306 _name, xml_path.to_string()) << endmsg;
3307 return 1;
3310 if (!tree.read (xml_path.to_string())) {
3311 error << string_compose (_("Could not understand session history file \"%1\""),
3312 xml_path.to_string()) << endmsg;
3313 return -1;
3316 // replace history
3317 _history.clear();
3319 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3321 XMLNode *t = *it;
3322 UndoTransaction* ut = new UndoTransaction ();
3323 struct timeval tv;
3325 ut->set_name(t->property("name")->value());
3326 stringstream ss(t->property("tv-sec")->value());
3327 ss >> tv.tv_sec;
3328 ss.str(t->property("tv-usec")->value());
3329 ss >> tv.tv_usec;
3330 ut->set_timestamp(tv);
3332 for (XMLNodeConstIterator child_it = t->children().begin();
3333 child_it != t->children().end(); child_it++)
3335 XMLNode *n = *child_it;
3336 Command *c;
3338 if (n->name() == "MementoCommand" ||
3339 n->name() == "MementoUndoCommand" ||
3340 n->name() == "MementoRedoCommand") {
3342 if ((c = memento_command_factory(n))) {
3343 ut->add_command(c);
3346 } else if (n->name() == "NoteDiffCommand") {
3347 PBD::ID id (n->property("midi-source")->value());
3348 boost::shared_ptr<MidiSource> midi_source =
3349 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3350 if (midi_source) {
3351 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3352 } else {
3353 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3356 } else if (n->name() == "SysExDiffCommand") {
3358 PBD::ID id (n->property("midi-source")->value());
3359 boost::shared_ptr<MidiSource> midi_source =
3360 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3361 if (midi_source) {
3362 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3363 } else {
3364 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3367 } else if (n->name() == "PatchChangeDiffCommand") {
3369 PBD::ID id (n->property("midi-source")->value());
3370 boost::shared_ptr<MidiSource> midi_source =
3371 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3372 if (midi_source) {
3373 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3374 } else {
3375 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3378 } else if (n->name() == "StatefulDiffCommand") {
3379 if ((c = stateful_diff_command_factory (n))) {
3380 ut->add_command (c);
3382 } else {
3383 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3387 _history.add (ut);
3390 return 0;
3393 void
3394 Session::config_changed (std::string p, bool ours)
3396 if (ours) {
3397 set_dirty ();
3400 if (p == "seamless-loop") {
3402 } else if (p == "rf-speed") {
3404 } else if (p == "auto-loop") {
3406 } else if (p == "auto-input") {
3408 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3409 /* auto-input only makes a difference if we're rolling */
3410 set_track_monitor_input_status (!config.get_auto_input());
3413 } else if (p == "punch-in") {
3415 Location* location;
3417 if ((location = _locations->auto_punch_location()) != 0) {
3419 if (config.get_punch_in ()) {
3420 replace_event (SessionEvent::PunchIn, location->start());
3421 } else {
3422 remove_event (location->start(), SessionEvent::PunchIn);
3426 } else if (p == "punch-out") {
3428 Location* location;
3430 if ((location = _locations->auto_punch_location()) != 0) {
3432 if (config.get_punch_out()) {
3433 replace_event (SessionEvent::PunchOut, location->end());
3434 } else {
3435 clear_events (SessionEvent::PunchOut);
3439 } else if (p == "edit-mode") {
3441 Glib::Mutex::Lock lm (playlists->lock);
3443 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3444 (*i)->set_edit_mode (Config->get_edit_mode ());
3447 } else if (p == "use-video-sync") {
3449 waiting_for_sync_offset = config.get_use_video_sync();
3451 } else if (p == "mmc-control") {
3453 //poke_midi_thread ();
3455 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3457 MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
3459 } else if (p == "mmc-send-id") {
3461 MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
3463 } else if (p == "midi-control") {
3465 //poke_midi_thread ();
3467 } else if (p == "raid-path") {
3469 setup_raid_path (config.get_raid_path());
3471 } else if (p == "timecode-format") {
3473 sync_time_vars ();
3475 } else if (p == "video-pullup") {
3477 sync_time_vars ();
3479 } else if (p == "seamless-loop") {
3481 if (play_loop && transport_rolling()) {
3482 // to reset diskstreams etc
3483 request_play_loop (true);
3486 } else if (p == "rf-speed") {
3488 cumulative_rf_motion = 0;
3489 reset_rf_scale (0);
3491 } else if (p == "click-sound") {
3493 setup_click_sounds (1);
3495 } else if (p == "click-emphasis-sound") {
3497 setup_click_sounds (-1);
3499 } else if (p == "clicking") {
3501 if (Config->get_clicking()) {
3502 if (_click_io && click_data) { // don't require emphasis data
3503 _clicking = true;
3505 } else {
3506 _clicking = false;
3509 } else if (p == "send-mtc") {
3511 if (Config->get_send_mtc ()) {
3512 /* mark us ready to send */
3513 next_quarter_frame_to_send = 0;
3516 } else if (p == "send-mmc") {
3518 MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
3520 } else if (p == "midi-feedback") {
3522 session_midi_feedback = Config->get_midi_feedback();
3524 } else if (p == "jack-time-master") {
3526 engine().reset_timebase ();
3528 } else if (p == "native-file-header-format") {
3530 if (!first_file_header_format_reset) {
3531 reset_native_file_format ();
3534 first_file_header_format_reset = false;
3536 } else if (p == "native-file-data-format") {
3538 if (!first_file_data_format_reset) {
3539 reset_native_file_format ();
3542 first_file_data_format_reset = false;
3544 } else if (p == "external-sync") {
3545 if (!config.get_external_sync()) {
3546 drop_sync_source ();
3547 } else {
3548 switch_to_sync_source (config.get_sync_source());
3550 } else if (p == "remote-model") {
3551 set_remote_control_ids ();
3552 } else if (p == "denormal-model") {
3553 setup_fpu ();
3554 } else if (p == "history-depth") {
3555 set_history_depth (Config->get_history_depth());
3556 } else if (p == "sync-all-route-ordering") {
3557 sync_order_keys ("session");
3558 } else if (p == "initial-program-change") {
3560 if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
3561 MIDI::byte buf[2];
3563 buf[0] = MIDI::program; // channel zero by default
3564 buf[1] = (Config->get_initial_program_change() & 0x7f);
3566 MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
3568 } else if (p == "solo-mute-override") {
3569 // catch_up_on_solo_mute_override ();
3570 } else if (p == "listen-position" || p == "pfl-position") {
3571 listen_position_changed ();
3572 } else if (p == "solo-control-is-listen-control") {
3573 solo_control_mode_changed ();
3574 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3575 last_timecode_valid = false;
3576 } else if (p == "playback-buffer-seconds") {
3577 AudioSource::allocate_working_buffers (frame_rate());
3580 set_dirty ();
3583 void
3584 Session::set_history_depth (uint32_t d)
3586 _history.set_depth (d);
3590 Session::load_diskstreams_2X (XMLNode const & node, int)
3592 XMLNodeList clist;
3593 XMLNodeConstIterator citer;
3595 clist = node.children();
3597 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3599 try {
3600 /* diskstreams added automatically by DiskstreamCreated handler */
3601 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3602 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3603 _diskstreams_2X.push_back (dsp);
3604 } else {
3605 error << _("Session: unknown diskstream type in XML") << endmsg;
3609 catch (failed_constructor& err) {
3610 error << _("Session: could not load diskstream via XML state") << endmsg;
3611 return -1;
3615 return 0;
3618 /** Connect things to the MMC object */
3619 void
3620 Session::setup_midi_machine_control ()
3622 MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
3624 mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3625 mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3626 mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3627 mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3628 mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3629 mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3630 mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3631 mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3632 mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3633 mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3634 mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3635 mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3636 mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3638 /* also handle MIDI SPP because its so common */
3640 mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this, _1, _2));
3641 mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this, _1, _2));
3642 mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this, _1, _2));
3645 boost::shared_ptr<Controllable>
3646 Session::solo_cut_control() const
3648 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3649 controls in Ardour that currently get presented to the user in the GUI that require
3650 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3652 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3653 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3654 parameter.
3657 return _solo_cut_control;
3661 Session::rename (const std::string& new_name)
3663 string legal_name = legalize_for_path (new_name);
3664 string newpath;
3665 string oldstr;
3666 string newstr;
3667 bool first = true;
3669 #define RENAME ::rename
3671 /* Rename:
3673 * session directory
3674 * interchange subdirectory
3675 * session file
3676 * session history
3678 * Backup files are left unchanged and not renamed.
3681 /* pass one: not 100% safe check that the new directory names don't
3682 * already exist ...
3685 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3686 vector<string> v;
3688 oldstr = (*i).path;
3690 /* this is a stupid hack because Glib::path_get_dirname() is
3691 * lexical-only, and so passing it /a/b/c/ gives a different
3692 * result than passing it /a/b/c ...
3695 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3696 oldstr = oldstr.substr (0, oldstr.length() - 1);
3699 string base = Glib::path_get_dirname (oldstr);
3700 string p = Glib::path_get_basename (oldstr);
3702 newstr = Glib::build_filename (base, legal_name);
3704 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3705 return -1;
3709 /* Session dirs */
3711 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3712 vector<string> v;
3714 oldstr = (*i).path;
3716 /* this is a stupid hack because Glib::path_get_dirname() is
3717 * lexical-only, and so passing it /a/b/c/ gives a different
3718 * result than passing it /a/b/c ...
3721 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3722 oldstr = oldstr.substr (0, oldstr.length() - 1);
3725 string base = Glib::path_get_dirname (oldstr);
3726 string p = Glib::path_get_basename (oldstr);
3728 newstr = Glib::build_filename (base, legal_name);
3730 cerr << "Rename " << oldstr << " => " << newstr << endl;
3732 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3733 return 1;
3736 if (first) {
3737 (*_session_dir) = newstr;
3738 newpath = newstr;
3739 first = 1;
3742 /* directory below interchange */
3744 v.push_back (newstr);
3745 v.push_back (interchange_dir_name);
3746 v.push_back (p);
3748 oldstr = Glib::build_filename (v);
3750 v.clear ();
3751 v.push_back (newstr);
3752 v.push_back (interchange_dir_name);
3753 v.push_back (legal_name);
3755 newstr = Glib::build_filename (v);
3757 cerr << "Rename " << oldstr << " => " << newstr << endl;
3759 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3760 return 1;
3764 /* state file */
3766 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3767 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3769 cerr << "Rename " << oldstr << " => " << newstr << endl;
3771 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3772 return 1;
3775 /* history file */
3777 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3778 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3780 cerr << "Rename " << oldstr << " => " << newstr << endl;
3782 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3783 return 1;
3786 _path = newpath;
3787 _current_snapshot_name = new_name;
3788 _name = new_name;
3790 set_dirty ();
3792 /* save state again to get everything just right */
3794 save_state (_current_snapshot_name);
3796 return 0;
3798 #undef RENAME