18c5721f7ab54c5bb61283e18d956efdc3874409
[ardour.git] / libs / ardour / session_state.cc
1 /*
2   Copyright (C) 1999-2002 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   $Id$
19 */
20
21 #include <algorithm>
22 #include <fstream>
23 #include <string>
24 #include <cerrno>
25
26 #include <sigc++/bind.h>
27
28 #include <cstdio> /* snprintf(3) ... grrr */
29 #include <cmath>
30 #include <unistd.h>
31 #include <sys/stat.h>
32 #include <climits>
33 #include <fcntl.h>
34 #include <poll.h>
35 #include <signal.h>
36 #include <sys/mman.h>
37 #include <sys/time.h>
38 #include <dirent.h>
39
40 #ifdef HAVE_SYS_VFS_H
41 #include <sys/vfs.h>
42 #else
43 #include <sys/mount.h>
44 #include <sys/param.h>
45 #endif
46
47 #include <glibmm.h>
48
49 #include <midi++/mmc.h>
50 #include <midi++/port.h>
51 #include <pbd/error.h>
52
53 #include <glibmm/thread.h>
54 #include <pbd/pathscanner.h>
55 #include <pbd/pthread_utils.h>
56 #include <pbd/strsplit.h>
57
58 #include <ardour/audioengine.h>
59 #include <ardour/configuration.h>
60 #include <ardour/session.h>
61 #include <ardour/audio_diskstream.h>
62 #include <ardour/utils.h>
63 #include <ardour/audioplaylist.h>
64 #include <ardour/audiofilesource.h>
65 #include <ardour/destructive_filesource.h>
66 #include <ardour/sndfile_helpers.h>
67 #include <ardour/auditioner.h>
68 #include <ardour/export.h>
69 #include <ardour/redirect.h>
70 #include <ardour/send.h>
71 #include <ardour/insert.h>
72 #include <ardour/connection.h>
73 #include <ardour/slave.h>
74 #include <ardour/tempo.h>
75 #include <ardour/audio_track.h>
76 #include <ardour/cycle_timer.h>
77 #include <ardour/utils.h>
78 #include <ardour/named_selection.h>
79 #include <ardour/version.h>
80 #include <ardour/location.h>
81 #include <ardour/audioregion.h>
82 #include <ardour/crossfade.h>
83 #include <ardour/control_protocol_manager.h>
84 #include <ardour/region_factory.h>
85 #include <ardour/source_factory.h>
86
87 #include "i18n.h"
88 #include <locale.h>
89
90 using namespace std;
91 using namespace ARDOUR;
92 using namespace PBD;
93
94 void
95 Session::first_stage_init (string fullpath, string snapshot_name)
96 {
97         if (fullpath.length() == 0) {
98                 throw failed_constructor();
99         }
100
101         char buf[PATH_MAX+1];
102         if (!realpath(fullpath.c_str(), buf) && (errno != ENOENT)) {
103                 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
104                 throw failed_constructor();
105         }
106         _path = string(buf);
107
108         if (_path[_path.length()-1] != '/') {
109                 _path += '/';
110         }
111
112         /* these two are just provisional settings. set_state()
113            will likely override them.
114         */
115
116         _name = _current_snapshot_name = snapshot_name;
117         setup_raid_path (_path);
118
119         _current_frame_rate = _engine.frame_rate ();
120         _tempo_map = new TempoMap (_current_frame_rate);
121         _tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
122
123         g_atomic_int_set (&processing_prohibited, 0);
124         send_cnt = 0;
125         insert_cnt = 0;
126         _transport_speed = 0;
127         _last_transport_speed = 0;
128         transport_sub_state = 0;
129         _transport_frame = 0;
130         last_stop_frame = 0;
131         end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
132         start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
133         _end_location_is_free = true;
134         g_atomic_int_set (&_record_status, Disabled);
135         auto_play = false;
136         punch_in = false;
137         punch_out = false;
138         auto_loop = false;
139         seamless_loop = false;
140         loop_changing = false;
141         auto_input = true;
142         crossfades_active = false;
143         all_safe = false;
144         auto_return = false;
145         _last_roll_location = 0;
146         _last_record_location = 0;
147         pending_locate_frame = 0;
148         pending_locate_roll = false;
149         pending_locate_flush = false;
150         dstream_buffer_size = 0;
151         state_tree = 0;
152         state_was_pending = false;
153         set_next_event ();
154         outbound_mtc_smpte_frame = 0;
155         next_quarter_frame_to_send = -1;
156         current_block_size = 0;
157         _solo_latched = true;
158         _solo_model = InverseMute;
159         solo_update_disabled = false;
160         currently_soloing = false;
161         _have_captured = false;
162         _worst_output_latency = 0;
163         _worst_input_latency = 0;
164         _worst_track_latency = 0;
165         _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
166         _slave = 0;
167         _slave_type = None;
168         butler_mixdown_buffer = 0;
169         butler_gain_buffer = 0;
170         mmc_control = false;
171         midi_control = true;
172         mmc = 0;
173         post_transport_work = PostTransportWork (0);
174         g_atomic_int_set (&butler_should_do_transport_work, 0);
175         g_atomic_int_set (&butler_active, 0);
176         g_atomic_int_set (&_playback_load, 100);
177         g_atomic_int_set (&_capture_load, 100);
178         g_atomic_int_set (&_playback_load_min, 100);
179         g_atomic_int_set (&_capture_load_min, 100);
180         _edit_mode = Slide;
181         pending_edit_mode = _edit_mode;
182         _play_range = false;
183         input_auto_connect = AutoConnectOption (0);
184         output_auto_connect = AutoConnectOption (0);
185         waiting_to_start = false;
186         _exporting = false;
187         _gain_automation_buffer = 0;
188         _pan_automation_buffer = 0;
189         _npan_buffers = 0;
190         pending_abort = false;
191         layer_model = MoveAddHigher;
192         xfade_model = ShortCrossfade;
193         destructive_index = 0;
194         current_trans = 0;
195
196         AudioDiskstream::allocate_working_buffers();
197         
198         /* default short fade = 15ms */
199
200         Crossfade::set_short_xfade_length ((jack_nframes_t) floor ((15.0 * frame_rate()) / 1000.0));
201         DestructiveFileSource::setup_standard_crossfades (frame_rate());
202
203         last_mmc_step.tv_sec = 0;
204         last_mmc_step.tv_usec = 0;
205         step_speed = 0.0;
206
207         preroll.type = AnyTime::Frames;
208         preroll.frames = 0;
209         postroll.type = AnyTime::Frames;
210         postroll.frames = 0;
211
212         /* click sounds are unset by default, which causes us to internal
213            waveforms for clicks.
214         */
215         
216         _clicking = false;
217         click_requested = false;
218         click_data = 0;
219         click_emphasis_data = 0;
220         click_length = 0;
221         click_emphasis_length = 0;
222
223         process_function = &Session::process_with_events;
224
225         if (Config->get_use_video_sync()) {
226                 waiting_for_sync_offset = true;
227         } else {
228                 waiting_for_sync_offset = false;
229         }
230
231         _current_frame_rate = 48000;
232         _base_frame_rate = 48000;
233
234         smpte_frames_per_second = 30;
235         video_pullup = 0.0;
236         smpte_drop_frames = false;
237         last_smpte_when = 0;
238         _smpte_offset = 0;
239         _smpte_offset_negative = true;
240         last_smpte_valid = false;
241
242         last_rr_session_dir = session_dirs.begin();
243         refresh_disk_space ();
244
245         // set_default_fade (0.2, 5.0); /* steepness, millisecs */
246
247         /* default configuration */
248
249         do_not_record_plugins = false;
250         over_length_short = 2;
251         over_length_long = 10;
252         send_midi_timecode = false;
253         send_midi_machine_control = false;
254         shuttle_speed_factor = 1.0;
255         shuttle_speed_threshold = 5;
256         rf_speed = 2.0;
257         _meter_hold = 100; // XXX unknown units: number of calls to meter::set()
258         _meter_falloff = 0.375f; // XXX unknown units: refresh_rate
259         max_level = 0;
260         min_level = 0;
261
262         /* slave stuff */
263
264         average_slave_delta = 1800;
265         have_first_delta_accumulator = false;
266         delta_accumulator_cnt = 0;
267         slave_state = Stopped;
268
269         /* default SMPTE type is 30 FPS, non-drop */
270
271         set_smpte_type (30.0, false);
272         set_video_pullup (0.0);
273
274         _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
275
276         /* These are all static "per-class" signals */
277
278         RegionFactory::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
279         SourceFactory::SourceCreated.connect (mem_fun (*this, &Session::add_source));
280         Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
281         Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
282         NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
283         Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve));
284         AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
285
286         Controllable::Created.connect (mem_fun (*this, &Session::add_controllable));
287         Controllable::GoingAway.connect (mem_fun (*this, &Session::remove_controllable));
288
289         IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers));
290
291         /* stop IO objects from doing stuff until we're ready for them */
292
293         IO::disable_panners ();
294         IO::disable_ports ();
295         IO::disable_connecting ();
296 }
297
298 int
299 Session::second_stage_init (bool new_session)
300 {
301         AudioFileSource::set_peak_dir (peak_dir());
302
303         if (!new_session) {
304                 if (load_state (_current_snapshot_name)) {
305                         cerr << "load state failed\n";
306                         return -1;
307                 }
308                 remove_empty_sounds ();
309         }
310
311         if (start_butler_thread()) {
312                 return -1;
313         }
314
315         if (start_midi_thread ()) {
316                 return -1;
317         }
318
319         if (state_tree) {
320                 if (set_state (*state_tree->root())) {
321                         return -1;
322                 }
323         }
324
325         /* we can't save till after ::when_engine_running() is called,
326            because otherwise we save state with no connections made.
327            therefore, we reset _state_of_the_state because ::set_state()
328            will have cleared it.
329
330            we also have to include Loading so that any events that get
331            generated between here and the end of ::when_engine_running()
332            will be processed directly rather than queued.
333         */
334
335         _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
336
337         // set_auto_input (true);
338         _locations.changed.connect (mem_fun (this, &Session::locations_changed));
339         _locations.added.connect (mem_fun (this, &Session::locations_added));
340         setup_click_sounds (0);
341         setup_midi_control ();
342
343         /* Pay attention ... */
344
345         _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
346         _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
347
348         if (_engine.running()) {
349                 when_engine_running();
350         } else {
351                 first_time_running = _engine.Running.connect (mem_fun (*this, &Session::when_engine_running));
352         }
353
354         send_full_time_code ();
355         _engine.transport_locate (0);
356         deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
357         deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
358
359         ControlProtocolManager::instance().set_session (*this);
360
361         if (new_session) {
362                 _end_location_is_free = true;
363         } else {
364                 _end_location_is_free = false;
365         }
366         
367         return 0;
368 }
369
370 string
371 Session::raid_path () const
372 {
373         string path;
374
375         for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
376                 path += (*i).path;
377                 path += ':';
378         }
379         
380         return path.substr (0, path.length() - 1); // drop final colon
381 }
382
383 void
384 Session::set_raid_path (string path)
385 {
386         /* public-access to setup_raid_path() */
387
388         setup_raid_path (path);
389 }
390
391 void
392 Session::setup_raid_path (string path)
393 {
394         string::size_type colon;
395         string remaining;
396         space_and_path sp;
397         string fspath;
398         string::size_type len = path.length();
399         int colons;
400
401         colons = 0;
402
403         if (path.length() == 0) {
404                 return;
405         }
406
407         session_dirs.clear ();
408
409         for (string::size_type n = 0; n < len; ++n) {
410                 if (path[n] == ':') {
411                         colons++;
412                 }
413         }
414
415         if (colons == 0) {
416
417                 /* no multiple search path, just one location (common case) */
418
419                 sp.path = path;
420                 sp.blocks = 0;
421                 session_dirs.push_back (sp);
422
423                 string fspath;
424
425                 /* sounds dir */
426
427                 fspath += sp.path;
428                 if (fspath[fspath.length()-1] != '/') {
429                         fspath += '/';
430                 }
431                 fspath += sound_dir (false);
432                 
433                 AudioFileSource::set_search_path (fspath);
434
435                 return;
436         }
437
438         remaining = path;
439
440         while ((colon = remaining.find_first_of (':')) != string::npos) {
441                 
442                 sp.blocks = 0;
443                 sp.path = remaining.substr (0, colon);
444                 session_dirs.push_back (sp);
445
446                 /* add sounds to file search path */
447
448                 fspath += sp.path;
449                 if (fspath[fspath.length()-1] != '/') {
450                         fspath += '/';
451                 }
452                 fspath += sound_dir (false);
453                 fspath += ':';
454
455                 remaining = remaining.substr (colon+1);
456         }
457
458         if (remaining.length()) {
459
460                 sp.blocks = 0;
461                 sp.path = remaining;
462
463                 fspath += ':';
464                 fspath += sp.path;
465                 if (fspath[fspath.length()-1] != '/') {
466                         fspath += '/';
467                 }
468                 fspath += sound_dir (false);
469                 fspath += ':';
470
471                 session_dirs.push_back (sp);
472         }
473
474         /* set the AudioFileSource search path */
475
476         AudioFileSource::set_search_path (fspath);
477
478         /* reset the round-robin soundfile path thingie */
479
480         last_rr_session_dir = session_dirs.begin();
481 }
482
483 int
484 Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
485 {
486         string dir;
487
488         new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
489         
490         if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
491                 error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
492                 return -1;
493         }
494
495         dir = peak_dir ();
496
497         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
498                 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
499                 return -1;
500         }
501
502         dir = sound_dir ();
503
504         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
505                 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
506                 return -1;
507         }
508
509         dir = dead_sound_dir ();
510
511         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
512                 error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
513                 return -1;
514         }
515
516         dir = automation_dir ();
517
518         if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
519                 error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
520                 return -1;
521         }
522
523         
524         /* check new_session so we don't overwrite an existing one */
525         
526         if (mix_template) {
527                 if (new_session){
528                         std::string in_path = *mix_template;
529
530                         ifstream in(in_path.c_str());
531                         
532                         if (in){
533                                 string out_path = _path;
534                                 out_path += _name;
535                                 out_path += _statefile_suffix;
536                                 
537                                 ofstream out(out_path.c_str());
538
539                                 if (out){
540                                         out << in.rdbuf();
541                                         
542                                         // okay, session is set up.  Treat like normal saved
543                                         // session from now on.
544                                         
545                                         new_session = false;
546                                         return 0;
547                                         
548                                 } else {
549                                         error << string_compose (_("Could not open %1 for writing mix template"), out_path) 
550                                               << endmsg;
551                                         return -1;
552                                 }
553                                 
554                         } else {
555                                 error << string_compose (_("Could not open mix template %1 for reading"), in_path) 
556                                       << endmsg;
557                                 return -1;
558                         }
559                         
560                         
561                 } else {
562                         warning << _("Session already exists.  Not overwriting") << endmsg;
563                         return -1;
564                 }
565         }
566
567         if (new_session) {
568
569                 /* set initial start + end point */
570
571                 start_location->set_end (0);
572                 _locations.add (start_location);
573
574                 end_location->set_end (initial_length);
575                 _locations.add (end_location);
576                 
577                 _state_of_the_state = Clean;
578
579                 if (save_state (_current_snapshot_name)) {
580                         save_history (_current_snapshot_name);
581                         return -1;
582                 }
583         }
584
585         return 0;
586 }
587
588 int
589 Session::load_diskstreams (const XMLNode& node)
590 {
591         XMLNodeList          clist;
592         XMLNodeConstIterator citer;
593         
594         clist = node.children();
595
596         for (citer = clist.begin(); citer != clist.end(); ++citer) {
597                 
598
599                 try {
600                         boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
601                         add_diskstream (dstream);
602                 } 
603                 
604                 catch (failed_constructor& err) {
605                         error << _("Session: could not load diskstream via XML state")                        << endmsg;
606                         return -1;
607                 }
608         }
609
610         return 0;
611 }
612
613 void
614 Session::remove_pending_capture_state ()
615 {
616         string xml_path;
617
618         xml_path = _path;
619         xml_path += _current_snapshot_name;
620         xml_path += _pending_suffix;
621
622         unlink (xml_path.c_str());
623 }
624
625 int
626 Session::save_state (string snapshot_name, bool pending)
627 {
628         XMLTree tree;
629         string xml_path;
630         string bak_path;
631
632         if (_state_of_the_state & CannotSave) {
633                 return 1;
634         }
635
636         tree.set_root (&get_state());
637
638         if (snapshot_name.empty()) {
639                 snapshot_name = _current_snapshot_name;
640         }
641
642         if (!pending) {
643
644                 xml_path = _path;
645                 xml_path += snapshot_name;
646                 xml_path += _statefile_suffix;
647                 bak_path = xml_path;
648                 bak_path += ".bak";
649                 
650                 // Make backup of state file
651                 
652                 if ((access (xml_path.c_str(), F_OK) == 0) &&
653                     (rename(xml_path.c_str(), bak_path.c_str()))) {
654                         error << _("could not backup old state file, current state not saved.") << endmsg;
655                         return -1;
656                 }
657
658         } else {
659
660                 xml_path = _path;
661                 xml_path += snapshot_name;
662                 xml_path += _pending_suffix;
663
664         }
665
666         cerr << "actually writing state\n";
667
668         if (!tree.write (xml_path)) {
669                 error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
670
671                 /* don't leave a corrupt file lying around if it is
672                    possible to fix.
673                 */
674
675                 if (unlink (xml_path.c_str())) {
676                         error << string_compose (_("could not remove corrupt state file %1"), xml_path) << endmsg;
677                 } else {
678                         if (!pending) {
679                                 if (rename (bak_path.c_str(), xml_path.c_str())) {
680                                         error << string_compose (_("could not restore state file from backup %1"), bak_path) << endmsg;
681                                 }
682                         }
683                 }
684
685                 return -1;
686         }
687
688         if (!pending) {
689                 save_history(snapshot_name);
690
691                 bool was_dirty = dirty();
692
693                 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
694                 
695                 if (was_dirty) {
696                         DirtyChanged (); /* EMIT SIGNAL */
697                 }
698                 
699                 StateSaved (snapshot_name); /* EMIT SIGNAL */
700         }
701
702         return 0;
703 }
704
705 int
706 Session::restore_state (string snapshot_name)
707 {
708         if (load_state (snapshot_name) == 0) {
709                 set_state (*state_tree->root());
710         }
711         
712         return 0;
713 }
714
715 int
716 Session::load_state (string snapshot_name)
717 {
718         if (state_tree) {
719                 delete state_tree;
720                 state_tree = 0;
721         }
722
723         string xmlpath;
724         
725         state_was_pending = false;
726
727         /* check for leftover pending state from a crashed capture attempt */
728
729         xmlpath = _path;
730         xmlpath += snapshot_name;
731         xmlpath += _pending_suffix;
732
733         if (!access (xmlpath.c_str(), F_OK)) {
734
735                 /* there is pending state from a crashed capture attempt */
736
737                 if (AskAboutPendingState()) {
738                         state_was_pending = true;
739                 } 
740         } 
741
742         if (!state_was_pending) {
743
744                 xmlpath = _path;
745                 xmlpath += snapshot_name;
746                 xmlpath += _statefile_suffix;
747         }
748
749         if (access (xmlpath.c_str(), F_OK)) {
750                 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
751                 return 1;
752         }
753
754         state_tree = new XMLTree;
755
756         set_dirty();
757
758         if (state_tree->read (xmlpath)) {
759                 return 0;
760         } else {
761                 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
762         }
763
764         delete state_tree;
765         state_tree = 0;
766         return -1;
767 }
768
769 int
770 Session::load_options (const XMLNode& node)
771 {
772         XMLNode* child;
773         XMLProperty* prop;
774         bool have_fade_msecs = false;
775         bool have_fade_steepness = false;
776         float fade_msecs = 0;
777         float fade_steepness = 0;
778         SlaveSource slave_src = None;
779         int x;
780         LocaleGuard lg (X_("POSIX"));
781         
782         if ((child = find_named_node (node, "input-auto-connect")) != 0) {
783                 if ((prop = child->property ("val")) != 0) {
784                         sscanf (prop->value().c_str(), "%x", &x);
785                         input_auto_connect = AutoConnectOption (x);
786                 }
787         }
788
789         if ((child = find_named_node (node, "output-auto-connect")) != 0) {
790                 if ((prop = child->property ("val")) != 0) {
791                         sscanf (prop->value().c_str(), "%x", &x);
792                         output_auto_connect = AutoConnectOption (x);
793                 }
794         }
795                                 
796         if ((child = find_named_node (node, "slave")) != 0) {
797                 if ((prop = child->property ("type")) != 0) {
798                         if (prop->value() == "none") {
799                                 slave_src = None;
800                         } else if (prop->value() == "mtc") {
801                                 slave_src = MTC;
802                         } else if (prop->value() == "jack") {
803                                 slave_src = JACK;
804                         }
805                         set_slave_source (slave_src, 0);
806                 }
807         }
808
809         /* we cannot set edit mode if we are loading a session,
810            because it might destroy the playlist's positioning
811         */
812
813         if ((child = find_named_node (node, "edit-mode")) != 0) {
814                 if ((prop = child->property ("val")) != 0) {
815                         if (prop->value() == "slide") {
816                                 pending_edit_mode = Slide;
817                         } else if (prop->value() == "splice") {
818                                 pending_edit_mode = Splice;
819                         } 
820                 }
821         }
822                                 
823         if ((child = find_named_node (node, "send-midi-timecode")) != 0) {
824                 if ((prop = child->property ("val")) != 0) {
825                         bool x = (prop->value() == "yes");
826                         send_mtc = !x; /* force change in value */
827                         set_send_mtc (x);
828                 }
829         }
830         if ((child = find_named_node (node, "send-midi-machine-control")) != 0) {
831                 if ((prop = child->property ("val")) != 0) {
832                         bool x = (prop->value() == "yes");
833                         send_mmc = !x; /* force change in value */
834                         set_send_mmc (prop->value() == "yes");
835                 }
836         }
837         if ((child = find_named_node (node, "max-level")) != 0) {
838                 if ((prop = child->property ("val")) != 0) {
839                         max_level = atoi (prop->value().c_str());
840                 }
841         }
842         if ((child = find_named_node (node, "min-level")) != 0) {
843                 if ((prop = child->property ("val")) != 0) {
844                         min_level = atoi (prop->value().c_str());
845                 }
846         }
847         if ((child = find_named_node (node, "meter-hold")) != 0) {
848                 if ((prop = child->property ("val")) != 0) {
849                         _meter_hold = atof (prop->value().c_str());
850                 }
851         }
852         if ((child = find_named_node (node, "meter-falloff")) != 0) {
853                 if ((prop = child->property ("val")) != 0) {
854                         _meter_falloff = atof (prop->value().c_str());
855                 }
856         }
857         if ((child = find_named_node (node, "long-over-length")) != 0) {
858                 if ((prop = child->property ("val")) != 0) {
859                         over_length_long = atoi (prop->value().c_str());
860                 }
861         }
862         if ((child = find_named_node (node, "short-over-length")) != 0) {
863                 if ((prop = child->property ("val")) != 0) {
864                         over_length_short = atoi (prop->value().c_str());
865                 }
866         }
867         if ((child = find_named_node (node, "shuttle-speed-factor")) != 0) {
868                 if ((prop = child->property ("val")) != 0) {
869                         shuttle_speed_factor = atof (prop->value().c_str());
870                 }
871         }
872         if ((child = find_named_node (node, "shuttle-speed-threshold")) != 0) {
873                 if ((prop = child->property ("val")) != 0) {
874                         shuttle_speed_threshold = atof (prop->value().c_str());
875                 }
876         }
877         if ((child = find_named_node (node, "rf-speed")) != 0) {
878                 if ((prop = child->property ("val")) != 0) {
879                         rf_speed = atof (prop->value().c_str());
880                 }
881         }
882         if ((child = find_named_node (node, "video-pullup")) != 0) {
883                 if ((prop = child->property ("val")) != 0) {
884                         set_video_pullup( atof (prop->value().c_str()) );
885                 }
886         }
887         if ((child = find_named_node (node, "smpte-frames-per-second")) != 0) {
888                 if ((prop = child->property ("val")) != 0) {
889                         set_smpte_type( atof (prop->value().c_str()), smpte_drop_frames );
890                 }
891         }
892         if ((child = find_named_node (node, "smpte-drop-frames")) != 0) {
893                 if ((prop = child->property ("val")) != 0) {
894                         set_smpte_type( smpte_frames_per_second, (prop->value() == "yes") );
895                 }
896         }
897         if ((child = find_named_node (node, "smpte-offset")) != 0) {
898                 if ((prop = child->property ("val")) != 0) {
899                         set_smpte_offset( atoi (prop->value().c_str()) );
900                 }
901         }
902         if ((child = find_named_node (node, "smpte-offset-negative")) != 0) {
903                 if ((prop = child->property ("val")) != 0) {
904                         set_smpte_offset_negative( (prop->value() == "yes") );
905                 }
906         }
907         if ((child = find_named_node (node, "click-sound")) != 0) {
908                 if ((prop = child->property ("val")) != 0) {
909                         click_sound = prop->value();
910                 }
911         }
912         if ((child = find_named_node (node, "click-emphasis-sound")) != 0) {
913                 if ((prop = child->property ("val")) != 0) {
914                         click_emphasis_sound = prop->value();
915                 }
916         }
917
918         if ((child = find_named_node (node, "solo-model")) != 0) {
919                 if ((prop = child->property ("val")) != 0) {
920                         if (prop->value() == "SoloBus")
921                                 _solo_model = SoloBus;
922                         else
923                                 _solo_model = InverseMute;
924                 }
925         }
926
927         /* BOOLEAN OPTIONS */
928
929         if ((child = find_named_node (node, "auto-play")) != 0) {
930                 if ((prop = child->property ("val")) != 0) {
931                         set_auto_play (prop->value() == "yes");
932                 }
933         }
934         if ((child = find_named_node (node, "auto-input")) != 0) {
935                 if ((prop = child->property ("val")) != 0) {
936                         set_auto_input (prop->value() == "yes");
937                 }
938         }
939         if ((child = find_named_node (node, "seamless-loop")) != 0) {
940                 if ((prop = child->property ("val")) != 0) {
941                         set_seamless_loop (prop->value() == "yes");
942                 }
943         }
944         if ((child = find_named_node (node, "punch-in")) != 0) {
945                 if ((prop = child->property ("val")) != 0) {
946                         set_punch_in (prop->value() == "yes");
947                 }
948         }
949         if ((child = find_named_node (node, "punch-out")) != 0) {
950                 if ((prop = child->property ("val")) != 0) {
951                         set_punch_out (prop->value() == "yes");
952                 }
953         }
954         if ((child = find_named_node (node, "auto-return")) != 0) {
955                 if ((prop = child->property ("val")) != 0) {
956                         set_auto_return (prop->value() == "yes");
957                 }
958         }
959         if ((child = find_named_node (node, "send-mtc")) != 0) {
960                 if ((prop = child->property ("val")) != 0) {
961                         set_send_mtc (prop->value() == "yes");
962                 }
963         }
964         if ((child = find_named_node (node, "mmc-control")) != 0) {
965                 if ((prop = child->property ("val")) != 0) {
966                         set_mmc_control (prop->value() == "yes");
967                 }
968         }
969         if ((child = find_named_node (node, "midi-control")) != 0) {
970                 if ((prop = child->property ("val")) != 0) {
971                         set_midi_control (prop->value() == "yes");
972                 }
973         }
974         if ((child = find_named_node (node, "midi-feedback")) != 0) {
975                 if ((prop = child->property ("val")) != 0) {
976                         set_midi_feedback (prop->value() == "yes");
977                 }
978         }
979         // Legacy support for <recording-plugins>
980         if ((child = find_named_node (node, "recording-plugins")) != 0) {
981                 if ((prop = child->property ("val")) != 0) {
982                         set_do_not_record_plugins (prop->value() == "no");
983                 }
984         }
985         if ((child = find_named_node (node, "do-not-record-plugins")) != 0) {
986                 if ((prop = child->property ("val")) != 0) {
987                         set_do_not_record_plugins (prop->value() == "yes");
988                 }
989         }
990         if ((child = find_named_node (node, "crossfades-active")) != 0) {
991                 if ((prop = child->property ("val")) != 0) {
992                         set_crossfades_active (prop->value() == "yes");
993                 }
994         }
995         if ((child = find_named_node (node, "audible-click")) != 0) {
996                 if ((prop = child->property ("val")) != 0) {
997                         set_clicking (prop->value() == "yes");
998                 }
999         }
1000
1001         if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
1002                 if ((prop = child->property ("val")) != 0) {
1003                         _end_location_is_free = (prop->value() == "yes");
1004                 }
1005         }
1006
1007         if ((child = find_named_node (node, "layer-model")) != 0) {
1008                 if ((prop = child->property ("val")) != 0) {
1009                         if (prop->value() == X_("LaterHigher")) {
1010                                 set_layer_model (LaterHigher);
1011                         } else if (prop->value() == X_("AddHigher")) {
1012                                 set_layer_model (AddHigher);
1013                         } else {
1014                                 set_layer_model (MoveAddHigher);
1015                         }
1016                 }
1017         }
1018
1019         if ((child = find_named_node (node, "xfade-model")) != 0) {
1020                 if ((prop = child->property ("val")) != 0) {
1021                         if (prop->value() == X_("Short")) {
1022                                 set_xfade_model (ShortCrossfade);
1023                         } else {
1024                                 set_xfade_model (FullCrossfade);
1025                         }
1026                 }
1027         }
1028
1029         if ((child = find_named_node (node, "short-xfade-length")) != 0) {
1030                 if ((prop = child->property ("val")) != 0) {
1031                         /* value is stored as a fractional seconds */
1032                         float secs = atof (prop->value().c_str());
1033                         Crossfade::set_short_xfade_length ((jack_nframes_t) floor (secs * frame_rate()));
1034                 } 
1035         }
1036
1037         if ((child = find_named_node (node, "full-xfades-unmuted")) != 0) {
1038                 if ((prop = child->property ("val")) != 0) {
1039                         crossfades_active = (prop->value() == "yes");
1040                 }
1041         } 
1042
1043         /* TIED OPTIONS */
1044
1045         if ((child = find_named_node (node, "default-fade-steepness")) != 0) {
1046                 if ((prop = child->property ("val")) != 0) {
1047                         fade_steepness = atof (prop->value().c_str());
1048                         have_fade_steepness = true;
1049                 }
1050         }
1051         if ((child = find_named_node (node, "default-fade-msec")) != 0) {
1052                 if ((prop = child->property ("val")) != 0) {
1053                         fade_msecs = atof (prop->value().c_str());
1054                         have_fade_msecs = true;
1055                 }
1056         }
1057
1058         if (have_fade_steepness || have_fade_msecs) {
1059                 // set_default_fade (fade_steepness, fade_msecs);
1060         }
1061
1062         return 0;
1063 }
1064
1065 XMLNode&
1066 Session::get_options () const
1067 {
1068         XMLNode* opthead;
1069         XMLNode* child;
1070         char buf[32];
1071         LocaleGuard lg (X_("POSIX"));
1072
1073         opthead = new XMLNode ("Options");
1074
1075         SlaveSource src = slave_source ();
1076         string src_string;
1077         switch (src) {
1078         case None:
1079                 src_string = "none";
1080                 break;
1081         case MTC:
1082                 src_string = "mtc";
1083                 break;
1084         case JACK:
1085                 src_string = "jack";
1086                 break;
1087         }
1088         child = opthead->add_child ("slave");
1089         child->add_property ("type", src_string);
1090         
1091         child = opthead->add_child ("send-midi-timecode");
1092         child->add_property ("val", send_midi_timecode?"yes":"no");
1093
1094         child = opthead->add_child ("send-midi-machine-control");
1095         child->add_property ("val", send_midi_machine_control?"yes":"no");
1096
1097         snprintf (buf, sizeof(buf)-1, "%x", (int) input_auto_connect);
1098         child = opthead->add_child ("input-auto-connect");
1099         child->add_property ("val", buf);
1100
1101         snprintf (buf, sizeof(buf)-1, "%x", (int) output_auto_connect);
1102         child = opthead->add_child ("output-auto-connect");
1103         child->add_property ("val", buf);
1104
1105         snprintf (buf, sizeof(buf)-1, "%d", max_level);
1106         child = opthead->add_child ("max-level");
1107         child->add_property ("val", buf);
1108
1109         snprintf (buf, sizeof(buf)-1, "%d", min_level);
1110         child = opthead->add_child ("min-level");
1111         child->add_property ("val", buf);
1112
1113         snprintf (buf, sizeof(buf)-1, "%f", _meter_hold);
1114         child = opthead->add_child ("meter-hold");
1115         child->add_property ("val", buf);
1116
1117         snprintf (buf, sizeof(buf)-1, "%f", _meter_falloff);
1118         child = opthead->add_child ("meter-falloff");
1119         child->add_property ("val", buf);
1120         
1121         snprintf (buf, sizeof(buf)-1, "%u", over_length_long);
1122         child = opthead->add_child ("long-over-length");
1123         child->add_property ("val", buf);
1124
1125         snprintf (buf, sizeof(buf)-1, "%u", over_length_short);
1126         child = opthead->add_child ("short-over-length");
1127         child->add_property ("val", buf);
1128
1129         snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_factor);
1130         child = opthead->add_child ("shuttle-speed-factor");
1131         child->add_property ("val", buf);
1132
1133         snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_threshold);
1134         child = opthead->add_child ("shuttle-speed-threshold");
1135         child->add_property ("val", buf);
1136
1137         snprintf (buf, sizeof(buf)-1, "%f", rf_speed);
1138         child = opthead->add_child ("rf-speed");
1139         child->add_property ("val", buf);
1140
1141         snprintf (buf, sizeof(buf)-1, "%.4f", video_pullup);
1142         child = opthead->add_child ("video-pullup");
1143         child->add_property ("val", buf);
1144         
1145         snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second);
1146         child = opthead->add_child ("smpte-frames-per-second");
1147         child->add_property ("val", buf);
1148         
1149         child = opthead->add_child ("smpte-drop-frames");
1150         child->add_property ("val", smpte_drop_frames ? "yes" : "no");
1151         
1152         snprintf (buf, sizeof(buf)-1, "%u", smpte_offset ());
1153         child = opthead->add_child ("smpte-offset");
1154         child->add_property ("val", buf);
1155         
1156         child = opthead->add_child ("smpte-offset-negative");
1157         child->add_property ("val", smpte_offset_negative () ? "yes" : "no");
1158         
1159         child = opthead->add_child ("edit-mode");
1160         switch (_edit_mode) {
1161         case Splice:
1162                 child->add_property ("val", "splice");
1163                 break;
1164
1165         case Slide:
1166                 child->add_property ("val", "slide");
1167                 break;
1168         }
1169
1170         child = opthead->add_child ("auto-play");
1171         child->add_property ("val", get_auto_play () ? "yes" : "no");
1172         child = opthead->add_child ("auto-input");
1173         child->add_property ("val", get_auto_input () ? "yes" : "no");
1174         child = opthead->add_child ("seamless-loop");
1175         child->add_property ("val", get_seamless_loop () ? "yes" : "no");
1176         child = opthead->add_child ("punch-in");
1177         child->add_property ("val", get_punch_in () ? "yes" : "no");
1178         child = opthead->add_child ("punch-out");
1179         child->add_property ("val", get_punch_out () ? "yes" : "no");
1180         child = opthead->add_child ("all-safe");
1181         child->add_property ("val", get_all_safe () ? "yes" : "no");
1182         child = opthead->add_child ("auto-return");
1183         child->add_property ("val", get_auto_return () ? "yes" : "no");
1184         child = opthead->add_child ("mmc-control");
1185         child->add_property ("val", get_mmc_control () ? "yes" : "no");
1186         child = opthead->add_child ("midi-control");
1187         child->add_property ("val", get_midi_control () ? "yes" : "no");
1188         child = opthead->add_child ("midi-feedback");
1189         child->add_property ("val", get_midi_feedback () ? "yes" : "no");
1190         child = opthead->add_child ("do-not-record-plugins");
1191         child->add_property ("val", get_do_not_record_plugins () ? "yes" : "no");
1192         child = opthead->add_child ("auto-crossfade");
1193         child->add_property ("val", get_crossfades_active () ? "yes" : "no");
1194         child = opthead->add_child ("audible-click");
1195         child->add_property ("val", get_clicking () ? "yes" : "no");
1196         child = opthead->add_child ("end-marker-is-free");
1197         child->add_property ("val", _end_location_is_free ? "yes" : "no");
1198
1199         if (click_sound.length()) {
1200                 child = opthead->add_child ("click-sound");
1201                 child->add_property ("val", click_sound);
1202         }
1203
1204         if (click_emphasis_sound.length()) {
1205                 child = opthead->add_child ("click-emphasis-sound");
1206                 child->add_property ("val", click_emphasis_sound);
1207         }
1208
1209         child = opthead->add_child ("solo-model");
1210         child->add_property ("val", _solo_model == SoloBus ? "SoloBus" : "InverseMute");
1211
1212         child = opthead->add_child ("layer-model");
1213         switch (layer_model) {
1214         case LaterHigher:
1215                 child->add_property ("val", X_("LaterHigher"));
1216                 break;
1217         case MoveAddHigher:
1218                 child->add_property ("val", X_("MoveAddHigher"));
1219                 break;
1220         case AddHigher:
1221                 child->add_property ("val", X_("AddHigher"));
1222                 break;
1223         }
1224
1225         child = opthead->add_child ("xfade-model");
1226         switch (xfade_model) {
1227         case FullCrossfade:
1228                 child->add_property ("val", X_("Full"));
1229                 break;
1230         case ShortCrossfade:
1231                 child->add_property ("val", X_("Short"));
1232         }
1233
1234         child = opthead->add_child ("short-xfade-length");
1235         /* store as fractions of a second */
1236         snprintf (buf, sizeof(buf)-1, "%f", 
1237                   (float) Crossfade::short_xfade_length() / frame_rate());
1238         child->add_property ("val", buf);
1239
1240         child = opthead->add_child ("full-xfades-unmuted");
1241         child->add_property ("val", crossfades_active ? "yes" : "no");
1242
1243         return *opthead;
1244 }
1245
1246 XMLNode&
1247 Session::get_state()
1248 {
1249         return state(true);
1250 }
1251
1252 XMLNode&
1253 Session::get_template()
1254 {
1255         /* if we don't disable rec-enable, diskstreams
1256            will believe they need to store their capture
1257            sources in their state node. 
1258         */
1259         
1260         disable_record (false);
1261
1262         return state(false);
1263 }
1264
1265 XMLNode&
1266 Session::state(bool full_state)
1267 {
1268         XMLNode* node = new XMLNode("Session");
1269         XMLNode* child;
1270
1271         // store libardour version, just in case
1272         char buf[16];
1273         snprintf(buf, sizeof(buf)-1, "%d.%d.%d", 
1274                  libardour_major_version, libardour_minor_version, libardour_micro_version);
1275         node->add_property("version", string(buf));
1276                 
1277         /* store configuration settings */
1278
1279         if (full_state) {
1280         
1281                 /* store the name */
1282                 node->add_property ("name", _name);
1283
1284                 if (session_dirs.size() > 1) {
1285
1286                         string p;
1287
1288                         vector<space_and_path>::iterator i = session_dirs.begin();
1289                         vector<space_and_path>::iterator next;
1290
1291                         ++i; /* skip the first one */
1292                         next = i;
1293                         ++next;
1294
1295                         while (i != session_dirs.end()) {
1296
1297                                 p += (*i).path;
1298
1299                                 if (next != session_dirs.end()) {
1300                                         p += ':';
1301                                 } else {
1302                                         break;
1303                                 }
1304
1305                                 ++next;
1306                                 ++i;
1307                         }
1308                         
1309                         child = node->add_child ("Path");
1310                         child->add_content (p);
1311                 }
1312         }
1313
1314         /* save the ID counter */
1315         
1316         snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1317         node->add_property ("id-counter", buf);
1318
1319         /* various options */
1320
1321         node->add_child_nocopy (get_options());
1322
1323         child = node->add_child ("Sources");
1324
1325         if (full_state) {
1326                 Glib::Mutex::Lock sl (audio_source_lock);
1327
1328                 for (AudioSourceList::iterator siter = audio_sources.begin(); siter != audio_sources.end(); ++siter) {
1329                         
1330                         /* Don't save information about AudioFileSources that are empty */
1331                         
1332                         boost::shared_ptr<AudioFileSource> fs;
1333
1334                         if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
1335                                 boost::shared_ptr<DestructiveFileSource> dfs = boost::dynamic_pointer_cast<DestructiveFileSource> (fs);
1336
1337                                 /* destructive file sources are OK if they are empty, because
1338                                    we will re-use them every time.
1339                                 */
1340
1341                                 if (!dfs) {
1342                                         if (fs->length() == 0) {
1343                                                 continue;
1344                                         }
1345                                 }
1346                         }
1347                         
1348                         child->add_child_nocopy (siter->second->get_state());
1349                 }
1350         }
1351
1352         child = node->add_child ("Regions");
1353
1354         if (full_state) { 
1355                 Glib::Mutex::Lock rl (region_lock);
1356
1357                 for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
1358                         
1359                         /* only store regions not attached to playlists */
1360
1361                         if (i->second->playlist() == 0) {
1362                                 child->add_child_nocopy (i->second->state (true));
1363                         }
1364                 }
1365         }
1366
1367         child = node->add_child ("DiskStreams");
1368
1369         { 
1370                 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1371                 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1372                         if (!(*i)->hidden()) {
1373                                 child->add_child_nocopy ((*i)->get_state());
1374                         }
1375                 }
1376         }
1377
1378         node->add_child_nocopy (_locations.get_state());
1379         
1380         child = node->add_child ("Connections");
1381         {
1382                 Glib::Mutex::Lock lm (connection_lock);
1383                 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1384                         if (!(*i)->system_dependent()) {
1385                                 child->add_child_nocopy ((*i)->get_state());
1386                         }
1387                 }
1388         }
1389
1390         child = node->add_child ("Routes");
1391         {
1392                 boost::shared_ptr<RouteList> r = routes.reader ();
1393                 
1394                 RoutePublicOrderSorter cmp;
1395                 RouteList public_order (*r);
1396                 public_order.sort (cmp);
1397                 
1398                 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1399                         if (!(*i)->hidden()) {
1400                                 if (full_state) {
1401                                         child->add_child_nocopy ((*i)->get_state());
1402                                 } else {
1403                                         child->add_child_nocopy ((*i)->get_template());
1404                                 }
1405                         }
1406                 }
1407         }
1408
1409         
1410         child = node->add_child ("EditGroups");
1411         for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1412                 child->add_child_nocopy ((*i)->get_state());
1413         }
1414
1415         child = node->add_child ("MixGroups");
1416         for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1417                 child->add_child_nocopy ((*i)->get_state());
1418         }
1419
1420         child = node->add_child ("Playlists");
1421         for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1422                 if (!(*i)->hidden()) {
1423                         if (!(*i)->empty()) {
1424                                 if (full_state) {
1425                                         child->add_child_nocopy ((*i)->get_state());
1426                                 } else {
1427                                         child->add_child_nocopy ((*i)->get_template());
1428                                 }
1429                         }
1430                 }
1431         }
1432
1433         child = node->add_child ("UnusedPlaylists");
1434         for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1435                 if (!(*i)->hidden()) {
1436                         if (!(*i)->empty()) {
1437                                 if (full_state) {
1438                                         child->add_child_nocopy ((*i)->get_state());
1439                                 } else {
1440                                         child->add_child_nocopy ((*i)->get_template());
1441                                 }
1442                         }
1443                 }
1444         }
1445         
1446         
1447         if (_click_io) {
1448                 child = node->add_child ("Click");
1449                 child->add_child_nocopy (_click_io->state (full_state));
1450         }
1451
1452         if (full_state) {
1453                 child = node->add_child ("NamedSelections");
1454                 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1455                         if (full_state) {
1456                                 child->add_child_nocopy ((*i)->get_state());
1457                         } 
1458                 }
1459         }
1460
1461         node->add_child_nocopy (_tempo_map->get_state());
1462
1463         if (_extra_xml) {
1464                 node->add_child_copy (*_extra_xml);
1465         }
1466
1467         return *node;
1468 }
1469
1470 int
1471 Session::set_state (const XMLNode& node)
1472 {
1473         XMLNodeList nlist;
1474         XMLNode* child;
1475         const XMLProperty* prop;
1476         int ret = -1;
1477
1478         _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1479         
1480         if (node.name() != X_("Session")){
1481                 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1482                 return -1;
1483         }
1484
1485         StateManager::prohibit_save ();
1486
1487         if ((prop = node.property ("name")) != 0) {
1488                 _name = prop->value ();
1489         }
1490
1491         if ((prop = node.property (X_("id-counter"))) != 0) {
1492                 uint64_t x;
1493                 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1494                 ID::init_counter (x);
1495         } else {
1496                 /* old sessions used a timebased counter, so fake
1497                    the startup ID counter based on a standard
1498                    timestamp.
1499                 */
1500                 time_t now;
1501                 time (&now);
1502                 ID::init_counter (now);
1503         }
1504
1505         
1506         IO::disable_ports ();
1507         IO::disable_connecting ();
1508
1509         /* Object loading order:
1510
1511         MIDI
1512         Path
1513         extra
1514         Options
1515         Sources
1516         AudioRegions
1517         AudioDiskstreams
1518         Connections
1519         Locations
1520         Routes
1521         EditGroups
1522         MixGroups
1523         Click
1524         */
1525
1526         if (use_config_midi_ports ()) {
1527         }
1528
1529         if ((child = find_named_node (node, "Path")) != 0) {
1530                 /* XXX this XML content stuff horrible API design */
1531                 string raid_path = _path + ':' + child->children().front()->content();
1532                 setup_raid_path (raid_path);
1533         } else {
1534                 /* the path is already set */
1535         }
1536
1537         if ((child = find_named_node (node, "extra")) != 0) {
1538                 _extra_xml = new XMLNode (*child);
1539         }
1540
1541         if ((child = find_named_node (node, "Options")) == 0) {
1542                 error << _("Session: XML state has no options section") << endmsg;
1543         } else if (load_options (*child)) {
1544         }
1545
1546         if ((child = find_named_node (node, "Sources")) == 0) {
1547                 error << _("Session: XML state has no sources section") << endmsg;
1548                 goto out;
1549         } else if (load_sources (*child)) {
1550                 goto out;
1551         }
1552
1553         if ((child = find_named_node (node, "Regions")) == 0) {
1554                 error << _("Session: XML state has no Regions section") << endmsg;
1555                 goto out;
1556         } else if (load_regions (*child)) {
1557                 goto out;
1558         }
1559
1560         if ((child = find_named_node (node, "Playlists")) == 0) {
1561                 error << _("Session: XML state has no playlists section") << endmsg;
1562                 goto out;
1563         } else if (load_playlists (*child)) {
1564                 goto out;
1565         }
1566
1567         if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1568                 // this is OK
1569         } else if (load_unused_playlists (*child)) {
1570                 goto out;
1571         }
1572         
1573         if ((child = find_named_node (node, "NamedSelections")) != 0) {
1574                 if (load_named_selections (*child)) {
1575                         goto out;
1576                 }
1577         }
1578
1579         if ((child = find_named_node (node, "DiskStreams")) == 0) {
1580                 error << _("Session: XML state has no diskstreams section") << endmsg;
1581                 goto out;
1582         } else if (load_diskstreams (*child)) {
1583                 goto out;
1584         }
1585
1586         if ((child = find_named_node (node, "Connections")) == 0) {
1587                 error << _("Session: XML state has no connections section") << endmsg;
1588                 goto out;
1589         } else if (load_connections (*child)) {
1590                 goto out;
1591         }
1592
1593         if ((child = find_named_node (node, "Locations")) == 0) {
1594                 error << _("Session: XML state has no locations section") << endmsg;
1595                 goto out;
1596         } else if (_locations.set_state (*child)) {
1597                 goto out;
1598         }
1599
1600         Location* location;
1601
1602         if ((location = _locations.auto_loop_location()) != 0) {
1603                 set_auto_loop_location (location);
1604         }
1605
1606         if ((location = _locations.auto_punch_location()) != 0) {
1607                 set_auto_punch_location (location);
1608         }
1609
1610         if ((location = _locations.end_location()) == 0) {
1611                 _locations.add (end_location);
1612         } else {
1613                 delete end_location;
1614                 end_location = location;
1615         }
1616
1617         if ((location = _locations.start_location()) == 0) {
1618                 _locations.add (start_location);
1619         } else {
1620                 delete start_location;
1621                 start_location = location;
1622         }
1623
1624         _locations.save_state (_("initial state"));
1625
1626         if ((child = find_named_node (node, "EditGroups")) == 0) {
1627                 error << _("Session: XML state has no edit groups section") << endmsg;
1628                 goto out;
1629         } else if (load_edit_groups (*child)) {
1630                 goto out;
1631         }
1632
1633         if ((child = find_named_node (node, "MixGroups")) == 0) {
1634                 error << _("Session: XML state has no mix groups section") << endmsg;
1635                 goto out;
1636         } else if (load_mix_groups (*child)) {
1637                 goto out;
1638         }
1639
1640         if ((child = find_named_node (node, "TempoMap")) == 0) {
1641                 error << _("Session: XML state has no Tempo Map section") << endmsg;
1642                 goto out;
1643         } else if (_tempo_map->set_state (*child)) {
1644                 goto out;
1645         }
1646
1647         if ((child = find_named_node (node, "Routes")) == 0) {
1648                 error << _("Session: XML state has no routes section") << endmsg;
1649                 goto out;
1650         } else if (load_routes (*child)) {
1651                 goto out;
1652         }
1653
1654         if ((child = find_named_node (node, "Click")) == 0) {
1655                 warning << _("Session: XML state has no click section") << endmsg;
1656         } else if (_click_io) {
1657                 _click_io->set_state (*child);
1658         }
1659         
1660         /* OK, now we can set edit mode */
1661
1662         set_edit_mode (pending_edit_mode);
1663
1664         /* here beginneth the second phase ... */
1665
1666         StateReady (); /* EMIT SIGNAL */
1667
1668         _state_of_the_state = Clean;
1669
1670         StateManager::allow_save (_("initial state"), true);
1671
1672         if (state_was_pending) {
1673                 save_state (_current_snapshot_name);
1674                 remove_pending_capture_state ();
1675                 state_was_pending = false;
1676         }
1677
1678         return 0;
1679
1680   out:
1681         /* we failed, re-enable state saving but don't actually save internal state */
1682         StateManager::allow_save (X_("ignored"), false);
1683         return ret;
1684 }
1685
1686 int
1687 Session::load_routes (const XMLNode& node)
1688 {
1689         XMLNodeList nlist;
1690         XMLNodeConstIterator niter;
1691         RouteList new_routes;
1692
1693         nlist = node.children();
1694
1695         set_dirty();
1696
1697         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1698
1699                 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1700
1701                 if (route == 0) {
1702                         error << _("Session: cannot create Route from XML description.")                              << endmsg;
1703                         return -1;
1704                 }
1705
1706                 new_routes.push_back (route);
1707         }
1708
1709         add_routes (new_routes);
1710
1711         return 0;
1712 }
1713
1714 boost::shared_ptr<Route>
1715 Session::XMLRouteFactory (const XMLNode& node)
1716 {
1717         if (node.name() != "Route") {
1718                 return boost::shared_ptr<Route> ((Route*) 0);
1719         }
1720
1721         if (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0) {
1722                 boost::shared_ptr<Route> x (new AudioTrack (*this, node));
1723                 return x;
1724         } else {
1725                 boost::shared_ptr<Route> x (new Route (*this, node));
1726                 return x;
1727         }
1728 }
1729
1730 int
1731 Session::load_regions (const XMLNode& node)
1732 {
1733         XMLNodeList nlist;
1734         XMLNodeConstIterator niter;
1735         boost::shared_ptr<AudioRegion> region;
1736
1737         nlist = node.children();
1738
1739         set_dirty();
1740
1741         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1742                 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1743                         error << _("Session: cannot create Region from XML description.") << endmsg;
1744                 }
1745         }
1746
1747         return 0;
1748 }
1749
1750 boost::shared_ptr<AudioRegion>
1751 Session::XMLRegionFactory (const XMLNode& node, bool full)
1752 {
1753         const XMLProperty* prop;
1754         boost::shared_ptr<Source> source;
1755         boost::shared_ptr<AudioSource> as;
1756         SourceList sources;
1757         uint32_t nchans = 1;
1758         char buf[128];
1759         
1760         if (node.name() != X_("Region")) {
1761                 return boost::shared_ptr<AudioRegion>();
1762         }
1763
1764         if ((prop = node.property (X_("channels"))) != 0) {
1765                 nchans = atoi (prop->value().c_str());
1766         }
1767
1768         
1769         if ((prop = node.property (X_("source-0"))) == 0) {
1770                 if ((prop = node.property ("source")) == 0) {
1771                         error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1772                         return boost::shared_ptr<AudioRegion>();
1773                 }
1774         }
1775
1776         PBD::ID s_id (prop->value());
1777
1778         if ((source = source_by_id (s_id)) == 0) {
1779                 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1780                 return boost::shared_ptr<AudioRegion>();
1781         }
1782         
1783         as = boost::dynamic_pointer_cast<AudioSource>(source);
1784         if (!as) {
1785                 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1786                 return boost::shared_ptr<AudioRegion>();
1787         }
1788
1789         sources.push_back (as);
1790
1791         /* pickup other channels */
1792
1793         for (uint32_t n=1; n < nchans; ++n) {
1794                 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1795                 if ((prop = node.property (buf)) != 0) {
1796                         
1797                         PBD::ID id2 (prop->value());
1798                         
1799                         if ((source = source_by_id (id2)) == 0) {
1800                                 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1801                                 return boost::shared_ptr<AudioRegion>();
1802                         }
1803                         
1804                         as = boost::dynamic_pointer_cast<AudioSource>(source);
1805                         if (!as) {
1806                                 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1807                                 return boost::shared_ptr<AudioRegion>();
1808                         }
1809                         sources.push_back (as);
1810                 }
1811         }
1812         
1813         try {
1814                 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1815                 return region;
1816                                                        
1817         }
1818
1819         catch (failed_constructor& err) {
1820                 return boost::shared_ptr<AudioRegion>();
1821         }
1822 }
1823
1824 XMLNode&
1825 Session::get_sources_as_xml ()
1826
1827 {
1828         XMLNode* node = new XMLNode (X_("Sources"));
1829         Glib::Mutex::Lock lm (audio_source_lock);
1830
1831         for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
1832                 node->add_child_nocopy (i->second->get_state());
1833         }
1834
1835         /* XXX get MIDI and other sources here */
1836
1837         return *node;
1838 }
1839
1840 string
1841 Session::path_from_region_name (string name, string identifier)
1842 {
1843         char buf[PATH_MAX+1];
1844         uint32_t n;
1845         string dir = discover_best_sound_dir ();
1846
1847         for (n = 0; n < 999999; ++n) {
1848                 if (identifier.length()) {
1849                         snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(), 
1850                                   identifier.c_str(), n);
1851                 } else {
1852                         snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1853                 }
1854                 if (access (buf, F_OK) != 0) {
1855                         return buf;
1856                 }
1857         }
1858
1859         return "";
1860 }
1861         
1862
1863 int
1864 Session::load_sources (const XMLNode& node)
1865 {
1866         XMLNodeList nlist;
1867         XMLNodeConstIterator niter;
1868         boost::shared_ptr<Source> source;
1869
1870         nlist = node.children();
1871
1872         set_dirty();
1873
1874         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1875
1876                 if ((source = XMLSourceFactory (**niter)) == 0) {
1877                         error << _("Session: cannot create Source from XML description.") << endmsg;
1878                 }
1879         }
1880
1881         return 0;
1882 }
1883
1884 boost::shared_ptr<Source>
1885 Session::XMLSourceFactory (const XMLNode& node)
1886 {
1887
1888         if (node.name() != "Source") {
1889                 return boost::shared_ptr<Source>();
1890         }
1891
1892         try {
1893                 return SourceFactory::create (*this, node);
1894         }
1895         
1896         catch (failed_constructor& err) {
1897                 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1898                 return boost::shared_ptr<Source>();
1899         }
1900 }
1901
1902 int
1903 Session::save_template (string template_name)
1904 {
1905         XMLTree tree;
1906         string xml_path, bak_path, template_path;
1907
1908         if (_state_of_the_state & CannotSave) {
1909                 return -1;
1910         }
1911
1912         DIR* dp;
1913         string dir = template_dir();
1914
1915         if ((dp = opendir (dir.c_str()))) {
1916                 closedir (dp);
1917         } else {
1918                 if (g_mkdir_with_parents (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
1919                         error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1920                         return -1;
1921                 }
1922         }
1923
1924         tree.set_root (&get_template());
1925
1926         xml_path = dir;
1927         xml_path += template_name;
1928         xml_path += _template_suffix;
1929
1930         ifstream in(xml_path.c_str());
1931         
1932         if (in) {
1933                 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1934                 return -1;
1935         } else {
1936                 in.close();
1937         }
1938
1939         if (!tree.write (xml_path)) {
1940                 error << _("mix template not saved") << endmsg;
1941                 return -1;
1942         }
1943
1944         return 0;
1945 }
1946
1947 int
1948 Session::rename_template (string old_name, string new_name) 
1949 {
1950         string old_path = template_dir() + old_name + _template_suffix;
1951         string new_path = template_dir() + new_name + _template_suffix;
1952
1953         return rename (old_path.c_str(), new_path.c_str());
1954 }
1955
1956 int
1957 Session::delete_template (string name) 
1958 {
1959         string template_path = template_dir();
1960         template_path += name;
1961         template_path += _template_suffix;
1962
1963         return remove (template_path.c_str());
1964 }
1965
1966 void
1967 Session::refresh_disk_space ()
1968 {
1969 #if HAVE_SYS_VFS_H
1970         struct statfs statfsbuf;
1971         vector<space_and_path>::iterator i;
1972         Glib::Mutex::Lock lm (space_lock);
1973         double scale;
1974
1975         /* get freespace on every FS that is part of the session path */
1976
1977         _total_free_4k_blocks = 0;
1978         
1979         for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1980                 statfs ((*i).path.c_str(), &statfsbuf);
1981
1982                 scale = statfsbuf.f_bsize/4096.0;
1983
1984                 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1985                 _total_free_4k_blocks += (*i).blocks;
1986         }
1987 #endif
1988 }
1989
1990 int
1991 Session::ensure_sound_dir (string path, string& result)
1992 {
1993         string dead;
1994         string peak;
1995
1996         /* Ensure that the parent directory exists */
1997         
1998         if (g_mkdir_with_parents (path.c_str(), 0775)) {
1999                 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
2000                 return -1;
2001         }
2002         
2003         /* Ensure that the sounds directory exists */
2004         
2005         result = path;
2006         result += '/';
2007         result += sound_dir_name;
2008         
2009         if (g_mkdir_with_parents (result.c_str(), 0775)) {
2010                 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
2011                 return -1;
2012         }
2013
2014         dead = path;
2015         dead += '/';
2016         dead += dead_sound_dir_name;
2017         
2018         if (g_mkdir_with_parents (dead.c_str(), 0775)) {
2019                 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
2020                 return -1;
2021         }
2022
2023         peak = path;
2024         peak += '/';
2025         peak += peak_dir_name;
2026         
2027         if (g_mkdir_with_parents (peak.c_str(), 0775)) {
2028                 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
2029                 return -1;
2030         }
2031         
2032         /* callers expect this to be terminated ... */
2033                         
2034         result += '/';
2035         return 0;
2036 }       
2037
2038 string
2039 Session::discover_best_sound_dir (bool destructive)
2040 {
2041         vector<space_and_path>::iterator i;
2042         string result;
2043
2044         /* handle common case without system calls */
2045
2046         if (session_dirs.size() == 1) {
2047                 return sound_dir();
2048         }
2049
2050         /* OK, here's the algorithm we're following here:
2051            
2052         We want to select which directory to use for 
2053         the next file source to be created. Ideally,
2054         we'd like to use a round-robin process so as to
2055         get maximum performance benefits from splitting
2056         the files across multiple disks.
2057
2058         However, in situations without much diskspace, an
2059         RR approach may end up filling up a filesystem
2060         with new files while others still have space.
2061         Its therefore important to pay some attention to
2062         the freespace in the filesystem holding each
2063         directory as well. However, if we did that by
2064         itself, we'd keep creating new files in the file
2065         system with the most space until it was as full
2066         as all others, thus negating any performance
2067         benefits of this RAID-1 like approach.
2068
2069         So, we use a user-configurable space threshold. If
2070         there are at least 2 filesystems with more than this
2071         much space available, we use RR selection between them. 
2072         If not, then we pick the filesystem with the most space.
2073
2074         This gets a good balance between the two
2075         approaches.  
2076         */
2077         
2078         refresh_disk_space ();
2079         
2080         int free_enough = 0;
2081
2082         for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2083                 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2084                         free_enough++;
2085                 }
2086         }
2087
2088         if (free_enough >= 2) {
2089
2090                 bool found_it = false;
2091
2092                 /* use RR selection process, ensuring that the one
2093                    picked works OK.
2094                 */
2095
2096                 i = last_rr_session_dir;
2097
2098                 do {
2099                         if (++i == session_dirs.end()) {
2100                                 i = session_dirs.begin();
2101                         }
2102
2103                         if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2104                                 if (ensure_sound_dir ((*i).path, result) == 0) {
2105                                         last_rr_session_dir = i;
2106                                         found_it = true;
2107                                         break;
2108                                 }
2109                         }
2110
2111                 } while (i != last_rr_session_dir);
2112
2113                 if (!found_it) {
2114                         result = sound_dir();
2115                 }
2116
2117         } else {
2118
2119                 /* pick FS with the most freespace (and that
2120                    seems to actually work ...)
2121                 */
2122                 
2123                 vector<space_and_path> sorted;
2124                 space_and_path_ascending_cmp cmp;
2125
2126                 sorted = session_dirs;
2127                 sort (sorted.begin(), sorted.end(), cmp);
2128                 
2129                 for (i = sorted.begin(); i != sorted.end(); ++i) {
2130                         if (ensure_sound_dir ((*i).path, result) == 0) {
2131                                 last_rr_session_dir = i;
2132                                 break;
2133                         }
2134                 }
2135                 
2136                 /* if the above fails, fall back to the most simplistic solution */
2137                 
2138                 if (i == sorted.end()) {
2139                         return sound_dir();
2140                 } 
2141         }
2142
2143         return result;
2144 }
2145
2146 int
2147 Session::load_playlists (const XMLNode& node)
2148 {
2149         XMLNodeList nlist;
2150         XMLNodeConstIterator niter;
2151         Playlist *playlist;
2152
2153         nlist = node.children();
2154
2155         set_dirty();
2156
2157         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2158                 
2159                 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2160                         error << _("Session: cannot create Playlist from XML description.") << endmsg;
2161                 }
2162         }
2163
2164         return 0;
2165 }
2166
2167 int
2168 Session::load_unused_playlists (const XMLNode& node)
2169 {
2170         XMLNodeList nlist;
2171         XMLNodeConstIterator niter;
2172         Playlist *playlist;
2173
2174         nlist = node.children();
2175
2176         set_dirty();
2177
2178         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2179                 
2180                 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2181                         error << _("Session: cannot create Playlist from XML description.") << endmsg;
2182                         continue;
2183                 }
2184
2185                 // now manually untrack it
2186
2187                 track_playlist (playlist, false);
2188         }
2189
2190         return 0;
2191 }
2192
2193
2194 Playlist *
2195 Session::XMLPlaylistFactory (const XMLNode& node)
2196 {
2197         try {
2198                 return new AudioPlaylist (*this, node);
2199         }
2200
2201         catch (failed_constructor& err) {
2202                 return 0;
2203         }
2204 }
2205
2206 int
2207 Session::load_named_selections (const XMLNode& node)
2208 {
2209         XMLNodeList nlist;
2210         XMLNodeConstIterator niter;
2211         NamedSelection *ns;
2212
2213         nlist = node.children();
2214
2215         set_dirty();
2216
2217         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2218                 
2219                 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2220                         error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2221                 }
2222         }
2223
2224         return 0;
2225 }
2226
2227 NamedSelection *
2228 Session::XMLNamedSelectionFactory (const XMLNode& node)
2229 {
2230         try {
2231                 return new NamedSelection (*this, node);
2232         }
2233
2234         catch (failed_constructor& err) {
2235                 return 0;
2236         }
2237 }
2238
2239 string
2240 Session::dead_sound_dir () const
2241 {
2242         string res = _path;
2243         res += dead_sound_dir_name;
2244         res += '/';
2245         return res;
2246 }
2247
2248 string
2249 Session::sound_dir (bool with_path) const
2250 {
2251         /* support old session structure */
2252
2253         struct stat statbuf;
2254         string old;
2255
2256         if (with_path) {
2257                 old = _path;
2258         }
2259
2260         old += sound_dir_name;
2261         old += '/';
2262
2263         if (stat (old.c_str(), &statbuf) == 0) {
2264                 return old;
2265         }
2266
2267         string res;
2268
2269         if (with_path) {
2270                 res = _path;
2271         }
2272
2273         res += interchange_dir_name;
2274         res += '/';
2275         res += legalize_for_path (_name);
2276         res += '/';
2277         res += sound_dir_name;
2278         res += '/';
2279
2280         return res;
2281 }
2282
2283 string
2284 Session::peak_dir () const
2285 {
2286         string res = _path;
2287         res += peak_dir_name;
2288         res += '/';
2289         return res;
2290 }
2291         
2292 string
2293 Session::automation_dir () const
2294 {
2295         string res = _path;
2296         res += "automation/";
2297         return res;
2298 }
2299
2300 string
2301 Session::template_dir ()
2302 {
2303         string path = get_user_ardour_path();
2304         path += "templates/";
2305
2306         return path;
2307 }
2308
2309 string
2310 Session::suffixed_search_path (string suffix, bool data)
2311 {
2312         string path;
2313
2314         path += get_user_ardour_path();
2315         if (path[path.length()-1] != ':') {
2316                 path += ':';
2317         }
2318
2319         if (data) {
2320                 path += get_system_data_path();
2321         } else {
2322                 path += get_system_module_path();
2323         }
2324
2325         vector<string> split_path;
2326         
2327         split (path, split_path, ':');
2328         path = "";
2329
2330         for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2331                 path += *i;
2332                 path += suffix;
2333                 path += '/';
2334                 
2335                 if (distance (i, split_path.end()) != 1) {
2336                         path += ':';
2337                 }
2338         }
2339                 
2340         return path;
2341 }
2342
2343 string
2344 Session::template_path ()
2345 {
2346         return suffixed_search_path (X_("templates"), true);
2347 }
2348
2349 string
2350 Session::control_protocol_path ()
2351 {
2352         return suffixed_search_path (X_("surfaces"), false);
2353 }
2354
2355 int
2356 Session::load_connections (const XMLNode& node)
2357 {
2358         XMLNodeList nlist = node.children();
2359         XMLNodeConstIterator niter;
2360
2361         set_dirty();
2362
2363         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2364                 if ((*niter)->name() == "InputConnection") {
2365                         add_connection (new ARDOUR::InputConnection (**niter));
2366                 } else if ((*niter)->name() == "OutputConnection") {
2367                         add_connection (new ARDOUR::OutputConnection (**niter));
2368                 } else {
2369                         error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2370                         return -1;
2371                 }
2372         }
2373
2374         return 0;
2375 }                               
2376
2377 int
2378 Session::load_edit_groups (const XMLNode& node)
2379 {
2380         return load_route_groups (node, true);
2381 }
2382
2383 int
2384 Session::load_mix_groups (const XMLNode& node)
2385 {
2386         return load_route_groups (node, false);
2387 }
2388
2389 int
2390 Session::load_route_groups (const XMLNode& node, bool edit)
2391 {
2392         XMLNodeList nlist = node.children();
2393         XMLNodeConstIterator niter;
2394         RouteGroup* rg;
2395
2396         set_dirty();
2397
2398         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2399                 if ((*niter)->name() == "RouteGroup") {
2400                         if (edit) {
2401                                 rg = add_edit_group ("");
2402                                 rg->set_state (**niter);
2403                         } else {
2404                                 rg = add_mix_group ("");
2405                                 rg->set_state (**niter);
2406                         }
2407                 }
2408         }
2409         
2410         return 0;
2411 }                               
2412
2413 static bool
2414 state_file_filter (const string &str, void *arg)
2415 {
2416         return (str.length() > strlen(Session::statefile_suffix()) &&
2417                 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2418 }
2419
2420 struct string_cmp {
2421         bool operator()(const string* a, const string* b) {
2422                 return *a < *b;
2423         }
2424 };
2425
2426 static string*
2427 remove_end(string* state)
2428 {
2429         string statename(*state);
2430         
2431         string::size_type start,end;
2432         if ((start = statename.find_last_of ('/')) != string::npos) {
2433                 statename = statename.substr (start+1);
2434         }
2435                 
2436         if ((end = statename.rfind(".ardour")) == string::npos) {
2437                 end = statename.length();
2438         }
2439
2440         return new string(statename.substr (0, end));
2441 }
2442
2443 vector<string *> *
2444 Session::possible_states (string path) 
2445 {
2446         PathScanner scanner;
2447         vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2448         
2449         transform(states->begin(), states->end(), states->begin(), remove_end);
2450         
2451         string_cmp cmp;
2452         sort (states->begin(), states->end(), cmp);
2453         
2454         return states;
2455 }
2456
2457 vector<string *> *
2458 Session::possible_states () const
2459 {
2460         return possible_states(_path);
2461 }
2462
2463 void
2464 Session::auto_save()
2465 {
2466         save_state (_current_snapshot_name);
2467 }
2468
2469 RouteGroup *
2470 Session::add_edit_group (string name)
2471 {
2472         RouteGroup* rg = new RouteGroup (*this, name);
2473         edit_groups.push_back (rg);
2474         edit_group_added (rg); /* EMIT SIGNAL */
2475         set_dirty();
2476         return rg;
2477 }
2478
2479 RouteGroup *
2480 Session::add_mix_group (string name)
2481 {
2482         RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2483         mix_groups.push_back (rg);
2484         mix_group_added (rg); /* EMIT SIGNAL */
2485         set_dirty();
2486         return rg;
2487 }
2488
2489 void
2490 Session::remove_edit_group (RouteGroup& rg)
2491 {
2492         list<RouteGroup*>::iterator i;
2493
2494         if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2495                 (*i)->apply (&Route::drop_edit_group, this);
2496                 edit_groups.erase (i);
2497                 edit_group_removed (); /* EMIT SIGNAL */
2498         }
2499
2500         delete &rg;
2501 }
2502
2503 void
2504 Session::remove_mix_group (RouteGroup& rg)
2505 {
2506         list<RouteGroup*>::iterator i;
2507
2508         if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2509                 (*i)->apply (&Route::drop_mix_group, this);
2510                 mix_groups.erase (i);
2511                 mix_group_removed (); /* EMIT SIGNAL */
2512         }
2513
2514         delete &rg;
2515 }
2516
2517 RouteGroup *
2518 Session::mix_group_by_name (string name)
2519 {
2520         list<RouteGroup *>::iterator i;
2521
2522         for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2523                 if ((*i)->name() == name) {
2524                         return* i;
2525                 }
2526         }
2527         return 0;
2528 }
2529
2530 RouteGroup *
2531 Session::edit_group_by_name (string name)
2532 {
2533         list<RouteGroup *>::iterator i;
2534
2535         for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2536                 if ((*i)->name() == name) {
2537                         return* i;
2538                 }
2539         }
2540         return 0;
2541 }
2542
2543 void
2544 Session::set_meter_hold (float val)
2545 {
2546         _meter_hold = val;
2547         MeterHoldChanged(); // emit
2548 }
2549
2550 void
2551 Session::set_meter_falloff (float val)
2552 {
2553         _meter_falloff = val;
2554         MeterFalloffChanged(); // emit
2555 }
2556
2557
2558 void
2559 Session::begin_reversible_command (string name)
2560 {
2561         current_trans = new UndoTransaction;
2562         current_trans->set_name (name);
2563 }
2564
2565 void
2566 Session::commit_reversible_command (Command *cmd)
2567 {
2568         struct timeval now;
2569
2570         if (cmd) {
2571                 current_trans->add_command (cmd);
2572         }
2573
2574         gettimeofday (&now, 0);
2575         current_trans->set_timestamp (now);
2576
2577         history.add (current_trans);
2578 }
2579
2580 Session::GlobalRouteBooleanState 
2581 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2582 {
2583         GlobalRouteBooleanState s;
2584         boost::shared_ptr<RouteList> r = routes.reader ();
2585
2586         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2587                 if (!(*i)->hidden()) {
2588                         RouteBooleanState v;
2589                         
2590                         v.first =* i;
2591                         Route* r = (*i).get();
2592                         v.second = (r->*method)();
2593                         
2594                         s.push_back (v);
2595                 }
2596         }
2597
2598         return s;
2599 }
2600
2601 Session::GlobalRouteMeterState
2602 Session::get_global_route_metering ()
2603 {
2604         GlobalRouteMeterState s;
2605         boost::shared_ptr<RouteList> r = routes.reader ();
2606
2607         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2608                 if (!(*i)->hidden()) {
2609                         RouteMeterState v;
2610                         
2611                         v.first =* i;
2612                         v.second = (*i)->meter_point();
2613                         
2614                         s.push_back (v);
2615                 }
2616         }
2617
2618         return s;
2619 }
2620
2621 void
2622 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg) 
2623 {
2624         for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2625                 i->first->set_meter_point (i->second, arg);
2626         }
2627 }
2628
2629 void
2630 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2631 {
2632         for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2633                 Route* r = i->first.get();
2634                 (r->*method) (i->second, arg);
2635         }
2636 }
2637
2638 void
2639 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2640 {
2641         set_global_route_boolean (s, &Route::set_mute, src);
2642 }
2643
2644 void
2645 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2646 {
2647         set_global_route_boolean (s, &Route::set_solo, src);
2648 }
2649
2650 void
2651 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2652 {
2653         set_global_route_boolean (s, &Route::set_record_enable, src);
2654 }
2655
2656 #if 0
2657 UndoAction
2658 Session::global_mute_memento (void* src)
2659 {
2660         return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2661 }
2662
2663 UndoAction
2664 Session::global_metering_memento (void* src)
2665 {
2666         return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2667 }
2668
2669 UndoAction
2670 Session::global_solo_memento (void* src)
2671 {
2672         return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2673 }
2674
2675 UndoAction
2676 Session::global_record_enable_memento (void* src)
2677 {
2678         return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2679 }
2680 #endif
2681
2682 static bool
2683 template_filter (const string &str, void *arg)
2684 {
2685         return (str.length() > strlen(Session::template_suffix()) &&
2686                 str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
2687 }
2688
2689 void
2690 Session::get_template_list (list<string> &template_names)
2691 {
2692         vector<string *> *templates;
2693         PathScanner scanner;
2694         string path;
2695
2696         path = template_path ();
2697
2698         templates = scanner (path, template_filter, 0, false, true);
2699         
2700         vector<string*>::iterator i;
2701         for (i = templates->begin(); i != templates->end(); ++i) {
2702                 string fullpath = *(*i);
2703                 int start, end;
2704
2705                 start = fullpath.find_last_of ('/') + 1;
2706                 if ((end = fullpath.find_last_of ('.')) <0) {
2707                         end = fullpath.length();
2708                 }
2709                 
2710                 template_names.push_back(fullpath.substr(start, (end-start)));
2711         }
2712 }
2713
2714 int
2715 Session::read_favorite_dirs (FavoriteDirs & favs)
2716 {
2717         string path = get_user_ardour_path();
2718         path += "/favorite_dirs";
2719
2720         ifstream fav (path.c_str());
2721
2722         favs.clear();
2723         
2724         if (!fav) {
2725                 if (errno != ENOENT) {
2726                         //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2727                         return -1;
2728                 } else {
2729                         return 1;
2730                 }
2731         }
2732
2733         while (true) {
2734
2735                 string newfav;
2736
2737                 getline(fav, newfav);
2738
2739                 if (!fav.good()) {
2740                         break;
2741                 }
2742
2743                 favs.push_back (newfav);
2744         }
2745
2746         return 0;
2747 }
2748
2749 int
2750 Session::write_favorite_dirs (FavoriteDirs & favs)
2751 {
2752         string path = get_user_ardour_path();
2753         path += "/favorite_dirs";
2754
2755         ofstream fav (path.c_str());
2756
2757         if (!fav) {
2758                 return -1;
2759         }
2760
2761         for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2762                 fav << (*i) << endl;
2763         }
2764         
2765         return 0;
2766 }
2767
2768 static bool
2769 accept_all_non_peak_files (const string& path, void *arg)
2770 {
2771         return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2772 }
2773
2774 static bool
2775 accept_all_state_files (const string& path, void *arg)
2776 {
2777         return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2778 }
2779
2780 int 
2781 Session::find_all_sources (string path, set<string>& result)
2782 {
2783         XMLTree tree;
2784         XMLNode* node;
2785
2786         if (!tree.read (path)) {
2787                 return -1;
2788         }
2789
2790         if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2791                 return -2;
2792         }
2793
2794         XMLNodeList nlist;
2795         XMLNodeConstIterator niter;
2796
2797         nlist = node->children();
2798
2799         set_dirty();
2800
2801         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2802                 
2803                 XMLProperty* prop;
2804
2805                 if ((prop = (*niter)->property (X_("name"))) == 0) {
2806                         continue;
2807                 }
2808
2809                 if (prop->value()[0] == '/') {
2810                         /* external file, ignore */
2811                         continue;
2812                 }
2813
2814                 string path = _path; /* /-terminated */
2815                 path += sound_dir_name;
2816                 path += '/';
2817                 path += prop->value();
2818
2819                 result.insert (path);
2820         }
2821
2822         return 0;
2823 }
2824
2825 int
2826 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2827 {
2828         PathScanner scanner;
2829         vector<string*>* state_files;
2830         string ripped;
2831         string this_snapshot_path;
2832
2833         result.clear ();
2834
2835         ripped = _path;
2836
2837         if (ripped[ripped.length()-1] == '/') {
2838                 ripped = ripped.substr (0, ripped.length() - 1);
2839         }
2840
2841         state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2842         
2843         if (state_files == 0) {
2844                 /* impossible! */
2845                 return 0;
2846         }
2847
2848         this_snapshot_path = _path;
2849         this_snapshot_path += _current_snapshot_name;
2850         this_snapshot_path += _statefile_suffix;
2851
2852         for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2853
2854                 if (exclude_this_snapshot && **i == this_snapshot_path) {
2855                         continue;
2856                 }
2857
2858                 if (find_all_sources (**i, result) < 0) {
2859                         return -1;
2860                 }
2861         }
2862
2863         return 0;
2864 }
2865
2866 int
2867 Session::cleanup_sources (Session::cleanup_report& rep)
2868 {
2869         vector<boost::shared_ptr<Source> > dead_sources;
2870         vector<Playlist*> playlists_tbd;
2871         PathScanner scanner;
2872         string sound_path;
2873         vector<space_and_path>::iterator i;
2874         vector<space_and_path>::iterator nexti;
2875         vector<string*>* soundfiles;
2876         vector<string> unused;
2877         set<string> all_sources;
2878         bool used;
2879         string spath;
2880         int ret = -1;
2881                 
2882         _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2883         
2884         /* step 1: consider deleting all unused playlists */
2885
2886         for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2887                 int status;
2888
2889                 status = AskAboutPlaylistDeletion (*x);
2890
2891                 switch (status) {
2892                 case -1:
2893                         ret = 0;
2894                         goto out;
2895                         break;
2896
2897                 case 0:
2898                         playlists_tbd.push_back (*x);
2899                         break;
2900
2901                 default:
2902                         /* leave it alone */
2903                         break;
2904                 }
2905         }
2906
2907         /* now delete any that were marked for deletion */
2908
2909         for (vector<Playlist*>::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2910                 PlaylistList::iterator foo;
2911
2912                 if ((foo = unused_playlists.find (*x)) != unused_playlists.end()) {
2913                         unused_playlists.erase (foo);
2914                 }
2915                 delete *x;
2916         }
2917
2918         /* step 2: clear the undo/redo history for all playlists */
2919
2920         for (PlaylistList::iterator x = playlists.begin(); x != playlists.end(); ++x) {
2921                 (*x)->drop_all_states ();
2922         }
2923
2924         /* step 3: find all un-referenced sources */
2925
2926         rep.paths.clear ();
2927         rep.space = 0;
2928
2929         for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ) {
2930
2931                 AudioSourceList::iterator tmp;
2932
2933                 tmp = i;
2934                 ++tmp;
2935
2936                 /* only remove files that are not in use and have some size
2937                    to them. otherwise we remove the current "nascent"
2938                    capture files.
2939                 */
2940
2941                 if (i->second.use_count() == 1 && i->second->length() > 0) {
2942                         dead_sources.push_back (i->second);
2943
2944                         /* remove this source from our own list to avoid us
2945                            adding it to the list of all sources below
2946                         */
2947
2948                         audio_sources.erase (i);
2949                 }
2950
2951                 i = tmp;
2952         }
2953
2954         /* Step 4: get rid of all regions in the region list that use any dead sources
2955            in case the sources themselves don't go away (they might be referenced in
2956            other snapshots).
2957         */
2958                 
2959         for (vector<boost::shared_ptr<Source> >::iterator i = dead_sources.begin(); i != dead_sources.end();++i) {
2960
2961                 for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ) {
2962                         AudioRegionList::iterator tmp;
2963                         boost::shared_ptr<AudioRegion> ar;
2964
2965                         tmp = r;
2966                         ++tmp;
2967                         
2968                         ar = r->second;
2969
2970                         for (uint32_t n = 0; n < ar->n_channels(); ++n) {
2971                                 if (ar->source (n) == (*i)) {
2972                                         /* this region is dead */
2973                                         remove_region (ar);
2974                                 }
2975                         }
2976                         
2977                         r = tmp;
2978                 }
2979         }
2980
2981         /* build a list of all the possible sound directories for the session */
2982
2983         for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2984
2985                 nexti = i;
2986                 ++nexti;
2987
2988                 sound_path += (*i).path;
2989                 sound_path += sound_dir_name;
2990
2991                 if (nexti != session_dirs.end()) {
2992                         sound_path += ':';
2993                 }
2994
2995                 i = nexti;
2996         }
2997         
2998         /* now do the same thing for the files that ended up in the sounds dir(s) 
2999            but are not referenced as sources in any snapshot.
3000         */
3001
3002         soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
3003
3004         if (soundfiles == 0) {
3005                 return 0;
3006         }
3007
3008         /* find all sources, but don't use this snapshot because the
3009            state file on disk still references sources we may have already
3010            dropped.
3011         */
3012         
3013         find_all_sources_across_snapshots (all_sources, true);
3014
3015         /*  add our current source list
3016          */
3017         
3018         for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
3019                 boost::shared_ptr<AudioFileSource> fs;
3020                 
3021                 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (i->second)) != 0) {
3022                         all_sources.insert (fs->path());
3023                 } 
3024         }
3025
3026         for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
3027
3028                 used = false;
3029                 spath = **x;
3030
3031                 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3032
3033                         if (spath == *i) {
3034                                 used = true;
3035                                 break;
3036                         }
3037
3038                 }
3039
3040                 if (!used) {
3041                         unused.push_back (spath);
3042                 }
3043         }
3044
3045         /* now try to move all unused files into the "dead_sounds" directory(ies) */
3046
3047         for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3048                 struct stat statbuf;
3049
3050                 rep.paths.push_back (*x);
3051                 if (stat ((*x).c_str(), &statbuf) == 0) {
3052                         rep.space += statbuf.st_size;
3053                 }
3054
3055                 string newpath;
3056                 
3057                 /* don't move the file across filesystems, just
3058                    stick it in the `dead_sound_dir_name' directory
3059                    on whichever filesystem it was already on.
3060                 */
3061
3062                 newpath = Glib::path_get_dirname (*x);
3063                 newpath = Glib::path_get_dirname (newpath);
3064
3065                 newpath += '/';
3066                 newpath += dead_sound_dir_name;
3067                 newpath += '/';
3068                 newpath += Glib::path_get_basename ((*x));
3069                 
3070                 if (access (newpath.c_str(), F_OK) == 0) {
3071                         
3072                         /* the new path already exists, try versioning */
3073                         
3074                         char buf[PATH_MAX+1];
3075                         int version = 1;
3076                         string newpath_v;
3077                         
3078                         snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3079                         newpath_v = buf;
3080
3081                         while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
3082                                 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3083                                 newpath_v = buf;
3084                         }
3085                         
3086                         if (version == 999) {
3087                                 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3088                                                   newpath)
3089                                       << endmsg;
3090                         } else {
3091                                 newpath = newpath_v;
3092                         }
3093                         
3094                 } else {
3095                         
3096                         /* it doesn't exist, or we can't read it or something */
3097                         
3098                 }
3099
3100                 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3101                         error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
3102                                           (*x), newpath, strerror (errno))
3103                               << endmsg;
3104                         goto out;
3105                 }
3106                 
3107
3108                 /* see if there an easy to find peakfile for this file, and remove it.
3109                  */
3110
3111                 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
3112                 peakpath += ".peak";
3113
3114                 if (access (peakpath.c_str(), W_OK) == 0) {
3115                         if (::unlink (peakpath.c_str()) != 0) {
3116                                 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3117                                                   peakpath, _path, strerror (errno))
3118                                       << endmsg;
3119                                 /* try to back out */
3120                                 rename (newpath.c_str(), _path.c_str());
3121                                 goto out;
3122                         }
3123                 }
3124
3125         }
3126
3127         ret = 0;
3128
3129         /* dump the history list */
3130
3131         history.clear ();
3132
3133         /* save state so we don't end up a session file
3134            referring to non-existent sources.
3135         */
3136         
3137         save_state ("");
3138
3139   out:
3140         _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3141         return ret;
3142 }
3143
3144 int
3145 Session::cleanup_trash_sources (Session::cleanup_report& rep)
3146 {
3147         vector<space_and_path>::iterator i;
3148         string dead_sound_dir;
3149         struct dirent* dentry;
3150         struct stat statbuf;
3151         DIR* dead;
3152
3153         rep.paths.clear ();
3154         rep.space = 0;
3155
3156         for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3157                 
3158                 dead_sound_dir = (*i).path;
3159                 dead_sound_dir += dead_sound_dir_name;
3160
3161                 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
3162                         continue;
3163                 }
3164
3165                 while ((dentry = readdir (dead)) != 0) {
3166
3167                         /* avoid '.' and '..' */
3168                         
3169                         if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') || 
3170                             (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
3171                                 continue;
3172                         }
3173
3174                         string fullpath;
3175
3176                         fullpath = dead_sound_dir;
3177                         fullpath += '/';
3178                         fullpath += dentry->d_name;
3179
3180                         if (stat (fullpath.c_str(), &statbuf)) {
3181                                 continue;
3182                         }
3183
3184                         if (!S_ISREG (statbuf.st_mode)) {
3185                                 continue;
3186                         }
3187
3188                         if (unlink (fullpath.c_str())) {
3189                                 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
3190                                                   fullpath, strerror (errno))
3191                                       << endmsg;
3192                         }
3193
3194                         rep.paths.push_back (dentry->d_name);
3195                         rep.space += statbuf.st_size;
3196                 }
3197
3198                 closedir (dead);
3199                 
3200         }
3201
3202         return 0;
3203 }
3204
3205 void
3206 Session::set_dirty ()
3207 {
3208         bool was_dirty = dirty();
3209
3210         _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3211
3212         if (!was_dirty) {
3213                 DirtyChanged(); /* EMIT SIGNAL */
3214         }
3215 }
3216
3217
3218 void
3219 Session::set_clean ()
3220 {
3221         bool was_dirty = dirty();
3222         
3223         _state_of_the_state = Clean;
3224
3225         if (was_dirty) {
3226                 DirtyChanged(); /* EMIT SIGNAL */
3227         }
3228 }
3229
3230 void
3231 Session::add_controllable (Controllable* c)
3232 {
3233         Glib::Mutex::Lock lm (controllables_lock);
3234         controllables.push_back (c);
3235 }
3236
3237 void
3238 Session::remove_controllable (Controllable* c)
3239 {
3240         if (_state_of_the_state | Deletion) {
3241                 return;
3242         }
3243
3244         Glib::Mutex::Lock lm (controllables_lock);
3245         controllables.remove (c);
3246 }       
3247
3248 Controllable*
3249 Session::controllable_by_id (const PBD::ID& id)
3250 {
3251         Glib::Mutex::Lock lm (controllables_lock);
3252         
3253         for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3254                 if ((*i)->id() == id) {
3255                         return *i;
3256                 }
3257         }
3258
3259         return 0;
3260 }
3261
3262 void 
3263 Session::add_instant_xml (XMLNode& node, const std::string& dir)
3264 {
3265         Stateful::add_instant_xml (node, dir);
3266         Config->add_instant_xml (node, get_user_ardour_path());
3267 }
3268
3269
3270 int 
3271 Session::save_history (string snapshot_name)
3272 {
3273     XMLTree tree;
3274     string xml_path;
3275     string bak_path;
3276     
3277     tree.set_root (&history.get_state());
3278
3279     if (snapshot_name.empty()) {
3280         snapshot_name = _current_snapshot_name;
3281     }
3282
3283     xml_path = _path + snapshot_name + ".history"; 
3284
3285     bak_path = xml_path + ".bak";
3286
3287     if ((access (xml_path.c_str(), F_OK) == 0) &&
3288         (rename (xml_path.c_str(), bak_path.c_str())))
3289     {
3290         error << _("could not backup old history file, current history not saved.") << endmsg;
3291         return -1;
3292     }
3293
3294     cerr << "actually writing history\n";
3295
3296     if (!tree.write (xml_path))
3297     {
3298         error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3299
3300         /* don't leave a corrupt file lying around if it is
3301          * possible to fix.
3302          */
3303
3304         if (unlink (xml_path.c_str())) 
3305         {
3306             error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
3307         } else {
3308             if (rename (bak_path.c_str(), xml_path.c_str())) 
3309             {
3310                 error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;
3311             }
3312         }
3313
3314         return -1;
3315     }
3316
3317     return 0;
3318 }
3319
3320 int
3321 Session::restore_history (string snapshot_name)
3322 {
3323     XMLTree tree;
3324     string xmlpath;
3325
3326     /* read xml */
3327     xmlpath = _path + snapshot_name + ".history";
3328     cerr << string_compose(_("Loading history from '%1'."), xmlpath) << endmsg;
3329
3330     if (access (xmlpath.c_str(), F_OK)) {
3331         error << string_compose(_("%1: session history file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
3332         return 1;
3333     }
3334
3335     if (!tree.read (xmlpath)) {
3336         error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
3337         return -1;
3338     }
3339
3340     /* replace history */
3341     history.clear();
3342     for (XMLNodeConstIterator it  = tree.root()->children().begin();
3343          it != tree.root()->children().end();
3344          it++)
3345     {
3346         XMLNode *t = *it;
3347         UndoTransaction* ut = new UndoTransaction ();
3348         struct timeval tv;
3349
3350         ut->set_name(t->property("name")->value());
3351         stringstream ss(t->property("tv_sec")->value());
3352         ss >> tv.tv_sec;
3353         ss.str(t->property("tv_usec")->value());
3354         ss >> tv.tv_usec;
3355         ut->set_timestamp(tv);
3356
3357         for (XMLNodeConstIterator child_it  = t->children().begin();
3358              child_it != t->children().end();
3359              child_it++)
3360         {
3361             XMLNode *n = *child_it;
3362             Command *c;
3363             if (n->name() == "MementoCommand" ||
3364                 n->name() == "MementoUndoCommand" ||
3365                 n->name() == "MementoRedoCommand")
3366             {
3367                 c = memento_command_factory(n);
3368                 if (c)
3369                     ut->add_command(c);
3370             }
3371             else
3372             {
3373                 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3374             }
3375         }
3376         history.add(ut);
3377     }
3378
3379     return 0;
3380 }