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