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