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