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