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