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