X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=libs%2Fardour%2Fsession_state.cc;h=b6569ba00edbc36765ff5a6d3f4980fdc5e93d41;hb=422e462c12bcea577a530bbdf4c2b651ba9f7ea4;hp=3c7ec0f780a94a1ec10ae7c24f1215caf21f7e8b;hpb=009c7a9e44d65184d6b6c613569decc9d93fb490;p=ardour.git diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 3c7ec0f780..b6569ba00e 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -46,10 +46,15 @@ #include #endif +#ifdef HAVE_SYS_STATVFS_H +#include +#endif + #include +#include #include -#include +#include #include @@ -57,49 +62,41 @@ #include "midi++/port.h" #include "midi++/manager.h" +#include "evoral/SMF.hpp" + #include "pbd/boost_debug.h" #include "pbd/basename.h" #include "pbd/controllable_descriptor.h" #include "pbd/enumwriter.h" #include "pbd/error.h" +#include "pbd/file_utils.h" #include "pbd/pathscanner.h" #include "pbd/pthread_utils.h" -#include "pbd/search_path.h" #include "pbd/stacktrace.h" #include "pbd/convert.h" #include "pbd/clear_dir.h" #include "ardour/amp.h" #include "ardour/audio_diskstream.h" -#include "ardour/audio_playlist_source.h" #include "ardour/audio_track.h" #include "ardour/audioengine.h" #include "ardour/audiofilesource.h" -#include "ardour/audioplaylist.h" #include "ardour/audioregion.h" -#include "ardour/auditioner.h" #include "ardour/automation_control.h" -#include "ardour/buffer.h" #include "ardour/butler.h" -#include "ardour/configuration.h" #include "ardour/control_protocol_manager.h" -#include "ardour/crossfade.h" -#include "ardour/cycle_timer.h" #include "ardour/directory_names.h" #include "ardour/filename_extensions.h" -#include "ardour/io_processor.h" #include "ardour/location.h" -#include "ardour/midi_diskstream.h" #include "ardour/midi_model.h" #include "ardour/midi_patch_manager.h" -#include "ardour/midi_playlist.h" #include "ardour/midi_region.h" #include "ardour/midi_source.h" #include "ardour/midi_track.h" -#include "ardour/named_selection.h" #include "ardour/pannable.h" -#include "ardour/processor.h" +#include "ardour/playlist_factory.h" #include "ardour/port.h" +#include "ardour/processor.h" #include "ardour/proxy_controllable.h" #include "ardour/recent_sessions.h" #include "ardour/region_factory.h" @@ -108,13 +105,9 @@ #include "ardour/session.h" #include "ardour/session_directory.h" #include "ardour/session_metadata.h" -#include "ardour/session_state_utils.h" #include "ardour/session_playlists.h" -#include "ardour/session_utils.h" +#include "ardour/session_state_utils.h" #include "ardour/silentfilesource.h" -#include "ardour/slave.h" -#include "ardour/smf_source.h" -#include "ardour/sndfile_helpers.h" #include "ardour/sndfilesource.h" #include "ardour/source_factory.h" #include "ardour/speakers.h" @@ -122,10 +115,6 @@ #include "ardour/tempo.h" #include "ardour/ticker.h" #include "ardour/user_bundle.h" -#include "ardour/utils.h" -#include "ardour/utils.h" -#include "ardour/version.h" -#include "ardour/playlist_factory.h" #include "control_protocol/control_protocol.h" @@ -179,6 +168,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) _solo_isolated_cnt = 0; g_atomic_int_set (&processing_prohibited, 0); _transport_speed = 0; + _default_transport_speed = 1.0; _last_transport_speed = 0; _target_transport_speed = 0; auto_play_legal = false; @@ -216,6 +206,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) _play_range = false; _exporting = false; pending_abort = false; + _adding_routes_in_progress = false; destructive_index = 0; first_file_data_format_reset = true; first_file_header_format_reset = true; @@ -232,7 +223,6 @@ Session::first_stage_init (string fullpath, string snapshot_name) /* default short fade = 15ms */ - Crossfade::set_short_xfade_length ((framecnt_t) floor (config.get_short_xfade_seconds() * frame_rate())); SndFileSource::setup_standard_crossfades (*this, frame_rate()); last_mmc_step.tv_sec = 0; @@ -298,7 +288,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) int Session::second_stage_init () { - AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string()); + AudioFileSource::set_peak_dir (_session_dir->peak_path()); if (!_is_new) { if (load_state (_current_snapshot_name)) { @@ -377,6 +367,7 @@ Session::second_stage_init () MIDI::Name::MidiPatchManager::instance().set_session (this); + ltc_tx_initialize(); /* initial program change will be delivered later; see ::config_changed() */ _state_of_the_state = Clean; @@ -402,7 +393,7 @@ Session::raid_path () const SearchPath raid_search_path; for (vector::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) { - raid_search_path += sys::path((*i).path); + raid_search_path += (*i).path; } return raid_search_path.to_string (); @@ -425,7 +416,7 @@ Session::setup_raid_path (string path) SearchPath midi_search_path; for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) { - sp.path = (*i).to_string (); + sp.path = *i; sp.blocks = 0; // not needed session_dirs.push_back (sp); @@ -443,7 +434,7 @@ bool Session::path_is_within_session (const std::string& path) { for (vector::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) { - if (path.find ((*i).path) == 0) { + if (PBD::path_is_within (i->path, path)) { return true; } } @@ -455,35 +446,35 @@ Session::ensure_subdirs () { string dir; - dir = session_directory().peak_path().to_string(); + dir = session_directory().peak_path(); if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) { error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg; return -1; } - dir = session_directory().sound_path().to_string(); + dir = session_directory().sound_path(); if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) { error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg; return -1; } - dir = session_directory().midi_path().to_string(); + dir = session_directory().midi_path(); if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) { error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg; return -1; } - dir = session_directory().dead_path().to_string(); + dir = session_directory().dead_path(); if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) { error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg; return -1; } - dir = session_directory().export_path().to_string(); + dir = session_directory().export_path(); if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) { error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg; @@ -529,7 +520,7 @@ Session::create (const string& session_template, BusProfile* bus_profile) return -1; } - _writable = exists_and_writable (sys::path (_path)); + _writable = exists_and_writable (_path); if (!session_template.empty()) { std::string in_path = session_template_dir_to_file (session_template); @@ -548,9 +539,8 @@ Session::create (const string& session_template, BusProfile* bus_profile) _is_new = false; /* Copy plugin state files from template to new session */ - sys::path template_plugins = session_template; - template_plugins /= X_("plugins"); - sys::copy_files (template_plugins, plugins_dir ()); + std::string template_plugins = Glib::build_filename (session_template, X_("plugins")); + copy_files (template_plugins, plugins_dir ()); return 0; @@ -568,10 +558,6 @@ Session::create (const string& session_template, BusProfile* bus_profile) } - /* Instantiate metadata */ - - _metadata = new SessionMetadata (); - /* set initial start + end point */ _state_of_the_state = Clean; @@ -592,7 +578,7 @@ Session::create (const string& session_template, BusProfile* bus_profile) // boost_debug_shared_ptr_mark_interesting (r.get(), "Route"); #endif { - Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ()); + Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ()); r->input()->ensure_io (count, false, this); r->output()->ensure_io (count, false, this); } @@ -605,7 +591,7 @@ Session::create (const string& session_template, BusProfile* bus_profile) } if (!rl.empty()) { - add_routes (rl, false, false); + add_routes (rl, false, false, false); } /* this allows the user to override settings with an environment variable. @@ -640,18 +626,15 @@ Session::maybe_write_autosave() void Session::remove_pending_capture_state () { - sys::path pending_state_file_path(_session_dir->root_path()); + std::string pending_state_file_path(_session_dir->root_path()); - pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix; + pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix); - try - { - sys::remove (pending_state_file_path); - } - catch(sys::filesystem_error& ex) - { - error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"), - pending_state_file_path.to_string(), ex.what()) << endmsg; + if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return; + + if (g_remove (pending_state_file_path.c_str()) != 0) { + error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"), + pending_state_file_path, g_strerror (errno)) << endmsg; } } @@ -670,17 +653,12 @@ Session::rename_state (string old_name, string new_name) const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix; const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix; - const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename; - const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename; + const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename)); + const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename)); - try - { - sys::rename (old_xml_path, new_xml_path); - } - catch (const sys::filesystem_error& err) - { + if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) { error << string_compose(_("could not rename snapshot %1 to %2 (%3)"), - old_name, new_name, err.what()) << endmsg; + old_name, new_name, g_strerror(errno)) << endmsg; } } @@ -690,14 +668,14 @@ Session::rename_state (string old_name, string new_name) void Session::remove_state (string snapshot_name) { - if (snapshot_name == _current_snapshot_name || snapshot_name == _name) { + if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) { // refuse to remove the current snapshot or the "main" one return; } - sys::path xml_path(_session_dir->root_path()); + std::string xml_path(_session_dir->root_path()); - xml_path /= legalize_for_path (snapshot_name) + statefile_suffix; + xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix); if (!create_backup_file (xml_path)) { // don't remove it if a backup can't be made @@ -706,7 +684,10 @@ Session::remove_state (string snapshot_name) } // and delete it - sys::remove (xml_path); + if (g_remove (xml_path.c_str()) != 0) { + error << string_compose(_("Could not remove session file at path \"%1\" (%2)"), + xml_path, g_strerror (errno)) << endmsg; + } } #ifdef HAVE_JACK_SESSION @@ -739,13 +720,14 @@ Session::jack_session_event (jack_session_event_t * event) if (save_state (timebuf)) { event->flags = JackSessionSaveError; } else { - sys::path xml_path (_session_dir->root_path()); - xml_path /= legalize_for_path (timebuf) + statefile_suffix; + std::string xml_path (_session_dir->root_path()); + std::string legalized_filename = legalize_for_path (timebuf) + statefile_suffix; + xml_path = Glib::build_filename (xml_path, legalized_filename); string cmd ("ardour3 -P -U "); cmd += event->client_uuid; cmd += " \""; - cmd += xml_path.to_string(); + cmd += xml_path; cmd += '\"'; event->command_line = strdup (cmd.c_str()); @@ -767,7 +749,7 @@ int Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot) { XMLTree tree; - sys::path xml_path(_session_dir->root_path()); + std::string xml_path(_session_dir->root_path()); if (!_writable || (_state_of_the_state & CannotSave)) { return 1; @@ -788,7 +770,7 @@ Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot } catch (Evoral::SMF::FileError& e) { error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg; } - } + } tree.set_root (&get_state()); @@ -802,11 +784,11 @@ Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot /* proper save: use statefile_suffix (.ardour in English) */ - xml_path /= legalize_for_path (snapshot_name) + statefile_suffix; + xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix); /* make a backup copy of the old file */ - if (sys::exists(xml_path) && !create_backup_file (xml_path)) { + if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) { // create_backup_file will log the error return -1; } @@ -814,26 +796,31 @@ Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot } else { /* pending save: use pending_suffix (.pending in English) */ - xml_path /= legalize_for_path (snapshot_name) + pending_suffix; + xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix); } - sys::path tmp_path(_session_dir->root_path()); + std::string tmp_path(_session_dir->root_path()); + tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix); - tmp_path /= legalize_for_path (snapshot_name) + temp_suffix; + // cerr << "actually writing state to " << xml_path << endl; - // cerr << "actually writing state to " << xml_path.to_string() << endl; - - if (!tree.write (tmp_path.to_string())) { - error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg; - sys::remove (tmp_path); + if (!tree.write (tmp_path)) { + error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg; + if (g_remove (tmp_path.c_str()) != 0) { + error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"), + tmp_path, g_strerror (errno)) << endmsg; + } return -1; } else { - if (::rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) { + if (::rename (tmp_path.c_str(), xml_path.c_str()) != 0) { error << string_compose (_("could not rename temporary session file %1 to %2"), - tmp_path.to_string(), xml_path.to_string()) << endmsg; - sys::remove (tmp_path); + tmp_path, xml_path) << endmsg; + if (g_remove (tmp_path.c_str()) != 0) { + error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"), + tmp_path, g_strerror (errno)) << endmsg; + } return -1; } } @@ -876,10 +863,10 @@ Session::load_state (string snapshot_name) /* check for leftover pending state from a crashed capture attempt */ - sys::path xmlpath(_session_dir->root_path()); - xmlpath /= legalize_for_path (snapshot_name) + pending_suffix; + std::string xmlpath(_session_dir->root_path()); + xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix); - if (sys::exists (xmlpath)) { + if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) { /* there is pending state from a crashed capture attempt */ @@ -890,15 +877,13 @@ Session::load_state (string snapshot_name) } if (!state_was_pending) { - xmlpath = _session_dir->root_path(); - xmlpath /= snapshot_name; + xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name); } - if (!sys::exists (xmlpath)) { - xmlpath = _session_dir->root_path(); - xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix; - if (!sys::exists (xmlpath)) { - error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg; + if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) { + xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix); + if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) { + error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg; return 1; } } @@ -909,8 +894,8 @@ Session::load_state (string snapshot_name) _writable = exists_and_writable (xmlpath); - if (!state_tree->read (xmlpath.to_string())) { - error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg; + if (!state_tree->read (xmlpath)) { + error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg; delete state_tree; state_tree = 0; return -1; @@ -919,7 +904,7 @@ Session::load_state (string snapshot_name) XMLNode& root (*state_tree->root()); if (root.name() != X_("Session")) { - error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg; + error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg; delete state_tree; state_tree = 0; return -1; @@ -931,39 +916,35 @@ Session::load_state (string snapshot_name) /* no version implies very old version of Ardour */ Stateful::loading_state_version = 1000; } else { - int major; - int minor; - int micro; - - sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ); - Stateful::loading_state_version = (major * 1000) + minor; + if (prop->value().find ('.') != string::npos) { + /* old school version format */ + if (prop->value()[0] == '2') { + Stateful::loading_state_version = 2000; + } else { + Stateful::loading_state_version = 3000; + } + } else { + Stateful::loading_state_version = atoi (prop->value()); + } } - if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) { - - sys::path backup_path(_session_dir->root_path()); + if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) { - backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix; - - // only create a backup once - if (sys::exists (backup_path)) { - return 0; - } + std::string backup_path(_session_dir->root_path()); + std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix); + backup_path = Glib::build_filename (backup_path, backup_filename); - info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"), - xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME) - << endmsg; + // only create a backup for a given statefile version once - try - { - sys::copy_file (xmlpath, backup_path); - } - catch(sys::filesystem_error& ex) - { - error << string_compose (_("Unable to make backup of state file %1 (%2)"), - xmlpath.to_string(), ex.what()) - << endmsg; - return -1; + if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) { + + info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"), + xmlpath, backup_path, PROGRAM_NAME) + << endmsg; + + if (!copy_file (xmlpath, backup_path)) {; + return -1; + } } } @@ -998,15 +979,14 @@ Session::get_template() } XMLNode& -Session::state(bool full_state) +Session::state (bool full_state) { XMLNode* node = new XMLNode("Session"); XMLNode* child; - // store libardour version, just in case char buf[16]; - snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version); - node->add_property("version", string(buf)); + snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION); + node->add_property("version", buf); /* store configuration settings */ @@ -1060,12 +1040,12 @@ Session::state(bool full_state) node->add_child_nocopy (config.get_variables ()); - node->add_child_nocopy (_metadata->get_state()); + node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state()); child = node->add_child ("Sources"); if (full_state) { - Glib::Mutex::Lock sl (source_lock); + Glib::Threads::Mutex::Lock sl (source_lock); for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) { @@ -1092,7 +1072,7 @@ Session::state(bool full_state) child = node->add_child ("Regions"); if (full_state) { - Glib::Mutex::Lock rl (region_lock); + Glib::Threads::Mutex::Lock rl (region_lock); const RegionFactory::RegionMap& region_map (RegionFactory::all_regions()); for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) { boost::shared_ptr r = i->second; @@ -1180,13 +1160,14 @@ Session::state(bool full_state) gain_child->add_child_nocopy (_click_gain->state (full_state)); } - if (full_state) { - XMLNode* ns_child = node->add_child ("NamedSelections"); - for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) { - if (full_state) { - ns_child->add_child_nocopy ((*i)->get_state()); - } - } + if (_ltc_input) { + XMLNode* ltc_input_child = node->add_child ("LTC-In"); + ltc_input_child->add_child_nocopy (_ltc_input->state (full_state)); + } + + if (_ltc_input) { + XMLNode* ltc_output_child = node->add_child ("LTC-Out"); + ltc_output_child->add_child_nocopy (_ltc_output->state (full_state)); } node->add_child_nocopy (_speakers->get_state()); @@ -1222,10 +1203,6 @@ Session::set_state (const XMLNode& node, int version) return -1; } - if ((prop = node.property ("version")) != 0) { - version = atoi (prop->value ()) * 1000; - } - if ((prop = node.property ("name")) != 0) { _name = prop->value (); } @@ -1242,7 +1219,7 @@ Session::set_state (const XMLNode& node, int version) } } - setup_raid_path(_session_dir->root_path().to_string()); + setup_raid_path(_session_dir->root_path()); if ((prop = node.property (X_("id-counter"))) != 0) { uint64_t x; @@ -1277,7 +1254,7 @@ Session::set_state (const XMLNode& node, int version) if (version >= 3000) { if ((child = find_named_node (node, "Metadata")) == 0) { warning << _("Session: XML state has no metadata section") << endmsg; - } else if (_metadata->set_state (*child, version)) { + } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) { goto out; } } @@ -1352,12 +1329,6 @@ Session::set_state (const XMLNode& node, int version) } } - if ((child = find_named_node (node, "NamedSelections")) != 0) { - if (load_named_selections (*child)) { - goto out; - } - } - if (version >= 3000) { if ((child = find_named_node (node, "Bundles")) == 0) { warning << _("Session: XML state has no bundles section") << endmsg; @@ -1427,10 +1398,12 @@ Session::set_state (const XMLNode& node, int version) } } - if ((child = find_named_node (node, "ControlProtocols")) != 0) { - ControlProtocolManager::instance().set_protocol_states (*child); + if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) { + ControlProtocolManager::instance().set_state (*child, version); } + update_have_rec_enabled_track (); + /* here beginneth the second phase ... */ StateReady (); /* EMIT SIGNAL */ @@ -1471,7 +1444,7 @@ Session::load_routes (const XMLNode& node, int version) new_routes.push_back (route); } - add_routes (new_routes, false, false); + add_routes (new_routes, false, false, false); return 0; } @@ -1686,7 +1659,7 @@ Session::load_nested_sources (const XMLNode& node) XMLProperty* prop = (*niter)->property (X_("id")); if (!prop) { - error << _("Nested source has no ID info in session state file! (ignored)") << endmsg; + error << _("Nested source has no ID info in session file! (ignored)") << endmsg; continue; } @@ -1918,7 +1891,7 @@ Session::get_sources_as_xml () { XMLNode* node = new XMLNode (X_("Sources")); - Glib::Mutex::Lock lm (source_lock); + Glib::Threads::Mutex::Lock lm (source_lock); for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) { node->add_child_nocopy (i->second->get_state()); @@ -1933,7 +1906,7 @@ Session::path_from_region_name (DataType type, string name, string identifier) char buf[PATH_MAX+1]; uint32_t n; SessionDirectory sdir(get_best_session_directory_for_new_source()); - sys::path source_dir = ((type == DataType::AUDIO) + std::string source_dir = ((type == DataType::AUDIO) ? sdir.sound_path() : sdir.midi_path()); string ext = native_header_format_extension (config.get_native_file_header_format(), type); @@ -1947,10 +1920,10 @@ Session::path_from_region_name (DataType type, string name, string identifier) n, ext.c_str()); } - sys::path source_path = source_dir / buf; + std::string source_path = Glib::build_filename (source_dir, buf); - if (!sys::exists (source_path)) { - return source_path.to_string(); + if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) { + return source_path; } } @@ -2048,49 +2021,54 @@ Session::save_template (string template_name) return -1; } - sys::path user_template_dir(user_template_directory()); + std::string user_template_dir(user_template_directory()); - try - { - sys::create_directories (user_template_dir); - } - catch(sys::filesystem_error& ex) - { + if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) { error << string_compose(_("Could not create templates directory \"%1\" (%2)"), - user_template_dir.to_string(), ex.what()) << endmsg; + user_template_dir, g_strerror (errno)) << endmsg; return -1; } tree.set_root (&get_template()); - sys::path template_dir_path(user_template_dir); + std::string template_dir_path(user_template_dir); /* directory to put the template in */ - template_dir_path /= template_name; - if (sys::exists (template_dir_path)) - { + template_dir_path = Glib::build_filename (template_dir_path, template_name); + + if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) { warning << string_compose(_("Template \"%1\" already exists - new version not created"), - template_dir_path.to_string()) << endmsg; + template_dir_path) << endmsg; return -1; } - sys::create_directories (template_dir_path); + if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) { + error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"), + template_dir_path, g_strerror (errno)) << endmsg; + return -1; + } /* file to write */ - sys::path template_file_path = template_dir_path; - template_file_path /= template_name + template_suffix; + std::string template_file_path(template_dir_path); + template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix); - if (!tree.write (template_file_path.to_string())) { + if (!tree.write (template_file_path)) { error << _("template not saved") << endmsg; return -1; } /* copy plugin state directory */ - sys::path template_plugin_state_path = template_dir_path; - template_plugin_state_path /= X_("plugins"); - sys::create_directories (template_plugin_state_path); - sys::copy_files (plugins_dir(), template_plugin_state_path); + std::string template_plugin_state_path(template_dir_path); + template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins")); + + if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) { + error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"), + template_plugin_state_path, g_strerror (errno)) << endmsg; + return -1; + } + + copy_files (plugins_dir(), template_plugin_state_path); return 0; } @@ -2098,23 +2076,48 @@ Session::save_template (string template_name) void Session::refresh_disk_space () { -#if HAVE_SYS_VFS_H - struct statfs statfsbuf; - vector::iterator i; - Glib::Mutex::Lock lm (space_lock); - double scale; +#if HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H + + Glib::Threads::Mutex::Lock lm (space_lock); /* get freespace on every FS that is part of the session path */ _total_free_4k_blocks = 0; + _total_free_4k_blocks_uncertain = false; - for (i = session_dirs.begin(); i != session_dirs.end(); ++i) { - statfs ((*i).path.c_str(), &statfsbuf); + for (vector::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) { + + struct statfs statfsbuf; + statfs (i->path.c_str(), &statfsbuf); - scale = statfsbuf.f_bsize/4096.0; + double const scale = statfsbuf.f_bsize / 4096.0; + + /* See if this filesystem is read-only */ + struct statvfs statvfsbuf; + statvfs (i->path.c_str(), &statvfsbuf); + + /* f_bavail can be 0 if it is undefined for whatever + filesystem we are looking at; Samba shares mounted + via GVFS are an example of this. + */ + if (statfsbuf.f_bavail == 0) { + /* block count unknown */ + i->blocks = 0; + i->blocks_unknown = true; + } else if (statvfsbuf.f_flag & ST_RDONLY) { + /* read-only filesystem */ + i->blocks = 0; + i->blocks_unknown = false; + } else { + /* read/write filesystem with known space */ + i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale); + i->blocks_unknown = false; + } - (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale); - _total_free_4k_blocks += (*i).blocks; + _total_free_4k_blocks += i->blocks; + if (i->blocks_unknown) { + _total_free_4k_blocks_uncertain = true; + } } #endif } @@ -2123,7 +2126,7 @@ string Session::get_best_session_directory_for_new_source () { vector::iterator i; - string result = _session_dir->root_path().to_string(); + string result = _session_dir->root_path(); /* handle common case without system calls */ @@ -2182,7 +2185,8 @@ Session::get_best_session_directory_for_new_source () } if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) { - if (create_session_directory ((*i).path)) { + SessionDirectory sdir(i->path); + if (sdir.create ()) { result = (*i).path; last_rr_session_dir = i; return result; @@ -2204,7 +2208,8 @@ Session::get_best_session_directory_for_new_source () sort (sorted.begin(), sorted.end(), cmp); for (i = sorted.begin(); i != sorted.end(); ++i) { - if (create_session_directory ((*i).path)) { + SessionDirectory sdir(i->path); + if (sdir.create ()) { result = (*i).path; last_rr_session_dir = i; return result; @@ -2215,39 +2220,6 @@ Session::get_best_session_directory_for_new_source () return result; } -int -Session::load_named_selections (const XMLNode& node) -{ - XMLNodeList nlist; - XMLNodeConstIterator niter; - NamedSelection *ns; - - nlist = node.children(); - - set_dirty(); - - for (niter = nlist.begin(); niter != nlist.end(); ++niter) { - - if ((ns = XMLNamedSelectionFactory (**niter)) == 0) { - error << _("Session: cannot create Named Selection from XML description.") << endmsg; - } - } - - return 0; -} - -NamedSelection * -Session::XMLNamedSelectionFactory (const XMLNode& node) -{ - try { - return new NamedSelection (*this, node); - } - - catch (failed_constructor& err) { - return 0; - } -} - string Session::automation_dir () const { @@ -2286,7 +2258,7 @@ Session::load_bundles (XMLNode const & node) } else if ((*niter)->name() == "OutputBundle") { add_bundle (boost::shared_ptr (new UserBundle (**niter, false))); } else { - error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg; + error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg; return -1; } } @@ -2613,7 +2585,7 @@ Session::find_all_sources_across_snapshots (set& result, bool exclude_th ripped = ripped.substr (0, ripped.length() - 1); } - state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true); + state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true); if (state_files == 0) { /* impossible! */ @@ -2739,7 +2711,7 @@ Session::cleanup_sources (CleanupReport& rep) ++nexti; SessionDirectory sdir ((*i).path); - audio_path += sdir.sound_path().to_string(); + audio_path += sdir.sound_path(); if (nexti != session_dirs.end()) { audio_path += ':'; @@ -2757,7 +2729,7 @@ Session::cleanup_sources (CleanupReport& rep) ++nexti; SessionDirectory sdir ((*i).path); - midi_path += sdir.midi_path().to_string(); + midi_path += sdir.midi_path(); if (nexti != session_dirs.end()) { midi_path += ':'; @@ -3043,7 +3015,7 @@ Session::add_controllable (boost::shared_ptr c) as part of the session. */ - Glib::Mutex::Lock lm (controllables_lock); + Glib::Threads::Mutex::Lock lm (controllables_lock); controllables.insert (c); } @@ -3052,11 +3024,11 @@ struct null_deleter { void operator()(void const *) const {} }; void Session::remove_controllable (Controllable* c) { - if (_state_of_the_state | Deletion) { + if (_state_of_the_state & Deletion) { return; } - Glib::Mutex::Lock lm (controllables_lock); + Glib::Threads::Mutex::Lock lm (controllables_lock); Controllables::iterator x = controllables.find (boost::shared_ptr(c, null_deleter())); @@ -3068,7 +3040,7 @@ Session::remove_controllable (Controllable* c) boost::shared_ptr Session::controllable_by_id (const PBD::ID& id) { - Glib::Mutex::Lock lm (controllables_lock); + Glib::Threads::Mutex::Lock lm (controllables_lock); for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) { if ((*i)->id() == id) { @@ -3192,7 +3164,7 @@ Session::controllable_by_descriptor (const ControllableDescriptor& desc) if (p) { boost::shared_ptr s = boost::dynamic_pointer_cast(p); boost::shared_ptr a = s->amp(); - + if (a) { c = s->amp()->gain_control(); } @@ -3241,16 +3213,11 @@ Session::save_history (string snapshot_name) const string history_filename = legalize_for_path (snapshot_name) + history_suffix; const string backup_filename = history_filename + backup_suffix; - const sys::path xml_path = _session_dir->root_path() / history_filename; - const sys::path backup_path = _session_dir->root_path() / backup_filename; + const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename)); + const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename)); - if (sys::exists (xml_path)) { - try - { - sys::rename (xml_path, backup_path); - } - catch (const sys::filesystem_error& err) - { + if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) { + if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) { error << _("could not backup old history file, current history not saved") << endmsg; return -1; } @@ -3262,19 +3229,17 @@ Session::save_history (string snapshot_name) tree.set_root (&_history.get_state (Config->get_saved_history_depth())); - if (!tree.write (xml_path.to_string())) + if (!tree.write (xml_path)) { - error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg; + error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg; - try - { - sys::remove (xml_path); - sys::rename (backup_path, xml_path); + if (g_remove (xml_path.c_str()) != 0) { + error << string_compose(_("Could not remove history file at path \"%1\" (%2)"), + xml_path, g_strerror (errno)) << endmsg; } - catch (const sys::filesystem_error& err) - { + if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) { error << string_compose (_("could not restore history file from backup %1 (%2)"), - backup_path.to_string(), err.what()) << endmsg; + backup_path, g_strerror (errno)) << endmsg; } return -1; @@ -3292,20 +3257,20 @@ Session::restore_history (string snapshot_name) snapshot_name = _current_snapshot_name; } - const string xml_filename = legalize_for_path (snapshot_name) + history_suffix; - const sys::path xml_path = _session_dir->root_path() / xml_filename; + const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix; + const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename)); - info << "Loading history from " << xml_path.to_string() << endmsg; + info << "Loading history from " << xml_path << endmsg; - if (!sys::exists (xml_path)) { + if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) { info << string_compose (_("%1: no history file \"%2\" for this session."), - _name, xml_path.to_string()) << endmsg; + _name, xml_path) << endmsg; return 1; } - if (!tree.read (xml_path.to_string())) { + if (!tree.read (xml_path)) { error << string_compose (_("Could not understand session history file \"%1\""), - xml_path.to_string()) << endmsg; + xml_path) << endmsg; return -1; } @@ -3434,7 +3399,7 @@ Session::config_changed (std::string p, bool ours) } else if (p == "edit-mode") { - Glib::Mutex::Lock lm (playlists->lock); + Glib::Threads::Mutex::Lock lm (playlists->lock); for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) { (*i)->set_edit_mode (Config->get_edit_mode ()); @@ -3547,16 +3512,32 @@ Session::config_changed (std::string p, bool ours) if (!config.get_external_sync()) { drop_sync_source (); } else { - switch_to_sync_source (config.get_sync_source()); + switch_to_sync_source (Config->get_sync_source()); } - } else if (p == "remote-model") { - set_remote_control_ids (); } else if (p == "denormal-model") { setup_fpu (); } else if (p == "history-depth") { set_history_depth (Config->get_history_depth()); + } else if (p == "remote-model") { + /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED + TO SET REMOTE ID'S + */ } else if (p == "sync-all-route-ordering") { - sync_order_keys ("session"); + + /* sync to editor order unless mixer is used for remote IDs + */ + + switch (Config->get_remote_model()) { + case UserOrdered: + sync_order_keys (EditorSort); + break; + case EditorOrdered: + sync_order_keys (EditorSort); + break; + case MixerOrdered: + sync_order_keys (MixerSort); + } + } else if (p == "initial-program-change") { if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) { @@ -3577,6 +3558,14 @@ Session::config_changed (std::string p, bool ours) last_timecode_valid = false; } else if (p == "playback-buffer-seconds") { AudioSource::allocate_working_buffers (frame_rate()); + } else if (p == "automation-thinning-factor") { + Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor()); + } else if (p == "ltc-source-port") { + reconnect_ltc_input (); + } else if (p == "ltc-sink-port") { + reconnect_ltc_output (); + } else if (p == "timecode-generator-offset") { + ltc_tx_parse_offset(); } set_dirty (); @@ -3639,9 +3628,9 @@ Session::setup_midi_machine_control () /* also handle MIDI SPP because its so common */ - mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this, _1, _2)); - mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this, _1, _2)); - mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this, _1, _2)); + mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this)); + mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this)); + mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this)); } boost::shared_ptr @@ -3668,7 +3657,7 @@ Session::rename (const std::string& new_name) string newstr; bool first = true; - string const old_sources_root = _session_dir->sources_root().to_string (); + string const old_sources_root = _session_dir->sources_root(); #define RENAME ::rename @@ -3797,7 +3786,7 @@ Session::rename (const std::string& new_name) boost::shared_ptr fs = boost::dynamic_pointer_cast (i->second); if (fs) { string p = fs->path (); - boost::replace_all (p, old_sources_root, _session_dir->sources_root().to_string ()); + boost::replace_all (p, old_sources_root, _session_dir->sources_root()); fs->set_path (p); } }