Setup fixed ports for MIDI control data; hence remove configuration of those ports...
[ArdourMidi.git] / libs / ardour / session_state.cc
blob76570cb64ac4219759a96e120f40ac11e38ccd4c
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 #define __STDC_FORMAT_MACROS 1
26 #include <stdint.h>
28 #include <algorithm>
29 #include <fstream>
30 #include <string>
31 #include <cerrno>
34 #include <cstdio> /* snprintf(3) ... grrr */
35 #include <cmath>
36 #include <unistd.h>
37 #include <sys/stat.h>
38 #include <climits>
39 #include <fcntl.h>
40 #include <poll.h>
41 #include <signal.h>
42 #include <sys/mman.h>
43 #include <sys/time.h>
44 #include <dirent.h>
46 #ifdef HAVE_SYS_VFS_H
47 #include <sys/vfs.h>
48 #else
49 #include <sys/param.h>
50 #include <sys/mount.h>
51 #endif
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/controllable_descriptor.h"
62 #include "pbd/enumwriter.h"
63 #include "pbd/error.h"
64 #include "pbd/pathscanner.h"
65 #include "pbd/pthread_utils.h"
66 #include "pbd/search_path.h"
67 #include "pbd/stacktrace.h"
68 #include "pbd/convert.h"
70 #include "ardour/amp.h"
71 #include "ardour/audio_diskstream.h"
72 #include "ardour/audio_track.h"
73 #include "ardour/audioengine.h"
74 #include "ardour/audiofilesource.h"
75 #include "ardour/audioplaylist.h"
76 #include "ardour/audioregion.h"
77 #include "ardour/auditioner.h"
78 #include "ardour/buffer.h"
79 #include "ardour/butler.h"
80 #include "ardour/configuration.h"
81 #include "ardour/control_protocol_manager.h"
82 #include "ardour/crossfade.h"
83 #include "ardour/cycle_timer.h"
84 #include "ardour/directory_names.h"
85 #include "ardour/filename_extensions.h"
86 #include "ardour/io_processor.h"
87 #include "ardour/location.h"
88 #include "ardour/midi_diskstream.h"
89 #include "ardour/midi_patch_manager.h"
90 #include "ardour/midi_playlist.h"
91 #include "ardour/midi_region.h"
92 #include "ardour/midi_source.h"
93 #include "ardour/midi_track.h"
94 #include "ardour/named_selection.h"
95 #include "ardour/processor.h"
96 #include "ardour/port.h"
97 #include "ardour/region_factory.h"
98 #include "ardour/route_group.h"
99 #include "ardour/send.h"
100 #include "ardour/session.h"
101 #include "ardour/session_directory.h"
102 #include "ardour/session_metadata.h"
103 #include "ardour/session_state_utils.h"
104 #include "ardour/session_playlists.h"
105 #include "ardour/session_utils.h"
106 #include "ardour/silentfilesource.h"
107 #include "ardour/slave.h"
108 #include "ardour/smf_source.h"
109 #include "ardour/sndfile_helpers.h"
110 #include "ardour/sndfilesource.h"
111 #include "ardour/source_factory.h"
112 #include "ardour/template_utils.h"
113 #include "ardour/tempo.h"
114 #include "ardour/ticker.h"
115 #include "ardour/user_bundle.h"
116 #include "ardour/utils.h"
117 #include "ardour/utils.h"
118 #include "ardour/version.h"
119 #include "ardour/playlist_factory.h"
121 #include "control_protocol/control_protocol.h"
123 #include "i18n.h"
124 #include <locale.h>
126 using namespace std;
127 using namespace ARDOUR;
128 using namespace PBD;
130 void
131 Session::first_stage_init (string fullpath, string snapshot_name)
133 if (fullpath.length() == 0) {
134 destroy ();
135 throw failed_constructor();
138 char buf[PATH_MAX+1];
139 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
140 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
141 destroy ();
142 throw failed_constructor();
145 _path = string(buf);
147 if (_path[_path.length()-1] != '/') {
148 _path += '/';
151 if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS) && ::access (_path.c_str(), W_OK)) {
152 _writable = false;
153 } else {
154 _writable = true;
157 /* these two are just provisional settings. set_state()
158 will likely override them.
161 _name = _current_snapshot_name = snapshot_name;
163 set_history_depth (Config->get_history_depth());
165 _current_frame_rate = _engine.frame_rate ();
166 _nominal_frame_rate = _current_frame_rate;
167 _base_frame_rate = _current_frame_rate;
169 _tempo_map = new TempoMap (_current_frame_rate);
170 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
173 _non_soloed_outs_muted = false;
174 _listen_cnt = 0;
175 _solo_isolated_cnt = 0;
176 g_atomic_int_set (&processing_prohibited, 0);
177 _transport_speed = 0;
178 _last_transport_speed = 0;
179 _target_transport_speed = 0;
180 auto_play_legal = false;
181 transport_sub_state = 0;
182 _transport_frame = 0;
183 _requested_return_frame = -1;
184 _session_range_location = 0;
185 g_atomic_int_set (&_record_status, Disabled);
186 loop_changing = false;
187 play_loop = false;
188 have_looped = false;
189 _last_roll_location = 0;
190 _last_roll_or_reversal_location = 0;
191 _last_record_location = 0;
192 pending_locate_frame = 0;
193 pending_locate_roll = false;
194 pending_locate_flush = false;
195 state_was_pending = false;
196 set_next_event ();
197 outbound_mtc_timecode_frame = 0;
198 next_quarter_frame_to_send = -1;
199 current_block_size = 0;
200 solo_update_disabled = false;
201 _have_captured = false;
202 _worst_output_latency = 0;
203 _worst_input_latency = 0;
204 _worst_track_latency = 0;
205 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
206 _was_seamless = Config->get_seamless_loop ();
207 _slave = 0;
208 session_send_mtc = false;
209 g_atomic_int_set (&_playback_load, 100);
210 g_atomic_int_set (&_capture_load, 100);
211 _play_range = false;
212 _exporting = false;
213 pending_abort = false;
214 destructive_index = 0;
215 first_file_data_format_reset = true;
216 first_file_header_format_reset = true;
217 post_export_sync = false;
218 midi_control_ui = 0;
220 AudioDiskstream::allocate_working_buffers();
222 /* default short fade = 15ms */
224 Crossfade::set_short_xfade_length ((nframes_t) floor (config.get_short_xfade_seconds() * frame_rate()));
225 SndFileSource::setup_standard_crossfades (*this, frame_rate());
227 last_mmc_step.tv_sec = 0;
228 last_mmc_step.tv_usec = 0;
229 step_speed = 0.0;
231 /* click sounds are unset by default, which causes us to internal
232 waveforms for clicks.
235 click_length = 0;
236 click_emphasis_length = 0;
237 _clicking = false;
239 process_function = &Session::process_with_events;
241 if (config.get_use_video_sync()) {
242 waiting_for_sync_offset = true;
243 } else {
244 waiting_for_sync_offset = false;
247 last_timecode_when = 0;
248 _timecode_offset = 0;
249 _timecode_offset_negative = true;
250 last_timecode_valid = false;
252 sync_time_vars ();
254 last_rr_session_dir = session_dirs.begin();
255 refresh_disk_space ();
257 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
259 /* slave stuff */
261 average_slave_delta = 1800; // !!! why 1800 ????
262 have_first_delta_accumulator = false;
263 delta_accumulator_cnt = 0;
264 _slave_state = Stopped;
266 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
268 /* These are all static "per-class" signals */
270 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
271 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
272 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
273 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
274 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
276 /* stop IO objects from doing stuff until we're ready for them */
278 Delivery::disable_panners ();
279 IO::disable_connecting ();
281 /* Create MIDI control ports */
283 MIDI::Manager* m = MIDI::Manager::instance ();
285 _mtc_input_port = m->add_port (new MIDI::Port ("MTC", O_RDONLY, _engine.jack()));
286 _mtc_output_port = m->add_port (new MIDI::Port ("MTC", O_WRONLY, _engine.jack()));
287 _midi_input_port = m->add_port (new MIDI::Port ("MIDI control", O_RDONLY, _engine.jack()));
288 _midi_output_port = m->add_port (new MIDI::Port ("MIDI control", O_WRONLY, _engine.jack()));
289 _midi_clock_input_port = m->add_port (new MIDI::Port ("MIDI clock", O_RDONLY, _engine.jack()));
290 _midi_clock_output_port = m->add_port (new MIDI::Port ("MIDI clock", O_WRONLY, _engine.jack()));
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;
302 remove_empty_sounds ();
305 if (_butler->start_thread()) {
306 return -1;
309 if (start_midi_thread ()) {
310 return -1;
313 setup_midi_machine_control ();
315 // set_state() will call setup_raid_path(), but if it's a new session we need
316 // to call setup_raid_path() here.
318 if (state_tree) {
319 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
320 return -1;
322 } else {
323 setup_raid_path(_path);
326 /* we can't save till after ::when_engine_running() is called,
327 because otherwise we save state with no connections made.
328 therefore, we reset _state_of_the_state because ::set_state()
329 will have cleared it.
331 we also have to include Loading so that any events that get
332 generated between here and the end of ::when_engine_running()
333 will be processed directly rather than queued.
336 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
338 _locations.changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
339 _locations.added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
340 setup_click_sounds (0);
341 setup_midi_control ();
343 /* Pay attention ... */
345 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
346 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
348 try {
349 when_engine_running ();
352 /* handle this one in a different way than all others, so that its clear what happened */
354 catch (AudioEngine::PortRegistrationFailure& err) {
355 error << err.what() << endmsg;
356 return -1;
359 catch (...) {
360 return -1;
363 BootMessage (_("Reset Remote Controls"));
365 send_full_time_code (0);
366 _engine.transport_locate (0);
368 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
369 _mmc->send (MIDI::MachineControlCommand (Timecode::Time ()));
371 MidiClockTicker::instance().set_session (this);
372 MIDI::Name::MidiPatchManager::instance().set_session (this);
374 /* initial program change will be delivered later; see ::config_changed() */
376 BootMessage (_("Reset Control Protocols"));
378 ControlProtocolManager::instance().set_session (this);
380 _state_of_the_state = Clean;
382 Port::set_connecting_blocked (false);
384 DirtyChanged (); /* EMIT SIGNAL */
386 if (state_was_pending) {
387 save_state (_current_snapshot_name);
388 remove_pending_capture_state ();
389 state_was_pending = false;
392 BootMessage (_("Session loading complete"));
394 return 0;
397 string
398 Session::raid_path () const
400 SearchPath raid_search_path;
402 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
403 raid_search_path += sys::path((*i).path);
406 return raid_search_path.to_string ();
409 void
410 Session::setup_raid_path (string path)
412 if (path.empty()) {
413 return;
416 space_and_path sp;
417 string fspath;
419 session_dirs.clear ();
421 SearchPath search_path(path);
422 SearchPath sound_search_path;
423 SearchPath midi_search_path;
425 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
426 sp.path = (*i).to_string ();
427 sp.blocks = 0; // not needed
428 session_dirs.push_back (sp);
430 SessionDirectory sdir(sp.path);
432 sound_search_path += sdir.sound_path ();
433 midi_search_path += sdir.midi_path ();
436 // set the search path for each data type
437 FileSource::set_search_path (DataType::AUDIO, sound_search_path.to_string ());
438 SMFSource::set_search_path (DataType::MIDI, midi_search_path.to_string ());
440 // reset the round-robin soundfile path thingie
441 last_rr_session_dir = session_dirs.begin();
444 bool
445 Session::path_is_within_session (const std::string& path)
447 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
448 if (path.find ((*i).path) == 0) {
449 return true;
452 return false;
456 Session::ensure_subdirs ()
458 string dir;
460 dir = session_directory().peak_path().to_string();
462 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
463 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
464 return -1;
467 dir = session_directory().sound_path().to_string();
469 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
470 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
471 return -1;
474 dir = session_directory().midi_path().to_string();
476 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
477 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
478 return -1;
481 dir = session_directory().dead_sound_path().to_string();
483 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
484 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
485 return -1;
488 dir = session_directory().export_path().to_string();
490 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
491 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
492 return -1;
495 dir = analysis_dir ();
497 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
498 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
499 return -1;
502 return 0;
506 Session::create (const string& mix_template, BusProfile* bus_profile)
509 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
510 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
511 return -1;
514 if (ensure_subdirs ()) {
515 return -1;
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 Route* rt = new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO);
567 if (rt->init ()) {
568 delete rt;
569 return -1;
571 boost_debug_shared_ptr_mark_interesting (rt, "Route");
572 boost::shared_ptr<Route> r (rt);
573 r->input()->ensure_io (count, false, this);
574 r->output()->ensure_io (count, false, this);
575 r->set_remote_control_id (control_id++);
577 rl.push_back (r);
579 if (Config->get_use_monitor_bus()) {
580 Route* rt = new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO);
581 if (rt->init ()) {
582 delete rt;
583 return -1;
585 boost_debug_shared_ptr_mark_interesting (rt, "Route");
586 boost::shared_ptr<Route> r (rt);
587 r->input()->ensure_io (count, false, this);
588 r->output()->ensure_io (count, false, this);
589 r->set_remote_control_id (control_id);
591 rl.push_back (r);
594 } else {
595 /* prohibit auto-connect to master, because there isn't one */
596 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
599 if (!rl.empty()) {
600 add_routes (rl, false);
603 /* this allows the user to override settings with an environment variable.
606 if (no_auto_connect()) {
607 bus_profile->input_ac = AutoConnectOption (0);
608 bus_profile->output_ac = AutoConnectOption (0);
611 Config->set_input_auto_connect (bus_profile->input_ac);
612 Config->set_output_auto_connect (bus_profile->output_ac);
615 save_state ("");
617 return 0;
620 void
621 Session::maybe_write_autosave()
623 if (dirty() && record_status() != Recording) {
624 save_state("", true);
628 void
629 Session::remove_pending_capture_state ()
631 sys::path pending_state_file_path(_session_dir->root_path());
633 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
637 sys::remove (pending_state_file_path);
639 catch(sys::filesystem_error& ex)
641 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
642 pending_state_file_path.to_string(), ex.what()) << endmsg;
646 /** Rename a state file.
647 * @param snapshot_name Snapshot name.
649 void
650 Session::rename_state (string old_name, string new_name)
652 if (old_name == _current_snapshot_name || old_name == _name) {
653 /* refuse to rename the current snapshot or the "main" one */
654 return;
657 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
658 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
660 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
661 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
665 sys::rename (old_xml_path, new_xml_path);
667 catch (const sys::filesystem_error& err)
669 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
670 old_name, new_name, err.what()) << endmsg;
674 /** Remove a state file.
675 * @param snapshot_name Snapshot name.
677 void
678 Session::remove_state (string snapshot_name)
680 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
681 // refuse to remove the current snapshot or the "main" one
682 return;
685 sys::path xml_path(_session_dir->root_path());
687 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
689 if (!create_backup_file (xml_path)) {
690 // don't remove it if a backup can't be made
691 // create_backup_file will log the error.
692 return;
695 // and delete it
696 sys::remove (xml_path);
699 #ifdef HAVE_JACK_SESSION
700 void
701 Session::jack_session_event (jack_session_event_t * event)
703 char timebuf[128];
704 time_t n;
705 struct tm local_time;
707 time (&n);
708 localtime_r (&n, &local_time);
709 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
711 if (event->type == JackSessionSaveTemplate)
713 if (save_template( timebuf )) {
714 event->flags = JackSessionSaveError;
715 } else {
716 string cmd ("ardour3 -P -U ");
717 cmd += event->client_uuid;
718 cmd += " -T ";
719 cmd += timebuf;
721 event->command_line = strdup (cmd.c_str());
724 else
726 if (save_state (timebuf)) {
727 event->flags = JackSessionSaveError;
728 } else {
729 sys::path xml_path (_session_dir->root_path());
730 xml_path /= legalize_for_path (timebuf) + statefile_suffix;
732 string cmd ("ardour3 -P -U ");
733 cmd += event->client_uuid;
734 cmd += " \"";
735 cmd += xml_path.to_string();
736 cmd += '\"';
738 event->command_line = strdup (cmd.c_str());
742 jack_session_reply (_engine.jack(), event);
744 if (event->type == JackSessionSaveAndQuit) {
745 // TODO: make ardour quit.
748 jack_session_event_free( event );
750 #endif
753 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
755 XMLTree tree;
756 sys::path xml_path(_session_dir->root_path());
758 if (!_writable || (_state_of_the_state & CannotSave)) {
759 return 1;
762 if (!_engine.connected ()) {
763 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
764 PROGRAM_NAME)
765 << endmsg;
766 return 1;
769 /* tell sources we're saving first, in case they write out to a new file
770 * which should be saved with the state rather than the old one */
771 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
772 i->second->session_saved();
775 tree.set_root (&get_state());
777 if (snapshot_name.empty()) {
778 snapshot_name = _current_snapshot_name;
779 } else if (switch_to_snapshot) {
780 _current_snapshot_name = snapshot_name;
783 if (!pending) {
785 /* proper save: use statefile_suffix (.ardour in English) */
787 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
789 /* make a backup copy of the old file */
791 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
792 // create_backup_file will log the error
793 return -1;
796 } else {
798 /* pending save: use pending_suffix (.pending in English) */
799 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
802 sys::path tmp_path(_session_dir->root_path());
804 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
806 // cerr << "actually writing state to " << xml_path.to_string() << endl;
808 if (!tree.write (tmp_path.to_string())) {
809 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
810 sys::remove (tmp_path);
811 return -1;
813 } else {
815 if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
816 error << string_compose (_("could not rename temporary session file %1 to %2"),
817 tmp_path.to_string(), xml_path.to_string()) << endmsg;
818 sys::remove (tmp_path);
819 return -1;
823 if (!pending) {
825 save_history (snapshot_name);
827 bool was_dirty = dirty();
829 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
831 if (was_dirty) {
832 DirtyChanged (); /* EMIT SIGNAL */
835 StateSaved (snapshot_name); /* EMIT SIGNAL */
838 return 0;
842 Session::restore_state (string snapshot_name)
844 if (load_state (snapshot_name) == 0) {
845 set_state (*state_tree->root(), Stateful::loading_state_version);
848 return 0;
852 Session::load_state (string snapshot_name)
854 delete state_tree;
855 state_tree = 0;
857 state_was_pending = false;
859 /* check for leftover pending state from a crashed capture attempt */
861 sys::path xmlpath(_session_dir->root_path());
862 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
864 if (sys::exists (xmlpath)) {
866 /* there is pending state from a crashed capture attempt */
868 boost::optional<int> r = AskAboutPendingState();
869 if (r.get_value_or (1)) {
870 state_was_pending = true;
874 if (!state_was_pending) {
875 xmlpath = _session_dir->root_path();
876 xmlpath /= snapshot_name;
879 if (!sys::exists (xmlpath)) {
880 xmlpath = _session_dir->root_path();
881 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
882 if (!sys::exists (xmlpath)) {
883 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
884 return 1;
888 state_tree = new XMLTree;
890 set_dirty();
892 /* writable() really reflects the whole folder, but if for any
893 reason the session state file can't be written to, still
894 make us unwritable.
897 if (::access (xmlpath.to_string().c_str(), W_OK) != 0) {
898 _writable = false;
901 if (!state_tree->read (xmlpath.to_string())) {
902 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
903 delete state_tree;
904 state_tree = 0;
905 return -1;
908 XMLNode& root (*state_tree->root());
910 if (root.name() != X_("Session")) {
911 error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg;
912 delete state_tree;
913 state_tree = 0;
914 return -1;
917 const XMLProperty* prop;
919 if ((prop = root.property ("version")) == 0) {
920 /* no version implies very old version of Ardour */
921 Stateful::loading_state_version = 1000;
922 } else {
923 int major;
924 int minor;
925 int micro;
927 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, &micro);
928 Stateful::loading_state_version = (major * 1000) + minor;
931 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
933 sys::path backup_path(_session_dir->root_path());
935 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
937 // only create a backup once
938 if (sys::exists (backup_path)) {
939 return 0;
942 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
943 xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME)
944 << endmsg;
948 sys::copy_file (xmlpath, backup_path);
950 catch(sys::filesystem_error& ex)
952 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
953 xmlpath.to_string(), ex.what())
954 << endmsg;
955 return -1;
959 return 0;
963 Session::load_options (const XMLNode& node)
965 LocaleGuard lg (X_("POSIX"));
966 config.set_variables (node);
967 return 0;
970 XMLNode&
971 Session::get_state()
973 return state(true);
976 XMLNode&
977 Session::get_template()
979 /* if we don't disable rec-enable, diskstreams
980 will believe they need to store their capture
981 sources in their state node.
984 disable_record (false);
986 return state(false);
989 XMLNode&
990 Session::state(bool full_state)
992 XMLNode* node = new XMLNode("Session");
993 XMLNode* child;
995 // store libardour version, just in case
996 char buf[16];
997 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
998 node->add_property("version", string(buf));
1000 /* store configuration settings */
1002 if (full_state) {
1004 node->add_property ("name", _name);
1005 snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
1006 node->add_property ("sample-rate", buf);
1008 if (session_dirs.size() > 1) {
1010 string p;
1012 vector<space_and_path>::iterator i = session_dirs.begin();
1013 vector<space_and_path>::iterator next;
1015 ++i; /* skip the first one */
1016 next = i;
1017 ++next;
1019 while (i != session_dirs.end()) {
1021 p += (*i).path;
1023 if (next != session_dirs.end()) {
1024 p += ':';
1025 } else {
1026 break;
1029 ++next;
1030 ++i;
1033 child = node->add_child ("Path");
1034 child->add_content (p);
1038 /* save the ID counter */
1040 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1041 node->add_property ("id-counter", buf);
1043 /* various options */
1045 node->add_child_nocopy (config.get_variables ());
1047 node->add_child_nocopy (_metadata->get_state());
1049 child = node->add_child ("Sources");
1051 if (full_state) {
1052 Glib::Mutex::Lock sl (source_lock);
1054 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1056 /* Don't save information about non-destructive file sources that are empty
1057 and unused by any regions.
1060 boost::shared_ptr<FileSource> fs;
1061 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1062 if (!fs->destructive()) {
1063 if (fs->empty() && !fs->used()) {
1064 continue;
1069 child->add_child_nocopy (siter->second->get_state());
1073 child = node->add_child ("Regions");
1075 if (full_state) {
1076 Glib::Mutex::Lock rl (region_lock);
1077 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1078 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1079 boost::shared_ptr<Region> r = i->second;
1080 /* only store regions not attached to playlists */
1081 if (r->playlist() == 0) {
1082 child->add_child_nocopy (r->state (true));
1087 if (full_state) {
1088 node->add_child_nocopy (_locations.get_state());
1089 } else {
1090 // for a template, just create a new Locations, populate it
1091 // with the default start and end, and get the state for that.
1092 Locations loc;
1093 Location* range = new Location (0, 0, _("session"), Location::IsSessionRange);
1094 range->set (max_frames, 0);
1095 loc.add (range);
1096 node->add_child_nocopy (loc.get_state());
1099 child = node->add_child ("Bundles");
1101 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1102 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1103 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1104 if (b) {
1105 child->add_child_nocopy (b->get_state());
1110 child = node->add_child ("Routes");
1112 boost::shared_ptr<RouteList> r = routes.reader ();
1114 RoutePublicOrderSorter cmp;
1115 RouteList public_order (*r);
1116 public_order.sort (cmp);
1118 /* the sort should have put control outs first */
1120 if (_monitor_out) {
1121 assert (_monitor_out == public_order.front());
1124 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1125 if (!(*i)->is_hidden()) {
1126 if (full_state) {
1127 child->add_child_nocopy ((*i)->get_state());
1128 } else {
1129 child->add_child_nocopy ((*i)->get_template());
1135 playlists->add_state (node, full_state);
1137 child = node->add_child ("RouteGroups");
1138 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1139 child->add_child_nocopy ((*i)->get_state());
1142 if (_click_io) {
1143 child = node->add_child ("Click");
1144 child->add_child_nocopy (_click_io->state (full_state));
1147 if (full_state) {
1148 child = node->add_child ("NamedSelections");
1149 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1150 if (full_state) {
1151 child->add_child_nocopy ((*i)->get_state());
1156 node->add_child_nocopy (_tempo_map->get_state());
1158 node->add_child_nocopy (get_control_protocol_state());
1160 if (_extra_xml) {
1161 node->add_child_copy (*_extra_xml);
1164 return *node;
1167 XMLNode&
1168 Session::get_control_protocol_state ()
1170 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1171 return cpm.get_state();
1175 Session::set_state (const XMLNode& node, int version)
1177 XMLNodeList nlist;
1178 XMLNode* child;
1179 const XMLProperty* prop;
1180 int ret = -1;
1182 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1184 if (node.name() != X_("Session")){
1185 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1186 return -1;
1189 if ((prop = node.property ("version")) != 0) {
1190 version = atoi (prop->value ()) * 1000;
1193 if ((prop = node.property ("name")) != 0) {
1194 _name = prop->value ();
1197 if ((prop = node.property (X_("sample-rate"))) != 0) {
1199 _nominal_frame_rate = atoi (prop->value());
1201 if (_nominal_frame_rate != _current_frame_rate) {
1202 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1203 if (r.get_value_or (0)) {
1204 return -1;
1209 setup_raid_path(_session_dir->root_path().to_string());
1211 if ((prop = node.property (X_("id-counter"))) != 0) {
1212 uint64_t x;
1213 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1214 ID::init_counter (x);
1215 } else {
1216 /* old sessions used a timebased counter, so fake
1217 the startup ID counter based on a standard
1218 timestamp.
1220 time_t now;
1221 time (&now);
1222 ID::init_counter (now);
1226 IO::disable_connecting ();
1228 /* Object loading order:
1230 Path
1231 Extra
1232 Options/Config
1233 MIDI Control // relies on data from Options/Config
1234 Metadata
1235 Locations
1236 Sources
1237 AudioRegions
1238 Connections
1239 Routes
1240 RouteGroups
1241 MixGroups
1242 Click
1243 ControlProtocols
1246 if ((child = find_named_node (node, "Extra")) != 0) {
1247 _extra_xml = new XMLNode (*child);
1250 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1251 load_options (*child);
1252 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1253 load_options (*child);
1254 } else {
1255 error << _("Session: XML state has no options section") << endmsg;
1258 if (version >= 3000) {
1259 if ((child = find_named_node (node, "Metadata")) == 0) {
1260 warning << _("Session: XML state has no metadata section") << endmsg;
1261 } else if (_metadata->set_state (*child, version)) {
1262 goto out;
1266 if ((child = find_named_node (node, "Locations")) == 0) {
1267 error << _("Session: XML state has no locations section") << endmsg;
1268 goto out;
1269 } else if (_locations.set_state (*child, version)) {
1270 goto out;
1273 Location* location;
1275 if ((location = _locations.auto_loop_location()) != 0) {
1276 set_auto_loop_location (location);
1279 if ((location = _locations.auto_punch_location()) != 0) {
1280 set_auto_punch_location (location);
1283 if ((location = _locations.session_range_location()) != 0) {
1284 delete _session_range_location;
1285 _session_range_location = location;
1288 if (_session_range_location) {
1289 AudioFileSource::set_header_position_offset (_session_range_location->start());
1292 if ((child = find_named_node (node, "Sources")) == 0) {
1293 error << _("Session: XML state has no sources section") << endmsg;
1294 goto out;
1295 } else if (load_sources (*child)) {
1296 goto out;
1299 if ((child = find_named_node (node, "Regions")) == 0) {
1300 error << _("Session: XML state has no Regions section") << endmsg;
1301 goto out;
1302 } else if (load_regions (*child)) {
1303 goto out;
1306 if ((child = find_named_node (node, "Playlists")) == 0) {
1307 error << _("Session: XML state has no playlists section") << endmsg;
1308 goto out;
1309 } else if (playlists->load (*this, *child)) {
1310 goto out;
1313 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1314 // this is OK
1315 } else if (playlists->load_unused (*this, *child)) {
1316 goto out;
1319 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1320 if (load_named_selections (*child)) {
1321 goto out;
1325 if (version >= 3000) {
1326 if ((child = find_named_node (node, "Bundles")) == 0) {
1327 warning << _("Session: XML state has no bundles section") << endmsg;
1328 //goto out;
1329 } else {
1330 /* We can't load Bundles yet as they need to be able
1331 to convert from port names to Port objects, which can't happen until
1332 later */
1333 _bundle_xml_node = new XMLNode (*child);
1337 if ((child = find_named_node (node, "TempoMap")) == 0) {
1338 error << _("Session: XML state has no Tempo Map section") << endmsg;
1339 goto out;
1340 } else if (_tempo_map->set_state (*child, version)) {
1341 goto out;
1344 if (version < 3000) {
1345 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1346 error << _("Session: XML state has no diskstreams section") << endmsg;
1347 goto out;
1348 } else if (load_diskstreams_2X (*child, version)) {
1349 goto out;
1353 if ((child = find_named_node (node, "Routes")) == 0) {
1354 error << _("Session: XML state has no routes section") << endmsg;
1355 goto out;
1356 } else if (load_routes (*child, version)) {
1357 goto out;
1360 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1361 _diskstreams_2X.clear ();
1363 if (version >= 3000) {
1365 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1366 error << _("Session: XML state has no route groups section") << endmsg;
1367 goto out;
1368 } else if (load_route_groups (*child, version)) {
1369 goto out;
1372 } else if (version < 3000) {
1374 if ((child = find_named_node (node, "EditGroups")) == 0) {
1375 error << _("Session: XML state has no edit groups section") << endmsg;
1376 goto out;
1377 } else if (load_route_groups (*child, version)) {
1378 goto out;
1381 if ((child = find_named_node (node, "MixGroups")) == 0) {
1382 error << _("Session: XML state has no mix groups section") << endmsg;
1383 goto out;
1384 } else if (load_route_groups (*child, version)) {
1385 goto out;
1389 if ((child = find_named_node (node, "Click")) == 0) {
1390 warning << _("Session: XML state has no click section") << endmsg;
1391 } else if (_click_io) {
1392 _click_io->set_state (*child, version);
1395 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1396 ControlProtocolManager::instance().set_protocol_states (*child);
1399 /* here beginneth the second phase ... */
1401 StateReady (); /* EMIT SIGNAL */
1403 return 0;
1405 out:
1406 return ret;
1410 Session::load_routes (const XMLNode& node, int version)
1412 XMLNodeList nlist;
1413 XMLNodeConstIterator niter;
1414 RouteList new_routes;
1416 nlist = node.children();
1418 set_dirty();
1420 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1422 boost::shared_ptr<Route> route;
1423 if (version < 3000) {
1424 route = XMLRouteFactory_2X (**niter, version);
1425 } else {
1426 route = XMLRouteFactory (**niter, version);
1429 if (route == 0) {
1430 error << _("Session: cannot create Route from XML description.") << endmsg;
1431 return -1;
1434 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1436 new_routes.push_back (route);
1439 add_routes (new_routes, false);
1441 return 0;
1444 boost::shared_ptr<Route>
1445 Session::XMLRouteFactory (const XMLNode& node, int version)
1447 boost::shared_ptr<Route> ret;
1449 if (node.name() != "Route") {
1450 return ret;
1453 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1455 DataType type = DataType::AUDIO;
1456 const XMLProperty* prop = node.property("default-type");
1458 if (prop) {
1459 type = DataType (prop->value());
1462 assert (type != DataType::NIL);
1464 if (ds_child) {
1466 Track* track;
1468 if (type == DataType::AUDIO) {
1469 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1471 } else {
1472 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1475 if (track->init()) {
1476 delete track;
1477 return ret;
1480 if (track->set_state (node, version)) {
1481 delete track;
1482 return ret;
1485 boost_debug_shared_ptr_mark_interesting (track, "Track");
1486 ret.reset (track);
1488 } else {
1489 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1491 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1492 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1493 ret.reset (rt);
1494 } else {
1495 delete rt;
1499 return ret;
1502 boost::shared_ptr<Route>
1503 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1505 boost::shared_ptr<Route> ret;
1507 if (node.name() != "Route") {
1508 return ret;
1511 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1512 if (!ds_prop) {
1513 ds_prop = node.property (X_("diskstream"));
1516 DataType type = DataType::AUDIO;
1517 const XMLProperty* prop = node.property("default-type");
1519 if (prop) {
1520 type = DataType (prop->value());
1523 assert (type != DataType::NIL);
1525 if (ds_prop) {
1527 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1528 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1529 ++i;
1532 if (i == _diskstreams_2X.end()) {
1533 error << _("Could not find diskstream for route") << endmsg;
1534 return boost::shared_ptr<Route> ();
1537 Track* track;
1539 if (type == DataType::AUDIO) {
1540 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1542 } else {
1543 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1546 if (track->init()) {
1547 delete track;
1548 return ret;
1551 if (track->set_state (node, version)) {
1552 delete track;
1553 return ret;
1556 track->set_diskstream (*i);
1558 boost_debug_shared_ptr_mark_interesting (track, "Track");
1559 ret.reset (track);
1561 } else {
1562 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1564 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1565 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1566 ret.reset (rt);
1567 } else {
1568 delete rt;
1572 return ret;
1576 Session::load_regions (const XMLNode& node)
1578 XMLNodeList nlist;
1579 XMLNodeConstIterator niter;
1580 boost::shared_ptr<Region> region;
1582 nlist = node.children();
1584 set_dirty();
1586 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1587 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1588 error << _("Session: cannot create Region from XML description.");
1589 const XMLProperty *name = (**niter).property("name");
1591 if (name) {
1592 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1595 error << endmsg;
1599 return 0;
1602 boost::shared_ptr<Region>
1603 Session::XMLRegionFactory (const XMLNode& node, bool full)
1605 const XMLProperty* type = node.property("type");
1607 try {
1609 if ( !type || type->value() == "audio" ) {
1611 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1613 } else if (type->value() == "midi") {
1615 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1619 } catch (failed_constructor& err) {
1620 return boost::shared_ptr<Region> ();
1623 return boost::shared_ptr<Region> ();
1626 boost::shared_ptr<AudioRegion>
1627 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1629 const XMLProperty* prop;
1630 boost::shared_ptr<Source> source;
1631 boost::shared_ptr<AudioSource> as;
1632 SourceList sources;
1633 SourceList master_sources;
1634 uint32_t nchans = 1;
1635 char buf[128];
1637 if (node.name() != X_("Region")) {
1638 return boost::shared_ptr<AudioRegion>();
1641 if ((prop = node.property (X_("channels"))) != 0) {
1642 nchans = atoi (prop->value().c_str());
1645 if ((prop = node.property ("name")) == 0) {
1646 cerr << "no name for this region\n";
1647 abort ();
1650 if ((prop = node.property (X_("source-0"))) == 0) {
1651 if ((prop = node.property ("source")) == 0) {
1652 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1653 return boost::shared_ptr<AudioRegion>();
1657 PBD::ID s_id (prop->value());
1659 if ((source = source_by_id (s_id)) == 0) {
1660 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1661 return boost::shared_ptr<AudioRegion>();
1664 as = boost::dynamic_pointer_cast<AudioSource>(source);
1665 if (!as) {
1666 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1667 return boost::shared_ptr<AudioRegion>();
1670 sources.push_back (as);
1672 /* pickup other channels */
1674 for (uint32_t n=1; n < nchans; ++n) {
1675 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1676 if ((prop = node.property (buf)) != 0) {
1678 PBD::ID id2 (prop->value());
1680 if ((source = source_by_id (id2)) == 0) {
1681 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1682 return boost::shared_ptr<AudioRegion>();
1685 as = boost::dynamic_pointer_cast<AudioSource>(source);
1686 if (!as) {
1687 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1688 return boost::shared_ptr<AudioRegion>();
1690 sources.push_back (as);
1694 for (uint32_t n = 0; n < nchans; ++n) {
1695 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1696 if ((prop = node.property (buf)) != 0) {
1698 PBD::ID id2 (prop->value());
1700 if ((source = source_by_id (id2)) == 0) {
1701 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1702 return boost::shared_ptr<AudioRegion>();
1705 as = boost::dynamic_pointer_cast<AudioSource>(source);
1706 if (!as) {
1707 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1708 return boost::shared_ptr<AudioRegion>();
1710 master_sources.push_back (as);
1714 try {
1715 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1717 /* a final detail: this is the one and only place that we know how long missing files are */
1719 if (region->whole_file()) {
1720 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1721 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1722 if (sfp) {
1723 sfp->set_length (region->length());
1728 if (!master_sources.empty()) {
1729 if (master_sources.size() != nchans) {
1730 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1731 } else {
1732 region->set_master_sources (master_sources);
1736 return region;
1740 catch (failed_constructor& err) {
1741 return boost::shared_ptr<AudioRegion>();
1745 boost::shared_ptr<MidiRegion>
1746 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1748 const XMLProperty* prop;
1749 boost::shared_ptr<Source> source;
1750 boost::shared_ptr<MidiSource> ms;
1751 SourceList sources;
1752 uint32_t nchans = 1;
1754 if (node.name() != X_("Region")) {
1755 return boost::shared_ptr<MidiRegion>();
1758 if ((prop = node.property (X_("channels"))) != 0) {
1759 nchans = atoi (prop->value().c_str());
1762 if ((prop = node.property ("name")) == 0) {
1763 cerr << "no name for this region\n";
1764 abort ();
1767 // Multiple midi channels? that's just crazy talk
1768 assert(nchans == 1);
1770 if ((prop = node.property (X_("source-0"))) == 0) {
1771 if ((prop = node.property ("source")) == 0) {
1772 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1773 return boost::shared_ptr<MidiRegion>();
1777 PBD::ID s_id (prop->value());
1779 if ((source = source_by_id (s_id)) == 0) {
1780 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1781 return boost::shared_ptr<MidiRegion>();
1784 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1785 if (!ms) {
1786 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1787 return boost::shared_ptr<MidiRegion>();
1790 sources.push_back (ms);
1792 try {
1793 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1794 /* a final detail: this is the one and only place that we know how long missing files are */
1796 if (region->whole_file()) {
1797 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1798 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1799 if (sfp) {
1800 sfp->set_length (region->length());
1805 return region;
1808 catch (failed_constructor& err) {
1809 return boost::shared_ptr<MidiRegion>();
1813 XMLNode&
1814 Session::get_sources_as_xml ()
1817 XMLNode* node = new XMLNode (X_("Sources"));
1818 Glib::Mutex::Lock lm (source_lock);
1820 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1821 node->add_child_nocopy (i->second->get_state());
1824 return *node;
1827 string
1828 Session::path_from_region_name (DataType type, string name, string identifier)
1830 char buf[PATH_MAX+1];
1831 uint32_t n;
1832 SessionDirectory sdir(get_best_session_directory_for_new_source());
1833 sys::path source_dir = ((type == DataType::AUDIO)
1834 ? sdir.sound_path() : sdir.midi_path());
1836 string ext = ((type == DataType::AUDIO) ? ".wav" : ".mid");
1838 for (n = 0; n < 999999; ++n) {
1839 if (identifier.length()) {
1840 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1841 identifier.c_str(), n, ext.c_str());
1842 } else {
1843 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1844 n, ext.c_str());
1847 sys::path source_path = source_dir / buf;
1849 if (!sys::exists (source_path)) {
1850 return source_path.to_string();
1854 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1855 name, identifier)
1856 << endmsg;
1858 return "";
1863 Session::load_sources (const XMLNode& node)
1865 XMLNodeList nlist;
1866 XMLNodeConstIterator niter;
1867 boost::shared_ptr<Source> source;
1869 nlist = node.children();
1871 set_dirty();
1873 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1874 try {
1875 if ((source = XMLSourceFactory (**niter)) == 0) {
1876 error << _("Session: cannot create Source from XML description.") << endmsg;
1878 } catch (MissingSource& err) {
1879 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1880 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1884 return 0;
1887 boost::shared_ptr<Source>
1888 Session::XMLSourceFactory (const XMLNode& node)
1890 if (node.name() != "Source") {
1891 return boost::shared_ptr<Source>();
1894 try {
1895 /* note: do peak building in another thread when loading session state */
1896 return SourceFactory::create (*this, node, true);
1899 catch (failed_constructor& err) {
1900 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1901 return boost::shared_ptr<Source>();
1906 Session::save_template (string template_name)
1908 XMLTree tree;
1910 if (_state_of_the_state & CannotSave) {
1911 return -1;
1914 sys::path user_template_dir(user_template_directory());
1918 sys::create_directories (user_template_dir);
1920 catch(sys::filesystem_error& ex)
1922 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1923 user_template_dir.to_string(), ex.what()) << endmsg;
1924 return -1;
1927 tree.set_root (&get_template());
1929 sys::path template_file_path(user_template_dir);
1930 template_file_path /= template_name + template_suffix;
1932 if (sys::exists (template_file_path))
1934 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1935 template_file_path.to_string()) << endmsg;
1936 return -1;
1939 if (!tree.write (template_file_path.to_string())) {
1940 error << _("mix template not saved") << endmsg;
1941 return -1;
1944 return 0;
1948 Session::rename_template (string old_name, string new_name)
1950 sys::path old_path (user_template_directory());
1951 old_path /= old_name + template_suffix;
1953 sys::path new_path(user_template_directory());
1954 new_path /= new_name + template_suffix;
1956 if (sys::exists (new_path)) {
1957 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
1958 new_path.to_string()) << endmsg;
1959 return -1;
1962 try {
1963 sys::rename (old_path, new_path);
1964 return 0;
1965 } catch (...) {
1966 return -1;
1971 Session::delete_template (string name)
1973 sys::path path = user_template_directory();
1974 path /= name + template_suffix;
1976 try {
1977 sys::remove (path);
1978 return 0;
1979 } catch (...) {
1980 return -1;
1984 void
1985 Session::refresh_disk_space ()
1987 #if HAVE_SYS_VFS_H
1988 struct statfs statfsbuf;
1989 vector<space_and_path>::iterator i;
1990 Glib::Mutex::Lock lm (space_lock);
1991 double scale;
1993 /* get freespace on every FS that is part of the session path */
1995 _total_free_4k_blocks = 0;
1997 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1998 statfs ((*i).path.c_str(), &statfsbuf);
2000 scale = statfsbuf.f_bsize/4096.0;
2002 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2003 _total_free_4k_blocks += (*i).blocks;
2005 #endif
2008 string
2009 Session::get_best_session_directory_for_new_source ()
2011 vector<space_and_path>::iterator i;
2012 string result = _session_dir->root_path().to_string();
2014 /* handle common case without system calls */
2016 if (session_dirs.size() == 1) {
2017 return result;
2020 /* OK, here's the algorithm we're following here:
2022 We want to select which directory to use for
2023 the next file source to be created. Ideally,
2024 we'd like to use a round-robin process so as to
2025 get maximum performance benefits from splitting
2026 the files across multiple disks.
2028 However, in situations without much diskspace, an
2029 RR approach may end up filling up a filesystem
2030 with new files while others still have space.
2031 Its therefore important to pay some attention to
2032 the freespace in the filesystem holding each
2033 directory as well. However, if we did that by
2034 itself, we'd keep creating new files in the file
2035 system with the most space until it was as full
2036 as all others, thus negating any performance
2037 benefits of this RAID-1 like approach.
2039 So, we use a user-configurable space threshold. If
2040 there are at least 2 filesystems with more than this
2041 much space available, we use RR selection between them.
2042 If not, then we pick the filesystem with the most space.
2044 This gets a good balance between the two
2045 approaches.
2048 refresh_disk_space ();
2050 int free_enough = 0;
2052 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2053 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2054 free_enough++;
2058 if (free_enough >= 2) {
2059 /* use RR selection process, ensuring that the one
2060 picked works OK.
2063 i = last_rr_session_dir;
2065 do {
2066 if (++i == session_dirs.end()) {
2067 i = session_dirs.begin();
2070 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2071 if (create_session_directory ((*i).path)) {
2072 result = (*i).path;
2073 last_rr_session_dir = i;
2074 return result;
2078 } while (i != last_rr_session_dir);
2080 } else {
2082 /* pick FS with the most freespace (and that
2083 seems to actually work ...)
2086 vector<space_and_path> sorted;
2087 space_and_path_ascending_cmp cmp;
2089 sorted = session_dirs;
2090 sort (sorted.begin(), sorted.end(), cmp);
2092 for (i = sorted.begin(); i != sorted.end(); ++i) {
2093 if (create_session_directory ((*i).path)) {
2094 result = (*i).path;
2095 last_rr_session_dir = i;
2096 return result;
2101 return result;
2105 Session::load_named_selections (const XMLNode& node)
2107 XMLNodeList nlist;
2108 XMLNodeConstIterator niter;
2109 NamedSelection *ns;
2111 nlist = node.children();
2113 set_dirty();
2115 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2117 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2118 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2122 return 0;
2125 NamedSelection *
2126 Session::XMLNamedSelectionFactory (const XMLNode& node)
2128 try {
2129 return new NamedSelection (*this, node);
2132 catch (failed_constructor& err) {
2133 return 0;
2137 string
2138 Session::automation_dir () const
2140 return Glib::build_filename (_path, "automation");
2143 string
2144 Session::analysis_dir () const
2146 return Glib::build_filename (_path, "analysis");
2150 Session::load_bundles (XMLNode const & node)
2152 XMLNodeList nlist = node.children();
2153 XMLNodeConstIterator niter;
2155 set_dirty();
2157 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2158 if ((*niter)->name() == "InputBundle") {
2159 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2160 } else if ((*niter)->name() == "OutputBundle") {
2161 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2162 } else {
2163 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2164 return -1;
2168 return 0;
2172 Session::load_route_groups (const XMLNode& node, int version)
2174 XMLNodeList nlist = node.children();
2175 XMLNodeConstIterator niter;
2177 set_dirty ();
2179 if (version >= 3000) {
2181 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2182 if ((*niter)->name() == "RouteGroup") {
2183 RouteGroup* rg = new RouteGroup (*this, "");
2184 add_route_group (rg);
2185 rg->set_state (**niter, version);
2189 } else if (version < 3000) {
2191 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2192 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2193 RouteGroup* rg = new RouteGroup (*this, "");
2194 add_route_group (rg);
2195 rg->set_state (**niter, version);
2200 return 0;
2203 void
2204 Session::auto_save()
2206 save_state (_current_snapshot_name);
2209 static bool
2210 state_file_filter (const string &str, void */*arg*/)
2212 return (str.length() > strlen(statefile_suffix) &&
2213 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2216 struct string_cmp {
2217 bool operator()(const string* a, const string* b) {
2218 return *a < *b;
2222 static string*
2223 remove_end(string* state)
2225 string statename(*state);
2227 string::size_type start,end;
2228 if ((start = statename.find_last_of ('/')) != string::npos) {
2229 statename = statename.substr (start+1);
2232 if ((end = statename.rfind(".ardour")) == string::npos) {
2233 end = statename.length();
2236 return new string(statename.substr (0, end));
2239 vector<string *> *
2240 Session::possible_states (string path)
2242 PathScanner scanner;
2243 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2245 transform(states->begin(), states->end(), states->begin(), remove_end);
2247 string_cmp cmp;
2248 sort (states->begin(), states->end(), cmp);
2250 return states;
2253 vector<string *> *
2254 Session::possible_states () const
2256 return possible_states(_path);
2259 void
2260 Session::add_route_group (RouteGroup* g)
2262 _route_groups.push_back (g);
2263 route_group_added (g); /* EMIT SIGNAL */
2265 g->MembershipChanged.connect_same_thread (*this, boost::bind (&Session::route_group_changed, this));
2266 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_changed, this));
2268 set_dirty ();
2271 void
2272 Session::remove_route_group (RouteGroup& rg)
2274 list<RouteGroup*>::iterator i;
2276 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2277 _route_groups.erase (i);
2278 delete &rg;
2280 route_group_removed (); /* EMIT SIGNAL */
2285 RouteGroup *
2286 Session::route_group_by_name (string name)
2288 list<RouteGroup *>::iterator i;
2290 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2291 if ((*i)->name() == name) {
2292 return* i;
2295 return 0;
2298 UndoTransaction*
2299 Session::start_reversible_command (const string& name)
2301 UndoTransaction* trans = new UndoTransaction();
2302 trans->set_name(name);
2303 return trans;
2306 void
2307 Session::finish_reversible_command (UndoTransaction& ut)
2309 struct timeval now;
2310 gettimeofday(&now, 0);
2311 ut.set_timestamp(now);
2312 _history.add (&ut);
2315 void
2316 Session::begin_reversible_command(const string& name)
2318 UndoTransaction* trans = new UndoTransaction();
2319 trans->set_name(name);
2321 if (!_current_trans.empty()) {
2322 _current_trans.top()->add_command (trans);
2323 } else {
2324 _current_trans.push(trans);
2328 void
2329 Session::commit_reversible_command(Command *cmd)
2331 assert(!_current_trans.empty());
2332 struct timeval now;
2334 if (cmd) {
2335 _current_trans.top()->add_command(cmd);
2338 if (_current_trans.top()->empty()) {
2339 _current_trans.pop();
2340 return;
2343 gettimeofday(&now, 0);
2344 _current_trans.top()->set_timestamp(now);
2346 _history.add(_current_trans.top());
2347 _current_trans.pop();
2350 static bool
2351 accept_all_non_peak_files (const string& path, void */*arg*/)
2353 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2356 static bool
2357 accept_all_state_files (const string& path, void */*arg*/)
2359 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2363 Session::find_all_sources (string path, set<string>& result)
2365 XMLTree tree;
2366 XMLNode* node;
2368 if (!tree.read (path)) {
2369 return -1;
2372 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2373 return -2;
2376 XMLNodeList nlist;
2377 XMLNodeConstIterator niter;
2379 nlist = node->children();
2381 set_dirty();
2383 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2385 XMLProperty* prop;
2387 if ((prop = (*niter)->property (X_("type"))) == 0) {
2388 continue;
2391 DataType type (prop->value());
2393 if ((prop = (*niter)->property (X_("name"))) == 0) {
2394 continue;
2397 if (prop->value()[0] == '/') {
2398 /* external file, ignore */
2399 continue;
2402 Glib::ustring found_path;
2403 bool is_new;
2404 uint16_t chan;
2406 if (FileSource::find (type, prop->value(), true, is_new, chan, found_path)) {
2407 result.insert (found_path);
2411 return 0;
2415 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2417 PathScanner scanner;
2418 vector<string*>* state_files;
2419 string ripped;
2420 string this_snapshot_path;
2422 result.clear ();
2424 ripped = _path;
2426 if (ripped[ripped.length()-1] == '/') {
2427 ripped = ripped.substr (0, ripped.length() - 1);
2430 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2432 if (state_files == 0) {
2433 /* impossible! */
2434 return 0;
2437 this_snapshot_path = _path;
2438 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2439 this_snapshot_path += statefile_suffix;
2441 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2443 if (exclude_this_snapshot && **i == this_snapshot_path) {
2444 continue;
2447 if (find_all_sources (**i, result) < 0) {
2448 return -1;
2452 return 0;
2455 struct RegionCounter {
2456 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2457 AudioSourceList::iterator iter;
2458 boost::shared_ptr<Region> region;
2459 uint32_t count;
2461 RegionCounter() : count (0) {}
2465 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2467 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2468 return r.get_value_or (1);
2472 Session::cleanup_sources (CleanupReport& rep)
2474 // FIXME: needs adaptation to midi
2476 vector<boost::shared_ptr<Source> > dead_sources;
2477 PathScanner scanner;
2478 string sound_path;
2479 vector<space_and_path>::iterator i;
2480 vector<space_and_path>::iterator nexti;
2481 vector<string*>* soundfiles;
2482 vector<string> unused;
2483 set<string> all_sources;
2484 bool used;
2485 string spath;
2486 int ret = -1;
2488 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2490 /* step 1: consider deleting all unused playlists */
2492 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2493 ret = 0;
2494 goto out;
2497 /* step 2: find all un-used sources */
2499 rep.paths.clear ();
2500 rep.space = 0;
2502 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2504 SourceMap::iterator tmp;
2506 tmp = i;
2507 ++tmp;
2509 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2510 capture files.
2513 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2514 dead_sources.push_back (i->second);
2515 i->second->drop_references ();
2518 i = tmp;
2521 /* build a list of all the possible sound directories for the session */
2523 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2525 nexti = i;
2526 ++nexti;
2528 SessionDirectory sdir ((*i).path);
2529 sound_path += sdir.sound_path().to_string();
2531 if (nexti != session_dirs.end()) {
2532 sound_path += ':';
2535 i = nexti;
2538 /* now do the same thing for the files that ended up in the sounds dir(s)
2539 but are not referenced as sources in any snapshot.
2542 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2544 if (soundfiles == 0) {
2545 return 0;
2548 /* find all sources, but don't use this snapshot because the
2549 state file on disk still references sources we may have already
2550 dropped.
2553 find_all_sources_across_snapshots (all_sources, true);
2555 /* add our current source list
2558 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2559 boost::shared_ptr<FileSource> fs;
2561 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2562 all_sources.insert (fs->path());
2566 char tmppath1[PATH_MAX+1];
2567 char tmppath2[PATH_MAX+1];
2569 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2571 used = false;
2572 spath = **x;
2574 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2576 if (realpath(spath.c_str(), tmppath1) == 0) {
2577 error << string_compose (_("Cannot expand path %1 (%2)"),
2578 spath, strerror (errno)) << endmsg;
2579 continue;
2582 if (realpath((*i).c_str(), tmppath2) == 0) {
2583 error << string_compose (_("Cannot expand path %1 (%2)"),
2584 (*i), strerror (errno)) << endmsg;
2585 continue;
2588 if (strcmp(tmppath1, tmppath2) == 0) {
2589 used = true;
2590 break;
2594 if (!used) {
2595 unused.push_back (spath);
2599 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2601 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2602 struct stat statbuf;
2604 rep.paths.push_back (*x);
2605 if (stat ((*x).c_str(), &statbuf) == 0) {
2606 rep.space += statbuf.st_size;
2609 string newpath;
2611 /* don't move the file across filesystems, just
2612 stick it in the `dead_sound_dir_name' directory
2613 on whichever filesystem it was already on.
2616 if ((*x).find ("/sounds/") != string::npos) {
2618 /* old school, go up 1 level */
2620 newpath = Glib::path_get_dirname (*x); // "sounds"
2621 newpath = Glib::path_get_dirname (newpath); // "session-name"
2623 } else {
2625 /* new school, go up 4 levels */
2627 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2628 newpath = Glib::path_get_dirname (newpath); // "session-name"
2629 newpath = Glib::path_get_dirname (newpath); // "interchange"
2630 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2633 newpath += '/';
2634 newpath += dead_sound_dir_name;
2636 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2637 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2638 return -1;
2641 newpath += '/';
2642 newpath += Glib::path_get_basename ((*x));
2644 if (access (newpath.c_str(), F_OK) == 0) {
2646 /* the new path already exists, try versioning */
2648 char buf[PATH_MAX+1];
2649 int version = 1;
2650 string newpath_v;
2652 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2653 newpath_v = buf;
2655 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2656 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2657 newpath_v = buf;
2660 if (version == 999) {
2661 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2662 newpath)
2663 << endmsg;
2664 } else {
2665 newpath = newpath_v;
2668 } else {
2670 /* it doesn't exist, or we can't read it or something */
2674 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2675 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2676 (*x), newpath, strerror (errno))
2677 << endmsg;
2678 goto out;
2681 /* see if there an easy to find peakfile for this file, and remove it.
2684 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2685 peakpath += peakfile_suffix;
2687 if (access (peakpath.c_str(), W_OK) == 0) {
2688 if (::unlink (peakpath.c_str()) != 0) {
2689 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2690 peakpath, _path, strerror (errno))
2691 << endmsg;
2692 /* try to back out */
2693 rename (newpath.c_str(), _path.c_str());
2694 goto out;
2699 ret = 0;
2701 /* dump the history list */
2703 _history.clear ();
2705 /* save state so we don't end up a session file
2706 referring to non-existent sources.
2709 save_state ("");
2711 out:
2712 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2714 return ret;
2718 Session::cleanup_trash_sources (CleanupReport& rep)
2720 // FIXME: needs adaptation for MIDI
2722 vector<space_and_path>::iterator i;
2723 string dead_sound_dir;
2724 struct dirent* dentry;
2725 struct stat statbuf;
2726 DIR* dead;
2728 rep.paths.clear ();
2729 rep.space = 0;
2731 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2733 dead_sound_dir = (*i).path;
2734 dead_sound_dir += dead_sound_dir_name;
2736 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2737 continue;
2740 while ((dentry = readdir (dead)) != 0) {
2742 /* avoid '.' and '..' */
2744 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2745 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2746 continue;
2749 string fullpath;
2751 fullpath = dead_sound_dir;
2752 fullpath += '/';
2753 fullpath += dentry->d_name;
2755 if (stat (fullpath.c_str(), &statbuf)) {
2756 continue;
2759 if (!S_ISREG (statbuf.st_mode)) {
2760 continue;
2763 if (unlink (fullpath.c_str())) {
2764 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2765 fullpath, strerror (errno))
2766 << endmsg;
2769 rep.paths.push_back (dentry->d_name);
2770 rep.space += statbuf.st_size;
2773 closedir (dead);
2777 return 0;
2780 void
2781 Session::set_dirty ()
2783 bool was_dirty = dirty();
2785 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2788 if (!was_dirty) {
2789 DirtyChanged(); /* EMIT SIGNAL */
2794 void
2795 Session::set_clean ()
2797 bool was_dirty = dirty();
2799 _state_of_the_state = Clean;
2802 if (was_dirty) {
2803 DirtyChanged(); /* EMIT SIGNAL */
2807 void
2808 Session::set_deletion_in_progress ()
2810 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2813 void
2814 Session::clear_deletion_in_progress ()
2816 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2819 void
2820 Session::add_controllable (boost::shared_ptr<Controllable> c)
2822 /* this adds a controllable to the list managed by the Session.
2823 this is a subset of those managed by the Controllable class
2824 itself, and represents the only ones whose state will be saved
2825 as part of the session.
2828 Glib::Mutex::Lock lm (controllables_lock);
2829 controllables.insert (c);
2832 struct null_deleter { void operator()(void const *) const {} };
2834 void
2835 Session::remove_controllable (Controllable* c)
2837 if (_state_of_the_state | Deletion) {
2838 return;
2841 Glib::Mutex::Lock lm (controllables_lock);
2843 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2845 if (x != controllables.end()) {
2846 controllables.erase (x);
2850 boost::shared_ptr<Controllable>
2851 Session::controllable_by_id (const PBD::ID& id)
2853 Glib::Mutex::Lock lm (controllables_lock);
2855 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2856 if ((*i)->id() == id) {
2857 return *i;
2861 return boost::shared_ptr<Controllable>();
2864 boost::shared_ptr<Controllable>
2865 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2867 boost::shared_ptr<Controllable> c;
2868 boost::shared_ptr<Route> r;
2870 switch (desc.top_level_type()) {
2871 case ControllableDescriptor::NamedRoute:
2873 std::string str = desc.top_level_name();
2874 if (str == "master") {
2875 r = _master_out;
2876 } else if (str == "control" || str == "listen") {
2877 r = _monitor_out;
2878 } else {
2879 r = route_by_name (desc.top_level_name());
2881 break;
2884 case ControllableDescriptor::RemoteControlID:
2885 r = route_by_remote_id (desc.rid());
2886 break;
2889 if (!r) {
2890 return c;
2893 switch (desc.subtype()) {
2894 case ControllableDescriptor::Gain:
2895 c = r->gain_control ();
2896 break;
2898 case ControllableDescriptor::Solo:
2899 c = r->solo_control();
2900 break;
2902 case ControllableDescriptor::Mute:
2903 c = r->mute_control();
2904 break;
2906 case ControllableDescriptor::Recenable:
2908 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
2910 if (t) {
2911 c = t->rec_enable_control ();
2913 break;
2916 case ControllableDescriptor::Pan:
2917 /* XXX pan control */
2918 break;
2920 case ControllableDescriptor::Balance:
2921 /* XXX simple pan control */
2922 break;
2924 case ControllableDescriptor::PluginParameter:
2926 uint32_t plugin = desc.target (0);
2927 uint32_t parameter_index = desc.target (1);
2929 /* revert to zero based counting */
2931 if (plugin > 0) {
2932 --plugin;
2935 if (parameter_index > 0) {
2936 --parameter_index;
2939 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
2941 if (p) {
2942 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
2943 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
2945 break;
2948 case ControllableDescriptor::SendGain:
2950 uint32_t send = desc.target (0);
2952 /* revert to zero-based counting */
2954 if (send > 0) {
2955 --send;
2958 boost::shared_ptr<Processor> p = r->nth_send (send);
2960 if (p) {
2961 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
2962 boost::shared_ptr<Amp> a = s->amp();
2964 if (a) {
2965 c = s->amp()->gain_control();
2968 break;
2971 default:
2972 /* relax and return a null pointer */
2973 break;
2976 return c;
2979 void
2980 Session::add_instant_xml (XMLNode& node, bool write_to_config)
2982 if (_writable) {
2983 Stateful::add_instant_xml (node, _path);
2986 if (write_to_config) {
2987 Config->add_instant_xml (node);
2991 XMLNode*
2992 Session::instant_xml (const string& node_name)
2994 return Stateful::instant_xml (node_name, _path);
2998 Session::save_history (string snapshot_name)
3000 XMLTree tree;
3002 if (!_writable) {
3003 return 0;
3006 if (snapshot_name.empty()) {
3007 snapshot_name = _current_snapshot_name;
3010 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3011 const string backup_filename = history_filename + backup_suffix;
3012 const sys::path xml_path = _session_dir->root_path() / history_filename;
3013 const sys::path backup_path = _session_dir->root_path() / backup_filename;
3015 if (sys::exists (xml_path)) {
3018 sys::rename (xml_path, backup_path);
3020 catch (const sys::filesystem_error& err)
3022 error << _("could not backup old history file, current history not saved") << endmsg;
3023 return -1;
3027 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3028 return 0;
3031 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3033 if (!tree.write (xml_path.to_string()))
3035 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
3039 sys::remove (xml_path);
3040 sys::rename (backup_path, xml_path);
3042 catch (const sys::filesystem_error& err)
3044 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3045 backup_path.to_string(), err.what()) << endmsg;
3048 return -1;
3051 return 0;
3055 Session::restore_history (string snapshot_name)
3057 XMLTree tree;
3059 if (snapshot_name.empty()) {
3060 snapshot_name = _current_snapshot_name;
3063 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3064 const sys::path xml_path = _session_dir->root_path() / xml_filename;
3066 info << "Loading history from " << xml_path.to_string() << endmsg;
3068 if (!sys::exists (xml_path)) {
3069 info << string_compose (_("%1: no history file \"%2\" for this session."),
3070 _name, xml_path.to_string()) << endmsg;
3071 return 1;
3074 if (!tree.read (xml_path.to_string())) {
3075 error << string_compose (_("Could not understand session history file \"%1\""),
3076 xml_path.to_string()) << endmsg;
3077 return -1;
3080 // replace history
3081 _history.clear();
3083 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3085 XMLNode *t = *it;
3086 UndoTransaction* ut = new UndoTransaction ();
3087 struct timeval tv;
3089 ut->set_name(t->property("name")->value());
3090 stringstream ss(t->property("tv-sec")->value());
3091 ss >> tv.tv_sec;
3092 ss.str(t->property("tv-usec")->value());
3093 ss >> tv.tv_usec;
3094 ut->set_timestamp(tv);
3096 for (XMLNodeConstIterator child_it = t->children().begin();
3097 child_it != t->children().end(); child_it++)
3099 XMLNode *n = *child_it;
3100 Command *c;
3102 if (n->name() == "MementoCommand" ||
3103 n->name() == "MementoUndoCommand" ||
3104 n->name() == "MementoRedoCommand") {
3106 if ((c = memento_command_factory(n))) {
3107 ut->add_command(c);
3110 } else if (n->name() == "DiffCommand") {
3111 PBD::ID id(n->property("midi-source")->value());
3112 boost::shared_ptr<MidiSource> midi_source =
3113 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3114 if (midi_source) {
3115 ut->add_command(new MidiModel::DiffCommand(midi_source->model(), *n));
3116 } else {
3117 error << _("Failed to downcast MidiSource for DiffCommand") << endmsg;
3120 } else if (n->name() == "StatefulDiffCommand") {
3121 if ((c = stateful_diff_command_factory (n))) {
3122 ut->add_command (c);
3124 } else {
3125 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3129 _history.add (ut);
3132 return 0;
3135 void
3136 Session::config_changed (std::string p, bool ours)
3138 if (ours) {
3139 set_dirty ();
3142 if (p == "seamless-loop") {
3144 } else if (p == "rf-speed") {
3146 } else if (p == "auto-loop") {
3148 } else if (p == "auto-input") {
3150 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3151 /* auto-input only makes a difference if we're rolling */
3153 boost::shared_ptr<RouteList> rl = routes.reader ();
3154 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
3155 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3156 if (tr && tr->record_enabled ()) {
3157 tr->monitor_input (!config.get_auto_input());
3162 } else if (p == "punch-in") {
3164 Location* location;
3166 if ((location = _locations.auto_punch_location()) != 0) {
3168 if (config.get_punch_in ()) {
3169 replace_event (SessionEvent::PunchIn, location->start());
3170 } else {
3171 remove_event (location->start(), SessionEvent::PunchIn);
3175 } else if (p == "punch-out") {
3177 Location* location;
3179 if ((location = _locations.auto_punch_location()) != 0) {
3181 if (config.get_punch_out()) {
3182 replace_event (SessionEvent::PunchOut, location->end());
3183 } else {
3184 clear_events (SessionEvent::PunchOut);
3188 } else if (p == "edit-mode") {
3190 Glib::Mutex::Lock lm (playlists->lock);
3192 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3193 (*i)->set_edit_mode (Config->get_edit_mode ());
3196 } else if (p == "use-video-sync") {
3198 waiting_for_sync_offset = config.get_use_video_sync();
3200 } else if (p == "mmc-control") {
3202 //poke_midi_thread ();
3204 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3206 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3208 } else if (p == "mmc-send-id") {
3210 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3212 } else if (p == "midi-control") {
3214 //poke_midi_thread ();
3216 } else if (p == "raid-path") {
3218 setup_raid_path (config.get_raid_path());
3220 } else if (p == "timecode-format") {
3222 sync_time_vars ();
3224 } else if (p == "video-pullup") {
3226 sync_time_vars ();
3228 } else if (p == "seamless-loop") {
3230 if (play_loop && transport_rolling()) {
3231 // to reset diskstreams etc
3232 request_play_loop (true);
3235 } else if (p == "rf-speed") {
3237 cumulative_rf_motion = 0;
3238 reset_rf_scale (0);
3240 } else if (p == "click-sound") {
3242 setup_click_sounds (1);
3244 } else if (p == "click-emphasis-sound") {
3246 setup_click_sounds (-1);
3248 } else if (p == "clicking") {
3250 if (Config->get_clicking()) {
3251 if (_click_io && click_data) { // don't require emphasis data
3252 _clicking = true;
3254 } else {
3255 _clicking = false;
3258 } else if (p == "send-mtc") {
3260 session_send_mtc = Config->get_send_mtc();
3261 if (session_send_mtc) {
3262 /* mark us ready to send */
3263 next_quarter_frame_to_send = 0;
3266 } else if (p == "send-mmc") {
3268 _mmc->enable_send (Config->get_send_mmc ());
3270 } else if (p == "midi-feedback") {
3272 session_midi_feedback = Config->get_midi_feedback();
3274 } else if (p == "jack-time-master") {
3276 engine().reset_timebase ();
3278 } else if (p == "native-file-header-format") {
3280 if (!first_file_header_format_reset) {
3281 reset_native_file_format ();
3284 first_file_header_format_reset = false;
3286 } else if (p == "native-file-data-format") {
3288 if (!first_file_data_format_reset) {
3289 reset_native_file_format ();
3292 first_file_data_format_reset = false;
3294 } else if (p == "external-sync") {
3295 if (!config.get_external_sync()) {
3296 drop_sync_source ();
3297 } else {
3298 switch_to_sync_source (config.get_sync_source());
3300 } else if (p == "remote-model") {
3301 set_remote_control_ids ();
3302 } else if (p == "denormal-model") {
3303 setup_fpu ();
3304 } else if (p == "history-depth") {
3305 set_history_depth (Config->get_history_depth());
3306 } else if (p == "sync-all-route-ordering") {
3307 sync_order_keys ("session");
3308 } else if (p == "initial-program-change") {
3310 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3311 MIDI::byte buf[2];
3313 buf[0] = MIDI::program; // channel zero by default
3314 buf[1] = (Config->get_initial_program_change() & 0x7f);
3316 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3318 } else if (p == "solo-mute-override") {
3319 // catch_up_on_solo_mute_override ();
3320 } else if (p == "listen-position") {
3321 listen_position_changed ();
3322 } else if (p == "solo-control-is-listen-control") {
3323 solo_control_mode_changed ();
3327 set_dirty ();
3330 void
3331 Session::set_history_depth (uint32_t d)
3333 _history.set_depth (d);
3337 Session::load_diskstreams_2X (XMLNode const & node, int)
3339 XMLNodeList clist;
3340 XMLNodeConstIterator citer;
3342 clist = node.children();
3344 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3346 try {
3347 /* diskstreams added automatically by DiskstreamCreated handler */
3348 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3349 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3350 _diskstreams_2X.push_back (dsp);
3351 } else {
3352 error << _("Session: unknown diskstream type in XML") << endmsg;
3356 catch (failed_constructor& err) {
3357 error << _("Session: could not load diskstream via XML state") << endmsg;
3358 return -1;
3362 return 0;
3365 /** Create our MachineControl object and connect things to it */
3366 void
3367 Session::setup_midi_machine_control ()
3369 _mmc = new MIDI::MachineControl (_engine.jack());
3371 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3372 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3373 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3374 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3375 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3376 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3377 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3378 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3379 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3380 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3381 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3382 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3383 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3385 /* also handle MIDI SPP because its so common */
3387 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this, _1, _2));
3388 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this, _1, _2));
3389 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this, _1, _2));