change MidiPlaylist::dump() into ::render(); change type of initial argument
[ardour.git] / libs / ardour / session_state.cc
1 /*
2  * Copyright (C) 1999-2019 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2005-2006 Taybin Rutkin <taybin@taybin.com>
4  * Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
5  * Copyright (C) 2006-2016 Tim Mayberry <mojofunk@gmail.com>
6  * Copyright (C) 2006 Jesse Chappell <jesse@essej.net>
7  * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
8  * Copyright (C) 2008-2009 Hans Baier <hansfbaier@googlemail.com>
9  * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
10  * Copyright (C) 2013-2016 John Emmas <john@creativepost.co.uk>
11  * Copyright (C) 2013-2017 Nick Mainsbridge <mainsbridge@gmail.com>
12  * Copyright (C) 2014-2018 Ben Loftis <ben@harrisonconsoles.com>
13  * Copyright (C) 2017 Johannes Mueller <github@johannes-mueller.org>
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with this program; if not, write to the Free Software Foundation, Inc.,
27  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28  */
29
30
31 #ifdef WAF_BUILD
32 #include "libardour-config.h"
33 #endif
34
35 #include <stdint.h>
36
37 #include <algorithm>
38 #include <string>
39 #include <cerrno>
40 #include <cstdio> /* snprintf(3) ... grrr */
41 #include <cmath>
42
43 #include <unistd.h>
44 #include <climits>
45 #include <signal.h>
46 #include <sys/time.h>
47
48 #ifdef HAVE_SYS_VFS_H
49 #include <sys/vfs.h>
50 #endif
51
52 #if defined(__APPLE__) || defined(__FreeBSD__)
53 #include <sys/param.h>
54 #include <sys/mount.h>
55 #endif
56
57 #ifdef HAVE_SYS_STATVFS_H
58 #include <sys/statvfs.h>
59 #endif
60
61 #include <glib.h>
62 #include "pbd/gstdio_compat.h"
63 #include "pbd/locale_guard.h"
64
65 #include <glibmm.h>
66 #include <glibmm/threads.h>
67 #include <glibmm/fileutils.h>
68
69 #include <boost/algorithm/string.hpp>
70
71 #include "midi++/mmc.h"
72 #include "midi++/port.h"
73
74 #include "evoral/SMF.hpp"
75
76 #include "pbd/basename.h"
77 #include "pbd/debug.h"
78 #include "pbd/enumwriter.h"
79 #include "pbd/error.h"
80 #include "pbd/file_utils.h"
81 #include "pbd/pathexpand.h"
82 #include "pbd/pthread_utils.h"
83 #include "pbd/stacktrace.h"
84 #include "pbd/types_convert.h"
85 #include "pbd/localtime_r.h"
86 #include "pbd/unwind.h"
87
88 #include "ardour/amp.h"
89 #include "ardour/async_midi_port.h"
90 #include "ardour/audio_track.h"
91 #include "ardour/audioengine.h"
92 #include "ardour/audiofilesource.h"
93 #include "ardour/audioregion.h"
94 #include "ardour/auditioner.h"
95 #include "ardour/automation_control.h"
96 #include "ardour/boost_debug.h"
97 #include "ardour/butler.h"
98 #include "ardour/control_protocol_manager.h"
99 #include "ardour/directory_names.h"
100 #include "ardour/disk_reader.h"
101 #include "ardour/filename_extensions.h"
102 #include "ardour/graph.h"
103 #include "ardour/location.h"
104 #ifdef LV2_SUPPORT
105 #include "ardour/lv2_plugin.h"
106 #endif
107 #include "ardour/midi_model.h"
108 #include "ardour/midi_patch_manager.h"
109 #include "ardour/midi_region.h"
110 #include "ardour/midi_scene_changer.h"
111 #include "ardour/midi_source.h"
112 #include "ardour/midi_track.h"
113 #include "ardour/pannable.h"
114 #include "ardour/playlist_factory.h"
115 #include "ardour/playlist_source.h"
116 #include "ardour/port.h"
117 #include "ardour/processor.h"
118 #include "ardour/progress.h"
119 #include "ardour/profile.h"
120 #include "ardour/proxy_controllable.h"
121 #include "ardour/recent_sessions.h"
122 #include "ardour/region_factory.h"
123 #include "ardour/revision.h"
124 #include "ardour/route_group.h"
125 #include "ardour/send.h"
126 #include "ardour/selection.h"
127 #include "ardour/session.h"
128 #include "ardour/session_directory.h"
129 #include "ardour/session_metadata.h"
130 #include "ardour/session_playlists.h"
131 #include "ardour/session_state_utils.h"
132 #include "ardour/silentfilesource.h"
133 #include "ardour/smf_source.h"
134 #include "ardour/sndfilesource.h"
135 #include "ardour/source_factory.h"
136 #include "ardour/speakers.h"
137 #include "ardour/template_utils.h"
138 #include "ardour/tempo.h"
139 #include "ardour/ticker.h"
140 #include "ardour/transport_master_manager.h"
141 #include "ardour/types_convert.h"
142 #include "ardour/user_bundle.h"
143 #include "ardour/vca.h"
144 #include "ardour/vca_manager.h"
145
146 #include "control_protocol/control_protocol.h"
147
148 #include "LuaBridge/LuaBridge.h"
149
150 #include "pbd/i18n.h"
151 #include <locale.h>
152
153 using namespace std;
154 using namespace ARDOUR;
155 using namespace PBD;
156
157 #define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg));
158
159 void
160 Session::pre_engine_init (string fullpath)
161 {
162         if (fullpath.empty()) {
163                 destroy ();
164                 throw failed_constructor();
165         }
166
167         /* discover canonical fullpath */
168
169         _path = canonical_path(fullpath);
170
171         /* is it new ? */
172
173         _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
174
175         /* finish initialization that can't be done in a normal C++ constructor
176            definition.
177         */
178
179         timerclear (&last_mmc_step);
180         g_atomic_int_set (&processing_prohibited, 0);
181         g_atomic_int_set (&_record_status, Disabled);
182         g_atomic_int_set (&_playback_load, 100);
183         g_atomic_int_set (&_capture_load, 100);
184         set_next_event ();
185         _all_route_group->set_active (true, this);
186
187         if (config.get_use_video_sync()) {
188                 waiting_for_sync_offset = true;
189         } else {
190                 waiting_for_sync_offset = false;
191         }
192
193         last_rr_session_dir = session_dirs.begin();
194
195         set_history_depth (Config->get_history_depth());
196
197         /* default: assume simple stereo speaker configuration */
198
199         _speakers->setup_default_speakers (2);
200
201         _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
202                                 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
203                                 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
204         add_controllable (_solo_cut_control);
205
206         /* These are all static "per-class" signals */
207
208         SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
209         PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
210         AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
211         IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
212
213         /* stop IO objects from doing stuff until we're ready for them */
214
215         Delivery::disable_panners ();
216         IO::disable_connecting ();
217 }
218
219 int
220 Session::post_engine_init ()
221 {
222         BootMessage (_("Set block size and sample rate"));
223
224         set_block_size (_engine.samples_per_cycle());
225         set_sample_rate (_engine.sample_rate());
226
227         BootMessage (_("Using configuration"));
228
229         _midi_ports = new MidiPortManager;
230
231         MIDISceneChanger* msc;
232
233         _scene_changer = msc = new MIDISceneChanger (*this);
234         msc->set_input_port (boost::dynamic_pointer_cast<MidiPort>(scene_input_port()));
235         msc->set_output_port (boost::dynamic_pointer_cast<MidiPort>(scene_output_port()));
236
237         boost::function<samplecnt_t(void)> timer_func (boost::bind (&Session::audible_sample, this, (bool*)(0)));
238         boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_input_port())->set_timer (timer_func);
239
240         setup_midi_machine_control ();
241
242         if (_butler->start_thread()) {
243                 error << _("Butler did not start") << endmsg;
244                 return -1;
245         }
246
247         if (start_midi_thread ()) {
248                 error << _("MIDI I/O thread did not start") << endmsg;
249                 return -1;
250         }
251
252         setup_click_sounds (0);
253         setup_midi_control ();
254
255         _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
256         _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
257
258         try {
259                 /* tempo map requires sample rate knowledge */
260
261                 delete _tempo_map;
262                 _tempo_map = new TempoMap (_current_sample_rate);
263                 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
264                 _tempo_map->MetricPositionChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
265         } catch (std::exception const & e) {
266                 error << _("Unexpected exception during session setup: ") << e.what() << endmsg;
267                 return -2;
268         } catch (...) {
269                 error << _("Unknown exception during session setup") << endmsg;
270                 return -3;
271         }
272
273         try {
274                 /* MidiClock requires a tempo map */
275
276                 delete midi_clock;
277                 midi_clock = new MidiClockTicker ();
278                 midi_clock->set_session (this);
279
280                 /* crossfades require sample rate knowledge */
281
282                 SndFileSource::setup_standard_crossfades (*this, sample_rate());
283                 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this, true));
284                 _engine.MidiSelectionPortsChanged.connect_same_thread (*this, boost::bind (&Session::rewire_midi_selection_ports, this));
285
286                 DiskReader::allocate_working_buffers();
287                 refresh_disk_space ();
288
289                 /* we're finally ready to call set_state() ... all objects have
290                  * been created, the engine is running.
291                  */
292
293                 if (state_tree) {
294                         try {
295                                 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
296                                         error << _("Could not set session state from XML") << endmsg;
297                                         return -4;
298                                 }
299                         } catch (PBD::unknown_enumeration& e) {
300                                 error << _("Session state: ") << e.what() << endmsg;
301                                 return -4;
302                         }
303                 } else {
304                         // set_state() will call setup_raid_path(), but if it's a new session we need
305                         // to call setup_raid_path() here.
306                         setup_raid_path (_path);
307                 }
308
309                 /* ENGINE */
310
311                 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
312                 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
313
314                 Config->map_parameters (ff);
315                 config.map_parameters (ft);
316                 _butler->map_parameters ();
317
318                 /* Configure all processors; now that the
319                  * engine is running, ports are re-established,
320                  * and IOChange are complete.
321                  */
322                 {
323                         Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
324                         ProcessorChangeBlocker pcb (this);
325                         boost::shared_ptr<RouteList> r = routes.reader ();
326                         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
327                                 (*i)->configure_processors (0);
328                         }
329                 }
330
331                 /* Reset all panners */
332
333                 Delivery::reset_panners ();
334
335                 /* this will cause the CPM to instantiate any protocols that are in use
336                  * (or mandatory), which will pass it this Session, and then call
337                  * set_state() on each instantiated protocol to match stored state.
338                  */
339
340                 ControlProtocolManager::instance().set_session (this);
341
342                 /* This must be done after the ControlProtocolManager set_session above,
343                    as it will set states for ports which the ControlProtocolManager creates.
344                 */
345
346                 // XXX set state of MIDI::Port's
347                 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
348
349                 /* And this must be done after the MIDI::Manager::set_port_states as
350                  * it will try to make connections whose details are loaded by set_port_states.
351                  */
352
353                 hookup_io ();
354
355                 /* Let control protocols know that we are now all connected, so they
356                  * could start talking to surfaces if they want to.
357                  */
358
359                 ControlProtocolManager::instance().midi_connectivity_established ();
360
361                 if (_is_new && !no_auto_connect()) {
362                         Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
363                         auto_connect_master_bus ();
364                 }
365
366                 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave | Dirty));
367
368                 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
369                 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
370                 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
371
372         } catch (AudioEngine::PortRegistrationFailure& err) {
373                 error << err.what() << endmsg;
374                 return -5;
375         } catch (std::exception const & e) {
376                 error << _("Unexpected exception during session setup: ") << e.what() << endmsg;
377                 return -6;
378         } catch (...) {
379                 error << _("Unknown exception during session setup") << endmsg;
380                 return -7;
381         }
382
383         BootMessage (_("Reset Remote Controls"));
384
385         // send_full_time_code (0);
386         _engine.transport_locate (0);
387
388         send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
389         send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
390
391         ltc_tx_initialize();
392
393         BootMessage (_("Loading MIDNAM Patch files"));
394
395         MIDI::Name::MidiPatchManager::instance().add_search_path (session_directory().midi_patch_path() );
396         /* initial program change will be delivered later; see ::config_changed() */
397
398         _state_of_the_state = Clean;
399
400         Port::set_connecting_blocked (false);
401
402         DirtyChanged (); /* EMIT SIGNAL */
403
404         /* Now, finally, we can fill the playback buffers */
405
406         BootMessage (_("Filling playback buffers"));
407
408         boost::shared_ptr<RouteList> rl = routes.reader();
409         for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
410                 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
411                 if (trk && !trk->is_private_route()) {
412                         trk->seek (_transport_sample, true);
413                 }
414         }
415
416         return 0;
417 }
418
419 void
420 Session::session_loaded ()
421 {
422         SessionLoaded();
423
424         _state_of_the_state = Clean;
425
426         DirtyChanged (); /* EMIT SIGNAL */
427
428         if (_is_new) {
429                 save_state ("");
430         } else if (state_was_pending) {
431                 save_state ("");
432                 state_was_pending = false;
433         }
434
435         /* Now, finally, we can fill the playback buffers */
436
437         BootMessage (_("Filling playback buffers"));
438         force_locate (_transport_sample, false);
439 }
440
441 string
442 Session::raid_path () const
443 {
444         Searchpath raid_search_path;
445
446         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
447                 raid_search_path += (*i).path;
448         }
449
450         return raid_search_path.to_string ();
451 }
452
453 void
454 Session::setup_raid_path (string path)
455 {
456         if (path.empty()) {
457                 return;
458         }
459
460         space_and_path sp;
461         string fspath;
462
463         session_dirs.clear ();
464
465         Searchpath search_path(path);
466         Searchpath sound_search_path;
467         Searchpath midi_search_path;
468
469         for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
470                 sp.path = *i;
471                 sp.blocks = 0; // not needed
472                 session_dirs.push_back (sp);
473
474                 SessionDirectory sdir(sp.path);
475
476                 sound_search_path += sdir.sound_path ();
477                 midi_search_path += sdir.midi_path ();
478         }
479
480         // reset the round-robin soundfile path thingie
481         last_rr_session_dir = session_dirs.begin();
482 }
483
484 bool
485 Session::path_is_within_session (const std::string& path)
486 {
487         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
488                 if (PBD::path_is_within (i->path, path)) {
489                         return true;
490                 }
491         }
492         return false;
493 }
494
495 int
496 Session::ensure_subdirs ()
497 {
498         string dir;
499
500         dir = session_directory().peak_path();
501
502         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
503                 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
504                 return -1;
505         }
506
507         dir = session_directory().sound_path();
508
509         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
510                 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
511                 return -1;
512         }
513
514         dir = session_directory().midi_path();
515
516         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
517                 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
518                 return -1;
519         }
520
521         dir = session_directory().dead_path();
522
523         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
524                 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
525                 return -1;
526         }
527
528         dir = session_directory().export_path();
529
530         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
531                 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
532                 return -1;
533         }
534
535         if(Profile->get_mixbus()) {
536                 dir = session_directory().backup_path();
537
538                 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
539                         error << string_compose(_("Session: cannot create session backup folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
540                         return -1;
541                 }
542         }
543
544         dir = analysis_dir ();
545
546         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
547                 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
548                 return -1;
549         }
550
551         dir = plugins_dir ();
552
553         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
554                 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
555                 return -1;
556         }
557
558         dir = externals_dir ();
559
560         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
561                 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
562                 return -1;
563         }
564
565         return 0;
566 }
567
568 /** @param session_template directory containing session template, or empty.
569  *  Caller must not hold process lock.
570  */
571 int
572 Session::create (const string& session_template, BusProfile const * bus_profile)
573 {
574         if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
575                 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
576                 return -1;
577         }
578
579         if (ensure_subdirs ()) {
580                 return -1;
581         }
582
583         _writable = exists_and_writable (_path);
584
585         if (!session_template.empty()) {
586                 string in_path = session_template_dir_to_file (session_template);
587
588                 FILE* in = g_fopen (in_path.c_str(), "rb");
589
590                 if (in) {
591                         /* no need to call legalize_for_path() since the string
592                          * in session_template is already a legal path name
593                          */
594                         string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
595
596                         FILE* out = g_fopen (out_path.c_str(), "wb");
597
598                         if (out) {
599                                 char buf[1024];
600                                 stringstream new_session;
601
602                                 while (!feof (in)) {
603                                         size_t charsRead = fread (buf, sizeof(char), 1024, in);
604
605                                         if (ferror (in)) {
606                                                 error << string_compose (_("Error reading session template file %1 (%2)"), in_path, strerror (errno)) << endmsg;
607                                                 fclose (in);
608                                                 fclose (out);
609                                                 return -1;
610                                         }
611                                         if (charsRead == 0) {
612                                                 break;
613                                         }
614                                         new_session.write (buf, charsRead);
615                                 }
616                                 fclose (in);
617
618                                 string file_contents = new_session.str();
619                                 size_t writeSize = file_contents.length();
620                                 if (fwrite (file_contents.c_str(), sizeof(char), writeSize, out) != writeSize) {
621                                         error << string_compose (_("Error writing session template file %1 (%2)"), out_path, strerror (errno)) << endmsg;
622                                         fclose (out);
623                                         return -1;
624                                 }
625                                 fclose (out);
626
627                                 _is_new = false;
628
629                                 /* Copy plugin state files from template to new session */
630                                 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
631                                 copy_recurse (template_plugins, plugins_dir ());
632
633                                 return 0;
634
635                         } else {
636                                 error << string_compose (_("Could not open %1 for writing session template"), out_path)
637                                         << endmsg;
638                                 fclose(in);
639                                 return -1;
640                         }
641
642                 } else {
643                         error << string_compose (_("Could not open session template %1 for reading"), in_path)
644                                 << endmsg;
645                         return -1;
646                 }
647
648         }
649
650         _state_of_the_state = Clean;
651
652         /* set up Master Out and Monitor Out if necessary */
653
654         if (bus_profile) {
655                 RouteList rl;
656                 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
657                 if (bus_profile->master_out_channels) {
658                         int rv = add_master_bus (count);
659
660                         if (rv) {
661                                 return rv;
662                         }
663
664                         if (Config->get_use_monitor_bus())
665                                 add_monitor_section ();
666                 }
667         }
668
669         return 0;
670 }
671
672 void
673 Session::maybe_write_autosave()
674 {
675         if (dirty() && record_status() != Recording) {
676                 save_state("", true);
677         }
678 }
679
680 void
681 Session::remove_pending_capture_state ()
682 {
683         std::string pending_state_file_path(_session_dir->root_path());
684
685         pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
686
687         if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) {
688                 return;
689         }
690
691         if (::g_unlink (pending_state_file_path.c_str()) != 0) {
692                 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
693                                 pending_state_file_path, g_strerror (errno)) << endmsg;
694         }
695 #ifndef NDEBUG
696         else {
697                 cerr << "removed " << pending_state_file_path << endl;
698         }
699 #endif
700 }
701
702 /** Rename a state file.
703  *  @param old_name Old snapshot name.
704  *  @param new_name New snapshot name.
705  */
706 void
707 Session::rename_state (string old_name, string new_name)
708 {
709         if (old_name == _current_snapshot_name || old_name == _name) {
710                 /* refuse to rename the current snapshot or the "main" one */
711                 return;
712         }
713
714         const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
715         const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
716
717         const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
718         const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
719
720         if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
721                 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
722                                 old_name, new_name, g_strerror(errno)) << endmsg;
723         }
724 }
725
726 /** Remove a state file.
727  *  @param snapshot_name Snapshot name.
728  */
729 void
730 Session::remove_state (string snapshot_name)
731 {
732         if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
733                 // refuse to remove the current snapshot or the "main" one
734                 return;
735         }
736
737         std::string xml_path(_session_dir->root_path());
738
739         xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
740
741         if (!create_backup_file (xml_path)) {
742                 // don't remove it if a backup can't be made
743                 // create_backup_file will log the error.
744                 return;
745         }
746
747         // and delete it
748         if (g_remove (xml_path.c_str()) != 0) {
749                 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
750                                 xml_path, g_strerror (errno)) << endmsg;
751         }
752
753         StateSaved (snapshot_name); /* EMIT SIGNAL */
754 }
755
756 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
757 int
758 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only, bool for_archive, bool only_used_assets)
759 {
760         DEBUG_TRACE (DEBUG::Locale, string_compose ("Session::save_state locale '%1'\n", setlocale (LC_NUMERIC, NULL)));
761
762         XMLTree tree;
763         std::string xml_path(_session_dir->root_path());
764
765         /* prevent concurrent saves from different threads */
766
767         Glib::Threads::Mutex::Lock lm (save_state_lock);
768         Glib::Threads::Mutex::Lock lx (save_source_lock, Glib::Threads::NOT_LOCK);
769         if (!for_archive) {
770                 lx.acquire ();
771         }
772
773         if (!_writable || cannot_save()) {
774                 return 1;
775         }
776
777         if (g_atomic_int_get(&_suspend_save)) {
778                 _save_queued = true;
779                 return 1;
780         }
781         _save_queued = false;
782
783         snapshot_t fork_state = NormalSave;
784         if (!snapshot_name.empty() && snapshot_name != _current_snapshot_name && !template_only && !pending && !for_archive) {
785                 /* snapshot, close midi */
786                 fork_state = switch_to_snapshot ? SwitchToSnapshot : SnapshotKeep;
787         }
788
789 #ifndef NDEBUG
790         const int64_t save_start_time = g_get_monotonic_time();
791 #endif
792
793         /* tell sources we're saving first, in case they write out to a new file
794          * which should be saved with the state rather than the old one */
795         for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
796                 try {
797                         i->second->session_saved();
798                 } catch (Evoral::SMF::FileError& e) {
799                         error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
800                 }
801         }
802
803         PBD::Unwinder<bool> uw (LV2Plugin::force_state_save, for_archive);
804
805         SessionSaveUnderway (); /* EMIT SIGNAL */
806
807         bool mark_as_clean = true;
808         if (!snapshot_name.empty() && !switch_to_snapshot) {
809                 mark_as_clean = false;
810         }
811
812         if (template_only) {
813                 mark_as_clean = false;
814                 tree.set_root (&get_template());
815         } else {
816                 tree.set_root (&state (false, fork_state, only_used_assets));
817         }
818
819         if (snapshot_name.empty()) {
820                 snapshot_name = _current_snapshot_name;
821         } else if (switch_to_snapshot) {
822                 set_snapshot_name (snapshot_name);
823         }
824
825         assert (!snapshot_name.empty());
826
827         if (!pending) {
828
829                 /* proper save: use statefile_suffix (.ardour in English) */
830
831                 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
832
833                 /* make a backup copy of the old file */
834
835                 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
836                         // create_backup_file will log the error
837                         return -1;
838                 }
839
840         } else {
841                 assert (snapshot_name == _current_snapshot_name);
842                 /* pending save: use pending_suffix (.pending in English) */
843                 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
844         }
845
846         std::string tmp_path(_session_dir->root_path());
847         tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
848
849 #ifndef NDEBUG
850         cerr << "actually writing state to " << tmp_path << endl;
851 #endif
852
853         if (!tree.write (tmp_path)) {
854                 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
855                 if (g_remove (tmp_path.c_str()) != 0) {
856                         error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
857                                         tmp_path, g_strerror (errno)) << endmsg;
858                 }
859                 return -1;
860
861         } else {
862
863 #ifndef NDEBUG
864                 cerr << "renaming state to " << xml_path << endl;
865 #endif
866
867                 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
868                         error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
869                                         tmp_path, xml_path, g_strerror(errno)) << endmsg;
870                         if (g_remove (tmp_path.c_str()) != 0) {
871                                 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
872                                                 tmp_path, g_strerror (errno)) << endmsg;
873                         }
874                         return -1;
875                 }
876         }
877
878         //Mixbus auto-backup mechanism
879         if(Profile->get_mixbus()) {
880                 if (pending) {  //"pending" save means it's a backup, or some other non-user-initiated save;  a good time to make a backup
881                         // make a serialized safety backup
882                         // (will make one periodically but only one per hour is left on disk)
883                         // these backup files go into a separated folder
884                         char timebuf[128];
885                         time_t n;
886                         struct tm local_time;
887                         time (&n);
888                         localtime_r (&n, &local_time);
889                         strftime (timebuf, sizeof(timebuf), "%y-%m-%d.%H", &local_time);
890                         std::string save_path(session_directory().backup_path());
891                         save_path += G_DIR_SEPARATOR;
892                         save_path += legalize_for_path(_current_snapshot_name);
893                         save_path += "-";
894                         save_path += timebuf;
895                         save_path += statefile_suffix;
896                         if ( !tree.write (save_path) )
897                                         error << string_compose(_("Could not save backup file at path \"%1\" (%2)"),
898                                                         save_path, g_strerror (errno)) << endmsg;
899                 }
900
901                 StateSaved (snapshot_name); /* EMIT SIGNAL */
902         }
903
904         if (!pending && !for_archive) {
905
906                 save_history (snapshot_name);
907
908                 if (mark_as_clean) {
909                         unset_dirty (/* EMIT SIGNAL */ true);
910                 }
911
912                 StateSaved (snapshot_name); /* EMIT SIGNAL */
913         }
914
915 #ifndef NDEBUG
916         const int64_t elapsed_time_us = g_get_monotonic_time() - save_start_time;
917         cerr << "saved state in " << fixed << setprecision (1) << elapsed_time_us / 1000. << " ms\n";
918 #endif
919
920         if (!pending && !for_archive && ! template_only) {
921                 remove_pending_capture_state ();
922         }
923
924         return 0;
925 }
926
927 int
928 Session::restore_state (string snapshot_name)
929 {
930         try {
931                 if (load_state (snapshot_name) == 0) {
932                         set_state (*state_tree->root(), Stateful::loading_state_version);
933                 }
934         } catch (...) {
935                 // SessionException
936                 // unknown_enumeration
937                 return -1;
938         }
939
940         return 0;
941 }
942
943 int
944 Session::load_state (string snapshot_name)
945 {
946         delete state_tree;
947         state_tree = 0;
948
949         state_was_pending = false;
950
951         /* check for leftover pending state from a crashed capture attempt */
952
953         std::string xmlpath(_session_dir->root_path());
954         xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
955
956         if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
957
958                 /* there is pending state from a crashed capture attempt */
959
960                 boost::optional<int> r = AskAboutPendingState();
961                 if (r.get_value_or (1)) {
962                         state_was_pending = true;
963                 }
964         }
965
966         if (!state_was_pending) {
967                 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
968         }
969
970         if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
971                 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
972                 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
973                         error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
974                         return 1;
975                 }
976         }
977
978         state_tree = new XMLTree;
979
980         set_dirty();
981
982         _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
983
984         if (!state_tree->read (xmlpath)) {
985                 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
986                 delete state_tree;
987                 state_tree = 0;
988                 return -1;
989         }
990
991         XMLNode const & root (*state_tree->root());
992
993         if (root.name() != X_("Session")) {
994                 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
995                 delete state_tree;
996                 state_tree = 0;
997                 return -1;
998         }
999
1000         std::string version;
1001         root.get_property ("version", version);
1002         Stateful::loading_state_version = parse_stateful_loading_version (version);
1003
1004         if ((Stateful::loading_state_version / 1000L) > (CURRENT_SESSION_FILE_VERSION / 1000L)) {
1005                 cerr << "Session-version: " << Stateful::loading_state_version << " is not supported. Current: " << CURRENT_SESSION_FILE_VERSION << "\n";
1006                 throw SessionException (string_compose (_("Incomatible Session Version. That session was created with a newer version of %1"), PROGRAM_NAME));
1007         }
1008
1009         if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
1010
1011                 std::string backup_path(_session_dir->root_path());
1012                 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
1013                 backup_path = Glib::build_filename (backup_path, backup_filename);
1014
1015                 // only create a backup for a given statefile version once
1016
1017                 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
1018
1019                         VersionMismatch (xmlpath, backup_path);
1020
1021                         if (!copy_file (xmlpath, backup_path)) {;
1022                                 return -1;
1023                         }
1024                 }
1025         }
1026
1027         save_snapshot_name (snapshot_name);
1028
1029         return 0;
1030 }
1031
1032 int
1033 Session::load_options (const XMLNode& node)
1034 {
1035         config.set_variables (node);
1036         return 0;
1037 }
1038
1039 bool
1040 Session::save_default_options ()
1041 {
1042         return config.save_state();
1043 }
1044
1045 XMLNode&
1046 Session::get_state ()
1047 {
1048         /* this is not directly called, but required by PBD::Stateful */
1049         assert (0);
1050         return state (false, NormalSave);
1051 }
1052
1053 XMLNode&
1054 Session::get_template ()
1055 {
1056         /* if we don't disable rec-enable, diskstreams
1057            will believe they need to store their capture
1058            sources in their state node.
1059         */
1060
1061         disable_record (false);
1062
1063         return state (true, NormalSave);
1064 }
1065
1066 typedef std::set<boost::shared_ptr<Playlist> > PlaylistSet;
1067 typedef std::set<boost::shared_ptr<Source> > SourceSet;
1068
1069 bool
1070 Session::export_track_state (boost::shared_ptr<RouteList> rl, const string& path)
1071 {
1072         if (Glib::file_test (path, Glib::FILE_TEST_EXISTS))  {
1073                 return false;
1074         }
1075         if (g_mkdir_with_parents (path.c_str(), 0755) != 0) {
1076                 return false;
1077         }
1078
1079         PBD::Unwinder<std::string> uw (_template_state_dir, path);
1080
1081         LocaleGuard lg;
1082         XMLNode* node = new XMLNode("TrackState"); // XXX
1083         XMLNode* child;
1084
1085         PlaylistSet playlists; // SessionPlaylists
1086         SourceSet sources;
1087
1088         // these will work with  new_route_from_template()
1089         // TODO: LV2 plugin-state-dir needs to be relative (on load?)
1090         child = node->add_child ("Routes");
1091         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1092                 if ((*i)->is_auditioner()) {
1093                         continue;
1094                 }
1095                 if ((*i)->is_master() || (*i)->is_monitor()) {
1096                         continue;
1097                 }
1098                 child->add_child_nocopy ((*i)->get_state());
1099                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (*i);
1100                 if (track) {
1101                         playlists.insert (track->playlist ());
1102                 }
1103         }
1104
1105         // on load, Regions in the playlists need to resolve and map Source-IDs
1106         // also playlist needs to be merged or created with new-name..
1107         // ... and Diskstream in tracks adjusted to use the correct playlist
1108         child = node->add_child ("Playlists"); // SessionPlaylists::add_state
1109         for (PlaylistSet::const_iterator i = playlists.begin(); i != playlists.end(); ++i) {
1110                 child->add_child_nocopy ((*i)->get_state ());
1111                 boost::shared_ptr<RegionList> prl = (*i)->region_list ();
1112                 for (RegionList::const_iterator s = prl->begin(); s != prl->end(); ++s) {
1113                         const Region::SourceList& sl = (*s)->sources ();
1114                         for (Region::SourceList::const_iterator sli = sl.begin(); sli != sl.end(); ++sli) {
1115                                 sources.insert (*sli);
1116                         }
1117                 }
1118         }
1119
1120         child = node->add_child ("Sources");
1121         for (SourceSet::const_iterator i = sources.begin(); i != sources.end(); ++i) {
1122                 child->add_child_nocopy ((*i)->get_state ());
1123                 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (*i);
1124                 if (fs) {
1125 #ifdef PLATFORM_WINDOWS
1126                         fs->close ();
1127 #endif
1128                         string p = fs->path ();
1129                         PBD::copy_file (p, Glib::build_filename (path, Glib::path_get_basename (p)));
1130                 }
1131         }
1132
1133         std::string sn = Glib::build_filename (path, "share.axml");
1134
1135         XMLTree tree;
1136         tree.set_root (node);
1137         return tree.write (sn.c_str());
1138 }
1139
1140 static void
1141 merge_all_sources (boost::shared_ptr<const Playlist> pl, std::set<boost::shared_ptr<Source> >* all_sources)
1142 {
1143         pl->deep_sources (*all_sources);
1144 }
1145
1146 namespace
1147 {
1148 struct route_id_compare {
1149         bool
1150         operator() (const boost::shared_ptr<Route>& r1, const boost::shared_ptr<Route>& r2)
1151         {
1152                 return r1->id () < r2->id ();
1153         }
1154 };
1155 } // anon namespace
1156
1157 XMLNode&
1158 Session::state (bool save_template, snapshot_t snapshot_type, bool only_used_assets)
1159 {
1160         LocaleGuard lg;
1161         XMLNode* node = new XMLNode("Session");
1162         XMLNode* child;
1163
1164         PBD::Unwinder<bool> uw (Automatable::skip_saving_automation, save_template);
1165
1166         node->set_property("version", CURRENT_SESSION_FILE_VERSION);
1167
1168         child = node->add_child ("ProgramVersion");
1169         child->set_property("created-with", created_with);
1170
1171         std::string modified_with = string_compose ("%1 %2", PROGRAM_NAME, revision);
1172         child->set_property("modified-with", modified_with);
1173
1174         /* store configuration settings */
1175
1176         if (!save_template) {
1177
1178                 node->set_property ("name", _name);
1179                 node->set_property ("sample-rate", _base_sample_rate);
1180
1181                 if (session_dirs.size() > 1) {
1182
1183                         string p;
1184
1185                         vector<space_and_path>::iterator i = session_dirs.begin();
1186                         vector<space_and_path>::iterator next;
1187
1188                         ++i; /* skip the first one */
1189                         next = i;
1190                         ++next;
1191
1192                         while (i != session_dirs.end()) {
1193
1194                                 p += (*i).path;
1195
1196                                 if (next != session_dirs.end()) {
1197                                         p += G_SEARCHPATH_SEPARATOR;
1198                                 } else {
1199                                         break;
1200                                 }
1201
1202                                 ++next;
1203                                 ++i;
1204                         }
1205
1206                         child = node->add_child ("Path");
1207                         child->add_content (p);
1208                 }
1209                 node->set_property ("end-is-free", _session_range_is_free);  //deprecated, but keep storing this value for compatibility with prior v5.
1210                 node->set_property ("session-range-is-free", _session_range_is_free);
1211         }
1212
1213         /* save the ID counter */
1214
1215         node->set_property ("id-counter", ID::counter());
1216
1217         node->set_property ("name-counter", name_id_counter ());
1218
1219         /* save the event ID counter */
1220
1221         node->set_property ("event-counter", Evoral::event_id_counter());
1222
1223         /* save the VCA counter */
1224
1225         node->set_property ("vca-counter", VCA::get_next_vca_number());
1226
1227         /* various options */
1228
1229         list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1230         if (!midi_port_nodes.empty()) {
1231                 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1232                 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1233                         midi_port_stuff->add_child_nocopy (**n);
1234                 }
1235                 node->add_child_nocopy (*midi_port_stuff);
1236         }
1237
1238         XMLNode& cfgxml (config.get_variables ());
1239         if (save_template) {
1240                 /* exclude search-paths from template */
1241                 cfgxml.remove_nodes_and_delete ("name", "audio-search-path");
1242                 cfgxml.remove_nodes_and_delete ("name", "midi-search-path");
1243                 cfgxml.remove_nodes_and_delete ("name", "raid-path");
1244         }
1245         node->add_child_nocopy (cfgxml);
1246
1247         node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1248
1249         child = node->add_child ("Sources");
1250
1251         if (!save_template) {
1252                 Glib::Threads::Mutex::Lock sl (source_lock);
1253
1254                 set<boost::shared_ptr<Source> > sources_used_by_this_snapshot;
1255
1256                 if (only_used_assets) {
1257                         _playlists->sync_all_regions_with_regions ();
1258                         _playlists->foreach (boost::bind (merge_all_sources, _1, &sources_used_by_this_snapshot), false);
1259                 }
1260
1261                 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1262
1263                         /* Don't save information about non-file Sources, or
1264                          * about non-destructive file sources that are empty
1265                          * and unused by any regions.
1266                          */
1267                         boost::shared_ptr<FileSource> fs;
1268
1269                         if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) == 0) {
1270                                 continue;
1271                         }
1272
1273                         if (!fs->destructive()) {
1274                                 if (fs->empty() && !fs->used()) {
1275                                         continue;
1276                                 }
1277                         }
1278
1279                         if (only_used_assets) {
1280                                 /* skip only unused audio files */
1281                                 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (fs);
1282                                 if (afs && !afs->used()) {
1283                                         continue;
1284                                 }
1285                                 if (afs && sources_used_by_this_snapshot.find (afs) == sources_used_by_this_snapshot.end ()) {
1286                                         continue;
1287                                 }
1288                         }
1289
1290                         if (snapshot_type != NormalSave && fs->within_session ()) {
1291                                 /* copy MIDI sources to new file
1292                                  *
1293                                  * We cannot replace the midi-source and MidiRegion::clobber_sources,
1294                                  * because the GUI (midi_region) has a direct pointer to the midi-model
1295                                  * of the source, as does UndoTransaction.
1296                                  *
1297                                  * On the upside, .mid files are not kept open. The file is only open
1298                                  * when reading the model initially and when flushing the model to disk:
1299                                  * source->session_saved () or export.
1300                                  *
1301                                  * We can change the _path of the existing source under the hood, keeping
1302                                  * all IDs, references and pointers intact.
1303                                  * */
1304                                 boost::shared_ptr<SMFSource> ms;
1305                                 if ((ms = boost::dynamic_pointer_cast<SMFSource> (siter->second)) != 0) {
1306                                         const std::string ancestor_name = ms->ancestor_name();
1307                                         const std::string base          = PBD::basename_nosuffix(ancestor_name);
1308                                         const string path               = new_midi_source_path (base, false);
1309
1310                                         /* use SMF-API to clone data (use the midi_model, not data on disk) */
1311                                         boost::shared_ptr<SMFSource> newsrc (new SMFSource (*this, path, SndFileSource::default_writable_flags));
1312                                         Source::Lock lm (ms->mutex());
1313
1314                                         // TODO special-case empty, removable() files: just create a new removable.
1315                                         // (load + write flushes the model and creates the file)
1316                                         if (!ms->model()) {
1317                                                 ms->load_model (lm);
1318                                         }
1319                                         if (ms->write_to (lm, newsrc, Temporal::Beats(), std::numeric_limits<Temporal::Beats>::max())) {
1320                                                 error << string_compose (_("Session-Save: Failed to copy MIDI Source '%1' for snapshot"), ancestor_name) << endmsg;
1321                                         } else {
1322                                                 if (snapshot_type == SnapshotKeep) {
1323                                                         /* keep working on current session.
1324                                                          *
1325                                                          * Save snapshot-state with the original filename.
1326                                                          * Switch to use new path for future saves of the main session.
1327                                                          */
1328                                                         child->add_child_nocopy (ms->get_state());
1329                                                 }
1330
1331                                                 /* swap file-paths.
1332                                                  * ~SMFSource  unlinks removable() files.
1333                                                  */
1334                                                 std::string npath (ms->path ());
1335                                                 ms->replace_file (newsrc->path ());
1336                                                 newsrc->replace_file (npath);
1337
1338                                                 if (snapshot_type == SwitchToSnapshot) {
1339                                                         /* save and switch to snapshot.
1340                                                          *
1341                                                          * Leave the old file in place (as is).
1342                                                          * Snapshot uses new source directly
1343                                                          */
1344                                                         child->add_child_nocopy (ms->get_state());
1345                                                 }
1346                                                 continue;
1347                                         }
1348                                 }
1349                         }
1350
1351                         child->add_child_nocopy (siter->second->get_state());
1352                 }
1353         }
1354
1355         child = node->add_child ("Regions");
1356
1357         if (!save_template) {
1358                 Glib::Threads::Mutex::Lock rl (region_lock);
1359
1360                 if (!only_used_assets) {
1361                         const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1362                         for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1363                                 boost::shared_ptr<Region> r = i->second;
1364                                 /* only store regions not attached to playlists */
1365                                 if (r->playlist() == 0) {
1366                                         if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1367                                                 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1368                                         } else {
1369                                                 child->add_child_nocopy (r->get_state ());
1370                                         }
1371                                 }
1372                         }
1373                 }
1374
1375                 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1376
1377                 if (!cassocs.empty()) {
1378                         XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1379
1380                         for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1381                                 if (i->first->playlist () == 0 && only_used_assets) {
1382                                         continue;
1383                                 }
1384                                 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1385                                 can->set_property (X_("copy"), i->first->id());
1386                                 can->set_property (X_("original"), i->second->id());
1387                                 ca->add_child_nocopy (*can);
1388                                 /* see above, child is still "Regions" here  */
1389                                 if (i->second->playlist() == 0 && only_used_assets) {
1390                                         if (boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>( i->second)) {
1391                                                 child->add_child_nocopy (ar->get_basic_state ());
1392                                         } else {
1393                                                 child->add_child_nocopy (ar->get_state ());
1394                                         }
1395                                 }
1396                         }
1397                 }
1398         }
1399
1400         if (!save_template) {
1401
1402                 node->add_child_nocopy (_selection->get_state());
1403
1404                 if (_locations) {
1405                         node->add_child_nocopy (_locations->get_state());
1406                 }
1407         } else {
1408                 Locations loc (*this);
1409                 const bool was_dirty = dirty();
1410                 // for a template, just create a new Locations, populate it
1411                 // with the default start and end, and get the state for that.
1412                 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange, 0);
1413                 range->set (max_samplepos, 0);
1414                 loc.add (range);
1415                 XMLNode& locations_state = loc.get_state();
1416
1417                 node->add_child_nocopy (locations_state);
1418
1419                 /* adding a location above will have marked the session
1420                  * dirty. This is an artifact, so fix it if the session wasn't
1421                  * already dirty
1422                  */
1423
1424                 if (!was_dirty) {
1425                         unset_dirty ();
1426                 }
1427         }
1428
1429         child = node->add_child ("Bundles");
1430         {
1431                 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1432                 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1433                         boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1434                         if (b) {
1435                                 child->add_child_nocopy (b->get_state());
1436                         }
1437                 }
1438         }
1439
1440         node->add_child_nocopy (_vca_manager->get_state());
1441
1442         child = node->add_child ("Routes");
1443         {
1444                 boost::shared_ptr<RouteList> r = routes.reader ();
1445
1446                 route_id_compare cmp;
1447                 RouteList xml_node_order (*r);
1448                 xml_node_order.sort (cmp);
1449
1450                 for (RouteList::const_iterator i = xml_node_order.begin(); i != xml_node_order.end(); ++i) {
1451                         if (!(*i)->is_auditioner()) {
1452                                 if (save_template) {
1453                                         child->add_child_nocopy ((*i)->get_template());
1454                                 } else {
1455                                         child->add_child_nocopy ((*i)->get_state());
1456                                 }
1457                         }
1458                 }
1459         }
1460
1461         _playlists->add_state (node, save_template, !only_used_assets);
1462
1463         child = node->add_child ("RouteGroups");
1464         for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1465                 child->add_child_nocopy ((*i)->get_state());
1466         }
1467
1468         if (_click_io) {
1469                 XMLNode* gain_child = node->add_child ("Click");
1470                 gain_child->add_child_nocopy (_click_io->get_state ());
1471                 gain_child->add_child_nocopy (_click_gain->get_state ());
1472         }
1473
1474         if (_ltc_output) {
1475                 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1476                 ltc_output_child->add_child_nocopy (_ltc_output->get_state ());
1477         }
1478
1479         node->add_child_nocopy (_speakers->get_state());
1480         node->add_child_nocopy (_tempo_map->get_state());
1481         node->add_child_nocopy (get_control_protocol_state());
1482
1483         if (_extra_xml) {
1484                 node->add_child_copy (*_extra_xml);
1485         }
1486
1487         {
1488                 Glib::Threads::Mutex::Lock lm (lua_lock);
1489                 std::string saved;
1490                 {
1491                         luabridge::LuaRef savedstate ((*_lua_save)());
1492                         saved = savedstate.cast<std::string>();
1493                 }
1494                 lua.collect_garbage ();
1495                 lm.release ();
1496
1497                 gchar* b64 = g_base64_encode ((const guchar*)saved.c_str (), saved.size ());
1498                 std::string b64s (b64);
1499                 g_free (b64);
1500
1501                 XMLNode* script_node = new XMLNode (X_("Script"));
1502                 script_node->set_property (X_("lua"), LUA_VERSION);
1503                 script_node->add_content (b64s);
1504                 node->add_child_nocopy (*script_node);
1505         }
1506
1507         return *node;
1508 }
1509
1510 XMLNode&
1511 Session::get_control_protocol_state ()
1512 {
1513         return ControlProtocolManager::instance().get_state ();
1514 }
1515
1516 int
1517 Session::set_state (const XMLNode& node, int version)
1518 {
1519         LocaleGuard lg;
1520         XMLNodeList nlist;
1521         XMLNode* child;
1522         int ret = -1;
1523
1524         _state_of_the_state = StateOfTheState (_state_of_the_state | CannotSave);
1525
1526         if (node.name() != X_("Session")) {
1527                 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1528                 goto out;
1529         }
1530
1531         node.get_property ("name", _name);
1532
1533         if (node.get_property (X_("sample-rate"), _base_sample_rate)) {
1534
1535                 _nominal_sample_rate = _base_sample_rate;
1536
1537                 assert (AudioEngine::instance()->running ());
1538                 if (_base_sample_rate != AudioEngine::instance()->sample_rate ()) {
1539                         boost::optional<int> r = AskAboutSampleRateMismatch (_base_sample_rate, _current_sample_rate);
1540                         if (r.get_value_or (0)) {
1541                                 goto out;
1542                         }
1543                 }
1544         }
1545
1546         created_with = "unknown";
1547         if ((child = find_named_node (node, "ProgramVersion")) != 0) {
1548                 child->get_property (X_("created-with"), created_with);
1549         }
1550
1551         setup_raid_path(_session_dir->root_path());
1552
1553         node.get_property (X_("end-is-free"), _session_range_is_free);  //deprectated, but use old values if they are in the config
1554
1555         node.get_property (X_("session-range-is-free"), _session_range_is_free);
1556
1557         uint64_t counter;
1558         if (node.get_property (X_("id-counter"), counter)) {
1559                 ID::init_counter (counter);
1560         } else {
1561                 /* old sessions used a timebased counter, so fake
1562                  * the startup ID counter based on a standard
1563                  * timestamp.
1564                  */
1565                 time_t now;
1566                 time (&now);
1567                 ID::init_counter (now);
1568         }
1569
1570         if (node.get_property (X_("name-counter"), counter)) {
1571                 init_name_id_counter (counter);
1572         }
1573
1574         if (node.get_property (X_("event-counter"), counter)) {
1575                 Evoral::init_event_id_counter (counter);
1576         }
1577
1578         if (node.get_property (X_("vca-counter"), counter)) {
1579                 VCA::set_next_vca_number (counter);
1580         } else {
1581                 VCA::set_next_vca_number (1);
1582         }
1583
1584         if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1585                 _midi_ports->set_midi_port_states (child->children());
1586         }
1587
1588         IO::disable_connecting ();
1589
1590         Stateful::save_extra_xml (node);
1591
1592         if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1593                 load_options (*child);
1594         } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1595                 load_options (*child);
1596         } else {
1597                 error << _("Session: XML state has no options section") << endmsg;
1598         }
1599
1600         if (version >= 3000) {
1601                 if ((child = find_named_node (node, "Metadata")) == 0) {
1602                         warning << _("Session: XML state has no metadata section") << endmsg;
1603                 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1604                         goto out;
1605                 }
1606         }
1607
1608         if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1609                 _speakers->set_state (*child, version);
1610         }
1611
1612         if ((child = find_named_node (node, "Sources")) == 0) {
1613                 error << _("Session: XML state has no sources section") << endmsg;
1614                 goto out;
1615         } else if (load_sources (*child)) {
1616                 goto out;
1617         }
1618
1619         if ((child = find_named_node (node, "TempoMap")) == 0) {
1620                 error << _("Session: XML state has no Tempo Map section") << endmsg;
1621                 goto out;
1622         } else if (_tempo_map->set_state (*child, version)) {
1623                 goto out;
1624         }
1625
1626         if ((child = find_named_node (node, "Locations")) == 0) {
1627                 error << _("Session: XML state has no locations section") << endmsg;
1628                 goto out;
1629         } else if (_locations->set_state (*child, version)) {
1630                 goto out;
1631         }
1632
1633         locations_changed ();
1634
1635         if (_session_range_location) {
1636                 AudioFileSource::set_header_position_offset (_session_range_location->start());
1637         }
1638
1639         if ((child = find_named_node (node, "Regions")) == 0) {
1640                 error << _("Session: XML state has no Regions section") << endmsg;
1641                 goto out;
1642         } else if (load_regions (*child)) {
1643                 goto out;
1644         }
1645
1646         if ((child = find_named_node (node, "Playlists")) == 0) {
1647                 error << _("Session: XML state has no playlists section") << endmsg;
1648                 goto out;
1649         } else if (_playlists->load (*this, *child)) {
1650                 goto out;
1651         }
1652
1653         if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1654                 // this is OK
1655         } else if (_playlists->load_unused (*this, *child)) {
1656                 goto out;
1657         }
1658
1659         if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1660                 if (load_compounds (*child)) {
1661                         goto out;
1662                 }
1663         }
1664
1665         if (version >= 3000) {
1666                 if ((child = find_named_node (node, "Bundles")) == 0) {
1667                         warning << _("Session: XML state has no bundles section") << endmsg;
1668                         //goto out;
1669                 } else {
1670                         /* We can't load Bundles yet as they need to be able
1671                          * to convert from port names to Port objects, which can't happen until
1672                          * later */
1673                         _bundle_xml_node = new XMLNode (*child);
1674                 }
1675         }
1676
1677         if ((child = find_named_node (node, VCAManager::xml_node_name)) != 0) {
1678                 _vca_manager->set_state (*child, version);
1679         }
1680
1681         if ((child = find_named_node (node, "Routes")) == 0) {
1682                 error << _("Session: XML state has no routes section") << endmsg;
1683                 goto out;
1684         } else if (load_routes (*child, version)) {
1685                 goto out;
1686         }
1687
1688         /* Now that we Tracks have been loaded and playlists are assigned */
1689         _playlists->update_tracking ();
1690
1691         /* Now that we have Routes and masters loaded, connect them if appropriate */
1692
1693         Slavable::Assign (_vca_manager); /* EMIT SIGNAL */
1694
1695         if (version >= 3000) {
1696
1697                 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1698                         error << _("Session: XML state has no route groups section") << endmsg;
1699                         goto out;
1700                 } else if (load_route_groups (*child, version)) {
1701                         goto out;
1702                 }
1703
1704         } else if (version < 3000) {
1705
1706                 if ((child = find_named_node (node, "EditGroups")) == 0) {
1707                         error << _("Session: XML state has no edit groups section") << endmsg;
1708                         goto out;
1709                 } else if (load_route_groups (*child, version)) {
1710                         goto out;
1711                 }
1712
1713                 if ((child = find_named_node (node, "MixGroups")) == 0) {
1714                         error << _("Session: XML state has no mix groups section") << endmsg;
1715                         goto out;
1716                 } else if (load_route_groups (*child, version)) {
1717                         goto out;
1718                 }
1719         }
1720
1721         if ((child = find_named_node (node, "Click")) == 0) {
1722                 warning << _("Session: XML state has no click section") << endmsg;
1723         } else if (_click_io) {
1724                 setup_click_state (&node);
1725         }
1726
1727         if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1728                 ControlProtocolManager::instance().set_state (*child, 1 /* here: session-specific state */);
1729         }
1730
1731         if ((child = find_named_node (node, "Script"))) {
1732                 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1733                         if (!(*n)->is_content ()) { continue; }
1734                         gsize size;
1735                         guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
1736                         try {
1737                                 Glib::Threads::Mutex::Lock lm (lua_lock);
1738                                 (*_lua_load)(std::string ((const char*)buf, size));
1739                         } catch (luabridge::LuaException const& e) {
1740                                 cerr << "LuaException:" << e.what () << endl;
1741                         } catch (...) { }
1742                         g_free (buf);
1743                 }
1744         }
1745
1746         if ((child = find_named_node (node, X_("Selection")))) {
1747                 _selection->set_state (*child, version);
1748         }
1749
1750         update_route_record_state ();
1751
1752         /* here beginneth the second phase ... */
1753         set_snapshot_name (_current_snapshot_name);
1754
1755         StateReady (); /* EMIT SIGNAL */
1756
1757         delete state_tree;
1758         state_tree = 0;
1759         return 0;
1760
1761 out:
1762         delete state_tree;
1763         state_tree = 0;
1764         return ret;
1765 }
1766
1767 int
1768 Session::load_routes (const XMLNode& node, int version)
1769 {
1770         XMLNodeList nlist;
1771         XMLNodeConstIterator niter;
1772         RouteList new_routes;
1773
1774         nlist = node.children();
1775
1776         set_dirty();
1777
1778         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1779
1780                 boost::shared_ptr<Route> route;
1781
1782                 if (version < 3000) {
1783                         route = XMLRouteFactory_2X (**niter, version);
1784                 } else if (version < 5000) {
1785                         route = XMLRouteFactory_3X (**niter, version);
1786                 } else {
1787                         route = XMLRouteFactory (**niter, version);
1788                 }
1789
1790                 if (route == 0) {
1791                         error << _("Session: cannot create Route from XML description.") << endmsg;
1792                         return -1;
1793                 }
1794
1795                 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1796
1797                 new_routes.push_back (route);
1798         }
1799
1800         BootMessage (_("Tracks/busses loaded;  Adding to Session"));
1801
1802         add_routes (new_routes, false, false, false, PresentationInfo::max_order);
1803
1804         BootMessage (_("Finished adding tracks/busses"));
1805
1806         return 0;
1807 }
1808
1809 boost::shared_ptr<Route>
1810 Session::XMLRouteFactory (const XMLNode& node, int version)
1811 {
1812         boost::shared_ptr<Route> ret;
1813
1814         if (node.name() != "Route") {
1815                 return ret;
1816         }
1817
1818         XMLProperty const * pl_prop = node.property (X_("audio-playlist"));
1819
1820         if (!pl_prop) {
1821                 pl_prop = node.property (X_("midi-playlist"));
1822         }
1823
1824         DataType type = DataType::AUDIO;
1825         node.get_property("default-type", type);
1826
1827         assert (type != DataType::NIL);
1828
1829         if (pl_prop) {
1830
1831                 /* has at least 1 playlist, therefore a track ... */
1832
1833                 boost::shared_ptr<Track> track;
1834
1835                 if (type == DataType::AUDIO) {
1836                         track.reset (new AudioTrack (*this, string())); // name will be reset from XML in ::set_state() below
1837                 } else {
1838                         track.reset (new MidiTrack (*this, string())); // name will be reset from XML in ::set_state() below
1839                 }
1840
1841                 if (track->init()) {
1842                         return ret;
1843                 }
1844
1845                 if (track->set_state (node, version)) {
1846                         return ret;
1847                 }
1848
1849                 BOOST_MARK_TRACK (track);
1850                 ret = track;
1851
1852         } else {
1853                 PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1854                 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1855
1856
1857                 if (r->init () == 0 && r->set_state (node, version) == 0) {
1858                         BOOST_MARK_ROUTE (r);
1859                         ret = r;
1860                 }
1861         }
1862
1863         return ret;
1864 }
1865
1866 boost::shared_ptr<Route>
1867 Session::XMLRouteFactory_3X (const XMLNode& node, int version)
1868 {
1869         boost::shared_ptr<Route> ret;
1870
1871         if (node.name() != "Route") {
1872                 return ret;
1873         }
1874
1875         XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1876
1877         DataType type = DataType::AUDIO;
1878         node.get_property("default-type", type);
1879
1880         assert (type != DataType::NIL);
1881
1882         if (ds_child) {
1883
1884                 boost::shared_ptr<Track> track;
1885
1886                 if (type == DataType::AUDIO) {
1887                         track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1888                 } else {
1889                         track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1890                 }
1891
1892                 if (track->init()) {
1893                         return ret;
1894                 }
1895
1896                 if (track->set_state (node, version)) {
1897                         return ret;
1898                 }
1899
1900                 BOOST_MARK_TRACK (track);
1901                 ret = track;
1902
1903         } else {
1904                 PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1905                 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1906
1907                 if (r->init () == 0 && r->set_state (node, version) == 0) {
1908                         BOOST_MARK_ROUTE (r);
1909                         ret = r;
1910                 }
1911         }
1912
1913         return ret;
1914 }
1915
1916 boost::shared_ptr<Route>
1917 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1918 {
1919         boost::shared_ptr<Route> ret;
1920
1921         if (node.name() != "Route") {
1922                 return ret;
1923         }
1924
1925         XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1926         if (!ds_prop) {
1927                 ds_prop = node.property (X_("diskstream"));
1928         }
1929
1930         DataType type = DataType::AUDIO;
1931         node.get_property("default-type", type);
1932
1933         assert (type != DataType::NIL);
1934
1935         if (ds_prop) {
1936
1937                 /* see comment in current ::set_state() regarding diskstream
1938                  * state and DiskReader/DiskWRiter.
1939                  */
1940
1941                 error << _("Could not find diskstream for route") << endmsg;
1942                 return boost::shared_ptr<Route> ();
1943
1944                 boost::shared_ptr<Track> track;
1945
1946                 if (type == DataType::AUDIO) {
1947                         track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1948                 } else {
1949                         track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1950                 }
1951
1952                 if (track->init()) {
1953                         return ret;
1954                 }
1955
1956                 if (track->set_state (node, version)) {
1957                         return ret;
1958                 }
1959
1960                 BOOST_MARK_TRACK (track);
1961                 ret = track;
1962
1963         } else {
1964                 PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1965                 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1966
1967                 if (r->init () == 0 && r->set_state (node, version) == 0) {
1968                         BOOST_MARK_ROUTE (r);
1969                         ret = r;
1970                 }
1971         }
1972
1973         return ret;
1974 }
1975
1976 int
1977 Session::load_regions (const XMLNode& node)
1978 {
1979         XMLNodeList nlist;
1980         XMLNodeConstIterator niter;
1981         boost::shared_ptr<Region> region;
1982
1983         nlist = node.children();
1984
1985         set_dirty();
1986
1987         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1988                 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1989                         error << _("Session: cannot create Region from XML description.");
1990                         XMLProperty const * name = (**niter).property("name");
1991
1992                         if (name) {
1993                                 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1994                         }
1995
1996                         error << endmsg;
1997                 }
1998         }
1999
2000         return 0;
2001 }
2002
2003 int
2004 Session::load_compounds (const XMLNode& node)
2005 {
2006         XMLNodeList calist = node.children();
2007         XMLNodeConstIterator caiter;
2008         XMLProperty const * caprop;
2009
2010         for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
2011                 XMLNode* ca = *caiter;
2012                 ID orig_id;
2013                 ID copy_id;
2014
2015                 if ((caprop = ca->property (X_("original"))) == 0) {
2016                         continue;
2017                 }
2018                 orig_id = caprop->value();
2019
2020                 if ((caprop = ca->property (X_("copy"))) == 0) {
2021                         continue;
2022                 }
2023                 copy_id = caprop->value();
2024
2025                 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
2026                 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
2027
2028                 if (!orig || !copy) {
2029                         warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
2030                                                    orig_id, copy_id)
2031                                 << endmsg;
2032                         continue;
2033                 }
2034
2035                 RegionFactory::add_compound_association (orig, copy);
2036         }
2037
2038         return 0;
2039 }
2040
2041 void
2042 Session::load_nested_sources (const XMLNode& node)
2043 {
2044         XMLNodeList nlist;
2045         XMLNodeConstIterator niter;
2046
2047         nlist = node.children();
2048
2049         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2050                 if ((*niter)->name() == "Source") {
2051
2052                         /* it may already exist, so don't recreate it unnecessarily
2053                          */
2054
2055                         XMLProperty const * prop = (*niter)->property (X_("id"));
2056                         if (!prop) {
2057                                 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
2058                                 continue;
2059                         }
2060
2061                         ID source_id (prop->value());
2062
2063                         if (!source_by_id (source_id)) {
2064
2065                                 try {
2066                                         SourceFactory::create (*this, **niter, true);
2067                                 }
2068                                 catch (failed_constructor& err) {
2069                                         error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
2070                                 }
2071                         }
2072                 }
2073         }
2074 }
2075
2076 boost::shared_ptr<Region>
2077 Session::XMLRegionFactory (const XMLNode& node, bool full)
2078 {
2079         XMLProperty const * type = node.property("type");
2080
2081         try {
2082
2083                 const XMLNodeList& nlist = node.children();
2084
2085                 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
2086                         XMLNode *child = (*niter);
2087                         if (child->name() == "NestedSource") {
2088                                 load_nested_sources (*child);
2089                         }
2090                 }
2091
2092                 if (!type || type->value() == "audio") {
2093                         return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
2094                 } else if (type->value() == "midi") {
2095                         return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
2096                 }
2097
2098         } catch (failed_constructor& err) {
2099                 return boost::shared_ptr<Region> ();
2100         }
2101
2102         return boost::shared_ptr<Region> ();
2103 }
2104
2105 boost::shared_ptr<AudioRegion>
2106 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
2107 {
2108         XMLProperty const * prop;
2109         boost::shared_ptr<Source> source;
2110         boost::shared_ptr<AudioSource> as;
2111         SourceList sources;
2112         SourceList master_sources;
2113         uint32_t nchans = 1;
2114         char buf[128];
2115
2116         if (node.name() != X_("Region")) {
2117                 return boost::shared_ptr<AudioRegion>();
2118         }
2119
2120         node.get_property (X_("channels"), nchans);
2121
2122         if ((prop = node.property ("name")) == 0) {
2123                 cerr << "no name for this region\n";
2124                 abort ();
2125         }
2126
2127         if ((prop = node.property (X_("source-0"))) == 0) {
2128                 if ((prop = node.property ("source")) == 0) {
2129                         error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
2130                         return boost::shared_ptr<AudioRegion>();
2131                 }
2132         }
2133
2134         PBD::ID s_id (prop->value());
2135
2136         if ((source = source_by_id (s_id)) == 0) {
2137                 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
2138                 return boost::shared_ptr<AudioRegion>();
2139         }
2140
2141         as = boost::dynamic_pointer_cast<AudioSource>(source);
2142         if (!as) {
2143                 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
2144                 return boost::shared_ptr<AudioRegion>();
2145         }
2146
2147         sources.push_back (as);
2148
2149         /* pickup other channels */
2150
2151         for (uint32_t n=1; n < nchans; ++n) {
2152                 snprintf (buf, sizeof(buf), X_("source-%d"), n);
2153                 if ((prop = node.property (buf)) != 0) {
2154
2155                         PBD::ID id2 (prop->value());
2156
2157                         if ((source = source_by_id (id2)) == 0) {
2158                                 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
2159                                 return boost::shared_ptr<AudioRegion>();
2160                         }
2161
2162                         as = boost::dynamic_pointer_cast<AudioSource>(source);
2163                         if (!as) {
2164                                 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
2165                                 return boost::shared_ptr<AudioRegion>();
2166                         }
2167                         sources.push_back (as);
2168                 }
2169         }
2170
2171         for (uint32_t n = 0; n < nchans; ++n) {
2172                 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
2173                 if ((prop = node.property (buf)) != 0) {
2174
2175                         PBD::ID id2 (prop->value());
2176
2177                         if ((source = source_by_id (id2)) == 0) {
2178                                 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
2179                                 return boost::shared_ptr<AudioRegion>();
2180                         }
2181
2182                         as = boost::dynamic_pointer_cast<AudioSource>(source);
2183                         if (!as) {
2184                                 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
2185                                 return boost::shared_ptr<AudioRegion>();
2186                         }
2187                         master_sources.push_back (as);
2188                 }
2189         }
2190
2191         try {
2192                 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
2193
2194                 /* a final detail: this is the one and only place that we know how long missing files are */
2195
2196                 if (region->whole_file()) {
2197                         for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
2198                                 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
2199                                 if (sfp) {
2200                                         sfp->set_length (region->length());
2201                                 }
2202                         }
2203                 }
2204
2205                 if (!master_sources.empty()) {
2206                         if (master_sources.size() != nchans) {
2207                                 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
2208                         } else {
2209                                 region->set_master_sources (master_sources);
2210                         }
2211                 }
2212
2213                 return region;
2214
2215         }
2216
2217         catch (failed_constructor& err) {
2218                 return boost::shared_ptr<AudioRegion>();
2219         }
2220 }
2221
2222 boost::shared_ptr<MidiRegion>
2223 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
2224 {
2225         XMLProperty const * prop;
2226         boost::shared_ptr<Source> source;
2227         boost::shared_ptr<MidiSource> ms;
2228         SourceList sources;
2229
2230         if (node.name() != X_("Region")) {
2231                 return boost::shared_ptr<MidiRegion>();
2232         }
2233
2234         if ((prop = node.property ("name")) == 0) {
2235                 cerr << "no name for this region\n";
2236                 abort ();
2237         }
2238
2239         if ((prop = node.property (X_("source-0"))) == 0) {
2240                 if ((prop = node.property ("source")) == 0) {
2241                         error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
2242                         return boost::shared_ptr<MidiRegion>();
2243                 }
2244         }
2245
2246         PBD::ID s_id (prop->value());
2247
2248         if ((source = source_by_id (s_id)) == 0) {
2249                 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
2250                 return boost::shared_ptr<MidiRegion>();
2251         }
2252
2253         ms = boost::dynamic_pointer_cast<MidiSource>(source);
2254         if (!ms) {
2255                 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
2256                 return boost::shared_ptr<MidiRegion>();
2257         }
2258
2259         sources.push_back (ms);
2260
2261         try {
2262                 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
2263                 /* a final detail: this is the one and only place that we know how long missing files are */
2264
2265                 if (region->whole_file()) {
2266                         for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
2267                                 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
2268                                 if (sfp) {
2269                                         sfp->set_length (region->length());
2270                                 }
2271                         }
2272                 }
2273
2274                 return region;
2275         }
2276
2277         catch (failed_constructor& err) {
2278                 return boost::shared_ptr<MidiRegion>();
2279         }
2280 }
2281
2282 XMLNode&
2283 Session::get_sources_as_xml ()
2284
2285 {
2286         XMLNode* node = new XMLNode (X_("Sources"));
2287         Glib::Threads::Mutex::Lock lm (source_lock);
2288
2289         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2290                 node->add_child_nocopy (i->second->get_state());
2291         }
2292
2293         return *node;
2294 }
2295
2296 void
2297 Session::reset_write_sources (bool mark_write_complete, bool force)
2298 {
2299         boost::shared_ptr<RouteList> rl = routes.reader();
2300         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2301                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2302                 if (tr) {
2303                         _state_of_the_state = StateOfTheState (_state_of_the_state | InCleanup);
2304                         tr->reset_write_sources(mark_write_complete, force);
2305                         _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
2306                 }
2307         }
2308 }
2309
2310 int
2311 Session::load_sources (const XMLNode& node)
2312 {
2313         XMLNodeList nlist;
2314         XMLNodeConstIterator niter;
2315         /* don't need this but it stops some
2316          * versions of gcc complaining about
2317          * discarded return values.
2318          */
2319         boost::shared_ptr<Source> source;
2320
2321         nlist = node.children();
2322
2323         set_dirty();
2324         std::map<std::string, std::string> relocation;
2325
2326         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2327 #ifdef PLATFORM_WINDOWS
2328                 int old_mode = 0;
2329 #endif
2330
2331                 XMLNode srcnode (**niter);
2332                 bool try_replace_abspath = true;
2333
2334 retry:
2335                 try {
2336 #ifdef PLATFORM_WINDOWS
2337                         // do not show "insert media" popups (files embedded from removable media).
2338                         old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
2339 #endif
2340                         if ((source = XMLSourceFactory (srcnode)) == 0) {
2341                                 error << _("Session: cannot create Source from XML description.") << endmsg;
2342                         }
2343 #ifdef PLATFORM_WINDOWS
2344                         SetErrorMode(old_mode);
2345 #endif
2346
2347                 } catch (MissingSource& err) {
2348 #ifdef PLATFORM_WINDOWS
2349                         SetErrorMode(old_mode);
2350 #endif
2351
2352                         /* try previous abs path replacements first */
2353                         if (try_replace_abspath && Glib::path_is_absolute (err.path)) {
2354                                 std::string dir = Glib::path_get_dirname (err.path);
2355                                 std::map<std::string, std::string>::const_iterator rl = relocation.find (dir);
2356                                 if (rl != relocation.end ()) {
2357                                         std::string newpath = Glib::build_filename (rl->second, Glib::path_get_basename (err.path));
2358                                         if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2359                                                 srcnode.set_property ("origin", newpath);
2360                                                 try_replace_abspath = false;
2361                                                 goto retry;
2362                                         }
2363                                 }
2364                         }
2365
2366                         int user_choice;
2367                         _missing_file_replacement = "";
2368
2369                         if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2370                                 error << string_compose (_("An external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2371                                                 PROGRAM_NAME) << endmsg;
2372                                 return -1;
2373                         }
2374
2375                         if (!no_questions_about_missing_files) {
2376                                 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2377                         } else {
2378                                 user_choice = -2;
2379                         }
2380
2381                         switch (user_choice) {
2382                                 case 0:
2383                                         /* user added a new search location
2384                                          * or selected a new absolute path,
2385                                          * so try again */
2386                                         if (Glib::path_is_absolute (err.path)) {
2387                                                 if (!_missing_file_replacement.empty ()) {
2388                                                         /* replace origin, in XML */
2389                                                         std::string newpath = Glib::build_filename (
2390                                                                         _missing_file_replacement, Glib::path_get_basename (err.path));
2391                                                         srcnode.set_property ("origin", newpath);
2392                                                         relocation[Glib::path_get_dirname (err.path)] = _missing_file_replacement;
2393                                                         _missing_file_replacement = "";
2394                                                 }
2395                                         }
2396                                         goto retry;
2397
2398
2399                                 case 1:
2400                                         /* user asked to quit the entire session load */
2401                                         return -1;
2402
2403                                 case 2:
2404                                         no_questions_about_missing_files = true;
2405                                         goto retry;
2406
2407                                 case 3:
2408                                         no_questions_about_missing_files = true;
2409                                         /* fallthrough */
2410
2411                                 case -1:
2412                                 default:
2413                                         switch (err.type) {
2414
2415                                                 case DataType::AUDIO:
2416                                                         source = SourceFactory::createSilent (*this, **niter, max_samplecnt, _current_sample_rate);
2417                                                         break;
2418
2419                                                 case DataType::MIDI:
2420                                                         /* The MIDI file is actually missing so
2421                                                          * just create a new one in the same
2422                                                          * location. Do not announce its
2423                                                          */
2424                                                         string fullpath;
2425
2426                                                         if (!Glib::path_is_absolute (err.path)) {
2427                                                                 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2428                                                         } else {
2429                                                                 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2430                                                                  * the session tree.
2431                                                                  */
2432                                                                 return -1;
2433                                                         }
2434                                                         /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2435                                                         source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_sample_rate, false, false);
2436                                                         /* reset ID to match the missing one */
2437                                                         source->set_id (**niter);
2438                                                         /* Now we can announce it */
2439                                                         SourceFactory::SourceCreated (source);
2440                                                         break;
2441                                         }
2442                                         break;
2443                         }
2444                 }
2445         }
2446
2447         return 0;
2448 }
2449
2450 boost::shared_ptr<Source>
2451 Session::XMLSourceFactory (const XMLNode& node)
2452 {
2453         if (node.name() != "Source") {
2454                 return boost::shared_ptr<Source>();
2455         }
2456
2457         try {
2458                 /* note: do peak building in another thread when loading session state */
2459                 return SourceFactory::create (*this, node, true);
2460         }
2461
2462         catch (failed_constructor& err) {
2463                 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2464                 return boost::shared_ptr<Source>();
2465         }
2466 }
2467
2468 int
2469 Session::save_template (const string& template_name, const string& description, bool replace_existing)
2470 {
2471         if (cannot_save () || template_name.empty ()) {
2472                 return -1;
2473         }
2474
2475         bool absolute_path = Glib::path_is_absolute (template_name);
2476
2477         /* directory to put the template in */
2478         std::string template_dir_path;
2479
2480         if (!absolute_path) {
2481                 std::string user_template_dir(user_template_directory());
2482
2483                 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2484                         error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2485                                         user_template_dir, g_strerror (errno)) << endmsg;
2486                         return -1;
2487                 }
2488
2489                 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2490         } else {
2491                 template_dir_path = template_name;
2492         }
2493
2494         if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2495                 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2496                                           template_dir_path) << endmsg;
2497                 return -2;
2498         }
2499
2500         if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2501                 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2502                                         template_dir_path, g_strerror (errno)) << endmsg;
2503                 return -1;
2504         }
2505
2506         /* file to write */
2507         std::string template_file_path;
2508
2509         if (absolute_path) {
2510                 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2511         } else {
2512                 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2513         }
2514
2515         SessionSaveUnderway (); /* EMIT SIGNAL */
2516
2517         XMLTree tree;
2518         XMLNode* root;
2519         {
2520                 PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2521                 root = &get_template ();
2522         }
2523
2524         root->remove_nodes_and_delete (X_("description"));
2525
2526         if (!description.empty()) {
2527                 XMLNode* desc = new XMLNode (X_("description"));
2528                 XMLNode* desc_cont = new XMLNode (X_("content"), description);
2529                 desc->add_child_nocopy (*desc_cont);
2530
2531                 root->add_child_nocopy (*desc);
2532         }
2533
2534         tree.set_root (root);
2535
2536         if (!tree.write (template_file_path)) {
2537                 error << _("template not saved") << endmsg;
2538                 return -1;
2539         }
2540
2541         store_recent_templates (template_file_path);
2542
2543         return 0;
2544 }
2545
2546 void
2547 Session::refresh_disk_space ()
2548 {
2549 #if __APPLE__ || __FreeBSD__ || __NetBSD__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2550
2551         Glib::Threads::Mutex::Lock lm (space_lock);
2552
2553         /* get freespace on every FS that is part of the session path */
2554
2555         _total_free_4k_blocks = 0;
2556         _total_free_4k_blocks_uncertain = false;
2557
2558         for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2559 #if defined(__NetBSD__)
2560                 struct statvfs statfsbuf;
2561
2562                 statvfs (i->path.c_str(), &statfsbuf);
2563 #else
2564                 struct statfs statfsbuf;
2565
2566                 statfs (i->path.c_str(), &statfsbuf);
2567 #endif
2568                 double const scale = statfsbuf.f_bsize / 4096.0;
2569
2570                 /* See if this filesystem is read-only */
2571                 struct statvfs statvfsbuf;
2572                 statvfs (i->path.c_str(), &statvfsbuf);
2573
2574                 /* f_bavail can be 0 if it is undefined for whatever
2575                    filesystem we are looking at; Samba shares mounted
2576                    via GVFS are an example of this.
2577                 */
2578                 if (statfsbuf.f_bavail == 0) {
2579                         /* block count unknown */
2580                         i->blocks = 0;
2581                         i->blocks_unknown = true;
2582                 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2583                         /* read-only filesystem */
2584                         i->blocks = 0;
2585                         i->blocks_unknown = false;
2586                 } else {
2587                         /* read/write filesystem with known space */
2588                         i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2589                         i->blocks_unknown = false;
2590                 }
2591
2592                 _total_free_4k_blocks += i->blocks;
2593                 if (i->blocks_unknown) {
2594                         _total_free_4k_blocks_uncertain = true;
2595                 }
2596         }
2597 #elif defined PLATFORM_WINDOWS
2598         vector<string> scanned_volumes;
2599         vector<string>::iterator j;
2600         vector<space_and_path>::iterator i;
2601         DWORD nSectorsPerCluster, nBytesPerSector,
2602               nFreeClusters, nTotalClusters;
2603         char disk_drive[4];
2604         bool volume_found;
2605
2606         _total_free_4k_blocks = 0;
2607
2608         for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2609                 strncpy (disk_drive, (*i).path.c_str(), 3);
2610                 disk_drive[3] = 0;
2611                 strupr(disk_drive);
2612
2613                 volume_found = false;
2614                 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2615                 {
2616                         int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2617                         int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2618                         i->blocks = (uint32_t)(nFreeBytes / 4096);
2619
2620                         for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2621                                 if (0 == j->compare(disk_drive)) {
2622                                         volume_found = true;
2623                                         break;
2624                                 }
2625                         }
2626
2627                         if (!volume_found) {
2628                                 scanned_volumes.push_back(disk_drive);
2629                                 _total_free_4k_blocks += i->blocks;
2630                         }
2631                 }
2632         }
2633
2634         if (0 == _total_free_4k_blocks) {
2635                 strncpy (disk_drive, path().c_str(), 3);
2636                 disk_drive[3] = 0;
2637
2638                 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2639                 {
2640                         int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2641                         int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2642                         _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2643                 }
2644         }
2645 #endif
2646 }
2647
2648 string
2649 Session::get_best_session_directory_for_new_audio ()
2650 {
2651         vector<space_and_path>::iterator i;
2652         string result = _session_dir->root_path();
2653
2654         /* handle common case without system calls */
2655
2656         if (session_dirs.size() == 1) {
2657                 return result;
2658         }
2659
2660         /* OK, here's the algorithm we're following here:
2661
2662         We want to select which directory to use for
2663         the next file source to be created. Ideally,
2664         we'd like to use a round-robin process so as to
2665         get maximum performance benefits from splitting
2666         the files across multiple disks.
2667
2668         However, in situations without much diskspace, an
2669         RR approach may end up filling up a filesystem
2670         with new files while others still have space.
2671         Its therefore important to pay some attention to
2672         the freespace in the filesystem holding each
2673         directory as well. However, if we did that by
2674         itself, we'd keep creating new files in the file
2675         system with the most space until it was as full
2676         as all others, thus negating any performance
2677         benefits of this RAID-1 like approach.
2678
2679         So, we use a user-configurable space threshold. If
2680         there are at least 2 filesystems with more than this
2681         much space available, we use RR selection between them.
2682         If not, then we pick the filesystem with the most space.
2683
2684         This gets a good balance between the two
2685         approaches.
2686         */
2687
2688         refresh_disk_space ();
2689
2690         int free_enough = 0;
2691
2692         for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2693                 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2694                         free_enough++;
2695                 }
2696         }
2697
2698         if (free_enough >= 2) {
2699                 /* use RR selection process, ensuring that the one
2700                    picked works OK.
2701                 */
2702
2703                 i = last_rr_session_dir;
2704
2705                 do {
2706                         if (++i == session_dirs.end()) {
2707                                 i = session_dirs.begin();
2708                         }
2709
2710                         if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2711                                 SessionDirectory sdir(i->path);
2712                                 if (sdir.create ()) {
2713                                         result = (*i).path;
2714                                         last_rr_session_dir = i;
2715                                         return result;
2716                                 }
2717                         }
2718
2719                 } while (i != last_rr_session_dir);
2720
2721         } else {
2722
2723                 /* pick FS with the most freespace (and that
2724                    seems to actually work ...)
2725                 */
2726
2727                 vector<space_and_path> sorted;
2728                 space_and_path_ascending_cmp cmp;
2729
2730                 sorted = session_dirs;
2731                 sort (sorted.begin(), sorted.end(), cmp);
2732
2733                 for (i = sorted.begin(); i != sorted.end(); ++i) {
2734                         SessionDirectory sdir(i->path);
2735                         if (sdir.create ()) {
2736                                 result = (*i).path;
2737                                 last_rr_session_dir = i;
2738                                 return result;
2739                         }
2740                 }
2741         }
2742
2743         return result;
2744 }
2745
2746 string
2747 Session::automation_dir () const
2748 {
2749         return Glib::build_filename (_path, automation_dir_name);
2750 }
2751
2752 string
2753 Session::analysis_dir () const
2754 {
2755         return Glib::build_filename (_path, analysis_dir_name);
2756 }
2757
2758 string
2759 Session::plugins_dir () const
2760 {
2761         return Glib::build_filename (_path, plugins_dir_name);
2762 }
2763
2764 string
2765 Session::externals_dir () const
2766 {
2767         return Glib::build_filename (_path, externals_dir_name);
2768 }
2769
2770 int
2771 Session::load_bundles (XMLNode const & node)
2772 {
2773         XMLNodeList nlist = node.children();
2774         XMLNodeConstIterator niter;
2775
2776         set_dirty();
2777
2778         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2779                 if ((*niter)->name() == "InputBundle") {
2780                         add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2781                 } else if ((*niter)->name() == "OutputBundle") {
2782                         add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2783                 } else {
2784                         error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2785                         return -1;
2786                 }
2787         }
2788
2789         return 0;
2790 }
2791
2792 int
2793 Session::load_route_groups (const XMLNode& node, int version)
2794 {
2795         XMLNodeList nlist = node.children();
2796         XMLNodeConstIterator niter;
2797
2798         set_dirty ();
2799
2800         if (version >= 3000) {
2801
2802                 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2803                         if ((*niter)->name() == "RouteGroup") {
2804                                 RouteGroup* rg = new RouteGroup (*this, "");
2805                                 add_route_group (rg);
2806                                 rg->set_state (**niter, version);
2807                         }
2808                 }
2809
2810         } else if (version < 3000) {
2811
2812                 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2813                         if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2814                                 RouteGroup* rg = new RouteGroup (*this, "");
2815                                 add_route_group (rg);
2816                                 rg->set_state (**niter, version);
2817                         }
2818                 }
2819         }
2820
2821         return 0;
2822 }
2823
2824 static bool
2825 state_file_filter (const string &str, void* /*arg*/)
2826 {
2827         return (str.length() > strlen(statefile_suffix) &&
2828                 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2829 }
2830
2831 static string
2832 remove_end(string state)
2833 {
2834         string statename(state);
2835
2836         string::size_type start,end;
2837         if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2838                 statename = statename.substr (start+1);
2839         }
2840
2841         if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2842                 end = statename.length();
2843         }
2844
2845         return string(statename.substr (0, end));
2846 }
2847
2848 vector<string>
2849 Session::possible_states (string path)
2850 {
2851         vector<string> states;
2852         find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2853
2854         transform(states.begin(), states.end(), states.begin(), remove_end);
2855
2856         sort (states.begin(), states.end());
2857
2858         return states;
2859 }
2860
2861 vector<string>
2862 Session::possible_states () const
2863 {
2864         return possible_states(_path);
2865 }
2866
2867 RouteGroup*
2868 Session::new_route_group (const std::string& name)
2869 {
2870         RouteGroup* rg = NULL;
2871
2872         for (std::list<RouteGroup*>::const_iterator i = _route_groups.begin (); i != _route_groups.end (); ++i) {
2873                 if ((*i)->name () == name) {
2874                         rg = *i;
2875                         break;
2876                 }
2877         }
2878
2879         if (!rg) {
2880                 rg = new RouteGroup (*this, name);
2881                 add_route_group (rg);
2882         }
2883         return (rg);
2884 }
2885
2886 void
2887 Session::add_route_group (RouteGroup* g)
2888 {
2889         _route_groups.push_back (g);
2890         route_group_added (g); /* EMIT SIGNAL */
2891
2892         g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2893         g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2894         g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2895
2896         set_dirty ();
2897 }
2898
2899 void
2900 Session::remove_route_group (RouteGroup& rg)
2901 {
2902         list<RouteGroup*>::iterator i;
2903
2904         if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2905                 _route_groups.erase (i);
2906                 delete &rg;
2907
2908                 route_group_removed (); /* EMIT SIGNAL */
2909         }
2910 }
2911
2912 /** Set a new order for our route groups, without adding or removing any.
2913  *  @param groups Route group list in the new order.
2914  */
2915 void
2916 Session::reorder_route_groups (list<RouteGroup*> groups)
2917 {
2918         _route_groups = groups;
2919
2920         route_groups_reordered (); /* EMIT SIGNAL */
2921         set_dirty ();
2922 }
2923
2924
2925 RouteGroup *
2926 Session::route_group_by_name (string name)
2927 {
2928         list<RouteGroup *>::iterator i;
2929
2930         for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2931                 if ((*i)->name() == name) {
2932                         return* i;
2933                 }
2934         }
2935         return 0;
2936 }
2937
2938 RouteGroup&
2939 Session::all_route_group() const
2940 {
2941         return *_all_route_group;
2942 }
2943
2944 void
2945 Session::add_commands (vector<Command*> const & cmds)
2946 {
2947         for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2948                 add_command (*i);
2949         }
2950 }
2951
2952 void
2953 Session::add_command (Command* const cmd)
2954 {
2955         assert (_current_trans);
2956         DEBUG_UNDO_HISTORY (
2957             string_compose ("Current Undo Transaction %1, adding command: %2",
2958                             _current_trans->name (),
2959                             cmd->name ()));
2960         _current_trans->add_command (cmd);
2961 }
2962
2963 PBD::StatefulDiffCommand*
2964 Session::add_stateful_diff_command (boost::shared_ptr<PBD::StatefulDestructible> sfd)
2965 {
2966         PBD::StatefulDiffCommand* cmd = new PBD::StatefulDiffCommand (sfd);
2967         add_command (cmd);
2968         return cmd;
2969 }
2970
2971 void
2972 Session::begin_reversible_command (const string& name)
2973 {
2974         begin_reversible_command (g_quark_from_string (name.c_str ()));
2975 }
2976
2977 /** Begin a reversible command using a GQuark to identify it.
2978  *  begin_reversible_command() and commit_reversible_command() calls may be nested,
2979  *  but there must be as many begin...()s as there are commit...()s.
2980  */
2981 void
2982 Session::begin_reversible_command (GQuark q)
2983 {
2984         /* If nested begin/commit pairs are used, we create just one UndoTransaction
2985            to hold all the commands that are committed.  This keeps the order of
2986            commands correct in the history.
2987         */
2988
2989         if (_current_trans == 0) {
2990                 DEBUG_UNDO_HISTORY (string_compose (
2991                     "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2992
2993                 /* start a new transaction */
2994                 assert (_current_trans_quarks.empty ());
2995                 _current_trans = new UndoTransaction();
2996                 _current_trans->set_name (g_quark_to_string (q));
2997         } else {
2998                 DEBUG_UNDO_HISTORY (
2999                     string_compose ("Begin Reversible Command, current transaction: %1",
3000                                     _current_trans->name ()));
3001         }
3002
3003         _current_trans_quarks.push_front (q);
3004 }
3005
3006 void
3007 Session::abort_reversible_command ()
3008 {
3009         if (_current_trans != 0) {
3010                 DEBUG_UNDO_HISTORY (
3011                     string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
3012                 _current_trans->clear();
3013                 delete _current_trans;
3014                 _current_trans = 0;
3015                 _current_trans_quarks.clear();
3016         }
3017 }
3018
3019 void
3020 Session::commit_reversible_command (Command *cmd)
3021 {
3022         assert (_current_trans);
3023         assert (!_current_trans_quarks.empty ());
3024
3025         struct timeval now;
3026
3027         if (cmd) {
3028                 DEBUG_UNDO_HISTORY (
3029                     string_compose ("Current Undo Transaction %1, adding command: %2",
3030                                     _current_trans->name (),
3031                                     cmd->name ()));
3032                 _current_trans->add_command (cmd);
3033         }
3034
3035         DEBUG_UNDO_HISTORY (
3036             string_compose ("Commit Reversible Command, current transaction: %1",
3037                             _current_trans->name ()));
3038
3039         _current_trans_quarks.pop_front ();
3040
3041         if (!_current_trans_quarks.empty ()) {
3042                 DEBUG_UNDO_HISTORY (
3043                     string_compose ("Commit Reversible Command, transaction is not "
3044                                     "top-level, current transaction: %1",
3045                                     _current_trans->name ()));
3046                 /* the transaction we're committing is not the top-level one */
3047                 return;
3048         }
3049
3050         if (_current_trans->empty()) {
3051                 /* no commands were added to the transaction, so just get rid of it */
3052                 DEBUG_UNDO_HISTORY (
3053                     string_compose ("Commit Reversible Command, No commands were "
3054                                     "added to current transaction: %1",
3055                                     _current_trans->name ()));
3056                 delete _current_trans;
3057                 _current_trans = 0;
3058                 return;
3059         }
3060
3061         gettimeofday (&now, 0);
3062         _current_trans->set_timestamp (now);
3063
3064         _history.add (_current_trans);
3065         _current_trans = 0;
3066 }
3067
3068 static bool
3069 accept_all_audio_files (const string& path, void* /*arg*/)
3070 {
3071         if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
3072                 return false;
3073         }
3074
3075         if (!AudioFileSource::safe_audio_file_extension (path)) {
3076                 return false;
3077         }
3078
3079         return true;
3080 }
3081
3082 static bool
3083 accept_all_midi_files (const string& path, void* /*arg*/)
3084 {
3085         if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
3086                 return false;
3087         }
3088
3089         return (   (path.length() > 4 && path.find (".mid") != (path.length() - 4))
3090                 || (path.length() > 4 && path.find (".smf") != (path.length() - 4))
3091                 || (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
3092 }
3093
3094 static bool
3095 accept_all_state_files (const string& path, void* /*arg*/)
3096 {
3097         if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
3098                 return false;
3099         }
3100
3101         std::string const statefile_ext (statefile_suffix);
3102         if (path.length() >= statefile_ext.length()) {
3103                 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
3104         } else {
3105                 return false;
3106         }
3107 }
3108
3109 int
3110 Session::find_all_sources (string path, set<string>& result)
3111 {
3112         XMLTree tree;
3113         XMLNode* node;
3114
3115         if (!tree.read (path)) {
3116                 return -1;
3117         }
3118
3119         if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
3120                 return -2;
3121         }
3122
3123         XMLNodeList nlist;
3124         XMLNodeConstIterator niter;
3125
3126         nlist = node->children();
3127
3128         set_dirty();
3129
3130         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
3131
3132                 XMLProperty const * prop;
3133
3134                 if ((prop = (*niter)->property (X_("type"))) == 0) {
3135                         continue;
3136                 }
3137
3138                 DataType type (prop->value());
3139
3140                 if ((prop = (*niter)->property (X_("name"))) == 0) {
3141                         continue;
3142                 }
3143
3144                 if (Glib::path_is_absolute (prop->value())) {
3145                         /* external file, ignore */
3146                         continue;
3147                 }
3148
3149                 string found_path;
3150                 bool is_new;
3151                 uint16_t chan;
3152
3153                 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
3154                         result.insert (found_path);
3155                 }
3156         }
3157
3158         return 0;
3159 }
3160
3161 int
3162 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
3163 {
3164         vector<string> state_files;
3165         string ripped;
3166         string this_snapshot_path;
3167
3168         result.clear ();
3169
3170         ripped = _path;
3171
3172         if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
3173                 ripped = ripped.substr (0, ripped.length() - 1);
3174         }
3175
3176         find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
3177
3178         if (state_files.empty()) {
3179                 /* impossible! */
3180                 return 0;
3181         }
3182
3183         this_snapshot_path = Glib::build_filename (_path, legalize_for_path (_current_snapshot_name));
3184         this_snapshot_path += statefile_suffix;
3185
3186         for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
3187
3188                 cerr << "Looking at snapshot " << (*i) << " ( with this = [" << this_snapshot_path << "])\n";
3189
3190                 if (exclude_this_snapshot && *i == this_snapshot_path) {
3191                         cerr << "\texcluded\n";
3192                         continue;
3193
3194                 }
3195
3196                 if (find_all_sources (*i, result) < 0) {
3197                         return -1;
3198                 }
3199         }
3200
3201         return 0;
3202 }
3203
3204 struct RegionCounter {
3205         typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
3206         AudioSourceList::iterator iter;
3207         boost::shared_ptr<Region> region;
3208         uint32_t count;
3209
3210         RegionCounter() : count (0) {}
3211 };
3212
3213 int
3214 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
3215 {
3216         boost::optional<int> r = AskAboutPlaylistDeletion (p);
3217         return r.get_value_or (1);
3218 }
3219
3220 void
3221 Session::cleanup_regions ()
3222 {
3223         bool removed = false;
3224         const RegionFactory::RegionMap& regions (RegionFactory::regions());
3225
3226         for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
3227
3228                 uint32_t used = _playlists->region_use_count (i->second);
3229
3230                 if (used == 0 && !i->second->automatic ()) {
3231                         boost::weak_ptr<Region> w = i->second;
3232                         ++i;
3233                         removed = true;
3234                         RegionFactory::map_remove (w);
3235                 } else {
3236                         ++i;
3237                 }
3238         }
3239
3240         if (removed) {
3241                 // re-check to remove parent references of compound regions
3242                 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
3243                         if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
3244                                 ++i;
3245                                 continue;
3246                         }
3247                         assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
3248                         if (0 == _playlists->region_use_count (i->second)) {
3249                                 boost::weak_ptr<Region> w = i->second;
3250                                 ++i;
3251                                 RegionFactory::map_remove (w);
3252                         } else {
3253                                 ++i;
3254                         }
3255                 }
3256         }
3257
3258         /* dump the history list */
3259         _history.clear ();
3260
3261         save_state ("");
3262 }
3263
3264 bool
3265 Session::can_cleanup_peakfiles () const
3266 {
3267         if (deletion_in_progress()) {
3268                 return false;
3269         }
3270         if (!_writable || cannot_save ()) {
3271                 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
3272                 return false;
3273         }
3274         if (record_status() == Recording) {
3275                 error << _("Cannot cleanup peak-files while recording") << endmsg;
3276                 return false;
3277         }
3278         return true;
3279 }
3280
3281 int
3282 Session::cleanup_peakfiles ()
3283 {
3284         Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
3285         if (!lm.locked()) {
3286                 return -1;
3287         }
3288
3289         assert (can_cleanup_peakfiles ());
3290         assert (!peaks_cleanup_in_progres());
3291
3292         _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
3293
3294         int timeout = 5000; // 5 seconds
3295         while (!SourceFactory::files_with_peaks.empty()) {
3296                 Glib::usleep (1000);
3297                 if (--timeout < 0) {
3298                         warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
3299                         _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
3300                         return -1;
3301                 }
3302         }
3303
3304         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3305                 boost::shared_ptr<AudioSource> as;
3306                 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
3307                         as->close_peakfile();
3308                 }
3309         }
3310
3311         PBD::clear_directory (session_directory().peak_path());
3312
3313         _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
3314
3315         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3316                 boost::shared_ptr<AudioSource> as;
3317                 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
3318                         SourceFactory::setup_peakfile(as, true);
3319                 }
3320         }
3321         return 0;
3322 }
3323
3324 int
3325 Session::cleanup_sources (CleanupReport& rep)
3326 {
3327         // FIXME: needs adaptation to midi
3328
3329         vector<boost::shared_ptr<Source> > dead_sources;
3330         string audio_path;
3331         string midi_path;
3332         vector<string> candidates;
3333         vector<string> unused;
3334         set<string> sources_used_by_all_snapshots;
3335         string spath;
3336         int ret = -1;
3337         string tmppath1;
3338         string tmppath2;
3339         Searchpath asp;
3340         Searchpath msp;
3341         set<boost::shared_ptr<Source> > sources_used_by_this_snapshot;
3342
3343         _state_of_the_state = StateOfTheState (_state_of_the_state | InCleanup);
3344
3345         /* this is mostly for windows which doesn't allow file
3346          * renaming if the file is in use. But we don't special
3347          * case it because we need to know if this causes
3348          * problems, and the easiest way to notice that is to
3349          * keep it in place for all platforms.
3350          */
3351
3352         request_stop (false);
3353         _butler->summon ();
3354         _butler->wait_until_finished ();
3355
3356         /* consider deleting all unused playlists */
3357
3358         if (_playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
3359                 ret = 0;
3360                 goto out;
3361         }
3362
3363         /* sync the "all regions" property of each playlist with its current state */
3364
3365         _playlists->sync_all_regions_with_regions ();
3366
3367         /* find all un-used sources */
3368
3369         rep.paths.clear ();
3370         rep.space = 0;
3371
3372         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3373
3374                 SourceMap::iterator tmp;
3375
3376                 tmp = i;
3377                 ++tmp;
3378
3379                 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
3380                  * capture files.
3381                  */
3382
3383                 if (!i->second->used() && (i->second->length(i->second->natural_position()) > 0)) {
3384                         dead_sources.push_back (i->second);
3385                         i->second->drop_references ();
3386                 }
3387
3388                 i = tmp;
3389         }
3390
3391         /* build a list of all the possible audio directories for the session */
3392
3393         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3394                 SessionDirectory sdir ((*i).path);
3395                 asp += sdir.sound_path();
3396         }
3397         audio_path += asp.to_string();
3398
3399
3400         /* build a list of all the possible midi directories for the session */
3401
3402         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3403                 SessionDirectory sdir ((*i).path);
3404                 msp += sdir.midi_path();
3405         }
3406         midi_path += msp.to_string();
3407
3408         find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3409         find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3410
3411         /* add sources from all other snapshots as "used", but don't use this
3412                  snapshot because the state file on disk still references sources we
3413                  may have already dropped.
3414                  */
3415
3416         find_all_sources_across_snapshots (sources_used_by_all_snapshots, true);
3417
3418         /* Although the region factory has a list of all regions ever created
3419          * for this session, we're only interested in regions actually in
3420          * playlists right now. So merge all playlist regions lists together.
3421          *
3422          * This will include the playlists used within compound regions.
3423          */
3424
3425         _playlists->foreach (boost::bind (merge_all_sources, _1, &sources_used_by_this_snapshot));
3426
3427         /*  add our current source list
3428         */
3429
3430         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3431                 boost::shared_ptr<FileSource> fs;
3432                 SourceMap::iterator tmp = i;
3433                 ++tmp;
3434
3435                 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) == 0) {
3436                         /* not a file */
3437                         i = tmp;
3438                         continue;
3439                 }
3440
3441                 /* this is mostly for windows which doesn't allow file
3442                  * renaming if the file is in use. But we do not special
3443                  * case it because we need to know if this causes
3444                  * problems, and the easiest way to notice that is to
3445                  * keep it in place for all platforms.
3446                  */
3447
3448                 fs->close ();
3449
3450                 if (!fs->is_stub()) {
3451
3452                         /* Note that we're checking a list of all
3453                          * sources across all snapshots with the list
3454                          * of sources used by this snapshot.
3455                          */
3456
3457                         if (sources_used_by_this_snapshot.find (i->second) != sources_used_by_this_snapshot.end()) {
3458                                 /* this source is in use by this snapshot */
3459                                 sources_used_by_all_snapshots.insert (fs->path());
3460                                 cerr << "Source from source list found in used_by_this_snapshot (" << fs->path() << ")\n";
3461                         } else {
3462                                 cerr << "Source from source list NOT found in used_by_this_snapshot (" << fs->path() << ")\n";
3463                                 /* this source is NOT in use by this snapshot */
3464
3465                                 /* remove all related regions from RegionFactory master list */
3466
3467                                 RegionFactory::remove_regions_using_source (i->second);
3468
3469                                 /* remove from our current source list
3470                                  * also. We may not remove it from
3471                                  * disk, because it may be used by
3472                                  * other snapshots, but it isn't used inside this
3473                                  * snapshot anymore, so we don't need a
3474                                  * reference to it.
3475                                  */
3476
3477                                 sources.erase (i);
3478                         }
3479                 }
3480
3481                 i = tmp;
3482         }
3483
3484         /* now check each candidate source to see if it exists in the list of
3485          * sources_used_by_all_snapshots. If it doesn't, put it into "unused".
3486          */
3487
3488         cerr << "Candidates: " << candidates.size() << endl;
3489         cerr << "Used by others: " << sources_used_by_all_snapshots.size() << endl;
3490
3491         for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3492
3493                 bool used = false;
3494                 spath = *x;
3495
3496                 for (set<string>::iterator i = sources_used_by_all_snapshots.begin(); i != sources_used_by_all_snapshots.end(); ++i) {
3497
3498                         tmppath1 = canonical_path (spath);
3499                         tmppath2 = canonical_path ((*i));
3500
3501                         cerr << "\t => " << tmppath2 << endl;
3502
3503                         if (tmppath1 == tmppath2) {
3504                                 used = true;
3505                                 break;
3506                         }
3507                 }
3508
3509                 if (!used) {
3510                         unused.push_back (spath);
3511                 }
3512         }
3513
3514         cerr << "Actually unused: " << unused.size() << endl;
3515
3516         if (unused.empty()) {
3517                 /* Nothing to do */
3518                 ret = 0;
3519                 goto out;
3520         }
3521
3522         /* now try to move all unused files into the "dead" directory(ies) */
3523
3524         for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3525                 GStatBuf statbuf;
3526
3527                 string newpath;
3528
3529                 /* don't move the file across filesystems, just
3530                  * stick it in the `dead_dir_name' directory
3531                  * on whichever filesystem it was already on.
3532                  */
3533
3534                 if ((*x).find ("/sounds/") != string::npos) {
3535
3536                         /* old school, go up 1 level */
3537
3538                         newpath = Glib::path_get_dirname (*x);      // "sounds"
3539                         newpath = Glib::path_get_dirname (newpath); // "session-name"
3540
3541                 } else {
3542
3543                         /* new school, go up 4 levels */
3544
3545                         newpath = Glib::path_get_dirname (*x);      // "audiofiles" or "midifiles"
3546                         newpath = Glib::path_get_dirname (newpath); // "session-name"
3547                         newpath = Glib::path_get_dirname (newpath); // "interchange"
3548                         newpath = Glib::path_get_dirname (newpath); // "session-dir"
3549                 }
3550
3551                 newpath = Glib::build_filename (newpath, dead_dir_name);
3552
3553                 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3554                         error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3555                         return -1;
3556                 }
3557
3558                 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3559
3560                 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3561
3562                         /* the new path already exists, try versioning */
3563
3564                         char buf[PATH_MAX+1];
3565                         int version = 1;
3566                         string newpath_v;
3567
3568                         snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3569                         newpath_v = buf;
3570
3571                         while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3572                                 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3573                                 newpath_v = buf;
3574                         }
3575
3576                         if (version == 999) {
3577                                 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3578                                                 newpath)
3579                                         << endmsg;
3580                         } else {
3581                                 newpath = newpath_v;
3582                         }
3583
3584                 }
3585
3586                 if ((g_stat ((*x).c_str(), &statbuf) != 0) || (::g_rename ((*x).c_str(), newpath.c_str()) != 0)) {
3587                         error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"), (*x),
3588                                         newpath, g_strerror (errno)) << endmsg;
3589                         continue;
3590                 }
3591
3592                 /* see if there an easy to find peakfile for this file, and remove it.  */
3593
3594                 string base = Glib::path_get_basename (*x);
3595                 base += "%A"; /* this is what we add for the channel suffix of all native files,
3596                                                                          * or for the first channel of embedded files. it will miss
3597                                                                          * some peakfiles for other channels
3598                                                                          */
3599                 string peakpath = construct_peak_filepath (base);
3600
3601                 if (Glib::file_test (peakpath.c_str (), Glib::FILE_TEST_EXISTS)) {
3602                         if (::g_unlink (peakpath.c_str ()) != 0) {
3603                                 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"), peakpath, _path,
3604                                                 g_strerror (errno)) << endmsg;
3605                                 /* try to back out */
3606                                 ::g_rename (newpath.c_str (), _path.c_str ());
3607                                 goto out;
3608                         }
3609                 }
3610
3611                 rep.paths.push_back (*x);
3612                 rep.space += statbuf.st_size;
3613         }
3614
3615         /* dump the history list */
3616
3617         _history.clear ();
3618
3619         /* save state so we don't end up a session file
3620          * referring to non-existent sources.
3621          */
3622
3623         save_state ("");
3624         ret = 0;
3625
3626 out:
3627         _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
3628
3629         return ret;
3630 }
3631
3632 int
3633 Session::cleanup_trash_sources (CleanupReport& rep)
3634 {
3635         // FIXME: needs adaptation for MIDI
3636
3637         vector<space_and_path>::iterator i;
3638         string dead_dir;
3639
3640         rep.paths.clear ();
3641         rep.space = 0;
3642
3643         for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3644
3645                 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3646
3647                 clear_directory (dead_dir, &rep.space, &rep.paths);
3648         }
3649
3650         return 0;
3651 }
3652
3653 void
3654 Session::set_dirty ()
3655 {
3656         /* return early if there's nothing to do */
3657         if (dirty ()) {
3658                 return;
3659         }
3660
3661         /* never mark session dirty during loading */
3662         if (loading () || deletion_in_progress ()) {
3663                 return;
3664         }
3665
3666         _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3667         DirtyChanged(); /* EMIT SIGNAL */
3668 }
3669
3670 void
3671 Session::set_clean ()
3672 {
3673         bool was_dirty = dirty();
3674
3675         _state_of_the_state = Clean;
3676
3677         if (was_dirty) {
3678                 DirtyChanged(); /* EMIT SIGNAL */
3679         }
3680 }
3681
3682 void
3683 Session::unset_dirty (bool emit_dirty_changed)
3684 {
3685         bool was_dirty = dirty();
3686
3687         _state_of_the_state = StateOfTheState (_state_of_the_state & (~Dirty));
3688
3689         if (was_dirty && emit_dirty_changed) {
3690                 DirtyChanged (); /* EMIT SIGNAL */
3691         }
3692 }
3693
3694 void
3695 Session::set_deletion_in_progress ()
3696 {
3697         _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3698 }
3699
3700 void
3701 Session::clear_deletion_in_progress ()
3702 {
3703         _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3704 }
3705
3706 void
3707 Session::add_controllable (boost::shared_ptr<Controllable> c)
3708 {
3709         /* this adds a controllable to the list managed by the Session.
3710            this is a subset of those managed by the Controllable class
3711            itself, and represents the only ones whose state will be saved
3712            as part of the session.
3713         */
3714
3715         Glib::Threads::Mutex::Lock lm (controllables_lock);
3716         controllables.insert (c);
3717 }
3718
3719 boost::shared_ptr<Controllable>
3720 Session::controllable_by_id (const PBD::ID& id)
3721 {
3722         Glib::Threads::Mutex::Lock lm (controllables_lock);
3723
3724         for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3725                 if ((*i)->id() == id) {
3726                         return *i;
3727                 }
3728         }
3729
3730         return boost::shared_ptr<Controllable>();
3731 }
3732
3733 boost::shared_ptr<AutomationControl>
3734 Session::automation_control_by_id (const PBD::ID& id)
3735 {
3736         return boost::dynamic_pointer_cast<AutomationControl> (controllable_by_id (id));
3737 }
3738
3739 void
3740 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3741 {
3742         if (_writable) {
3743                 Stateful::add_instant_xml (node, _path);
3744         }
3745
3746         if (write_to_config) {
3747                 Config->add_instant_xml (node);
3748         }
3749 }
3750
3751 XMLNode*
3752 Session::instant_xml (const string& node_name)
3753 {
3754 #ifdef MIXBUS // "Safe Mode" (shift + click open) -> also ignore instant.xml
3755         if (get_disable_all_loaded_plugins ()) {
3756                 return NULL;
3757         }
3758 #endif
3759         return Stateful::instant_xml (node_name, _path);
3760 }
3761
3762 int
3763 Session::save_history (string snapshot_name)
3764 {
3765         XMLTree tree;
3766
3767         if (!_writable) {
3768                 return 0;
3769         }
3770
3771         if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3772             (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3773                 return 0;
3774         }
3775
3776         if (snapshot_name.empty()) {
3777                 snapshot_name = _current_snapshot_name;
3778         }
3779
3780         const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3781         const string backup_filename = history_filename + backup_suffix;
3782         const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3783         const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3784
3785         if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3786                 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3787                         error << _("could not backup old history file, current history not saved") << endmsg;
3788                         return -1;
3789                 }
3790         }
3791
3792         tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3793
3794         if (!tree.write (xml_path))
3795         {
3796                 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3797
3798                 if (g_remove (xml_path.c_str()) != 0) {
3799                         error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3800                                         xml_path, g_strerror (errno)) << endmsg;
3801                 }
3802                 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3803                         error << string_compose (_("could not restore history file from backup %1 (%2)"),
3804                                         backup_path, g_strerror (errno)) << endmsg;
3805                 }
3806
3807                 return -1;
3808         }
3809
3810         return 0;
3811 }
3812
3813 int
3814 Session::restore_history (string snapshot_name)
3815 {
3816         XMLTree tree;
3817
3818         if (snapshot_name.empty()) {
3819                 snapshot_name = _current_snapshot_name;
3820         }
3821
3822         const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3823         const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3824
3825         info << "Loading history from " << xml_path << endmsg;
3826
3827         if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3828                 info << string_compose (_("%1: no history file \"%2\" for this session."),
3829                                 _name, xml_path) << endmsg;
3830                 return 1;
3831         }
3832
3833         if (!tree.read (xml_path)) {
3834                 error << string_compose (_("Could not understand session history file \"%1\""),
3835                                 xml_path) << endmsg;
3836                 return -1;
3837         }
3838
3839         // replace history
3840         _history.clear();
3841
3842         for (XMLNodeConstIterator it  = tree.root()->children().begin(); it != tree.root()->children().end(); ++it) {
3843
3844                 XMLNode *t = *it;
3845
3846                 std::string name;
3847                 int64_t tv_sec;
3848                 int64_t tv_usec;
3849
3850                 if (!t->get_property ("name", name) || !t->get_property ("tv-sec", tv_sec) ||
3851                     !t->get_property ("tv-usec", tv_usec)) {
3852                         continue;
3853                 }
3854
3855                 UndoTransaction* ut = new UndoTransaction ();
3856                 ut->set_name (name);
3857
3858                 struct timeval tv;
3859                 tv.tv_sec = tv_sec;
3860                 tv.tv_usec = tv_usec;
3861                 ut->set_timestamp(tv);
3862
3863                 for (XMLNodeConstIterator child_it  = t->children().begin();
3864                                 child_it != t->children().end(); child_it++)
3865                 {
3866                         XMLNode *n = *child_it;
3867                         Command *c;
3868
3869                         if (n->name() == "MementoCommand" ||
3870                                         n->name() == "MementoUndoCommand" ||
3871                                         n->name() == "MementoRedoCommand") {
3872
3873                                 if ((c = memento_command_factory(n))) {
3874                                         ut->add_command(c);
3875                                 }
3876
3877                         } else if (n->name() == "NoteDiffCommand") {
3878                                 PBD::ID id (n->property("midi-source")->value());
3879                                 boost::shared_ptr<MidiSource> midi_source =
3880                                         boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3881                                 if (midi_source) {
3882                                         ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3883                                 } else {
3884                                         error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3885                                 }
3886
3887                         } else if (n->name() == "SysExDiffCommand") {
3888
3889                                 PBD::ID id (n->property("midi-source")->value());
3890                                 boost::shared_ptr<MidiSource> midi_source =
3891                                         boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3892                                 if (midi_source) {
3893                                         ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3894                                 } else {
3895                                         error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3896                                 }
3897
3898                         } else if (n->name() == "PatchChangeDiffCommand") {
3899
3900                                 PBD::ID id (n->property("midi-source")->value());
3901                                 boost::shared_ptr<MidiSource> midi_source =
3902                                         boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3903                                 if (midi_source) {
3904                                         ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3905                                 } else {
3906                                         error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3907                                 }
3908
3909                         } else if (n->name() == "StatefulDiffCommand") {
3910                                 if ((c = stateful_diff_command_factory (n))) {
3911                                         ut->add_command (c);
3912                                 }
3913                         } else {
3914                                 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3915                         }
3916                 }
3917
3918                 _history.add (ut);
3919         }
3920
3921         return 0;
3922 }
3923
3924 void
3925 Session::config_changed (std::string p, bool ours)
3926 {
3927         if (ours) {
3928                 set_dirty ();
3929         }
3930
3931         if (p == "auto-loop") {
3932
3933         } else if (p == "session-monitoring") {
3934
3935         } else if (p == "auto-input") {
3936
3937                 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3938                         /* auto-input only makes a difference if we're rolling */
3939                         set_track_monitor_input_status (!config.get_auto_input());
3940                 }
3941
3942         } else if (p == "punch-in") {
3943
3944                 Location* location;
3945
3946                 if ((location = _locations->auto_punch_location()) != 0) {
3947
3948                         if (config.get_punch_in ()) {
3949                                 auto_punch_start_changed (location);
3950                         } else {
3951                                 clear_events (SessionEvent::PunchIn);
3952                         }
3953                 }
3954
3955         } else if (p == "punch-out") {
3956
3957                 Location* location;
3958
3959                 if ((location = _locations->auto_punch_location()) != 0) {
3960
3961                         if (config.get_punch_out()) {
3962                                 auto_punch_end_changed (location);
3963                         } else {
3964                                 clear_events (SessionEvent::PunchOut);
3965                         }
3966                 }
3967
3968         } else if (p == "edit-mode") {
3969
3970                 Glib::Threads::Mutex::Lock lm (_playlists->lock);
3971
3972                 for (SessionPlaylists::List::iterator i = _playlists->playlists.begin(); i != _playlists->playlists.end(); ++i) {
3973                         (*i)->set_edit_mode (Config->get_edit_mode ());
3974                 }
3975
3976         } else if (p == "use-video-sync") {
3977
3978                 waiting_for_sync_offset = config.get_use_video_sync();
3979
3980         } else if (p == "mmc-control") {
3981
3982                 //poke_midi_thread ();
3983
3984         } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3985
3986                 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3987
3988         } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3989
3990                 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3991
3992         } else if (p == "midi-control") {
3993
3994                 //poke_midi_thread ();
3995
3996         } else if (p == "raid-path") {
3997
3998                 setup_raid_path (config.get_raid_path());
3999
4000         } else if (p == "timecode-format") {
4001
4002                 sync_time_vars ();
4003
4004         } else if (p == "video-pullup") {
4005
4006                 sync_time_vars ();
4007
4008         } else if (p == "seamless-loop") {
4009
4010                 if (play_loop && transport_rolling()) {
4011                         // to reset diskstreams etc
4012                         request_play_loop (true);
4013                 }
4014
4015         } else if (p == "click-sound") {
4016
4017                 setup_click_sounds (1);
4018
4019         } else if (p == "click-emphasis-sound") {
4020
4021                 setup_click_sounds (-1);
4022
4023         } else if (p == "clicking") {
4024
4025                 if (Config->get_clicking()) {
4026                         if (_click_io && click_data) { // don't require emphasis data
4027                                 _clicking = true;
4028                         }
4029                 } else {
4030                         _clicking = false;
4031                 }
4032
4033         } else if (p == "click-record-only") {
4034
4035                         _click_rec_only = Config->get_click_record_only();
4036
4037         } else if (p == "click-gain") {
4038
4039                 if (_click_gain) {
4040                         _click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
4041                 }
4042
4043         } else if (p == "send-mtc") {
4044
4045                 if (Config->get_send_mtc ()) {
4046                         /* mark us ready to send */
4047                         next_quarter_frame_to_send = 0;
4048                 }
4049
4050         } else if (p == "send-mmc") {
4051
4052                 _mmc->enable_send (Config->get_send_mmc ());
4053                 if (Config->get_send_mmc ()) {
4054                         /* re-initialize MMC */
4055                         send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
4056                         send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
4057                 }
4058
4059         } else if (p == "jack-time-master") {
4060
4061                 engine().reset_timebase ();
4062
4063         } else if (p == "native-file-header-format") {
4064
4065                 if (!first_file_header_format_reset) {
4066                         reset_native_file_format ();
4067                 }
4068
4069                 first_file_header_format_reset = false;
4070
4071         } else if (p == "native-file-data-format") {
4072
4073                 if (!first_file_data_format_reset) {
4074                         reset_native_file_format ();
4075                 }
4076
4077                 first_file_data_format_reset = false;
4078
4079         } else if (p == "external-sync") {
4080                 request_sync_source (TransportMasterManager::instance().current());
4081         }  else if (p == "denormal-model") {
4082                 setup_fpu ();
4083         } else if (p == "history-depth") {
4084                 set_history_depth (Config->get_history_depth());
4085         } else if (p == "remote-model") {
4086                 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
4087                    TO SET REMOTE ID'S
4088                 */
4089         } else if (p == "initial-program-change") {
4090
4091                 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
4092                         MIDI::byte buf[2];
4093
4094                         buf[0] = MIDI::program; // channel zero by default
4095                         buf[1] = (Config->get_initial_program_change() & 0x7f);
4096
4097                         _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
4098                 }
4099         } else if (p == "solo-mute-override") {
4100                 // catch_up_on_solo_mute_override ();
4101         } else if (p == "listen-position" || p == "pfl-position") {
4102                 listen_position_changed ();
4103         } else if (p == "solo-control-is-listen-control") {
4104                 solo_control_mode_changed ();
4105         } else if (p == "solo-mute-gain") {
4106                 _solo_cut_control->Changed (true, Controllable::NoGroup);
4107         } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
4108                 last_timecode_valid = false;
4109         } else if (p == "playback-buffer-seconds") {
4110                 AudioSource::allocate_working_buffers (sample_rate());
4111         } else if (p == "ltc-sink-port") {
4112                 reconnect_ltc_output ();
4113         } else if (p == "timecode-generator-offset") {
4114                 ltc_tx_parse_offset();
4115         } else if (p == "auto-return-target-list") {
4116                 if (!loading()) {
4117                         follow_playhead_priority ();
4118                 }
4119         } else if (p == "use-monitor-bus") {
4120                 /* NB. This is always called when constructing a session,
4121                  * after restoring session state (if any),
4122                  * via post_engine_init() -> Config->map_parameters()
4123                  */
4124                 bool want_ms = Config->get_use_monitor_bus();
4125                 bool have_ms = _monitor_out ? true : false;
4126                 if (loading ()) {
4127                         /* When loading an existing session, the config "use-monitor-bus"
4128                          * is ignored. Instead the sesion-state (xml) will have added the
4129                          * "monitor-route" and restored its state (and connections)
4130                          * if the session has a monitor-section.
4131                          * Update the config to reflect this.
4132                          */
4133                         if (want_ms != have_ms) {
4134                                 Config->set_use_monitor_bus (have_ms);
4135                         }
4136                         MonitorBusAddedOrRemoved (); /* EMIT SIGNAL */
4137                 } else  {
4138                         /* Otherwise, Config::set_use_monitor_bus() does
4139                          * control the the presence of the monitor-section
4140                          * (new sessions, user initiated change)
4141                          */
4142                         if (want_ms && !have_ms) {
4143                                 add_monitor_section ();
4144                         } else if (!want_ms && have_ms) {
4145                                 remove_monitor_section ();
4146                         }
4147                 }
4148         }
4149
4150         set_dirty ();
4151 }
4152
4153 void
4154 Session::set_history_depth (uint32_t d)
4155 {
4156         _history.set_depth (d);
4157 }
4158
4159 /** Connect things to the MMC object */
4160 void
4161 Session::setup_midi_machine_control ()
4162 {
4163         _mmc = new MIDI::MachineControl;
4164
4165         boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
4166         boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
4167
4168         if (!async_out || !async_out) {
4169                 return;
4170         }
4171
4172         /* XXXX argh, passing raw pointers back into libmidi++ */
4173
4174         MIDI::Port* mmc_in = async_in.get();
4175         MIDI::Port* mmc_out = async_out.get();
4176
4177         _mmc->set_ports (mmc_in, mmc_out);
4178
4179         _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
4180         _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
4181         _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
4182         _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
4183         _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
4184         _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
4185         _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
4186         _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
4187         _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
4188         _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
4189         _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
4190         _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
4191         _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
4192
4193         /* also handle MIDI SPP because its so common */
4194
4195         _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
4196         _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
4197         _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
4198 }
4199
4200 boost::shared_ptr<Controllable>
4201 Session::solo_cut_control() const
4202 {
4203         /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
4204          * controls in Ardour that currently get presented to the user in the GUI that require
4205          * access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
4206          *
4207          * its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
4208          * it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
4209          * parameter.
4210          */
4211         return _solo_cut_control;
4212 }
4213
4214 void
4215 Session::save_snapshot_name (const std::string & n)
4216 {
4217         /* assure Stateful::_instant_xml is loaded
4218          * add_instant_xml() only adds to existing data and defaults
4219          * to use an empty Tree otherwise
4220          */
4221         instant_xml ("LastUsedSnapshot");
4222
4223         XMLNode last_used_snapshot ("LastUsedSnapshot");
4224         last_used_snapshot.set_property ("name", n);
4225         add_instant_xml (last_used_snapshot, false);
4226 }
4227
4228 void
4229 Session::set_snapshot_name (const std::string & n)
4230 {
4231         _current_snapshot_name = n;
4232         save_snapshot_name (n);
4233 }
4234
4235 int
4236 Session::rename (const std::string& new_name)
4237 {
4238         string legal_name = legalize_for_path (new_name);
4239         string new_path;
4240         string oldstr;
4241         string newstr;
4242         bool first = true;
4243
4244         string const old_sources_root = _session_dir->sources_root();
4245
4246         if (!_writable || cannot_save ()) {
4247                 error << _("Cannot rename read-only session.") << endmsg;
4248                 return 0; // don't show "messed up" warning
4249         }
4250         if (record_status() == Recording) {
4251                 error << _("Cannot rename session while recording") << endmsg;
4252                 return 0; // don't show "messed up" warning
4253         }
4254
4255         StateProtector stp (this);
4256
4257         /* Rename:
4258
4259          * session directory
4260          * interchange subdirectory
4261          * session file
4262          * session history
4263
4264          * Backup files are left unchanged and not renamed.
4265          */
4266
4267         /* Windows requires that we close all files before attempting the
4268          * rename. This works on other platforms, but isn't necessary there.
4269          * Leave it in place for all platforms though, since it may help
4270          * catch issues that could arise if the way Source files work ever
4271          * change (since most developers are not using Windows).
4272          */
4273
4274         for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4275                 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4276                 if (fs) {
4277                         fs->close ();
4278                 }
4279         }
4280
4281         /* pass one: not 100% safe check that the new directory names don't
4282          * already exist ...
4283          */
4284
4285         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4286
4287                 oldstr = (*i).path;
4288
4289                 /* this is a stupid hack because Glib::path_get_dirname() is
4290                  * lexical-only, and so passing it /a/b/c/ gives a different
4291                  * result than passing it /a/b/c ...
4292                  */
4293
4294                 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4295                         oldstr = oldstr.substr (0, oldstr.length() - 1);
4296                 }
4297
4298                 string base = Glib::path_get_dirname (oldstr);
4299
4300                 newstr = Glib::build_filename (base, legal_name);
4301
4302                 cerr << "Looking for " << newstr << endl;
4303
4304                 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4305                         cerr << " exists\n";
4306                         return -1;
4307                 }
4308         }
4309
4310         /* Session dirs */
4311
4312         first = true;
4313
4314         for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4315
4316                 vector<string> v;
4317
4318                 oldstr = (*i).path;
4319
4320                 /* this is a stupid hack because Glib::path_get_dirname() is
4321                  * lexical-only, and so passing it /a/b/c/ gives a different
4322                  * result than passing it /a/b/c ...
4323                  */
4324
4325                 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4326                         oldstr = oldstr.substr (0, oldstr.length() - 1);
4327                 }
4328
4329                 string base = Glib::path_get_dirname (oldstr);
4330                 newstr = Glib::build_filename (base, legal_name);
4331
4332                 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4333
4334                 cerr << "Rename " << oldstr << " => " << newstr << endl;
4335                 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4336                         cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4337                         error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4338                         return 1;
4339                 }
4340
4341                 /* Reset path in "session dirs" */
4342
4343                 (*i).path = newstr;
4344                 (*i).blocks = 0;
4345
4346                 /* reset primary SessionDirectory object */
4347
4348                 if (first) {
4349                         (*_session_dir) = newstr;
4350                         new_path = newstr;
4351                         first = false;
4352                 }
4353
4354                 /* now rename directory below session_dir/interchange */
4355
4356                 string old_interchange_dir;
4357                 string new_interchange_dir;
4358
4359                 /* use newstr here because we renamed the path
4360                  * (folder/directory) that used to be oldstr to newstr above
4361                  */
4362
4363                 v.push_back (newstr);
4364                 v.push_back (interchange_dir_name);
4365                 v.push_back (Glib::path_get_basename (oldstr));
4366
4367                 old_interchange_dir = Glib::build_filename (v);
4368
4369                 v.clear ();
4370                 v.push_back (newstr);
4371                 v.push_back (interchange_dir_name);
4372                 v.push_back (legal_name);
4373
4374                 new_interchange_dir = Glib::build_filename (v);
4375
4376                 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4377
4378                 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4379                         cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4380                                                 old_interchange_dir, new_interchange_dir,
4381                                                 g_strerror (errno))
4382                              << endl;
4383                         error << string_compose (_("renaming %s as %2 failed (%3)"),
4384                                                  old_interchange_dir, new_interchange_dir,
4385                                                  g_strerror (errno))
4386                               << endmsg;
4387                         return 1;
4388                 }
4389         }
4390
4391         /* state file */
4392
4393         oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4394         newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4395
4396         cerr << "Rename " << oldstr << " => " << newstr << endl;
4397
4398         if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4399                 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4400                 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4401                 return 1;
4402         }
4403
4404         /* history file */
4405
4406         oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4407
4408         if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS))  {
4409                 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4410
4411                 cerr << "Rename " << oldstr << " => " << newstr << endl;
4412
4413                 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4414                         cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4415                         error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4416                         return 1;
4417                 }
4418         }
4419
4420         /* remove old name from recent sessions */
4421         remove_recent_sessions (_path);
4422         _path = new_path;
4423
4424         /* update file source paths */
4425
4426         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4427                 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4428                 if (fs) {
4429                         string p = fs->path ();
4430                         boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4431                         fs->set_path (p);
4432                         SourceFactory::setup_peakfile(i->second, true);
4433                 }
4434         }
4435
4436         set_snapshot_name (new_name);
4437         _name = new_name;
4438
4439         set_dirty ();
4440
4441         /* save state again to get everything just right */
4442
4443         save_state (_current_snapshot_name);
4444
4445         /* add to recent sessions */
4446
4447         store_recent_sessions (new_name, _path);
4448
4449         return 0;
4450 }
4451
4452 int
4453 Session::parse_stateful_loading_version (const std::string& version)
4454 {
4455         if (version.empty ()) {
4456                 /* no version implies very old version of Ardour */
4457                 return 1000;
4458         }
4459
4460         if (version.find ('.') != string::npos) {
4461                 /* old school version format */
4462                 if (version[0] == '2') {
4463                         return 2000;
4464                 } else {
4465                         return 3000;
4466                 }
4467         } else {
4468                 return string_to<int32_t>(version);
4469         }
4470 }
4471
4472 int
4473 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format, std::string& program_version)
4474 {
4475         bool found_sr = false;
4476         bool found_data_format = false;
4477         std::string version;
4478         program_version = "";
4479
4480         if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4481                 return -1;
4482         }
4483
4484         xmlParserCtxtPtr ctxt = xmlNewParserCtxt();
4485         if (ctxt == NULL) {
4486                 return -1;
4487         }
4488         xmlDocPtr doc = xmlCtxtReadFile (ctxt, xmlpath.c_str(), NULL, XML_PARSE_HUGE);
4489
4490         if (doc == NULL) {
4491                 xmlFreeParserCtxt(ctxt);
4492                 return -1;
4493         }
4494
4495         xmlNodePtr node = xmlDocGetRootElement(doc);
4496
4497         if (node == NULL) {
4498                 xmlFreeParserCtxt(ctxt);
4499                 xmlFreeDoc (doc);
4500                 return -1;
4501         }
4502
4503         /* sample rate & version*/
4504
4505         xmlAttrPtr attr;
4506         for (attr = node->properties; attr; attr = attr->next) {
4507                 if (!strcmp ((const char*)attr->name, "version") && attr->children) {
4508                         version = std::string ((char*)attr->children->content);
4509                 }
4510                 if (!strcmp ((const char*)attr->name, "sample-rate") && attr->children) {
4511                         sample_rate = atoi ((char*)attr->children->content);
4512                         found_sr = true;
4513                 }
4514         }
4515
4516         if ((parse_stateful_loading_version(version) / 1000L) > (CURRENT_SESSION_FILE_VERSION / 1000L)) {
4517                 return -1;
4518         }
4519
4520         node = node->children;
4521         while (node != NULL) {
4522                  if (!strcmp((const char*) node->name, "ProgramVersion")) {
4523                          xmlChar* val = xmlGetProp (node, (const xmlChar*)"modified-with");
4524                          if (val) {
4525                                  program_version = string ((const char*)val);
4526                                  size_t sep = program_version.find_first_of("-");
4527                                  if (sep != string::npos) {
4528                                          program_version = program_version.substr (0, sep);
4529                                  }
4530                          }
4531                          xmlFree (val);
4532                  }
4533                  if (strcmp((const char*) node->name, "Config")) {
4534                          node = node->next;
4535                          continue;
4536                  }
4537                  for (node = node->children; node; node = node->next) {
4538                          xmlChar* pv = xmlGetProp (node, (const xmlChar*)"name");
4539                          if (pv && !strcmp ((const char*)pv, "native-file-data-format")) {
4540                                  xmlFree (pv);
4541                                  xmlChar* val = xmlGetProp (node, (const xmlChar*)"value");
4542                                  if (val) {
4543                                          try {
4544                                                  SampleFormat fmt = (SampleFormat) string_2_enum (string ((const char*)val), fmt);
4545                                                  data_format = fmt;
4546                                                  found_data_format = true;
4547                                          } catch (PBD::unknown_enumeration& e) {}
4548                                  }
4549                                  xmlFree (val);
4550                                  break;
4551                          }
4552                          xmlFree (pv);
4553                  }
4554                  break;
4555         }
4556
4557         xmlFreeParserCtxt(ctxt);
4558         xmlFreeDoc (doc);
4559
4560         return (found_sr && found_data_format) ? 0 : 1;
4561 }
4562
4563 std::string
4564 Session::get_snapshot_from_instant (const std::string& session_dir)
4565 {
4566         std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4567
4568         if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4569                 return "";
4570         }
4571
4572         XMLTree tree;
4573         if (!tree.read (instant_xml_path)) {
4574                 return "";
4575         }
4576
4577         XMLProperty const * prop;
4578         XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4579         if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4580                 return prop->value();
4581         }
4582
4583         return "";
4584 }
4585
4586 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4587 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4588
4589 int
4590 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4591 {
4592         uint32_t total = 0;
4593         uint32_t n = 0;
4594         SourcePathMap source_path_map;
4595         string new_path;
4596         boost::shared_ptr<AudioFileSource> afs;
4597         int ret = 0;
4598
4599         {
4600
4601                 Glib::Threads::Mutex::Lock lm (source_lock);
4602
4603                 cerr << " total sources = " << sources.size();
4604
4605                 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4606                         boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4607
4608                         if (!fs) {
4609                                 continue;
4610                         }
4611
4612                         if (fs->within_session()) {
4613                                 continue;
4614                         }
4615
4616                         if (source_path_map.find (fs->path()) != source_path_map.end()) {
4617                                 source_path_map[fs->path()].push_back (fs);
4618                         } else {
4619                                 SeveralFileSources v;
4620                                 v.push_back (fs);
4621                                 source_path_map.insert (make_pair (fs->path(), v));
4622                         }
4623
4624                         total++;
4625                 }
4626
4627                 cerr << " fsources = " << total << endl;
4628
4629                 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4630
4631                         /* tell caller where we are */
4632
4633                         string old_path = i->first;
4634
4635                         callback (n, total, old_path);
4636
4637                         cerr << old_path << endl;
4638
4639                         new_path.clear ();
4640
4641                         switch (i->second.front()->type()) {
4642                         case DataType::AUDIO:
4643                                 new_path = new_audio_source_path_for_embedded (old_path);
4644                                 break;
4645
4646                         case DataType::MIDI:
4647                                 /* XXX not implemented yet */
4648                                 break;
4649                         }
4650
4651                         if (new_path.empty()) {
4652                                 continue;
4653                         }
4654
4655                         cerr << "Move " << old_path << " => " << new_path << endl;
4656
4657                         if (!copy_file (old_path, new_path)) {
4658                                 cerr << "failed !\n";
4659                                 ret = -1;
4660                         }
4661
4662                         /* make sure we stop looking in the external
4663                            dir/folder. Remember, this is an all-or-nothing
4664                            operations, it doesn't merge just some files.
4665                         */
4666                         remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4667
4668                         for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4669                                 (*f)->set_path (new_path);
4670                         }
4671                 }
4672         }
4673
4674         save_state ("", false, false);
4675
4676         return ret;
4677 }
4678
4679 static
4680 bool accept_all_files (string const &, void *)
4681 {
4682         return true;
4683 }
4684
4685 void
4686 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4687 {
4688         /* 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.
4689         */
4690 }
4691
4692 static string
4693 make_new_media_path (string old_path, string new_session_folder, string new_session_name)
4694 {
4695         // old_path must be in within_session ()
4696         string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4697         vector<string> v;
4698         v.push_back (new_session_folder); /* full path */
4699         v.push_back (interchange_dir_name);
4700         v.push_back (new_session_name);   /* just one directory/folder */
4701         v.push_back (typedir);
4702         v.push_back (Glib::path_get_basename (old_path));
4703
4704         return Glib::build_filename (v);
4705 }
4706
4707 static string
4708 make_new_audio_path (string filename, string new_session_folder, string new_session_name)
4709 {
4710         vector<string> v;
4711         v.push_back (new_session_folder); /* full path */
4712         v.push_back (interchange_dir_name);
4713         v.push_back (new_session_name);
4714         v.push_back (ARDOUR::sound_dir_name);
4715         v.push_back (filename);
4716
4717         return Glib::build_filename (v);
4718 }
4719
4720 int
4721 Session::save_as (SaveAs& saveas)
4722 {
4723         vector<string> files;
4724         string current_folder = Glib::path_get_dirname (_path);
4725         string new_folder = legalize_for_path (saveas.new_name);
4726         string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4727         int64_t total_bytes = 0;
4728         int64_t copied = 0;
4729         int64_t cnt = 0;
4730         int64_t all = 0;
4731         int32_t internal_file_cnt = 0;
4732
4733         vector<string> do_not_copy_extensions;
4734         do_not_copy_extensions.push_back (statefile_suffix);
4735         do_not_copy_extensions.push_back (pending_suffix);
4736         do_not_copy_extensions.push_back (backup_suffix);
4737         do_not_copy_extensions.push_back (temp_suffix);
4738         do_not_copy_extensions.push_back (history_suffix);
4739
4740         /* get total size */
4741
4742         for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4743
4744                 /* need to clear this because
4745                  * find_files_matching_filter() is cumulative
4746                  */
4747
4748                 files.clear ();
4749
4750                 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4751
4752                 all += files.size();
4753
4754                 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4755                         GStatBuf gsb;
4756                         g_stat ((*i).c_str(), &gsb);
4757                         total_bytes += gsb.st_size;
4758                 }
4759         }
4760
4761         /* save old values so we can switch back if we are not switching to the new session */
4762
4763         string old_path = _path;
4764         string old_name = _name;
4765         string old_snapshot = _current_snapshot_name;
4766         string old_sd = _session_dir->root_path();
4767         vector<string> old_search_path[DataType::num_types];
4768         string old_config_search_path[DataType::num_types];
4769
4770         old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4771         old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4772         old_config_search_path[DataType::AUDIO]  = config.get_audio_search_path ();
4773         old_config_search_path[DataType::MIDI]  = config.get_midi_search_path ();
4774
4775         /* switch session directory */
4776
4777         (*_session_dir) = to_dir;
4778
4779         /* create new tree */
4780
4781         if (!_session_dir->create()) {
4782                 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4783                 return -1;
4784         }
4785
4786         try {
4787                 /* copy all relevant files. Find each location in session_dirs,
4788                  * and copy files from there to target.
4789                  */
4790
4791                 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4792
4793                         /* need to clear this because
4794                          * find_files_matching_filter() is cumulative
4795                          */
4796
4797                         files.clear ();
4798
4799                         const size_t prefix_len = (*sd).path.size();
4800
4801                         /* Work just on the files within this session dir */
4802
4803                         find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4804
4805                         /* add dir separator to protect against collisions with
4806                          * track names (e.g. track named "audiofiles" or
4807                          * "analysis".
4808                          */
4809
4810                         static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4811                         static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4812                         static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4813
4814                         /* copy all the files. Handling is different for media files
4815                            than others because of the *silly* subtree we have below the interchange
4816                            folder. That really was a bad idea, but I'm not fixing it as part of
4817                            implementing ::save_as().
4818                         */
4819
4820                         for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4821
4822                                 std::string from = *i;
4823
4824 #ifdef __APPLE__
4825                                 string filename = Glib::path_get_basename (from);
4826                                 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4827                                 if (filename == ".DS_STORE") {
4828                                         continue;
4829                                 }
4830 #endif
4831
4832                                 if (from.find (audiofile_dir_string) != string::npos) {
4833
4834                                         /* audio file: only copy if asked */
4835
4836                                         if (saveas.include_media && saveas.copy_media) {
4837
4838                                                 string to = make_new_media_path (*i, to_dir, new_folder);
4839
4840                                                 info << "media file copying from " << from << " to " << to << endmsg;
4841
4842                                                 if (!copy_file (from, to)) {
4843                                                         throw Glib::FileError (Glib::FileError::IO_ERROR,
4844                                                                                                    string_compose(_("\ncopying \"%1\" failed !"), from));
4845                                                 }
4846                                         }
4847
4848                                         /* we found media files inside the session folder */
4849
4850                                         internal_file_cnt++;
4851
4852                                 } else if (from.find (midifile_dir_string) != string::npos) {
4853
4854                                         /* midi file: always copy unless
4855                                          * creating an empty new session
4856                                          */
4857
4858                                         if (saveas.include_media) {
4859
4860                                                 string to = make_new_media_path (*i, to_dir, new_folder);
4861
4862                                                 info << "media file copying from " << from << " to " << to << endmsg;
4863
4864                                                 if (!copy_file (from, to)) {
4865                                                         throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4866                                                 }
4867                                         }
4868
4869                                         /* we found media files inside the session folder */
4870
4871                                         internal_file_cnt++;
4872
4873                                 } else if (from.find (analysis_dir_string) != string::npos) {
4874
4875                                         /*  make sure analysis dir exists in
4876                                          *  new session folder, but we're not
4877                                          *  copying analysis files here, see
4878                                          *  below
4879                                          */
4880
4881                                         (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4882                                         continue;
4883
4884                                 } else {
4885
4886                                         /* normal non-media file. Don't copy state, history, etc.
4887                                          */
4888
4889                                         bool do_copy = true;
4890
4891                                         for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4892                                                 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4893                                                         /* end of filename matches extension, do not copy file */
4894                                                         do_copy = false;
4895                                                         break;
4896                                                 }
4897                                         }
4898
4899                                         if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4900                                                 /* don't copy peakfiles if
4901                                                  * we're not copying media
4902                                                  */
4903                                                 do_copy = false;
4904                                         }
4905
4906                                         if (do_copy) {
4907                                                 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4908
4909                                                 info << "attempting to make directory/folder " << to << endmsg;
4910
4911                                                 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4912                                                         throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4913                                                 }
4914
4915                                                 info << "attempting to copy " << from << " to " << to << endmsg;
4916
4917                                                 if (!copy_file (from, to)) {
4918                                                         throw Glib::FileError (Glib::FileError::IO_ERROR,
4919                                                                                                    string_compose(_("\ncopying \"%1\" failed !"), from));
4920                                                 }
4921                                         }
4922                                 }
4923
4924                                 /* measure file size even if we're not going to copy so that our Progress
4925                                    signals are correct, since we included these do-not-copy files
4926                                    in the computation of the total size and file count.
4927                                 */
4928
4929                                 GStatBuf gsb;
4930                                 g_stat (from.c_str(), &gsb);
4931                                 copied += gsb.st_size;
4932                                 cnt++;
4933
4934                                 double fraction = (double) copied / total_bytes;
4935
4936                                 bool keep_going = true;
4937
4938                                 if (saveas.copy_media) {
4939
4940                                         /* no need or expectation of this if
4941                                          * media is not being copied, because
4942                                          * it will be fast(ish).
4943                                          */
4944
4945                                         /* tell someone "X percent, file M of N"; M is one-based */
4946
4947                                         boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4948
4949                                         if (res) {
4950                                                 keep_going = *res;
4951                                         }
4952                                 }
4953
4954                                 if (!keep_going) {
4955                                         throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4956                                 }
4957                         }
4958
4959                 }
4960
4961                 /* copy optional folders, if any */
4962
4963                 string old = plugins_dir ();
4964                 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4965                         string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4966                         copy_files (old, newdir);
4967                 }
4968
4969                 old = externals_dir ();
4970                 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4971                         string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4972                         copy_files (old, newdir);
4973                 }
4974
4975                 old = automation_dir ();
4976                 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4977                         string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4978                         copy_files (old, newdir);
4979                 }
4980
4981                 if (saveas.include_media) {
4982
4983                         if (saveas.copy_media) {
4984 #ifndef PLATFORM_WINDOWS
4985                                 /* There are problems with analysis files on
4986                                  * Windows, because they used a colon in their
4987                                  * names as late as 4.0. Colons are not legal
4988                                  * under Windows even if NTFS allows them.
4989                                  *
4990                                  * This is a tricky problem to solve so for
4991                                  * just don't copy these files. They will be
4992                                  * regenerated as-needed anyway, subject to the
4993                                  * existing issue that the filenames will be
4994                                  * rejected by Windows, which is a separate
4995                                  * problem (though related).
4996                                  */
4997
4998                                 /* only needed if we are copying media, since the
4999                                  * analysis data refers to media data
5000                                  */
5001
5002                                 old = analysis_dir ();
5003                                 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
5004                                         string newdir = Glib::build_filename (to_dir, "analysis");
5005                                         copy_files (old, newdir);
5006                                 }
5007 #endif /* PLATFORM_WINDOWS */
5008                         }
5009                 }
5010
5011                 _path = to_dir;
5012                 set_snapshot_name (saveas.new_name);
5013                 _name = saveas.new_name;
5014
5015                 if (saveas.include_media && !saveas.copy_media) {
5016
5017                         /* reset search paths of the new session (which we're pretending to be right now) to
5018                            include the original session search path, so we can still find all audio.
5019                         */
5020
5021                         if (internal_file_cnt) {
5022                                 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
5023                                         ensure_search_path_includes (*s, DataType::AUDIO);
5024                                         cerr << "be sure to include " << *s << "  for audio" << endl;
5025                                 }
5026
5027                                 /* we do not do this for MIDI because we copy
5028                                    all MIDI files if saveas.include_media is
5029                                    true
5030                                 */
5031                         }
5032                 }
5033
5034                 bool was_dirty = dirty ();
5035
5036                 save_default_options ();
5037
5038                 if (saveas.copy_media && saveas.copy_external) {
5039                         if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
5040                                 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
5041                         }
5042                 }
5043
5044                 saveas.final_session_folder_name = _path;
5045
5046                 store_recent_sessions (_name, _path);
5047
5048                 if (!saveas.switch_to) {
5049
5050                         /* save the new state */
5051
5052                         save_state ("", false, false, !saveas.include_media);
5053
5054                         /* switch back to the way things were */
5055
5056                         _path = old_path;
5057                         _name = old_name;
5058                         set_snapshot_name (old_snapshot);
5059
5060                         (*_session_dir) = old_sd;
5061
5062                         if (was_dirty) {
5063                                 set_dirty ();
5064                         }
5065
5066                         if (internal_file_cnt) {
5067                                 /* reset these to their original values */
5068                                 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
5069                                 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
5070                         }
5071
5072                 } else {
5073
5074                         /* prune session dirs, and update disk space statistics
5075                          */
5076
5077                         space_and_path sp;
5078                         sp.path = _path;
5079                         session_dirs.clear ();
5080                         session_dirs.push_back (sp);
5081                         refresh_disk_space ();
5082
5083                         _writable = exists_and_writable (_path);
5084
5085                         /* ensure that all existing tracks reset their current capture source paths
5086                          */
5087                         reset_write_sources (true, true);
5088
5089                         /* creating new write sources marks the session as
5090                            dirty. If the new session is empty, then
5091                            save_state() thinks we're saving a template and will
5092                            not mark the session as clean. So do that here,
5093                            before we save state.
5094                         */
5095
5096                         if (!saveas.include_media) {
5097                                 unset_dirty ();
5098                         }
5099
5100                         save_state ("", false, false, !saveas.include_media);
5101
5102                         /* the copying above was based on actually discovering files, not just iterating over the sources list.
5103                            But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
5104                         */
5105
5106                         for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
5107                                 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
5108
5109                                 if (!fs) {
5110                                         continue;
5111                                 }
5112
5113                                 if (fs->within_session()) {
5114                                         string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
5115                                         fs->set_path (newpath);
5116                                 }
5117                         }
5118                 }
5119
5120         } catch (Glib::FileError& e) {
5121
5122                 saveas.failure_message = e.what();
5123
5124                 /* recursively remove all the directories */
5125
5126                 remove_directory (to_dir);
5127
5128                 /* return error */
5129
5130                 return -1;
5131
5132         } catch (...) {
5133
5134                 saveas.failure_message = _("unknown reason");
5135
5136                 /* recursively remove all the directories */
5137
5138                 remove_directory (to_dir);
5139
5140                 /* return error */
5141
5142                 return -1;
5143         }
5144
5145         return 0;
5146 }
5147
5148 static void set_progress (Progress* p, size_t n, size_t t)
5149 {
5150         p->set_progress (float (n) / float(t));
5151 }
5152
5153 int
5154 Session::archive_session (const std::string& dest,
5155                           const std::string& name,
5156                           ArchiveEncode compress_audio,
5157                           FileArchive::CompressionLevel compression_level,
5158                           bool only_used_sources,
5159                           Progress* progress)
5160 {
5161         if (dest.empty () || name.empty ()) {
5162                 return -1;
5163         }
5164
5165         /* We are going to temporarily change some source properties,
5166          * don't allow any concurrent saves (periodic or otherwise */
5167         Glib::Threads::Mutex::Lock lm (save_source_lock);
5168
5169         disable_record (false);
5170
5171         /* save current values */
5172         string old_path = _path;
5173         string old_name = _name;
5174         string old_snapshot = _current_snapshot_name;
5175         string old_sd = _session_dir->root_path();
5176         string old_config_search_path[DataType::num_types];
5177         old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
5178         old_config_search_path[DataType::MIDI]  = config.get_midi_search_path ();
5179
5180         /* ensure that session-path is included in search-path */
5181         bool ok = false;
5182         for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
5183                 if ((*sd).path == old_path) {
5184                         ok = true;
5185                 }
5186         }
5187         if (!ok) {
5188                 return -1;
5189         }
5190
5191         /* create temporary dir to save session to */
5192 #ifdef PLATFORM_WINDOWS
5193         char tmp[256] = "C:\\TEMP\\";
5194         GetTempPath (sizeof (tmp), tmp);
5195 #else
5196         char const* tmp = getenv("TMPDIR");
5197         if (!tmp) {
5198                 tmp = "/tmp/";
5199         }
5200 #endif
5201         if ((strlen (tmp) + 21) > 1024) {
5202                 return -1;
5203         }
5204
5205         char tmptpl[1024];
5206         strcpy (tmptpl, tmp);
5207         strcat (tmptpl, "ardourarchive-XXXXXX");
5208         char*  tmpdir = g_mkdtemp (tmptpl);
5209
5210         if (!tmpdir) {
5211                 return -1;
5212         }
5213
5214         std::string to_dir = std::string (tmpdir);
5215
5216         /* switch session directory temporarily */
5217         (*_session_dir) = to_dir;
5218
5219         if (!_session_dir->create()) {
5220                 (*_session_dir) = old_sd;
5221                 remove_directory (to_dir);
5222                 return -1;
5223         }
5224
5225         /* prepare archive */
5226         string archive = Glib::build_filename (dest, name + session_archive_suffix);
5227
5228         PBD::ScopedConnectionList progress_connection;
5229         PBD::FileArchive ar (archive);
5230         if (progress) {
5231                 ar.progress.connect_same_thread (progress_connection, boost::bind (&set_progress, progress, _1, _2));
5232         }
5233
5234         /* collect files to archive */
5235         std::map<string,string> filemap;
5236
5237         vector<string> do_not_copy_extensions;
5238         do_not_copy_extensions.push_back (statefile_suffix);
5239         do_not_copy_extensions.push_back (pending_suffix);
5240         do_not_copy_extensions.push_back (backup_suffix);
5241         do_not_copy_extensions.push_back (temp_suffix);
5242         do_not_copy_extensions.push_back (history_suffix);
5243
5244         vector<string> blacklist_dirs;
5245         blacklist_dirs.push_back (string (peak_dir_name) + G_DIR_SEPARATOR);
5246         blacklist_dirs.push_back (string (analysis_dir_name) + G_DIR_SEPARATOR);
5247         blacklist_dirs.push_back (string (dead_dir_name) + G_DIR_SEPARATOR);
5248         blacklist_dirs.push_back (string (export_dir_name) + G_DIR_SEPARATOR);
5249         blacklist_dirs.push_back (string (externals_dir_name) + G_DIR_SEPARATOR);
5250         blacklist_dirs.push_back (string (plugins_dir_name) + G_DIR_SEPARATOR);
5251
5252         std::map<boost::shared_ptr<AudioFileSource>, std::string> orig_sources;
5253         std::map<boost::shared_ptr<AudioFileSource>, std::string> orig_origin;
5254         std::map<boost::shared_ptr<AudioFileSource>, float> orig_gain;
5255
5256         set<boost::shared_ptr<Source> > sources_used_by_this_snapshot;
5257         if (only_used_sources) {
5258                 _playlists->sync_all_regions_with_regions ();
5259                 _playlists->foreach (boost::bind (merge_all_sources, _1, &sources_used_by_this_snapshot), false);
5260         }
5261
5262         /* collect audio sources for this session, calc total size for encoding
5263          * add option to only include *used* sources (see Session::cleanup_sources)
5264          */
5265         size_t total_size = 0;
5266         {
5267                 Glib::Threads::Mutex::Lock lm (source_lock);
5268
5269                 /* build a list of used names */
5270                 std::set<std::string> audio_file_names;
5271                 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
5272                         if (boost::dynamic_pointer_cast<SilentFileSource> (i->second)) {
5273                                 continue;
5274                         }
5275                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (i->second);
5276                         if (!afs || afs->readable_length () == 0) {
5277                                 continue;
5278                         }
5279                         if (only_used_sources) {
5280                                 if (!afs->used()) {
5281                                         continue;
5282                                 }
5283                                 if (sources_used_by_this_snapshot.find (afs) == sources_used_by_this_snapshot.end ()) {
5284                                         continue;
5285                                 }
5286                         }
5287                         audio_file_names.insert (Glib::path_get_basename (afs->path()));
5288                 }
5289
5290                 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
5291                         if (boost::dynamic_pointer_cast<SilentFileSource> (i->second)) {
5292                                 continue;
5293                         }
5294                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (i->second);
5295                         if (!afs || afs->readable_length () == 0) {
5296                                 continue;
5297                         }
5298
5299                         if (only_used_sources) {
5300                                 if (!afs->used()) {
5301                                         continue;
5302                                 }
5303                                 if (sources_used_by_this_snapshot.find (afs) == sources_used_by_this_snapshot.end ()) {
5304                                         continue;
5305                                 }
5306                         }
5307
5308                         std::string from = afs->path();
5309
5310                         if (compress_audio != NO_ENCODE) {
5311                                 total_size += afs->readable_length ();
5312                         } else {
5313                                 /* copy files as-is */
5314                                 if (!afs->within_session()) {
5315                                         string to = Glib::path_get_basename (from);
5316
5317                                         /* avoid name collitions, see also new_audio_source_path_for_embedded ()
5318                                          * - avoid conflict with files existing in interchange
5319                                          * - avoid conflict with other embedded sources
5320                                          */
5321                                         if (audio_file_names.find (to) == audio_file_names.end ()) {
5322                                                 // we need a new name, add a '-<num>' before the '.<ext>'
5323                                                 string bn   = to.substr (0, to.find_last_of ('.'));
5324                                                 string ext  = to.find_last_of ('.') == string::npos ? "" : to.substr (to.find_last_of ('.'));
5325                                                 to = bn + "-1" + ext;
5326                                         }
5327                                         while (audio_file_names.find (to) == audio_file_names.end ()) {
5328                                                 to = bump_name_once (to, '-');
5329                                         }
5330
5331                                         audio_file_names.insert (to);
5332                                         filemap[from] = make_new_audio_path (to, name, name);
5333
5334                                         remove_dir_from_search_path (Glib::path_get_dirname (from), DataType::AUDIO);
5335
5336                                         orig_origin[afs] = afs->origin ();
5337                                         afs->set_origin ("");
5338
5339                                 } else {
5340                                         filemap[from] = make_new_media_path (from, name, name);
5341                                 }
5342                         }
5343                 }
5344         }
5345
5346         /* encode audio */
5347         if (compress_audio != NO_ENCODE) {
5348                 if (progress) {
5349                         progress->set_progress (2); // set to "encoding"
5350                         progress->set_progress (0);
5351                 }
5352
5353                 Glib::Threads::Mutex::Lock lm (source_lock);
5354                 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
5355                         if (boost::dynamic_pointer_cast<SilentFileSource> (i->second)) {
5356                                 continue;
5357                         }
5358                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (i->second);
5359                         if (!afs || afs->readable_length () == 0) {
5360                                 continue;
5361                         }
5362
5363                         if (only_used_sources) {
5364                                 if (!afs->used()) {
5365                                         continue;
5366                                 }
5367                                 if (sources_used_by_this_snapshot.find (afs) == sources_used_by_this_snapshot.end ()) {
5368                                         continue;
5369                                 }
5370                         }
5371
5372                         orig_sources[afs] = afs->path();
5373                         orig_gain[afs]    = afs->gain();
5374
5375                         std::string new_path = make_new_media_path (afs->path (), to_dir, name);
5376
5377                         std::string channelsuffix = "";
5378                         if (afs->channel() > 0) {  /* n_channels() is /wrongly/ 1. */
5379                                 /* embedded external multi-channel files are converted to multiple-mono */
5380                                 channelsuffix = string_compose ("-c%1", afs->channel ());
5381                         }
5382                         new_path = Glib::build_filename (Glib::path_get_dirname (new_path), PBD::basename_nosuffix (new_path) + channelsuffix + ".flac");
5383                         g_mkdir_with_parents (Glib::path_get_dirname (new_path).c_str (), 0755);
5384
5385                         /* avoid name collisions of external files with same name */
5386                         if (Glib::file_test (new_path, Glib::FILE_TEST_EXISTS)) {
5387                                 new_path = Glib::build_filename (Glib::path_get_dirname (new_path), PBD::basename_nosuffix (new_path) + channelsuffix + "-1.flac");
5388                         }
5389                         while (Glib::file_test (new_path, Glib::FILE_TEST_EXISTS)) {
5390                                 new_path = bump_name_once (new_path, '-');
5391                         }
5392
5393                         if (progress) {
5394                                 progress->descend ((float)afs->readable_length () / total_size);
5395                         }
5396
5397                         try {
5398                                 SndFileSource* ns = new SndFileSource (*this, *(afs.get()), new_path, compress_audio == FLAC_16BIT, progress);
5399                                 afs->replace_file (new_path);
5400                                 afs->set_gain (ns->gain(), true);
5401                                 delete ns;
5402                         } catch (...) {
5403                                 cerr << "failed to encode " << afs->path() << " to " << new_path << "\n";
5404                         }
5405
5406                         if (progress) {
5407                                 progress->ascend ();
5408                         }
5409                 }
5410         }
5411
5412         if (progress) {
5413                 progress->set_progress (-1); // set to "archiving"
5414                 progress->set_progress (0);
5415         }
5416
5417         /* index files relevant for this session */
5418         for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
5419                 vector<string> files;
5420
5421                 size_t prefix_len = (*sd).path.size();
5422                 if (prefix_len > 0 && (*sd).path.at (prefix_len - 1) != G_DIR_SEPARATOR) {
5423                         ++prefix_len;
5424                 }
5425
5426                 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
5427
5428                 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
5429                 static const std::string videofile_dir_string = string (video_dir_name) + G_DIR_SEPARATOR;
5430                 static const std::string midifile_dir_string  = string (midi_dir_name)  + G_DIR_SEPARATOR;
5431
5432                 for (vector<string>::const_iterator i = files.begin (); i != files.end (); ++i) {
5433                         std::string from = *i;
5434
5435 #ifdef __APPLE__
5436                         string filename = Glib::path_get_basename (from);
5437                         std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
5438                         if (filename == ".DS_STORE") {
5439                                 continue;
5440                         }
5441 #endif
5442
5443                         if (from.find (audiofile_dir_string) != string::npos) {
5444                                 ; // handled above
5445                         } else if (from.find (midifile_dir_string) != string::npos) {
5446                                 filemap[from] = make_new_media_path (from, name, name);
5447                         } else if (from.find (videofile_dir_string) != string::npos) {
5448                                 filemap[from] = make_new_media_path (from, name, name);
5449                         } else {
5450                                 bool do_copy = true;
5451                                 for (vector<string>::iterator v = blacklist_dirs.begin(); v != blacklist_dirs.end(); ++v) {
5452                                         if (from.find (*v) != string::npos) {
5453                                                 do_copy = false;
5454                                                 break;
5455                                         }
5456                                 }
5457                                 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
5458                                         if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
5459                                                 do_copy = false;
5460                                                 break;
5461                                         }
5462                                 }
5463
5464                                 if (do_copy) {
5465                                         filemap[from] = name + G_DIR_SEPARATOR + from.substr (prefix_len);
5466                                 }
5467                         }
5468                 }
5469         }
5470
5471         /* write session file */
5472         _path = to_dir;
5473         g_mkdir_with_parents (externals_dir ().c_str (), 0755);
5474
5475         save_state (name, false, false, false, true, only_used_sources);
5476
5477         save_default_options ();
5478
5479         size_t prefix_len = _path.size();
5480         if (prefix_len > 0 && _path.at (prefix_len - 1) != G_DIR_SEPARATOR) {
5481                 ++prefix_len;
5482         }
5483
5484         /* collect session-state files */
5485         vector<string> files;
5486         do_not_copy_extensions.clear ();
5487         do_not_copy_extensions.push_back (history_suffix);
5488
5489         blacklist_dirs.clear ();
5490         blacklist_dirs.push_back (string (externals_dir_name) + G_DIR_SEPARATOR);
5491
5492         find_files_matching_filter (files, to_dir, accept_all_files, 0, false, true, true);
5493         for (vector<string>::const_iterator i = files.begin (); i != files.end (); ++i) {
5494                 std::string from = *i;
5495                 bool do_copy = true;
5496                 for (vector<string>::iterator v = blacklist_dirs.begin(); v != blacklist_dirs.end(); ++v) {
5497                         if (from.find (*v) != string::npos) {
5498                                 do_copy = false;
5499                                 break;
5500                         }
5501                 }
5502                 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
5503                         if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
5504                                 do_copy = false;
5505                                 break;
5506                         }
5507                 }
5508                 if (do_copy) {
5509                         filemap[from] = name + G_DIR_SEPARATOR + from.substr (prefix_len);
5510                 }
5511         }
5512
5513         /* restore original values */
5514         _path = old_path;
5515         _name = old_name;
5516         set_snapshot_name (old_snapshot);
5517         (*_session_dir) = old_sd;
5518         config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
5519         config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
5520
5521         for (std::map<boost::shared_ptr<AudioFileSource>, std::string>::iterator i = orig_origin.begin (); i != orig_origin.end (); ++i) {
5522                 i->first->set_origin (i->second);
5523         }
5524         for (std::map<boost::shared_ptr<AudioFileSource>, std::string>::iterator i = orig_sources.begin (); i != orig_sources.end (); ++i) {
5525                 i->first->replace_file (i->second);
5526         }
5527         for (std::map<boost::shared_ptr<AudioFileSource>, float>::iterator i = orig_gain.begin (); i != orig_gain.end (); ++i) {
5528                 i->first->set_gain (i->second, true);
5529         }
5530
5531         int rv = ar.create (filemap, compression_level);
5532         remove_directory (to_dir);
5533
5534         return rv;
5535 }
5536
5537 void
5538 Session::undo (uint32_t n)
5539 {
5540         if (actively_recording()) {
5541                 return;
5542         }
5543
5544         _history.undo (n);
5545 }
5546
5547 void
5548 Session::redo (uint32_t n)
5549 {
5550         if (actively_recording()) {
5551                 return;
5552         }
5553
5554         _history.redo (n);
5555 }