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