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