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