#include "ardour/filename_extensions.h"
#include "ardour/graph.h"
#include "ardour/location.h"
+#ifdef LV2_SUPPORT
#include "ardour/lv2_plugin.h"
+#endif
#include "ardour/midi_model.h"
#include "ardour/midi_patch_manager.h"
#include "ardour/midi_region.h"
/* Initial loop location, from absolute zero, length 10 seconds */
- Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
+ Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop, 0);
_locations->add (loc, true);
set_auto_loop_location (loc);
}
return state(false);
}
+typedef std::set<boost::shared_ptr<Playlist> > PlaylistSet;
+typedef std::set<boost::shared_ptr<Source> > SourceSet;
+
+bool
+Session::export_track_state (boost::shared_ptr<RouteList> rl, const string& path)
+{
+ if (Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
+ return false;
+ }
+ if (g_mkdir_with_parents (path.c_str(), 0755) != 0) {
+ return false;
+ }
+
+ PBD::Unwinder<std::string> uw (_template_state_dir, path);
+
+ LocaleGuard lg;
+ XMLNode* node = new XMLNode("TrackState"); // XXX
+ XMLNode* child;
+
+ PlaylistSet playlists; // SessionPlaylists
+ SourceSet sources;
+
+ // these will work with new_route_from_template()
+ // TODO: LV2 plugin-state-dir needs to be relative (on load?)
+ child = node->add_child ("Routes");
+ for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
+ if ((*i)->is_auditioner()) {
+ continue;
+ }
+ if ((*i)->is_master() || (*i)->is_monitor()) {
+ continue;
+ }
+ child->add_child_nocopy ((*i)->get_state());
+ boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (*i);
+ if (track) {
+ playlists.insert (track->playlist ());
+ }
+ }
+
+ // on load, Regions in the playlists need to resolve and map Source-IDs
+ // also playlist needs to be merged or created with new-name..
+ // ... and Diskstream in tracks adjusted to use the correct playlist
+ child = node->add_child ("Playlists"); // SessionPlaylists::add_state
+ for (PlaylistSet::const_iterator i = playlists.begin(); i != playlists.end(); ++i) {
+ child->add_child_nocopy ((*i)->get_state ());
+ boost::shared_ptr<RegionList> prl = (*i)->region_list ();
+ for (RegionList::const_iterator s = prl->begin(); s != prl->end(); ++s) {
+ const Region::SourceList& sl = (*s)->sources ();
+ for (Region::SourceList::const_iterator sli = sl.begin(); sli != sl.end(); ++sli) {
+ sources.insert (*sli);
+ }
+ }
+ }
+
+ child = node->add_child ("Sources");
+ for (SourceSet::const_iterator i = sources.begin(); i != sources.end(); ++i) {
+ child->add_child_nocopy ((*i)->get_state ());
+ boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (*i);
+ if (fs) {
+#ifdef PLATFORM_WINDOWS
+ fs->close ();
+#endif
+ string p = fs->path ();
+ PBD::copy_file (p, Glib::build_filename (path, Glib::path_get_basename (p)));
+ }
+ }
+
+ std::string sn = Glib::build_filename (path, "share.axml");
+
+ XMLTree tree;
+ tree.set_root (node);
+ return tree.write (sn.c_str());
+}
+
XMLNode&
Session::state (bool full_state)
{
Locations loc (*this);
// for a template, just create a new Locations, populate it
// with the default start and end, and get the state for that.
- Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
+ Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange, 0);
range->set (max_framepos, 0);
loc.add (range);
XMLNode& locations_state = loc.get_state();
} else if (p == "auto-loop") {
+ } else if (p == "session-monitoring") {
+
} else if (p == "auto-input") {
if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
/* auto-input only makes a difference if we're rolling */
- set_track_monitor_input_status (!config.get_auto_input());
+ set_track_monitor_input_status (!config.get_auto_input());
}
} else if (p == "punch-in") {
_mmc->enable_send (Config->get_send_mmc ());
- } else if (p == "midi-feedback") {
-
- session_midi_feedback = Config->get_midi_feedback();
-
} else if (p == "jack-time-master") {
engine().reset_timebase ();
}
int
-Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
+Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format, std::string& created_version)
{
bool found_sr = false;
bool found_data_format = false;
+ created_version = "";
if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
return -1;
if (node == NULL) {
xmlFreeParserCtxt(ctxt);
+ xmlFreeDoc (doc);
return -1;
}
node = node->children;
while (node != NULL) {
+ if (!strcmp((const char*) node->name, "ProgramVersion")) {
+ xmlChar* val = xmlGetProp (node, (const xmlChar*)"created-with");
+ if (val) {
+ created_version = string ((const char*)val);
+ }
+ xmlFree (val);
+ }
if (strcmp((const char*) node->name, "Config")) {
node = node->next;
continue;
}
xmlFreeParserCtxt(ctxt);
+ xmlFreeDoc (doc);
return !(found_sr && found_data_format); // zero if they are both found
}
/* write session file */
_path = to_dir;
g_mkdir_with_parents (externals_dir ().c_str (), 0755);
-
+#ifdef LV2_SUPPORT
PBD::Unwinder<bool> uw (LV2Plugin::force_state_save, true);
+#endif
save_state (name);
save_default_options ();