replace unicode dash with (monospace) minus.
[ardour.git] / libs / ardour / session_state.cc
1 /*
2   Copyright (C) 1999-2002 Paul Davis
3
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.
8
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.
13
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.
17
18 */
19
20
21 #ifdef WAF_BUILD
22 #include "libardour-config.h"
23 #endif
24
25 #include <stdint.h>
26
27 #include <algorithm>
28 #include <fstream>
29 #include <string>
30 #include <cerrno>
31 #include <cstdio> /* snprintf(3) ... grrr */
32 #include <cmath>
33 #include <unistd.h>
34 #include <sys/stat.h>
35 #include <climits>
36 #include <fcntl.h>
37 #include <poll.h>
38 #include <signal.h>
39 #include <sys/mman.h>
40 #include <sys/time.h>
41
42 #ifdef HAVE_SYS_VFS_H
43 #include <sys/vfs.h>
44 #else
45 #include <sys/param.h>
46 #include <sys/mount.h>
47 #endif
48
49 #ifdef HAVE_SYS_STATVFS_H
50 #include <sys/statvfs.h>
51 #endif
52
53 #include <glib.h>
54 #include <glib/gstdio.h>
55
56 #include <glibmm.h>
57 #include <glibmm/threads.h>
58
59 #include <boost/algorithm/string.hpp>
60
61 #include "midi++/mmc.h"
62 #include "midi++/port.h"
63 #include "midi++/manager.h"
64
65 #include "evoral/SMF.hpp"
66
67 #include "pbd/boost_debug.h"
68 #include "pbd/basename.h"
69 #include "pbd/controllable_descriptor.h"
70 #include "pbd/enumwriter.h"
71 #include "pbd/error.h"
72 #include "pbd/file_utils.h"
73 #include "pbd/pathscanner.h"
74 #include "pbd/pthread_utils.h"
75 #include "pbd/stacktrace.h"
76 #include "pbd/convert.h"
77 #include "pbd/clear_dir.h"
78
79 #include "ardour/amp.h"
80 #include "ardour/audio_diskstream.h"
81 #include "ardour/audio_track.h"
82 #include "ardour/audioengine.h"
83 #include "ardour/audiofilesource.h"
84 #include "ardour/audioregion.h"
85 #include "ardour/automation_control.h"
86 #include "ardour/butler.h"
87 #include "ardour/control_protocol_manager.h"
88 #include "ardour/directory_names.h"
89 #include "ardour/filename_extensions.h"
90 #include "ardour/location.h"
91 #include "ardour/midi_model.h"
92 #include "ardour/midi_patch_manager.h"
93 #include "ardour/midi_region.h"
94 #include "ardour/midi_source.h"
95 #include "ardour/midi_track.h"
96 #include "ardour/pannable.h"
97 #include "ardour/playlist_factory.h"
98 #include "ardour/port.h"
99 #include "ardour/processor.h"
100 #include "ardour/proxy_controllable.h"
101 #include "ardour/recent_sessions.h"
102 #include "ardour/region_factory.h"
103 #include "ardour/route_group.h"
104 #include "ardour/send.h"
105 #include "ardour/session.h"
106 #include "ardour/session_directory.h"
107 #include "ardour/session_metadata.h"
108 #include "ardour/session_playlists.h"
109 #include "ardour/session_state_utils.h"
110 #include "ardour/silentfilesource.h"
111 #include "ardour/sndfilesource.h"
112 #include "ardour/source_factory.h"
113 #include "ardour/speakers.h"
114 #include "ardour/template_utils.h"
115 #include "ardour/tempo.h"
116 #include "ardour/ticker.h"
117 #include "ardour/user_bundle.h"
118
119 #include "control_protocol/control_protocol.h"
120
121 #include "i18n.h"
122 #include <locale.h>
123
124 using namespace std;
125 using namespace ARDOUR;
126 using namespace PBD;
127
128 /** @param snapshot_name Snapshot name, without the .ardour prefix */
129 void
130 Session::first_stage_init (string fullpath, string snapshot_name)
131 {
132         if (fullpath.length() == 0) {
133                 destroy ();
134                 throw failed_constructor();
135         }
136
137         char buf[PATH_MAX+1];
138         if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
139                 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
140                 destroy ();
141                 throw failed_constructor();
142         }
143
144         _path = string(buf);
145
146         if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
147                 _path += G_DIR_SEPARATOR;
148         }
149
150         /* these two are just provisional settings. set_state()
151            will likely override them.
152         */
153
154         _name = _current_snapshot_name = snapshot_name;
155
156         set_history_depth (Config->get_history_depth());
157
158         _current_frame_rate = _engine.frame_rate ();
159         _nominal_frame_rate = _current_frame_rate;
160         _base_frame_rate = _current_frame_rate;
161
162         _tempo_map = new TempoMap (_current_frame_rate);
163         _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
164
165
166         _non_soloed_outs_muted = false;
167         _listen_cnt = 0;
168         _solo_isolated_cnt = 0;
169         g_atomic_int_set (&processing_prohibited, 0);
170         _transport_speed = 0;
171         _default_transport_speed = 1.0;
172         _last_transport_speed = 0;
173         _target_transport_speed = 0;
174         auto_play_legal = false;
175         transport_sub_state = 0;
176         _transport_frame = 0;
177         _requested_return_frame = -1;
178         _session_range_location = 0;
179         g_atomic_int_set (&_record_status, Disabled);
180         loop_changing = false;
181         play_loop = false;
182         have_looped = false;
183         _last_roll_location = 0;
184         _last_roll_or_reversal_location = 0;
185         _last_record_location = 0;
186         pending_locate_frame = 0;
187         pending_locate_roll = false;
188         pending_locate_flush = false;
189         state_was_pending = false;
190         set_next_event ();
191         outbound_mtc_timecode_frame = 0;
192         next_quarter_frame_to_send = -1;
193         current_block_size = 0;
194         solo_update_disabled = false;
195         _have_captured = false;
196         _worst_output_latency = 0;
197         _worst_input_latency = 0;
198         _worst_track_latency = 0;
199         _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
200         _was_seamless = Config->get_seamless_loop ();
201         _slave = 0;
202         _send_qf_mtc = false;
203         _pframes_since_last_mtc = 0;
204         g_atomic_int_set (&_playback_load, 100);
205         g_atomic_int_set (&_capture_load, 100);
206         _play_range = false;
207         _exporting = false;
208         pending_abort = false;
209         _adding_routes_in_progress = false;
210         destructive_index = 0;
211         first_file_data_format_reset = true;
212         first_file_header_format_reset = true;
213         post_export_sync = false;
214         midi_control_ui = 0;
215         _step_editors = 0;
216         no_questions_about_missing_files = false;
217         _speakers.reset (new Speakers);
218         _clicks_cleared = 0;
219         ignore_route_processor_changes = false;
220         _pre_export_mmc_enabled = false;
221
222         AudioDiskstream::allocate_working_buffers();
223
224         /* default short fade = 15ms */
225
226         SndFileSource::setup_standard_crossfades (*this, frame_rate());
227
228         last_mmc_step.tv_sec = 0;
229         last_mmc_step.tv_usec = 0;
230         step_speed = 0.0;
231
232         /* click sounds are unset by default, which causes us to internal
233            waveforms for clicks.
234         */
235
236         click_length = 0;
237         click_emphasis_length = 0;
238         _clicking = false;
239
240         process_function = &Session::process_with_events;
241
242         if (config.get_use_video_sync()) {
243                 waiting_for_sync_offset = true;
244         } else {
245                 waiting_for_sync_offset = false;
246         }
247
248         last_timecode_when = 0;
249         last_timecode_valid = false;
250
251         sync_time_vars ();
252
253         last_rr_session_dir = session_dirs.begin();
254         refresh_disk_space ();
255
256         /* default: assume simple stereo speaker configuration */
257
258         _speakers->setup_default_speakers (2);
259
260         /* slave stuff */
261
262         average_slave_delta = 1800; // !!! why 1800 ????
263         have_first_delta_accumulator = false;
264         delta_accumulator_cnt = 0;
265         _slave_state = Stopped;
266
267         _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
268                                                         boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
269                                                         boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
270         add_controllable (_solo_cut_control);
271
272         _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
273
274         /* These are all static "per-class" signals */
275
276         SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
277         PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
278         AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
279         Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
280         IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
281
282         /* stop IO objects from doing stuff until we're ready for them */
283
284         Delivery::disable_panners ();
285         IO::disable_connecting ();
286 }
287
288 int
289 Session::second_stage_init ()
290 {
291         AudioFileSource::set_peak_dir (_session_dir->peak_path());
292
293         if (!_is_new) {
294                 if (load_state (_current_snapshot_name)) {
295                         return -1;
296                 }
297         }
298
299         if (_butler->start_thread()) {
300                 return -1;
301         }
302
303         if (start_midi_thread ()) {
304                 return -1;
305         }
306
307         setup_midi_machine_control ();
308
309         // set_state() will call setup_raid_path(), but if it's a new session we need
310         // to call setup_raid_path() here.
311
312         if (state_tree) {
313                 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
314                         return -1;
315                 }
316         } else {
317                 setup_raid_path(_path);
318         }
319
320         /* we can't save till after ::when_engine_running() is called,
321            because otherwise we save state with no connections made.
322            therefore, we reset _state_of_the_state because ::set_state()
323            will have cleared it.
324
325            we also have to include Loading so that any events that get
326            generated between here and the end of ::when_engine_running()
327            will be processed directly rather than queued.
328         */
329
330         _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
331
332         _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
333         _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
334         setup_click_sounds (0);
335         setup_midi_control ();
336
337         /* Pay attention ... */
338
339         _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
340         _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
341
342         midi_clock = new MidiClockTicker ();
343         midi_clock->set_session (this);
344
345         try {
346                 when_engine_running ();
347         }
348
349         /* handle this one in a different way than all others, so that its clear what happened */
350
351         catch (AudioEngine::PortRegistrationFailure& err) {
352                 error << err.what() << endmsg;
353                 return -1;
354         }
355
356         catch (...) {
357                 return -1;
358         }
359
360         BootMessage (_("Reset Remote Controls"));
361
362         send_full_time_code (0);
363         _engine.transport_locate (0);
364
365         MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
366         MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
367
368         MIDI::Name::MidiPatchManager::instance().set_session (this);
369
370         ltc_tx_initialize();
371         /* initial program change will be delivered later; see ::config_changed() */
372
373         _state_of_the_state = Clean;
374
375         Port::set_connecting_blocked (false);
376
377         DirtyChanged (); /* EMIT SIGNAL */
378
379         if (state_was_pending) {
380                 save_state (_current_snapshot_name);
381                 remove_pending_capture_state ();
382                 state_was_pending = false;
383         }
384
385         BootMessage (_("Session loading complete"));
386
387         return 0;
388 }
389
390 string
391 Session::raid_path () const
392 {
393         SearchPath raid_search_path;
394
395         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
396                 raid_search_path += (*i).path;
397         }
398
399         return raid_search_path.to_string ();
400 }
401
402 void
403 Session::setup_raid_path (string path)
404 {
405         if (path.empty()) {
406                 return;
407         }
408
409         space_and_path sp;
410         string fspath;
411
412         session_dirs.clear ();
413
414         SearchPath search_path(path);
415         SearchPath sound_search_path;
416         SearchPath midi_search_path;
417
418         for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
419                 sp.path = *i;
420                 sp.blocks = 0; // not needed
421                 session_dirs.push_back (sp);
422
423                 SessionDirectory sdir(sp.path);
424
425                 sound_search_path += sdir.sound_path ();
426                 midi_search_path += sdir.midi_path ();
427         }
428
429         // reset the round-robin soundfile path thingie
430         last_rr_session_dir = session_dirs.begin();
431 }
432
433 bool
434 Session::path_is_within_session (const std::string& path)
435 {
436         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
437                 if (PBD::path_is_within (i->path, path)) {
438                         return true;
439                 }
440         }
441         return false;
442 }
443
444 int
445 Session::ensure_subdirs ()
446 {
447         string dir;
448
449         dir = session_directory().peak_path();
450
451         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
452                 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
453                 return -1;
454         }
455
456         dir = session_directory().sound_path();
457
458         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
459                 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
460                 return -1;
461         }
462
463         dir = session_directory().midi_path();
464
465         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
466                 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
467                 return -1;
468         }
469
470         dir = session_directory().dead_path();
471
472         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
473                 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
474                 return -1;
475         }
476
477         dir = session_directory().export_path();
478
479         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
480                 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
481                 return -1;
482         }
483
484         dir = analysis_dir ();
485
486         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
487                 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
488                 return -1;
489         }
490
491         dir = plugins_dir ();
492
493         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
494                 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
495                 return -1;
496         }
497
498         dir = externals_dir ();
499
500         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
501                 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
502                 return -1;
503         }
504
505         return 0;
506 }
507
508 /** @param session_template directory containing session template, or empty.
509  *  Caller must not hold process lock.
510  */
511 int
512 Session::create (const string& session_template, BusProfile* bus_profile)
513 {
514         if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
515                 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
516                 return -1;
517         }
518
519         if (ensure_subdirs ()) {
520                 return -1;
521         }
522
523         _writable = exists_and_writable (_path);
524
525         if (!session_template.empty()) {
526                 std::string in_path = session_template_dir_to_file (session_template);
527
528                 ifstream in(in_path.c_str());
529
530                 if (in) {
531                         string out_path = _path;
532                         out_path += _name;
533                         out_path += statefile_suffix;
534
535                         ofstream out(out_path.c_str());
536
537                         if (out) {
538                                 out << in.rdbuf();
539                                 _is_new = false;
540
541                                 /* Copy plugin state files from template to new session */
542                                 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
543                                 copy_files (template_plugins, plugins_dir ());
544                                 
545                                 return 0;
546
547                         } else {
548                                 error << string_compose (_("Could not open %1 for writing session template"), out_path)
549                                         << endmsg;
550                                 return -1;
551                         }
552
553                 } else {
554                         error << string_compose (_("Could not open session template %1 for reading"), in_path)
555                                 << endmsg;
556                         return -1;
557                 }
558
559         }
560
561         /* set initial start + end point */
562
563         _state_of_the_state = Clean;
564
565         /* set up Master Out and Control Out if necessary */
566
567         if (bus_profile) {
568
569                 RouteList rl;
570                 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
571
572                 if (bus_profile->master_out_channels) {
573                         boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
574                         if (r->init ()) {
575                                 return -1;
576                         }
577 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
578                         // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
579 #endif
580                         {
581                                 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
582                                 r->input()->ensure_io (count, false, this);
583                                 r->output()->ensure_io (count, false, this);
584                         }
585
586                         rl.push_back (r);
587
588                 } else {
589                         /* prohibit auto-connect to master, because there isn't one */
590                         bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
591                 }
592
593                 if (!rl.empty()) {
594                         add_routes (rl, false, false, false);
595                 }
596
597                 /* this allows the user to override settings with an environment variable.
598                  */
599
600                 if (no_auto_connect()) {
601                         bus_profile->input_ac = AutoConnectOption (0);
602                         bus_profile->output_ac = AutoConnectOption (0);
603                 }
604
605                 Config->set_input_auto_connect (bus_profile->input_ac);
606                 Config->set_output_auto_connect (bus_profile->output_ac);
607         }
608
609         if (Config->get_use_monitor_bus() && bus_profile) {
610                 add_monitor_section ();
611         }
612
613         save_state ("");
614
615         return 0;
616 }
617
618 void
619 Session::maybe_write_autosave()
620 {
621         if (dirty() && record_status() != Recording) {
622                 save_state("", true);
623         }
624 }
625
626 void
627 Session::remove_pending_capture_state ()
628 {
629         std::string pending_state_file_path(_session_dir->root_path());
630
631         pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
632
633         if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
634
635         if (g_remove (pending_state_file_path.c_str()) != 0) {
636                 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
637                                 pending_state_file_path, g_strerror (errno)) << endmsg;
638         }
639 }
640
641 /** Rename a state file.
642  *  @param old_name Old snapshot name.
643  *  @param new_name New snapshot name.
644  */
645 void
646 Session::rename_state (string old_name, string new_name)
647 {
648         if (old_name == _current_snapshot_name || old_name == _name) {
649                 /* refuse to rename the current snapshot or the "main" one */
650                 return;
651         }
652
653         const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
654         const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
655
656         const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
657         const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
658
659         if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
660                 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
661                                 old_name, new_name, g_strerror(errno)) << endmsg;
662         }
663 }
664
665 /** Remove a state file.
666  *  @param snapshot_name Snapshot name.
667  */
668 void
669 Session::remove_state (string snapshot_name)
670 {
671         if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
672                 // refuse to remove the current snapshot or the "main" one
673                 return;
674         }
675
676         std::string xml_path(_session_dir->root_path());
677
678         xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
679
680         if (!create_backup_file (xml_path)) {
681                 // don't remove it if a backup can't be made
682                 // create_backup_file will log the error.
683                 return;
684         }
685
686         // and delete it
687         if (g_remove (xml_path.c_str()) != 0) {
688                 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
689                                 xml_path, g_strerror (errno)) << endmsg;
690         }
691 }
692
693 #ifdef HAVE_JACK_SESSION
694 void
695 Session::jack_session_event (jack_session_event_t * event)
696 {
697         char timebuf[128];
698         time_t n;
699         struct tm local_time;
700
701         time (&n);
702         localtime_r (&n, &local_time);
703         strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
704
705         if (event->type == JackSessionSaveTemplate)
706         {
707                 if (save_template( timebuf )) {
708                         event->flags = JackSessionSaveError;
709                 } else {
710                         string cmd ("ardour3 -P -U ");
711                         cmd += event->client_uuid;
712                         cmd += " -T ";
713                         cmd += timebuf;
714
715                         event->command_line = strdup (cmd.c_str());
716                 }
717         }
718         else
719         {
720                 if (save_state (timebuf)) {
721                         event->flags = JackSessionSaveError;
722                 } else {
723                         std::string xml_path (_session_dir->root_path());
724                         std::string legalized_filename = legalize_for_path (timebuf) + statefile_suffix;
725                         xml_path = Glib::build_filename (xml_path, legalized_filename);
726
727                         string cmd ("ardour3 -P -U ");
728                         cmd += event->client_uuid;
729                         cmd += " \"";
730                         cmd += xml_path;
731                         cmd += '\"';
732
733                         event->command_line = strdup (cmd.c_str());
734                 }
735         }
736
737         jack_session_reply (_engine.jack(), event);
738
739         if (event->type == JackSessionSaveAndQuit) {
740                 Quit (); /* EMIT SIGNAL */
741         }
742
743         jack_session_event_free( event );
744 }
745 #endif
746
747 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
748 int
749 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
750 {
751         XMLTree tree;
752         std::string xml_path(_session_dir->root_path());
753
754         if (!_writable || (_state_of_the_state & CannotSave)) {
755                 return 1;
756         }
757
758         if (!_engine.connected ()) {
759                 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
760                                          PROGRAM_NAME)
761                       << endmsg;
762                 return 1;
763         }
764
765         /* tell sources we're saving first, in case they write out to a new file
766          * which should be saved with the state rather than the old one */
767         for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
768                 try {
769                         i->second->session_saved();
770                 } catch (Evoral::SMF::FileError& e) {
771                         error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
772                 }
773         }
774
775         tree.set_root (&get_state());
776
777         if (snapshot_name.empty()) {
778                 snapshot_name = _current_snapshot_name;
779         } else if (switch_to_snapshot) {
780                 _current_snapshot_name = snapshot_name;
781         }
782
783         if (!pending) {
784
785                 /* proper save: use statefile_suffix (.ardour in English) */
786
787                 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
788
789                 /* make a backup copy of the old file */
790
791                 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
792                         // create_backup_file will log the error
793                         return -1;
794                 }
795
796         } else {
797
798                 /* pending save: use pending_suffix (.pending in English) */
799                 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
800         }
801
802         std::string tmp_path(_session_dir->root_path());
803         tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
804
805         // cerr << "actually writing state to " << xml_path << endl;
806
807         if (!tree.write (tmp_path)) {
808                 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
809                 if (g_remove (tmp_path.c_str()) != 0) {
810                         error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
811                                         tmp_path, g_strerror (errno)) << endmsg;
812                 }
813                 return -1;
814
815         } else {
816
817                 if (::rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
818                         error << string_compose (_("could not rename temporary session file %1 to %2"),
819                                         tmp_path, xml_path) << endmsg;
820                         if (g_remove (tmp_path.c_str()) != 0) {
821                                 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
822                                                 tmp_path, g_strerror (errno)) << endmsg;
823                         }
824                         return -1;
825                 }
826         }
827
828         if (!pending) {
829
830                 save_history (snapshot_name);
831
832                 bool was_dirty = dirty();
833
834                 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
835
836                 if (was_dirty) {
837                         DirtyChanged (); /* EMIT SIGNAL */
838                 }
839
840                 StateSaved (snapshot_name); /* EMIT SIGNAL */
841         }
842
843         return 0;
844 }
845
846 int
847 Session::restore_state (string snapshot_name)
848 {
849         if (load_state (snapshot_name) == 0) {
850                 set_state (*state_tree->root(), Stateful::loading_state_version);
851         }
852
853         return 0;
854 }
855
856 int
857 Session::load_state (string snapshot_name)
858 {
859         delete state_tree;
860         state_tree = 0;
861
862         state_was_pending = false;
863
864         /* check for leftover pending state from a crashed capture attempt */
865
866         std::string xmlpath(_session_dir->root_path());
867         xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
868
869         if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
870
871                 /* there is pending state from a crashed capture attempt */
872
873                 boost::optional<int> r = AskAboutPendingState();
874                 if (r.get_value_or (1)) {
875                         state_was_pending = true;
876                 }
877         }
878
879         if (!state_was_pending) {
880                 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
881         }
882
883         if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
884                 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
885                 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
886                         error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
887                         return 1;
888                 }
889         }
890
891         state_tree = new XMLTree;
892
893         set_dirty();
894
895         _writable = exists_and_writable (xmlpath);
896
897         if (!state_tree->read (xmlpath)) {
898                 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
899                 delete state_tree;
900                 state_tree = 0;
901                 return -1;
902         }
903
904         XMLNode& root (*state_tree->root());
905
906         if (root.name() != X_("Session")) {
907                 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
908                 delete state_tree;
909                 state_tree = 0;
910                 return -1;
911         }
912
913         const XMLProperty* prop;
914
915         if ((prop = root.property ("version")) == 0) {
916                 /* no version implies very old version of Ardour */
917                 Stateful::loading_state_version = 1000;
918         } else {
919                 if (prop->value().find ('.') != string::npos) {
920                         /* old school version format */
921                         if (prop->value()[0] == '2') {
922                                 Stateful::loading_state_version = 2000;
923                         } else {
924                                 Stateful::loading_state_version = 3000;
925                         }
926                 } else {
927                         Stateful::loading_state_version = atoi (prop->value());
928                 }
929         }
930
931         if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
932
933                 std::string backup_path(_session_dir->root_path());
934                 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
935                 backup_path = Glib::build_filename (backup_path, backup_filename);
936
937                 // only create a backup for a given statefile version once
938
939                 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
940                         
941                         info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
942                                                 xmlpath, backup_path, PROGRAM_NAME)
943                              << endmsg;
944                         
945                         if (!copy_file (xmlpath, backup_path)) {;
946                                 return -1;
947                         }
948                 }
949         }
950
951         return 0;
952 }
953
954 int
955 Session::load_options (const XMLNode& node)
956 {
957         LocaleGuard lg (X_("POSIX"));
958         config.set_variables (node);
959         return 0;
960 }
961
962 XMLNode&
963 Session::get_state()
964 {
965         return state(true);
966 }
967
968 XMLNode&
969 Session::get_template()
970 {
971         /* if we don't disable rec-enable, diskstreams
972            will believe they need to store their capture
973            sources in their state node.
974         */
975
976         disable_record (false);
977
978         return state(false);
979 }
980
981 XMLNode&
982 Session::state (bool full_state)
983 {
984         XMLNode* node = new XMLNode("Session");
985         XMLNode* child;
986
987         char buf[16];
988         snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
989         node->add_property("version", buf);
990
991         /* store configuration settings */
992
993         if (full_state) {
994
995                 node->add_property ("name", _name);
996                 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
997                 node->add_property ("sample-rate", buf);
998
999                 if (session_dirs.size() > 1) {
1000
1001                         string p;
1002
1003                         vector<space_and_path>::iterator i = session_dirs.begin();
1004                         vector<space_and_path>::iterator next;
1005
1006                         ++i; /* skip the first one */
1007                         next = i;
1008                         ++next;
1009
1010                         while (i != session_dirs.end()) {
1011
1012                                 p += (*i).path;
1013
1014                                 if (next != session_dirs.end()) {
1015                                         p += ':';
1016                                 } else {
1017                                         break;
1018                                 }
1019
1020                                 ++next;
1021                                 ++i;
1022                         }
1023
1024                         child = node->add_child ("Path");
1025                         child->add_content (p);
1026                 }
1027         }
1028
1029         /* save the ID counter */
1030
1031         snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1032         node->add_property ("id-counter", buf);
1033
1034         /* save the event ID counter */
1035
1036         snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1037         node->add_property ("event-counter", buf);
1038
1039         /* various options */
1040
1041         node->add_child_nocopy (config.get_variables ());
1042
1043         node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1044
1045         child = node->add_child ("Sources");
1046
1047         if (full_state) {
1048                 Glib::Threads::Mutex::Lock sl (source_lock);
1049
1050                 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1051
1052                         /* Don't save information about non-file Sources, or
1053                          * about non-destructive file sources that are empty
1054                          * and unused by any regions.
1055                         */
1056
1057                         boost::shared_ptr<FileSource> fs;
1058
1059                         if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1060
1061                                 if (!fs->destructive()) {
1062                                         if (fs->empty() && !fs->used()) {
1063                                                 continue;
1064                                         }
1065                                 }
1066
1067                                 child->add_child_nocopy (siter->second->get_state());
1068                         }
1069                 }
1070         }
1071
1072         child = node->add_child ("Regions");
1073
1074         if (full_state) {
1075                 Glib::Threads::Mutex::Lock rl (region_lock);
1076                 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1077                 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1078                         boost::shared_ptr<Region> r = i->second;
1079                         /* only store regions not attached to playlists */
1080                         if (r->playlist() == 0) {
1081                                 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1082                                         child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1083                                 } else {
1084                                         child->add_child_nocopy (r->get_state ());
1085                                 }
1086                         }
1087                 }
1088
1089                 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1090
1091                 if (!cassocs.empty()) {
1092                         XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1093
1094                         for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1095                                 char buf[64];
1096                                 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1097                                 i->first->id().print (buf, sizeof (buf));
1098                                 can->add_property (X_("copy"), buf);
1099                                 i->second->id().print (buf, sizeof (buf));
1100                                 can->add_property (X_("original"), buf);
1101                                 ca->add_child_nocopy (*can);
1102                         }
1103                 }
1104         }
1105
1106         if (full_state) {
1107                 node->add_child_nocopy (_locations->get_state());
1108         } else {
1109                 // for a template, just create a new Locations, populate it
1110                 // with the default start and end, and get the state for that.
1111                 Locations loc (*this);
1112                 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1113                 range->set (max_framepos, 0);
1114                 loc.add (range);
1115                 node->add_child_nocopy (loc.get_state());
1116         }
1117
1118         child = node->add_child ("Bundles");
1119         {
1120                 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1121                 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1122                         boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1123                         if (b) {
1124                                 child->add_child_nocopy (b->get_state());
1125                         }
1126                 }
1127         }
1128
1129         child = node->add_child ("Routes");
1130         {
1131                 boost::shared_ptr<RouteList> r = routes.reader ();
1132
1133                 RoutePublicOrderSorter cmp;
1134                 RouteList public_order (*r);
1135                 public_order.sort (cmp);
1136
1137                 /* the sort should have put control outs first */
1138
1139                 if (_monitor_out) {
1140                         assert (_monitor_out == public_order.front());
1141                 }
1142
1143                 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1144                         if (!(*i)->is_hidden()) {
1145                                 if (full_state) {
1146                                         child->add_child_nocopy ((*i)->get_state());
1147                                 } else {
1148                                         child->add_child_nocopy ((*i)->get_template());
1149                                 }
1150                         }
1151                 }
1152         }
1153
1154         playlists->add_state (node, full_state);
1155
1156         child = node->add_child ("RouteGroups");
1157         for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1158                 child->add_child_nocopy ((*i)->get_state());
1159         }
1160
1161         if (_click_io) {
1162                 XMLNode* gain_child = node->add_child ("Click");
1163                 gain_child->add_child_nocopy (_click_io->state (full_state));
1164                 gain_child->add_child_nocopy (_click_gain->state (full_state));
1165         }
1166
1167         if (_ltc_input) {
1168                 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1169                 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1170         }
1171
1172         if (_ltc_input) {
1173                 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1174                 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1175         }
1176
1177         node->add_child_nocopy (_speakers->get_state());
1178         node->add_child_nocopy (_tempo_map->get_state());
1179         node->add_child_nocopy (get_control_protocol_state());
1180
1181         if (_extra_xml) {
1182                 node->add_child_copy (*_extra_xml);
1183         }
1184
1185         return *node;
1186 }
1187
1188 XMLNode&
1189 Session::get_control_protocol_state ()
1190 {
1191         ControlProtocolManager& cpm (ControlProtocolManager::instance());
1192         return cpm.get_state();
1193 }
1194
1195 int
1196 Session::set_state (const XMLNode& node, int version)
1197 {
1198         XMLNodeList nlist;
1199         XMLNode* child;
1200         const XMLProperty* prop;
1201         int ret = -1;
1202
1203         _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1204
1205         if (node.name() != X_("Session")) {
1206                 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1207                 return -1;
1208         }
1209
1210         if ((prop = node.property ("name")) != 0) {
1211                 _name = prop->value ();
1212         }
1213
1214         if ((prop = node.property (X_("sample-rate"))) != 0) {
1215
1216                 _nominal_frame_rate = atoi (prop->value());
1217
1218                 if (_nominal_frame_rate != _current_frame_rate) {
1219                         boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1220                         if (r.get_value_or (0)) {
1221                                 return -1;
1222                         }
1223                 }
1224         }
1225
1226         setup_raid_path(_session_dir->root_path());
1227
1228         if ((prop = node.property (X_("id-counter"))) != 0) {
1229                 uint64_t x;
1230                 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1231                 ID::init_counter (x);
1232         } else {
1233                 /* old sessions used a timebased counter, so fake
1234                    the startup ID counter based on a standard
1235                    timestamp.
1236                 */
1237                 time_t now;
1238                 time (&now);
1239                 ID::init_counter (now);
1240         }
1241
1242         if ((prop = node.property (X_("event-counter"))) != 0) {
1243                 Evoral::init_event_id_counter (atoi (prop->value()));
1244         }
1245
1246         IO::disable_connecting ();
1247
1248         Stateful::save_extra_xml (node);
1249
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;
1256         }
1257
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 ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1262                         goto out;
1263                 }
1264         }
1265
1266         if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1267                 _speakers->set_state (*child, version);
1268         }
1269
1270         if ((child = find_named_node (node, "Sources")) == 0) {
1271                 error << _("Session: XML state has no sources section") << endmsg;
1272                 goto out;
1273         } else if (load_sources (*child)) {
1274                 goto out;
1275         }
1276
1277         if ((child = find_named_node (node, "TempoMap")) == 0) {
1278                 error << _("Session: XML state has no Tempo Map section") << endmsg;
1279                 goto out;
1280         } else if (_tempo_map->set_state (*child, version)) {
1281                 goto out;
1282         }
1283
1284         if ((child = find_named_node (node, "Locations")) == 0) {
1285                 error << _("Session: XML state has no locations section") << endmsg;
1286                 goto out;
1287         } else if (_locations->set_state (*child, version)) {
1288                 goto out;
1289         }
1290
1291         Location* location;
1292
1293         if ((location = _locations->auto_loop_location()) != 0) {
1294                 set_auto_loop_location (location);
1295         }
1296
1297         if ((location = _locations->auto_punch_location()) != 0) {
1298                 set_auto_punch_location (location);
1299         }
1300
1301         if ((location = _locations->session_range_location()) != 0) {
1302                 delete _session_range_location;
1303                 _session_range_location = location;
1304         }
1305
1306         if (_session_range_location) {
1307                 AudioFileSource::set_header_position_offset (_session_range_location->start());
1308         }
1309
1310         if ((child = find_named_node (node, "Regions")) == 0) {
1311                 error << _("Session: XML state has no Regions section") << endmsg;
1312                 goto out;
1313         } else if (load_regions (*child)) {
1314                 goto out;
1315         }
1316
1317         if ((child = find_named_node (node, "Playlists")) == 0) {
1318                 error << _("Session: XML state has no playlists section") << endmsg;
1319                 goto out;
1320         } else if (playlists->load (*this, *child)) {
1321                 goto out;
1322         }
1323
1324         if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1325                 // this is OK
1326         } else if (playlists->load_unused (*this, *child)) {
1327                 goto out;
1328         }
1329
1330         if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1331                 if (load_compounds (*child)) {
1332                         goto out;
1333                 }
1334         }
1335
1336         if (version >= 3000) {
1337                 if ((child = find_named_node (node, "Bundles")) == 0) {
1338                         warning << _("Session: XML state has no bundles section") << endmsg;
1339                         //goto out;
1340                 } else {
1341                         /* We can't load Bundles yet as they need to be able
1342                            to convert from port names to Port objects, which can't happen until
1343                            later */
1344                         _bundle_xml_node = new XMLNode (*child);
1345                 }
1346         }
1347
1348         if (version < 3000) {
1349                 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1350                         error << _("Session: XML state has no diskstreams section") << endmsg;
1351                         goto out;
1352                 } else if (load_diskstreams_2X (*child, version)) {
1353                         goto out;
1354                 }
1355         }
1356
1357         if ((child = find_named_node (node, "Routes")) == 0) {
1358                 error << _("Session: XML state has no routes section") << endmsg;
1359                 goto out;
1360         } else if (load_routes (*child, version)) {
1361                 goto out;
1362         }
1363
1364         /* our diskstreams list is no longer needed as they are now all owned by their Route */
1365         _diskstreams_2X.clear ();
1366
1367         if (version >= 3000) {
1368
1369                 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1370                         error << _("Session: XML state has no route groups section") << endmsg;
1371                         goto out;
1372                 } else if (load_route_groups (*child, version)) {
1373                         goto out;
1374                 }
1375
1376         } else if (version < 3000) {
1377
1378                 if ((child = find_named_node (node, "EditGroups")) == 0) {
1379                         error << _("Session: XML state has no edit groups section") << endmsg;
1380                         goto out;
1381                 } else if (load_route_groups (*child, version)) {
1382                         goto out;
1383                 }
1384
1385                 if ((child = find_named_node (node, "MixGroups")) == 0) {
1386                         error << _("Session: XML state has no mix groups section") << endmsg;
1387                         goto out;
1388                 } else if (load_route_groups (*child, version)) {
1389                         goto out;
1390                 }
1391         }
1392
1393         if ((child = find_named_node (node, "Click")) == 0) {
1394                 warning << _("Session: XML state has no click section") << endmsg;
1395         } else if (_click_io) {
1396                 const XMLNodeList& children (child->children());
1397                 XMLNodeList::const_iterator i = children.begin();
1398                 _click_io->set_state (**i, version);
1399                 ++i;
1400                 if (i != children.end()) {
1401                         _click_gain->set_state (**i, version);
1402                 }
1403         }
1404
1405         if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1406                 ControlProtocolManager::instance().set_state (*child, version);
1407         }
1408
1409         update_have_rec_enabled_track ();
1410
1411         /* here beginneth the second phase ... */
1412
1413         StateReady (); /* EMIT SIGNAL */
1414
1415         return 0;
1416
1417   out:
1418         return ret;
1419 }
1420
1421 int
1422 Session::load_routes (const XMLNode& node, int version)
1423 {
1424         XMLNodeList nlist;
1425         XMLNodeConstIterator niter;
1426         RouteList new_routes;
1427
1428         nlist = node.children();
1429
1430         set_dirty();
1431
1432         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1433
1434                 boost::shared_ptr<Route> route;
1435                 if (version < 3000) {
1436                         route = XMLRouteFactory_2X (**niter, version);
1437                 } else {
1438                         route = XMLRouteFactory (**niter, version);
1439                 }
1440
1441                 if (route == 0) {
1442                         error << _("Session: cannot create Route from XML description.") << endmsg;
1443                         return -1;
1444                 }
1445
1446                 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1447
1448                 new_routes.push_back (route);
1449         }
1450
1451         add_routes (new_routes, false, false, false);
1452
1453         return 0;
1454 }
1455
1456 boost::shared_ptr<Route>
1457 Session::XMLRouteFactory (const XMLNode& node, int version)
1458 {
1459         boost::shared_ptr<Route> ret;
1460
1461         if (node.name() != "Route") {
1462                 return ret;
1463         }
1464
1465         XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1466
1467         DataType type = DataType::AUDIO;
1468         const XMLProperty* prop = node.property("default-type");
1469
1470         if (prop) {
1471                 type = DataType (prop->value());
1472         }
1473
1474         assert (type != DataType::NIL);
1475
1476         if (ds_child) {
1477
1478                 boost::shared_ptr<Track> track;
1479
1480                 if (type == DataType::AUDIO) {
1481                         track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1482                 } else {
1483                         track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1484                 }
1485
1486                 if (track->init()) {
1487                         return ret;
1488                 }
1489
1490                 if (track->set_state (node, version)) {
1491                         return ret;
1492                 }
1493
1494 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1495                 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1496 #endif
1497                 ret = track;
1498
1499         } else {
1500                 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1501
1502                 if (r->init () == 0 && r->set_state (node, version) == 0) {
1503 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1504                         // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1505 #endif
1506                         ret = r;
1507                 }
1508         }
1509
1510         return ret;
1511 }
1512
1513 boost::shared_ptr<Route>
1514 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1515 {
1516         boost::shared_ptr<Route> ret;
1517
1518         if (node.name() != "Route") {
1519                 return ret;
1520         }
1521
1522         XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1523         if (!ds_prop) {
1524                 ds_prop = node.property (X_("diskstream"));
1525         }
1526
1527         DataType type = DataType::AUDIO;
1528         const XMLProperty* prop = node.property("default-type");
1529
1530         if (prop) {
1531                 type = DataType (prop->value());
1532         }
1533
1534         assert (type != DataType::NIL);
1535
1536         if (ds_prop) {
1537
1538                 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1539                 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1540                         ++i;
1541                 }
1542
1543                 if (i == _diskstreams_2X.end()) {
1544                         error << _("Could not find diskstream for route") << endmsg;
1545                         return boost::shared_ptr<Route> ();
1546                 }
1547
1548                 boost::shared_ptr<Track> track;
1549
1550                 if (type == DataType::AUDIO) {
1551                         track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1552                 } else {
1553                         track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1554                 }
1555
1556                 if (track->init()) {
1557                         return ret;
1558                 }
1559
1560                 if (track->set_state (node, version)) {
1561                         return ret;
1562                 }
1563
1564                 track->set_diskstream (*i);
1565
1566 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1567                 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1568 #endif
1569                 ret = track;
1570
1571         } else {
1572                 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1573
1574                 if (r->init () == 0 && r->set_state (node, version) == 0) {
1575 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1576                         // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1577 #endif
1578                         ret = r;
1579                 }
1580         }
1581
1582         return ret;
1583 }
1584
1585 int
1586 Session::load_regions (const XMLNode& node)
1587 {
1588         XMLNodeList nlist;
1589         XMLNodeConstIterator niter;
1590         boost::shared_ptr<Region> region;
1591
1592         nlist = node.children();
1593
1594         set_dirty();
1595
1596         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1597                 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1598                         error << _("Session: cannot create Region from XML description.");
1599                         const XMLProperty *name = (**niter).property("name");
1600
1601                         if (name) {
1602                                 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1603                         }
1604
1605                         error << endmsg;
1606                 }
1607         }
1608
1609         return 0;
1610 }
1611
1612 int
1613 Session::load_compounds (const XMLNode& node)
1614 {
1615         XMLNodeList calist = node.children();
1616         XMLNodeConstIterator caiter;
1617         XMLProperty *caprop;
1618
1619         for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1620                 XMLNode* ca = *caiter;
1621                 ID orig_id;
1622                 ID copy_id;
1623
1624                 if ((caprop = ca->property (X_("original"))) == 0) {
1625                         continue;
1626                 }
1627                 orig_id = caprop->value();
1628
1629                 if ((caprop = ca->property (X_("copy"))) == 0) {
1630                         continue;
1631                 }
1632                 copy_id = caprop->value();
1633
1634                 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1635                 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1636
1637                 if (!orig || !copy) {
1638                         warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1639                                                    orig_id, copy_id)
1640                                 << endmsg;
1641                         continue;
1642                 }
1643
1644                 RegionFactory::add_compound_association (orig, copy);
1645         }
1646
1647         return 0;
1648 }
1649
1650 void
1651 Session::load_nested_sources (const XMLNode& node)
1652 {
1653         XMLNodeList nlist;
1654         XMLNodeConstIterator niter;
1655
1656         nlist = node.children();
1657
1658         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1659                 if ((*niter)->name() == "Source") {
1660
1661                         /* it may already exist, so don't recreate it unnecessarily 
1662                          */
1663
1664                         XMLProperty* prop = (*niter)->property (X_("id"));
1665                         if (!prop) {
1666                                 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1667                                 continue;
1668                         }
1669
1670                         ID source_id (prop->value());
1671
1672                         if (!source_by_id (source_id)) {
1673
1674                                 try {
1675                                         SourceFactory::create (*this, **niter, true);
1676                                 }
1677                                 catch (failed_constructor& err) {
1678                                         error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1679                                 }
1680                         }
1681                 }
1682         }
1683 }
1684
1685 boost::shared_ptr<Region>
1686 Session::XMLRegionFactory (const XMLNode& node, bool full)
1687 {
1688         const XMLProperty* type = node.property("type");
1689
1690         try {
1691
1692                 const XMLNodeList& nlist = node.children();
1693
1694                 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1695                         XMLNode *child = (*niter);
1696                         if (child->name() == "NestedSource") {
1697                                 load_nested_sources (*child);
1698                         }
1699                 }
1700
1701                 if (!type || type->value() == "audio") {
1702                         return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1703                 } else if (type->value() == "midi") {
1704                         return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1705                 }
1706
1707         } catch (failed_constructor& err) {
1708                 return boost::shared_ptr<Region> ();
1709         }
1710
1711         return boost::shared_ptr<Region> ();
1712 }
1713
1714 boost::shared_ptr<AudioRegion>
1715 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1716 {
1717         const XMLProperty* prop;
1718         boost::shared_ptr<Source> source;
1719         boost::shared_ptr<AudioSource> as;
1720         SourceList sources;
1721         SourceList master_sources;
1722         uint32_t nchans = 1;
1723         char buf[128];
1724
1725         if (node.name() != X_("Region")) {
1726                 return boost::shared_ptr<AudioRegion>();
1727         }
1728
1729         if ((prop = node.property (X_("channels"))) != 0) {
1730                 nchans = atoi (prop->value().c_str());
1731         }
1732
1733         if ((prop = node.property ("name")) == 0) {
1734                 cerr << "no name for this region\n";
1735                 abort ();
1736         }
1737
1738         if ((prop = node.property (X_("source-0"))) == 0) {
1739                 if ((prop = node.property ("source")) == 0) {
1740                         error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1741                         return boost::shared_ptr<AudioRegion>();
1742                 }
1743         }
1744
1745         PBD::ID s_id (prop->value());
1746
1747         if ((source = source_by_id (s_id)) == 0) {
1748                 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1749                 return boost::shared_ptr<AudioRegion>();
1750         }
1751
1752         as = boost::dynamic_pointer_cast<AudioSource>(source);
1753         if (!as) {
1754                 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1755                 return boost::shared_ptr<AudioRegion>();
1756         }
1757
1758         sources.push_back (as);
1759
1760         /* pickup other channels */
1761
1762         for (uint32_t n=1; n < nchans; ++n) {
1763                 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1764                 if ((prop = node.property (buf)) != 0) {
1765
1766                         PBD::ID id2 (prop->value());
1767
1768                         if ((source = source_by_id (id2)) == 0) {
1769                                 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1770                                 return boost::shared_ptr<AudioRegion>();
1771                         }
1772
1773                         as = boost::dynamic_pointer_cast<AudioSource>(source);
1774                         if (!as) {
1775                                 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1776                                 return boost::shared_ptr<AudioRegion>();
1777                         }
1778                         sources.push_back (as);
1779                 }
1780         }
1781
1782         for (uint32_t n = 0; n < nchans; ++n) {
1783                 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1784                 if ((prop = node.property (buf)) != 0) {
1785
1786                         PBD::ID id2 (prop->value());
1787
1788                         if ((source = source_by_id (id2)) == 0) {
1789                                 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1790                                 return boost::shared_ptr<AudioRegion>();
1791                         }
1792
1793                         as = boost::dynamic_pointer_cast<AudioSource>(source);
1794                         if (!as) {
1795                                 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1796                                 return boost::shared_ptr<AudioRegion>();
1797                         }
1798                         master_sources.push_back (as);
1799                 }
1800         }
1801
1802         try {
1803                 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1804
1805                 /* a final detail: this is the one and only place that we know how long missing files are */
1806
1807                 if (region->whole_file()) {
1808                         for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1809                                 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1810                                 if (sfp) {
1811                                         sfp->set_length (region->length());
1812                                 }
1813                         }
1814                 }
1815
1816                 if (!master_sources.empty()) {
1817                         if (master_sources.size() != nchans) {
1818                                 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1819                         } else {
1820                                 region->set_master_sources (master_sources);
1821                         }
1822                 }
1823
1824                 return region;
1825
1826         }
1827
1828         catch (failed_constructor& err) {
1829                 return boost::shared_ptr<AudioRegion>();
1830         }
1831 }
1832
1833 boost::shared_ptr<MidiRegion>
1834 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1835 {
1836         const XMLProperty* prop;
1837         boost::shared_ptr<Source> source;
1838         boost::shared_ptr<MidiSource> ms;
1839         SourceList sources;
1840
1841         if (node.name() != X_("Region")) {
1842                 return boost::shared_ptr<MidiRegion>();
1843         }
1844
1845         if ((prop = node.property ("name")) == 0) {
1846                 cerr << "no name for this region\n";
1847                 abort ();
1848         }
1849
1850         if ((prop = node.property (X_("source-0"))) == 0) {
1851                 if ((prop = node.property ("source")) == 0) {
1852                         error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1853                         return boost::shared_ptr<MidiRegion>();
1854                 }
1855         }
1856
1857         PBD::ID s_id (prop->value());
1858
1859         if ((source = source_by_id (s_id)) == 0) {
1860                 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1861                 return boost::shared_ptr<MidiRegion>();
1862         }
1863
1864         ms = boost::dynamic_pointer_cast<MidiSource>(source);
1865         if (!ms) {
1866                 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1867                 return boost::shared_ptr<MidiRegion>();
1868         }
1869
1870         sources.push_back (ms);
1871
1872         try {
1873                 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1874                 /* a final detail: this is the one and only place that we know how long missing files are */
1875
1876                 if (region->whole_file()) {
1877                         for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1878                                 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1879                                 if (sfp) {
1880                                         sfp->set_length (region->length());
1881                                 }
1882                         }
1883                 }
1884
1885                 return region;
1886         }
1887
1888         catch (failed_constructor& err) {
1889                 return boost::shared_ptr<MidiRegion>();
1890         }
1891 }
1892
1893 XMLNode&
1894 Session::get_sources_as_xml ()
1895
1896 {
1897         XMLNode* node = new XMLNode (X_("Sources"));
1898         Glib::Threads::Mutex::Lock lm (source_lock);
1899
1900         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1901                 node->add_child_nocopy (i->second->get_state());
1902         }
1903
1904         return *node;
1905 }
1906
1907 string
1908 Session::path_from_region_name (DataType type, string name, string identifier)
1909 {
1910         char buf[PATH_MAX+1];
1911         uint32_t n;
1912         SessionDirectory sdir(get_best_session_directory_for_new_source());
1913         std::string source_dir = ((type == DataType::AUDIO)
1914                 ? sdir.sound_path() : sdir.midi_path());
1915
1916         string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1917
1918         for (n = 0; n < 999999; ++n) {
1919                 if (identifier.length()) {
1920                         snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1921                                   identifier.c_str(), n, ext.c_str());
1922                 } else {
1923                         snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1924                                         n, ext.c_str());
1925                 }
1926
1927                 std::string source_path = Glib::build_filename (source_dir, buf);
1928
1929                 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1930                         return source_path;
1931                 }
1932         }
1933
1934         error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1935                                  name, identifier)
1936               << endmsg;
1937
1938         return "";
1939 }
1940
1941
1942 int
1943 Session::load_sources (const XMLNode& node)
1944 {
1945         XMLNodeList nlist;
1946         XMLNodeConstIterator niter;
1947         boost::shared_ptr<Source> source;
1948
1949         nlist = node.children();
1950
1951         set_dirty();
1952
1953         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1954           retry:
1955                 try {
1956                         if ((source = XMLSourceFactory (**niter)) == 0) {
1957                                 error << _("Session: cannot create Source from XML description.") << endmsg;
1958                         }
1959
1960                 } catch (MissingSource& err) {
1961
1962                         int user_choice;
1963
1964                         if (!no_questions_about_missing_files) {
1965                                 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1966                         } else {
1967                                 user_choice = -2;
1968                         }
1969
1970                         switch (user_choice) {
1971                         case 0:
1972                                 /* user added a new search location, so try again */
1973                                 goto retry;
1974
1975
1976                         case 1:
1977                                 /* user asked to quit the entire session load
1978                                  */
1979                                 return -1;
1980
1981                         case 2:
1982                                 no_questions_about_missing_files = true;
1983                                 goto retry;
1984
1985                         case 3:
1986                                 no_questions_about_missing_files = true;
1987                                 /* fallthru */
1988
1989                         case -1:
1990                         default:
1991                                 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1992                                 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1993                                 break;
1994                         }
1995                 }
1996         }
1997
1998         return 0;
1999 }
2000
2001 boost::shared_ptr<Source>
2002 Session::XMLSourceFactory (const XMLNode& node)
2003 {
2004         if (node.name() != "Source") {
2005                 return boost::shared_ptr<Source>();
2006         }
2007
2008         try {
2009                 /* note: do peak building in another thread when loading session state */
2010                 return SourceFactory::create (*this, node, true);
2011         }
2012
2013         catch (failed_constructor& err) {
2014                 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
2015                 return boost::shared_ptr<Source>();
2016         }
2017 }
2018
2019 int
2020 Session::save_template (string template_name)
2021 {
2022         XMLTree tree;
2023
2024         if (_state_of_the_state & CannotSave) {
2025                 return -1;
2026         }
2027
2028         std::string user_template_dir(user_template_directory());
2029
2030         if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2031                 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2032                                 user_template_dir, g_strerror (errno)) << endmsg;
2033                 return -1;
2034         }
2035
2036         tree.set_root (&get_template());
2037
2038         std::string template_dir_path(user_template_dir);
2039         
2040         /* directory to put the template in */
2041         template_dir_path = Glib::build_filename (template_dir_path, template_name);
2042
2043         if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2044                 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2045                                 template_dir_path) << endmsg;
2046                 return -1;
2047         }
2048         
2049         if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2050                 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2051                                 template_dir_path, g_strerror (errno)) << endmsg;
2052                 return -1;
2053         }
2054
2055         /* file to write */
2056         std::string template_file_path(template_dir_path);
2057         template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
2058
2059         if (!tree.write (template_file_path)) {
2060                 error << _("template not saved") << endmsg;
2061                 return -1;
2062         }
2063
2064         /* copy plugin state directory */
2065
2066         std::string template_plugin_state_path(template_dir_path);
2067         template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2068
2069         if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2070                 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2071                                 template_plugin_state_path, g_strerror (errno)) << endmsg;
2072                 return -1;
2073         }
2074
2075         copy_files (plugins_dir(), template_plugin_state_path);
2076
2077         return 0;
2078 }
2079
2080 void
2081 Session::refresh_disk_space ()
2082 {
2083 #if HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H
2084         
2085         Glib::Threads::Mutex::Lock lm (space_lock);
2086
2087         /* get freespace on every FS that is part of the session path */
2088
2089         _total_free_4k_blocks = 0;
2090         _total_free_4k_blocks_uncertain = false;
2091
2092         for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2093
2094                 struct statfs statfsbuf;
2095                 statfs (i->path.c_str(), &statfsbuf);
2096
2097                 double const scale = statfsbuf.f_bsize / 4096.0;
2098
2099                 /* See if this filesystem is read-only */
2100                 struct statvfs statvfsbuf;
2101                 statvfs (i->path.c_str(), &statvfsbuf);
2102
2103                 /* f_bavail can be 0 if it is undefined for whatever
2104                    filesystem we are looking at; Samba shares mounted
2105                    via GVFS are an example of this.
2106                 */
2107                 if (statfsbuf.f_bavail == 0) {
2108                         /* block count unknown */
2109                         i->blocks = 0;
2110                         i->blocks_unknown = true;
2111                 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2112                         /* read-only filesystem */
2113                         i->blocks = 0;
2114                         i->blocks_unknown = false;
2115                 } else {
2116                         /* read/write filesystem with known space */
2117                         i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2118                         i->blocks_unknown = false;
2119                 }
2120
2121                 _total_free_4k_blocks += i->blocks;
2122                 if (i->blocks_unknown) {
2123                         _total_free_4k_blocks_uncertain = true;
2124                 }
2125         }
2126 #endif
2127 }
2128
2129 string
2130 Session::get_best_session_directory_for_new_source ()
2131 {
2132         vector<space_and_path>::iterator i;
2133         string result = _session_dir->root_path();
2134
2135         /* handle common case without system calls */
2136
2137         if (session_dirs.size() == 1) {
2138                 return result;
2139         }
2140
2141         /* OK, here's the algorithm we're following here:
2142
2143         We want to select which directory to use for
2144         the next file source to be created. Ideally,
2145         we'd like to use a round-robin process so as to
2146         get maximum performance benefits from splitting
2147         the files across multiple disks.
2148
2149         However, in situations without much diskspace, an
2150         RR approach may end up filling up a filesystem
2151         with new files while others still have space.
2152         Its therefore important to pay some attention to
2153         the freespace in the filesystem holding each
2154         directory as well. However, if we did that by
2155         itself, we'd keep creating new files in the file
2156         system with the most space until it was as full
2157         as all others, thus negating any performance
2158         benefits of this RAID-1 like approach.
2159
2160         So, we use a user-configurable space threshold. If
2161         there are at least 2 filesystems with more than this
2162         much space available, we use RR selection between them.
2163         If not, then we pick the filesystem with the most space.
2164
2165         This gets a good balance between the two
2166         approaches.
2167         */
2168
2169         refresh_disk_space ();
2170
2171         int free_enough = 0;
2172
2173         for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2174                 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2175                         free_enough++;
2176                 }
2177         }
2178
2179         if (free_enough >= 2) {
2180                 /* use RR selection process, ensuring that the one
2181                    picked works OK.
2182                 */
2183
2184                 i = last_rr_session_dir;
2185
2186                 do {
2187                         if (++i == session_dirs.end()) {
2188                                 i = session_dirs.begin();
2189                         }
2190
2191                         if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2192                                 SessionDirectory sdir(i->path);
2193                                 if (sdir.create ()) {
2194                                         result = (*i).path;
2195                                         last_rr_session_dir = i;
2196                                         return result;
2197                                 }
2198                         }
2199
2200                 } while (i != last_rr_session_dir);
2201
2202         } else {
2203
2204                 /* pick FS with the most freespace (and that
2205                    seems to actually work ...)
2206                 */
2207
2208                 vector<space_and_path> sorted;
2209                 space_and_path_ascending_cmp cmp;
2210
2211                 sorted = session_dirs;
2212                 sort (sorted.begin(), sorted.end(), cmp);
2213
2214                 for (i = sorted.begin(); i != sorted.end(); ++i) {
2215                         SessionDirectory sdir(i->path);
2216                         if (sdir.create ()) {
2217                                 result = (*i).path;
2218                                 last_rr_session_dir = i;
2219                                 return result;
2220                         }
2221                 }
2222         }
2223
2224         return result;
2225 }
2226
2227 string
2228 Session::automation_dir () const
2229 {
2230         return Glib::build_filename (_path, "automation");
2231 }
2232
2233 string
2234 Session::analysis_dir () const
2235 {
2236         return Glib::build_filename (_path, "analysis");
2237 }
2238
2239 string
2240 Session::plugins_dir () const
2241 {
2242         return Glib::build_filename (_path, "plugins");
2243 }
2244
2245 string
2246 Session::externals_dir () const
2247 {
2248         return Glib::build_filename (_path, "externals");
2249 }
2250
2251 int
2252 Session::load_bundles (XMLNode const & node)
2253 {
2254         XMLNodeList nlist = node.children();
2255         XMLNodeConstIterator niter;
2256
2257         set_dirty();
2258
2259         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2260                 if ((*niter)->name() == "InputBundle") {
2261                         add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2262                 } else if ((*niter)->name() == "OutputBundle") {
2263                         add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2264                 } else {
2265                         error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2266                         return -1;
2267                 }
2268         }
2269
2270         return 0;
2271 }
2272
2273 int
2274 Session::load_route_groups (const XMLNode& node, int version)
2275 {
2276         XMLNodeList nlist = node.children();
2277         XMLNodeConstIterator niter;
2278
2279         set_dirty ();
2280
2281         if (version >= 3000) {
2282
2283                 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2284                         if ((*niter)->name() == "RouteGroup") {
2285                                 RouteGroup* rg = new RouteGroup (*this, "");
2286                                 add_route_group (rg);
2287                                 rg->set_state (**niter, version);
2288                         }
2289                 }
2290
2291         } else if (version < 3000) {
2292
2293                 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2294                         if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2295                                 RouteGroup* rg = new RouteGroup (*this, "");
2296                                 add_route_group (rg);
2297                                 rg->set_state (**niter, version);
2298                         }
2299                 }
2300         }
2301
2302         return 0;
2303 }
2304
2305 void
2306 Session::auto_save()
2307 {
2308         save_state (_current_snapshot_name);
2309 }
2310
2311 static bool
2312 state_file_filter (const string &str, void */*arg*/)
2313 {
2314         return (str.length() > strlen(statefile_suffix) &&
2315                 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2316 }
2317
2318 struct string_cmp {
2319         bool operator()(const string* a, const string* b) {
2320                 return *a < *b;
2321         }
2322 };
2323
2324 static string*
2325 remove_end(string* state)
2326 {
2327         string statename(*state);
2328
2329         string::size_type start,end;
2330         if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2331                 statename = statename.substr (start+1);
2332         }
2333
2334         if ((end = statename.rfind(".ardour")) == string::npos) {
2335                 end = statename.length();
2336         }
2337
2338         return new string(statename.substr (0, end));
2339 }
2340
2341 vector<string *> *
2342 Session::possible_states (string path)
2343 {
2344         PathScanner scanner;
2345         vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2346
2347         transform(states->begin(), states->end(), states->begin(), remove_end);
2348
2349         string_cmp cmp;
2350         sort (states->begin(), states->end(), cmp);
2351
2352         return states;
2353 }
2354
2355 vector<string *> *
2356 Session::possible_states () const
2357 {
2358         return possible_states(_path);
2359 }
2360
2361 void
2362 Session::add_route_group (RouteGroup* g)
2363 {
2364         _route_groups.push_back (g);
2365         route_group_added (g); /* EMIT SIGNAL */
2366
2367         g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2368         g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2369         g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2370
2371         set_dirty ();
2372 }
2373
2374 void
2375 Session::remove_route_group (RouteGroup& rg)
2376 {
2377         list<RouteGroup*>::iterator i;
2378
2379         if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2380                 _route_groups.erase (i);
2381                 delete &rg;
2382
2383                 route_group_removed (); /* EMIT SIGNAL */
2384         }
2385 }
2386
2387 /** Set a new order for our route groups, without adding or removing any.
2388  *  @param groups Route group list in the new order.
2389  */
2390 void
2391 Session::reorder_route_groups (list<RouteGroup*> groups)
2392 {
2393         _route_groups = groups;
2394
2395         route_groups_reordered (); /* EMIT SIGNAL */
2396         set_dirty ();
2397 }
2398
2399
2400 RouteGroup *
2401 Session::route_group_by_name (string name)
2402 {
2403         list<RouteGroup *>::iterator i;
2404
2405         for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2406                 if ((*i)->name() == name) {
2407                         return* i;
2408                 }
2409         }
2410         return 0;
2411 }
2412
2413 RouteGroup&
2414 Session::all_route_group() const
2415 {
2416         return *_all_route_group;
2417 }
2418
2419 void
2420 Session::add_commands (vector<Command*> const & cmds)
2421 {
2422         for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2423                 add_command (*i);
2424         }
2425 }
2426
2427 void
2428 Session::begin_reversible_command (const string& name)
2429 {
2430         begin_reversible_command (g_quark_from_string (name.c_str ()));
2431 }
2432
2433 /** Begin a reversible command using a GQuark to identify it.
2434  *  begin_reversible_command() and commit_reversible_command() calls may be nested,
2435  *  but there must be as many begin...()s as there are commit...()s.
2436  */
2437 void
2438 Session::begin_reversible_command (GQuark q)
2439 {
2440         /* If nested begin/commit pairs are used, we create just one UndoTransaction
2441            to hold all the commands that are committed.  This keeps the order of
2442            commands correct in the history.
2443         */
2444
2445         if (_current_trans == 0) {
2446                 /* start a new transaction */
2447                 assert (_current_trans_quarks.empty ());
2448                 _current_trans = new UndoTransaction();
2449                 _current_trans->set_name (g_quark_to_string (q));
2450         }
2451
2452         _current_trans_quarks.push_front (q);
2453 }
2454
2455 void
2456 Session::commit_reversible_command (Command *cmd)
2457 {
2458         assert (_current_trans);
2459         assert (!_current_trans_quarks.empty ());
2460
2461         struct timeval now;
2462
2463         if (cmd) {
2464                 _current_trans->add_command (cmd);
2465         }
2466
2467         _current_trans_quarks.pop_front ();
2468
2469         if (!_current_trans_quarks.empty ()) {
2470                 /* the transaction we're committing is not the top-level one */
2471                 return;
2472         }
2473
2474         if (_current_trans->empty()) {
2475                 /* no commands were added to the transaction, so just get rid of it */
2476                 delete _current_trans;
2477                 _current_trans = 0;
2478                 return;
2479         }
2480
2481         gettimeofday (&now, 0);
2482         _current_trans->set_timestamp (now);
2483
2484         _history.add (_current_trans);
2485         _current_trans = 0;
2486 }
2487
2488 static bool
2489 accept_all_audio_files (const string& path, void */*arg*/)
2490 {
2491         if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2492                 return false;
2493         }
2494
2495         if (!AudioFileSource::safe_audio_file_extension (path)) {
2496                 return false;
2497         }
2498
2499         return true;
2500 }
2501
2502 static bool
2503 accept_all_midi_files (const string& path, void */*arg*/)
2504 {
2505         if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2506                 return false;
2507         }
2508
2509         return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2510                 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2511                 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2512 }
2513
2514 static bool
2515 accept_all_state_files (const string& path, void */*arg*/)
2516 {
2517         if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2518                 return false;
2519         }
2520
2521         return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2522 }
2523
2524 int
2525 Session::find_all_sources (string path, set<string>& result)
2526 {
2527         XMLTree tree;
2528         XMLNode* node;
2529
2530         if (!tree.read (path)) {
2531                 return -1;
2532         }
2533
2534         if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2535                 return -2;
2536         }
2537
2538         XMLNodeList nlist;
2539         XMLNodeConstIterator niter;
2540
2541         nlist = node->children();
2542
2543         set_dirty();
2544
2545         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2546
2547                 XMLProperty* prop;
2548
2549                 if ((prop = (*niter)->property (X_("type"))) == 0) {
2550                         continue;
2551                 }
2552
2553                 DataType type (prop->value());
2554
2555                 if ((prop = (*niter)->property (X_("name"))) == 0) {
2556                         continue;
2557                 }
2558
2559                 if (Glib::path_is_absolute (prop->value())) {
2560                         /* external file, ignore */
2561                         continue;
2562                 }
2563
2564                 string found_path;
2565                 bool is_new;
2566                 uint16_t chan;
2567
2568                 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2569                         result.insert (found_path);
2570                 }
2571         }
2572
2573         return 0;
2574 }
2575
2576 int
2577 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2578 {
2579         PathScanner scanner;
2580         vector<string*>* state_files;
2581         string ripped;
2582         string this_snapshot_path;
2583
2584         result.clear ();
2585
2586         ripped = _path;
2587
2588         if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2589                 ripped = ripped.substr (0, ripped.length() - 1);
2590         }
2591
2592         state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2593
2594         if (state_files == 0) {
2595                 /* impossible! */
2596                 return 0;
2597         }
2598
2599         this_snapshot_path = _path;
2600         this_snapshot_path += legalize_for_path (_current_snapshot_name);
2601         this_snapshot_path += statefile_suffix;
2602
2603         for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2604
2605                 if (exclude_this_snapshot && **i == this_snapshot_path) {
2606                         continue;
2607                 }
2608
2609                 if (find_all_sources (**i, result) < 0) {
2610                         return -1;
2611                 }
2612         }
2613
2614         return 0;
2615 }
2616
2617 struct RegionCounter {
2618     typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2619     AudioSourceList::iterator iter;
2620     boost::shared_ptr<Region> region;
2621     uint32_t count;
2622
2623     RegionCounter() : count (0) {}
2624 };
2625
2626 int
2627 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2628 {
2629         boost::optional<int> r = AskAboutPlaylistDeletion (p);
2630         return r.get_value_or (1);
2631 }
2632
2633 void
2634 Session::cleanup_regions ()
2635 {
2636         const RegionFactory::RegionMap& regions (RegionFactory::regions());
2637
2638         for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2639
2640                 uint32_t used = playlists->region_use_count (i->second);
2641
2642                 if (used == 0 && !i->second->automatic ()) {
2643                         RegionFactory::map_remove (i->second);
2644                 }
2645         }
2646
2647         /* dump the history list */
2648         _history.clear ();
2649
2650         save_state ("");
2651 }
2652
2653 int
2654 Session::cleanup_sources (CleanupReport& rep)
2655 {
2656         // FIXME: needs adaptation to midi
2657
2658         vector<boost::shared_ptr<Source> > dead_sources;
2659         PathScanner scanner;
2660         string audio_path;
2661         string midi_path;
2662         vector<space_and_path>::iterator i;
2663         vector<space_and_path>::iterator nexti;
2664         vector<string*>* candidates;
2665         vector<string*>* candidates2;
2666         vector<string> unused;
2667         set<string> all_sources;
2668         bool used;
2669         string spath;
2670         int ret = -1;
2671
2672         _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2673
2674         /* consider deleting all unused playlists */
2675
2676         if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2677                 ret = 0;
2678                 goto out;
2679         }
2680
2681         /* sync the "all regions" property of each playlist with its current state
2682          */
2683
2684         playlists->sync_all_regions_with_regions ();
2685
2686         /* find all un-used sources */
2687
2688         rep.paths.clear ();
2689         rep.space = 0;
2690
2691         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2692
2693                 SourceMap::iterator tmp;
2694
2695                 tmp = i;
2696                 ++tmp;
2697
2698                 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2699                    capture files.
2700                 */
2701
2702                 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2703                         dead_sources.push_back (i->second);
2704                         i->second->drop_references ();
2705                 }
2706
2707                 i = tmp;
2708         }
2709
2710         /* build a list of all the possible audio directories for the session */
2711
2712         for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2713
2714                 nexti = i;
2715                 ++nexti;
2716
2717                 SessionDirectory sdir ((*i).path);
2718                 audio_path += sdir.sound_path();
2719
2720                 if (nexti != session_dirs.end()) {
2721                         audio_path += ':';
2722                 }
2723
2724                 i = nexti;
2725         }
2726
2727
2728         /* build a list of all the possible midi directories for the session */
2729
2730         for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2731
2732                 nexti = i;
2733                 ++nexti;
2734
2735                 SessionDirectory sdir ((*i).path);
2736                 midi_path += sdir.midi_path();
2737
2738                 if (nexti != session_dirs.end()) {
2739                         midi_path += ':';
2740                 }
2741
2742                 i = nexti;
2743         }
2744
2745         candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2746         candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2747
2748         /* merge them */
2749
2750         if (candidates) {
2751                 if (candidates2) {
2752                         for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2753                                 candidates->push_back (*i);
2754                         }
2755                         delete candidates2;
2756                 }
2757         } else {
2758                 candidates = candidates2; // might still be null
2759         }
2760
2761         /* find all sources, but don't use this snapshot because the
2762            state file on disk still references sources we may have already
2763            dropped.
2764         */
2765
2766         find_all_sources_across_snapshots (all_sources, true);
2767
2768         /*  add our current source list
2769          */
2770
2771         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2772                 boost::shared_ptr<FileSource> fs;
2773                 SourceMap::iterator tmp = i;
2774                 ++tmp;
2775
2776                 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2777                         if (playlists->source_use_count (fs) != 0) {
2778                                 all_sources.insert (fs->path());
2779                         } else {
2780
2781                                 /* we might not remove this source from disk, because it may be used
2782                                    by other snapshots, but its not being used in this version
2783                                    so lets get rid of it now, along with any representative regions
2784                                    in the region list.
2785                                 */
2786
2787                                 RegionFactory::remove_regions_using_source (i->second);
2788                                 sources.erase (i);
2789                         }
2790                 }
2791
2792                 i = tmp;
2793         }
2794
2795         char tmppath1[PATH_MAX+1];
2796         char tmppath2[PATH_MAX+1];
2797
2798         if (candidates) {
2799                 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2800
2801                         used = false;
2802                         spath = **x;
2803
2804                         for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2805
2806                                 if (realpath(spath.c_str(), tmppath1) == 0) {
2807                                         error << string_compose (_("Cannot expand path %1 (%2)"),
2808                                                                  spath, strerror (errno)) << endmsg;
2809                                         continue;
2810                                 }
2811
2812                                 if (realpath((*i).c_str(),  tmppath2) == 0) {
2813                                         error << string_compose (_("Cannot expand path %1 (%2)"),
2814                                                                  (*i), strerror (errno)) << endmsg;
2815                                         continue;
2816                                 }
2817
2818                                 if (strcmp(tmppath1, tmppath2) == 0) {
2819                                         used = true;
2820                                         break;
2821                                 }
2822                         }
2823
2824                         if (!used) {
2825                                 unused.push_back (spath);
2826                         }
2827
2828                         delete *x;
2829                 }
2830
2831                 delete candidates;
2832         }
2833
2834         /* now try to move all unused files into the "dead" directory(ies) */
2835
2836         for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2837                 struct stat statbuf;
2838
2839                 string newpath;
2840
2841                 /* don't move the file across filesystems, just
2842                    stick it in the `dead_dir_name' directory
2843                    on whichever filesystem it was already on.
2844                 */
2845
2846                 if ((*x).find ("/sounds/") != string::npos) {
2847
2848                         /* old school, go up 1 level */
2849
2850                         newpath = Glib::path_get_dirname (*x);      // "sounds"
2851                         newpath = Glib::path_get_dirname (newpath); // "session-name"
2852
2853                 } else {
2854
2855                         /* new school, go up 4 levels */
2856
2857                         newpath = Glib::path_get_dirname (*x);      // "audiofiles" or "midifiles"
2858                         newpath = Glib::path_get_dirname (newpath); // "session-name"
2859                         newpath = Glib::path_get_dirname (newpath); // "interchange"
2860                         newpath = Glib::path_get_dirname (newpath); // "session-dir"
2861                 }
2862
2863                 newpath = Glib::build_filename (newpath, dead_dir_name);
2864
2865                 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2866                         error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2867                         return -1;
2868                 }
2869
2870                 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2871
2872                 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2873
2874                         /* the new path already exists, try versioning */
2875
2876                         char buf[PATH_MAX+1];
2877                         int version = 1;
2878                         string newpath_v;
2879
2880                         snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2881                         newpath_v = buf;
2882
2883                         while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2884                                 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2885                                 newpath_v = buf;
2886                         }
2887
2888                         if (version == 999) {
2889                                 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2890                                                   newpath)
2891                                       << endmsg;
2892                         } else {
2893                                 newpath = newpath_v;
2894                         }
2895
2896                 } else {
2897
2898                         /* it doesn't exist, or we can't read it or something */
2899
2900                 }
2901
2902                 stat ((*x).c_str(), &statbuf);
2903
2904                 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2905                         error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2906                                           (*x), newpath, strerror (errno))
2907                               << endmsg;
2908                         goto out;
2909                 }
2910
2911                 /* see if there an easy to find peakfile for this file, and remove it.
2912                  */
2913
2914                 string base = basename_nosuffix (*x);
2915                 base += "%A"; /* this is what we add for the channel suffix of all native files,
2916                                  or for the first channel of embedded files. it will miss
2917                                  some peakfiles for other channels
2918                               */
2919                 string peakpath = peak_path (base);
2920
2921                 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2922                         if (::unlink (peakpath.c_str()) != 0) {
2923                                 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2924                                                          peakpath, _path, strerror (errno))
2925                                       << endmsg;
2926                                 /* try to back out */
2927                                 ::rename (newpath.c_str(), _path.c_str());
2928                                 goto out;
2929                         }
2930                 }
2931
2932                 rep.paths.push_back (*x);
2933                 rep.space += statbuf.st_size;
2934         }
2935
2936         /* dump the history list */
2937
2938         _history.clear ();
2939
2940         /* save state so we don't end up a session file
2941            referring to non-existent sources.
2942         */
2943
2944         save_state ("");
2945         ret = 0;
2946
2947   out:
2948         _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2949
2950         return ret;
2951 }
2952
2953 int
2954 Session::cleanup_trash_sources (CleanupReport& rep)
2955 {
2956         // FIXME: needs adaptation for MIDI
2957
2958         vector<space_and_path>::iterator i;
2959         string dead_dir;
2960
2961         rep.paths.clear ();
2962         rep.space = 0;
2963
2964         for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2965
2966                 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2967
2968                 clear_directory (dead_dir, &rep.space, &rep.paths);
2969         }
2970
2971         return 0;
2972 }
2973
2974 void
2975 Session::set_dirty ()
2976 {
2977         bool was_dirty = dirty();
2978
2979         _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2980
2981
2982         if (!was_dirty) {
2983                 DirtyChanged(); /* EMIT SIGNAL */
2984         }
2985 }
2986
2987
2988 void
2989 Session::set_clean ()
2990 {
2991         bool was_dirty = dirty();
2992
2993         _state_of_the_state = Clean;
2994
2995
2996         if (was_dirty) {
2997                 DirtyChanged(); /* EMIT SIGNAL */
2998         }
2999 }
3000
3001 void
3002 Session::set_deletion_in_progress ()
3003 {
3004         _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3005 }
3006
3007 void
3008 Session::clear_deletion_in_progress ()
3009 {
3010         _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3011 }
3012
3013 void
3014 Session::add_controllable (boost::shared_ptr<Controllable> c)
3015 {
3016         /* this adds a controllable to the list managed by the Session.
3017            this is a subset of those managed by the Controllable class
3018            itself, and represents the only ones whose state will be saved
3019            as part of the session.
3020         */
3021
3022         Glib::Threads::Mutex::Lock lm (controllables_lock);
3023         controllables.insert (c);
3024 }
3025
3026 struct null_deleter { void operator()(void const *) const {} };
3027
3028 void
3029 Session::remove_controllable (Controllable* c)
3030 {
3031         if (_state_of_the_state & Deletion) {
3032                 return;
3033         }
3034
3035         Glib::Threads::Mutex::Lock lm (controllables_lock);
3036
3037         Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3038
3039         if (x != controllables.end()) {
3040                 controllables.erase (x);
3041         }
3042 }
3043
3044 boost::shared_ptr<Controllable>
3045 Session::controllable_by_id (const PBD::ID& id)
3046 {
3047         Glib::Threads::Mutex::Lock lm (controllables_lock);
3048
3049         for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3050                 if ((*i)->id() == id) {
3051                         return *i;
3052                 }
3053         }
3054
3055         return boost::shared_ptr<Controllable>();
3056 }
3057
3058 boost::shared_ptr<Controllable>
3059 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3060 {
3061         boost::shared_ptr<Controllable> c;
3062         boost::shared_ptr<Route> r;
3063
3064         switch (desc.top_level_type()) {
3065         case ControllableDescriptor::NamedRoute:
3066         {
3067                 std::string str = desc.top_level_name();
3068                 if (str == "master") {
3069                         r = _master_out;
3070                 } else if (str == "control" || str == "listen") {
3071                         r = _monitor_out;
3072                 } else {
3073                         r = route_by_name (desc.top_level_name());
3074                 }
3075                 break;
3076         }
3077
3078         case ControllableDescriptor::RemoteControlID:
3079                 r = route_by_remote_id (desc.rid());
3080                 break;
3081         }
3082
3083         if (!r) {
3084                 return c;
3085         }
3086
3087         switch (desc.subtype()) {
3088         case ControllableDescriptor::Gain:
3089                 c = r->gain_control ();
3090                 break;
3091
3092         case ControllableDescriptor::Solo:
3093                 c = r->solo_control();
3094                 break;
3095
3096         case ControllableDescriptor::Mute:
3097                 c = r->mute_control();
3098                 break;
3099
3100         case ControllableDescriptor::Recenable:
3101         {
3102                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3103
3104                 if (t) {
3105                         c = t->rec_enable_control ();
3106                 }
3107                 break;
3108         }
3109
3110         case ControllableDescriptor::PanDirection:
3111         {
3112                 c = r->pannable()->pan_azimuth_control;
3113                 break;
3114         }
3115
3116         case ControllableDescriptor::PanWidth:
3117         {
3118                 c = r->pannable()->pan_width_control;
3119                 break;
3120         }
3121
3122         case ControllableDescriptor::PanElevation:
3123         {
3124                 c = r->pannable()->pan_elevation_control;
3125                 break;
3126         }
3127
3128         case ControllableDescriptor::Balance:
3129                 /* XXX simple pan control */
3130                 break;
3131
3132         case ControllableDescriptor::PluginParameter:
3133         {
3134                 uint32_t plugin = desc.target (0);
3135                 uint32_t parameter_index = desc.target (1);
3136
3137                 /* revert to zero based counting */
3138
3139                 if (plugin > 0) {
3140                         --plugin;
3141                 }
3142
3143                 if (parameter_index > 0) {
3144                         --parameter_index;
3145                 }
3146
3147                 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3148
3149                 if (p) {
3150                         c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3151                                 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3152                 }
3153                 break;
3154         }
3155
3156         case ControllableDescriptor::SendGain:
3157         {
3158                 uint32_t send = desc.target (0);
3159
3160                 /* revert to zero-based counting */
3161
3162                 if (send > 0) {
3163                         --send;
3164                 }
3165
3166                 boost::shared_ptr<Processor> p = r->nth_send (send);
3167
3168                 if (p) {
3169                         boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3170                         boost::shared_ptr<Amp> a = s->amp();
3171                         
3172                         if (a) {
3173                                 c = s->amp()->gain_control();
3174                         }
3175                 }
3176                 break;
3177         }
3178
3179         default:
3180                 /* relax and return a null pointer */
3181                 break;
3182         }
3183
3184         return c;
3185 }
3186
3187 void
3188 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3189 {
3190         if (_writable) {
3191                 Stateful::add_instant_xml (node, _path);
3192         }
3193
3194         if (write_to_config) {
3195                 Config->add_instant_xml (node);
3196         }
3197 }
3198
3199 XMLNode*
3200 Session::instant_xml (const string& node_name)
3201 {
3202         return Stateful::instant_xml (node_name, _path);
3203 }
3204
3205 int
3206 Session::save_history (string snapshot_name)
3207 {
3208         XMLTree tree;
3209
3210         if (!_writable) {
3211                 return 0;
3212         }
3213
3214         if (snapshot_name.empty()) {
3215                 snapshot_name = _current_snapshot_name;
3216         }
3217
3218         const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3219         const string backup_filename = history_filename + backup_suffix;
3220         const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3221         const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3222
3223         if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3224                 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3225                         error << _("could not backup old history file, current history not saved") << endmsg;
3226                         return -1;
3227                 }
3228         }
3229
3230         if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3231                 return 0;
3232         }
3233
3234         tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3235
3236         if (!tree.write (xml_path))
3237         {
3238                 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3239
3240                 if (g_remove (xml_path.c_str()) != 0) {
3241                         error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3242                                         xml_path, g_strerror (errno)) << endmsg;
3243                 }
3244                 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3245                         error << string_compose (_("could not restore history file from backup %1 (%2)"),
3246                                         backup_path, g_strerror (errno)) << endmsg;
3247                 }
3248
3249                 return -1;
3250         }
3251
3252         return 0;
3253 }
3254
3255 int
3256 Session::restore_history (string snapshot_name)
3257 {
3258         XMLTree tree;
3259
3260         if (snapshot_name.empty()) {
3261                 snapshot_name = _current_snapshot_name;
3262         }
3263
3264         const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3265         const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3266
3267         info << "Loading history from " << xml_path << endmsg;
3268
3269         if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3270                 info << string_compose (_("%1: no history file \"%2\" for this session."),
3271                                 _name, xml_path) << endmsg;
3272                 return 1;
3273         }
3274
3275         if (!tree.read (xml_path)) {
3276                 error << string_compose (_("Could not understand session history file \"%1\""),
3277                                 xml_path) << endmsg;
3278                 return -1;
3279         }
3280
3281         // replace history
3282         _history.clear();
3283
3284         for (XMLNodeConstIterator it  = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3285
3286                 XMLNode *t = *it;
3287                 UndoTransaction* ut = new UndoTransaction ();
3288                 struct timeval tv;
3289
3290                 ut->set_name(t->property("name")->value());
3291                 stringstream ss(t->property("tv-sec")->value());
3292                 ss >> tv.tv_sec;
3293                 ss.str(t->property("tv-usec")->value());
3294                 ss >> tv.tv_usec;
3295                 ut->set_timestamp(tv);
3296
3297                 for (XMLNodeConstIterator child_it  = t->children().begin();
3298                                 child_it != t->children().end(); child_it++)
3299                 {
3300                         XMLNode *n = *child_it;
3301                         Command *c;
3302
3303                         if (n->name() == "MementoCommand" ||
3304                                         n->name() == "MementoUndoCommand" ||
3305                                         n->name() == "MementoRedoCommand") {
3306
3307                                 if ((c = memento_command_factory(n))) {
3308                                         ut->add_command(c);
3309                                 }
3310
3311                         } else if (n->name() == "NoteDiffCommand") {
3312                                 PBD::ID id (n->property("midi-source")->value());
3313                                 boost::shared_ptr<MidiSource> midi_source =
3314                                         boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3315                                 if (midi_source) {
3316                                         ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3317                                 } else {
3318                                         error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3319                                 }
3320
3321                         } else if (n->name() == "SysExDiffCommand") {
3322
3323                                 PBD::ID id (n->property("midi-source")->value());
3324                                 boost::shared_ptr<MidiSource> midi_source =
3325                                         boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3326                                 if (midi_source) {
3327                                         ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3328                                 } else {
3329                                         error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3330                                 }
3331
3332                         } else if (n->name() == "PatchChangeDiffCommand") {
3333
3334                                 PBD::ID id (n->property("midi-source")->value());
3335                                 boost::shared_ptr<MidiSource> midi_source =
3336                                         boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3337                                 if (midi_source) {
3338                                         ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3339                                 } else {
3340                                         error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3341                                 }
3342
3343                         } else if (n->name() == "StatefulDiffCommand") {
3344                                 if ((c = stateful_diff_command_factory (n))) {
3345                                         ut->add_command (c);
3346                                 }
3347                         } else {
3348                                 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3349                         }
3350                 }
3351
3352                 _history.add (ut);
3353         }
3354
3355         return 0;
3356 }
3357
3358 void
3359 Session::config_changed (std::string p, bool ours)
3360 {
3361         if (ours) {
3362                 set_dirty ();
3363         }
3364
3365         if (p == "seamless-loop") {
3366
3367         } else if (p == "rf-speed") {
3368
3369         } else if (p == "auto-loop") {
3370
3371         } else if (p == "auto-input") {
3372
3373                 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3374                         /* auto-input only makes a difference if we're rolling */
3375                         set_track_monitor_input_status (!config.get_auto_input());
3376                 }
3377
3378         } else if (p == "punch-in") {
3379
3380                 Location* location;
3381
3382                 if ((location = _locations->auto_punch_location()) != 0) {
3383
3384                         if (config.get_punch_in ()) {
3385                                 replace_event (SessionEvent::PunchIn, location->start());
3386                         } else {
3387                                 remove_event (location->start(), SessionEvent::PunchIn);
3388                         }
3389                 }
3390
3391         } else if (p == "punch-out") {
3392
3393                 Location* location;
3394
3395                 if ((location = _locations->auto_punch_location()) != 0) {
3396
3397                         if (config.get_punch_out()) {
3398                                 replace_event (SessionEvent::PunchOut, location->end());
3399                         } else {
3400                                 clear_events (SessionEvent::PunchOut);
3401                         }
3402                 }
3403
3404         } else if (p == "edit-mode") {
3405
3406                 Glib::Threads::Mutex::Lock lm (playlists->lock);
3407
3408                 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3409                         (*i)->set_edit_mode (Config->get_edit_mode ());
3410                 }
3411
3412         } else if (p == "use-video-sync") {
3413
3414                 waiting_for_sync_offset = config.get_use_video_sync();
3415
3416         } else if (p == "mmc-control") {
3417
3418                 //poke_midi_thread ();
3419
3420         } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3421
3422                 MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
3423
3424         } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3425
3426                 MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
3427
3428         } else if (p == "midi-control") {
3429
3430                 //poke_midi_thread ();
3431
3432         } else if (p == "raid-path") {
3433
3434                 setup_raid_path (config.get_raid_path());
3435
3436         } else if (p == "timecode-format") {
3437
3438                 sync_time_vars ();
3439
3440         } else if (p == "video-pullup") {
3441
3442                 sync_time_vars ();
3443
3444         } else if (p == "seamless-loop") {
3445
3446                 if (play_loop && transport_rolling()) {
3447                         // to reset diskstreams etc
3448                         request_play_loop (true);
3449                 }
3450
3451         } else if (p == "rf-speed") {
3452
3453                 cumulative_rf_motion = 0;
3454                 reset_rf_scale (0);
3455
3456         } else if (p == "click-sound") {
3457
3458                 setup_click_sounds (1);
3459
3460         } else if (p == "click-emphasis-sound") {
3461
3462                 setup_click_sounds (-1);
3463
3464         } else if (p == "clicking") {
3465
3466                 if (Config->get_clicking()) {
3467                         if (_click_io && click_data) { // don't require emphasis data
3468                                 _clicking = true;
3469                         }
3470                 } else {
3471                         _clicking = false;
3472                 }
3473
3474         } else if (p == "click-gain") {
3475                 
3476                 if (_click_gain) {
3477                         _click_gain->set_gain (Config->get_click_gain(), this);
3478                 }
3479
3480         } else if (p == "send-mtc") {
3481
3482                 if (Config->get_send_mtc ()) {
3483                         /* mark us ready to send */
3484                         next_quarter_frame_to_send = 0;
3485                 }
3486
3487         } else if (p == "send-mmc") {
3488
3489                 MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
3490
3491         } else if (p == "midi-feedback") {
3492
3493                 session_midi_feedback = Config->get_midi_feedback();
3494
3495         } else if (p == "jack-time-master") {
3496
3497                 engine().reset_timebase ();
3498
3499         } else if (p == "native-file-header-format") {
3500
3501                 if (!first_file_header_format_reset) {
3502                         reset_native_file_format ();
3503                 }
3504
3505                 first_file_header_format_reset = false;
3506
3507         } else if (p == "native-file-data-format") {
3508
3509                 if (!first_file_data_format_reset) {
3510                         reset_native_file_format ();
3511                 }
3512
3513                 first_file_data_format_reset = false;
3514
3515         } else if (p == "external-sync") {
3516                 if (!config.get_external_sync()) {
3517                         drop_sync_source ();
3518                 } else {
3519                         switch_to_sync_source (Config->get_sync_source());
3520                 }
3521         }  else if (p == "denormal-model") {
3522                 setup_fpu ();
3523         } else if (p == "history-depth") {
3524                 set_history_depth (Config->get_history_depth());
3525         } else if (p == "remote-model") {
3526                 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3527                    TO SET REMOTE ID'S
3528                 */
3529         } else if (p == "sync-all-route-ordering") {
3530
3531                 /* sync to editor order unless mixer is used for remote IDs 
3532                  */
3533
3534                 switch (Config->get_remote_model()) {
3535                 case UserOrdered:
3536                         sync_order_keys (EditorSort);
3537                         break;
3538                 case EditorOrdered:
3539                         sync_order_keys (EditorSort);
3540                         break;
3541                 case MixerOrdered:
3542                         sync_order_keys (MixerSort);
3543                 }
3544                         
3545         } else if (p == "initial-program-change") {
3546
3547                 if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
3548                         MIDI::byte buf[2];
3549
3550                         buf[0] = MIDI::program; // channel zero by default
3551                         buf[1] = (Config->get_initial_program_change() & 0x7f);
3552
3553                         MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
3554                 }
3555         } else if (p == "solo-mute-override") {
3556                 // catch_up_on_solo_mute_override ();
3557         } else if (p == "listen-position" || p == "pfl-position") {
3558                 listen_position_changed ();
3559         } else if (p == "solo-control-is-listen-control") {
3560                 solo_control_mode_changed ();
3561         } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3562                 last_timecode_valid = false;
3563         } else if (p == "playback-buffer-seconds") {
3564                 AudioSource::allocate_working_buffers (frame_rate());
3565         } else if (p == "automation-thinning-factor") {
3566                 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3567         } else if (p == "ltc-source-port") {
3568                 reconnect_ltc_input ();
3569         } else if (p == "ltc-sink-port") {
3570                 reconnect_ltc_output ();
3571         } else if (p == "timecode-generator-offset") {
3572                 ltc_tx_parse_offset();
3573         }
3574
3575         set_dirty ();
3576 }
3577
3578 void
3579 Session::set_history_depth (uint32_t d)
3580 {
3581         _history.set_depth (d);
3582 }
3583
3584 int
3585 Session::load_diskstreams_2X (XMLNode const & node, int)
3586 {
3587         XMLNodeList          clist;
3588         XMLNodeConstIterator citer;
3589
3590         clist = node.children();
3591
3592         for (citer = clist.begin(); citer != clist.end(); ++citer) {
3593
3594                 try {
3595                         /* diskstreams added automatically by DiskstreamCreated handler */
3596                         if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3597                                 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3598                                 _diskstreams_2X.push_back (dsp);
3599                         } else {
3600                                 error << _("Session: unknown diskstream type in XML") << endmsg;
3601                         }
3602                 }
3603
3604                 catch (failed_constructor& err) {
3605                         error << _("Session: could not load diskstream via XML state") << endmsg;
3606                         return -1;
3607                 }
3608         }
3609
3610         return 0;
3611 }
3612
3613 /** Connect things to the MMC object */
3614 void
3615 Session::setup_midi_machine_control ()
3616 {
3617         MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
3618
3619         mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3620         mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3621         mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3622         mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3623         mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3624         mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3625         mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3626         mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3627         mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3628         mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3629         mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3630         mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3631         mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3632
3633         /* also handle MIDI SPP because its so common */
3634
3635         mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3636         mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3637         mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3638 }
3639
3640 boost::shared_ptr<Controllable>
3641 Session::solo_cut_control() const
3642 {
3643         /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3644            controls in Ardour that currently get presented to the user in the GUI that require
3645            access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3646
3647            its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3648            it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3649            parameter.
3650         */
3651
3652         return _solo_cut_control;
3653 }
3654
3655 int
3656 Session::rename (const std::string& new_name)
3657 {
3658         string legal_name = legalize_for_path (new_name);
3659         string newpath;
3660         string oldstr;
3661         string newstr;
3662         bool first = true;
3663
3664         string const old_sources_root = _session_dir->sources_root();
3665
3666 #define RENAME ::rename
3667
3668         /* Rename:
3669
3670          * session directory
3671          * interchange subdirectory
3672          * session file
3673          * session history
3674          
3675          * Backup files are left unchanged and not renamed.
3676          */
3677
3678         /* pass one: not 100% safe check that the new directory names don't
3679          * already exist ...
3680          */
3681
3682         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3683                 vector<string> v;
3684
3685                 oldstr = (*i).path;
3686
3687                 /* this is a stupid hack because Glib::path_get_dirname() is
3688                  * lexical-only, and so passing it /a/b/c/ gives a different
3689                  * result than passing it /a/b/c ...
3690                  */
3691
3692                 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3693                         oldstr = oldstr.substr (0, oldstr.length() - 1);
3694                 }
3695
3696                 string base = Glib::path_get_dirname (oldstr);
3697                 string p = Glib::path_get_basename (oldstr);
3698
3699                 newstr = Glib::build_filename (base, legal_name);
3700                 
3701                 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3702                         return -1;
3703                 }
3704         }
3705
3706         /* Session dirs */
3707         
3708         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3709                 vector<string> v;
3710
3711                 oldstr = (*i).path;
3712
3713                 /* this is a stupid hack because Glib::path_get_dirname() is
3714                  * lexical-only, and so passing it /a/b/c/ gives a different
3715                  * result than passing it /a/b/c ...
3716                  */
3717
3718                 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3719                         oldstr = oldstr.substr (0, oldstr.length() - 1);
3720                 }
3721
3722                 string base = Glib::path_get_dirname (oldstr);
3723                 string p = Glib::path_get_basename (oldstr);
3724
3725                 newstr = Glib::build_filename (base, legal_name);
3726
3727                 cerr << "Rename " << oldstr << " => " << newstr << endl;                
3728
3729                 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3730                         return 1;
3731                 }
3732
3733                 if (first) {
3734                         (*_session_dir) = newstr;
3735                         newpath = newstr;
3736                         first = 1;
3737                 }
3738
3739                 /* directory below interchange */
3740
3741                 v.push_back (newstr);
3742                 v.push_back (interchange_dir_name);
3743                 v.push_back (p);
3744
3745                 oldstr = Glib::build_filename (v);
3746
3747                 v.clear ();
3748                 v.push_back (newstr);
3749                 v.push_back (interchange_dir_name);
3750                 v.push_back (legal_name);
3751
3752                 newstr = Glib::build_filename (v);
3753                 
3754                 cerr << "Rename " << oldstr << " => " << newstr << endl;
3755                 
3756                 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3757                         return 1;
3758                 }
3759         }
3760
3761         /* state file */
3762         
3763         oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3764         newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3765         
3766         cerr << "Rename " << oldstr << " => " << newstr << endl;                
3767
3768         if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3769                 return 1;
3770         }
3771
3772         /* history file */
3773
3774         
3775         oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3776
3777         if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS))  {
3778                 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3779                 
3780                 cerr << "Rename " << oldstr << " => " << newstr << endl;                
3781                 
3782                 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3783                         return 1;
3784                 }
3785         }
3786
3787         /* update file source paths */
3788         
3789         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3790                 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3791                 if (fs) {
3792                         string p = fs->path ();
3793                         boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3794                         fs->set_path (p);
3795                 }
3796         }
3797
3798         /* remove old name from recent sessions */
3799
3800         remove_recent_sessions (_path);
3801
3802         _path = newpath;
3803         _current_snapshot_name = new_name;
3804         _name = new_name;
3805
3806         set_dirty ();
3807
3808         /* save state again to get everything just right */
3809
3810         save_state (_current_snapshot_name);
3811
3812
3813         /* add to recent sessions */
3814
3815         store_recent_sessions (new_name, _path);
3816
3817         return 0;
3818
3819 #undef RENAME
3820 }