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