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