2 Copyright (C) 1999-2002 Paul Davis
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.
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.
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.
20 #define __STDC_FORMAT_MACROS 1
28 #include <sigc++/bind.h>
30 #include <cstdio> /* snprintf(3) ... grrr */
45 #include <sys/param.h>
46 #include <sys/mount.h>
51 #include <midi++/mmc.h>
52 #include <midi++/port.h>
53 #include <pbd/error.h>
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>
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>
100 #include <control_protocol/control_protocol.h>
106 using namespace ARDOUR;
110 Session::first_stage_init (string fullpath, string snapshot_name)
112 if (fullpath.length() == 0) {
114 throw failed_constructor();
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;
121 throw failed_constructor();
126 if (_path[_path.length()-1] != '/') {
130 /* these two are just provisional settings. set_state()
131 will likely override them.
134 _name = _current_snapshot_name = snapshot_name;
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));
140 g_atomic_int_set (&processing_prohibited, 0);
142 _transport_speed = 0;
143 _last_transport_speed = 0;
144 auto_play_legal = false;
145 transport_sub_state = 0;
146 _transport_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;
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;
161 state_was_pending = false;
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);
174 butler_mixdown_buffer = 0;
175 butler_gain_buffer = 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);
187 waiting_to_start = false;
189 _gain_automation_buffer = 0;
190 _pan_automation_buffer = 0;
192 pending_abort = false;
193 destructive_index = 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;
200 AudioDiskstream::allocate_working_buffers();
202 /* default short fade = 15ms */
204 Crossfade::set_short_xfade_length ((nframes_t) floor (Config->get_short_xfade_seconds() * frame_rate()));
205 SndFileSource::setup_standard_crossfades (frame_rate());
207 last_mmc_step.tv_sec = 0;
208 last_mmc_step.tv_usec = 0;
211 /* click sounds are unset by default, which causes us to internal
212 waveforms for clicks.
216 click_emphasis_data = 0;
218 click_emphasis_length = 0;
221 process_function = &Session::process_with_events;
223 if (Config->get_use_video_sync()) {
224 waiting_for_sync_offset = true;
226 waiting_for_sync_offset = false;
229 _current_frame_rate = 48000;
230 _base_frame_rate = 48000;
234 _smpte_offset_negative = true;
235 last_smpte_valid = false;
239 last_rr_session_dir = session_dirs.begin();
240 refresh_disk_space ();
242 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
246 average_slave_delta = 1800;
247 have_first_delta_accumulator = false;
248 delta_accumulator_cnt = 0;
249 slave_state = Stopped;
251 _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
253 /* These are all static "per-class" signals */
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));
262 Controllable::Destroyed.connect (mem_fun (*this, &Session::remove_controllable));
264 IO::MoreChannels.connect (mem_fun (*this, &Session::ensure_buffers));
266 /* stop IO objects from doing stuff until we're ready for them */
268 IO::disable_panners ();
269 IO::disable_ports ();
270 IO::disable_connecting ();
274 Session::second_stage_init (bool new_session)
276 AudioFileSource::set_peak_dir (peak_dir());
279 if (load_state (_current_snapshot_name)) {
282 remove_empty_sounds ();
285 if (start_butler_thread()) {
289 /*if (start_midi_thread ()) {
293 // set_state() will call setup_raid_path(), but if it's a new session we need
294 // to call setup_raid_path() here.
296 if (set_state (*state_tree->root())) {
300 setup_raid_path(_path);
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.
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.
313 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
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 ();
321 /* Pay attention ... */
323 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
324 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
327 when_engine_running();
330 /* handle this one in a different way than all others, so that its clear what happened */
332 catch (AudioEngine::PortRegistrationFailure& err) {
333 error << _("Unable to create all required ports")
342 //send_full_time_code ();
343 _engine.transport_locate (0);
344 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
345 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
347 ControlProtocolManager::instance().set_session (*this);
350 _end_location_is_free = true;
352 _end_location_is_free = false;
359 Session::raid_path () const
363 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
368 return path.substr (0, path.length() - 1); // drop final colon
372 Session::setup_raid_path (string path)
374 string::size_type colon;
378 string::size_type len = path.length();
383 if (path.length() == 0) {
387 session_dirs.clear ();
389 for (string::size_type n = 0; n < len; ++n) {
390 if (path[n] == ':') {
397 /* no multiple search path, just one location (common case) */
401 session_dirs.push_back (sp);
408 if (fspath[fspath.length()-1] != '/') {
412 fspath += sound_dir (false);
414 AudioFileSource::set_search_path (fspath);
415 SMFSource::set_search_path (fspath); // FIXME: should be different
422 while ((colon = remaining.find_first_of (':')) != string::npos) {
425 sp.path = remaining.substr (0, colon);
426 session_dirs.push_back (sp);
428 /* add sounds to file search path */
431 if (fspath[fspath.length()-1] != '/') {
434 fspath += sound_dir (false);
437 remaining = remaining.substr (colon+1);
440 if (remaining.length()) {
447 if (fspath[fspath.length()-1] != '/') {
450 fspath += sound_dir (false);
453 session_dirs.push_back (sp);
456 /* set the AudioFileSource search path */
458 AudioFileSource::set_search_path (fspath);
459 SMFSource::set_search_path (fspath); // FIXME: should be different
461 /* reset the round-robin soundfile path thingie */
463 last_rr_session_dir = session_dirs.begin();
467 Session::create (bool& new_session, string* mix_template, nframes_t initial_length)
471 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
472 error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
478 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
479 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
483 /* if this is is an existing session with an old "sounds" directory, just use it. see Session::sound_dir() for more details */
485 if (!Glib::file_test (old_sound_dir(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
489 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
490 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
495 dir = dead_sound_dir ();
497 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
498 error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
504 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
505 error << string_compose(_("Session: cannot create session export dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
510 /* check new_session so we don't overwrite an existing one */
513 std::string in_path = *mix_template;
515 ifstream in(in_path.c_str());
518 string out_path = _path;
520 out_path += _statefile_suffix;
522 ofstream out(out_path.c_str());
527 // okay, session is set up. Treat like normal saved
528 // session from now on.
534 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
540 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
547 /* set initial start + end point */
549 start_location->set_end (0);
550 _locations.add (start_location);
552 end_location->set_end (initial_length);
553 _locations.add (end_location);
555 _state_of_the_state = Clean;
557 if (save_state (_current_snapshot_name)) {
565 Session::load_diskstreams (const XMLNode& node)
568 XMLNodeConstIterator citer;
570 clist = node.children();
572 for (citer = clist.begin(); citer != clist.end(); ++citer) {
575 /* diskstreams added automatically by DiskstreamCreated handler */
576 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
577 boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
578 add_diskstream (dstream);
579 } else if ((*citer)->name() == "MidiDiskstream") {
580 boost::shared_ptr<MidiDiskstream> dstream (new MidiDiskstream (*this, **citer));
581 add_diskstream (dstream);
583 error << _("Session: unknown diskstream type in XML") << endmsg;
587 catch (failed_constructor& err) {
588 error << _("Session: could not load diskstream via XML state") << endmsg;
597 Session::maybe_write_autosave()
599 if (dirty() && record_status() != Recording) {
600 save_state("", true);
605 Session::remove_pending_capture_state ()
610 xml_path += _current_snapshot_name;
611 xml_path += _pending_suffix;
613 unlink (xml_path.c_str());
616 /** Rename a state file.
617 * @param snapshot_name Snapshot name.
620 Session::rename_state (string old_name, string new_name)
622 if (old_name == _current_snapshot_name || old_name == _name) {
623 /* refuse to rename the current snapshot or the "main" one */
627 const string old_xml_path = _path + old_name + _statefile_suffix;
628 const string new_xml_path = _path + new_name + _statefile_suffix;
630 if (rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
631 error << string_compose(_("could not rename snapshot %1 to %2"), old_name, new_name) << endmsg;
635 /** Remove a state file.
636 * @param snapshot_name Snapshot name.
639 Session::remove_state (string snapshot_name)
641 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
642 /* refuse to remove the current snapshot or the "main" one */
646 const string xml_path = _path + snapshot_name + _statefile_suffix;
648 /* make a backup copy of the state file */
649 const string bak_path = xml_path + ".bak";
650 if (g_file_test (xml_path.c_str(), G_FILE_TEST_EXISTS)) {
651 copy_file (xml_path, bak_path);
655 unlink (xml_path.c_str());
659 Session::save_state (string snapshot_name, bool pending)
665 if (_state_of_the_state & CannotSave) {
669 if (!_engine.connected ()) {
670 error << _("Ardour's audio engine is not connected and state saving would lose all I/O connections. Session not saved")
675 tree.set_root (&get_state());
677 if (snapshot_name.empty()) {
678 snapshot_name = _current_snapshot_name;
683 /* proper save: use _statefile_suffix (.ardour in English) */
685 xml_path += snapshot_name;
686 xml_path += _statefile_suffix;
688 /* make a backup copy of the old file */
692 if (g_file_test (xml_path.c_str(), G_FILE_TEST_EXISTS)) {
693 copy_file (xml_path, bak_path);
698 /* pending save: use _pending_suffix (.pending in English) */
700 xml_path += snapshot_name;
701 xml_path += _pending_suffix;
708 tmp_path += snapshot_name;
711 // cerr << "actually writing state to " << xml_path << endl;
713 if (!tree.write (tmp_path)) {
714 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
715 unlink (tmp_path.c_str());
720 if (rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
721 error << string_compose (_("could not rename temporary session file %1 to %2"), tmp_path, xml_path) << endmsg;
722 unlink (tmp_path.c_str());
729 save_history (snapshot_name);
731 bool was_dirty = dirty();
733 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
736 DirtyChanged (); /* EMIT SIGNAL */
739 StateSaved (snapshot_name); /* EMIT SIGNAL */
746 Session::restore_state (string snapshot_name)
748 if (load_state (snapshot_name) == 0) {
749 set_state (*state_tree->root());
756 Session::load_state (string snapshot_name)
765 state_was_pending = false;
767 /* check for leftover pending state from a crashed capture attempt */
770 xmlpath += snapshot_name;
771 xmlpath += _pending_suffix;
773 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
775 /* there is pending state from a crashed capture attempt */
777 if (AskAboutPendingState()) {
778 state_was_pending = true;
782 if (!state_was_pending) {
785 xmlpath += snapshot_name;
786 xmlpath += _statefile_suffix;
789 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
790 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
794 state_tree = new XMLTree;
798 if (!state_tree->read (xmlpath)) {
799 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
805 XMLNode& root (*state_tree->root());
807 if (root.name() != X_("Session")) {
808 error << string_compose (_("Session file %1 is not an Ardour session"), xmlpath) << endmsg;
814 const XMLProperty* prop;
817 if ((prop = root.property ("version")) == 0) {
818 /* no version implies very old version of Ardour */
822 major_version = atoi (prop->value()); // grab just the first number before the period
823 if (major_version < 2) {
832 backup_path += snapshot_name;
834 backup_path += _statefile_suffix;
836 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with Ardour versions before 2.0 from now on"),
837 xmlpath, backup_path)
840 copy_file (xmlpath, backup_path);
842 /* if it fails, don't worry. right? */
849 Session::load_options (const XMLNode& node)
853 LocaleGuard lg (X_("POSIX"));
855 Config->set_variables (node, ConfigVariableBase::Session);
857 if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
858 if ((prop = child->property ("val")) != 0) {
859 _end_location_is_free = (prop->value() == "yes");
867 Session::save_config_options_predicate (ConfigVariableBase::Owner owner) const
869 const ConfigVariableBase::Owner modified_by_session_or_user = (ConfigVariableBase::Owner)
870 (ConfigVariableBase::Session|ConfigVariableBase::Interface);
872 return owner & modified_by_session_or_user;
876 Session::get_options () const
879 LocaleGuard lg (X_("POSIX"));
881 XMLNode& option_root = Config->get_variables (mem_fun (*this, &Session::save_config_options_predicate));
883 child = option_root.add_child ("end-marker-is-free");
884 child->add_property ("val", _end_location_is_free ? "yes" : "no");
896 Session::get_template()
898 /* if we don't disable rec-enable, diskstreams
899 will believe they need to store their capture
900 sources in their state node.
903 disable_record (false);
909 Session::state(bool full_state)
911 XMLNode* node = new XMLNode("Session");
914 // store libardour version, just in case
916 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
917 libardour_major_version, libardour_minor_version, libardour_micro_version);
918 node->add_property("version", string(buf));
920 /* store configuration settings */
925 node->add_property ("name", _name);
927 if (session_dirs.size() > 1) {
931 vector<space_and_path>::iterator i = session_dirs.begin();
932 vector<space_and_path>::iterator next;
934 ++i; /* skip the first one */
938 while (i != session_dirs.end()) {
942 if (next != session_dirs.end()) {
952 child = node->add_child ("Path");
953 child->add_content (p);
957 /* save the ID counter */
959 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
960 node->add_property ("id-counter", buf);
962 /* various options */
964 node->add_child_nocopy (get_options());
966 child = node->add_child ("Sources");
969 Glib::Mutex::Lock sl (source_lock);
971 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
973 /* Don't save information about AudioFileSources that are empty */
975 boost::shared_ptr<AudioFileSource> fs;
977 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
979 /* Don't save sources that are empty, unless they're destructive (which are OK
980 if they are empty, because we will re-use them every time.)
983 if (!fs->destructive()) {
984 if (fs->length() == 0) {
990 child->add_child_nocopy (siter->second->get_state());
994 child = node->add_child ("Regions");
997 Glib::Mutex::Lock rl (region_lock);
999 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
1001 /* only store regions not attached to playlists */
1003 if (i->second->playlist() == 0) {
1004 child->add_child_nocopy (i->second->state (true));
1009 child = node->add_child ("DiskStreams");
1012 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1013 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1014 if (!(*i)->hidden()) {
1015 child->add_child_nocopy ((*i)->get_state());
1021 node->add_child_nocopy (_locations.get_state());
1023 // for a template, just create a new Locations, populate it
1024 // with the default start and end, and get the state for that.
1026 Location* start = new Location(0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
1027 Location* end = new Location(0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
1030 end->set_end(compute_initial_length());
1032 node->add_child_nocopy (loc.get_state());
1035 child = node->add_child ("Connections");
1037 Glib::Mutex::Lock lm (connection_lock);
1038 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1039 if (!(*i)->system_dependent()) {
1040 child->add_child_nocopy ((*i)->get_state());
1045 child = node->add_child ("Routes");
1047 boost::shared_ptr<RouteList> r = routes.reader ();
1049 RoutePublicOrderSorter cmp;
1050 RouteList public_order (*r);
1051 public_order.sort (cmp);
1053 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1054 if (!(*i)->hidden()) {
1056 child->add_child_nocopy ((*i)->get_state());
1058 child->add_child_nocopy ((*i)->get_template());
1065 child = node->add_child ("EditGroups");
1066 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1067 child->add_child_nocopy ((*i)->get_state());
1070 child = node->add_child ("MixGroups");
1071 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1072 child->add_child_nocopy ((*i)->get_state());
1075 child = node->add_child ("Playlists");
1076 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1077 if (!(*i)->hidden()) {
1078 if (!(*i)->empty()) {
1080 child->add_child_nocopy ((*i)->get_state());
1082 child->add_child_nocopy ((*i)->get_template());
1088 child = node->add_child ("UnusedPlaylists");
1089 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1090 if (!(*i)->hidden()) {
1091 if (!(*i)->empty()) {
1093 child->add_child_nocopy ((*i)->get_state());
1095 child->add_child_nocopy ((*i)->get_template());
1103 child = node->add_child ("Click");
1104 child->add_child_nocopy (_click_io->state (full_state));
1108 child = node->add_child ("NamedSelections");
1109 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1111 child->add_child_nocopy ((*i)->get_state());
1116 node->add_child_nocopy (_tempo_map->get_state());
1118 node->add_child_nocopy (get_control_protocol_state());
1121 node->add_child_copy (*_extra_xml);
1128 Session::get_control_protocol_state ()
1130 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1131 return cpm.get_state();
1135 Session::set_state (const XMLNode& node)
1139 const XMLProperty* prop;
1142 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1144 if (node.name() != X_("Session")){
1145 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1149 if ((prop = node.property ("name")) != 0) {
1150 _name = prop->value ();
1153 setup_raid_path(_path);
1155 if ((prop = node.property (X_("id-counter"))) != 0) {
1157 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1158 ID::init_counter (x);
1160 /* old sessions used a timebased counter, so fake
1161 the startup ID counter based on a standard
1166 ID::init_counter (now);
1170 IO::disable_ports ();
1171 IO::disable_connecting ();
1173 /* Object loading order:
1191 if (use_config_midi_ports ()) {
1194 if ((child = find_named_node (node, "extra")) != 0) {
1195 _extra_xml = new XMLNode (*child);
1198 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1199 load_options (*child);
1200 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1201 load_options (*child);
1203 error << _("Session: XML state has no options section") << endmsg;
1206 if ((child = find_named_node (node, "Locations")) == 0) {
1207 error << _("Session: XML state has no locations section") << endmsg;
1209 } else if (_locations.set_state (*child)) {
1215 if ((location = _locations.auto_loop_location()) != 0) {
1216 set_auto_loop_location (location);
1219 if ((location = _locations.auto_punch_location()) != 0) {
1220 set_auto_punch_location (location);
1223 if ((location = _locations.end_location()) == 0) {
1224 _locations.add (end_location);
1226 delete end_location;
1227 end_location = location;
1230 if ((location = _locations.start_location()) == 0) {
1231 _locations.add (start_location);
1233 delete start_location;
1234 start_location = location;
1237 AudioFileSource::set_header_position_offset (start_location->start());
1239 if ((child = find_named_node (node, "Sources")) == 0) {
1240 error << _("Session: XML state has no sources section") << endmsg;
1242 } else if (load_sources (*child)) {
1246 if ((child = find_named_node (node, "Regions")) == 0) {
1247 error << _("Session: XML state has no Regions section") << endmsg;
1249 } else if (load_regions (*child)) {
1253 if ((child = find_named_node (node, "Playlists")) == 0) {
1254 error << _("Session: XML state has no playlists section") << endmsg;
1256 } else if (load_playlists (*child)) {
1260 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1262 } else if (load_unused_playlists (*child)) {
1266 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1267 if (load_named_selections (*child)) {
1272 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1273 error << _("Session: XML state has no diskstreams section") << endmsg;
1275 } else if (load_diskstreams (*child)) {
1279 if ((child = find_named_node (node, "Connections")) == 0) {
1280 error << _("Session: XML state has no connections section") << endmsg;
1282 } else if (load_connections (*child)) {
1286 if ((child = find_named_node (node, "EditGroups")) == 0) {
1287 error << _("Session: XML state has no edit groups section") << endmsg;
1289 } else if (load_edit_groups (*child)) {
1293 if ((child = find_named_node (node, "MixGroups")) == 0) {
1294 error << _("Session: XML state has no mix groups section") << endmsg;
1296 } else if (load_mix_groups (*child)) {
1300 if ((child = find_named_node (node, "TempoMap")) == 0) {
1301 error << _("Session: XML state has no Tempo Map section") << endmsg;
1303 } else if (_tempo_map->set_state (*child)) {
1307 if ((child = find_named_node (node, "Routes")) == 0) {
1308 error << _("Session: XML state has no routes section") << endmsg;
1310 } else if (load_routes (*child)) {
1314 if ((child = find_named_node (node, "Click")) == 0) {
1315 warning << _("Session: XML state has no click section") << endmsg;
1316 } else if (_click_io) {
1317 _click_io->set_state (*child);
1320 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1321 ControlProtocolManager::instance().set_protocol_states (*child);
1324 /* here beginneth the second phase ... */
1326 StateReady (); /* EMIT SIGNAL */
1328 _state_of_the_state = Clean;
1330 if (state_was_pending) {
1331 save_state (_current_snapshot_name);
1332 remove_pending_capture_state ();
1333 state_was_pending = false;
1343 Session::load_routes (const XMLNode& node)
1346 XMLNodeConstIterator niter;
1347 RouteList new_routes;
1349 nlist = node.children();
1353 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1355 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1358 error << _("Session: cannot create Route from XML description.") << endmsg;
1362 new_routes.push_back (route);
1365 add_routes (new_routes);
1370 boost::shared_ptr<Route>
1371 Session::XMLRouteFactory (const XMLNode& node)
1373 if (node.name() != "Route") {
1374 return boost::shared_ptr<Route> ((Route*) 0);
1377 bool has_diskstream = (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0);
1379 DataType type = DataType::AUDIO;
1380 const XMLProperty* prop = node.property("default-type");
1382 type = DataType(prop->value());
1384 assert(type != DataType::NIL);
1386 if (has_diskstream) {
1387 if (type == DataType::AUDIO) {
1388 boost::shared_ptr<Route> ret (new AudioTrack (*this, node));
1391 boost::shared_ptr<Route> ret (new MidiTrack (*this, node));
1395 boost::shared_ptr<Route> ret (new Route (*this, node));
1401 Session::load_regions (const XMLNode& node)
1404 XMLNodeConstIterator niter;
1405 boost::shared_ptr<Region> region;
1407 nlist = node.children();
1411 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1412 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1413 error << _("Session: cannot create Region from XML description.") << endmsg;
1420 boost::shared_ptr<Region>
1421 Session::XMLRegionFactory (const XMLNode& node, bool full)
1423 const XMLProperty* type = node.property("type");
1427 if ( !type || type->value() == "audio" ) {
1429 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1431 } else if (type->value() == "midi") {
1433 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1437 } catch (failed_constructor& err) {
1438 return boost::shared_ptr<Region> ();
1441 return boost::shared_ptr<Region> ();
1444 boost::shared_ptr<AudioRegion>
1445 Session::XMLAudioRegionFactory (const XMLNode& node, bool full)
1447 const XMLProperty* prop;
1448 boost::shared_ptr<Source> source;
1449 boost::shared_ptr<AudioSource> as;
1451 uint32_t nchans = 1;
1454 if (node.name() != X_("Region")) {
1455 return boost::shared_ptr<AudioRegion>();
1458 if ((prop = node.property (X_("channels"))) != 0) {
1459 nchans = atoi (prop->value().c_str());
1463 if ((prop = node.property ("name")) == 0) {
1464 cerr << "no name for this region\n";
1468 if ((prop = node.property (X_("source-0"))) == 0) {
1469 if ((prop = node.property ("source")) == 0) {
1470 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1471 return boost::shared_ptr<AudioRegion>();
1475 PBD::ID s_id (prop->value());
1477 if ((source = source_by_id (s_id)) == 0) {
1478 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1479 return boost::shared_ptr<AudioRegion>();
1482 as = boost::dynamic_pointer_cast<AudioSource>(source);
1484 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1485 return boost::shared_ptr<AudioRegion>();
1488 sources.push_back (as);
1490 /* pickup other channels */
1492 for (uint32_t n=1; n < nchans; ++n) {
1493 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1494 if ((prop = node.property (buf)) != 0) {
1496 PBD::ID id2 (prop->value());
1498 if ((source = source_by_id (id2)) == 0) {
1499 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1500 return boost::shared_ptr<AudioRegion>();
1503 as = boost::dynamic_pointer_cast<AudioSource>(source);
1505 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1506 return boost::shared_ptr<AudioRegion>();
1508 sources.push_back (as);
1513 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1515 /* a final detail: this is the one and only place that we know how long missing files are */
1517 if (region->whole_file()) {
1518 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1519 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1521 sfp->set_length (region->length());
1531 catch (failed_constructor& err) {
1532 return boost::shared_ptr<AudioRegion>();
1536 boost::shared_ptr<MidiRegion>
1537 Session::XMLMidiRegionFactory (const XMLNode& node, bool full)
1539 const XMLProperty* prop;
1540 boost::shared_ptr<Source> source;
1541 boost::shared_ptr<MidiSource> ms;
1542 MidiRegion::SourceList sources;
1543 uint32_t nchans = 1;
1545 if (node.name() != X_("Region")) {
1546 return boost::shared_ptr<MidiRegion>();
1549 if ((prop = node.property (X_("channels"))) != 0) {
1550 nchans = atoi (prop->value().c_str());
1553 // Multiple midi channels? that's just crazy talk
1554 assert(nchans == 1);
1556 if ((prop = node.property (X_("source-0"))) == 0) {
1557 if ((prop = node.property ("source")) == 0) {
1558 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1559 return boost::shared_ptr<MidiRegion>();
1563 PBD::ID s_id (prop->value());
1565 if ((source = source_by_id (s_id)) == 0) {
1566 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1567 return boost::shared_ptr<MidiRegion>();
1570 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1572 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1573 return boost::shared_ptr<MidiRegion>();
1576 sources.push_back (ms);
1579 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1583 catch (failed_constructor& err) {
1584 return boost::shared_ptr<MidiRegion>();
1589 Session::get_sources_as_xml ()
1592 XMLNode* node = new XMLNode (X_("Sources"));
1593 Glib::Mutex::Lock lm (source_lock);
1595 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1596 node->add_child_nocopy (i->second->get_state());
1599 /* XXX get MIDI and other sources here */
1605 Session::path_from_region_name (string name, string identifier)
1607 char buf[PATH_MAX+1];
1609 string dir = discover_best_sound_dir ();
1611 for (n = 0; n < 999999; ++n) {
1612 if (identifier.length()) {
1613 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1614 identifier.c_str(), n);
1616 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1619 if (!Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
1624 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1633 Session::load_sources (const XMLNode& node)
1636 XMLNodeConstIterator niter;
1637 boost::shared_ptr<Source> source;
1639 nlist = node.children();
1643 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1646 if ((source = XMLSourceFactory (**niter)) == 0) {
1647 error << _("Session: cannot create Source from XML description.") << endmsg;
1651 catch (non_existent_source& err) {
1652 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1653 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1660 boost::shared_ptr<Source>
1661 Session::XMLSourceFactory (const XMLNode& node)
1663 if (node.name() != "Source") {
1664 return boost::shared_ptr<Source>();
1668 return SourceFactory::create (*this, node);
1671 catch (failed_constructor& err) {
1672 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1673 return boost::shared_ptr<Source>();
1678 Session::save_template (string template_name)
1681 string xml_path, bak_path, template_path;
1683 if (_state_of_the_state & CannotSave) {
1688 string dir = template_dir();
1690 if ((dp = opendir (dir.c_str()))) {
1693 if (g_mkdir_with_parents (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
1694 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1699 tree.set_root (&get_template());
1702 xml_path += template_name;
1703 xml_path += _template_suffix;
1705 ifstream in(xml_path.c_str());
1708 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1714 if (!tree.write (xml_path)) {
1715 error << _("mix template not saved") << endmsg;
1723 Session::rename_template (string old_name, string new_name)
1725 string old_path = template_dir() + old_name + _template_suffix;
1726 string new_path = template_dir() + new_name + _template_suffix;
1728 return rename (old_path.c_str(), new_path.c_str());
1732 Session::delete_template (string name)
1734 string template_path = template_dir();
1735 template_path += name;
1736 template_path += _template_suffix;
1738 return remove (template_path.c_str());
1742 Session::refresh_disk_space ()
1745 struct statfs statfsbuf;
1746 vector<space_and_path>::iterator i;
1747 Glib::Mutex::Lock lm (space_lock);
1750 /* get freespace on every FS that is part of the session path */
1752 _total_free_4k_blocks = 0;
1754 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1755 statfs ((*i).path.c_str(), &statfsbuf);
1757 scale = statfsbuf.f_bsize/4096.0;
1759 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1760 _total_free_4k_blocks += (*i).blocks;
1766 Session::ensure_sound_dir (string path, string& result)
1771 /* Ensure that the parent directory exists */
1773 if (g_mkdir_with_parents (path.c_str(), 0775)) {
1774 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
1778 /* Ensure that the sounds directory exists */
1782 result += sound_dir_name;
1784 if (g_mkdir_with_parents (result.c_str(), 0775)) {
1785 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
1791 dead += dead_sound_dir_name;
1793 if (g_mkdir_with_parents (dead.c_str(), 0775)) {
1794 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
1800 peak += peak_dir_name;
1802 if (g_mkdir_with_parents (peak.c_str(), 0775)) {
1803 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
1807 /* callers expect this to be terminated ... */
1814 Session::discover_best_sound_dir (bool destructive)
1816 vector<space_and_path>::iterator i;
1819 /* handle common case without system calls */
1821 if (session_dirs.size() == 1) {
1825 /* OK, here's the algorithm we're following here:
1827 We want to select which directory to use for
1828 the next file source to be created. Ideally,
1829 we'd like to use a round-robin process so as to
1830 get maximum performance benefits from splitting
1831 the files across multiple disks.
1833 However, in situations without much diskspace, an
1834 RR approach may end up filling up a filesystem
1835 with new files while others still have space.
1836 Its therefore important to pay some attention to
1837 the freespace in the filesystem holding each
1838 directory as well. However, if we did that by
1839 itself, we'd keep creating new files in the file
1840 system with the most space until it was as full
1841 as all others, thus negating any performance
1842 benefits of this RAID-1 like approach.
1844 So, we use a user-configurable space threshold. If
1845 there are at least 2 filesystems with more than this
1846 much space available, we use RR selection between them.
1847 If not, then we pick the filesystem with the most space.
1849 This gets a good balance between the two
1853 refresh_disk_space ();
1855 int free_enough = 0;
1857 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1858 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1863 if (free_enough >= 2) {
1865 bool found_it = false;
1867 /* use RR selection process, ensuring that the one
1871 i = last_rr_session_dir;
1874 if (++i == session_dirs.end()) {
1875 i = session_dirs.begin();
1878 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1879 if (ensure_sound_dir ((*i).path, result) == 0) {
1880 last_rr_session_dir = i;
1886 } while (i != last_rr_session_dir);
1889 result = sound_dir();
1894 /* pick FS with the most freespace (and that
1895 seems to actually work ...)
1898 vector<space_and_path> sorted;
1899 space_and_path_ascending_cmp cmp;
1901 sorted = session_dirs;
1902 sort (sorted.begin(), sorted.end(), cmp);
1904 for (i = sorted.begin(); i != sorted.end(); ++i) {
1905 if (ensure_sound_dir ((*i).path, result) == 0) {
1906 last_rr_session_dir = i;
1911 /* if the above fails, fall back to the most simplistic solution */
1913 if (i == sorted.end()) {
1922 Session::load_playlists (const XMLNode& node)
1925 XMLNodeConstIterator niter;
1926 boost::shared_ptr<Playlist> playlist;
1928 nlist = node.children();
1932 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1934 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1935 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1943 Session::load_unused_playlists (const XMLNode& node)
1946 XMLNodeConstIterator niter;
1947 boost::shared_ptr<Playlist> playlist;
1949 nlist = node.children();
1953 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1955 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1956 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1960 // now manually untrack it
1962 track_playlist (false, boost::weak_ptr<Playlist> (playlist));
1968 boost::shared_ptr<Playlist>
1969 Session::XMLPlaylistFactory (const XMLNode& node)
1972 return PlaylistFactory::create (*this, node);
1975 catch (failed_constructor& err) {
1976 return boost::shared_ptr<Playlist>();
1981 Session::load_named_selections (const XMLNode& node)
1984 XMLNodeConstIterator niter;
1987 nlist = node.children();
1991 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1993 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
1994 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2002 Session::XMLNamedSelectionFactory (const XMLNode& node)
2005 return new NamedSelection (*this, node);
2008 catch (failed_constructor& err) {
2014 Session::dead_sound_dir () const
2017 res += dead_sound_dir_name;
2023 Session::old_sound_dir (bool with_path) const
2031 res += old_sound_dir_name;
2037 Session::sound_dir (bool with_path) const
2048 res += interchange_dir_name;
2050 res += legalize_for_path (_name);
2052 res += sound_dir_name;
2060 /* if this already exists, don't check for the old session sound directory */
2062 if (Glib::file_test (full, Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
2066 /* possibly support old session structure */
2069 string old_withpath;
2071 old_nopath += old_sound_dir_name;
2074 old_withpath = _path;
2075 old_withpath += old_sound_dir_name;
2077 if (Glib::file_test (old_withpath.c_str(), Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
2079 return old_withpath;
2084 /* ok, old "sounds" directory isn't there, return the new path */
2090 Session::peak_dir () const
2093 res += peak_dir_name;
2099 Session::automation_dir () const
2102 res += "automation/";
2107 Session::template_dir ()
2109 string path = get_user_ardour_path();
2110 path += "templates/";
2116 Session::export_dir () const
2119 res += export_dir_name;
2125 Session::suffixed_search_path (string suffix, bool data)
2129 path += get_user_ardour_path();
2130 if (path[path.length()-1] != ':') {
2135 path += get_system_data_path();
2137 path += get_system_module_path();
2140 vector<string> split_path;
2142 split (path, split_path, ':');
2145 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2150 if (distance (i, split_path.end()) != 1) {
2159 Session::template_path ()
2161 return suffixed_search_path (X_("templates"), true);
2165 Session::control_protocol_path ()
2167 return suffixed_search_path (X_("surfaces"), false);
2171 Session::load_connections (const XMLNode& node)
2173 XMLNodeList nlist = node.children();
2174 XMLNodeConstIterator niter;
2178 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2179 if ((*niter)->name() == "InputConnection") {
2180 add_connection (new ARDOUR::InputConnection (**niter));
2181 } else if ((*niter)->name() == "OutputConnection") {
2182 add_connection (new ARDOUR::OutputConnection (**niter));
2184 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2193 Session::load_edit_groups (const XMLNode& node)
2195 return load_route_groups (node, true);
2199 Session::load_mix_groups (const XMLNode& node)
2201 return load_route_groups (node, false);
2205 Session::load_route_groups (const XMLNode& node, bool edit)
2207 XMLNodeList nlist = node.children();
2208 XMLNodeConstIterator niter;
2213 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2214 if ((*niter)->name() == "RouteGroup") {
2216 rg = add_edit_group ("");
2217 rg->set_state (**niter);
2219 rg = add_mix_group ("");
2220 rg->set_state (**niter);
2229 state_file_filter (const string &str, void *arg)
2231 return (str.length() > strlen(Session::statefile_suffix()) &&
2232 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2236 bool operator()(const string* a, const string* b) {
2242 remove_end(string* state)
2244 string statename(*state);
2246 string::size_type start,end;
2247 if ((start = statename.find_last_of ('/')) != string::npos) {
2248 statename = statename.substr (start+1);
2251 if ((end = statename.rfind(".ardour")) == string::npos) {
2252 end = statename.length();
2255 return new string(statename.substr (0, end));
2259 Session::possible_states (string path)
2261 PathScanner scanner;
2262 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2264 transform(states->begin(), states->end(), states->begin(), remove_end);
2267 sort (states->begin(), states->end(), cmp);
2273 Session::possible_states () const
2275 return possible_states(_path);
2279 Session::auto_save()
2281 save_state (_current_snapshot_name);
2285 Session::add_edit_group (string name)
2287 RouteGroup* rg = new RouteGroup (*this, name);
2288 edit_groups.push_back (rg);
2289 edit_group_added (rg); /* EMIT SIGNAL */
2295 Session::add_mix_group (string name)
2297 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2298 mix_groups.push_back (rg);
2299 mix_group_added (rg); /* EMIT SIGNAL */
2305 Session::remove_edit_group (RouteGroup& rg)
2307 list<RouteGroup*>::iterator i;
2309 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2310 (*i)->apply (&Route::drop_edit_group, this);
2311 edit_groups.erase (i);
2312 edit_group_removed (); /* EMIT SIGNAL */
2319 Session::remove_mix_group (RouteGroup& rg)
2321 list<RouteGroup*>::iterator i;
2323 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2324 (*i)->apply (&Route::drop_mix_group, this);
2325 mix_groups.erase (i);
2326 mix_group_removed (); /* EMIT SIGNAL */
2333 Session::mix_group_by_name (string name)
2335 list<RouteGroup *>::iterator i;
2337 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2338 if ((*i)->name() == name) {
2346 Session::edit_group_by_name (string name)
2348 list<RouteGroup *>::iterator i;
2350 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2351 if ((*i)->name() == name) {
2359 Session::begin_reversible_command (string name)
2361 current_trans = new UndoTransaction;
2362 current_trans->set_name (name);
2366 Session::commit_reversible_command (Command *cmd)
2371 current_trans->add_command (cmd);
2374 gettimeofday (&now, 0);
2375 current_trans->set_timestamp (now);
2377 _history.add (current_trans);
2380 Session::GlobalRouteBooleanState
2381 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2383 GlobalRouteBooleanState s;
2384 boost::shared_ptr<RouteList> r = routes.reader ();
2386 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2387 if (!(*i)->hidden()) {
2388 RouteBooleanState v;
2391 Route* r = (*i).get();
2392 v.second = (r->*method)();
2401 Session::GlobalRouteMeterState
2402 Session::get_global_route_metering ()
2404 GlobalRouteMeterState s;
2405 boost::shared_ptr<RouteList> r = routes.reader ();
2407 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2408 if (!(*i)->hidden()) {
2412 v.second = (*i)->meter_point();
2422 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2424 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2426 boost::shared_ptr<Route> r = (i->first.lock());
2429 r->set_meter_point (i->second, arg);
2435 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2437 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2439 boost::shared_ptr<Route> r = (i->first.lock());
2442 Route* rp = r.get();
2443 (rp->*method) (i->second, arg);
2449 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2451 set_global_route_boolean (s, &Route::set_mute, src);
2455 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2457 set_global_route_boolean (s, &Route::set_solo, src);
2461 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2463 set_global_route_boolean (s, &Route::set_record_enable, src);
2468 Session::global_mute_memento (void* src)
2470 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2474 Session::global_metering_memento (void* src)
2476 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2480 Session::global_solo_memento (void* src)
2482 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2486 Session::global_record_enable_memento (void* src)
2488 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2493 template_filter (const string &str, void *arg)
2495 return (str.length() > strlen(Session::template_suffix()) &&
2496 str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
2500 Session::get_template_list (list<string> &template_names)
2502 vector<string *> *templates;
2503 PathScanner scanner;
2506 path = template_path ();
2508 templates = scanner (path, template_filter, 0, false, true);
2510 vector<string*>::iterator i;
2511 for (i = templates->begin(); i != templates->end(); ++i) {
2512 string fullpath = *(*i);
2515 start = fullpath.find_last_of ('/') + 1;
2516 if ((end = fullpath.find_last_of ('.')) <0) {
2517 end = fullpath.length();
2520 template_names.push_back(fullpath.substr(start, (end-start)));
2525 Session::read_favorite_dirs (FavoriteDirs & favs)
2527 string path = get_user_ardour_path();
2528 path += "/favorite_dirs";
2530 ifstream fav (path.c_str());
2535 if (errno != ENOENT) {
2536 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2547 getline(fav, newfav);
2553 favs.push_back (newfav);
2560 Session::write_favorite_dirs (FavoriteDirs & favs)
2562 string path = get_user_ardour_path();
2563 path += "/favorite_dirs";
2565 ofstream fav (path.c_str());
2571 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2572 fav << (*i) << endl;
2579 accept_all_non_peak_files (const string& path, void *arg)
2581 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2585 accept_all_state_files (const string& path, void *arg)
2587 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2591 Session::find_all_sources (string path, set<string>& result)
2596 if (!tree.read (path)) {
2600 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2605 XMLNodeConstIterator niter;
2607 nlist = node->children();
2611 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2615 if ((prop = (*niter)->property (X_("name"))) == 0) {
2619 if (prop->value()[0] == '/') {
2620 /* external file, ignore */
2624 string path = _path; /* /-terminated */
2625 path += sound_dir_name;
2627 path += prop->value();
2629 result.insert (path);
2636 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2638 PathScanner scanner;
2639 vector<string*>* state_files;
2641 string this_snapshot_path;
2647 if (ripped[ripped.length()-1] == '/') {
2648 ripped = ripped.substr (0, ripped.length() - 1);
2651 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2653 if (state_files == 0) {
2658 this_snapshot_path = _path;
2659 this_snapshot_path += _current_snapshot_name;
2660 this_snapshot_path += _statefile_suffix;
2662 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2664 if (exclude_this_snapshot && **i == this_snapshot_path) {
2668 if (find_all_sources (**i, result) < 0) {
2676 struct RegionCounter {
2677 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2678 AudioSourceList::iterator iter;
2679 boost::shared_ptr<Region> region;
2682 RegionCounter() : count (0) {}
2686 Session::cleanup_sources (Session::cleanup_report& rep)
2688 vector<boost::shared_ptr<Source> > dead_sources;
2689 vector<boost::shared_ptr<Playlist> > playlists_tbd;
2690 PathScanner scanner;
2692 vector<space_and_path>::iterator i;
2693 vector<space_and_path>::iterator nexti;
2694 vector<string*>* soundfiles;
2695 vector<string> unused;
2696 set<string> all_sources;
2701 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2703 /* step 1: consider deleting all unused playlists */
2705 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2708 status = AskAboutPlaylistDeletion (*x);
2717 playlists_tbd.push_back (*x);
2721 /* leave it alone */
2726 /* now delete any that were marked for deletion */
2728 for (vector<boost::shared_ptr<Playlist> >::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2729 (*x)->drop_references ();
2732 playlists_tbd.clear ();
2734 /* step 2: find all un-used sources */
2739 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2741 SourceMap::iterator tmp;
2746 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2750 if (!i->second->used() && i->second->length() > 0) {
2751 dead_sources.push_back (i->second);
2752 i->second->GoingAway();
2758 /* build a list of all the possible sound directories for the session */
2760 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2765 sound_path += (*i).path;
2766 sound_path += sound_dir (false);
2768 if (nexti != session_dirs.end()) {
2775 /* now do the same thing for the files that ended up in the sounds dir(s)
2776 but are not referenced as sources in any snapshot.
2779 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2781 if (soundfiles == 0) {
2785 /* find all sources, but don't use this snapshot because the
2786 state file on disk still references sources we may have already
2790 find_all_sources_across_snapshots (all_sources, true);
2792 /* add our current source list
2795 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2796 boost::shared_ptr<AudioFileSource> fs;
2798 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (i->second)) != 0) {
2799 all_sources.insert (fs->path());
2803 char tmppath1[PATH_MAX+1];
2804 char tmppath2[PATH_MAX+1];
2806 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2811 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2813 realpath(spath.c_str(), tmppath1);
2814 realpath((*i).c_str(), tmppath2);
2816 if (strcmp(tmppath1, tmppath2) == 0) {
2823 unused.push_back (spath);
2827 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2829 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2830 struct stat statbuf;
2832 rep.paths.push_back (*x);
2833 if (stat ((*x).c_str(), &statbuf) == 0) {
2834 rep.space += statbuf.st_size;
2839 /* don't move the file across filesystems, just
2840 stick it in the `dead_sound_dir_name' directory
2841 on whichever filesystem it was already on.
2844 if ((*x).find ("/sounds/") != string::npos) {
2846 /* old school, go up 1 level */
2848 newpath = Glib::path_get_dirname (*x); // "sounds"
2849 newpath = Glib::path_get_dirname (newpath); // "session-name"
2853 /* new school, go up 4 levels */
2855 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2856 newpath = Glib::path_get_dirname (newpath); // "session-name"
2857 newpath = Glib::path_get_dirname (newpath); // "interchange"
2858 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2862 newpath += dead_sound_dir_name;
2864 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2865 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2870 newpath += Glib::path_get_basename ((*x));
2872 if (access (newpath.c_str(), F_OK) == 0) {
2874 /* the new path already exists, try versioning */
2876 char buf[PATH_MAX+1];
2880 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2883 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2884 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2888 if (version == 999) {
2889 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2893 newpath = newpath_v;
2898 /* it doesn't exist, or we can't read it or something */
2902 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2903 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2904 (*x), newpath, strerror (errno))
2909 /* see if there an easy to find peakfile for this file, and remove it.
2912 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2913 peakpath += ".peak";
2915 if (access (peakpath.c_str(), W_OK) == 0) {
2916 if (::unlink (peakpath.c_str()) != 0) {
2917 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2918 peakpath, _path, strerror (errno))
2920 /* try to back out */
2921 rename (newpath.c_str(), _path.c_str());
2929 /* dump the history list */
2933 /* save state so we don't end up a session file
2934 referring to non-existent sources.
2940 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2945 Session::cleanup_trash_sources (Session::cleanup_report& rep)
2947 vector<space_and_path>::iterator i;
2948 string dead_sound_dir;
2949 struct dirent* dentry;
2950 struct stat statbuf;
2956 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2958 dead_sound_dir = (*i).path;
2959 dead_sound_dir += dead_sound_dir_name;
2961 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2965 while ((dentry = readdir (dead)) != 0) {
2967 /* avoid '.' and '..' */
2969 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2970 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2976 fullpath = dead_sound_dir;
2978 fullpath += dentry->d_name;
2980 if (stat (fullpath.c_str(), &statbuf)) {
2984 if (!S_ISREG (statbuf.st_mode)) {
2988 if (unlink (fullpath.c_str())) {
2989 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2990 fullpath, strerror (errno))
2994 rep.paths.push_back (dentry->d_name);
2995 rep.space += statbuf.st_size;
3006 Session::set_dirty ()
3008 bool was_dirty = dirty();
3010 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3013 DirtyChanged(); /* EMIT SIGNAL */
3019 Session::set_clean ()
3021 bool was_dirty = dirty();
3023 _state_of_the_state = Clean;
3026 DirtyChanged(); /* EMIT SIGNAL */
3031 Session::set_deletion_in_progress ()
3033 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3037 Session::add_controllable (Controllable* c)
3039 /* this adds a controllable to the list managed by the Session.
3040 this is a subset of those managed by the Controllable class
3041 itself, and represents the only ones whose state will be saved
3042 as part of the session.
3045 Glib::Mutex::Lock lm (controllables_lock);
3046 controllables.insert (c);
3050 Session::remove_controllable (Controllable* c)
3052 if (_state_of_the_state | Deletion) {
3056 Glib::Mutex::Lock lm (controllables_lock);
3058 Controllables::iterator x = controllables.find (c);
3060 if (x != controllables.end()) {
3061 controllables.erase (x);
3066 Session::controllable_by_id (const PBD::ID& id)
3068 Glib::Mutex::Lock lm (controllables_lock);
3070 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3071 if ((*i)->id() == id) {
3080 Session::add_instant_xml (XMLNode& node, const std::string& dir)
3082 Stateful::add_instant_xml (node, dir);
3083 Config->add_instant_xml (node, get_user_ardour_path());
3088 Session::save_history (string snapshot_name)
3094 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3096 if (snapshot_name.empty()) {
3097 snapshot_name = _current_snapshot_name;
3100 xml_path = _path + snapshot_name + ".history";
3102 bak_path = xml_path + ".bak";
3104 if ((access (xml_path.c_str(), F_OK) == 0) &&
3105 (rename (xml_path.c_str(), bak_path.c_str())))
3107 error << _("could not backup old history file, current history not saved.") << endmsg;
3111 if (!tree.write (xml_path))
3113 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3115 /* don't leave a corrupt file lying around if it is
3119 if (unlink (xml_path.c_str())) {
3120 error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
3122 if (rename (bak_path.c_str(), xml_path.c_str()))
3124 error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;
3135 Session::restore_history (string snapshot_name)
3140 if (snapshot_name.empty()) {
3141 snapshot_name = _current_snapshot_name;
3145 xmlpath = _path + snapshot_name + ".history";
3146 cerr << string_compose(_("Loading history from '%1'."), xmlpath) << endmsg;
3148 if (access (xmlpath.c_str(), F_OK)) {
3149 info << string_compose (_("%1: no history file \"%2\" for this session."), _name, xmlpath) << endmsg;
3153 if (!tree.read (xmlpath)) {
3154 error << string_compose (_("Could not understand session history file \"%1\""), xmlpath) << endmsg;
3158 /* replace history */
3161 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3164 UndoTransaction* ut = new UndoTransaction ();
3167 ut->set_name(t->property("name")->value());
3168 stringstream ss(t->property("tv_sec")->value());
3170 ss.str(t->property("tv_usec")->value());
3172 ut->set_timestamp(tv);
3174 for (XMLNodeConstIterator child_it = t->children().begin();
3175 child_it != t->children().end();
3178 XMLNode *n = *child_it;
3181 if (n->name() == "MementoCommand" ||
3182 n->name() == "MementoUndoCommand" ||
3183 n->name() == "MementoRedoCommand") {
3185 if ((c = memento_command_factory(n))) {
3189 } else if (n->name() == X_("GlobalRouteStateCommand")) {
3191 if ((c = global_state_command_factory (*n))) {
3192 ut->add_command (c);
3197 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3208 Session::config_changed (const char* parameter_name)
3210 #define PARAM_IS(x) (!strcmp (parameter_name, (x)))
3212 if (PARAM_IS ("seamless-loop")) {
3214 } else if (PARAM_IS ("rf-speed")) {
3216 } else if (PARAM_IS ("auto-loop")) {
3218 } else if (PARAM_IS ("auto-input")) {
3220 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3221 /* auto-input only makes a difference if we're rolling */
3223 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3225 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3226 if ((*i)->record_enabled ()) {
3227 (*i)->monitor_input (!Config->get_auto_input());
3232 } else if (PARAM_IS ("punch-in")) {
3236 if ((location = _locations.auto_punch_location()) != 0) {
3238 if (Config->get_punch_in ()) {
3239 replace_event (Event::PunchIn, location->start());
3241 remove_event (location->start(), Event::PunchIn);
3245 } else if (PARAM_IS ("punch-out")) {
3249 if ((location = _locations.auto_punch_location()) != 0) {
3251 if (Config->get_punch_out()) {
3252 replace_event (Event::PunchOut, location->end());
3254 clear_events (Event::PunchOut);
3258 } else if (PARAM_IS ("edit-mode")) {
3260 Glib::Mutex::Lock lm (playlist_lock);
3262 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3263 (*i)->set_edit_mode (Config->get_edit_mode ());
3266 } else if (PARAM_IS ("use-video-sync")) {
3268 waiting_for_sync_offset = Config->get_use_video_sync();
3270 } else if (PARAM_IS ("mmc-control")) {
3272 //poke_midi_thread ();
3274 } else if (PARAM_IS ("mmc-device-id")) {
3277 mmc->set_device_id (Config->get_mmc_device_id());
3280 } else if (PARAM_IS ("midi-control")) {
3282 //poke_midi_thread ();
3284 } else if (PARAM_IS ("raid-path")) {
3286 setup_raid_path (Config->get_raid_path());
3288 } else if (PARAM_IS ("smpte-format")) {
3292 } else if (PARAM_IS ("video-pullup")) {
3296 } else if (PARAM_IS ("seamless-loop")) {
3298 if (play_loop && transport_rolling()) {
3299 // to reset diskstreams etc
3300 request_play_loop (true);
3303 } else if (PARAM_IS ("rf-speed")) {
3305 cumulative_rf_motion = 0;
3308 } else if (PARAM_IS ("click-sound")) {
3310 setup_click_sounds (1);
3312 } else if (PARAM_IS ("click-emphasis-sound")) {
3314 setup_click_sounds (-1);
3316 } else if (PARAM_IS ("clicking")) {
3318 if (Config->get_clicking()) {
3319 if (_click_io && click_data) { // don't require emphasis data
3326 } else if (PARAM_IS ("send-mtc")) {
3328 /* only set the internal flag if we have
3332 if (_mtc_port != 0) {
3333 session_send_mtc = Config->get_send_mtc();
3334 if (session_send_mtc) {
3335 /* mark us ready to send */
3336 next_quarter_frame_to_send = 0;
3339 session_send_mtc = false;
3342 } else if (PARAM_IS ("send-mmc")) {
3344 /* only set the internal flag if we have
3348 if (_mmc_port != 0) {
3349 session_send_mmc = Config->get_send_mmc();
3352 session_send_mmc = false;
3355 } else if (PARAM_IS ("midi-feedback")) {
3357 /* only set the internal flag if we have
3361 if (_mtc_port != 0) {
3362 session_midi_feedback = Config->get_midi_feedback();
3365 } else if (PARAM_IS ("jack-time-master")) {
3367 engine().reset_timebase ();
3369 } else if (PARAM_IS ("native-file-header-format")) {
3371 if (!first_file_header_format_reset) {
3372 reset_native_file_format ();
3375 first_file_header_format_reset = false;
3377 } else if (PARAM_IS ("native-file-data-format")) {
3379 if (!first_file_data_format_reset) {
3380 reset_native_file_format ();
3383 first_file_data_format_reset = false;
3385 } else if (PARAM_IS ("slave-source")) {
3386 set_slave_source (Config->get_slave_source());
3387 } else if (PARAM_IS ("remote-model")) {
3388 set_remote_control_ids ();