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