X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fsession_state.cc;h=cae3b9720acf7233030d13206066a4617a45de63;hb=616f2a0370a10dcc7372a95f6bca9f5a45698980;hp=48e7f206e7b1836b494c3e66bea1c7c681f49e9c;hpb=bd4e498a1bc0565d011e03536b65496f7b1b7582;p=ardour.git diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 48e7f206e7..cae3b9720a 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,48 +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/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" @@ -107,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" @@ -121,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" @@ -146,7 +136,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) char buf[PATH_MAX+1]; if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) { - error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg; + error << string_compose(_("Could not use path %1 (%2)"), buf, strerror(errno)) << endmsg; destroy (); throw failed_constructor(); } @@ -165,7 +155,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) set_history_depth (Config->get_history_depth()); - _current_frame_rate = _engine.frame_rate (); + _current_frame_rate = _engine.sample_rate (); _nominal_frame_rate = _current_frame_rate; _base_frame_rate = _current_frame_rate; @@ -178,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; @@ -215,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; @@ -296,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)) { @@ -375,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; @@ -400,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 (); @@ -423,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); @@ -441,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; } } @@ -453,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; @@ -527,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); @@ -546,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; @@ -586,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); } @@ -634,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; } } @@ -664,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; } } @@ -684,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 @@ -700,14 +684,17 @@ 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 void Session::jack_session_event (jack_session_event_t * event) { - char timebuf[128]; + char timebuf[128], *tmp; time_t n; struct tm local_time; @@ -715,6 +702,8 @@ Session::jack_session_event (jack_session_event_t * event) localtime_r (&n, &local_time); strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time); + while ((tmp = strchr(timebuf, ':'))) { *tmp = '.'; } + if (event->type == JackSessionSaveTemplate) { if (save_template( timebuf )) { @@ -733,20 +722,29 @@ 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()); } } - jack_session_reply (_engine.jack(), event); + /* this won't be called if the port engine in use is not JACK, so we do + not have to worry about the type of PortEngine::private_handle() + */ + + jack_client_t* jack_client = (jack_client_t*) AudioEngine::instance()->port_engine().private_handle(); + + if (jack_client) { + jack_session_reply (jack_client, event); + } if (event->type == JackSessionSaveAndQuit) { Quit (); /* EMIT SIGNAL */ @@ -761,7 +759,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; @@ -782,7 +780,9 @@ 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; } - } + } + + SaveSession (); /* EMIT SIGNAL */ tree.set_root (&get_state()); @@ -796,11 +796,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; } @@ -808,26 +808,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()); - - tmp_path /= legalize_for_path (snapshot_name) + temp_suffix; + std::string tmp_path(_session_dir->root_path()); + tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix); - // cerr << "actually writing state to " << xml_path.to_string() << endl; + // cerr << "actually writing state to " << xml_path << 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; } } @@ -870,10 +875,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 */ @@ -884,15 +889,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; } } @@ -903,8 +906,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; @@ -913,7 +916,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; @@ -925,36 +928,31 @@ Session::load_state (string snapshot_name) /* no version implies very old version of Ardour */ Stateful::loading_state_version = 1000; } else { - if (prop->value().find ('.')) { - /* old school version format - lock at 3000 */ - Stateful::loading_state_version = 3000; + 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 /= string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix); + 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); // only create a backup for a given statefile version once - if (!sys::exists (backup_path)) { + 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.to_string(), backup_path.to_string(), PROGRAM_NAME) - << endmsg; + VersionMismatch (xmlpath, backup_path); - 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; + if (!copy_file (xmlpath, backup_path)) {; return -1; } } @@ -1057,7 +1055,7 @@ Session::state (bool full_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) { @@ -1084,13 +1082,17 @@ 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; /* only store regions not attached to playlists */ if (r->playlist() == 0) { - child->add_child_nocopy (r->state ()); + if (boost::dynamic_pointer_cast(r)) { + child->add_child_nocopy ((boost::dynamic_pointer_cast(r))->get_basic_state ()); + } else { + child->add_child_nocopy (r->get_state ()); + } } } @@ -1149,7 +1151,7 @@ Session::state (bool full_state) } for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) { - if (!(*i)->is_hidden()) { + if (!(*i)->is_auditioner()) { if (full_state) { child->add_child_nocopy ((*i)->get_state()); } else { @@ -1172,13 +1174,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()); @@ -1230,7 +1233,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; @@ -1340,12 +1343,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; @@ -1415,8 +1412,8 @@ 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 (); @@ -1676,7 +1673,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; } @@ -1908,7 +1905,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()); @@ -1923,7 +1920,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); @@ -1937,10 +1934,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; } } @@ -2038,49 +2035,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; } @@ -2088,23 +2090,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 __APPLE__ || (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); + + double const scale = statfsbuf.f_bsize / 4096.0; - scale = statfsbuf.f_bsize/4096.0; + /* See if this filesystem is read-only */ + struct statvfs statvfsbuf; + statvfs (i->path.c_str(), &statvfsbuf); - (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale); - _total_free_4k_blocks += (*i).blocks; + /* 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; + } + + _total_free_4k_blocks += i->blocks; + if (i->blocks_unknown) { + _total_free_4k_blocks_uncertain = true; + } } #endif } @@ -2113,7 +2140,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 */ @@ -2172,7 +2199,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; @@ -2194,7 +2222,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; @@ -2205,39 +2234,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 { @@ -2276,7 +2272,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; } } @@ -2603,7 +2599,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! */ @@ -2729,7 +2725,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 += ':'; @@ -2747,7 +2743,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 += ':'; @@ -3033,7 +3029,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); } @@ -3046,7 +3042,7 @@ Session::remove_controllable (Controllable* c) 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())); @@ -3058,7 +3054,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) { @@ -3182,7 +3178,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(); } @@ -3231,16 +3227,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; } @@ -3252,19 +3243,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; @@ -3282,20 +3271,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; } @@ -3424,7 +3413,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 ()); @@ -3537,16 +3526,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) { @@ -3569,6 +3574,12 @@ Session::config_changed (std::string p, bool ours) 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 (); @@ -3660,7 +3671,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 @@ -3789,7 +3800,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); } }