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