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