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