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