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