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