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