#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 <glib/gstdio.h>
#include <glibmm.h>
-#include <glibmm/thread.h>
+#include <glibmm/threads.h>
#include <boost/algorithm/string.hpp>
#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/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/midi_region.h"
#include "ardour/midi_source.h"
#include "ardour/midi_track.h"
-#include "ardour/named_selection.h"
#include "ardour/pannable.h"
#include "ardour/playlist_factory.h"
#include "ardour/port.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;
_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;
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;
// 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);
}
// and delete it
if (g_remove (xml_path.c_str()) != 0) {
- error << string_compose(_("Could not remove state file at path \"%1\" (%2)"),
+ error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
xml_path, g_strerror (errno)) << endmsg;
}
}
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 )) {
}
}
+ SaveSession (); /* EMIT SIGNAL */
+
tree.set_root (&get_state());
if (snapshot_name.empty()) {
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 state file at path \"%1\" (%2)"),
+ 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.c_str(), xml_path.c_str()) != 0) {
- error << string_compose (_("could not rename temporary session file %1 to %2"),
- tmp_path, xml_path) << endmsg;
+ 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 state file at path \"%1\" (%2)"),
+ error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
tmp_path, g_strerror (errno)) << endmsg;
}
return -1;
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 state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
+ 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)) {
- error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
+ error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
delete state_tree;
state_tree = 0;
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;
+ VersionMismatch (xmlpath, backup_path);
if (!copy_file (xmlpath, backup_path)) {;
return -1;
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 {
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());
}
}
- 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, "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 ();
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());
void
Session::refresh_disk_space ()
{
-#if HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H
+#if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
- Glib::Mutex::Lock lm (space_lock);
+ Glib::Threads::Mutex::Lock lm (space_lock);
/* get freespace on every FS that is part of the session path */
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
{
} 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);
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;
- }
+ tmppath1 = canonical_path (spath);
+ tmppath2 = canonical_path ((*i));
- if (realpath((*i).c_str(), tmppath2) == 0) {
- error << string_compose (_("Cannot expand path %1 (%2)"),
- (*i), strerror (errno)) << endmsg;
- continue;
- }
-
- 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);
}
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) {
}
case ControllableDescriptor::RemoteControlID:
- cerr << "RID " << desc.rid() << endl;
r = route_by_remote_id (desc.rid());
break;
}
if (!r) {
- cerr << "no controllable with no route\n";
return c;
}
--send;
}
- cerr << "Look for send " << send << endl;
-
boost::shared_ptr<Processor> p = r->nth_send (send);
if (p) {
boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
boost::shared_ptr<Amp> a = s->amp();
- cerr << " looked for send " << send << " got " << s << " amp = " << a << endl;
-
if (a) {
c = s->amp()->gain_control();
}
} 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 ());
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 == "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 (UndefinedSort);
+
+ /* 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) {
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 ();