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