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