Plug a memory leak (recent session list, session info)
[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::gui_tempo_map_changed, this));
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                 // for a template, just create a new Locations, populate it
1298                 // with the default start and end, and get the state for that.
1299                 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange, 0);
1300                 range->set (max_framepos, 0);
1301                 loc.add (range);
1302                 XMLNode& locations_state = loc.get_state();
1303
1304                 if (ARDOUR::Profile->get_trx() && _locations) {
1305                         // For tracks we need stored the Auto Loop Range and all MIDI markers.
1306                         for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1307                                 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1308                                         locations_state.add_child_nocopy ((*i)->get_state ());
1309                                 }
1310                         }
1311                 }
1312                 node->add_child_nocopy (locations_state);
1313         }
1314
1315         child = node->add_child ("Bundles");
1316         {
1317                 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1318                 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1319                         boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1320                         if (b) {
1321                                 child->add_child_nocopy (b->get_state());
1322                         }
1323                 }
1324         }
1325
1326         node->add_child_nocopy (_vca_manager->get_state());
1327
1328         child = node->add_child ("Routes");
1329         {
1330                 boost::shared_ptr<RouteList> r = routes.reader ();
1331
1332                 RoutePublicOrderSorter cmp;
1333                 RouteList public_order (*r);
1334                 public_order.sort (cmp);
1335
1336                 /* the sort should have put the monitor out first */
1337
1338                 if (_monitor_out) {
1339                         assert (_monitor_out == public_order.front());
1340                 }
1341
1342                 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1343                         if (!(*i)->is_auditioner()) {
1344                                 if (full_state) {
1345                                         child->add_child_nocopy ((*i)->get_state());
1346                                 } else {
1347                                         child->add_child_nocopy ((*i)->get_template());
1348                                 }
1349                         }
1350                 }
1351         }
1352
1353         playlists->add_state (node, full_state);
1354
1355         child = node->add_child ("RouteGroups");
1356         for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1357                 child->add_child_nocopy ((*i)->get_state());
1358         }
1359
1360         if (_click_io) {
1361                 XMLNode* gain_child = node->add_child ("Click");
1362                 gain_child->add_child_nocopy (_click_io->state (full_state));
1363                 gain_child->add_child_nocopy (_click_gain->state (full_state));
1364         }
1365
1366         if (_ltc_input) {
1367                 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1368                 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1369         }
1370
1371         if (_ltc_input) {
1372                 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1373                 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1374         }
1375
1376         node->add_child_nocopy (_speakers->get_state());
1377         node->add_child_nocopy (_tempo_map->get_state());
1378         node->add_child_nocopy (get_control_protocol_state());
1379
1380         if (_extra_xml) {
1381                 node->add_child_copy (*_extra_xml);
1382         }
1383
1384         {
1385                 Glib::Threads::Mutex::Lock lm (lua_lock);
1386                 std::string saved;
1387                 {
1388                         luabridge::LuaRef savedstate ((*_lua_save)());
1389                         saved = savedstate.cast<std::string>();
1390                 }
1391                 lua.collect_garbage ();
1392                 lm.release ();
1393
1394                 gchar* b64 = g_base64_encode ((const guchar*)saved.c_str (), saved.size ());
1395                 std::string b64s (b64);
1396                 g_free (b64);
1397
1398                 XMLNode* script_node = new XMLNode (X_("Script"));
1399                 script_node->add_property (X_("lua"), LUA_VERSION);
1400                 script_node->add_content (b64s);
1401                 node->add_child_nocopy (*script_node);
1402         }
1403
1404         return *node;
1405 }
1406
1407 XMLNode&
1408 Session::get_control_protocol_state ()
1409 {
1410         ControlProtocolManager& cpm (ControlProtocolManager::instance());
1411         return cpm.get_state();
1412 }
1413
1414 int
1415 Session::set_state (const XMLNode& node, int version)
1416 {
1417         LocaleGuard lg;
1418         XMLNodeList nlist;
1419         XMLNode* child;
1420         XMLProperty const * prop;
1421         int ret = -1;
1422
1423         _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1424
1425         if (node.name() != X_("Session")) {
1426                 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1427                 goto out;
1428         }
1429
1430         if ((prop = node.property ("name")) != 0) {
1431                 _name = prop->value ();
1432         }
1433
1434         if ((prop = node.property (X_("sample-rate"))) != 0) {
1435
1436                 _base_frame_rate = atoi (prop->value());
1437                 _nominal_frame_rate = _base_frame_rate;
1438
1439                 assert (AudioEngine::instance()->running ());
1440                 if (_base_frame_rate != AudioEngine::instance()->sample_rate ()) {
1441                         boost::optional<int> r = AskAboutSampleRateMismatch (_base_frame_rate, _current_frame_rate);
1442                         if (r.get_value_or (0)) {
1443                                 goto out;
1444                         }
1445                 }
1446         }
1447
1448         created_with = "unknown";
1449         if ((child = find_named_node (node, "ProgramVersion")) != 0) {
1450                 if ((prop = child->property (X_("created-with"))) != 0) {
1451                         created_with = prop->value ();
1452                 }
1453         }
1454
1455         setup_raid_path(_session_dir->root_path());
1456
1457         if ((prop = node.property (X_("end-is-free"))) != 0) {
1458                 _session_range_end_is_free = string_is_affirmative (prop->value());
1459         }
1460
1461         if ((prop = node.property (X_("id-counter"))) != 0) {
1462                 uint64_t x;
1463                 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1464                 ID::init_counter (x);
1465         } else {
1466                 /* old sessions used a timebased counter, so fake
1467                    the startup ID counter based on a standard
1468                    timestamp.
1469                 */
1470                 time_t now;
1471                 time (&now);
1472                 ID::init_counter (now);
1473         }
1474
1475         if ((prop = node.property (X_("name-counter"))) != 0) {
1476                 init_name_id_counter (atoi (prop->value()));
1477         }
1478
1479         if ((prop = node.property (X_("event-counter"))) != 0) {
1480                 Evoral::init_event_id_counter (atoi (prop->value()));
1481         }
1482
1483         if ((prop = node.property (X_("vca-counter"))) != 0) {
1484                 uint32_t x;
1485                 sscanf (prop->value().c_str(), "%" PRIu32, &x);
1486                 VCA::set_next_vca_number (x);
1487         } else {
1488                 VCA::set_next_vca_number (1);
1489         }
1490
1491         if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1492                 _midi_ports->set_midi_port_states (child->children());
1493         }
1494
1495         IO::disable_connecting ();
1496
1497         Stateful::save_extra_xml (node);
1498
1499         if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1500                 load_options (*child);
1501         } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1502                 load_options (*child);
1503         } else {
1504                 error << _("Session: XML state has no options section") << endmsg;
1505         }
1506
1507         if (version >= 3000) {
1508                 if ((child = find_named_node (node, "Metadata")) == 0) {
1509                         warning << _("Session: XML state has no metadata section") << endmsg;
1510                 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1511                         goto out;
1512                 }
1513         }
1514
1515         if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1516                 _speakers->set_state (*child, version);
1517         }
1518
1519         if ((child = find_named_node (node, "Sources")) == 0) {
1520                 error << _("Session: XML state has no sources section") << endmsg;
1521                 goto out;
1522         } else if (load_sources (*child)) {
1523                 goto out;
1524         }
1525
1526         if ((child = find_named_node (node, "TempoMap")) == 0) {
1527                 error << _("Session: XML state has no Tempo Map section") << endmsg;
1528                 goto out;
1529         } else if (_tempo_map->set_state (*child, version)) {
1530                 goto out;
1531         }
1532
1533         if ((child = find_named_node (node, "Locations")) == 0) {
1534                 error << _("Session: XML state has no locations section") << endmsg;
1535                 goto out;
1536         } else if (_locations->set_state (*child, version)) {
1537                 goto out;
1538         }
1539
1540         locations_changed ();
1541
1542         if (_session_range_location) {
1543                 AudioFileSource::set_header_position_offset (_session_range_location->start());
1544         }
1545
1546         if ((child = find_named_node (node, "Regions")) == 0) {
1547                 error << _("Session: XML state has no Regions section") << endmsg;
1548                 goto out;
1549         } else if (load_regions (*child)) {
1550                 goto out;
1551         }
1552
1553         if ((child = find_named_node (node, "Playlists")) == 0) {
1554                 error << _("Session: XML state has no playlists section") << endmsg;
1555                 goto out;
1556         } else if (playlists->load (*this, *child)) {
1557                 goto out;
1558         }
1559
1560         if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1561                 // this is OK
1562         } else if (playlists->load_unused (*this, *child)) {
1563                 goto out;
1564         }
1565
1566         if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1567                 if (load_compounds (*child)) {
1568                         goto out;
1569                 }
1570         }
1571
1572         if (version >= 3000) {
1573                 if ((child = find_named_node (node, "Bundles")) == 0) {
1574                         warning << _("Session: XML state has no bundles section") << endmsg;
1575                         //goto out;
1576                 } else {
1577                         /* We can't load Bundles yet as they need to be able
1578                            to convert from port names to Port objects, which can't happen until
1579                            later */
1580                         _bundle_xml_node = new XMLNode (*child);
1581                 }
1582         }
1583
1584         if (version < 3000) {
1585                 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1586                         error << _("Session: XML state has no diskstreams section") << endmsg;
1587                         goto out;
1588                 } else if (load_diskstreams_2X (*child, version)) {
1589                         goto out;
1590                 }
1591         }
1592
1593         if ((child = find_named_node (node, VCAManager::xml_node_name)) != 0) {
1594                 _vca_manager->set_state (*child, version);
1595         }
1596
1597         if ((child = find_named_node (node, "Routes")) == 0) {
1598                 error << _("Session: XML state has no routes section") << endmsg;
1599                 goto out;
1600         } else if (load_routes (*child, version)) {
1601                 goto out;
1602         }
1603
1604         /* Now that we have Routes and masters loaded, connect them if appropriate */
1605
1606         Slavable::Assign (_vca_manager); /* EMIT SIGNAL */
1607
1608         /* our diskstreams list is no longer needed as they are now all owned by their Route */
1609         _diskstreams_2X.clear ();
1610
1611         if (version >= 3000) {
1612
1613                 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1614                         error << _("Session: XML state has no route groups section") << endmsg;
1615                         goto out;
1616                 } else if (load_route_groups (*child, version)) {
1617                         goto out;
1618                 }
1619
1620         } else if (version < 3000) {
1621
1622                 if ((child = find_named_node (node, "EditGroups")) == 0) {
1623                         error << _("Session: XML state has no edit groups section") << endmsg;
1624                         goto out;
1625                 } else if (load_route_groups (*child, version)) {
1626                         goto out;
1627                 }
1628
1629                 if ((child = find_named_node (node, "MixGroups")) == 0) {
1630                         error << _("Session: XML state has no mix groups section") << endmsg;
1631                         goto out;
1632                 } else if (load_route_groups (*child, version)) {
1633                         goto out;
1634                 }
1635         }
1636
1637         if ((child = find_named_node (node, "Click")) == 0) {
1638                 warning << _("Session: XML state has no click section") << endmsg;
1639         } else if (_click_io) {
1640                 setup_click_state (&node);
1641         }
1642
1643         if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1644                 ControlProtocolManager::instance().set_state (*child, version);
1645         }
1646
1647         if ((child = find_named_node (node, "Script"))) {
1648                 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1649                         if (!(*n)->is_content ()) { continue; }
1650                         gsize size;
1651                         guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
1652                         try {
1653                                 Glib::Threads::Mutex::Lock lm (lua_lock);
1654                                 (*_lua_load)(std::string ((const char*)buf, size));
1655                         } catch (luabridge::LuaException const& e) {
1656                                 cerr << "LuaException:" << e.what () << endl;
1657                         }
1658                         g_free (buf);
1659                 }
1660         }
1661
1662         update_route_record_state ();
1663
1664         /* here beginneth the second phase ... */
1665         set_snapshot_name (_current_snapshot_name);
1666
1667         StateReady (); /* EMIT SIGNAL */
1668
1669         delete state_tree;
1670         state_tree = 0;
1671         return 0;
1672
1673   out:
1674         delete state_tree;
1675         state_tree = 0;
1676         return ret;
1677 }
1678
1679 int
1680 Session::load_routes (const XMLNode& node, int version)
1681 {
1682         XMLNodeList nlist;
1683         XMLNodeConstIterator niter;
1684         RouteList new_routes;
1685
1686         nlist = node.children();
1687
1688         set_dirty();
1689
1690         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1691
1692                 boost::shared_ptr<Route> route;
1693                 if (version < 3000) {
1694                         route = XMLRouteFactory_2X (**niter, version);
1695                 } else {
1696                         route = XMLRouteFactory (**niter, version);
1697                 }
1698
1699                 if (route == 0) {
1700                         error << _("Session: cannot create Route from XML description.") << endmsg;
1701                         return -1;
1702                 }
1703
1704                 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1705
1706                 new_routes.push_back (route);
1707         }
1708
1709         BootMessage (_("Tracks/busses loaded;  Adding to Session"));
1710
1711         add_routes (new_routes, false, false, false, PresentationInfo::max_order);
1712
1713         BootMessage (_("Finished adding tracks/busses"));
1714
1715         return 0;
1716 }
1717
1718 boost::shared_ptr<Route>
1719 Session::XMLRouteFactory (const XMLNode& node, int version)
1720 {
1721         boost::shared_ptr<Route> ret;
1722
1723         if (node.name() != "Route") {
1724                 return ret;
1725         }
1726
1727         XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1728
1729         DataType type = DataType::AUDIO;
1730         XMLProperty const * prop = node.property("default-type");
1731
1732         if (prop) {
1733                 type = DataType (prop->value());
1734         }
1735
1736         assert (type != DataType::NIL);
1737
1738         if (ds_child) {
1739
1740                 boost::shared_ptr<Track> track;
1741
1742                 if (type == DataType::AUDIO) {
1743                         track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1744                 } else {
1745                         track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1746                 }
1747
1748                 if (track->init()) {
1749                         return ret;
1750                 }
1751
1752                 if (track->set_state (node, version)) {
1753                         return ret;
1754                 }
1755
1756                 BOOST_MARK_TRACK (track);
1757                 ret = track;
1758
1759         } else {
1760                 PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1761                 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1762
1763                 if (r->init () == 0 && r->set_state (node, version) == 0) {
1764                         BOOST_MARK_ROUTE (r);
1765                         ret = r;
1766                 }
1767         }
1768
1769         return ret;
1770 }
1771
1772 boost::shared_ptr<Route>
1773 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1774 {
1775         boost::shared_ptr<Route> ret;
1776
1777         if (node.name() != "Route") {
1778                 return ret;
1779         }
1780
1781         XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1782         if (!ds_prop) {
1783                 ds_prop = node.property (X_("diskstream"));
1784         }
1785
1786         DataType type = DataType::AUDIO;
1787         XMLProperty const * prop = node.property("default-type");
1788
1789         if (prop) {
1790                 type = DataType (prop->value());
1791         }
1792
1793         assert (type != DataType::NIL);
1794
1795         if (ds_prop) {
1796
1797                 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1798                 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1799                         ++i;
1800                 }
1801
1802                 if (i == _diskstreams_2X.end()) {
1803                         error << _("Could not find diskstream for route") << endmsg;
1804                         return boost::shared_ptr<Route> ();
1805                 }
1806
1807                 boost::shared_ptr<Track> track;
1808
1809                 if (type == DataType::AUDIO) {
1810                         track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1811                 } else {
1812                         track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1813                 }
1814
1815                 if (track->init()) {
1816                         return ret;
1817                 }
1818
1819                 if (track->set_state (node, version)) {
1820                         return ret;
1821                 }
1822
1823                 track->set_diskstream (*i);
1824
1825                 BOOST_MARK_TRACK (track);
1826                 ret = track;
1827
1828         } else {
1829                 PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1830                 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1831
1832                 if (r->init () == 0 && r->set_state (node, version) == 0) {
1833                         BOOST_MARK_ROUTE (r);
1834                         ret = r;
1835                 }
1836         }
1837
1838         return ret;
1839 }
1840
1841 int
1842 Session::load_regions (const XMLNode& node)
1843 {
1844         XMLNodeList nlist;
1845         XMLNodeConstIterator niter;
1846         boost::shared_ptr<Region> region;
1847
1848         nlist = node.children();
1849
1850         set_dirty();
1851
1852         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1853                 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1854                         error << _("Session: cannot create Region from XML description.");
1855                         XMLProperty const * name = (**niter).property("name");
1856
1857                         if (name) {
1858                                 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1859                         }
1860
1861                         error << endmsg;
1862                 }
1863         }
1864
1865         return 0;
1866 }
1867
1868 int
1869 Session::load_compounds (const XMLNode& node)
1870 {
1871         XMLNodeList calist = node.children();
1872         XMLNodeConstIterator caiter;
1873         XMLProperty const * caprop;
1874
1875         for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1876                 XMLNode* ca = *caiter;
1877                 ID orig_id;
1878                 ID copy_id;
1879
1880                 if ((caprop = ca->property (X_("original"))) == 0) {
1881                         continue;
1882                 }
1883                 orig_id = caprop->value();
1884
1885                 if ((caprop = ca->property (X_("copy"))) == 0) {
1886                         continue;
1887                 }
1888                 copy_id = caprop->value();
1889
1890                 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1891                 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1892
1893                 if (!orig || !copy) {
1894                         warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1895                                                    orig_id, copy_id)
1896                                 << endmsg;
1897                         continue;
1898                 }
1899
1900                 RegionFactory::add_compound_association (orig, copy);
1901         }
1902
1903         return 0;
1904 }
1905
1906 void
1907 Session::load_nested_sources (const XMLNode& node)
1908 {
1909         XMLNodeList nlist;
1910         XMLNodeConstIterator niter;
1911
1912         nlist = node.children();
1913
1914         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1915                 if ((*niter)->name() == "Source") {
1916
1917                         /* it may already exist, so don't recreate it unnecessarily
1918                          */
1919
1920                         XMLProperty const * prop = (*niter)->property (X_("id"));
1921                         if (!prop) {
1922                                 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1923                                 continue;
1924                         }
1925
1926                         ID source_id (prop->value());
1927
1928                         if (!source_by_id (source_id)) {
1929
1930                                 try {
1931                                         SourceFactory::create (*this, **niter, true);
1932                                 }
1933                                 catch (failed_constructor& err) {
1934                                         error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1935                                 }
1936                         }
1937                 }
1938         }
1939 }
1940
1941 boost::shared_ptr<Region>
1942 Session::XMLRegionFactory (const XMLNode& node, bool full)
1943 {
1944         XMLProperty const * type = node.property("type");
1945
1946         try {
1947
1948                 const XMLNodeList& nlist = node.children();
1949
1950                 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1951                         XMLNode *child = (*niter);
1952                         if (child->name() == "NestedSource") {
1953                                 load_nested_sources (*child);
1954                         }
1955                 }
1956
1957                 if (!type || type->value() == "audio") {
1958                         return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1959                 } else if (type->value() == "midi") {
1960                         return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1961                 }
1962
1963         } catch (failed_constructor& err) {
1964                 return boost::shared_ptr<Region> ();
1965         }
1966
1967         return boost::shared_ptr<Region> ();
1968 }
1969
1970 boost::shared_ptr<AudioRegion>
1971 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1972 {
1973         XMLProperty const * prop;
1974         boost::shared_ptr<Source> source;
1975         boost::shared_ptr<AudioSource> as;
1976         SourceList sources;
1977         SourceList master_sources;
1978         uint32_t nchans = 1;
1979         char buf[128];
1980
1981         if (node.name() != X_("Region")) {
1982                 return boost::shared_ptr<AudioRegion>();
1983         }
1984
1985         if ((prop = node.property (X_("channels"))) != 0) {
1986                 nchans = atoi (prop->value().c_str());
1987         }
1988
1989         if ((prop = node.property ("name")) == 0) {
1990                 cerr << "no name for this region\n";
1991                 abort ();
1992         }
1993
1994         if ((prop = node.property (X_("source-0"))) == 0) {
1995                 if ((prop = node.property ("source")) == 0) {
1996                         error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1997                         return boost::shared_ptr<AudioRegion>();
1998                 }
1999         }
2000
2001         PBD::ID s_id (prop->value());
2002
2003         if ((source = source_by_id (s_id)) == 0) {
2004                 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
2005                 return boost::shared_ptr<AudioRegion>();
2006         }
2007
2008         as = boost::dynamic_pointer_cast<AudioSource>(source);
2009         if (!as) {
2010                 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
2011                 return boost::shared_ptr<AudioRegion>();
2012         }
2013
2014         sources.push_back (as);
2015
2016         /* pickup other channels */
2017
2018         for (uint32_t n=1; n < nchans; ++n) {
2019                 snprintf (buf, sizeof(buf), X_("source-%d"), n);
2020                 if ((prop = node.property (buf)) != 0) {
2021
2022                         PBD::ID id2 (prop->value());
2023
2024                         if ((source = source_by_id (id2)) == 0) {
2025                                 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
2026                                 return boost::shared_ptr<AudioRegion>();
2027                         }
2028
2029                         as = boost::dynamic_pointer_cast<AudioSource>(source);
2030                         if (!as) {
2031                                 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
2032                                 return boost::shared_ptr<AudioRegion>();
2033                         }
2034                         sources.push_back (as);
2035                 }
2036         }
2037
2038         for (uint32_t n = 0; n < nchans; ++n) {
2039                 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
2040                 if ((prop = node.property (buf)) != 0) {
2041
2042                         PBD::ID id2 (prop->value());
2043
2044                         if ((source = source_by_id (id2)) == 0) {
2045                                 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
2046                                 return boost::shared_ptr<AudioRegion>();
2047                         }
2048
2049                         as = boost::dynamic_pointer_cast<AudioSource>(source);
2050                         if (!as) {
2051                                 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
2052                                 return boost::shared_ptr<AudioRegion>();
2053                         }
2054                         master_sources.push_back (as);
2055                 }
2056         }
2057
2058         try {
2059                 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
2060
2061                 /* a final detail: this is the one and only place that we know how long missing files are */
2062
2063                 if (region->whole_file()) {
2064                         for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
2065                                 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
2066                                 if (sfp) {
2067                                         sfp->set_length (region->length());
2068                                 }
2069                         }
2070                 }
2071
2072                 if (!master_sources.empty()) {
2073                         if (master_sources.size() != nchans) {
2074                                 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
2075                         } else {
2076                                 region->set_master_sources (master_sources);
2077                         }
2078                 }
2079
2080                 return region;
2081
2082         }
2083
2084         catch (failed_constructor& err) {
2085                 return boost::shared_ptr<AudioRegion>();
2086         }
2087 }
2088
2089 boost::shared_ptr<MidiRegion>
2090 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
2091 {
2092         XMLProperty const * prop;
2093         boost::shared_ptr<Source> source;
2094         boost::shared_ptr<MidiSource> ms;
2095         SourceList sources;
2096
2097         if (node.name() != X_("Region")) {
2098                 return boost::shared_ptr<MidiRegion>();
2099         }
2100
2101         if ((prop = node.property ("name")) == 0) {
2102                 cerr << "no name for this region\n";
2103                 abort ();
2104         }
2105
2106         if ((prop = node.property (X_("source-0"))) == 0) {
2107                 if ((prop = node.property ("source")) == 0) {
2108                         error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
2109                         return boost::shared_ptr<MidiRegion>();
2110                 }
2111         }
2112
2113         PBD::ID s_id (prop->value());
2114
2115         if ((source = source_by_id (s_id)) == 0) {
2116                 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
2117                 return boost::shared_ptr<MidiRegion>();
2118         }
2119
2120         ms = boost::dynamic_pointer_cast<MidiSource>(source);
2121         if (!ms) {
2122                 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
2123                 return boost::shared_ptr<MidiRegion>();
2124         }
2125
2126         sources.push_back (ms);
2127
2128         try {
2129                 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
2130                 /* a final detail: this is the one and only place that we know how long missing files are */
2131
2132                 if (region->whole_file()) {
2133                         for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
2134                                 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
2135                                 if (sfp) {
2136                                         sfp->set_length (region->length());
2137                                 }
2138                         }
2139                 }
2140
2141                 return region;
2142         }
2143
2144         catch (failed_constructor& err) {
2145                 return boost::shared_ptr<MidiRegion>();
2146         }
2147 }
2148
2149 XMLNode&
2150 Session::get_sources_as_xml ()
2151
2152 {
2153         XMLNode* node = new XMLNode (X_("Sources"));
2154         Glib::Threads::Mutex::Lock lm (source_lock);
2155
2156         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2157                 node->add_child_nocopy (i->second->get_state());
2158         }
2159
2160         return *node;
2161 }
2162
2163 void
2164 Session::reset_write_sources (bool mark_write_complete, bool force)
2165 {
2166         boost::shared_ptr<RouteList> rl = routes.reader();
2167         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2168                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2169                 if (tr) {
2170                         _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
2171                         tr->reset_write_sources(mark_write_complete, force);
2172                         _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
2173                 }
2174         }
2175 }
2176
2177 int
2178 Session::load_sources (const XMLNode& node)
2179 {
2180         XMLNodeList nlist;
2181         XMLNodeConstIterator niter;
2182         boost::shared_ptr<Source> source; /* don't need this but it stops some
2183                                            * versions of gcc complaining about
2184                                            * discarded return values.
2185                                            */
2186
2187         nlist = node.children();
2188
2189         set_dirty();
2190
2191         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2192 #ifdef PLATFORM_WINDOWS
2193                 int old_mode = 0;
2194 #endif
2195
2196           retry:
2197                 try {
2198 #ifdef PLATFORM_WINDOWS
2199                         // do not show "insert media" popups (files embedded from removable media).
2200                         old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
2201 #endif
2202                         if ((source = XMLSourceFactory (**niter)) == 0) {
2203                                 error << _("Session: cannot create Source from XML description.") << endmsg;
2204                         }
2205 #ifdef PLATFORM_WINDOWS
2206                         SetErrorMode(old_mode);
2207 #endif
2208
2209                 } catch (MissingSource& err) {
2210 #ifdef PLATFORM_WINDOWS
2211                         SetErrorMode(old_mode);
2212 #endif
2213
2214                         int user_choice;
2215
2216                         if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2217                                 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2218                                                          PROGRAM_NAME) << endmsg;
2219                                 return -1;
2220                         }
2221
2222                         if (!no_questions_about_missing_files) {
2223                                 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2224                         } else {
2225                                 user_choice = -2;
2226                         }
2227
2228                         switch (user_choice) {
2229                         case 0:
2230                                 /* user added a new search location, so try again */
2231                                 goto retry;
2232
2233
2234                         case 1:
2235                                 /* user asked to quit the entire session load
2236                                  */
2237                                 return -1;
2238
2239                         case 2:
2240                                 no_questions_about_missing_files = true;
2241                                 goto retry;
2242
2243                         case 3:
2244                                 no_questions_about_missing_files = true;
2245                                 /* fallthru */
2246
2247                         case -1:
2248                         default:
2249                                 switch (err.type) {
2250
2251                                 case DataType::AUDIO:
2252                                         source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2253                                         break;
2254
2255                                 case DataType::MIDI:
2256                                         /* The MIDI file is actually missing so
2257                                          * just create a new one in the same
2258                                          * location. Do not announce its
2259                                          */
2260                                         string fullpath;
2261
2262                                         if (!Glib::path_is_absolute (err.path)) {
2263                                                 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2264                                         } else {
2265                                                 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2266                                                    the session tree.
2267                                                 */
2268                                                 return -1;
2269                                         }
2270                                         /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2271                                         source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2272                                         /* reset ID to match the missing one */
2273                                         source->set_id (**niter);
2274                                         /* Now we can announce it */
2275                                         SourceFactory::SourceCreated (source);
2276                                         break;
2277                                 }
2278                                 break;
2279                         }
2280                 }
2281         }
2282
2283         return 0;
2284 }
2285
2286 boost::shared_ptr<Source>
2287 Session::XMLSourceFactory (const XMLNode& node)
2288 {
2289         if (node.name() != "Source") {
2290                 return boost::shared_ptr<Source>();
2291         }
2292
2293         try {
2294                 /* note: do peak building in another thread when loading session state */
2295                 return SourceFactory::create (*this, node, true);
2296         }
2297
2298         catch (failed_constructor& err) {
2299                 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2300                 return boost::shared_ptr<Source>();
2301         }
2302 }
2303
2304 int
2305 Session::save_template (string template_name, bool replace_existing)
2306 {
2307         if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2308                 return -1;
2309         }
2310
2311         bool absolute_path = Glib::path_is_absolute (template_name);
2312
2313         /* directory to put the template in */
2314         std::string template_dir_path;
2315
2316         if (!absolute_path) {
2317                 std::string user_template_dir(user_template_directory());
2318
2319                 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2320                         error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2321                                         user_template_dir, g_strerror (errno)) << endmsg;
2322                         return -1;
2323                 }
2324
2325                 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2326         } else {
2327                 template_dir_path = template_name;
2328         }
2329
2330         if (!ARDOUR::Profile->get_trx()) {
2331                 if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2332                         warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2333                                                                           template_dir_path) << endmsg;
2334                         return -2;
2335                 }
2336
2337                 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2338                         error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2339                                                                         template_dir_path, g_strerror (errno)) << endmsg;
2340                         return -1;
2341                 }
2342         }
2343
2344         /* file to write */
2345         std::string template_file_path;
2346
2347         if (ARDOUR::Profile->get_trx()) {
2348                 template_file_path = template_name;
2349         } else {
2350                 if (absolute_path) {
2351                         template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2352                 } else {
2353                         template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2354                 }
2355         }
2356
2357         SessionSaveUnderway (); /* EMIT SIGNAL */
2358
2359         XMLTree tree;
2360
2361         {
2362                 PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2363                 tree.set_root (&get_template());
2364         }
2365
2366         if (!tree.write (template_file_path)) {
2367                 error << _("template not saved") << endmsg;
2368                 return -1;
2369         }
2370
2371         store_recent_templates (template_file_path);
2372
2373         return 0;
2374 }
2375
2376 void
2377 Session::refresh_disk_space ()
2378 {
2379 #if __APPLE__ || __FreeBSD__ || __NetBSD__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2380
2381         Glib::Threads::Mutex::Lock lm (space_lock);
2382
2383         /* get freespace on every FS that is part of the session path */
2384
2385         _total_free_4k_blocks = 0;
2386         _total_free_4k_blocks_uncertain = false;
2387
2388         for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2389 #if defined(__NetBSD__)
2390                 struct statvfs statfsbuf;
2391
2392                 statvfs (i->path.c_str(), &statfsbuf);
2393 #else
2394                 struct statfs statfsbuf;
2395
2396                 statfs (i->path.c_str(), &statfsbuf);
2397 #endif
2398                 double const scale = statfsbuf.f_bsize / 4096.0;
2399
2400                 /* See if this filesystem is read-only */
2401                 struct statvfs statvfsbuf;
2402                 statvfs (i->path.c_str(), &statvfsbuf);
2403
2404                 /* f_bavail can be 0 if it is undefined for whatever
2405                    filesystem we are looking at; Samba shares mounted
2406                    via GVFS are an example of this.
2407                 */
2408                 if (statfsbuf.f_bavail == 0) {
2409                         /* block count unknown */
2410                         i->blocks = 0;
2411                         i->blocks_unknown = true;
2412                 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2413                         /* read-only filesystem */
2414                         i->blocks = 0;
2415                         i->blocks_unknown = false;
2416                 } else {
2417                         /* read/write filesystem with known space */
2418                         i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2419                         i->blocks_unknown = false;
2420                 }
2421
2422                 _total_free_4k_blocks += i->blocks;
2423                 if (i->blocks_unknown) {
2424                         _total_free_4k_blocks_uncertain = true;
2425                 }
2426         }
2427 #elif defined PLATFORM_WINDOWS
2428         vector<string> scanned_volumes;
2429         vector<string>::iterator j;
2430         vector<space_and_path>::iterator i;
2431     DWORD nSectorsPerCluster, nBytesPerSector,
2432           nFreeClusters, nTotalClusters;
2433     char disk_drive[4];
2434         bool volume_found;
2435
2436         _total_free_4k_blocks = 0;
2437
2438         for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2439                 strncpy (disk_drive, (*i).path.c_str(), 3);
2440                 disk_drive[3] = 0;
2441                 strupr(disk_drive);
2442
2443                 volume_found = false;
2444                 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2445                 {
2446                         int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2447                         int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2448                         i->blocks = (uint32_t)(nFreeBytes / 4096);
2449
2450                         for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2451                                 if (0 == j->compare(disk_drive)) {
2452                                         volume_found = true;
2453                                         break;
2454                                 }
2455                         }
2456
2457                         if (!volume_found) {
2458                                 scanned_volumes.push_back(disk_drive);
2459                                 _total_free_4k_blocks += i->blocks;
2460                         }
2461                 }
2462         }
2463
2464         if (0 == _total_free_4k_blocks) {
2465                 strncpy (disk_drive, path().c_str(), 3);
2466                 disk_drive[3] = 0;
2467
2468                 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2469                 {
2470                         int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2471                         int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2472                         _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2473                 }
2474         }
2475 #endif
2476 }
2477
2478 string
2479 Session::get_best_session_directory_for_new_audio ()
2480 {
2481         vector<space_and_path>::iterator i;
2482         string result = _session_dir->root_path();
2483
2484         /* handle common case without system calls */
2485
2486         if (session_dirs.size() == 1) {
2487                 return result;
2488         }
2489
2490         /* OK, here's the algorithm we're following here:
2491
2492         We want to select which directory to use for
2493         the next file source to be created. Ideally,
2494         we'd like to use a round-robin process so as to
2495         get maximum performance benefits from splitting
2496         the files across multiple disks.
2497
2498         However, in situations without much diskspace, an
2499         RR approach may end up filling up a filesystem
2500         with new files while others still have space.
2501         Its therefore important to pay some attention to
2502         the freespace in the filesystem holding each
2503         directory as well. However, if we did that by
2504         itself, we'd keep creating new files in the file
2505         system with the most space until it was as full
2506         as all others, thus negating any performance
2507         benefits of this RAID-1 like approach.
2508
2509         So, we use a user-configurable space threshold. If
2510         there are at least 2 filesystems with more than this
2511         much space available, we use RR selection between them.
2512         If not, then we pick the filesystem with the most space.
2513
2514         This gets a good balance between the two
2515         approaches.
2516         */
2517
2518         refresh_disk_space ();
2519
2520         int free_enough = 0;
2521
2522         for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2523                 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2524                         free_enough++;
2525                 }
2526         }
2527
2528         if (free_enough >= 2) {
2529                 /* use RR selection process, ensuring that the one
2530                    picked works OK.
2531                 */
2532
2533                 i = last_rr_session_dir;
2534
2535                 do {
2536                         if (++i == session_dirs.end()) {
2537                                 i = session_dirs.begin();
2538                         }
2539
2540                         if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2541                                 SessionDirectory sdir(i->path);
2542                                 if (sdir.create ()) {
2543                                         result = (*i).path;
2544                                         last_rr_session_dir = i;
2545                                         return result;
2546                                 }
2547                         }
2548
2549                 } while (i != last_rr_session_dir);
2550
2551         } else {
2552
2553                 /* pick FS with the most freespace (and that
2554                    seems to actually work ...)
2555                 */
2556
2557                 vector<space_and_path> sorted;
2558                 space_and_path_ascending_cmp cmp;
2559
2560                 sorted = session_dirs;
2561                 sort (sorted.begin(), sorted.end(), cmp);
2562
2563                 for (i = sorted.begin(); i != sorted.end(); ++i) {
2564                         SessionDirectory sdir(i->path);
2565                         if (sdir.create ()) {
2566                                 result = (*i).path;
2567                                 last_rr_session_dir = i;
2568                                 return result;
2569                         }
2570                 }
2571         }
2572
2573         return result;
2574 }
2575
2576 string
2577 Session::automation_dir () const
2578 {
2579         return Glib::build_filename (_path, automation_dir_name);
2580 }
2581
2582 string
2583 Session::analysis_dir () const
2584 {
2585         return Glib::build_filename (_path, analysis_dir_name);
2586 }
2587
2588 string
2589 Session::plugins_dir () const
2590 {
2591         return Glib::build_filename (_path, plugins_dir_name);
2592 }
2593
2594 string
2595 Session::externals_dir () const
2596 {
2597         return Glib::build_filename (_path, externals_dir_name);
2598 }
2599
2600 int
2601 Session::load_bundles (XMLNode const & node)
2602 {
2603         XMLNodeList nlist = node.children();
2604         XMLNodeConstIterator niter;
2605
2606         set_dirty();
2607
2608         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2609                 if ((*niter)->name() == "InputBundle") {
2610                         add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2611                 } else if ((*niter)->name() == "OutputBundle") {
2612                         add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2613                 } else {
2614                         error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2615                         return -1;
2616                 }
2617         }
2618
2619         return 0;
2620 }
2621
2622 int
2623 Session::load_route_groups (const XMLNode& node, int version)
2624 {
2625         XMLNodeList nlist = node.children();
2626         XMLNodeConstIterator niter;
2627
2628         set_dirty ();
2629
2630         if (version >= 3000) {
2631
2632                 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2633                         if ((*niter)->name() == "RouteGroup") {
2634                                 RouteGroup* rg = new RouteGroup (*this, "");
2635                                 add_route_group (rg);
2636                                 rg->set_state (**niter, version);
2637                         }
2638                 }
2639
2640         } else if (version < 3000) {
2641
2642                 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2643                         if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2644                                 RouteGroup* rg = new RouteGroup (*this, "");
2645                                 add_route_group (rg);
2646                                 rg->set_state (**niter, version);
2647                         }
2648                 }
2649         }
2650
2651         return 0;
2652 }
2653
2654 static bool
2655 state_file_filter (const string &str, void* /*arg*/)
2656 {
2657         return (str.length() > strlen(statefile_suffix) &&
2658                 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2659 }
2660
2661 static string
2662 remove_end(string state)
2663 {
2664         string statename(state);
2665
2666         string::size_type start,end;
2667         if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2668                 statename = statename.substr (start+1);
2669         }
2670
2671         if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2672                 end = statename.length();
2673         }
2674
2675         return string(statename.substr (0, end));
2676 }
2677
2678 vector<string>
2679 Session::possible_states (string path)
2680 {
2681         vector<string> states;
2682         find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2683
2684         transform(states.begin(), states.end(), states.begin(), remove_end);
2685
2686         sort (states.begin(), states.end());
2687
2688         return states;
2689 }
2690
2691 vector<string>
2692 Session::possible_states () const
2693 {
2694         return possible_states(_path);
2695 }
2696
2697 RouteGroup*
2698 Session::new_route_group (const std::string& name)
2699 {
2700         RouteGroup* rg = NULL;
2701
2702         for (std::list<RouteGroup*>::const_iterator i = _route_groups.begin (); i != _route_groups.end (); ++i) {
2703                 if ((*i)->name () == name) {
2704                         rg = *i;
2705                         break;
2706                 }
2707         }
2708
2709         if (!rg) {
2710                 rg = new RouteGroup (*this, name);
2711                 add_route_group (rg);
2712         }
2713         return (rg);
2714 }
2715
2716 void
2717 Session::add_route_group (RouteGroup* g)
2718 {
2719         _route_groups.push_back (g);
2720         route_group_added (g); /* EMIT SIGNAL */
2721
2722         g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2723         g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2724         g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2725
2726         set_dirty ();
2727 }
2728
2729 void
2730 Session::remove_route_group (RouteGroup& rg)
2731 {
2732         list<RouteGroup*>::iterator i;
2733
2734         if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2735                 _route_groups.erase (i);
2736                 delete &rg;
2737
2738                 route_group_removed (); /* EMIT SIGNAL */
2739         }
2740 }
2741
2742 /** Set a new order for our route groups, without adding or removing any.
2743  *  @param groups Route group list in the new order.
2744  */
2745 void
2746 Session::reorder_route_groups (list<RouteGroup*> groups)
2747 {
2748         _route_groups = groups;
2749
2750         route_groups_reordered (); /* EMIT SIGNAL */
2751         set_dirty ();
2752 }
2753
2754
2755 RouteGroup *
2756 Session::route_group_by_name (string name)
2757 {
2758         list<RouteGroup *>::iterator i;
2759
2760         for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2761                 if ((*i)->name() == name) {
2762                         return* i;
2763                 }
2764         }
2765         return 0;
2766 }
2767
2768 RouteGroup&
2769 Session::all_route_group() const
2770 {
2771         return *_all_route_group;
2772 }
2773
2774 void
2775 Session::add_commands (vector<Command*> const & cmds)
2776 {
2777         for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2778                 add_command (*i);
2779         }
2780 }
2781
2782 void
2783 Session::add_command (Command* const cmd)
2784 {
2785         assert (_current_trans);
2786         DEBUG_UNDO_HISTORY (
2787             string_compose ("Current Undo Transaction %1, adding command: %2",
2788                             _current_trans->name (),
2789                             cmd->name ()));
2790         _current_trans->add_command (cmd);
2791 }
2792
2793 PBD::StatefulDiffCommand*
2794 Session::add_stateful_diff_command (boost::shared_ptr<PBD::StatefulDestructible> sfd)
2795 {
2796         PBD::StatefulDiffCommand* cmd = new PBD::StatefulDiffCommand (sfd);
2797         add_command (cmd);
2798         return cmd;
2799 }
2800
2801 void
2802 Session::begin_reversible_command (const string& name)
2803 {
2804         begin_reversible_command (g_quark_from_string (name.c_str ()));
2805 }
2806
2807 /** Begin a reversible command using a GQuark to identify it.
2808  *  begin_reversible_command() and commit_reversible_command() calls may be nested,
2809  *  but there must be as many begin...()s as there are commit...()s.
2810  */
2811 void
2812 Session::begin_reversible_command (GQuark q)
2813 {
2814         /* If nested begin/commit pairs are used, we create just one UndoTransaction
2815            to hold all the commands that are committed.  This keeps the order of
2816            commands correct in the history.
2817         */
2818
2819         if (_current_trans == 0) {
2820                 DEBUG_UNDO_HISTORY (string_compose (
2821                     "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2822
2823                 /* start a new transaction */
2824                 assert (_current_trans_quarks.empty ());
2825                 _current_trans = new UndoTransaction();
2826                 _current_trans->set_name (g_quark_to_string (q));
2827         } else {
2828                 DEBUG_UNDO_HISTORY (
2829                     string_compose ("Begin Reversible Command, current transaction: %1",
2830                                     _current_trans->name ()));
2831         }
2832
2833         _current_trans_quarks.push_front (q);
2834 }
2835
2836 void
2837 Session::abort_reversible_command ()
2838 {
2839         if (_current_trans != 0) {
2840                 DEBUG_UNDO_HISTORY (
2841                     string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2842                 _current_trans->clear();
2843                 delete _current_trans;
2844                 _current_trans = 0;
2845                 _current_trans_quarks.clear();
2846         }
2847 }
2848
2849 void
2850 Session::commit_reversible_command (Command *cmd)
2851 {
2852         assert (_current_trans);
2853         assert (!_current_trans_quarks.empty ());
2854
2855         struct timeval now;
2856
2857         if (cmd) {
2858                 DEBUG_UNDO_HISTORY (
2859                     string_compose ("Current Undo Transaction %1, adding command: %2",
2860                                     _current_trans->name (),
2861                                     cmd->name ()));
2862                 _current_trans->add_command (cmd);
2863         }
2864
2865         DEBUG_UNDO_HISTORY (
2866             string_compose ("Commit Reversible Command, current transaction: %1",
2867                             _current_trans->name ()));
2868
2869         _current_trans_quarks.pop_front ();
2870
2871         if (!_current_trans_quarks.empty ()) {
2872                 DEBUG_UNDO_HISTORY (
2873                     string_compose ("Commit Reversible Command, transaction is not "
2874                                     "top-level, current transaction: %1",
2875                                     _current_trans->name ()));
2876                 /* the transaction we're committing is not the top-level one */
2877                 return;
2878         }
2879
2880         if (_current_trans->empty()) {
2881                 /* no commands were added to the transaction, so just get rid of it */
2882                 DEBUG_UNDO_HISTORY (
2883                     string_compose ("Commit Reversible Command, No commands were "
2884                                     "added to current transaction: %1",
2885                                     _current_trans->name ()));
2886                 delete _current_trans;
2887                 _current_trans = 0;
2888                 return;
2889         }
2890
2891         gettimeofday (&now, 0);
2892         _current_trans->set_timestamp (now);
2893
2894         _history.add (_current_trans);
2895         _current_trans = 0;
2896 }
2897
2898 static bool
2899 accept_all_audio_files (const string& path, void* /*arg*/)
2900 {
2901         if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2902                 return false;
2903         }
2904
2905         if (!AudioFileSource::safe_audio_file_extension (path)) {
2906                 return false;
2907         }
2908
2909         return true;
2910 }
2911
2912 static bool
2913 accept_all_midi_files (const string& path, void* /*arg*/)
2914 {
2915         if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2916                 return false;
2917         }
2918
2919         return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2920                 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2921                 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2922 }
2923
2924 static bool
2925 accept_all_state_files (const string& path, void* /*arg*/)
2926 {
2927         if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2928                 return false;
2929         }
2930
2931         std::string const statefile_ext (statefile_suffix);
2932         if (path.length() >= statefile_ext.length()) {
2933                 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2934         } else {
2935                 return false;
2936         }
2937 }
2938
2939 int
2940 Session::find_all_sources (string path, set<string>& result)
2941 {
2942         XMLTree tree;
2943         XMLNode* node;
2944
2945         if (!tree.read (path)) {
2946                 return -1;
2947         }
2948
2949         if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2950                 return -2;
2951         }
2952
2953         XMLNodeList nlist;
2954         XMLNodeConstIterator niter;
2955
2956         nlist = node->children();
2957
2958         set_dirty();
2959
2960         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2961
2962                 XMLProperty const * prop;
2963
2964                 if ((prop = (*niter)->property (X_("type"))) == 0) {
2965                         continue;
2966                 }
2967
2968                 DataType type (prop->value());
2969
2970                 if ((prop = (*niter)->property (X_("name"))) == 0) {
2971                         continue;
2972                 }
2973
2974                 if (Glib::path_is_absolute (prop->value())) {
2975                         /* external file, ignore */
2976                         continue;
2977                 }
2978
2979                 string found_path;
2980                 bool is_new;
2981                 uint16_t chan;
2982
2983                 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2984                         result.insert (found_path);
2985                 }
2986         }
2987
2988         return 0;
2989 }
2990
2991 int
2992 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2993 {
2994         vector<string> state_files;
2995         string ripped;
2996         string this_snapshot_path;
2997
2998         result.clear ();
2999
3000         ripped = _path;
3001
3002         if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
3003                 ripped = ripped.substr (0, ripped.length() - 1);
3004         }
3005
3006         find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
3007
3008         if (state_files.empty()) {
3009                 /* impossible! */
3010                 return 0;
3011         }
3012
3013         this_snapshot_path = Glib::build_filename (_path, legalize_for_path (_current_snapshot_name));
3014         this_snapshot_path += statefile_suffix;
3015
3016         for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
3017
3018                 cerr << "Looking at snapshot " << (*i) << " ( with this = [" << this_snapshot_path << "])\n";
3019
3020                 if (exclude_this_snapshot && *i == this_snapshot_path) {
3021                         cerr << "\texcluded\n";
3022                         continue;
3023
3024                 }
3025
3026                 if (find_all_sources (*i, result) < 0) {
3027                         return -1;
3028                 }
3029         }
3030
3031         return 0;
3032 }
3033
3034 struct RegionCounter {
3035     typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
3036     AudioSourceList::iterator iter;
3037     boost::shared_ptr<Region> region;
3038     uint32_t count;
3039
3040     RegionCounter() : count (0) {}
3041 };
3042
3043 int
3044 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
3045 {
3046         boost::optional<int> r = AskAboutPlaylistDeletion (p);
3047         return r.get_value_or (1);
3048 }
3049
3050 void
3051 Session::cleanup_regions ()
3052 {
3053         bool removed = false;
3054         const RegionFactory::RegionMap& regions (RegionFactory::regions());
3055
3056         for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
3057
3058                 uint32_t used = playlists->region_use_count (i->second);
3059
3060                 if (used == 0 && !i->second->automatic ()) {
3061                         boost::weak_ptr<Region> w = i->second;
3062                         ++i;
3063                         removed = true;
3064                         RegionFactory::map_remove (w);
3065                 } else {
3066                         ++i;
3067                 }
3068         }
3069
3070         if (removed) {
3071                 // re-check to remove parent references of compound regions
3072                 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
3073                         if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
3074                                 ++i;
3075                                 continue;
3076                         }
3077                         assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
3078                         if (0 == playlists->region_use_count (i->second)) {
3079                                 boost::weak_ptr<Region> w = i->second;
3080                                 ++i;
3081                                 RegionFactory::map_remove (w);
3082                         } else {
3083                                 ++i;
3084                         }
3085                 }
3086         }
3087
3088         /* dump the history list */
3089         _history.clear ();
3090
3091         save_state ("");
3092 }
3093
3094 bool
3095 Session::can_cleanup_peakfiles () const
3096 {
3097         if (deletion_in_progress()) {
3098                 return false;
3099         }
3100         if (!_writable || (_state_of_the_state & CannotSave)) {
3101                 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
3102                 return false;
3103         }
3104         if (record_status() == Recording) {
3105                 error << _("Cannot cleanup peak-files while recording") << endmsg;
3106                 return false;
3107         }
3108         return true;
3109 }
3110
3111 int
3112 Session::cleanup_peakfiles ()
3113 {
3114         Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
3115         if (!lm.locked()) {
3116                 return -1;
3117         }
3118
3119         assert (can_cleanup_peakfiles ());
3120         assert (!peaks_cleanup_in_progres());
3121
3122         _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
3123
3124         int timeout = 5000; // 5 seconds
3125         while (!SourceFactory::files_with_peaks.empty()) {
3126                 Glib::usleep (1000);
3127                 if (--timeout < 0) {
3128                         warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
3129                         _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
3130                         return -1;
3131                 }
3132         }
3133
3134         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3135                 boost::shared_ptr<AudioSource> as;
3136                 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
3137                         as->close_peakfile();
3138                 }
3139         }
3140
3141         PBD::clear_directory (session_directory().peak_path());
3142
3143         _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
3144
3145         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3146                 boost::shared_ptr<AudioSource> as;
3147                 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
3148                         SourceFactory::setup_peakfile(as, true);
3149                 }
3150         }
3151         return 0;
3152 }
3153
3154 static void
3155 merge_all_sources (boost::shared_ptr<const Playlist> pl, std::set<boost::shared_ptr<Source> >* all_sources)
3156 {
3157         pl->deep_sources (*all_sources);
3158 }
3159
3160 int
3161 Session::cleanup_sources (CleanupReport& rep)
3162 {
3163         // FIXME: needs adaptation to midi
3164
3165         vector<boost::shared_ptr<Source> > dead_sources;
3166         string audio_path;
3167         string midi_path;
3168         vector<string> candidates;
3169         vector<string> unused;
3170         set<string> sources_used_by_all_snapshots;
3171         string spath;
3172         int ret = -1;
3173         string tmppath1;
3174         string tmppath2;
3175         Searchpath asp;
3176         Searchpath msp;
3177         set<boost::shared_ptr<Source> > sources_used_by_this_snapshot;
3178
3179         _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
3180
3181         /* this is mostly for windows which doesn't allow file
3182          * renaming if the file is in use. But we don't special
3183          * case it because we need to know if this causes
3184          * problems, and the easiest way to notice that is to
3185          * keep it in place for all platforms.
3186          */
3187
3188         request_stop (false);
3189         _butler->summon ();
3190         _butler->wait_until_finished ();
3191
3192         /* consider deleting all unused playlists */
3193
3194         if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
3195                 ret = 0;
3196                 goto out;
3197         }
3198
3199         /* sync the "all regions" property of each playlist with its current state
3200          */
3201
3202         playlists->sync_all_regions_with_regions ();
3203
3204         /* find all un-used sources */
3205
3206         rep.paths.clear ();
3207         rep.space = 0;
3208
3209         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3210
3211                 SourceMap::iterator tmp;
3212
3213                 tmp = i;
3214                 ++tmp;
3215
3216                 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
3217                    capture files.
3218                 */
3219
3220                 if (!i->second->used() && (i->second->length(i->second->timeline_position()) > 0)) {
3221                         dead_sources.push_back (i->second);
3222                         i->second->drop_references ();
3223                 }
3224
3225                 i = tmp;
3226         }
3227
3228         /* build a list of all the possible audio directories for the session */
3229
3230         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3231                 SessionDirectory sdir ((*i).path);
3232                 asp += sdir.sound_path();
3233         }
3234         audio_path += asp.to_string();
3235
3236
3237         /* build a list of all the possible midi directories for the session */
3238
3239         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3240                 SessionDirectory sdir ((*i).path);
3241                 msp += sdir.midi_path();
3242         }
3243         midi_path += msp.to_string();
3244
3245         find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3246         find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3247
3248         /* add sources from all other snapshots as "used", but don't use this
3249            snapshot because the state file on disk still references sources we
3250            may have already dropped.
3251         */
3252
3253         find_all_sources_across_snapshots (sources_used_by_all_snapshots, true);
3254
3255         /* Although the region factory has a list of all regions ever created
3256          * for this session, we're only interested in regions actually in
3257          * playlists right now. So merge all playlist regions lists together.
3258          *
3259          * This will include the playlists used within compound regions.
3260          */
3261
3262         playlists->foreach (boost::bind (merge_all_sources, _1, &sources_used_by_this_snapshot));
3263
3264         /*  add our current source list
3265          */
3266
3267         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3268                 boost::shared_ptr<FileSource> fs;
3269                 SourceMap::iterator tmp = i;
3270                 ++tmp;
3271
3272                 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) == 0) {
3273                         /* not a file */
3274                         i = tmp;
3275                         continue;
3276                 }
3277
3278                 /* this is mostly for windows which doesn't allow file
3279                  * renaming if the file is in use. But we do not special
3280                  * case it because we need to know if this causes
3281                  * problems, and the easiest way to notice that is to
3282                  * keep it in place for all platforms.
3283                  */
3284
3285                 fs->close ();
3286
3287                 if (!fs->is_stub()) {
3288
3289                         /* Note that we're checking a list of all
3290                          * sources across all snapshots with the list
3291                          * of sources used by this snapshot.
3292                          */
3293
3294                         if (sources_used_by_this_snapshot.find (i->second) != sources_used_by_this_snapshot.end()) {
3295                                 /* this source is in use by this snapshot */
3296                                 sources_used_by_all_snapshots.insert (fs->path());
3297                                 cerr << "Source from source list found in used_by_this_snapshot (" << fs->path() << ")\n";
3298                         } else {
3299                                 cerr << "Source from source list NOT found in used_by_this_snapshot (" << fs->path() << ")\n";
3300                                 /* this source is NOT in use by this snapshot
3301                                  */
3302
3303                                 /* remove all related regions from RegionFactory master list
3304                                  */
3305
3306                                 RegionFactory::remove_regions_using_source (i->second);
3307
3308                                 /* remove from our current source list
3309                                  * also. We may not remove it from
3310                                  * disk, because it may be used by
3311                                  * other snapshots, but it isn't used inside this
3312                                  * snapshot anymore, so we don't need a
3313                                  * reference to it.
3314                                  */
3315
3316                                 sources.erase (i);
3317                         }
3318                 }
3319
3320                 i = tmp;
3321         }
3322
3323         /* now check each candidate source to see if it exists in the list of
3324            sources_used_by_all_snapshots. If it doesn't, put it into "unused".
3325         */
3326
3327         cerr << "Candidates: " << candidates.size() << endl;
3328         cerr << "Used by others: " << sources_used_by_all_snapshots.size() << endl;
3329
3330         for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3331
3332                 bool used = false;
3333                 spath = *x;
3334
3335                 for (set<string>::iterator i = sources_used_by_all_snapshots.begin(); i != sources_used_by_all_snapshots.end(); ++i) {
3336
3337                         tmppath1 = canonical_path (spath);
3338                         tmppath2 = canonical_path ((*i));
3339
3340                         cerr << "\t => " << tmppath2 << endl;
3341
3342                         if (tmppath1 == tmppath2) {
3343                                 used = true;
3344                                 break;
3345                         }
3346                 }
3347
3348                 if (!used) {
3349                         unused.push_back (spath);
3350                 }
3351         }
3352
3353         cerr << "Actually unused: " << unused.size() << endl;
3354
3355         if (unused.empty()) {
3356                 /* Nothing to do */
3357                 ret = 0;
3358                 goto out;
3359         }
3360
3361         /* now try to move all unused files into the "dead" directory(ies) */
3362
3363         for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3364                 GStatBuf statbuf;
3365
3366                 string newpath;
3367
3368                 /* don't move the file across filesystems, just
3369                    stick it in the `dead_dir_name' directory
3370                    on whichever filesystem it was already on.
3371                 */
3372
3373                 if ((*x).find ("/sounds/") != string::npos) {
3374
3375                         /* old school, go up 1 level */
3376
3377                         newpath = Glib::path_get_dirname (*x);      // "sounds"
3378                         newpath = Glib::path_get_dirname (newpath); // "session-name"
3379
3380                 } else {
3381
3382                         /* new school, go up 4 levels */
3383
3384                         newpath = Glib::path_get_dirname (*x);      // "audiofiles" or "midifiles"
3385                         newpath = Glib::path_get_dirname (newpath); // "session-name"
3386                         newpath = Glib::path_get_dirname (newpath); // "interchange"
3387                         newpath = Glib::path_get_dirname (newpath); // "session-dir"
3388                 }
3389
3390                 newpath = Glib::build_filename (newpath, dead_dir_name);
3391
3392                 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3393                         error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3394                         return -1;
3395                 }
3396
3397                 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3398
3399                 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3400
3401                         /* the new path already exists, try versioning */
3402
3403                         char buf[PATH_MAX+1];
3404                         int version = 1;
3405                         string newpath_v;
3406
3407                         snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3408                         newpath_v = buf;
3409
3410                         while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3411                                 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3412                                 newpath_v = buf;
3413                         }
3414
3415                         if (version == 999) {
3416                                 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3417                                                   newpath)
3418                                       << endmsg;
3419                         } else {
3420                                 newpath = newpath_v;
3421                         }
3422
3423                 }
3424
3425                 if ((g_stat ((*x).c_str(), &statbuf) != 0) || (::g_rename ((*x).c_str(), newpath.c_str()) != 0)) {
3426                         error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"), (*x),
3427                                                  newpath, g_strerror (errno)) << endmsg;
3428                         continue;
3429                 }
3430
3431                 /* see if there an easy to find peakfile for this file, and remove it.
3432                  */
3433
3434                 string base = Glib::path_get_basename (*x);
3435                 base += "%A"; /* this is what we add for the channel suffix of all native files,
3436                                  or for the first channel of embedded files. it will miss
3437                                  some peakfiles for other channels
3438                                */
3439                 string peakpath = construct_peak_filepath (base);
3440
3441                 if (Glib::file_test (peakpath.c_str (), Glib::FILE_TEST_EXISTS)) {
3442                         if (::g_unlink (peakpath.c_str ()) != 0) {
3443                                 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"), peakpath, _path,
3444                                                          g_strerror (errno)) << endmsg;
3445                                 /* try to back out */
3446                                 ::g_rename (newpath.c_str (), _path.c_str ());
3447                                 goto out;
3448                         }
3449                 }
3450
3451                 rep.paths.push_back (*x);
3452                 rep.space += statbuf.st_size;
3453         }
3454
3455         /* dump the history list */
3456
3457         _history.clear ();
3458
3459         /* save state so we don't end up a session file
3460            referring to non-existent sources.
3461         */
3462
3463         save_state ("");
3464         ret = 0;
3465
3466   out:
3467         _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3468
3469         return ret;
3470 }
3471
3472 int
3473 Session::cleanup_trash_sources (CleanupReport& rep)
3474 {
3475         // FIXME: needs adaptation for MIDI
3476
3477         vector<space_and_path>::iterator i;
3478         string dead_dir;
3479
3480         rep.paths.clear ();
3481         rep.space = 0;
3482
3483         for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3484
3485                 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3486
3487                 clear_directory (dead_dir, &rep.space, &rep.paths);
3488         }
3489
3490         return 0;
3491 }
3492
3493 void
3494 Session::set_dirty ()
3495 {
3496         /* never mark session dirty during loading */
3497
3498         if (_state_of_the_state & Loading) {
3499                 return;
3500         }
3501
3502         bool was_dirty = dirty();
3503
3504         _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3505
3506
3507         if (!was_dirty) {
3508                 DirtyChanged(); /* EMIT SIGNAL */
3509         }
3510 }
3511
3512
3513 void
3514 Session::set_clean ()
3515 {
3516         bool was_dirty = dirty();
3517
3518         _state_of_the_state = Clean;
3519
3520
3521         if (was_dirty) {
3522                 DirtyChanged(); /* EMIT SIGNAL */
3523         }
3524 }
3525
3526 void
3527 Session::set_deletion_in_progress ()
3528 {
3529         _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3530 }
3531
3532 void
3533 Session::clear_deletion_in_progress ()
3534 {
3535         _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3536 }
3537
3538 void
3539 Session::add_controllable (boost::shared_ptr<Controllable> c)
3540 {
3541         /* this adds a controllable to the list managed by the Session.
3542            this is a subset of those managed by the Controllable class
3543            itself, and represents the only ones whose state will be saved
3544            as part of the session.
3545         */
3546
3547         Glib::Threads::Mutex::Lock lm (controllables_lock);
3548         controllables.insert (c);
3549 }
3550
3551 struct null_deleter { void operator()(void const *) const {} };
3552
3553 void
3554 Session::remove_controllable (Controllable* c)
3555 {
3556         if (_state_of_the_state & Deletion) {
3557                 return;
3558         }
3559
3560         Glib::Threads::Mutex::Lock lm (controllables_lock);
3561
3562         Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3563
3564         if (x != controllables.end()) {
3565                 controllables.erase (x);
3566         }
3567 }
3568
3569 boost::shared_ptr<Controllable>
3570 Session::controllable_by_id (const PBD::ID& id)
3571 {
3572         Glib::Threads::Mutex::Lock lm (controllables_lock);
3573
3574         for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3575                 if ((*i)->id() == id) {
3576                         return *i;
3577                 }
3578         }
3579
3580         return boost::shared_ptr<Controllable>();
3581 }
3582
3583 boost::shared_ptr<Controllable>
3584 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3585 {
3586         boost::shared_ptr<Controllable> c;
3587         boost::shared_ptr<Stripable> s;
3588         boost::shared_ptr<Route> r;
3589
3590         switch (desc.top_level_type()) {
3591         case ControllableDescriptor::NamedRoute:
3592         {
3593                 std::string str = desc.top_level_name();
3594
3595                 if (str == "Master" || str == "master") {
3596                         s = _master_out;
3597                 } else if (str == "control" || str == "listen" || str == "monitor" || str == "Monitor") {
3598                         s = _monitor_out;
3599                 } else if (str == "auditioner") {
3600                         s = auditioner;
3601                 } else {
3602                         s = route_by_name (desc.top_level_name());
3603                 }
3604
3605                 break;
3606         }
3607
3608         case ControllableDescriptor::PresentationOrderRoute:
3609                 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::Route);
3610                 break;
3611
3612         case ControllableDescriptor::PresentationOrderTrack:
3613                 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::Track);
3614                 break;
3615
3616         case ControllableDescriptor::PresentationOrderBus:
3617                 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::Bus);
3618                 break;
3619
3620         case ControllableDescriptor::PresentationOrderVCA:
3621                 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::VCA);
3622                 break;
3623
3624         case ControllableDescriptor::SelectionCount:
3625                 s = route_by_selected_count (desc.selection_id());
3626                 break;
3627         }
3628
3629         if (!s) {
3630                 return c;
3631         }
3632
3633         r = boost::dynamic_pointer_cast<Route> (s);
3634
3635         switch (desc.subtype()) {
3636         case ControllableDescriptor::Gain:
3637                 c = s->gain_control ();
3638                 break;
3639
3640         case ControllableDescriptor::Trim:
3641                 c = s->trim_control ();
3642                 break;
3643
3644         case ControllableDescriptor::Solo:
3645                 c = s->solo_control();
3646                 break;
3647
3648         case ControllableDescriptor::Mute:
3649                 c = s->mute_control();
3650                 break;
3651
3652         case ControllableDescriptor::Recenable:
3653                 c = s->rec_enable_control ();
3654                 break;
3655
3656         case ControllableDescriptor::PanDirection:
3657                 c = s->pan_azimuth_control();
3658                 break;
3659
3660         case ControllableDescriptor::PanWidth:
3661                 c = s->pan_width_control();
3662                 break;
3663
3664         case ControllableDescriptor::PanElevation:
3665                 c = s->pan_elevation_control();
3666                 break;
3667
3668         case ControllableDescriptor::Balance:
3669                 /* XXX simple pan control */
3670                 break;
3671
3672         case ControllableDescriptor::PluginParameter:
3673         {
3674                 uint32_t plugin = desc.target (0);
3675                 uint32_t parameter_index = desc.target (1);
3676
3677                 /* revert to zero based counting */
3678
3679                 if (plugin > 0) {
3680                         --plugin;
3681                 }
3682
3683                 if (parameter_index > 0) {
3684                         --parameter_index;
3685                 }
3686
3687                 if (!r) {
3688                         return c;
3689                 }
3690
3691                 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3692
3693                 if (p) {
3694                         c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3695                                 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3696                 }
3697                 break;
3698         }
3699
3700         case ControllableDescriptor::SendGain: {
3701                 uint32_t send = desc.target (0);
3702                 if (send > 0) {
3703                         --send;
3704                 }
3705                 if (!r) {
3706                         return c;
3707                 }
3708                 c = r->send_level_controllable (send);
3709                 break;
3710         }
3711
3712         default:
3713                 /* relax and return a null pointer */
3714                 break;
3715         }
3716
3717         return c;
3718 }
3719
3720 void
3721 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3722 {
3723         if (_writable) {
3724                 Stateful::add_instant_xml (node, _path);
3725         }
3726
3727         if (write_to_config) {
3728                 Config->add_instant_xml (node);
3729         }
3730 }
3731
3732 XMLNode*
3733 Session::instant_xml (const string& node_name)
3734 {
3735 #ifdef MIXBUS // "Safe Mode" (shift + click open) -> also ignore instant.xml
3736         if (get_disable_all_loaded_plugins ()) {
3737                 return NULL;
3738         }
3739 #endif
3740         return Stateful::instant_xml (node_name, _path);
3741 }
3742
3743 int
3744 Session::save_history (string snapshot_name)
3745 {
3746         XMLTree tree;
3747
3748         if (!_writable) {
3749                 return 0;
3750         }
3751
3752         if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3753             (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3754                 return 0;
3755         }
3756
3757         if (snapshot_name.empty()) {
3758                 snapshot_name = _current_snapshot_name;
3759         }
3760
3761         const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3762         const string backup_filename = history_filename + backup_suffix;
3763         const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3764         const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3765
3766         if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3767                 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3768                         error << _("could not backup old history file, current history not saved") << endmsg;
3769                         return -1;
3770                 }
3771         }
3772
3773         tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3774
3775         if (!tree.write (xml_path))
3776         {
3777                 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3778
3779                 if (g_remove (xml_path.c_str()) != 0) {
3780                         error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3781                                         xml_path, g_strerror (errno)) << endmsg;
3782                 }
3783                 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3784                         error << string_compose (_("could not restore history file from backup %1 (%2)"),
3785                                         backup_path, g_strerror (errno)) << endmsg;
3786                 }
3787
3788                 return -1;
3789         }
3790
3791         return 0;
3792 }
3793
3794 int
3795 Session::restore_history (string snapshot_name)
3796 {
3797         XMLTree tree;
3798
3799         if (snapshot_name.empty()) {
3800                 snapshot_name = _current_snapshot_name;
3801         }
3802
3803         const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3804         const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3805
3806         info << "Loading history from " << xml_path << endmsg;
3807
3808         if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3809                 info << string_compose (_("%1: no history file \"%2\" for this session."),
3810                                 _name, xml_path) << endmsg;
3811                 return 1;
3812         }
3813
3814         if (!tree.read (xml_path)) {
3815                 error << string_compose (_("Could not understand session history file \"%1\""),
3816                                 xml_path) << endmsg;
3817                 return -1;
3818         }
3819
3820         // replace history
3821         _history.clear();
3822
3823         for (XMLNodeConstIterator it  = tree.root()->children().begin(); it != tree.root()->children().end(); ++it) {
3824
3825                 XMLNode *t = *it;
3826                 UndoTransaction* ut = new UndoTransaction ();
3827                 struct timeval tv;
3828
3829                 ut->set_name(t->property("name")->value());
3830                 stringstream ss(t->property("tv-sec")->value());
3831                 ss >> tv.tv_sec;
3832                 ss.str(t->property("tv-usec")->value());
3833                 ss >> tv.tv_usec;
3834                 ut->set_timestamp(tv);
3835
3836                 for (XMLNodeConstIterator child_it  = t->children().begin();
3837                                 child_it != t->children().end(); child_it++)
3838                 {
3839                         XMLNode *n = *child_it;
3840                         Command *c;
3841
3842                         if (n->name() == "MementoCommand" ||
3843                                         n->name() == "MementoUndoCommand" ||
3844                                         n->name() == "MementoRedoCommand") {
3845
3846                                 if ((c = memento_command_factory(n))) {
3847                                         ut->add_command(c);
3848                                 }
3849
3850                         } else if (n->name() == "NoteDiffCommand") {
3851                                 PBD::ID id (n->property("midi-source")->value());
3852                                 boost::shared_ptr<MidiSource> midi_source =
3853                                         boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3854                                 if (midi_source) {
3855                                         ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3856                                 } else {
3857                                         error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3858                                 }
3859
3860                         } else if (n->name() == "SysExDiffCommand") {
3861
3862                                 PBD::ID id (n->property("midi-source")->value());
3863                                 boost::shared_ptr<MidiSource> midi_source =
3864                                         boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3865                                 if (midi_source) {
3866                                         ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3867                                 } else {
3868                                         error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3869                                 }
3870
3871                         } else if (n->name() == "PatchChangeDiffCommand") {
3872
3873                                 PBD::ID id (n->property("midi-source")->value());
3874                                 boost::shared_ptr<MidiSource> midi_source =
3875                                         boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3876                                 if (midi_source) {
3877                                         ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3878                                 } else {
3879                                         error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3880                                 }
3881
3882                         } else if (n->name() == "StatefulDiffCommand") {
3883                                 if ((c = stateful_diff_command_factory (n))) {
3884                                         ut->add_command (c);
3885                                 }
3886                         } else {
3887                                 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3888                         }
3889                 }
3890
3891                 _history.add (ut);
3892         }
3893
3894         return 0;
3895 }
3896
3897 void
3898 Session::config_changed (std::string p, bool ours)
3899 {
3900         if (ours) {
3901                 set_dirty ();
3902         }
3903
3904         if (p == "seamless-loop") {
3905
3906         } else if (p == "rf-speed") {
3907
3908         } else if (p == "auto-loop") {
3909
3910         } else if (p == "session-monitoring") {
3911
3912         } else if (p == "auto-input") {
3913
3914                 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3915                         /* auto-input only makes a difference if we're rolling */
3916                         set_track_monitor_input_status (!config.get_auto_input());
3917                 }
3918
3919         } else if (p == "punch-in") {
3920
3921                 Location* location;
3922
3923                 if ((location = _locations->auto_punch_location()) != 0) {
3924
3925                         if (config.get_punch_in ()) {
3926                                 replace_event (SessionEvent::PunchIn, location->start());
3927                         } else {
3928                                 remove_event (location->start(), SessionEvent::PunchIn);
3929                         }
3930                 }
3931
3932         } else if (p == "punch-out") {
3933
3934                 Location* location;
3935
3936                 if ((location = _locations->auto_punch_location()) != 0) {
3937
3938                         if (config.get_punch_out()) {
3939                                 replace_event (SessionEvent::PunchOut, location->end());
3940                         } else {
3941                                 clear_events (SessionEvent::PunchOut);
3942                         }
3943                 }
3944
3945         } else if (p == "edit-mode") {
3946
3947                 Glib::Threads::Mutex::Lock lm (playlists->lock);
3948
3949                 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3950                         (*i)->set_edit_mode (Config->get_edit_mode ());
3951                 }
3952
3953         } else if (p == "use-video-sync") {
3954
3955                 waiting_for_sync_offset = config.get_use_video_sync();
3956
3957         } else if (p == "mmc-control") {
3958
3959                 //poke_midi_thread ();
3960
3961         } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3962
3963                 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3964
3965         } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3966
3967                 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3968
3969         } else if (p == "midi-control") {
3970
3971                 //poke_midi_thread ();
3972
3973         } else if (p == "raid-path") {
3974
3975                 setup_raid_path (config.get_raid_path());
3976
3977         } else if (p == "timecode-format") {
3978
3979                 sync_time_vars ();
3980
3981         } else if (p == "video-pullup") {
3982
3983                 sync_time_vars ();
3984
3985         } else if (p == "seamless-loop") {
3986
3987                 if (play_loop && transport_rolling()) {
3988                         // to reset diskstreams etc
3989                         request_play_loop (true);
3990                 }
3991
3992         } else if (p == "rf-speed") {
3993
3994                 cumulative_rf_motion = 0;
3995                 reset_rf_scale (0);
3996
3997         } else if (p == "click-sound") {
3998
3999                 setup_click_sounds (1);
4000
4001         } else if (p == "click-emphasis-sound") {
4002
4003                 setup_click_sounds (-1);
4004
4005         } else if (p == "clicking") {
4006
4007                 if (Config->get_clicking()) {
4008                         if (_click_io && click_data) { // don't require emphasis data
4009                                 _clicking = true;
4010                         }
4011                 } else {
4012                         _clicking = false;
4013                 }
4014
4015         } else if (p == "click-gain") {
4016
4017                 if (_click_gain) {
4018                         _click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
4019                 }
4020
4021         } else if (p == "send-mtc") {
4022
4023                 if (Config->get_send_mtc ()) {
4024                         /* mark us ready to send */
4025                         next_quarter_frame_to_send = 0;
4026                 }
4027
4028         } else if (p == "send-mmc") {
4029
4030                 _mmc->enable_send (Config->get_send_mmc ());
4031
4032         } else if (p == "jack-time-master") {
4033
4034                 engine().reset_timebase ();
4035
4036         } else if (p == "native-file-header-format") {
4037
4038                 if (!first_file_header_format_reset) {
4039                         reset_native_file_format ();
4040                 }
4041
4042                 first_file_header_format_reset = false;
4043
4044         } else if (p == "native-file-data-format") {
4045
4046                 if (!first_file_data_format_reset) {
4047                         reset_native_file_format ();
4048                 }
4049
4050                 first_file_data_format_reset = false;
4051
4052         } else if (p == "external-sync") {
4053                 if (!config.get_external_sync()) {
4054                         drop_sync_source ();
4055                 } else {
4056                         switch_to_sync_source (Config->get_sync_source());
4057                 }
4058         }  else if (p == "denormal-model") {
4059                 setup_fpu ();
4060         } else if (p == "history-depth") {
4061                 set_history_depth (Config->get_history_depth());
4062         } else if (p == "remote-model") {
4063                 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
4064                    TO SET REMOTE ID'S
4065                 */
4066         } else if (p == "initial-program-change") {
4067
4068                 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
4069                         MIDI::byte buf[2];
4070
4071                         buf[0] = MIDI::program; // channel zero by default
4072                         buf[1] = (Config->get_initial_program_change() & 0x7f);
4073
4074                         _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
4075                 }
4076         } else if (p == "solo-mute-override") {
4077                 // catch_up_on_solo_mute_override ();
4078         } else if (p == "listen-position" || p == "pfl-position") {
4079                 listen_position_changed ();
4080         } else if (p == "solo-control-is-listen-control") {
4081                 solo_control_mode_changed ();
4082         } else if (p == "solo-mute-gain") {
4083                 _solo_cut_control->Changed (true, Controllable::NoGroup);
4084         } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
4085                 last_timecode_valid = false;
4086         } else if (p == "playback-buffer-seconds") {
4087                 AudioSource::allocate_working_buffers (frame_rate());
4088         } else if (p == "ltc-source-port") {
4089                 reconnect_ltc_input ();
4090         } else if (p == "ltc-sink-port") {
4091                 reconnect_ltc_output ();
4092         } else if (p == "timecode-generator-offset") {
4093                 ltc_tx_parse_offset();
4094         } else if (p == "auto-return-target-list") {
4095                 follow_playhead_priority ();
4096         }
4097
4098         set_dirty ();
4099 }
4100
4101 void
4102 Session::set_history_depth (uint32_t d)
4103 {
4104         _history.set_depth (d);
4105 }
4106
4107 int
4108 Session::load_diskstreams_2X (XMLNode const & node, int)
4109 {
4110         XMLNodeList          clist;
4111         XMLNodeConstIterator citer;
4112
4113         clist = node.children();
4114
4115         for (citer = clist.begin(); citer != clist.end(); ++citer) {
4116
4117                 try {
4118                         /* diskstreams added automatically by DiskstreamCreated handler */
4119                         if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
4120                                 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
4121                                 _diskstreams_2X.push_back (dsp);
4122                         } else {
4123                                 error << _("Session: unknown diskstream type in XML") << endmsg;
4124                         }
4125                 }
4126
4127                 catch (failed_constructor& err) {
4128                         error << _("Session: could not load diskstream via XML state") << endmsg;
4129                         return -1;
4130                 }
4131         }
4132
4133         return 0;
4134 }
4135
4136 /** Connect things to the MMC object */
4137 void
4138 Session::setup_midi_machine_control ()
4139 {
4140         _mmc = new MIDI::MachineControl;
4141
4142         boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
4143         boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
4144
4145         if (!async_out || !async_out) {
4146                 return;
4147         }
4148
4149         /* XXXX argh, passing raw pointers back into libmidi++ */
4150
4151         MIDI::Port* mmc_in = async_in.get();
4152         MIDI::Port* mmc_out = async_out.get();
4153
4154         _mmc->set_ports (mmc_in, mmc_out);
4155
4156         _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
4157         _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
4158         _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
4159         _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
4160         _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
4161         _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
4162         _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
4163         _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
4164         _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
4165         _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
4166         _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
4167         _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
4168         _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
4169
4170         /* also handle MIDI SPP because its so common */
4171
4172         _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
4173         _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
4174         _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
4175 }
4176
4177 boost::shared_ptr<Controllable>
4178 Session::solo_cut_control() const
4179 {
4180         /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
4181            controls in Ardour that currently get presented to the user in the GUI that require
4182            access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
4183
4184            its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
4185            it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
4186            parameter.
4187         */
4188
4189         return _solo_cut_control;
4190 }
4191
4192 void
4193 Session::save_snapshot_name (const std::string & n)
4194 {
4195         /* assure Stateful::_instant_xml is loaded
4196          * add_instant_xml() only adds to existing data and defaults
4197          * to use an empty Tree otherwise
4198          */
4199         instant_xml ("LastUsedSnapshot");
4200
4201         XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
4202         last_used_snapshot->add_property ("name", string(n));
4203         add_instant_xml (*last_used_snapshot, false);
4204 }
4205
4206 void
4207 Session::set_snapshot_name (const std::string & n)
4208 {
4209         _current_snapshot_name = n;
4210         save_snapshot_name (n);
4211 }
4212
4213 int
4214 Session::rename (const std::string& new_name)
4215 {
4216         string legal_name = legalize_for_path (new_name);
4217         string new_path;
4218         string oldstr;
4219         string newstr;
4220         bool first = true;
4221
4222         string const old_sources_root = _session_dir->sources_root();
4223
4224         if (!_writable || (_state_of_the_state & CannotSave)) {
4225                 error << _("Cannot rename read-only session.") << endmsg;
4226                 return 0; // don't show "messed up" warning
4227         }
4228         if (record_status() == Recording) {
4229                 error << _("Cannot rename session while recording") << endmsg;
4230                 return 0; // don't show "messed up" warning
4231         }
4232
4233         StateProtector stp (this);
4234
4235         /* Rename:
4236
4237          * session directory
4238          * interchange subdirectory
4239          * session file
4240          * session history
4241
4242          * Backup files are left unchanged and not renamed.
4243          */
4244
4245         /* Windows requires that we close all files before attempting the
4246          * rename. This works on other platforms, but isn't necessary there.
4247          * Leave it in place for all platforms though, since it may help
4248          * catch issues that could arise if the way Source files work ever
4249          * change (since most developers are not using Windows).
4250          */
4251
4252         for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4253                 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4254                 if (fs) {
4255                         fs->close ();
4256                 }
4257         }
4258
4259         /* pass one: not 100% safe check that the new directory names don't
4260          * already exist ...
4261          */
4262
4263         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4264
4265                 oldstr = (*i).path;
4266
4267                 /* this is a stupid hack because Glib::path_get_dirname() is
4268                  * lexical-only, and so passing it /a/b/c/ gives a different
4269                  * result than passing it /a/b/c ...
4270                  */
4271
4272                 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4273                         oldstr = oldstr.substr (0, oldstr.length() - 1);
4274                 }
4275
4276                 string base = Glib::path_get_dirname (oldstr);
4277
4278                 newstr = Glib::build_filename (base, legal_name);
4279
4280                 cerr << "Looking for " << newstr << endl;
4281
4282                 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4283                         cerr << " exists\n";
4284                         return -1;
4285                 }
4286         }
4287
4288         /* Session dirs */
4289
4290         first = true;
4291
4292         for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4293
4294                 vector<string> v;
4295
4296                 oldstr = (*i).path;
4297
4298                 /* this is a stupid hack because Glib::path_get_dirname() is
4299                  * lexical-only, and so passing it /a/b/c/ gives a different
4300                  * result than passing it /a/b/c ...
4301                  */
4302
4303                 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4304                         oldstr = oldstr.substr (0, oldstr.length() - 1);
4305                 }
4306
4307                 string base = Glib::path_get_dirname (oldstr);
4308                 newstr = Glib::build_filename (base, legal_name);
4309
4310                 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4311
4312                 cerr << "Rename " << oldstr << " => " << newstr << endl;
4313                 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4314                         cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4315                         error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4316                         return 1;
4317                 }
4318
4319                 /* Reset path in "session dirs" */
4320
4321                 (*i).path = newstr;
4322                 (*i).blocks = 0;
4323
4324                 /* reset primary SessionDirectory object */
4325
4326                 if (first) {
4327                         (*_session_dir) = newstr;
4328                         new_path = newstr;
4329                         first = false;
4330                 }
4331
4332                 /* now rename directory below session_dir/interchange */
4333
4334                 string old_interchange_dir;
4335                 string new_interchange_dir;
4336
4337                 /* use newstr here because we renamed the path
4338                  * (folder/directory) that used to be oldstr to newstr above
4339                  */
4340
4341                 v.push_back (newstr);
4342                 v.push_back (interchange_dir_name);
4343                 v.push_back (Glib::path_get_basename (oldstr));
4344
4345                 old_interchange_dir = Glib::build_filename (v);
4346
4347                 v.clear ();
4348                 v.push_back (newstr);
4349                 v.push_back (interchange_dir_name);
4350                 v.push_back (legal_name);
4351
4352                 new_interchange_dir = Glib::build_filename (v);
4353
4354                 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4355
4356                 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4357                         cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4358                                                  old_interchange_dir, new_interchange_dir,
4359                                                  g_strerror (errno))
4360                               << endl;
4361                         error << string_compose (_("renaming %s as %2 failed (%3)"),
4362                                                  old_interchange_dir, new_interchange_dir,
4363                                                  g_strerror (errno))
4364                               << endmsg;
4365                         return 1;
4366                 }
4367         }
4368
4369         /* state file */
4370
4371         oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4372         newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4373
4374         cerr << "Rename " << oldstr << " => " << newstr << endl;
4375
4376         if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4377                 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4378                 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4379                 return 1;
4380         }
4381
4382         /* history file */
4383
4384         oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4385
4386         if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS))  {
4387                 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4388
4389                 cerr << "Rename " << oldstr << " => " << newstr << endl;
4390
4391                 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4392                         cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4393                         error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4394                         return 1;
4395                 }
4396         }
4397
4398         /* remove old name from recent sessions */
4399         remove_recent_sessions (_path);
4400         _path = new_path;
4401
4402         /* update file source paths */
4403
4404         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4405                 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4406                 if (fs) {
4407                         string p = fs->path ();
4408                         boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4409                         fs->set_path (p);
4410                         SourceFactory::setup_peakfile(i->second, true);
4411                 }
4412         }
4413
4414         set_snapshot_name (new_name);
4415         _name = new_name;
4416
4417         set_dirty ();
4418
4419         /* save state again to get everything just right */
4420
4421         save_state (_current_snapshot_name);
4422
4423         /* add to recent sessions */
4424
4425         store_recent_sessions (new_name, _path);
4426
4427         return 0;
4428 }
4429
4430 int
4431 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4432 {
4433         bool found_sr = false;
4434         bool found_data_format = false;
4435
4436         if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4437                 return -1;
4438         }
4439
4440         xmlParserCtxtPtr ctxt = xmlNewParserCtxt();
4441         if (ctxt == NULL) {
4442                 return -1;
4443         }
4444         xmlDocPtr doc = xmlCtxtReadFile (ctxt, xmlpath.c_str(), NULL, XML_PARSE_HUGE);
4445
4446         if (doc == NULL) {
4447                 xmlFreeParserCtxt(ctxt);
4448                 return -1;
4449         }
4450
4451         xmlNodePtr node = xmlDocGetRootElement(doc);
4452
4453         if (node == NULL) {
4454                 xmlFreeParserCtxt(ctxt);
4455                 xmlFreeDoc (doc);
4456                 return -1;
4457         }
4458
4459         /* sample rate */
4460
4461         xmlAttrPtr attr;
4462         for (attr = node->properties; attr; attr = attr->next) {
4463                 if (!strcmp ((const char*)attr->name, "sample-rate") && attr->children) {
4464                         sample_rate = atoi ((char*)attr->children->content);
4465                         found_sr = true;
4466                 }
4467         }
4468
4469         node = node->children;
4470         while (node != NULL) {
4471                  if (strcmp((const char*) node->name, "Config")) {
4472                          node = node->next;
4473                          continue;
4474                  }
4475                  for (node = node->children; node; node = node->next) {
4476                          xmlChar* pv = xmlGetProp (node, (const xmlChar*)"name");
4477                          if (pv && !strcmp ((const char*)pv, "native-file-data-format")) {
4478                                  xmlFree (pv);
4479                                  xmlChar* val = xmlGetProp (node, (const xmlChar*)"value");
4480                                  if (val) {
4481                                          SampleFormat fmt = (SampleFormat) string_2_enum (string ((const char*)val), fmt);
4482                                          data_format = fmt;
4483                                          found_data_format = true;
4484                                  }
4485                                  xmlFree (val);
4486                                  break;
4487                          }
4488                          xmlFree (pv);
4489                  }
4490                  break;
4491         }
4492
4493         xmlFreeParserCtxt(ctxt);
4494         xmlFreeDoc (doc);
4495
4496         return !(found_sr && found_data_format); // zero if they are both found
4497 }
4498
4499 std::string
4500 Session::get_snapshot_from_instant (const std::string& session_dir)
4501 {
4502         std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4503
4504         if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4505                 return "";
4506         }
4507
4508         XMLTree tree;
4509         if (!tree.read (instant_xml_path)) {
4510                 return "";
4511         }
4512
4513         XMLProperty const * prop;
4514         XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4515         if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4516                 return prop->value();
4517         }
4518
4519         return "";
4520 }
4521
4522 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4523 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4524
4525 int
4526 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4527 {
4528         uint32_t total = 0;
4529         uint32_t n = 0;
4530         SourcePathMap source_path_map;
4531         string new_path;
4532         boost::shared_ptr<AudioFileSource> afs;
4533         int ret = 0;
4534
4535         {
4536
4537                 Glib::Threads::Mutex::Lock lm (source_lock);
4538
4539                 cerr << " total sources = " << sources.size();
4540
4541                 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4542                         boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4543
4544                         if (!fs) {
4545                                 continue;
4546                         }
4547
4548                         if (fs->within_session()) {
4549                                 continue;
4550                         }
4551
4552                         if (source_path_map.find (fs->path()) != source_path_map.end()) {
4553                                 source_path_map[fs->path()].push_back (fs);
4554                         } else {
4555                                 SeveralFileSources v;
4556                                 v.push_back (fs);
4557                                 source_path_map.insert (make_pair (fs->path(), v));
4558                         }
4559
4560                         total++;
4561                 }
4562
4563                 cerr << " fsources = " << total << endl;
4564
4565                 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4566
4567                         /* tell caller where we are */
4568
4569                         string old_path = i->first;
4570
4571                         callback (n, total, old_path);
4572
4573                         cerr << old_path << endl;
4574
4575                         new_path.clear ();
4576
4577                         switch (i->second.front()->type()) {
4578                         case DataType::AUDIO:
4579                                 new_path = new_audio_source_path_for_embedded (old_path);
4580                                 break;
4581
4582                         case DataType::MIDI:
4583                                 /* XXX not implemented yet */
4584                                 break;
4585                         }
4586
4587                         if (new_path.empty()) {
4588                                 continue;
4589                         }
4590
4591                         cerr << "Move " << old_path << " => " << new_path << endl;
4592
4593                         if (!copy_file (old_path, new_path)) {
4594                                 cerr << "failed !\n";
4595                                 ret = -1;
4596                         }
4597
4598                         /* make sure we stop looking in the external
4599                            dir/folder. Remember, this is an all-or-nothing
4600                            operations, it doesn't merge just some files.
4601                         */
4602                         remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4603
4604                         for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4605                                 (*f)->set_path (new_path);
4606                         }
4607                 }
4608         }
4609
4610         save_state ("", false, false);
4611
4612         return ret;
4613 }
4614
4615 static
4616 bool accept_all_files (string const &, void *)
4617 {
4618         return true;
4619 }
4620
4621 void
4622 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4623 {
4624         /* 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.
4625         */
4626 }
4627
4628 static string
4629 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4630 {
4631         /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4632
4633         string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4634         vector<string> v;
4635         v.push_back (new_session_folder); /* full path */
4636         v.push_back (interchange_dir_name);
4637         v.push_back (new_session_path);   /* just one directory/folder */
4638         v.push_back (typedir);
4639         v.push_back (Glib::path_get_basename (old_path));
4640
4641         return Glib::build_filename (v);
4642 }
4643
4644 int
4645 Session::save_as (SaveAs& saveas)
4646 {
4647         vector<string> files;
4648         string current_folder = Glib::path_get_dirname (_path);
4649         string new_folder = legalize_for_path (saveas.new_name);
4650         string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4651         int64_t total_bytes = 0;
4652         int64_t copied = 0;
4653         int64_t cnt = 0;
4654         int64_t all = 0;
4655         int32_t internal_file_cnt = 0;
4656
4657         vector<string> do_not_copy_extensions;
4658         do_not_copy_extensions.push_back (statefile_suffix);
4659         do_not_copy_extensions.push_back (pending_suffix);
4660         do_not_copy_extensions.push_back (backup_suffix);
4661         do_not_copy_extensions.push_back (temp_suffix);
4662         do_not_copy_extensions.push_back (history_suffix);
4663
4664         /* get total size */
4665
4666         for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4667
4668                 /* need to clear this because
4669                  * find_files_matching_filter() is cumulative
4670                  */
4671
4672                 files.clear ();
4673
4674                 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4675
4676                 all += files.size();
4677
4678                 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4679                         GStatBuf gsb;
4680                         g_stat ((*i).c_str(), &gsb);
4681                         total_bytes += gsb.st_size;
4682                 }
4683         }
4684
4685         /* save old values so we can switch back if we are not switching to the new session */
4686
4687         string old_path = _path;
4688         string old_name = _name;
4689         string old_snapshot = _current_snapshot_name;
4690         string old_sd = _session_dir->root_path();
4691         vector<string> old_search_path[DataType::num_types];
4692         string old_config_search_path[DataType::num_types];
4693
4694         old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4695         old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4696         old_config_search_path[DataType::AUDIO]  = config.get_audio_search_path ();
4697         old_config_search_path[DataType::MIDI]  = config.get_midi_search_path ();
4698
4699         /* switch session directory */
4700
4701         (*_session_dir) = to_dir;
4702
4703         /* create new tree */
4704
4705         if (!_session_dir->create()) {
4706                 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4707                 return -1;
4708         }
4709
4710         try {
4711                 /* copy all relevant files. Find each location in session_dirs,
4712                  * and copy files from there to target.
4713                  */
4714
4715                 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4716
4717                         /* need to clear this because
4718                          * find_files_matching_filter() is cumulative
4719                          */
4720
4721                         files.clear ();
4722
4723                         const size_t prefix_len = (*sd).path.size();
4724
4725                         /* Work just on the files within this session dir */
4726
4727                         find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4728
4729                         /* add dir separator to protect against collisions with
4730                          * track names (e.g. track named "audiofiles" or
4731                          * "analysis".
4732                          */
4733
4734                         static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4735                         static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4736                         static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4737
4738                         /* copy all the files. Handling is different for media files
4739                            than others because of the *silly* subtree we have below the interchange
4740                            folder. That really was a bad idea, but I'm not fixing it as part of
4741                            implementing ::save_as().
4742                         */
4743
4744                         for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4745
4746                                 std::string from = *i;
4747
4748 #ifdef __APPLE__
4749                                 string filename = Glib::path_get_basename (from);
4750                                 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4751                                 if (filename == ".DS_STORE") {
4752                                         continue;
4753                                 }
4754 #endif
4755
4756                                 if (from.find (audiofile_dir_string) != string::npos) {
4757
4758                                         /* audio file: only copy if asked */
4759
4760                                         if (saveas.include_media && saveas.copy_media) {
4761
4762                                                 string to = make_new_media_path (*i, to_dir, new_folder);
4763
4764                                                 info << "media file copying from " << from << " to " << to << endmsg;
4765
4766                                                 if (!copy_file (from, to)) {
4767                                                         throw Glib::FileError (Glib::FileError::IO_ERROR,
4768                                                                                                    string_compose(_("\ncopying \"%1\" failed !"), from));
4769                                                 }
4770                                         }
4771
4772                                         /* we found media files inside the session folder */
4773
4774                                         internal_file_cnt++;
4775
4776                                 } else if (from.find (midifile_dir_string) != string::npos) {
4777
4778                                         /* midi file: always copy unless
4779                                          * creating an empty new session
4780                                          */
4781
4782                                         if (saveas.include_media) {
4783
4784                                                 string to = make_new_media_path (*i, to_dir, new_folder);
4785
4786                                                 info << "media file copying from " << from << " to " << to << endmsg;
4787
4788                                                 if (!copy_file (from, to)) {
4789                                                         throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4790                                                 }
4791                                         }
4792
4793                                         /* we found media files inside the session folder */
4794
4795                                         internal_file_cnt++;
4796
4797                                 } else if (from.find (analysis_dir_string) != string::npos) {
4798
4799                                         /*  make sure analysis dir exists in
4800                                          *  new session folder, but we're not
4801                                          *  copying analysis files here, see
4802                                          *  below
4803                                          */
4804
4805                                         (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4806                                         continue;
4807
4808                                 } else {
4809
4810                                         /* normal non-media file. Don't copy state, history, etc.
4811                                          */
4812
4813                                         bool do_copy = true;
4814
4815                                         for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4816                                                 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4817                                                         /* end of filename matches extension, do not copy file */
4818                                                         do_copy = false;
4819                                                         break;
4820                                                 }
4821                                         }
4822
4823                                         if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4824                                                 /* don't copy peakfiles if
4825                                                  * we're not copying media
4826                                                  */
4827                                                 do_copy = false;
4828                                         }
4829
4830                                         if (do_copy) {
4831                                                 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4832
4833                                                 info << "attempting to make directory/folder " << to << endmsg;
4834
4835                                                 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4836                                                         throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4837                                                 }
4838
4839                                                 info << "attempting to copy " << from << " to " << to << endmsg;
4840
4841                                                 if (!copy_file (from, to)) {
4842                                                         throw Glib::FileError (Glib::FileError::IO_ERROR,
4843                                                                                                    string_compose(_("\ncopying \"%1\" failed !"), from));
4844                                                 }
4845                                         }
4846                                 }
4847
4848                                 /* measure file size even if we're not going to copy so that our Progress
4849                                    signals are correct, since we included these do-not-copy files
4850                                    in the computation of the total size and file count.
4851                                 */
4852
4853                                 GStatBuf gsb;
4854                                 g_stat (from.c_str(), &gsb);
4855                                 copied += gsb.st_size;
4856                                 cnt++;
4857
4858                                 double fraction = (double) copied / total_bytes;
4859
4860                                 bool keep_going = true;
4861
4862                                 if (saveas.copy_media) {
4863
4864                                         /* no need or expectation of this if
4865                                          * media is not being copied, because
4866                                          * it will be fast(ish).
4867                                          */
4868
4869                                         /* tell someone "X percent, file M of N"; M is one-based */
4870
4871                                         boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4872
4873                                         if (res) {
4874                                                 keep_going = *res;
4875                                         }
4876                                 }
4877
4878                                 if (!keep_going) {
4879                                         throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4880                                 }
4881                         }
4882
4883                 }
4884
4885                 /* copy optional folders, if any */
4886
4887                 string old = plugins_dir ();
4888                 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4889                         string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4890                         copy_files (old, newdir);
4891                 }
4892
4893                 old = externals_dir ();
4894                 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4895                         string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4896                         copy_files (old, newdir);
4897                 }
4898
4899                 old = automation_dir ();
4900                 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4901                         string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4902                         copy_files (old, newdir);
4903                 }
4904
4905                 if (saveas.include_media) {
4906
4907                         if (saveas.copy_media) {
4908 #ifndef PLATFORM_WINDOWS
4909                                 /* There are problems with analysis files on
4910                                  * Windows, because they used a colon in their
4911                                  * names as late as 4.0. Colons are not legal
4912                                  * under Windows even if NTFS allows them.
4913                                  *
4914                                  * This is a tricky problem to solve so for
4915                                  * just don't copy these files. They will be
4916                                  * regenerated as-needed anyway, subject to the
4917                                  * existing issue that the filenames will be
4918                                  * rejected by Windows, which is a separate
4919                                  * problem (though related).
4920                                  */
4921
4922                                 /* only needed if we are copying media, since the
4923                                  * analysis data refers to media data
4924                                  */
4925
4926                                 old = analysis_dir ();
4927                                 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4928                                         string newdir = Glib::build_filename (to_dir, "analysis");
4929                                         copy_files (old, newdir);
4930                                 }
4931 #endif /* PLATFORM_WINDOWS */
4932                         }
4933                 }
4934
4935
4936                 _path = to_dir;
4937                 set_snapshot_name (saveas.new_name);
4938                 _name = saveas.new_name;
4939
4940                 if (saveas.include_media && !saveas.copy_media) {
4941
4942                         /* reset search paths of the new session (which we're pretending to be right now) to
4943                            include the original session search path, so we can still find all audio.
4944                         */
4945
4946                         if (internal_file_cnt) {
4947                                 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4948                                         ensure_search_path_includes (*s, DataType::AUDIO);
4949                                         cerr << "be sure to include " << *s << "  for audio" << endl;
4950                                 }
4951
4952                                 /* we do not do this for MIDI because we copy
4953                                    all MIDI files if saveas.include_media is
4954                                    true
4955                                 */
4956                         }
4957                 }
4958
4959                 bool was_dirty = dirty ();
4960
4961                 save_state ("", false, false, !saveas.include_media);
4962                 save_default_options ();
4963
4964                 if (saveas.copy_media && saveas.copy_external) {
4965                         if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4966                                 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4967                         }
4968                 }
4969
4970                 saveas.final_session_folder_name = _path;
4971
4972                 store_recent_sessions (_name, _path);
4973
4974                 if (!saveas.switch_to) {
4975
4976                         /* switch back to the way things were */
4977
4978                         _path = old_path;
4979                         _name = old_name;
4980                         set_snapshot_name (old_snapshot);
4981
4982                         (*_session_dir) = old_sd;
4983
4984                         if (was_dirty) {
4985                                 set_dirty ();
4986                         }
4987
4988                         if (internal_file_cnt) {
4989                                 /* reset these to their original values */
4990                                 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4991                                 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4992                         }
4993
4994                 } else {
4995
4996                         /* prune session dirs, and update disk space statistics
4997                          */
4998
4999                         space_and_path sp;
5000                         sp.path = _path;
5001                         session_dirs.clear ();
5002                         session_dirs.push_back (sp);
5003                         refresh_disk_space ();
5004
5005                         /* ensure that all existing tracks reset their current capture source paths
5006                          */
5007                         reset_write_sources (true, true);
5008
5009                         /* the copying above was based on actually discovering files, not just iterating over the sources list.
5010                            But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
5011                         */
5012
5013                         for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
5014                                 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
5015
5016                                 if (!fs) {
5017                                         continue;
5018                                 }
5019
5020                                 if (fs->within_session()) {
5021                                         string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
5022                                         fs->set_path (newpath);
5023                                 }
5024                         }
5025                 }
5026
5027         } catch (Glib::FileError& e) {
5028
5029                 saveas.failure_message = e.what();
5030
5031                 /* recursively remove all the directories */
5032
5033                 remove_directory (to_dir);
5034
5035                 /* return error */
5036
5037                 return -1;
5038
5039         } catch (...) {
5040
5041                 saveas.failure_message = _("unknown reason");
5042
5043                 /* recursively remove all the directories */
5044
5045                 remove_directory (to_dir);
5046
5047                 /* return error */
5048
5049                 return -1;
5050         }
5051
5052         return 0;
5053 }
5054
5055 static void set_progress (Progress* p, size_t n, size_t t)
5056 {
5057         p->set_progress (float (n) / float(t));
5058 }
5059
5060 int
5061 Session::archive_session (const std::string& dest,
5062                           const std::string& name,
5063                           ArchiveEncode compress_audio,
5064                           bool only_used_sources,
5065                           Progress* progress)
5066 {
5067         if (dest.empty () || name.empty ()) {
5068                 return -1;
5069         }
5070
5071         /* save current values */
5072         bool was_dirty = dirty ();
5073         string old_path = _path;
5074         string old_name = _name;
5075         string old_snapshot = _current_snapshot_name;
5076         string old_sd = _session_dir->root_path();
5077         string old_config_search_path[DataType::num_types];
5078         old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
5079         old_config_search_path[DataType::MIDI]  = config.get_midi_search_path ();
5080
5081         /* ensure that session-path is included in search-path */
5082         bool ok = false;
5083         for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
5084                 if ((*sd).path == old_path) {
5085                         ok = true;
5086                 }
5087         }
5088         if (!ok) {
5089                 return -1;
5090         }
5091
5092         /* create temporary dir to save session to */
5093 #ifdef PLATFORM_WINDOWS
5094         char tmp[256] = "C:\\TEMP\\";
5095         GetTempPath (sizeof (tmp), tmp);
5096 #else
5097         char const* tmp = getenv("TMPDIR");
5098         if (!tmp) {
5099                 tmp = "/tmp/";
5100         }
5101 #endif
5102         if ((strlen (tmp) + 21) > 1024) {
5103                 return -1;
5104         }
5105
5106         char tmptpl[1024];
5107         strcpy (tmptpl, tmp);
5108         strcat (tmptpl, "ardourarchive-XXXXXX");
5109         char*  tmpdir = g_mkdtemp (tmptpl);
5110
5111         if (!tmpdir) {
5112                 return -1;
5113         }
5114
5115         std::string to_dir = std::string (tmpdir);
5116
5117         /* switch session directory temporarily */
5118         (*_session_dir) = to_dir;
5119
5120         if (!_session_dir->create()) {
5121                 (*_session_dir) = old_sd;
5122                 remove_directory (to_dir);
5123                 return -1;
5124         }
5125
5126         /* prepare archive */
5127         string archive = Glib::build_filename (dest, name + ".tar.xz");
5128
5129         PBD::ScopedConnectionList progress_connection;
5130         PBD::FileArchive ar (archive);
5131         if (progress) {
5132                 ar.progress.connect_same_thread (progress_connection, boost::bind (&set_progress, progress, _1, _2));
5133         }
5134
5135         /* collect files to archive */
5136         std::map<string,string> filemap;
5137
5138         vector<string> do_not_copy_extensions;
5139         do_not_copy_extensions.push_back (statefile_suffix);
5140         do_not_copy_extensions.push_back (pending_suffix);
5141         do_not_copy_extensions.push_back (backup_suffix);
5142         do_not_copy_extensions.push_back (temp_suffix);
5143         do_not_copy_extensions.push_back (history_suffix);
5144
5145         vector<string> blacklist_dirs;
5146         blacklist_dirs.push_back (string (peak_dir_name) + G_DIR_SEPARATOR);
5147         blacklist_dirs.push_back (string (analysis_dir_name) + G_DIR_SEPARATOR);
5148         blacklist_dirs.push_back (string (dead_dir_name) + G_DIR_SEPARATOR);
5149         blacklist_dirs.push_back (string (export_dir_name) + G_DIR_SEPARATOR);
5150         blacklist_dirs.push_back (string (externals_dir_name) + G_DIR_SEPARATOR);
5151         blacklist_dirs.push_back (string (plugins_dir_name) + G_DIR_SEPARATOR);
5152
5153         std::map<boost::shared_ptr<AudioFileSource>, std::string> orig_sources;
5154         std::map<boost::shared_ptr<AudioFileSource>, float> orig_gain;
5155
5156         set<boost::shared_ptr<Source> > sources_used_by_this_snapshot;
5157         if (only_used_sources) {
5158                 playlists->sync_all_regions_with_regions ();
5159                 playlists->foreach (boost::bind (merge_all_sources, _1, &sources_used_by_this_snapshot), false);
5160         }
5161
5162         // collect audio sources for this session, calc total size for encoding
5163         // add option to only include *used* sources (see Session::cleanup_sources)
5164         size_t total_size = 0;
5165         {
5166                 Glib::Threads::Mutex::Lock lm (source_lock);
5167                 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
5168                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (i->second);
5169                         if (!afs || afs->readable_length () == 0) {
5170                                 continue;
5171                         }
5172
5173                         if (only_used_sources) {
5174                                 if (!afs->used()) {
5175                                         continue;
5176                                 }
5177                                 if (sources_used_by_this_snapshot.find (afs) == sources_used_by_this_snapshot.end ()) {
5178                                         continue;
5179                                 }
5180                         }
5181
5182                         std::string from = afs->path();
5183
5184                         if (compress_audio != NO_ENCODE) {
5185                                 total_size += afs->readable_length ();
5186                         } else {
5187                                 if (afs->within_session()) {
5188                                         filemap[from] = make_new_media_path (from, name, name);
5189                                 } else {
5190                                         filemap[from] = make_new_media_path (from, name, name);
5191                                         remove_dir_from_search_path (Glib::path_get_dirname (from), DataType::AUDIO);
5192                                 }
5193                         }
5194                 }
5195         }
5196
5197         /* encode audio */
5198         if (compress_audio != NO_ENCODE) {
5199                 if (progress) {
5200                         progress->set_progress (2); // set to "encoding"
5201                         progress->set_progress (0);
5202                 }
5203
5204                 Glib::Threads::Mutex::Lock lm (source_lock);
5205                 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
5206                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (i->second);
5207                         if (!afs || afs->readable_length () == 0) {
5208                                 continue;
5209                         }
5210
5211                         if (only_used_sources) {
5212                                 if (!afs->used()) {
5213                                         continue;
5214                                 }
5215                                 if (sources_used_by_this_snapshot.find (afs) == sources_used_by_this_snapshot.end ()) {
5216                                         continue;
5217                                 }
5218                         }
5219
5220                         orig_sources[afs] = afs->path();
5221                         orig_gain[afs]    = afs->gain();
5222
5223                         std::string new_path = make_new_media_path (afs->path (), to_dir, name);
5224                         new_path = Glib::build_filename (Glib::path_get_dirname (new_path), PBD::basename_nosuffix (new_path) + ".flac");
5225                         g_mkdir_with_parents (Glib::path_get_dirname (new_path).c_str (), 0755);
5226
5227                         if (progress) {
5228                                 progress->descend ((float)afs->readable_length () / total_size);
5229                         }
5230
5231                         try {
5232                                 SndFileSource* ns = new SndFileSource (*this, *(afs.get()), new_path, compress_audio == FLAC_16BIT, progress);
5233                                 afs->replace_file (new_path);
5234                                 afs->set_gain (ns->gain(), true);
5235                                 delete ns;
5236                         } catch (...) {
5237                                 cerr << "failed to encode " << afs->path() << " to " << new_path << "\n";
5238                         }
5239
5240                         if (progress) {
5241                                 progress->ascend ();
5242                         }
5243                 }
5244         }
5245
5246         if (progress) {
5247                 progress->set_progress (-1); // set to "archiving"
5248                 progress->set_progress (0);
5249         }
5250
5251         /* index files relevant for this session */
5252         for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
5253                 vector<string> files;
5254
5255                 size_t prefix_len = (*sd).path.size();
5256                 if (prefix_len > 0 && (*sd).path.at (prefix_len - 1) != G_DIR_SEPARATOR) {
5257                         ++prefix_len;
5258                 }
5259
5260                 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
5261
5262                 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
5263                 static const std::string videofile_dir_string = string (video_dir_name) + G_DIR_SEPARATOR;
5264                 static const std::string midifile_dir_string  = string (midi_dir_name)  + G_DIR_SEPARATOR;
5265
5266                 for (vector<string>::const_iterator i = files.begin (); i != files.end (); ++i) {
5267                         std::string from = *i;
5268
5269 #ifdef __APPLE__
5270                         string filename = Glib::path_get_basename (from);
5271                         std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
5272                         if (filename == ".DS_STORE") {
5273                                 continue;
5274                         }
5275 #endif
5276
5277                         if (from.find (audiofile_dir_string) != string::npos) {
5278                                 ; // handled above
5279                         } else if (from.find (midifile_dir_string) != string::npos) {
5280                                 filemap[from] = make_new_media_path (from, name, name);
5281                         } else if (from.find (videofile_dir_string) != string::npos) {
5282                                 filemap[from] = make_new_media_path (from, name, name);
5283                         } else {
5284                                 bool do_copy = true;
5285                                 for (vector<string>::iterator v = blacklist_dirs.begin(); v != blacklist_dirs.end(); ++v) {
5286                                         if (from.find (*v) != string::npos) {
5287                                                 do_copy = false;
5288                                                 break;
5289                                         }
5290                                 }
5291                                 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
5292                                         if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
5293                                                 do_copy = false;
5294                                                 break;
5295                                         }
5296                                 }
5297
5298                                 if (do_copy) {
5299                                         filemap[from] = name + G_DIR_SEPARATOR + from.substr (prefix_len);
5300                                 }
5301                         }
5302                 }
5303         }
5304
5305         /* write session file */
5306         _path = to_dir;
5307         g_mkdir_with_parents (externals_dir ().c_str (), 0755);
5308 #ifdef LV2_SUPPORT
5309         PBD::Unwinder<bool> uw (LV2Plugin::force_state_save, true);
5310 #endif
5311         save_state (name);
5312         save_default_options ();
5313
5314         size_t prefix_len = _path.size();
5315         if (prefix_len > 0 && _path.at (prefix_len - 1) != G_DIR_SEPARATOR) {
5316                 ++prefix_len;
5317         }
5318
5319         /* collect session-state files */
5320         vector<string> files;
5321         do_not_copy_extensions.clear ();
5322         do_not_copy_extensions.push_back (history_suffix);
5323
5324         blacklist_dirs.clear ();
5325         blacklist_dirs.push_back (string (externals_dir_name) + G_DIR_SEPARATOR);
5326
5327         find_files_matching_filter (files, to_dir, accept_all_files, 0, false, true, true);
5328         for (vector<string>::const_iterator i = files.begin (); i != files.end (); ++i) {
5329                 std::string from = *i;
5330                 bool do_copy = true;
5331                 for (vector<string>::iterator v = blacklist_dirs.begin(); v != blacklist_dirs.end(); ++v) {
5332                         if (from.find (*v) != string::npos) {
5333                                 do_copy = false;
5334                                 break;
5335                         }
5336                 }
5337                 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
5338                         if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
5339                                 do_copy = false;
5340                                 break;
5341                         }
5342                 }
5343                 if (do_copy) {
5344                         filemap[from] = name + G_DIR_SEPARATOR + from.substr (prefix_len);
5345                 }
5346         }
5347
5348         /* restore original values */
5349         _path = old_path;
5350         _name = old_name;
5351         set_snapshot_name (old_snapshot);
5352         (*_session_dir) = old_sd;
5353         if (was_dirty) {
5354                 set_dirty ();
5355         }
5356         config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
5357         config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
5358
5359         for (std::map<boost::shared_ptr<AudioFileSource>, std::string>::iterator i = orig_sources.begin (); i != orig_sources.end (); ++i) {
5360                 i->first->replace_file (i->second);
5361         }
5362         for (std::map<boost::shared_ptr<AudioFileSource>, float>::iterator i = orig_gain.begin (); i != orig_gain.end (); ++i) {
5363                 i->first->set_gain (i->second, true);
5364         }
5365
5366         int rv = ar.create (filemap);
5367         remove_directory (to_dir);
5368
5369         return rv;
5370 }
5371
5372 void
5373 Session::undo (uint32_t n)
5374 {
5375         if (actively_recording()) {
5376                 return;
5377         }
5378
5379         _history.undo (n);
5380 }
5381
5382 void
5383 Session::redo (uint32_t n)
5384 {
5385         if (actively_recording()) {
5386                 return;
5387         }
5388
5389         _history.redo (n);
5390 }