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