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