track changes to config parameters for MMC device id's correctly (from roy vegard)
[ardour2.git] / libs / ardour / session_state.cc
blob074527dc33d929b994f7db051c91ba40cbf41fb1
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/recent_sessions.h"
104 #include "ardour/region_factory.h"
105 #include "ardour/route_group.h"
106 #include "ardour/send.h"
107 #include "ardour/session.h"
108 #include "ardour/session_directory.h"
109 #include "ardour/session_metadata.h"
110 #include "ardour/session_state_utils.h"
111 #include "ardour/session_playlists.h"
112 #include "ardour/session_utils.h"
113 #include "ardour/silentfilesource.h"
114 #include "ardour/slave.h"
115 #include "ardour/smf_source.h"
116 #include "ardour/sndfile_helpers.h"
117 #include "ardour/sndfilesource.h"
118 #include "ardour/source_factory.h"
119 #include "ardour/template_utils.h"
120 #include "ardour/tempo.h"
121 #include "ardour/ticker.h"
122 #include "ardour/user_bundle.h"
123 #include "ardour/utils.h"
124 #include "ardour/utils.h"
125 #include "ardour/version.h"
126 #include "ardour/playlist_factory.h"
128 #include "control_protocol/control_protocol.h"
130 #include "i18n.h"
131 #include <locale.h>
133 using namespace std;
134 using namespace ARDOUR;
135 using namespace PBD;
138 void
139 Session::first_stage_init (string fullpath, string snapshot_name)
141 if (fullpath.length() == 0) {
142 destroy ();
143 throw failed_constructor();
146 char buf[PATH_MAX+1];
147 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
148 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
149 destroy ();
150 throw failed_constructor();
153 _path = string(buf);
155 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
156 _path += G_DIR_SEPARATOR;
159 /* these two are just provisional settings. set_state()
160 will likely override them.
163 _name = _current_snapshot_name = snapshot_name;
165 set_history_depth (Config->get_history_depth());
167 _current_frame_rate = _engine.frame_rate ();
168 _nominal_frame_rate = _current_frame_rate;
169 _base_frame_rate = _current_frame_rate;
171 _tempo_map = new TempoMap (_current_frame_rate);
172 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
175 _non_soloed_outs_muted = false;
176 _listen_cnt = 0;
177 _solo_isolated_cnt = 0;
178 g_atomic_int_set (&processing_prohibited, 0);
179 _transport_speed = 0;
180 _last_transport_speed = 0;
181 _target_transport_speed = 0;
182 auto_play_legal = false;
183 transport_sub_state = 0;
184 _transport_frame = 0;
185 _requested_return_frame = -1;
186 _session_range_location = 0;
187 g_atomic_int_set (&_record_status, Disabled);
188 loop_changing = false;
189 play_loop = false;
190 have_looped = false;
191 _last_roll_location = 0;
192 _last_roll_or_reversal_location = 0;
193 _last_record_location = 0;
194 pending_locate_frame = 0;
195 pending_locate_roll = false;
196 pending_locate_flush = false;
197 state_was_pending = false;
198 set_next_event ();
199 outbound_mtc_timecode_frame = 0;
200 next_quarter_frame_to_send = -1;
201 current_block_size = 0;
202 solo_update_disabled = false;
203 _have_captured = false;
204 _worst_output_latency = 0;
205 _worst_input_latency = 0;
206 _worst_track_latency = 0;
207 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
208 _was_seamless = Config->get_seamless_loop ();
209 _slave = 0;
210 _send_qf_mtc = false;
211 _pframes_since_last_mtc = 0;
212 g_atomic_int_set (&_playback_load, 100);
213 g_atomic_int_set (&_capture_load, 100);
214 _play_range = false;
215 _exporting = false;
216 pending_abort = false;
217 destructive_index = 0;
218 first_file_data_format_reset = true;
219 first_file_header_format_reset = true;
220 post_export_sync = false;
221 midi_control_ui = 0;
222 _step_editors = 0;
223 no_questions_about_missing_files = false;
224 _speakers.reset (new Speakers);
226 AudioDiskstream::allocate_working_buffers();
228 /* default short fade = 15ms */
230 Crossfade::set_short_xfade_length ((framecnt_t) floor (config.get_short_xfade_seconds() * frame_rate()));
231 SndFileSource::setup_standard_crossfades (*this, frame_rate());
233 last_mmc_step.tv_sec = 0;
234 last_mmc_step.tv_usec = 0;
235 step_speed = 0.0;
237 /* click sounds are unset by default, which causes us to internal
238 waveforms for clicks.
241 click_length = 0;
242 click_emphasis_length = 0;
243 _clicking = false;
245 process_function = &Session::process_with_events;
247 if (config.get_use_video_sync()) {
248 waiting_for_sync_offset = true;
249 } else {
250 waiting_for_sync_offset = false;
253 last_timecode_when = 0;
254 last_timecode_valid = false;
256 sync_time_vars ();
258 last_rr_session_dir = session_dirs.begin();
259 refresh_disk_space ();
261 /* default: assume simple stereo speaker configuration */
263 _speakers->setup_default_speakers (2);
265 /* slave stuff */
267 average_slave_delta = 1800; // !!! why 1800 ????
268 have_first_delta_accumulator = false;
269 delta_accumulator_cnt = 0;
270 _slave_state = Stopped;
272 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
273 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
274 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
275 add_controllable (_solo_cut_control);
277 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
279 /* These are all static "per-class" signals */
281 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
282 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
283 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
284 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
285 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
287 /* stop IO objects from doing stuff until we're ready for them */
289 Delivery::disable_panners ();
290 IO::disable_connecting ();
294 Session::second_stage_init ()
296 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
298 if (!_is_new) {
299 if (load_state (_current_snapshot_name)) {
300 return -1;
304 if (_butler->start_thread()) {
305 return -1;
308 if (start_midi_thread ()) {
309 return -1;
312 setup_midi_machine_control ();
314 // set_state() will call setup_raid_path(), but if it's a new session we need
315 // to call setup_raid_path() here.
317 if (state_tree) {
318 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
319 return -1;
321 } else {
322 setup_raid_path(_path);
325 /* we can't save till after ::when_engine_running() is called,
326 because otherwise we save state with no connections made.
327 therefore, we reset _state_of_the_state because ::set_state()
328 will have cleared it.
330 we also have to include Loading so that any events that get
331 generated between here and the end of ::when_engine_running()
332 will be processed directly rather than queued.
335 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
337 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
338 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
339 setup_click_sounds (0);
340 setup_midi_control ();
342 /* Pay attention ... */
344 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
345 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
347 try {
348 when_engine_running ();
351 /* handle this one in a different way than all others, so that its clear what happened */
353 catch (AudioEngine::PortRegistrationFailure& err) {
354 error << err.what() << endmsg;
355 return -1;
358 catch (...) {
359 return -1;
362 BootMessage (_("Reset Remote Controls"));
364 send_full_time_code (0);
365 _engine.transport_locate (0);
367 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
368 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
370 MidiClockTicker::instance().set_session (this);
371 MIDI::Name::MidiPatchManager::instance().set_session (this);
373 /* initial program change will be delivered later; see ::config_changed() */
375 _state_of_the_state = Clean;
377 Port::set_connecting_blocked (false);
379 DirtyChanged (); /* EMIT SIGNAL */
381 if (state_was_pending) {
382 save_state (_current_snapshot_name);
383 remove_pending_capture_state ();
384 state_was_pending = false;
387 BootMessage (_("Session loading complete"));
389 return 0;
392 string
393 Session::raid_path () const
395 SearchPath raid_search_path;
397 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
398 raid_search_path += sys::path((*i).path);
401 return raid_search_path.to_string ();
404 void
405 Session::setup_raid_path (string path)
407 if (path.empty()) {
408 return;
411 space_and_path sp;
412 string fspath;
414 session_dirs.clear ();
416 SearchPath search_path(path);
417 SearchPath sound_search_path;
418 SearchPath midi_search_path;
420 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
421 sp.path = (*i).to_string ();
422 sp.blocks = 0; // not needed
423 session_dirs.push_back (sp);
425 SessionDirectory sdir(sp.path);
427 sound_search_path += sdir.sound_path ();
428 midi_search_path += sdir.midi_path ();
431 // reset the round-robin soundfile path thingie
432 last_rr_session_dir = session_dirs.begin();
435 bool
436 Session::path_is_within_session (const std::string& path)
438 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
439 if (path.find ((*i).path) == 0) {
440 return true;
443 return false;
447 Session::ensure_subdirs ()
449 string dir;
451 dir = session_directory().peak_path().to_string();
453 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
454 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
455 return -1;
458 dir = session_directory().sound_path().to_string();
460 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
461 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
462 return -1;
465 dir = session_directory().midi_path().to_string();
467 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
468 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
469 return -1;
472 dir = session_directory().dead_path().to_string();
474 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
475 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
476 return -1;
479 dir = session_directory().export_path().to_string();
481 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
482 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
483 return -1;
486 dir = analysis_dir ();
488 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
489 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
490 return -1;
493 dir = plugins_dir ();
495 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
496 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
497 return -1;
500 return 0;
503 /** Caller must not hold process lock */
505 Session::create (const string& mix_template, BusProfile* bus_profile)
507 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
508 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
509 return -1;
512 if (ensure_subdirs ()) {
513 return -1;
516 _writable = exists_and_writable (sys::path (_path));
518 if (!mix_template.empty()) {
519 std::string in_path = mix_template;
521 ifstream in(in_path.c_str());
523 if (in) {
524 string out_path = _path;
525 out_path += _name;
526 out_path += statefile_suffix;
528 ofstream out(out_path.c_str());
530 if (out) {
531 out << in.rdbuf();
532 _is_new = false;
533 return 0;
535 } else {
536 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
537 << endmsg;
538 return -1;
541 } else {
542 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
543 << endmsg;
544 return -1;
549 /* Instantiate metadata */
551 _metadata = new SessionMetadata ();
553 /* set initial start + end point */
555 _state_of_the_state = Clean;
557 /* set up Master Out and Control Out if necessary */
559 if (bus_profile) {
561 RouteList rl;
562 int control_id = 1;
563 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
565 if (bus_profile->master_out_channels) {
566 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
567 if (r->init ()) {
568 return -1;
570 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
571 boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
572 #endif
574 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
575 r->input()->ensure_io (count, false, this);
576 r->output()->ensure_io (count, false, this);
578 r->set_remote_control_id (control_id++);
580 rl.push_back (r);
582 if (Config->get_use_monitor_bus()) {
583 boost::shared_ptr<Route> r (new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO));
584 if (r->init ()) {
585 return -1;
587 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
588 boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
589 #endif
591 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
592 r->input()->ensure_io (count, false, this);
593 r->output()->ensure_io (count, false, this);
595 r->set_remote_control_id (control_id);
597 rl.push_back (r);
600 } else {
601 /* prohibit auto-connect to master, because there isn't one */
602 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
605 if (!rl.empty()) {
606 add_routes (rl, false, false);
609 /* this allows the user to override settings with an environment variable.
612 if (no_auto_connect()) {
613 bus_profile->input_ac = AutoConnectOption (0);
614 bus_profile->output_ac = AutoConnectOption (0);
617 Config->set_input_auto_connect (bus_profile->input_ac);
618 Config->set_output_auto_connect (bus_profile->output_ac);
621 save_state ("");
623 return 0;
626 void
627 Session::maybe_write_autosave()
629 if (dirty() && record_status() != Recording) {
630 save_state("", true);
634 void
635 Session::remove_pending_capture_state ()
637 sys::path pending_state_file_path(_session_dir->root_path());
639 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
643 sys::remove (pending_state_file_path);
645 catch(sys::filesystem_error& ex)
647 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
648 pending_state_file_path.to_string(), ex.what()) << endmsg;
652 /** Rename a state file.
653 * @param old_name Old snapshot name.
654 * @param new_name New snapshot name.
656 void
657 Session::rename_state (string old_name, string new_name)
659 if (old_name == _current_snapshot_name || old_name == _name) {
660 /* refuse to rename the current snapshot or the "main" one */
661 return;
664 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
665 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
667 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
668 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
672 sys::rename (old_xml_path, new_xml_path);
674 catch (const sys::filesystem_error& err)
676 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
677 old_name, new_name, err.what()) << endmsg;
681 /** Remove a state file.
682 * @param snapshot_name Snapshot name.
684 void
685 Session::remove_state (string snapshot_name)
687 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
688 // refuse to remove the current snapshot or the "main" one
689 return;
692 sys::path xml_path(_session_dir->root_path());
694 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
696 if (!create_backup_file (xml_path)) {
697 // don't remove it if a backup can't be made
698 // create_backup_file will log the error.
699 return;
702 // and delete it
703 sys::remove (xml_path);
706 #ifdef HAVE_JACK_SESSION
707 void
708 Session::jack_session_event (jack_session_event_t * event)
710 char timebuf[128];
711 time_t n;
712 struct tm local_time;
714 time (&n);
715 localtime_r (&n, &local_time);
716 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
718 if (event->type == JackSessionSaveTemplate)
720 if (save_template( timebuf )) {
721 event->flags = JackSessionSaveError;
722 } else {
723 string cmd ("ardour3 -P -U ");
724 cmd += event->client_uuid;
725 cmd += " -T ";
726 cmd += timebuf;
728 event->command_line = strdup (cmd.c_str());
731 else
733 if (save_state (timebuf)) {
734 event->flags = JackSessionSaveError;
735 } else {
736 sys::path xml_path (_session_dir->root_path());
737 xml_path /= legalize_for_path (timebuf) + statefile_suffix;
739 string cmd ("ardour3 -P -U ");
740 cmd += event->client_uuid;
741 cmd += " \"";
742 cmd += xml_path.to_string();
743 cmd += '\"';
745 event->command_line = strdup (cmd.c_str());
749 jack_session_reply (_engine.jack(), event);
751 if (event->type == JackSessionSaveAndQuit) {
752 Quit (); /* EMIT SIGNAL */
755 jack_session_event_free( event );
757 #endif
759 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
761 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
763 XMLTree tree;
764 sys::path xml_path(_session_dir->root_path());
766 if (!_writable || (_state_of_the_state & CannotSave)) {
767 return 1;
770 if (!_engine.connected ()) {
771 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
772 PROGRAM_NAME)
773 << endmsg;
774 return 1;
777 /* tell sources we're saving first, in case they write out to a new file
778 * which should be saved with the state rather than the old one */
779 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
780 i->second->session_saved();
783 tree.set_root (&get_state());
785 if (snapshot_name.empty()) {
786 snapshot_name = _current_snapshot_name;
787 } else if (switch_to_snapshot) {
788 _current_snapshot_name = snapshot_name;
791 if (!pending) {
793 /* proper save: use statefile_suffix (.ardour in English) */
795 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
797 /* make a backup copy of the old file */
799 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
800 // create_backup_file will log the error
801 return -1;
804 } else {
806 /* pending save: use pending_suffix (.pending in English) */
807 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
810 sys::path tmp_path(_session_dir->root_path());
812 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
814 // cerr << "actually writing state to " << xml_path.to_string() << endl;
816 if (!tree.write (tmp_path.to_string())) {
817 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
818 sys::remove (tmp_path);
819 return -1;
821 } else {
823 if (::rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
824 error << string_compose (_("could not rename temporary session file %1 to %2"),
825 tmp_path.to_string(), xml_path.to_string()) << endmsg;
826 sys::remove (tmp_path);
827 return -1;
831 if (!pending) {
833 save_history (snapshot_name);
835 bool was_dirty = dirty();
837 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
839 if (was_dirty) {
840 DirtyChanged (); /* EMIT SIGNAL */
843 StateSaved (snapshot_name); /* EMIT SIGNAL */
846 return 0;
850 Session::restore_state (string snapshot_name)
852 if (load_state (snapshot_name) == 0) {
853 set_state (*state_tree->root(), Stateful::loading_state_version);
856 return 0;
860 Session::load_state (string snapshot_name)
862 delete state_tree;
863 state_tree = 0;
865 state_was_pending = false;
867 /* check for leftover pending state from a crashed capture attempt */
869 sys::path xmlpath(_session_dir->root_path());
870 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
872 if (sys::exists (xmlpath)) {
874 /* there is pending state from a crashed capture attempt */
876 boost::optional<int> r = AskAboutPendingState();
877 if (r.get_value_or (1)) {
878 state_was_pending = true;
882 if (!state_was_pending) {
883 xmlpath = _session_dir->root_path();
884 xmlpath /= snapshot_name;
887 if (!sys::exists (xmlpath)) {
888 xmlpath = _session_dir->root_path();
889 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
890 if (!sys::exists (xmlpath)) {
891 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
892 return 1;
896 state_tree = new XMLTree;
898 set_dirty();
900 _writable = exists_and_writable (xmlpath);
902 if (!state_tree->read (xmlpath.to_string())) {
903 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
904 delete state_tree;
905 state_tree = 0;
906 return -1;
909 XMLNode& root (*state_tree->root());
911 if (root.name() != X_("Session")) {
912 error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg;
913 delete state_tree;
914 state_tree = 0;
915 return -1;
918 const XMLProperty* prop;
920 if ((prop = root.property ("version")) == 0) {
921 /* no version implies very old version of Ardour */
922 Stateful::loading_state_version = 1000;
923 } else {
924 int major;
925 int minor;
926 int micro;
928 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, &micro);
929 Stateful::loading_state_version = (major * 1000) + minor;
932 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
934 sys::path backup_path(_session_dir->root_path());
936 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
938 // only create a backup once
939 if (sys::exists (backup_path)) {
940 return 0;
943 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
944 xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME)
945 << endmsg;
949 sys::copy_file (xmlpath, backup_path);
951 catch(sys::filesystem_error& ex)
953 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
954 xmlpath.to_string(), ex.what())
955 << endmsg;
956 return -1;
960 return 0;
964 Session::load_options (const XMLNode& node)
966 LocaleGuard lg (X_("POSIX"));
967 config.set_variables (node);
968 return 0;
971 XMLNode&
972 Session::get_state()
974 return state(true);
977 XMLNode&
978 Session::get_template()
980 /* if we don't disable rec-enable, diskstreams
981 will believe they need to store their capture
982 sources in their state node.
985 disable_record (false);
987 return state(false);
990 XMLNode&
991 Session::state(bool full_state)
993 XMLNode* node = new XMLNode("Session");
994 XMLNode* child;
996 // store libardour version, just in case
997 char buf[16];
998 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
999 node->add_property("version", string(buf));
1001 /* store configuration settings */
1003 if (full_state) {
1005 node->add_property ("name", _name);
1006 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
1007 node->add_property ("sample-rate", buf);
1009 if (session_dirs.size() > 1) {
1011 string p;
1013 vector<space_and_path>::iterator i = session_dirs.begin();
1014 vector<space_and_path>::iterator next;
1016 ++i; /* skip the first one */
1017 next = i;
1018 ++next;
1020 while (i != session_dirs.end()) {
1022 p += (*i).path;
1024 if (next != session_dirs.end()) {
1025 p += ':';
1026 } else {
1027 break;
1030 ++next;
1031 ++i;
1034 child = node->add_child ("Path");
1035 child->add_content (p);
1039 /* save the ID counter */
1041 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1042 node->add_property ("id-counter", buf);
1044 /* save the event ID counter */
1046 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1047 node->add_property ("event-counter", buf);
1049 /* various options */
1051 node->add_child_nocopy (config.get_variables ());
1053 node->add_child_nocopy (_metadata->get_state());
1055 child = node->add_child ("Sources");
1057 if (full_state) {
1058 Glib::Mutex::Lock sl (source_lock);
1060 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1062 /* Don't save information about non-file Sources, or
1063 * about non-destructive file sources that are empty
1064 * and unused by any regions.
1067 boost::shared_ptr<FileSource> fs;
1069 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1071 if (!fs->destructive()) {
1072 if (fs->empty() && !fs->used()) {
1073 continue;
1077 child->add_child_nocopy (siter->second->get_state());
1082 child = node->add_child ("Regions");
1084 if (full_state) {
1085 Glib::Mutex::Lock rl (region_lock);
1086 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1087 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1088 boost::shared_ptr<Region> r = i->second;
1089 /* only store regions not attached to playlists */
1090 if (r->playlist() == 0) {
1091 child->add_child_nocopy (r->state ());
1095 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1097 if (!cassocs.empty()) {
1098 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1100 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1101 char buf[64];
1102 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1103 i->first->id().print (buf, sizeof (buf));
1104 can->add_property (X_("copy"), buf);
1105 i->second->id().print (buf, sizeof (buf));
1106 can->add_property (X_("original"), buf);
1107 ca->add_child_nocopy (*can);
1112 if (full_state) {
1113 node->add_child_nocopy (_locations->get_state());
1114 } else {
1115 // for a template, just create a new Locations, populate it
1116 // with the default start and end, and get the state for that.
1117 Locations loc (*this);
1118 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1119 range->set (max_framepos, 0);
1120 loc.add (range);
1121 node->add_child_nocopy (loc.get_state());
1124 child = node->add_child ("Bundles");
1126 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1127 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1128 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1129 if (b) {
1130 child->add_child_nocopy (b->get_state());
1135 child = node->add_child ("Routes");
1137 boost::shared_ptr<RouteList> r = routes.reader ();
1139 RoutePublicOrderSorter cmp;
1140 RouteList public_order (*r);
1141 public_order.sort (cmp);
1143 /* the sort should have put control outs first */
1145 if (_monitor_out) {
1146 assert (_monitor_out == public_order.front());
1149 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1150 if (!(*i)->is_hidden()) {
1151 if (full_state) {
1152 child->add_child_nocopy ((*i)->get_state());
1153 } else {
1154 child->add_child_nocopy ((*i)->get_template());
1160 playlists->add_state (node, full_state);
1162 child = node->add_child ("RouteGroups");
1163 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1164 child->add_child_nocopy ((*i)->get_state());
1167 if (_click_io) {
1168 child = node->add_child ("Click");
1169 child->add_child_nocopy (_click_io->state (full_state));
1172 if (full_state) {
1173 child = node->add_child ("NamedSelections");
1174 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1175 if (full_state) {
1176 child->add_child_nocopy ((*i)->get_state());
1181 node->add_child_nocopy (_speakers->get_state());
1182 node->add_child_nocopy (_tempo_map->get_state());
1183 node->add_child_nocopy (get_control_protocol_state());
1185 if (_extra_xml) {
1186 node->add_child_copy (*_extra_xml);
1189 return *node;
1192 XMLNode&
1193 Session::get_control_protocol_state ()
1195 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1196 return cpm.get_state();
1200 Session::set_state (const XMLNode& node, int version)
1202 XMLNodeList nlist;
1203 XMLNode* child;
1204 const XMLProperty* prop;
1205 int ret = -1;
1207 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1209 if (node.name() != X_("Session")) {
1210 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1211 return -1;
1214 if ((prop = node.property ("version")) != 0) {
1215 version = atoi (prop->value ()) * 1000;
1218 if ((prop = node.property ("name")) != 0) {
1219 _name = prop->value ();
1222 if ((prop = node.property (X_("sample-rate"))) != 0) {
1224 _nominal_frame_rate = atoi (prop->value());
1226 if (_nominal_frame_rate != _current_frame_rate) {
1227 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1228 if (r.get_value_or (0)) {
1229 return -1;
1234 setup_raid_path(_session_dir->root_path().to_string());
1236 if ((prop = node.property (X_("id-counter"))) != 0) {
1237 uint64_t x;
1238 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1239 ID::init_counter (x);
1240 } else {
1241 /* old sessions used a timebased counter, so fake
1242 the startup ID counter based on a standard
1243 timestamp.
1245 time_t now;
1246 time (&now);
1247 ID::init_counter (now);
1250 if ((prop = node.property (X_("event-counter"))) != 0) {
1251 Evoral::init_event_id_counter (atoi (prop->value()));
1254 IO::disable_connecting ();
1256 Stateful::save_extra_xml (node);
1258 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1259 load_options (*child);
1260 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1261 load_options (*child);
1262 } else {
1263 error << _("Session: XML state has no options section") << endmsg;
1266 if (version >= 3000) {
1267 if ((child = find_named_node (node, "Metadata")) == 0) {
1268 warning << _("Session: XML state has no metadata section") << endmsg;
1269 } else if (_metadata->set_state (*child, version)) {
1270 goto out;
1274 if ((child = find_named_node (node, "Locations")) == 0) {
1275 error << _("Session: XML state has no locations section") << endmsg;
1276 goto out;
1277 } else if (_locations->set_state (*child, version)) {
1278 goto out;
1281 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1282 _speakers->set_state (*child, version);
1285 Location* location;
1287 if ((location = _locations->auto_loop_location()) != 0) {
1288 set_auto_loop_location (location);
1291 if ((location = _locations->auto_punch_location()) != 0) {
1292 set_auto_punch_location (location);
1295 if ((location = _locations->session_range_location()) != 0) {
1296 delete _session_range_location;
1297 _session_range_location = location;
1300 if (_session_range_location) {
1301 AudioFileSource::set_header_position_offset (_session_range_location->start());
1304 if ((child = find_named_node (node, "Sources")) == 0) {
1305 error << _("Session: XML state has no sources section") << endmsg;
1306 goto out;
1307 } else if (load_sources (*child)) {
1308 goto out;
1311 if ((child = find_named_node (node, "TempoMap")) == 0) {
1312 error << _("Session: XML state has no Tempo Map section") << endmsg;
1313 goto out;
1314 } else if (_tempo_map->set_state (*child, version)) {
1315 goto out;
1318 if ((child = find_named_node (node, "Regions")) == 0) {
1319 error << _("Session: XML state has no Regions section") << endmsg;
1320 goto out;
1321 } else if (load_regions (*child)) {
1322 goto out;
1325 if ((child = find_named_node (node, "Playlists")) == 0) {
1326 error << _("Session: XML state has no playlists section") << endmsg;
1327 goto out;
1328 } else if (playlists->load (*this, *child)) {
1329 goto out;
1332 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1333 // this is OK
1334 } else if (playlists->load_unused (*this, *child)) {
1335 goto out;
1338 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1339 if (load_compounds (*child)) {
1340 goto out;
1344 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1345 if (load_named_selections (*child)) {
1346 goto out;
1350 if (version >= 3000) {
1351 if ((child = find_named_node (node, "Bundles")) == 0) {
1352 warning << _("Session: XML state has no bundles section") << endmsg;
1353 //goto out;
1354 } else {
1355 /* We can't load Bundles yet as they need to be able
1356 to convert from port names to Port objects, which can't happen until
1357 later */
1358 _bundle_xml_node = new XMLNode (*child);
1362 if (version < 3000) {
1363 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1364 error << _("Session: XML state has no diskstreams section") << endmsg;
1365 goto out;
1366 } else if (load_diskstreams_2X (*child, version)) {
1367 goto out;
1371 if ((child = find_named_node (node, "Routes")) == 0) {
1372 error << _("Session: XML state has no routes section") << endmsg;
1373 goto out;
1374 } else if (load_routes (*child, version)) {
1375 goto out;
1378 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1379 _diskstreams_2X.clear ();
1381 if (version >= 3000) {
1383 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1384 error << _("Session: XML state has no route groups section") << endmsg;
1385 goto out;
1386 } else if (load_route_groups (*child, version)) {
1387 goto out;
1390 } else if (version < 3000) {
1392 if ((child = find_named_node (node, "EditGroups")) == 0) {
1393 error << _("Session: XML state has no edit groups section") << endmsg;
1394 goto out;
1395 } else if (load_route_groups (*child, version)) {
1396 goto out;
1399 if ((child = find_named_node (node, "MixGroups")) == 0) {
1400 error << _("Session: XML state has no mix groups section") << endmsg;
1401 goto out;
1402 } else if (load_route_groups (*child, version)) {
1403 goto out;
1407 if ((child = find_named_node (node, "Click")) == 0) {
1408 warning << _("Session: XML state has no click section") << endmsg;
1409 } else if (_click_io) {
1410 _click_io->set_state (*child, version);
1413 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1414 ControlProtocolManager::instance().set_protocol_states (*child);
1417 /* here beginneth the second phase ... */
1419 StateReady (); /* EMIT SIGNAL */
1421 return 0;
1423 out:
1424 return ret;
1428 Session::load_routes (const XMLNode& node, int version)
1430 XMLNodeList nlist;
1431 XMLNodeConstIterator niter;
1432 RouteList new_routes;
1434 nlist = node.children();
1436 set_dirty();
1438 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1440 boost::shared_ptr<Route> route;
1441 if (version < 3000) {
1442 route = XMLRouteFactory_2X (**niter, version);
1443 } else {
1444 route = XMLRouteFactory (**niter, version);
1447 if (route == 0) {
1448 error << _("Session: cannot create Route from XML description.") << endmsg;
1449 return -1;
1452 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1454 new_routes.push_back (route);
1457 add_routes (new_routes, false, false);
1459 return 0;
1462 boost::shared_ptr<Route>
1463 Session::XMLRouteFactory (const XMLNode& node, int version)
1465 boost::shared_ptr<Route> ret;
1467 if (node.name() != "Route") {
1468 return ret;
1471 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1473 DataType type = DataType::AUDIO;
1474 const XMLProperty* prop = node.property("default-type");
1476 if (prop) {
1477 type = DataType (prop->value());
1480 assert (type != DataType::NIL);
1482 if (ds_child) {
1484 boost::shared_ptr<Track> track;
1486 if (type == DataType::AUDIO) {
1487 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1488 } else {
1489 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1492 if (track->init()) {
1493 return ret;
1496 if (track->set_state (node, version)) {
1497 return ret;
1500 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1501 boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1502 #endif
1503 ret = track;
1505 } else {
1506 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1508 if (r->init () == 0 && r->set_state (node, version) == 0) {
1509 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1510 boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1511 #endif
1512 ret = r;
1516 return ret;
1519 boost::shared_ptr<Route>
1520 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1522 boost::shared_ptr<Route> ret;
1524 if (node.name() != "Route") {
1525 return ret;
1528 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1529 if (!ds_prop) {
1530 ds_prop = node.property (X_("diskstream"));
1533 DataType type = DataType::AUDIO;
1534 const XMLProperty* prop = node.property("default-type");
1536 if (prop) {
1537 type = DataType (prop->value());
1540 assert (type != DataType::NIL);
1542 if (ds_prop) {
1544 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1545 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1546 ++i;
1549 if (i == _diskstreams_2X.end()) {
1550 error << _("Could not find diskstream for route") << endmsg;
1551 return boost::shared_ptr<Route> ();
1554 boost::shared_ptr<Track> track;
1556 if (type == DataType::AUDIO) {
1557 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1558 } else {
1559 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1562 if (track->init()) {
1563 return ret;
1566 if (track->set_state (node, version)) {
1567 return ret;
1570 track->set_diskstream (*i);
1572 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1573 boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1574 #endif
1575 ret = track;
1577 } else {
1578 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1580 if (r->init () == 0 && r->set_state (node, version) == 0) {
1581 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1582 boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1583 #endif
1584 ret = r;
1588 return ret;
1592 Session::load_regions (const XMLNode& node)
1594 XMLNodeList nlist;
1595 XMLNodeConstIterator niter;
1596 boost::shared_ptr<Region> region;
1598 nlist = node.children();
1600 set_dirty();
1602 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1603 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1604 error << _("Session: cannot create Region from XML description.");
1605 const XMLProperty *name = (**niter).property("name");
1607 if (name) {
1608 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1611 error << endmsg;
1615 return 0;
1619 Session::load_compounds (const XMLNode& node)
1621 XMLNodeList calist = node.children();
1622 XMLNodeConstIterator caiter;
1623 XMLProperty *caprop;
1625 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1626 XMLNode* ca = *caiter;
1627 ID orig_id;
1628 ID copy_id;
1630 if ((caprop = ca->property (X_("original"))) == 0) {
1631 continue;
1633 orig_id = caprop->value();
1635 if ((caprop = ca->property (X_("copy"))) == 0) {
1636 continue;
1638 copy_id = caprop->value();
1640 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1641 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1643 if (!orig || !copy) {
1644 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1645 orig_id, copy_id)
1646 << endmsg;
1647 continue;
1650 RegionFactory::add_compound_association (orig, copy);
1653 return 0;
1656 void
1657 Session::load_nested_sources (const XMLNode& node)
1659 XMLNodeList nlist;
1660 XMLNodeConstIterator niter;
1662 nlist = node.children();
1664 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1665 if ((*niter)->name() == "Source") {
1667 /* it may already exist, so don't recreate it unnecessarily
1670 XMLProperty* prop = (*niter)->property (X_("id"));
1671 if (!prop) {
1672 error << _("Nested source has no ID info in session state file! (ignored)") << endmsg;
1673 continue;
1676 ID source_id (prop->value());
1678 if (!source_by_id (source_id)) {
1680 try {
1681 SourceFactory::create (*this, **niter, true);
1683 catch (failed_constructor& err) {
1684 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1691 boost::shared_ptr<Region>
1692 Session::XMLRegionFactory (const XMLNode& node, bool full)
1694 const XMLProperty* type = node.property("type");
1696 try {
1698 const XMLNodeList& nlist = node.children();
1700 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1701 XMLNode *child = (*niter);
1702 if (child->name() == "NestedSource") {
1703 load_nested_sources (*child);
1707 if (!type || type->value() == "audio") {
1708 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1709 } else if (type->value() == "midi") {
1710 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1713 } catch (failed_constructor& err) {
1714 return boost::shared_ptr<Region> ();
1717 return boost::shared_ptr<Region> ();
1720 boost::shared_ptr<AudioRegion>
1721 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1723 const XMLProperty* prop;
1724 boost::shared_ptr<Source> source;
1725 boost::shared_ptr<AudioSource> as;
1726 SourceList sources;
1727 SourceList master_sources;
1728 uint32_t nchans = 1;
1729 char buf[128];
1731 if (node.name() != X_("Region")) {
1732 return boost::shared_ptr<AudioRegion>();
1735 if ((prop = node.property (X_("channels"))) != 0) {
1736 nchans = atoi (prop->value().c_str());
1739 if ((prop = node.property ("name")) == 0) {
1740 cerr << "no name for this region\n";
1741 abort ();
1744 if ((prop = node.property (X_("source-0"))) == 0) {
1745 if ((prop = node.property ("source")) == 0) {
1746 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1747 return boost::shared_ptr<AudioRegion>();
1751 PBD::ID s_id (prop->value());
1753 if ((source = source_by_id (s_id)) == 0) {
1754 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1755 return boost::shared_ptr<AudioRegion>();
1758 as = boost::dynamic_pointer_cast<AudioSource>(source);
1759 if (!as) {
1760 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1761 return boost::shared_ptr<AudioRegion>();
1764 sources.push_back (as);
1766 /* pickup other channels */
1768 for (uint32_t n=1; n < nchans; ++n) {
1769 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1770 if ((prop = node.property (buf)) != 0) {
1772 PBD::ID id2 (prop->value());
1774 if ((source = source_by_id (id2)) == 0) {
1775 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1776 return boost::shared_ptr<AudioRegion>();
1779 as = boost::dynamic_pointer_cast<AudioSource>(source);
1780 if (!as) {
1781 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1782 return boost::shared_ptr<AudioRegion>();
1784 sources.push_back (as);
1788 for (uint32_t n = 0; n < nchans; ++n) {
1789 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1790 if ((prop = node.property (buf)) != 0) {
1792 PBD::ID id2 (prop->value());
1794 if ((source = source_by_id (id2)) == 0) {
1795 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1796 return boost::shared_ptr<AudioRegion>();
1799 as = boost::dynamic_pointer_cast<AudioSource>(source);
1800 if (!as) {
1801 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1802 return boost::shared_ptr<AudioRegion>();
1804 master_sources.push_back (as);
1808 try {
1809 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1811 /* a final detail: this is the one and only place that we know how long missing files are */
1813 if (region->whole_file()) {
1814 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1815 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1816 if (sfp) {
1817 sfp->set_length (region->length());
1822 if (!master_sources.empty()) {
1823 if (master_sources.size() != nchans) {
1824 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1825 } else {
1826 region->set_master_sources (master_sources);
1830 return region;
1834 catch (failed_constructor& err) {
1835 return boost::shared_ptr<AudioRegion>();
1839 boost::shared_ptr<MidiRegion>
1840 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1842 const XMLProperty* prop;
1843 boost::shared_ptr<Source> source;
1844 boost::shared_ptr<MidiSource> ms;
1845 SourceList sources;
1847 if (node.name() != X_("Region")) {
1848 return boost::shared_ptr<MidiRegion>();
1851 if ((prop = node.property ("name")) == 0) {
1852 cerr << "no name for this region\n";
1853 abort ();
1856 if ((prop = node.property (X_("source-0"))) == 0) {
1857 if ((prop = node.property ("source")) == 0) {
1858 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1859 return boost::shared_ptr<MidiRegion>();
1863 PBD::ID s_id (prop->value());
1865 if ((source = source_by_id (s_id)) == 0) {
1866 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1867 return boost::shared_ptr<MidiRegion>();
1870 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1871 if (!ms) {
1872 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1873 return boost::shared_ptr<MidiRegion>();
1876 sources.push_back (ms);
1878 try {
1879 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1880 /* a final detail: this is the one and only place that we know how long missing files are */
1882 if (region->whole_file()) {
1883 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1884 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1885 if (sfp) {
1886 sfp->set_length (region->length());
1891 return region;
1894 catch (failed_constructor& err) {
1895 return boost::shared_ptr<MidiRegion>();
1899 XMLNode&
1900 Session::get_sources_as_xml ()
1903 XMLNode* node = new XMLNode (X_("Sources"));
1904 Glib::Mutex::Lock lm (source_lock);
1906 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1907 node->add_child_nocopy (i->second->get_state());
1910 return *node;
1913 string
1914 Session::path_from_region_name (DataType type, string name, string identifier)
1916 char buf[PATH_MAX+1];
1917 uint32_t n;
1918 SessionDirectory sdir(get_best_session_directory_for_new_source());
1919 sys::path source_dir = ((type == DataType::AUDIO)
1920 ? sdir.sound_path() : sdir.midi_path());
1922 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1924 for (n = 0; n < 999999; ++n) {
1925 if (identifier.length()) {
1926 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1927 identifier.c_str(), n, ext.c_str());
1928 } else {
1929 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1930 n, ext.c_str());
1933 sys::path source_path = source_dir / buf;
1935 if (!sys::exists (source_path)) {
1936 return source_path.to_string();
1940 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1941 name, identifier)
1942 << endmsg;
1944 return "";
1949 Session::load_sources (const XMLNode& node)
1951 XMLNodeList nlist;
1952 XMLNodeConstIterator niter;
1953 boost::shared_ptr<Source> source;
1955 nlist = node.children();
1957 set_dirty();
1959 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1960 retry:
1961 try {
1962 if ((source = XMLSourceFactory (**niter)) == 0) {
1963 error << _("Session: cannot create Source from XML description.") << endmsg;
1966 } catch (MissingSource& err) {
1968 int user_choice;
1970 if (!no_questions_about_missing_files) {
1971 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1972 } else {
1973 user_choice = -2;
1976 switch (user_choice) {
1977 case 0:
1978 /* user added a new search location, so try again */
1979 goto retry;
1982 case 1:
1983 /* user asked to quit the entire session load
1985 return -1;
1987 case 2:
1988 no_questions_about_missing_files = true;
1989 goto retry;
1991 case 3:
1992 no_questions_about_missing_files = true;
1993 /* fallthru */
1995 case -1:
1996 default:
1997 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1998 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1999 break;
2004 return 0;
2007 boost::shared_ptr<Source>
2008 Session::XMLSourceFactory (const XMLNode& node)
2010 if (node.name() != "Source") {
2011 return boost::shared_ptr<Source>();
2014 try {
2015 /* note: do peak building in another thread when loading session state */
2016 return SourceFactory::create (*this, node, true);
2019 catch (failed_constructor& err) {
2020 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
2021 return boost::shared_ptr<Source>();
2026 Session::save_template (string template_name)
2028 XMLTree tree;
2030 if (_state_of_the_state & CannotSave) {
2031 return -1;
2034 sys::path user_template_dir(user_template_directory());
2038 sys::create_directories (user_template_dir);
2040 catch(sys::filesystem_error& ex)
2042 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
2043 user_template_dir.to_string(), ex.what()) << endmsg;
2044 return -1;
2047 tree.set_root (&get_template());
2049 sys::path template_file_path(user_template_dir);
2050 template_file_path /= template_name + template_suffix;
2052 if (sys::exists (template_file_path))
2054 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2055 template_file_path.to_string()) << endmsg;
2056 return -1;
2059 if (!tree.write (template_file_path.to_string())) {
2060 error << _("template not saved") << endmsg;
2061 return -1;
2064 return 0;
2068 Session::rename_template (string old_name, string new_name)
2070 sys::path old_path (user_template_directory());
2071 old_path /= old_name + template_suffix;
2073 sys::path new_path(user_template_directory());
2074 new_path /= new_name + template_suffix;
2076 if (sys::exists (new_path)) {
2077 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
2078 new_path.to_string()) << endmsg;
2079 return -1;
2082 try {
2083 sys::rename (old_path, new_path);
2084 return 0;
2085 } catch (...) {
2086 return -1;
2091 Session::delete_template (string name)
2093 sys::path path = user_template_directory();
2094 path /= name + template_suffix;
2096 try {
2097 sys::remove (path);
2098 return 0;
2099 } catch (...) {
2100 return -1;
2104 void
2105 Session::refresh_disk_space ()
2107 #if HAVE_SYS_VFS_H
2108 struct statfs statfsbuf;
2109 vector<space_and_path>::iterator i;
2110 Glib::Mutex::Lock lm (space_lock);
2111 double scale;
2113 /* get freespace on every FS that is part of the session path */
2115 _total_free_4k_blocks = 0;
2117 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2118 statfs ((*i).path.c_str(), &statfsbuf);
2120 scale = statfsbuf.f_bsize/4096.0;
2122 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2123 _total_free_4k_blocks += (*i).blocks;
2125 #endif
2128 string
2129 Session::get_best_session_directory_for_new_source ()
2131 vector<space_and_path>::iterator i;
2132 string result = _session_dir->root_path().to_string();
2134 /* handle common case without system calls */
2136 if (session_dirs.size() == 1) {
2137 return result;
2140 /* OK, here's the algorithm we're following here:
2142 We want to select which directory to use for
2143 the next file source to be created. Ideally,
2144 we'd like to use a round-robin process so as to
2145 get maximum performance benefits from splitting
2146 the files across multiple disks.
2148 However, in situations without much diskspace, an
2149 RR approach may end up filling up a filesystem
2150 with new files while others still have space.
2151 Its therefore important to pay some attention to
2152 the freespace in the filesystem holding each
2153 directory as well. However, if we did that by
2154 itself, we'd keep creating new files in the file
2155 system with the most space until it was as full
2156 as all others, thus negating any performance
2157 benefits of this RAID-1 like approach.
2159 So, we use a user-configurable space threshold. If
2160 there are at least 2 filesystems with more than this
2161 much space available, we use RR selection between them.
2162 If not, then we pick the filesystem with the most space.
2164 This gets a good balance between the two
2165 approaches.
2168 refresh_disk_space ();
2170 int free_enough = 0;
2172 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2173 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2174 free_enough++;
2178 if (free_enough >= 2) {
2179 /* use RR selection process, ensuring that the one
2180 picked works OK.
2183 i = last_rr_session_dir;
2185 do {
2186 if (++i == session_dirs.end()) {
2187 i = session_dirs.begin();
2190 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2191 if (create_session_directory ((*i).path)) {
2192 result = (*i).path;
2193 last_rr_session_dir = i;
2194 return result;
2198 } while (i != last_rr_session_dir);
2200 } else {
2202 /* pick FS with the most freespace (and that
2203 seems to actually work ...)
2206 vector<space_and_path> sorted;
2207 space_and_path_ascending_cmp cmp;
2209 sorted = session_dirs;
2210 sort (sorted.begin(), sorted.end(), cmp);
2212 for (i = sorted.begin(); i != sorted.end(); ++i) {
2213 if (create_session_directory ((*i).path)) {
2214 result = (*i).path;
2215 last_rr_session_dir = i;
2216 return result;
2221 return result;
2225 Session::load_named_selections (const XMLNode& node)
2227 XMLNodeList nlist;
2228 XMLNodeConstIterator niter;
2229 NamedSelection *ns;
2231 nlist = node.children();
2233 set_dirty();
2235 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2237 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2238 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2242 return 0;
2245 NamedSelection *
2246 Session::XMLNamedSelectionFactory (const XMLNode& node)
2248 try {
2249 return new NamedSelection (*this, node);
2252 catch (failed_constructor& err) {
2253 return 0;
2257 string
2258 Session::automation_dir () const
2260 return Glib::build_filename (_path, "automation");
2263 string
2264 Session::analysis_dir () const
2266 return Glib::build_filename (_path, "analysis");
2269 string
2270 Session::plugins_dir () const
2272 return Glib::build_filename (_path, "plugins");
2276 Session::load_bundles (XMLNode const & node)
2278 XMLNodeList nlist = node.children();
2279 XMLNodeConstIterator niter;
2281 set_dirty();
2283 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2284 if ((*niter)->name() == "InputBundle") {
2285 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2286 } else if ((*niter)->name() == "OutputBundle") {
2287 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2288 } else {
2289 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2290 return -1;
2294 return 0;
2298 Session::load_route_groups (const XMLNode& node, int version)
2300 XMLNodeList nlist = node.children();
2301 XMLNodeConstIterator niter;
2303 set_dirty ();
2305 if (version >= 3000) {
2307 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2308 if ((*niter)->name() == "RouteGroup") {
2309 RouteGroup* rg = new RouteGroup (*this, "");
2310 add_route_group (rg);
2311 rg->set_state (**niter, version);
2315 } else if (version < 3000) {
2317 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2318 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2319 RouteGroup* rg = new RouteGroup (*this, "");
2320 add_route_group (rg);
2321 rg->set_state (**niter, version);
2326 return 0;
2329 void
2330 Session::auto_save()
2332 save_state (_current_snapshot_name);
2335 static bool
2336 state_file_filter (const string &str, void */*arg*/)
2338 return (str.length() > strlen(statefile_suffix) &&
2339 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2342 struct string_cmp {
2343 bool operator()(const string* a, const string* b) {
2344 return *a < *b;
2348 static string*
2349 remove_end(string* state)
2351 string statename(*state);
2353 string::size_type start,end;
2354 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2355 statename = statename.substr (start+1);
2358 if ((end = statename.rfind(".ardour")) == string::npos) {
2359 end = statename.length();
2362 return new string(statename.substr (0, end));
2365 vector<string *> *
2366 Session::possible_states (string path)
2368 PathScanner scanner;
2369 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2371 transform(states->begin(), states->end(), states->begin(), remove_end);
2373 string_cmp cmp;
2374 sort (states->begin(), states->end(), cmp);
2376 return states;
2379 vector<string *> *
2380 Session::possible_states () const
2382 return possible_states(_path);
2385 void
2386 Session::add_route_group (RouteGroup* g)
2388 _route_groups.push_back (g);
2389 route_group_added (g); /* EMIT SIGNAL */
2391 g->MembershipChanged.connect_same_thread (*this, boost::bind (&Session::route_group_changed, this));
2392 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_changed, this));
2394 set_dirty ();
2397 void
2398 Session::remove_route_group (RouteGroup& rg)
2400 list<RouteGroup*>::iterator i;
2402 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2403 _route_groups.erase (i);
2404 delete &rg;
2406 route_group_removed (); /* EMIT SIGNAL */
2410 /** Set a new order for our route groups, without adding or removing any.
2411 * @param groups Route group list in the new order.
2413 void
2414 Session::reorder_route_groups (list<RouteGroup*> groups)
2416 _route_groups = groups;
2418 route_groups_reordered (); /* EMIT SIGNAL */
2419 set_dirty ();
2423 RouteGroup *
2424 Session::route_group_by_name (string name)
2426 list<RouteGroup *>::iterator i;
2428 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2429 if ((*i)->name() == name) {
2430 return* i;
2433 return 0;
2436 RouteGroup&
2437 Session::all_route_group() const
2439 return *_all_route_group;
2442 void
2443 Session::add_commands (vector<Command*> const & cmds)
2445 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2446 add_command (*i);
2450 void
2451 Session::begin_reversible_command (const string& name)
2453 begin_reversible_command (g_quark_from_string (name.c_str ()));
2456 /** Begin a reversible command using a GQuark to identify it.
2457 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2458 * but there must be as many begin...()s as there are commit...()s.
2460 void
2461 Session::begin_reversible_command (GQuark q)
2463 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2464 to hold all the commands that are committed. This keeps the order of
2465 commands correct in the history.
2468 if (_current_trans == 0) {
2469 /* start a new transaction */
2470 assert (_current_trans_quarks.empty ());
2471 _current_trans = new UndoTransaction();
2472 _current_trans->set_name (g_quark_to_string (q));
2475 _current_trans_quarks.push_front (q);
2478 void
2479 Session::commit_reversible_command (Command *cmd)
2481 assert (_current_trans);
2482 assert (!_current_trans_quarks.empty ());
2484 struct timeval now;
2486 if (cmd) {
2487 _current_trans->add_command (cmd);
2490 _current_trans_quarks.pop_front ();
2492 if (!_current_trans_quarks.empty ()) {
2493 /* the transaction we're committing is not the top-level one */
2494 return;
2497 if (_current_trans->empty()) {
2498 /* no commands were added to the transaction, so just get rid of it */
2499 delete _current_trans;
2500 _current_trans = 0;
2501 return;
2504 gettimeofday (&now, 0);
2505 _current_trans->set_timestamp (now);
2507 _history.add (_current_trans);
2508 _current_trans = 0;
2511 static bool
2512 accept_all_audio_files (const string& path, void */*arg*/)
2514 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2515 return false;
2518 if (!AudioFileSource::safe_audio_file_extension (path)) {
2519 return false;
2522 return true;
2525 static bool
2526 accept_all_midi_files (const string& path, void */*arg*/)
2528 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2529 return false;
2532 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2533 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2534 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2537 static bool
2538 accept_all_state_files (const string& path, void */*arg*/)
2540 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2541 return false;
2544 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2548 Session::find_all_sources (string path, set<string>& result)
2550 XMLTree tree;
2551 XMLNode* node;
2553 if (!tree.read (path)) {
2554 return -1;
2557 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2558 return -2;
2561 XMLNodeList nlist;
2562 XMLNodeConstIterator niter;
2564 nlist = node->children();
2566 set_dirty();
2568 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2570 XMLProperty* prop;
2572 if ((prop = (*niter)->property (X_("type"))) == 0) {
2573 continue;
2576 DataType type (prop->value());
2578 if ((prop = (*niter)->property (X_("name"))) == 0) {
2579 continue;
2582 if (Glib::path_is_absolute (prop->value())) {
2583 /* external file, ignore */
2584 continue;
2587 string found_path;
2588 bool is_new;
2589 uint16_t chan;
2591 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2592 result.insert (found_path);
2596 return 0;
2600 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2602 PathScanner scanner;
2603 vector<string*>* state_files;
2604 string ripped;
2605 string this_snapshot_path;
2607 result.clear ();
2609 ripped = _path;
2611 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2612 ripped = ripped.substr (0, ripped.length() - 1);
2615 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2617 if (state_files == 0) {
2618 /* impossible! */
2619 return 0;
2622 this_snapshot_path = _path;
2623 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2624 this_snapshot_path += statefile_suffix;
2626 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2628 if (exclude_this_snapshot && **i == this_snapshot_path) {
2629 continue;
2632 if (find_all_sources (**i, result) < 0) {
2633 return -1;
2637 return 0;
2640 struct RegionCounter {
2641 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2642 AudioSourceList::iterator iter;
2643 boost::shared_ptr<Region> region;
2644 uint32_t count;
2646 RegionCounter() : count (0) {}
2650 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2652 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2653 return r.get_value_or (1);
2656 void
2657 Session::cleanup_regions ()
2659 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2661 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2663 boost::shared_ptr<AudioRegion> audio_region = boost::dynamic_pointer_cast<AudioRegion>( i->second);
2665 if (!audio_region) {
2666 continue;
2669 uint32_t used = playlists->region_use_count (audio_region);
2671 if (used == 0 && !audio_region->automatic()) {
2672 RegionFactory::map_remove(i->second);
2676 /* dump the history list */
2677 _history.clear ();
2679 save_state ("");
2683 Session::cleanup_sources (CleanupReport& rep)
2685 // FIXME: needs adaptation to midi
2687 vector<boost::shared_ptr<Source> > dead_sources;
2688 PathScanner scanner;
2689 string audio_path;
2690 string midi_path;
2691 vector<space_and_path>::iterator i;
2692 vector<space_and_path>::iterator nexti;
2693 vector<string*>* candidates;
2694 vector<string*>* candidates2;
2695 vector<string> unused;
2696 set<string> all_sources;
2697 bool used;
2698 string spath;
2699 int ret = -1;
2701 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2703 /* consider deleting all unused playlists */
2705 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2706 ret = 0;
2707 goto out;
2710 /* sync the "all regions" property of each playlist with its current state
2713 playlists->sync_all_regions_with_regions ();
2715 /* find all un-used sources */
2717 rep.paths.clear ();
2718 rep.space = 0;
2720 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2722 SourceMap::iterator tmp;
2724 tmp = i;
2725 ++tmp;
2727 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2728 capture files.
2731 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2732 dead_sources.push_back (i->second);
2733 i->second->drop_references ();
2736 i = tmp;
2739 /* build a list of all the possible audio directories for the session */
2741 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2743 nexti = i;
2744 ++nexti;
2746 SessionDirectory sdir ((*i).path);
2747 audio_path += sdir.sound_path().to_string();
2749 if (nexti != session_dirs.end()) {
2750 audio_path += ':';
2753 i = nexti;
2757 /* build a list of all the possible midi directories for the session */
2759 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2761 nexti = i;
2762 ++nexti;
2764 SessionDirectory sdir ((*i).path);
2765 midi_path += sdir.midi_path().to_string();
2767 if (nexti != session_dirs.end()) {
2768 midi_path += ':';
2771 i = nexti;
2774 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2775 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2777 /* merge them */
2779 if (candidates) {
2780 if (candidates2) {
2781 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2782 candidates->push_back (*i);
2784 delete candidates2;
2786 } else {
2787 candidates = candidates2; // might still be null
2790 /* find all sources, but don't use this snapshot because the
2791 state file on disk still references sources we may have already
2792 dropped.
2795 find_all_sources_across_snapshots (all_sources, true);
2797 /* add our current source list
2800 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2801 boost::shared_ptr<FileSource> fs;
2802 SourceMap::iterator tmp = i;
2803 ++tmp;
2805 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2806 if (playlists->source_use_count (fs) != 0) {
2807 all_sources.insert (fs->path());
2808 } else {
2810 /* we might not remove this source from disk, because it may be used
2811 by other snapshots, but its not being used in this version
2812 so lets get rid of it now, along with any representative regions
2813 in the region list.
2816 RegionFactory::remove_regions_using_source (i->second);
2817 sources.erase (i);
2821 i = tmp;
2824 char tmppath1[PATH_MAX+1];
2825 char tmppath2[PATH_MAX+1];
2827 if (candidates) {
2828 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2830 used = false;
2831 spath = **x;
2833 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2835 if (realpath(spath.c_str(), tmppath1) == 0) {
2836 error << string_compose (_("Cannot expand path %1 (%2)"),
2837 spath, strerror (errno)) << endmsg;
2838 continue;
2841 if (realpath((*i).c_str(), tmppath2) == 0) {
2842 error << string_compose (_("Cannot expand path %1 (%2)"),
2843 (*i), strerror (errno)) << endmsg;
2844 continue;
2847 if (strcmp(tmppath1, tmppath2) == 0) {
2848 used = true;
2849 break;
2853 if (!used) {
2854 unused.push_back (spath);
2857 delete *x;
2860 delete candidates;
2863 /* now try to move all unused files into the "dead" directory(ies) */
2865 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2866 struct stat statbuf;
2868 string newpath;
2870 /* don't move the file across filesystems, just
2871 stick it in the `dead_dir_name' directory
2872 on whichever filesystem it was already on.
2875 if ((*x).find ("/sounds/") != string::npos) {
2877 /* old school, go up 1 level */
2879 newpath = Glib::path_get_dirname (*x); // "sounds"
2880 newpath = Glib::path_get_dirname (newpath); // "session-name"
2882 } else {
2884 /* new school, go up 4 levels */
2886 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2887 newpath = Glib::path_get_dirname (newpath); // "session-name"
2888 newpath = Glib::path_get_dirname (newpath); // "interchange"
2889 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2892 newpath = Glib::build_filename (newpath, dead_dir_name);
2894 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2895 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2896 return -1;
2899 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2901 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2903 /* the new path already exists, try versioning */
2905 char buf[PATH_MAX+1];
2906 int version = 1;
2907 string newpath_v;
2909 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2910 newpath_v = buf;
2912 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2913 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2914 newpath_v = buf;
2917 if (version == 999) {
2918 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2919 newpath)
2920 << endmsg;
2921 } else {
2922 newpath = newpath_v;
2925 } else {
2927 /* it doesn't exist, or we can't read it or something */
2931 stat ((*x).c_str(), &statbuf);
2933 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2934 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2935 (*x), newpath, strerror (errno))
2936 << endmsg;
2937 goto out;
2940 /* see if there an easy to find peakfile for this file, and remove it.
2943 string base = basename_nosuffix (*x);
2944 base += "%A"; /* this is what we add for the channel suffix of all native files,
2945 or for the first channel of embedded files. it will miss
2946 some peakfiles for other channels
2948 string peakpath = peak_path (base);
2950 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2951 if (::unlink (peakpath.c_str()) != 0) {
2952 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2953 peakpath, _path, strerror (errno))
2954 << endmsg;
2955 /* try to back out */
2956 ::rename (newpath.c_str(), _path.c_str());
2957 goto out;
2961 rep.paths.push_back (*x);
2962 rep.space += statbuf.st_size;
2965 /* dump the history list */
2967 _history.clear ();
2969 /* save state so we don't end up a session file
2970 referring to non-existent sources.
2973 save_state ("");
2974 ret = 0;
2976 out:
2977 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2979 return ret;
2983 Session::cleanup_trash_sources (CleanupReport& rep)
2985 // FIXME: needs adaptation for MIDI
2987 vector<space_and_path>::iterator i;
2988 string dead_dir;
2990 rep.paths.clear ();
2991 rep.space = 0;
2993 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2995 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2997 clear_directory (dead_dir, &rep.space, &rep.paths);
3000 return 0;
3003 void
3004 Session::set_dirty ()
3006 bool was_dirty = dirty();
3008 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3011 if (!was_dirty) {
3012 DirtyChanged(); /* EMIT SIGNAL */
3017 void
3018 Session::set_clean ()
3020 bool was_dirty = dirty();
3022 _state_of_the_state = Clean;
3025 if (was_dirty) {
3026 DirtyChanged(); /* EMIT SIGNAL */
3030 void
3031 Session::set_deletion_in_progress ()
3033 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3036 void
3037 Session::clear_deletion_in_progress ()
3039 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3042 void
3043 Session::add_controllable (boost::shared_ptr<Controllable> c)
3045 /* this adds a controllable to the list managed by the Session.
3046 this is a subset of those managed by the Controllable class
3047 itself, and represents the only ones whose state will be saved
3048 as part of the session.
3051 Glib::Mutex::Lock lm (controllables_lock);
3052 controllables.insert (c);
3055 struct null_deleter { void operator()(void const *) const {} };
3057 void
3058 Session::remove_controllable (Controllable* c)
3060 if (_state_of_the_state | Deletion) {
3061 return;
3064 Glib::Mutex::Lock lm (controllables_lock);
3066 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3068 if (x != controllables.end()) {
3069 controllables.erase (x);
3073 boost::shared_ptr<Controllable>
3074 Session::controllable_by_id (const PBD::ID& id)
3076 Glib::Mutex::Lock lm (controllables_lock);
3078 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3079 if ((*i)->id() == id) {
3080 return *i;
3084 return boost::shared_ptr<Controllable>();
3087 boost::shared_ptr<Controllable>
3088 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3090 boost::shared_ptr<Controllable> c;
3091 boost::shared_ptr<Route> r;
3093 switch (desc.top_level_type()) {
3094 case ControllableDescriptor::NamedRoute:
3096 std::string str = desc.top_level_name();
3097 if (str == "master") {
3098 r = _master_out;
3099 } else if (str == "control" || str == "listen") {
3100 r = _monitor_out;
3101 } else {
3102 r = route_by_name (desc.top_level_name());
3104 break;
3107 case ControllableDescriptor::RemoteControlID:
3108 r = route_by_remote_id (desc.rid());
3109 break;
3112 if (!r) {
3113 return c;
3116 switch (desc.subtype()) {
3117 case ControllableDescriptor::Gain:
3118 c = r->gain_control ();
3119 break;
3121 case ControllableDescriptor::Solo:
3122 c = r->solo_control();
3123 break;
3125 case ControllableDescriptor::Mute:
3126 c = r->mute_control();
3127 break;
3129 case ControllableDescriptor::Recenable:
3131 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3133 if (t) {
3134 c = t->rec_enable_control ();
3136 break;
3139 case ControllableDescriptor::PanDirection:
3141 c = r->pannable()->pan_azimuth_control;
3142 break;
3145 case ControllableDescriptor::PanWidth:
3147 c = r->pannable()->pan_width_control;
3148 break;
3151 case ControllableDescriptor::PanElevation:
3153 c = r->pannable()->pan_elevation_control;
3154 break;
3157 case ControllableDescriptor::Balance:
3158 /* XXX simple pan control */
3159 break;
3161 case ControllableDescriptor::PluginParameter:
3163 uint32_t plugin = desc.target (0);
3164 uint32_t parameter_index = desc.target (1);
3166 /* revert to zero based counting */
3168 if (plugin > 0) {
3169 --plugin;
3172 if (parameter_index > 0) {
3173 --parameter_index;
3176 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3178 if (p) {
3179 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3180 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3182 break;
3185 case ControllableDescriptor::SendGain:
3187 uint32_t send = desc.target (0);
3189 /* revert to zero-based counting */
3191 if (send > 0) {
3192 --send;
3195 boost::shared_ptr<Processor> p = r->nth_send (send);
3197 if (p) {
3198 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3199 boost::shared_ptr<Amp> a = s->amp();
3201 if (a) {
3202 c = s->amp()->gain_control();
3205 break;
3208 default:
3209 /* relax and return a null pointer */
3210 break;
3213 return c;
3216 void
3217 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3219 if (_writable) {
3220 Stateful::add_instant_xml (node, _path);
3223 if (write_to_config) {
3224 Config->add_instant_xml (node);
3228 XMLNode*
3229 Session::instant_xml (const string& node_name)
3231 return Stateful::instant_xml (node_name, _path);
3235 Session::save_history (string snapshot_name)
3237 XMLTree tree;
3239 if (!_writable) {
3240 return 0;
3243 if (snapshot_name.empty()) {
3244 snapshot_name = _current_snapshot_name;
3247 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3248 const string backup_filename = history_filename + backup_suffix;
3249 const sys::path xml_path = _session_dir->root_path() / history_filename;
3250 const sys::path backup_path = _session_dir->root_path() / backup_filename;
3252 if (sys::exists (xml_path)) {
3255 sys::rename (xml_path, backup_path);
3257 catch (const sys::filesystem_error& err)
3259 error << _("could not backup old history file, current history not saved") << endmsg;
3260 return -1;
3264 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3265 return 0;
3268 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3270 if (!tree.write (xml_path.to_string()))
3272 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
3276 sys::remove (xml_path);
3277 sys::rename (backup_path, xml_path);
3279 catch (const sys::filesystem_error& err)
3281 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3282 backup_path.to_string(), err.what()) << endmsg;
3285 return -1;
3288 return 0;
3292 Session::restore_history (string snapshot_name)
3294 XMLTree tree;
3296 if (snapshot_name.empty()) {
3297 snapshot_name = _current_snapshot_name;
3300 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3301 const sys::path xml_path = _session_dir->root_path() / xml_filename;
3303 info << "Loading history from " << xml_path.to_string() << endmsg;
3305 if (!sys::exists (xml_path)) {
3306 info << string_compose (_("%1: no history file \"%2\" for this session."),
3307 _name, xml_path.to_string()) << endmsg;
3308 return 1;
3311 if (!tree.read (xml_path.to_string())) {
3312 error << string_compose (_("Could not understand session history file \"%1\""),
3313 xml_path.to_string()) << endmsg;
3314 return -1;
3317 // replace history
3318 _history.clear();
3320 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3322 XMLNode *t = *it;
3323 UndoTransaction* ut = new UndoTransaction ();
3324 struct timeval tv;
3326 ut->set_name(t->property("name")->value());
3327 stringstream ss(t->property("tv-sec")->value());
3328 ss >> tv.tv_sec;
3329 ss.str(t->property("tv-usec")->value());
3330 ss >> tv.tv_usec;
3331 ut->set_timestamp(tv);
3333 for (XMLNodeConstIterator child_it = t->children().begin();
3334 child_it != t->children().end(); child_it++)
3336 XMLNode *n = *child_it;
3337 Command *c;
3339 if (n->name() == "MementoCommand" ||
3340 n->name() == "MementoUndoCommand" ||
3341 n->name() == "MementoRedoCommand") {
3343 if ((c = memento_command_factory(n))) {
3344 ut->add_command(c);
3347 } else if (n->name() == "NoteDiffCommand") {
3348 PBD::ID id (n->property("midi-source")->value());
3349 boost::shared_ptr<MidiSource> midi_source =
3350 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3351 if (midi_source) {
3352 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3353 } else {
3354 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3357 } else if (n->name() == "SysExDiffCommand") {
3359 PBD::ID id (n->property("midi-source")->value());
3360 boost::shared_ptr<MidiSource> midi_source =
3361 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3362 if (midi_source) {
3363 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3364 } else {
3365 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3368 } else if (n->name() == "PatchChangeDiffCommand") {
3370 PBD::ID id (n->property("midi-source")->value());
3371 boost::shared_ptr<MidiSource> midi_source =
3372 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3373 if (midi_source) {
3374 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3375 } else {
3376 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3379 } else if (n->name() == "StatefulDiffCommand") {
3380 if ((c = stateful_diff_command_factory (n))) {
3381 ut->add_command (c);
3383 } else {
3384 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3388 _history.add (ut);
3391 return 0;
3394 void
3395 Session::config_changed (std::string p, bool ours)
3397 if (ours) {
3398 set_dirty ();
3401 if (p == "seamless-loop") {
3403 } else if (p == "rf-speed") {
3405 } else if (p == "auto-loop") {
3407 } else if (p == "auto-input") {
3409 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3410 /* auto-input only makes a difference if we're rolling */
3411 set_track_monitor_input_status (!config.get_auto_input());
3414 } else if (p == "punch-in") {
3416 Location* location;
3418 if ((location = _locations->auto_punch_location()) != 0) {
3420 if (config.get_punch_in ()) {
3421 replace_event (SessionEvent::PunchIn, location->start());
3422 } else {
3423 remove_event (location->start(), SessionEvent::PunchIn);
3427 } else if (p == "punch-out") {
3429 Location* location;
3431 if ((location = _locations->auto_punch_location()) != 0) {
3433 if (config.get_punch_out()) {
3434 replace_event (SessionEvent::PunchOut, location->end());
3435 } else {
3436 clear_events (SessionEvent::PunchOut);
3440 } else if (p == "edit-mode") {
3442 Glib::Mutex::Lock lm (playlists->lock);
3444 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3445 (*i)->set_edit_mode (Config->get_edit_mode ());
3448 } else if (p == "use-video-sync") {
3450 waiting_for_sync_offset = config.get_use_video_sync();
3452 } else if (p == "mmc-control") {
3454 //poke_midi_thread ();
3456 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3458 MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
3460 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3462 MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
3464 } else if (p == "midi-control") {
3466 //poke_midi_thread ();
3468 } else if (p == "raid-path") {
3470 setup_raid_path (config.get_raid_path());
3472 } else if (p == "timecode-format") {
3474 sync_time_vars ();
3476 } else if (p == "video-pullup") {
3478 sync_time_vars ();
3480 } else if (p == "seamless-loop") {
3482 if (play_loop && transport_rolling()) {
3483 // to reset diskstreams etc
3484 request_play_loop (true);
3487 } else if (p == "rf-speed") {
3489 cumulative_rf_motion = 0;
3490 reset_rf_scale (0);
3492 } else if (p == "click-sound") {
3494 setup_click_sounds (1);
3496 } else if (p == "click-emphasis-sound") {
3498 setup_click_sounds (-1);
3500 } else if (p == "clicking") {
3502 if (Config->get_clicking()) {
3503 if (_click_io && click_data) { // don't require emphasis data
3504 _clicking = true;
3506 } else {
3507 _clicking = false;
3510 } else if (p == "send-mtc") {
3512 if (Config->get_send_mtc ()) {
3513 /* mark us ready to send */
3514 next_quarter_frame_to_send = 0;
3517 } else if (p == "send-mmc") {
3519 MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
3521 } else if (p == "midi-feedback") {
3523 session_midi_feedback = Config->get_midi_feedback();
3525 } else if (p == "jack-time-master") {
3527 engine().reset_timebase ();
3529 } else if (p == "native-file-header-format") {
3531 if (!first_file_header_format_reset) {
3532 reset_native_file_format ();
3535 first_file_header_format_reset = false;
3537 } else if (p == "native-file-data-format") {
3539 if (!first_file_data_format_reset) {
3540 reset_native_file_format ();
3543 first_file_data_format_reset = false;
3545 } else if (p == "external-sync") {
3546 if (!config.get_external_sync()) {
3547 drop_sync_source ();
3548 } else {
3549 switch_to_sync_source (config.get_sync_source());
3551 } else if (p == "remote-model") {
3552 set_remote_control_ids ();
3553 } else if (p == "denormal-model") {
3554 setup_fpu ();
3555 } else if (p == "history-depth") {
3556 set_history_depth (Config->get_history_depth());
3557 } else if (p == "sync-all-route-ordering") {
3558 sync_order_keys ("session");
3559 } else if (p == "initial-program-change") {
3561 if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
3562 MIDI::byte buf[2];
3564 buf[0] = MIDI::program; // channel zero by default
3565 buf[1] = (Config->get_initial_program_change() & 0x7f);
3567 MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
3569 } else if (p == "solo-mute-override") {
3570 // catch_up_on_solo_mute_override ();
3571 } else if (p == "listen-position" || p == "pfl-position") {
3572 listen_position_changed ();
3573 } else if (p == "solo-control-is-listen-control") {
3574 solo_control_mode_changed ();
3575 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3576 last_timecode_valid = false;
3577 } else if (p == "playback-buffer-seconds") {
3578 AudioSource::allocate_working_buffers (frame_rate());
3581 set_dirty ();
3584 void
3585 Session::set_history_depth (uint32_t d)
3587 _history.set_depth (d);
3591 Session::load_diskstreams_2X (XMLNode const & node, int)
3593 XMLNodeList clist;
3594 XMLNodeConstIterator citer;
3596 clist = node.children();
3598 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3600 try {
3601 /* diskstreams added automatically by DiskstreamCreated handler */
3602 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3603 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3604 _diskstreams_2X.push_back (dsp);
3605 } else {
3606 error << _("Session: unknown diskstream type in XML") << endmsg;
3610 catch (failed_constructor& err) {
3611 error << _("Session: could not load diskstream via XML state") << endmsg;
3612 return -1;
3616 return 0;
3619 /** Connect things to the MMC object */
3620 void
3621 Session::setup_midi_machine_control ()
3623 MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
3625 mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3626 mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3627 mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3628 mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3629 mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3630 mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3631 mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3632 mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3633 mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3634 mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3635 mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3636 mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3637 mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3639 /* also handle MIDI SPP because its so common */
3641 mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this, _1, _2));
3642 mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this, _1, _2));
3643 mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this, _1, _2));
3646 boost::shared_ptr<Controllable>
3647 Session::solo_cut_control() const
3649 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3650 controls in Ardour that currently get presented to the user in the GUI that require
3651 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3653 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3654 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3655 parameter.
3658 return _solo_cut_control;
3662 Session::rename (const std::string& new_name)
3664 string legal_name = legalize_for_path (new_name);
3665 string newpath;
3666 string oldstr;
3667 string newstr;
3668 bool first = true;
3670 #define RENAME ::rename
3672 /* Rename:
3674 * session directory
3675 * interchange subdirectory
3676 * session file
3677 * session history
3679 * Backup files are left unchanged and not renamed.
3682 /* pass one: not 100% safe check that the new directory names don't
3683 * already exist ...
3686 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3687 vector<string> v;
3689 oldstr = (*i).path;
3691 /* this is a stupid hack because Glib::path_get_dirname() is
3692 * lexical-only, and so passing it /a/b/c/ gives a different
3693 * result than passing it /a/b/c ...
3696 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3697 oldstr = oldstr.substr (0, oldstr.length() - 1);
3700 string base = Glib::path_get_dirname (oldstr);
3701 string p = Glib::path_get_basename (oldstr);
3703 newstr = Glib::build_filename (base, legal_name);
3705 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3706 return -1;
3710 /* Session dirs */
3712 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3713 vector<string> v;
3715 oldstr = (*i).path;
3717 /* this is a stupid hack because Glib::path_get_dirname() is
3718 * lexical-only, and so passing it /a/b/c/ gives a different
3719 * result than passing it /a/b/c ...
3722 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3723 oldstr = oldstr.substr (0, oldstr.length() - 1);
3726 string base = Glib::path_get_dirname (oldstr);
3727 string p = Glib::path_get_basename (oldstr);
3729 newstr = Glib::build_filename (base, legal_name);
3731 cerr << "Rename " << oldstr << " => " << newstr << endl;
3733 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3734 return 1;
3737 if (first) {
3738 (*_session_dir) = newstr;
3739 newpath = newstr;
3740 first = 1;
3743 /* directory below interchange */
3745 v.push_back (newstr);
3746 v.push_back (interchange_dir_name);
3747 v.push_back (p);
3749 oldstr = Glib::build_filename (v);
3751 v.clear ();
3752 v.push_back (newstr);
3753 v.push_back (interchange_dir_name);
3754 v.push_back (legal_name);
3756 newstr = Glib::build_filename (v);
3758 cerr << "Rename " << oldstr << " => " << newstr << endl;
3760 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3761 return 1;
3765 /* state file */
3767 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3768 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3770 cerr << "Rename " << oldstr << " => " << newstr << endl;
3772 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3773 return 1;
3776 /* history file */
3779 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3781 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3782 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3784 cerr << "Rename " << oldstr << " => " << newstr << endl;
3786 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3787 return 1;
3791 /* remove old name from recent sessions */
3793 remove_recent_sessions (_path);
3795 _path = newpath;
3796 _current_snapshot_name = new_name;
3797 _name = new_name;
3799 set_dirty ();
3801 /* save state again to get everything just right */
3803 save_state (_current_snapshot_name);
3806 /* add to recent sessions */
3808 store_recent_sessions (new_name, _path);
3810 return 0;
3812 #undef RENAME