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