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