#include <unistd.h>
#include <sys/stat.h>
#include <climits>
-#include <fcntl.h>
-#include <poll.h>
#include <signal.h>
-#include <sys/mman.h>
#include <sys/time.h>
#ifdef HAVE_SYS_VFS_H
#include <sys/vfs.h>
-#else
-#include <sys/param.h>
-#include <sys/mount.h>
+#endif
+
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
#endif
#include <glib.h>
+#include <glib/gstdio.h>
#include <glibmm.h>
-#include <glibmm/thread.h>
+#include <glibmm/threads.h>
#include <boost/algorithm/string.hpp>
#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/pathexpand.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 "pbd/localtime_r.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"
#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"
#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"
throw failed_constructor();
}
- 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;
- destroy ();
- throw failed_constructor();
- }
-
- _path = string(buf);
+ _path = canonical_path (fullpath);
if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
_path += G_DIR_SEPARATOR;
_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;
_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;
no_questions_about_missing_files = false;
_speakers.reset (new Speakers);
_clicks_cleared = 0;
+ ignore_route_processor_changes = false;
+ _pre_export_mmc_enabled = false;
AudioDiskstream::allocate_working_buffers();
/* 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;
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)) {
_engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
_engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
+ midi_clock = new MidiClockTicker ();
+ midi_clock->set_session (this);
+
try {
when_engine_running ();
}
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
- MidiClockTicker::instance().set_session (this);
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;
SearchPath raid_search_path;
for (vector<space_and_path>::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 ();
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);
Session::path_is_within_session (const std::string& path)
{
for (vector<space_and_path>::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;
}
}
{
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;
return -1;
}
+ dir = externals_dir ();
+
+ if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+ error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+ return -1;
+ }
+
return 0;
}
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);
_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;
}
- /* Instantiate metadata */
-
- _metadata = new SessionMetadata ();
-
/* set initial start + end point */
_state_of_the_state = Clean;
if (bus_profile) {
RouteList rl;
- int control_id = 1;
ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
if (bus_profile->master_out_channels) {
// 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);
}
- r->set_remote_control_id (control_id++);
rl.push_back (r);
- if (Config->get_use_monitor_bus()) {
- boost::shared_ptr<Route> r (new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO));
- if (r->init ()) {
- return -1;
- }
-#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
- // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
-#endif
- {
- Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
- r->input()->ensure_io (count, false, this);
- r->output()->ensure_io (count, false, this);
- }
- r->set_remote_control_id (control_id);
-
- rl.push_back (r);
- }
-
} else {
/* prohibit auto-connect to master, because there isn't one */
bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
}
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.
Config->set_output_auto_connect (bus_profile->output_ac);
}
+ if (Config->get_use_monitor_bus() && bus_profile) {
+ add_monitor_section ();
+ }
+
save_state ("");
return 0;
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;
}
}
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;
}
}
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
}
// 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;
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 )) {
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());
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;
/* tell sources we're saving first, in case they write out to a new file
* which should be saved with the state rather than the old one */
for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
- i->second->session_saved();
- }
+ try {
+ i->second->session_saved();
+ } 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());
/* 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;
}
} 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) {
- 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);
+ if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
+ error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
+ tmp_path, xml_path, g_strerror(errno)) << 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;
}
}
/* 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 */
}
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;
}
}
_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;
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;
/* 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)) {
+
+ VersionMismatch (xmlpath, backup_path);
+
+ if (!copy_file (xmlpath, backup_path)) {;
+ return -1;
+ }
}
}
}
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 */
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) {
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<Region> 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<AudioRegion>(r)) {
+ child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
+ } else {
+ child->add_child_nocopy (r->get_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 {
}
if (_click_io) {
- child = node->add_child ("Click");
- child->add_child_nocopy (_click_io->state (full_state));
+ XMLNode* gain_child = node->add_child ("Click");
+ gain_child->add_child_nocopy (_click_io->state (full_state));
+ gain_child->add_child_nocopy (_click_gain->state (full_state));
}
- if (full_state) {
- child = node->add_child ("NamedSelections");
- for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
- if (full_state) {
- 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());
return -1;
}
- if ((prop = node.property ("version")) != 0) {
- version = atoi (prop->value ()) * 1000;
- }
-
if ((prop = node.property ("name")) != 0) {
_name = prop->value ();
}
}
}
- 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;
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;
}
}
}
}
- 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;
if ((child = find_named_node (node, "Click")) == 0) {
warning << _("Session: XML state has no click section") << endmsg;
} else if (_click_io) {
- _click_io->set_state (*child, version);
+ const XMLNodeList& children (child->children());
+ XMLNodeList::const_iterator i = children.begin();
+ _click_io->set_state (**i, version);
+ ++i;
+ if (i != children.end()) {
+ _click_gain->set_state (**i, 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 */
new_routes.push_back (route);
}
- add_routes (new_routes, false, false);
+ add_routes (new_routes, false, false, false);
return 0;
}
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;
}
{
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());
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);
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;
}
}
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;
}
void
Session::refresh_disk_space ()
{
-#if HAVE_SYS_VFS_H
- struct statfs statfsbuf;
- vector<space_and_path>::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<space_and_path>::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;
- (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
- _total_free_4k_blocks += (*i).blocks;
+ /* 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;
+ }
+
+ _total_free_4k_blocks += i->blocks;
+ if (i->blocks_unknown) {
+ _total_free_4k_blocks_uncertain = true;
+ }
}
#endif
}
Session::get_best_session_directory_for_new_source ()
{
vector<space_and_path>::iterator i;
- string result = _session_dir->root_path().to_string();
+ string result = _session_dir->root_path();
/* handle common case without system calls */
}
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;
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;
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
{
return Glib::build_filename (_path, "plugins");
}
+string
+Session::externals_dir () const
+{
+ return Glib::build_filename (_path, "externals");
+}
+
int
Session::load_bundles (XMLNode const & node)
{
} else if ((*niter)->name() == "OutputBundle") {
add_bundle (boost::shared_ptr<UserBundle> (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;
}
}
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! */
bool used;
string spath;
int ret = -1;
+ string tmppath1;
+ string tmppath2;
_state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
++nexti;
SessionDirectory sdir ((*i).path);
- audio_path += sdir.sound_path().to_string();
+ audio_path += sdir.sound_path();
if (nexti != session_dirs.end()) {
audio_path += ':';
++nexti;
SessionDirectory sdir ((*i).path);
- midi_path += sdir.midi_path().to_string();
+ midi_path += sdir.midi_path();
if (nexti != session_dirs.end()) {
midi_path += ':';
i = tmp;
}
- char tmppath1[PATH_MAX+1];
- char tmppath2[PATH_MAX+1];
-
if (candidates) {
for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
- if (realpath(spath.c_str(), tmppath1) == 0) {
- error << string_compose (_("Cannot expand path %1 (%2)"),
- spath, strerror (errno)) << endmsg;
- continue;
- }
-
- if (realpath((*i).c_str(), tmppath2) == 0) {
- error << string_compose (_("Cannot expand path %1 (%2)"),
- (*i), strerror (errno)) << endmsg;
- continue;
- }
+ tmppath1 = canonical_path (spath);
+ tmppath2 = canonical_path ((*i));
- if (strcmp(tmppath1, tmppath2) == 0) {
+ if (tmppath1 == tmppath2) {
used = true;
break;
}
string peakpath = peak_path (base);
if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
- if (::unlink (peakpath.c_str()) != 0) {
+ if (::g_unlink (peakpath.c_str()) != 0) {
error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
peakpath, _path, strerror (errno))
<< endmsg;
as part of the session.
*/
- Glib::Mutex::Lock lm (controllables_lock);
+ Glib::Threads::Mutex::Lock lm (controllables_lock);
controllables.insert (c);
}
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<Controllable>(c, null_deleter()));
boost::shared_ptr<Controllable>
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) {
if (p) {
boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
boost::shared_ptr<Amp> a = s->amp();
-
+
if (a) {
c = s->amp()->gain_control();
}
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;
}
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;
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;
}
} 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 ());
_clicking = false;
}
+ } else if (p == "click-gain") {
+
+ if (_click_gain) {
+ _click_gain->set_gain (Config->get_click_gain(), this);
+ }
+
} else if (p == "send-mtc") {
if (Config->get_send_mtc ()) {
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) {
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 ();
/* 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<Controllable>
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
boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (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);
}
}