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