improved error handling and checking for Session::save_template()
[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         XMLTree tree;
2032
2033         tree.set_root (&get_template());
2034         if (!tree.write (template_file_path)) {
2035                 error << _("template not saved") << endmsg;
2036                 return -1;
2037         }
2038
2039         /* copy plugin state directory */
2040
2041         std::string template_plugin_state_path (Glib::build_filename (template_dir_path, X_("plugins")));
2042
2043         if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2044                 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2045                                 template_plugin_state_path, g_strerror (errno)) << endmsg;
2046                 return -1;
2047         }
2048
2049         copy_recurse (plugins_dir(), template_plugin_state_path);
2050
2051         return 0;
2052 }
2053
2054 void
2055 Session::refresh_disk_space ()
2056 {
2057 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2058         
2059         Glib::Threads::Mutex::Lock lm (space_lock);
2060
2061         /* get freespace on every FS that is part of the session path */
2062
2063         _total_free_4k_blocks = 0;
2064         _total_free_4k_blocks_uncertain = false;
2065
2066         for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2067
2068                 struct statfs statfsbuf;
2069                 statfs (i->path.c_str(), &statfsbuf);
2070
2071                 double const scale = statfsbuf.f_bsize / 4096.0;
2072
2073                 /* See if this filesystem is read-only */
2074                 struct statvfs statvfsbuf;
2075                 statvfs (i->path.c_str(), &statvfsbuf);
2076
2077                 /* f_bavail can be 0 if it is undefined for whatever
2078                    filesystem we are looking at; Samba shares mounted
2079                    via GVFS are an example of this.
2080                 */
2081                 if (statfsbuf.f_bavail == 0) {
2082                         /* block count unknown */
2083                         i->blocks = 0;
2084                         i->blocks_unknown = true;
2085                 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2086                         /* read-only filesystem */
2087                         i->blocks = 0;
2088                         i->blocks_unknown = false;
2089                 } else {
2090                         /* read/write filesystem with known space */
2091                         i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2092                         i->blocks_unknown = false;
2093                 }
2094
2095                 _total_free_4k_blocks += i->blocks;
2096                 if (i->blocks_unknown) {
2097                         _total_free_4k_blocks_uncertain = true;
2098                 }
2099         }
2100 #elif defined PLATFORM_WINDOWS
2101         vector<string> scanned_volumes;
2102         vector<string>::iterator j;
2103         vector<space_and_path>::iterator i;
2104     DWORD nSectorsPerCluster, nBytesPerSector,
2105           nFreeClusters, nTotalClusters;
2106     char disk_drive[4];
2107         bool volume_found;
2108
2109         _total_free_4k_blocks = 0;
2110
2111         for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2112                 strncpy (disk_drive, (*i).path.c_str(), 3);
2113                 disk_drive[3] = 0;
2114                 strupr(disk_drive);
2115
2116                 volume_found = false;
2117                 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2118                 {
2119                         int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2120                         int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2121                         i->blocks = (uint32_t)(nFreeBytes / 4096);
2122
2123                         for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2124                                 if (0 == j->compare(disk_drive)) {
2125                                         volume_found = true;
2126                                         break;
2127                                 }
2128                         }
2129
2130                         if (!volume_found) {
2131                                 scanned_volumes.push_back(disk_drive);
2132                                 _total_free_4k_blocks += i->blocks;
2133                         }
2134                 }
2135         }
2136
2137         if (0 == _total_free_4k_blocks) {
2138                 strncpy (disk_drive, path().c_str(), 3);
2139                 disk_drive[3] = 0;
2140
2141                 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2142                 {
2143                         int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2144                         int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2145                         _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2146                 }
2147         }
2148 #endif
2149 }
2150
2151 string
2152 Session::get_best_session_directory_for_new_audio ()
2153 {
2154         vector<space_and_path>::iterator i;
2155         string result = _session_dir->root_path();
2156
2157         /* handle common case without system calls */
2158
2159         if (session_dirs.size() == 1) {
2160                 return result;
2161         }
2162
2163         /* OK, here's the algorithm we're following here:
2164
2165         We want to select which directory to use for
2166         the next file source to be created. Ideally,
2167         we'd like to use a round-robin process so as to
2168         get maximum performance benefits from splitting
2169         the files across multiple disks.
2170
2171         However, in situations without much diskspace, an
2172         RR approach may end up filling up a filesystem
2173         with new files while others still have space.
2174         Its therefore important to pay some attention to
2175         the freespace in the filesystem holding each
2176         directory as well. However, if we did that by
2177         itself, we'd keep creating new files in the file
2178         system with the most space until it was as full
2179         as all others, thus negating any performance
2180         benefits of this RAID-1 like approach.
2181
2182         So, we use a user-configurable space threshold. If
2183         there are at least 2 filesystems with more than this
2184         much space available, we use RR selection between them.
2185         If not, then we pick the filesystem with the most space.
2186
2187         This gets a good balance between the two
2188         approaches.
2189         */
2190
2191         refresh_disk_space ();
2192
2193         int free_enough = 0;
2194
2195         for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2196                 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2197                         free_enough++;
2198                 }
2199         }
2200
2201         if (free_enough >= 2) {
2202                 /* use RR selection process, ensuring that the one
2203                    picked works OK.
2204                 */
2205
2206                 i = last_rr_session_dir;
2207
2208                 do {
2209                         if (++i == session_dirs.end()) {
2210                                 i = session_dirs.begin();
2211                         }
2212
2213                         if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2214                                 SessionDirectory sdir(i->path);
2215                                 if (sdir.create ()) {
2216                                         result = (*i).path;
2217                                         last_rr_session_dir = i;
2218                                         return result;
2219                                 }
2220                         }
2221
2222                 } while (i != last_rr_session_dir);
2223
2224         } else {
2225
2226                 /* pick FS with the most freespace (and that
2227                    seems to actually work ...)
2228                 */
2229
2230                 vector<space_and_path> sorted;
2231                 space_and_path_ascending_cmp cmp;
2232
2233                 sorted = session_dirs;
2234                 sort (sorted.begin(), sorted.end(), cmp);
2235
2236                 for (i = sorted.begin(); i != sorted.end(); ++i) {
2237                         SessionDirectory sdir(i->path);
2238                         if (sdir.create ()) {
2239                                 result = (*i).path;
2240                                 last_rr_session_dir = i;
2241                                 return result;
2242                         }
2243                 }
2244         }
2245
2246         return result;
2247 }
2248
2249 string
2250 Session::automation_dir () const
2251 {
2252         return Glib::build_filename (_path, "automation");
2253 }
2254
2255 string
2256 Session::analysis_dir () const
2257 {
2258         return Glib::build_filename (_path, "analysis");
2259 }
2260
2261 string
2262 Session::plugins_dir () const
2263 {
2264         return Glib::build_filename (_path, "plugins");
2265 }
2266
2267 string
2268 Session::externals_dir () const
2269 {
2270         return Glib::build_filename (_path, "externals");
2271 }
2272
2273 int
2274 Session::load_bundles (XMLNode const & node)
2275 {
2276         XMLNodeList nlist = node.children();
2277         XMLNodeConstIterator niter;
2278
2279         set_dirty();
2280
2281         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2282                 if ((*niter)->name() == "InputBundle") {
2283                         add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2284                 } else if ((*niter)->name() == "OutputBundle") {
2285                         add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2286                 } else {
2287                         error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2288                         return -1;
2289                 }
2290         }
2291
2292         return 0;
2293 }
2294
2295 int
2296 Session::load_route_groups (const XMLNode& node, int version)
2297 {
2298         XMLNodeList nlist = node.children();
2299         XMLNodeConstIterator niter;
2300
2301         set_dirty ();
2302
2303         if (version >= 3000) {
2304
2305                 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2306                         if ((*niter)->name() == "RouteGroup") {
2307                                 RouteGroup* rg = new RouteGroup (*this, "");
2308                                 add_route_group (rg);
2309                                 rg->set_state (**niter, version);
2310                         }
2311                 }
2312
2313         } else if (version < 3000) {
2314
2315                 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2316                         if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2317                                 RouteGroup* rg = new RouteGroup (*this, "");
2318                                 add_route_group (rg);
2319                                 rg->set_state (**niter, version);
2320                         }
2321                 }
2322         }
2323
2324         return 0;
2325 }
2326
2327 static bool
2328 state_file_filter (const string &str, void* /*arg*/)
2329 {
2330         return (str.length() > strlen(statefile_suffix) &&
2331                 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2332 }
2333
2334 static string
2335 remove_end(string state)
2336 {
2337         string statename(state);
2338
2339         string::size_type start,end;
2340         if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2341                 statename = statename.substr (start+1);
2342         }
2343
2344         if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2345                 end = statename.length();
2346         }
2347
2348         return string(statename.substr (0, end));
2349 }
2350
2351 vector<string>
2352 Session::possible_states (string path)
2353 {
2354         vector<string> states;
2355         find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2356
2357         transform(states.begin(), states.end(), states.begin(), remove_end);
2358
2359         sort (states.begin(), states.end());
2360
2361         return states;
2362 }
2363
2364 vector<string>
2365 Session::possible_states () const
2366 {
2367         return possible_states(_path);
2368 }
2369
2370 void
2371 Session::add_route_group (RouteGroup* g)
2372 {
2373         _route_groups.push_back (g);
2374         route_group_added (g); /* EMIT SIGNAL */
2375
2376         g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2377         g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2378         g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2379
2380         set_dirty ();
2381 }
2382
2383 void
2384 Session::remove_route_group (RouteGroup& rg)
2385 {
2386         list<RouteGroup*>::iterator i;
2387
2388         if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2389                 _route_groups.erase (i);
2390                 delete &rg;
2391
2392                 route_group_removed (); /* EMIT SIGNAL */
2393         }
2394 }
2395
2396 /** Set a new order for our route groups, without adding or removing any.
2397  *  @param groups Route group list in the new order.
2398  */
2399 void
2400 Session::reorder_route_groups (list<RouteGroup*> groups)
2401 {
2402         _route_groups = groups;
2403
2404         route_groups_reordered (); /* EMIT SIGNAL */
2405         set_dirty ();
2406 }
2407
2408
2409 RouteGroup *
2410 Session::route_group_by_name (string name)
2411 {
2412         list<RouteGroup *>::iterator i;
2413
2414         for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2415                 if ((*i)->name() == name) {
2416                         return* i;
2417                 }
2418         }
2419         return 0;
2420 }
2421
2422 RouteGroup&
2423 Session::all_route_group() const
2424 {
2425         return *_all_route_group;
2426 }
2427
2428 void
2429 Session::add_commands (vector<Command*> const & cmds)
2430 {
2431         for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2432                 add_command (*i);
2433         }
2434 }
2435
2436 void
2437 Session::begin_reversible_command (const string& name)
2438 {
2439         begin_reversible_command (g_quark_from_string (name.c_str ()));
2440 }
2441
2442 /** Begin a reversible command using a GQuark to identify it.
2443  *  begin_reversible_command() and commit_reversible_command() calls may be nested,
2444  *  but there must be as many begin...()s as there are commit...()s.
2445  */
2446 void
2447 Session::begin_reversible_command (GQuark q)
2448 {
2449         /* If nested begin/commit pairs are used, we create just one UndoTransaction
2450            to hold all the commands that are committed.  This keeps the order of
2451            commands correct in the history.
2452         */
2453
2454         if (_current_trans == 0) {
2455                 /* start a new transaction */
2456                 assert (_current_trans_quarks.empty ());
2457                 _current_trans = new UndoTransaction();
2458                 _current_trans->set_name (g_quark_to_string (q));
2459         }
2460
2461         _current_trans_quarks.push_front (q);
2462 }
2463
2464 void
2465 Session::abort_reversible_command ()
2466 {
2467         if (_current_trans != 0) {
2468                 _current_trans->clear();
2469                 delete _current_trans;
2470                 _current_trans = 0;
2471                 _current_trans_quarks.clear();
2472         }
2473 }
2474
2475 void
2476 Session::commit_reversible_command (Command *cmd)
2477 {
2478         assert (_current_trans);
2479         assert (!_current_trans_quarks.empty ());
2480
2481         struct timeval now;
2482
2483         if (cmd) {
2484                 _current_trans->add_command (cmd);
2485         }
2486
2487         _current_trans_quarks.pop_front ();
2488
2489         if (!_current_trans_quarks.empty ()) {
2490                 /* the transaction we're committing is not the top-level one */
2491                 return;
2492         }
2493
2494         if (_current_trans->empty()) {
2495                 /* no commands were added to the transaction, so just get rid of it */
2496                 delete _current_trans;
2497                 _current_trans = 0;
2498                 return;
2499         }
2500
2501         gettimeofday (&now, 0);
2502         _current_trans->set_timestamp (now);
2503
2504         _history.add (_current_trans);
2505         _current_trans = 0;
2506 }
2507
2508 static bool
2509 accept_all_audio_files (const string& path, void* /*arg*/)
2510 {
2511         if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2512                 return false;
2513         }
2514
2515         if (!AudioFileSource::safe_audio_file_extension (path)) {
2516                 return false;
2517         }
2518
2519         return true;
2520 }
2521
2522 static bool
2523 accept_all_midi_files (const string& path, void* /*arg*/)
2524 {
2525         if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2526                 return false;
2527         }
2528
2529         return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2530                 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2531                 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2532 }
2533
2534 static bool
2535 accept_all_state_files (const string& path, void* /*arg*/)
2536 {
2537         if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2538                 return false;
2539         }
2540
2541         std::string const statefile_ext (statefile_suffix);
2542         if (path.length() >= statefile_ext.length()) {
2543                 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2544         } else {
2545                 return false;
2546         }
2547 }
2548
2549 int
2550 Session::find_all_sources (string path, set<string>& result)
2551 {
2552         XMLTree tree;
2553         XMLNode* node;
2554
2555         if (!tree.read (path)) {
2556                 return -1;
2557         }
2558
2559         if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2560                 return -2;
2561         }
2562
2563         XMLNodeList nlist;
2564         XMLNodeConstIterator niter;
2565
2566         nlist = node->children();
2567
2568         set_dirty();
2569
2570         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2571
2572                 XMLProperty* prop;
2573
2574                 if ((prop = (*niter)->property (X_("type"))) == 0) {
2575                         continue;
2576                 }
2577
2578                 DataType type (prop->value());
2579
2580                 if ((prop = (*niter)->property (X_("name"))) == 0) {
2581                         continue;
2582                 }
2583
2584                 if (Glib::path_is_absolute (prop->value())) {
2585                         /* external file, ignore */
2586                         continue;
2587                 }
2588
2589                 string found_path;
2590                 bool is_new;
2591                 uint16_t chan;
2592
2593                 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2594                         result.insert (found_path);
2595                 }
2596         }
2597
2598         return 0;
2599 }
2600
2601 int
2602 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2603 {
2604         vector<string> state_files;
2605         string ripped;
2606         string this_snapshot_path;
2607
2608         result.clear ();
2609
2610         ripped = _path;
2611
2612         if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2613                 ripped = ripped.substr (0, ripped.length() - 1);
2614         }
2615
2616         find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2617
2618         if (state_files.empty()) {
2619                 /* impossible! */
2620                 return 0;
2621         }
2622
2623         this_snapshot_path = _path;
2624         this_snapshot_path += legalize_for_path (_current_snapshot_name);
2625         this_snapshot_path += statefile_suffix;
2626
2627         for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2628
2629                 if (exclude_this_snapshot && *i == this_snapshot_path) {
2630                         continue;
2631                 }
2632
2633                 if (find_all_sources (*i, result) < 0) {
2634                         return -1;
2635                 }
2636         }
2637
2638         return 0;
2639 }
2640
2641 struct RegionCounter {
2642     typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2643     AudioSourceList::iterator iter;
2644     boost::shared_ptr<Region> region;
2645     uint32_t count;
2646
2647     RegionCounter() : count (0) {}
2648 };
2649
2650 int
2651 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2652 {
2653         boost::optional<int> r = AskAboutPlaylistDeletion (p);
2654         return r.get_value_or (1);
2655 }
2656
2657 void
2658 Session::cleanup_regions ()
2659 {
2660         bool removed = false;
2661         const RegionFactory::RegionMap& regions (RegionFactory::regions());
2662
2663         for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2664
2665                 uint32_t used = playlists->region_use_count (i->second);
2666
2667                 if (used == 0 && !i->second->automatic ()) {
2668                         removed = true;
2669                         RegionFactory::map_remove (i->second);
2670                 }
2671         }
2672
2673         if (removed) {
2674                 // re-check to remove parent references of compound regions
2675                 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2676                         if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2677                                 continue;
2678                         }
2679                         assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2680                         if (0 == playlists->region_use_count (i->second)) {
2681                                 RegionFactory::map_remove (i->second);
2682                         }
2683                 }
2684         }
2685
2686         /* dump the history list */
2687         _history.clear ();
2688
2689         save_state ("");
2690 }
2691
2692 int
2693 Session::cleanup_sources (CleanupReport& rep)
2694 {
2695         // FIXME: needs adaptation to midi
2696
2697         vector<boost::shared_ptr<Source> > dead_sources;
2698         string audio_path;
2699         string midi_path;
2700         vector<string> candidates;
2701         vector<string> unused;
2702         set<string> all_sources;
2703         bool used;
2704         string spath;
2705         int ret = -1;
2706         string tmppath1;
2707         string tmppath2;
2708         Searchpath asp;
2709         Searchpath msp;
2710
2711         _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2712
2713         /* consider deleting all unused playlists */
2714
2715         if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2716                 ret = 0;
2717                 goto out;
2718         }
2719
2720         /* sync the "all regions" property of each playlist with its current state
2721          */
2722
2723         playlists->sync_all_regions_with_regions ();
2724
2725         /* find all un-used sources */
2726
2727         rep.paths.clear ();
2728         rep.space = 0;
2729
2730         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2731
2732                 SourceMap::iterator tmp;
2733
2734                 tmp = i;
2735                 ++tmp;
2736
2737                 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2738                    capture files.
2739                 */
2740
2741                 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2742                         dead_sources.push_back (i->second);
2743                         i->second->drop_references ();
2744                 }
2745
2746                 i = tmp;
2747         }
2748
2749         /* build a list of all the possible audio directories for the session */
2750
2751         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2752                 SessionDirectory sdir ((*i).path);
2753                 asp += sdir.sound_path();
2754         }
2755         audio_path += asp.to_string();
2756
2757
2758         /* build a list of all the possible midi directories for the session */
2759
2760         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2761                 SessionDirectory sdir ((*i).path);
2762                 msp += sdir.midi_path();
2763         }
2764         midi_path += msp.to_string();
2765
2766         find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2767         find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2768
2769         /* find all sources, but don't use this snapshot because the
2770            state file on disk still references sources we may have already
2771            dropped.
2772         */
2773
2774         find_all_sources_across_snapshots (all_sources, true);
2775
2776         /*  add our current source list
2777          */
2778
2779         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2780                 boost::shared_ptr<FileSource> fs;
2781                 SourceMap::iterator tmp = i;
2782                 ++tmp;
2783
2784                 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2785
2786                         if (!fs->is_stub()) {
2787
2788                                 if (playlists->source_use_count (fs) != 0) {
2789                                         all_sources.insert (fs->path());
2790                                 } else {
2791                                         
2792                                         /* we might not remove this source from disk, because it may be used
2793                                            by other snapshots, but its not being used in this version
2794                                            so lets get rid of it now, along with any representative regions
2795                                            in the region list.
2796                                         */
2797                                         
2798                                         RegionFactory::remove_regions_using_source (i->second);
2799                                         sources.erase (i);
2800                                         
2801                                         // also remove source from all_sources
2802                                         
2803                                         for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
2804                                                 spath = Glib::path_get_basename (*j);
2805                                                 if ( spath == i->second->name () ) {
2806                                                         all_sources.erase (j);
2807                                                         break;
2808                                                 }
2809                                         }
2810                                 }
2811                         }
2812                 }
2813
2814                 i = tmp;
2815         }
2816
2817         for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2818
2819                 used = false;
2820                 spath = *x;
2821
2822                 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2823
2824                         tmppath1 = canonical_path (spath);
2825                         tmppath2 = canonical_path ((*i));
2826
2827                         if (tmppath1 == tmppath2) {
2828                                 used = true;
2829                                 break;
2830                         }
2831                 }
2832
2833                 if (!used) {
2834                         unused.push_back (spath);
2835                 }
2836         }
2837
2838         /* now try to move all unused files into the "dead" directory(ies) */
2839
2840         for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2841                 struct stat statbuf;
2842
2843                 string newpath;
2844
2845                 /* don't move the file across filesystems, just
2846                    stick it in the `dead_dir_name' directory
2847                    on whichever filesystem it was already on.
2848                 */
2849
2850                 if ((*x).find ("/sounds/") != string::npos) {
2851
2852                         /* old school, go up 1 level */
2853
2854                         newpath = Glib::path_get_dirname (*x);      // "sounds"
2855                         newpath = Glib::path_get_dirname (newpath); // "session-name"
2856
2857                 } else {
2858
2859                         /* new school, go up 4 levels */
2860
2861                         newpath = Glib::path_get_dirname (*x);      // "audiofiles" or "midifiles"
2862                         newpath = Glib::path_get_dirname (newpath); // "session-name"
2863                         newpath = Glib::path_get_dirname (newpath); // "interchange"
2864                         newpath = Glib::path_get_dirname (newpath); // "session-dir"
2865                 }
2866
2867                 newpath = Glib::build_filename (newpath, dead_dir_name);
2868
2869                 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2870                         error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2871                         return -1;
2872                 }
2873
2874                 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2875
2876                 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2877
2878                         /* the new path already exists, try versioning */
2879
2880                         char buf[PATH_MAX+1];
2881                         int version = 1;
2882                         string newpath_v;
2883
2884                         snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2885                         newpath_v = buf;
2886
2887                         while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2888                                 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2889                                 newpath_v = buf;
2890                         }
2891
2892                         if (version == 999) {
2893                                 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2894                                                   newpath)
2895                                       << endmsg;
2896                         } else {
2897                                 newpath = newpath_v;
2898                         }
2899
2900                 } else {
2901
2902                         /* it doesn't exist, or we can't read it or something */
2903
2904                 }
2905
2906                 stat ((*x).c_str(), &statbuf);
2907
2908                 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2909                         error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2910                                           (*x), newpath, strerror (errno))
2911                               << endmsg;
2912                         goto out;
2913                 }
2914
2915                 /* see if there an easy to find peakfile for this file, and remove it.
2916                  */
2917
2918                 string base = basename_nosuffix (*x);
2919                 base += "%A"; /* this is what we add for the channel suffix of all native files,
2920                                  or for the first channel of embedded files. it will miss
2921                                  some peakfiles for other channels
2922                               */
2923                 string peakpath = peak_path (base);
2924
2925                 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2926                         if (::g_unlink (peakpath.c_str()) != 0) {
2927                                 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2928                                                          peakpath, _path, strerror (errno))
2929                                       << endmsg;
2930                                 /* try to back out */
2931                                 ::rename (newpath.c_str(), _path.c_str());
2932                                 goto out;
2933                         }
2934                 }
2935
2936                 rep.paths.push_back (*x);
2937                 rep.space += statbuf.st_size;
2938         }
2939
2940         /* dump the history list */
2941
2942         _history.clear ();
2943
2944         /* save state so we don't end up a session file
2945            referring to non-existent sources.
2946         */
2947
2948         save_state ("");
2949         ret = 0;
2950
2951   out:
2952         _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2953
2954         return ret;
2955 }
2956
2957 int
2958 Session::cleanup_trash_sources (CleanupReport& rep)
2959 {
2960         // FIXME: needs adaptation for MIDI
2961
2962         vector<space_and_path>::iterator i;
2963         string dead_dir;
2964
2965         rep.paths.clear ();
2966         rep.space = 0;
2967
2968         for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2969
2970                 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2971
2972                 clear_directory (dead_dir, &rep.space, &rep.paths);
2973         }
2974
2975         return 0;
2976 }
2977
2978 void
2979 Session::set_dirty ()
2980 {
2981         /* never mark session dirty during loading */
2982
2983         if (_state_of_the_state & Loading) {
2984                 return;
2985         }
2986
2987         bool was_dirty = dirty();
2988
2989         _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2990
2991
2992         if (!was_dirty) {
2993                 DirtyChanged(); /* EMIT SIGNAL */
2994         }
2995 }
2996
2997
2998 void
2999 Session::set_clean ()
3000 {
3001         bool was_dirty = dirty();
3002
3003         _state_of_the_state = Clean;
3004
3005
3006         if (was_dirty) {
3007                 DirtyChanged(); /* EMIT SIGNAL */
3008         }
3009 }
3010
3011 void
3012 Session::set_deletion_in_progress ()
3013 {
3014         _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3015 }
3016
3017 void
3018 Session::clear_deletion_in_progress ()
3019 {
3020         _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3021 }
3022
3023 void
3024 Session::add_controllable (boost::shared_ptr<Controllable> c)
3025 {
3026         /* this adds a controllable to the list managed by the Session.
3027            this is a subset of those managed by the Controllable class
3028            itself, and represents the only ones whose state will be saved
3029            as part of the session.
3030         */
3031
3032         Glib::Threads::Mutex::Lock lm (controllables_lock);
3033         controllables.insert (c);
3034 }
3035
3036 struct null_deleter { void operator()(void const *) const {} };
3037
3038 void
3039 Session::remove_controllable (Controllable* c)
3040 {
3041         if (_state_of_the_state & Deletion) {
3042                 return;
3043         }
3044
3045         Glib::Threads::Mutex::Lock lm (controllables_lock);
3046
3047         Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3048
3049         if (x != controllables.end()) {
3050                 controllables.erase (x);
3051         }
3052 }
3053
3054 boost::shared_ptr<Controllable>
3055 Session::controllable_by_id (const PBD::ID& id)
3056 {
3057         Glib::Threads::Mutex::Lock lm (controllables_lock);
3058
3059         for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3060                 if ((*i)->id() == id) {
3061                         return *i;
3062                 }
3063         }
3064
3065         return boost::shared_ptr<Controllable>();
3066 }
3067
3068 boost::shared_ptr<Controllable>
3069 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3070 {
3071         boost::shared_ptr<Controllable> c;
3072         boost::shared_ptr<Route> r;
3073
3074         switch (desc.top_level_type()) {
3075         case ControllableDescriptor::NamedRoute:
3076         {
3077                 std::string str = desc.top_level_name();
3078                 if (str == "Master" || str == "master") {
3079                         r = _master_out;
3080                 } else if (str == "control" || str == "listen") {
3081                         r = _monitor_out;
3082                 } else {
3083                         r = route_by_name (desc.top_level_name());
3084                 }
3085                 break;
3086         }
3087
3088         case ControllableDescriptor::RemoteControlID:
3089                 r = route_by_remote_id (desc.rid());
3090                 break;
3091         }
3092
3093         if (!r) {
3094                 return c;
3095         }
3096
3097         switch (desc.subtype()) {
3098         case ControllableDescriptor::Gain:
3099                 c = r->gain_control ();
3100                 break;
3101
3102         case ControllableDescriptor::Trim:
3103                 c = r->trim()->gain_control ();
3104                 break;
3105
3106         case ControllableDescriptor::Solo:
3107                 c = r->solo_control();
3108                 break;
3109
3110         case ControllableDescriptor::Mute:
3111                 c = r->mute_control();
3112                 break;
3113
3114         case ControllableDescriptor::Recenable:
3115         {
3116                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3117
3118                 if (t) {
3119                         c = t->rec_enable_control ();
3120                 }
3121                 break;
3122         }
3123
3124         case ControllableDescriptor::PanDirection:
3125         {
3126                 c = r->pannable()->pan_azimuth_control;
3127                 break;
3128         }
3129
3130         case ControllableDescriptor::PanWidth:
3131         {
3132                 c = r->pannable()->pan_width_control;
3133                 break;
3134         }
3135
3136         case ControllableDescriptor::PanElevation:
3137         {
3138                 c = r->pannable()->pan_elevation_control;
3139                 break;
3140         }
3141
3142         case ControllableDescriptor::Balance:
3143                 /* XXX simple pan control */
3144                 break;
3145
3146         case ControllableDescriptor::PluginParameter:
3147         {
3148                 uint32_t plugin = desc.target (0);
3149                 uint32_t parameter_index = desc.target (1);
3150
3151                 /* revert to zero based counting */
3152
3153                 if (plugin > 0) {
3154                         --plugin;
3155                 }
3156
3157                 if (parameter_index > 0) {
3158                         --parameter_index;
3159                 }
3160
3161                 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3162
3163                 if (p) {
3164                         c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3165                                 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3166                 }
3167                 break;
3168         }
3169
3170         case ControllableDescriptor::SendGain:
3171         {
3172                 uint32_t send = desc.target (0);
3173
3174                 /* revert to zero-based counting */
3175
3176                 if (send > 0) {
3177                         --send;
3178                 }
3179
3180                 boost::shared_ptr<Processor> p = r->nth_send (send);
3181
3182                 if (p) {
3183                         boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3184                         boost::shared_ptr<Amp> a = s->amp();
3185                         
3186                         if (a) {
3187                                 c = s->amp()->gain_control();
3188                         }
3189                 }
3190                 break;
3191         }
3192
3193         default:
3194                 /* relax and return a null pointer */
3195                 break;
3196         }
3197
3198         return c;
3199 }
3200
3201 void
3202 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3203 {
3204         if (_writable) {
3205                 Stateful::add_instant_xml (node, _path);
3206         }
3207
3208         if (write_to_config) {
3209                 Config->add_instant_xml (node);
3210         }
3211 }
3212
3213 XMLNode*
3214 Session::instant_xml (const string& node_name)
3215 {
3216         return Stateful::instant_xml (node_name, _path);
3217 }
3218
3219 int
3220 Session::save_history (string snapshot_name)
3221 {
3222         XMLTree tree;
3223
3224         if (!_writable) {
3225                 return 0;
3226         }
3227
3228         if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 || 
3229             (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3230                 return 0;
3231         }
3232
3233         if (snapshot_name.empty()) {
3234                 snapshot_name = _current_snapshot_name;
3235         }
3236
3237         const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3238         const string backup_filename = history_filename + backup_suffix;
3239         const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3240         const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3241
3242         if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3243                 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3244                         error << _("could not backup old history file, current history not saved") << endmsg;
3245                         return -1;
3246                 }
3247         }
3248
3249         tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3250
3251         if (!tree.write (xml_path))
3252         {
3253                 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3254
3255                 if (g_remove (xml_path.c_str()) != 0) {
3256                         error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3257                                         xml_path, g_strerror (errno)) << endmsg;
3258                 }
3259                 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3260                         error << string_compose (_("could not restore history file from backup %1 (%2)"),
3261                                         backup_path, g_strerror (errno)) << endmsg;
3262                 }
3263
3264                 return -1;
3265         }
3266
3267         return 0;
3268 }
3269
3270 int
3271 Session::restore_history (string snapshot_name)
3272 {
3273         XMLTree tree;
3274
3275         if (snapshot_name.empty()) {
3276                 snapshot_name = _current_snapshot_name;
3277         }
3278
3279         const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3280         const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3281
3282         info << "Loading history from " << xml_path << endmsg;
3283
3284         if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3285                 info << string_compose (_("%1: no history file \"%2\" for this session."),
3286                                 _name, xml_path) << endmsg;
3287                 return 1;
3288         }
3289
3290         if (!tree.read (xml_path)) {
3291                 error << string_compose (_("Could not understand session history file \"%1\""),
3292                                 xml_path) << endmsg;
3293                 return -1;
3294         }
3295
3296         // replace history
3297         _history.clear();
3298
3299         for (XMLNodeConstIterator it  = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3300
3301                 XMLNode *t = *it;
3302                 UndoTransaction* ut = new UndoTransaction ();
3303                 struct timeval tv;
3304
3305                 ut->set_name(t->property("name")->value());
3306                 stringstream ss(t->property("tv-sec")->value());
3307                 ss >> tv.tv_sec;
3308                 ss.str(t->property("tv-usec")->value());
3309                 ss >> tv.tv_usec;
3310                 ut->set_timestamp(tv);
3311
3312                 for (XMLNodeConstIterator child_it  = t->children().begin();
3313                                 child_it != t->children().end(); child_it++)
3314                 {
3315                         XMLNode *n = *child_it;
3316                         Command *c;
3317
3318                         if (n->name() == "MementoCommand" ||
3319                                         n->name() == "MementoUndoCommand" ||
3320                                         n->name() == "MementoRedoCommand") {
3321
3322                                 if ((c = memento_command_factory(n))) {
3323                                         ut->add_command(c);
3324                                 }
3325
3326                         } else if (n->name() == "NoteDiffCommand") {
3327                                 PBD::ID id (n->property("midi-source")->value());
3328                                 boost::shared_ptr<MidiSource> midi_source =
3329                                         boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3330                                 if (midi_source) {
3331                                         ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3332                                 } else {
3333                                         error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3334                                 }
3335
3336                         } else if (n->name() == "SysExDiffCommand") {
3337
3338                                 PBD::ID id (n->property("midi-source")->value());
3339                                 boost::shared_ptr<MidiSource> midi_source =
3340                                         boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3341                                 if (midi_source) {
3342                                         ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3343                                 } else {
3344                                         error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3345                                 }
3346
3347                         } else if (n->name() == "PatchChangeDiffCommand") {
3348
3349                                 PBD::ID id (n->property("midi-source")->value());
3350                                 boost::shared_ptr<MidiSource> midi_source =
3351                                         boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3352                                 if (midi_source) {
3353                                         ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3354                                 } else {
3355                                         error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3356                                 }
3357
3358                         } else if (n->name() == "StatefulDiffCommand") {
3359                                 if ((c = stateful_diff_command_factory (n))) {
3360                                         ut->add_command (c);
3361                                 }
3362                         } else {
3363                                 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3364                         }
3365                 }
3366
3367                 _history.add (ut);
3368         }
3369
3370         return 0;
3371 }
3372
3373 void
3374 Session::config_changed (std::string p, bool ours)
3375 {
3376         if (ours) {
3377                 set_dirty ();
3378         }
3379
3380         if (p == "seamless-loop") {
3381
3382         } else if (p == "rf-speed") {
3383
3384         } else if (p == "auto-loop") {
3385
3386         } else if (p == "auto-input") {
3387
3388                 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3389                         /* auto-input only makes a difference if we're rolling */
3390                         set_track_monitor_input_status (!config.get_auto_input());
3391                 }
3392
3393         } else if (p == "punch-in") {
3394
3395                 Location* location;
3396
3397                 if ((location = _locations->auto_punch_location()) != 0) {
3398
3399                         if (config.get_punch_in ()) {
3400                                 replace_event (SessionEvent::PunchIn, location->start());
3401                         } else {
3402                                 remove_event (location->start(), SessionEvent::PunchIn);
3403                         }
3404                 }
3405
3406         } else if (p == "punch-out") {
3407
3408                 Location* location;
3409
3410                 if ((location = _locations->auto_punch_location()) != 0) {
3411
3412                         if (config.get_punch_out()) {
3413                                 replace_event (SessionEvent::PunchOut, location->end());
3414                         } else {
3415                                 clear_events (SessionEvent::PunchOut);
3416                         }
3417                 }
3418
3419         } else if (p == "edit-mode") {
3420
3421                 Glib::Threads::Mutex::Lock lm (playlists->lock);
3422
3423                 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3424                         (*i)->set_edit_mode (Config->get_edit_mode ());
3425                 }
3426
3427         } else if (p == "use-video-sync") {
3428
3429                 waiting_for_sync_offset = config.get_use_video_sync();
3430
3431         } else if (p == "mmc-control") {
3432
3433                 //poke_midi_thread ();
3434
3435         } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3436
3437                 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3438
3439         } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3440
3441                 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3442
3443         } else if (p == "midi-control") {
3444
3445                 //poke_midi_thread ();
3446
3447         } else if (p == "raid-path") {
3448
3449                 setup_raid_path (config.get_raid_path());
3450
3451         } else if (p == "timecode-format") {
3452
3453                 sync_time_vars ();
3454
3455         } else if (p == "video-pullup") {
3456
3457                 sync_time_vars ();
3458
3459         } else if (p == "seamless-loop") {
3460
3461                 if (play_loop && transport_rolling()) {
3462                         // to reset diskstreams etc
3463                         request_play_loop (true);
3464                 }
3465
3466         } else if (p == "rf-speed") {
3467
3468                 cumulative_rf_motion = 0;
3469                 reset_rf_scale (0);
3470
3471         } else if (p == "click-sound") {
3472
3473                 setup_click_sounds (1);
3474
3475         } else if (p == "click-emphasis-sound") {
3476
3477                 setup_click_sounds (-1);
3478
3479         } else if (p == "clicking") {
3480
3481                 if (Config->get_clicking()) {
3482                         if (_click_io && click_data) { // don't require emphasis data
3483                                 _clicking = true;
3484                         }
3485                 } else {
3486                         _clicking = false;
3487                 }
3488
3489         } else if (p == "click-gain") {
3490                 
3491                 if (_click_gain) {
3492                         _click_gain->set_gain (Config->get_click_gain(), this);
3493                 }
3494
3495         } else if (p == "send-mtc") {
3496
3497                 if (Config->get_send_mtc ()) {
3498                         /* mark us ready to send */
3499                         next_quarter_frame_to_send = 0;
3500                 }
3501
3502         } else if (p == "send-mmc") {
3503
3504                 _mmc->enable_send (Config->get_send_mmc ());
3505
3506         } else if (p == "midi-feedback") {
3507
3508                 session_midi_feedback = Config->get_midi_feedback();
3509
3510         } else if (p == "jack-time-master") {
3511
3512                 engine().reset_timebase ();
3513
3514         } else if (p == "native-file-header-format") {
3515
3516                 if (!first_file_header_format_reset) {
3517                         reset_native_file_format ();
3518                 }
3519
3520                 first_file_header_format_reset = false;
3521
3522         } else if (p == "native-file-data-format") {
3523
3524                 if (!first_file_data_format_reset) {
3525                         reset_native_file_format ();
3526                 }
3527
3528                 first_file_data_format_reset = false;
3529
3530         } else if (p == "external-sync") {
3531                 if (!config.get_external_sync()) {
3532                         drop_sync_source ();
3533                 } else {
3534                         switch_to_sync_source (Config->get_sync_source());
3535                 }
3536         }  else if (p == "denormal-model") {
3537                 setup_fpu ();
3538         } else if (p == "history-depth") {
3539                 set_history_depth (Config->get_history_depth());
3540         } else if (p == "remote-model") {
3541                 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3542                    TO SET REMOTE ID'S
3543                 */
3544         } else if (p == "initial-program-change") {
3545
3546                 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3547                         MIDI::byte buf[2];
3548
3549                         buf[0] = MIDI::program; // channel zero by default
3550                         buf[1] = (Config->get_initial_program_change() & 0x7f);
3551
3552                         _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3553                 }
3554         } else if (p == "solo-mute-override") {
3555                 // catch_up_on_solo_mute_override ();
3556         } else if (p == "listen-position" || p == "pfl-position") {
3557                 listen_position_changed ();
3558         } else if (p == "solo-control-is-listen-control") {
3559                 solo_control_mode_changed ();
3560         } else if (p == "solo-mute-gain") {
3561                 _solo_cut_control->Changed();
3562         } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3563                 last_timecode_valid = false;
3564         } else if (p == "playback-buffer-seconds") {
3565                 AudioSource::allocate_working_buffers (frame_rate());
3566         } else if (p == "ltc-source-port") {
3567                 reconnect_ltc_input ();
3568         } else if (p == "ltc-sink-port") {
3569                 reconnect_ltc_output ();
3570         } else if (p == "timecode-generator-offset") {
3571                 ltc_tx_parse_offset();
3572         }
3573
3574         set_dirty ();
3575 }
3576
3577 void
3578 Session::set_history_depth (uint32_t d)
3579 {
3580         _history.set_depth (d);
3581 }
3582
3583 int
3584 Session::load_diskstreams_2X (XMLNode const & node, int)
3585 {
3586         XMLNodeList          clist;
3587         XMLNodeConstIterator citer;
3588
3589         clist = node.children();
3590
3591         for (citer = clist.begin(); citer != clist.end(); ++citer) {
3592
3593                 try {
3594                         /* diskstreams added automatically by DiskstreamCreated handler */
3595                         if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3596                                 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3597                                 _diskstreams_2X.push_back (dsp);
3598                         } else {
3599                                 error << _("Session: unknown diskstream type in XML") << endmsg;
3600                         }
3601                 }
3602
3603                 catch (failed_constructor& err) {
3604                         error << _("Session: could not load diskstream via XML state") << endmsg;
3605                         return -1;
3606                 }
3607         }
3608
3609         return 0;
3610 }
3611
3612 /** Connect things to the MMC object */
3613 void
3614 Session::setup_midi_machine_control ()
3615 {
3616         _mmc = new MIDI::MachineControl;
3617         _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3618
3619         _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3620         _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3621         _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3622         _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3623         _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3624         _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3625         _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3626         _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3627         _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3628         _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3629         _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3630         _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3631         _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3632
3633         /* also handle MIDI SPP because its so common */
3634
3635         _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3636         _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3637         _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3638 }
3639
3640 boost::shared_ptr<Controllable>
3641 Session::solo_cut_control() const
3642 {
3643         /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3644            controls in Ardour that currently get presented to the user in the GUI that require
3645            access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3646
3647            its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3648            it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3649            parameter.
3650         */
3651
3652         return _solo_cut_control;
3653 }
3654
3655 int
3656 Session::rename (const std::string& new_name)
3657 {
3658         string legal_name = legalize_for_path (new_name);
3659         string new_path;
3660         string oldstr;
3661         string newstr;
3662         bool first = true;
3663
3664         string const old_sources_root = _session_dir->sources_root();
3665
3666         if (!_writable || (_state_of_the_state & CannotSave)) {
3667                 error << _("Cannot rename read-only session.") << endmsg;
3668                 return 0; // don't show "messed up" warning
3669         }
3670         if (record_status() == Recording) {
3671                 error << _("Cannot rename session while recording") << endmsg;
3672                 return 0; // don't show "messed up" warning
3673         }
3674
3675         StateProtector stp (this);
3676
3677         /* Rename:
3678
3679          * session directory
3680          * interchange subdirectory
3681          * session file
3682          * session history
3683          
3684          * Backup files are left unchanged and not renamed.
3685          */
3686
3687         /* Windows requires that we close all files before attempting the
3688          * rename. This works on other platforms, but isn't necessary there.
3689          * Leave it in place for all platforms though, since it may help
3690          * catch issues that could arise if the way Source files work ever
3691          * change (since most developers are not using Windows).
3692          */
3693
3694         for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3695                 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3696                 if (fs) {
3697                         fs->close ();
3698                 }
3699         }
3700         
3701         /* pass one: not 100% safe check that the new directory names don't
3702          * already exist ...
3703          */
3704
3705         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3706                 
3707                 oldstr = (*i).path;
3708                 
3709                 /* this is a stupid hack because Glib::path_get_dirname() is
3710                  * lexical-only, and so passing it /a/b/c/ gives a different
3711                  * result than passing it /a/b/c ...
3712                  */
3713                 
3714                 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3715                         oldstr = oldstr.substr (0, oldstr.length() - 1);
3716                 }
3717                 
3718                 string base = Glib::path_get_dirname (oldstr);
3719                 
3720                 newstr = Glib::build_filename (base, legal_name);
3721                 
3722                 cerr << "Looking for " << newstr << endl;
3723                 
3724                 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3725                         cerr << " exists\n";
3726                         return -1;
3727                 }
3728         }
3729
3730         /* Session dirs */
3731
3732         first = true;
3733         
3734         for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3735
3736                 vector<string> v;
3737
3738                 oldstr = (*i).path;
3739                 
3740                 /* this is a stupid hack because Glib::path_get_dirname() is
3741                  * lexical-only, and so passing it /a/b/c/ gives a different
3742                  * result than passing it /a/b/c ...
3743                  */
3744                 
3745                 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3746                         oldstr = oldstr.substr (0, oldstr.length() - 1);
3747                 }
3748
3749                 string base = Glib::path_get_dirname (oldstr);
3750                 newstr = Glib::build_filename (base, legal_name);
3751
3752                 cerr << "for " << oldstr << " new dir = " << newstr << endl;
3753                 
3754                 cerr << "Rename " << oldstr << " => " << newstr << endl;                
3755                 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3756                         cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3757                         error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3758                         return 1;
3759                 }
3760
3761                 /* Reset path in "session dirs" */
3762                 
3763                 (*i).path = newstr;
3764                 (*i).blocks = 0;
3765                 
3766                 /* reset primary SessionDirectory object */
3767                 
3768                 if (first) {
3769                         (*_session_dir) = newstr;
3770                         new_path = newstr;
3771                         first = false;
3772                 }
3773
3774                 /* now rename directory below session_dir/interchange */
3775
3776                 string old_interchange_dir;
3777                 string new_interchange_dir;
3778
3779                 /* use newstr here because we renamed the path
3780                  * (folder/directory) that used to be oldstr to newstr above 
3781                  */     
3782                 
3783                 v.push_back (newstr); 
3784                 v.push_back (interchange_dir_name);
3785                 v.push_back (Glib::path_get_basename (oldstr));
3786
3787                 old_interchange_dir = Glib::build_filename (v);
3788
3789                 v.clear ();
3790                 v.push_back (newstr);
3791                 v.push_back (interchange_dir_name);
3792                 v.push_back (legal_name);
3793                 
3794                 new_interchange_dir = Glib::build_filename (v);
3795                 
3796                 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
3797                 
3798                 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
3799                         cerr << string_compose (_("renaming %s as %2 failed (%3)"),
3800                                                  old_interchange_dir, new_interchange_dir,
3801                                                  g_strerror (errno))
3802                               << endl;
3803                         error << string_compose (_("renaming %s as %2 failed (%3)"),
3804                                                  old_interchange_dir, new_interchange_dir,
3805                                                  g_strerror (errno))
3806                               << endmsg;
3807                         return 1;
3808                 }
3809         }
3810
3811         /* state file */
3812         
3813         oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
3814         newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
3815         
3816         cerr << "Rename " << oldstr << " => " << newstr << endl;                
3817
3818         if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3819                 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3820                 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3821                 return 1;
3822         }
3823
3824         /* history file */
3825         
3826         oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
3827
3828         if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS))  {
3829                 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
3830                 
3831                 cerr << "Rename " << oldstr << " => " << newstr << endl;                
3832                 
3833                 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3834                         cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3835                         error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3836                         return 1;
3837                 }
3838         }
3839
3840         /* remove old name from recent sessions */
3841         remove_recent_sessions (_path);
3842         _path = new_path;
3843         
3844         /* update file source paths */
3845         
3846         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3847                 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3848                 if (fs) {
3849                         string p = fs->path ();
3850                         boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3851                         fs->set_path (p);
3852                         SourceFactory::setup_peakfile(i->second, true);
3853                 }
3854         }
3855
3856         _current_snapshot_name = new_name;
3857         _name = new_name;
3858         
3859         set_dirty ();
3860
3861         /* save state again to get everything just right */
3862
3863         save_state (_current_snapshot_name);
3864
3865         /* add to recent sessions */
3866
3867         store_recent_sessions (new_name, _path);
3868
3869         return 0;
3870 }
3871
3872 int
3873 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3874 {
3875         if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3876                 return -1;
3877         }
3878
3879         if (!tree.read (xmlpath)) {
3880                 return -1;
3881         }
3882
3883         return 0;
3884 }
3885
3886 int
3887 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3888 {
3889         XMLTree tree;
3890         bool found_sr = false;
3891         bool found_data_format = false;
3892
3893         if (get_session_info_from_path (tree, xmlpath)) {
3894                 return -1;
3895         }
3896
3897         /* sample rate */
3898
3899         const XMLProperty* prop;
3900         if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {          
3901                 sample_rate = atoi (prop->value());
3902                 found_sr = true;
3903         }
3904
3905         const XMLNodeList& children (tree.root()->children());
3906         for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3907                 const XMLNode* child = *c;
3908                 if (child->name() == "Config") {
3909                         const XMLNodeList& options (child->children());
3910                         for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3911                                 const XMLNode* option = *oc;
3912                                 const XMLProperty* name = option->property("name");
3913
3914                                 if (!name) {
3915                                         continue;
3916                                 }
3917
3918                                 if (name->value() == "native-file-data-format") {
3919                                         const XMLProperty* value = option->property ("value");
3920                                         if (value) {
3921                                                 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3922                                                 data_format = fmt;
3923                                                 found_data_format = true;
3924                                                 break;
3925                                         }
3926                                 }
3927                         }
3928                 }
3929                 if (found_data_format) {
3930                         break;
3931                 }
3932         }
3933
3934         return !(found_sr && found_data_format); // zero if they are both found
3935 }
3936
3937 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
3938 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
3939
3940 int
3941 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
3942 {
3943         uint32_t total = 0;
3944         uint32_t n = 0;
3945         SourcePathMap source_path_map;
3946         string new_path;
3947         boost::shared_ptr<AudioFileSource> afs;
3948         int ret = 0;
3949
3950         {
3951
3952                 Glib::Threads::Mutex::Lock lm (source_lock);
3953                 
3954                 cerr << " total sources = " << sources.size();
3955                 
3956                 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3957                         boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3958                         
3959                         if (!fs) {
3960                                 continue;
3961                         }
3962                         
3963                         if (fs->within_session()) {
3964                                 continue;
3965                         }
3966                         
3967                         if (source_path_map.find (fs->path()) != source_path_map.end()) {
3968                                 source_path_map[fs->path()].push_back (fs);
3969                         } else {
3970                                 SeveralFileSources v;
3971                                 v.push_back (fs);
3972                                 source_path_map.insert (make_pair (fs->path(), v));
3973                         }
3974                         
3975                         total++;
3976                 }
3977                 
3978                 cerr << " fsources = " << total << endl;
3979                 
3980                 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
3981                         
3982                         /* tell caller where we are */
3983                         
3984                         string old_path = i->first;
3985                         
3986                         callback (n, total, old_path);
3987                         
3988                         cerr << old_path << endl;
3989                         
3990                         new_path.clear ();
3991                         
3992                         switch (i->second.front()->type()) {
3993                         case DataType::AUDIO:
3994                                 new_path = new_audio_source_path_for_embedded (old_path);
3995                                 break;
3996                                 
3997                         case DataType::MIDI:
3998                                 /* XXX not implemented yet */
3999                                 break;
4000                         }
4001                         
4002                         if (new_path.empty()) {
4003                                 continue;
4004                         }
4005                         
4006                         cerr << "Move " << old_path << " => " << new_path << endl;
4007                         
4008                         if (!copy_file (old_path, new_path)) {
4009                                 cerr << "failed !\n";
4010                                 ret = -1;
4011                         }
4012                         
4013                         /* make sure we stop looking in the external
4014                            dir/folder. Remember, this is an all-or-nothing
4015                            operations, it doesn't merge just some files.
4016                         */
4017                         remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4018
4019                         for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4020                                 (*f)->set_path (new_path);
4021                         }
4022                 }
4023         }
4024
4025         save_state ("", false, false);
4026
4027         return ret;
4028 }
4029
4030 static
4031 bool accept_all_files (string const &, void *)
4032 {
4033         return true;
4034 }
4035
4036 void
4037 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4038 {
4039         /* 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.
4040         */
4041 }
4042
4043 static string
4044 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4045 {
4046         /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4047
4048         string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4049         vector<string> v;
4050         v.push_back (new_session_folder); /* full path */
4051         v.push_back (interchange_dir_name);
4052         v.push_back (new_session_path);   /* just one directory/folder */
4053         v.push_back (typedir);
4054         v.push_back (Glib::path_get_basename (old_path));
4055         
4056         return Glib::build_filename (v);
4057 }
4058
4059 int
4060 Session::save_as (SaveAs& saveas)
4061 {
4062         vector<string> files;
4063         string current_folder = Glib::path_get_dirname (_path);
4064         string new_folder = legalize_for_path (saveas.new_name);
4065         string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4066         int64_t total_bytes = 0;
4067         int64_t copied = 0;
4068         int64_t cnt = 0;
4069         int64_t all = 0;
4070         int32_t internal_file_cnt = 0;
4071
4072         vector<string> do_not_copy_extensions;
4073         do_not_copy_extensions.push_back (statefile_suffix);
4074         do_not_copy_extensions.push_back (pending_suffix);
4075         do_not_copy_extensions.push_back (backup_suffix);
4076         do_not_copy_extensions.push_back (temp_suffix);
4077         do_not_copy_extensions.push_back (history_suffix);
4078
4079         /* get total size */
4080
4081         for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4082                 
4083                 /* need to clear this because
4084                  * find_files_matching_filter() is cumulative
4085                  */
4086                 
4087                 files.clear ();
4088                 
4089                 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4090                 
4091                 all += files.size();
4092
4093                 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4094                         GStatBuf gsb;
4095                         g_stat ((*i).c_str(), &gsb);
4096                         total_bytes += gsb.st_size;
4097                 }
4098         }
4099
4100         /* save old values so we can switch back if we are not switching to the new session */
4101         
4102         string old_path = _path;
4103         string old_name = _name;
4104         string old_snapshot = _current_snapshot_name;
4105         string old_sd = _session_dir->root_path();
4106         vector<string> old_search_path[DataType::num_types];
4107         string old_config_search_path[DataType::num_types];
4108
4109         old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4110         old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4111         old_config_search_path[DataType::AUDIO]  = config.get_audio_search_path ();     
4112         old_config_search_path[DataType::MIDI]  = config.get_midi_search_path ();       
4113
4114         /* switch session directory */
4115         
4116         (*_session_dir) = to_dir;
4117
4118         /* create new tree */
4119         
4120         if (!_session_dir->create()) {
4121                 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4122                 return -1;
4123         }
4124
4125         try {
4126                 /* copy all relevant files. Find each location in session_dirs,
4127                  * and copy files from there to target.
4128                  */
4129                 
4130                 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4131                         
4132                         /* need to clear this because
4133                          * find_files_matching_filter() is cumulative
4134                          */
4135                         
4136                         files.clear ();
4137                         
4138                         const size_t prefix_len = (*sd).path.size();
4139                         
4140                         /* Work just on the files within this session dir */
4141                         
4142                         find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4143                         
4144                         /* add dir separator to protect against collisions with
4145                          * track names (e.g. track named "audiofiles" or
4146                          * "analysis".
4147                          */
4148
4149                         static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4150                         static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4151                         static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4152
4153                         /* copy all the files. Handling is different for media files
4154                            than others because of the *silly* subtree we have below the interchange
4155                            folder. That really was a bad idea, but I'm not fixing it as part of
4156                            implementing ::save_as().
4157                         */
4158                         
4159                         for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4160
4161                                 std::string from = *i;
4162
4163                                 if ((*i).find (audiofile_dir_string) != string::npos) {
4164                                         
4165                                         /* audio file: only copy if asked */
4166
4167                                         if (saveas.include_media && saveas.copy_media) {
4168                                                 
4169                                                 string to = make_new_media_path (*i, to_dir, new_folder);
4170
4171                                                 info << "media file copying from " << from << " to " << to << endmsg;
4172                                                 
4173                                                 if (!copy_file (from, to)) {
4174                                                         throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4175                                                 }
4176                                         }
4177                                         
4178                                         /* we found media files inside the session folder */
4179                                         
4180                                         internal_file_cnt++;
4181
4182                                 } else if ((*i).find (midifile_dir_string) != string::npos) {
4183
4184                                         /* midi file: always copy unless
4185                                          * creating an empty new session
4186                                          */
4187
4188                                         if (saveas.include_media) {
4189                                         
4190                                                 string to = make_new_media_path (*i, to_dir, new_folder);
4191                                                 
4192                                                 info << "media file copying from " << from << " to " << to << endmsg;
4193                                                 
4194                                                 if (!copy_file (from, to)) {
4195                                                         throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4196                                                 }
4197                                         }
4198
4199                                         /* we found media files inside the session folder */
4200                                                 
4201                                         internal_file_cnt++;
4202                                         
4203                                 } else if ((*i).find (analysis_dir_string) != string::npos) {
4204
4205                                         /*  make sure analysis dir exists in
4206                                          *  new session folder, but we're not
4207                                          *  copying analysis files here, see
4208                                          *  below 
4209                                          */
4210                                         
4211                                         (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4212                                         continue;
4213                                         
4214                                 } else {
4215                                         
4216                                         /* normal non-media file. Don't copy state, history, etc.
4217                                          */
4218                                         
4219                                         bool do_copy = true;
4220                                         
4221                                         for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4222                                                 if (((*i).length() > (*v).length()) && ((*i).find (*v) == (*i).length() - (*v).length())) {
4223                                                         /* end of filename matches extension, do not copy file */
4224                                                         do_copy = false;
4225                                                         break;
4226                                                 } 
4227                                         }
4228
4229                                         if (!saveas.copy_media && (*i).find (peakfile_suffix) != string::npos) {
4230                                                 /* don't copy peakfiles if
4231                                                  * we're not copying media
4232                                                  */
4233                                                 do_copy = false;
4234                                         }
4235                                         
4236                                         if (do_copy) {
4237                                                 string to = Glib::build_filename (to_dir, (*i).substr (prefix_len));
4238                                                 
4239                                                 info << "attempting to make directory/folder " << to << endmsg;
4240
4241                                                 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4242                                                         throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4243                                                 }
4244
4245                                                 info << "attempting to copy " << from << " to " << to << endmsg;
4246                                                 
4247                                                 if (!copy_file (from, to)) {
4248                                                         throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4249                                                 }
4250                                         }
4251                                 }
4252                                 
4253                                 /* measure file size even if we're not going to copy so that our Progress
4254                                    signals are correct, since we included these do-not-copy files
4255                                    in the computation of the total size and file count.
4256                                 */
4257                                 
4258                                 GStatBuf gsb;
4259                                 g_stat ((*i).c_str(), &gsb);
4260                                 copied += gsb.st_size;
4261                                 cnt++;
4262                                 
4263                                 double fraction = (double) copied / total_bytes;
4264                                 
4265                                 bool keep_going = true;
4266
4267                                 if (saveas.copy_media) {
4268
4269                                         /* no need or expectation of this if
4270                                          * media is not being copied, because
4271                                          * it will be fast(ish).
4272                                          */
4273                                         
4274                                         /* tell someone "X percent, file M of N"; M is one-based */
4275                                         
4276                                         boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4277                                         
4278                                         if (res) {
4279                                                 keep_going = *res;
4280                                         }
4281                                 }
4282
4283                                 if (!keep_going) {
4284                                         throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4285                                 }
4286                         }
4287
4288                 }
4289
4290                 /* copy optional folders, if any */
4291
4292                 string old = plugins_dir ();
4293                 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4294                         string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4295                         copy_files (old, newdir);
4296                 }
4297
4298                 old = externals_dir ();
4299                 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4300                         string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4301                         copy_files (old, newdir);
4302                 }
4303
4304                 old = automation_dir ();
4305                 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4306                         string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4307                         copy_files (old, newdir);
4308                 }
4309
4310                 if (saveas.include_media) {
4311                 
4312                         if (saveas.copy_media) {
4313 #ifndef PLATFORM_WINDOWS
4314                                 /* There are problems with analysis files on
4315                                  * Windows, because they used a colon in their
4316                                  * names as late as 4.0. Colons are not legal
4317                                  * under Windows even if NTFS allows them.
4318                                  *
4319                                  * This is a tricky problem to solve so for
4320                                  * just don't copy these files. They will be
4321                                  * regenerated as-needed anyway, subject to the 
4322                                  * existing issue that the filenames will be
4323                                  * rejected by Windows, which is a separate
4324                                  * problem (though related).
4325                                  */
4326
4327                                 /* only needed if we are copying media, since the
4328                                  * analysis data refers to media data
4329                                  */
4330                                 
4331                                 old = analysis_dir ();
4332                                 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4333                                         string newdir = Glib::build_filename (to_dir, "analysis");
4334                                         copy_files (old, newdir);
4335                                 }
4336 #endif /* PLATFORM_WINDOWS */                           
4337                         }
4338                 }
4339                         
4340                 
4341                 _path = to_dir;
4342                 _current_snapshot_name = saveas.new_name;
4343                 _name = saveas.new_name;
4344
4345                 if (saveas.include_media && !saveas.copy_media) {
4346
4347                         /* reset search paths of the new session (which we're pretending to be right now) to
4348                            include the original session search path, so we can still find all audio.
4349                         */
4350
4351                         if (internal_file_cnt) {
4352                                 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4353                                         ensure_search_path_includes (*s, DataType::AUDIO);
4354                                 }
4355
4356                                 /* we do not do this for MIDI because we copy
4357                                    all MIDI files if saveas.include_media is
4358                                    true
4359                                 */
4360                         }
4361                 }
4362                 
4363                 bool was_dirty = dirty ();
4364
4365                 save_state ("", false, false, !saveas.include_media);
4366                 save_default_options ();
4367                 
4368                 if (saveas.copy_media && saveas.copy_external) {
4369                         if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4370                                 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4371                         }
4372                 }
4373
4374                 saveas.final_session_folder_name = _path;
4375                 
4376                 if (!saveas.switch_to) {
4377
4378                         /* switch back to the way things were */
4379
4380                         _path = old_path;
4381                         _name = old_name;
4382                         _current_snapshot_name = old_snapshot;
4383
4384                         (*_session_dir) = old_sd;
4385
4386                         if (was_dirty) {
4387                                 set_dirty ();
4388                         }
4389
4390                         if (internal_file_cnt) {
4391                                 /* reset these to their original values */
4392                                 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4393                                 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4394                         }
4395                         
4396                 } else {
4397
4398                         /* prune session dirs, and update disk space statistics
4399                          */
4400
4401                         space_and_path sp;
4402                         sp.path = _path;
4403                         session_dirs.clear ();
4404                         session_dirs.push_back (sp);
4405                         refresh_disk_space ();
4406
4407                         /* ensure that all existing tracks reset their current capture source paths 
4408                          */
4409                         reset_write_sources (true, true);
4410
4411                         /* the copying above was based on actually discovering files, not just iterating over the sources list.
4412                            But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4413                         */
4414
4415                         for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4416                                 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4417
4418                                 if (!fs) {
4419                                         continue;
4420                                 }
4421
4422                                 if (fs->within_session()) {
4423                                         string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4424                                         fs->set_path (newpath);
4425                                 }
4426                         }
4427                 }
4428
4429         } catch (Glib::FileError& e) {
4430
4431                 saveas.failure_message = e.what();
4432                 
4433                 /* recursively remove all the directories */
4434                 
4435                 remove_directory (to_dir);
4436                 
4437                 /* return error */
4438                 
4439                 return -1;
4440
4441         } catch (...) {
4442
4443                 saveas.failure_message = _("unknown reason");
4444                 
4445                 /* recursively remove all the directories */
4446                 
4447                 remove_directory (to_dir);
4448                 
4449                 /* return error */
4450                 
4451                 return -1;
4452         }
4453         
4454         return 0;
4455 }