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