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