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