#include <stdint.h>
#include <algorithm>
-#include <fstream>
#include <string>
#include <cerrno>
#include <cstdio> /* snprintf(3) ... grrr */
#endif
#include <glib.h>
-#include <pbd/gstdio_compat.h>
+#include "pbd/gstdio_compat.h"
#include <glibmm.h>
#include <glibmm/threads.h>
MIDISceneChanger* msc;
_scene_changer = msc = new MIDISceneChanger (*this);
- msc->set_input_port (scene_input_port());
- msc->set_output_port (scene_out());
+ msc->set_input_port (boost::dynamic_pointer_cast<MidiPort>(scene_input_port()));
+ msc->set_output_port (boost::dynamic_pointer_cast<MidiPort>(scene_output_port()));
boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
- boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
+ boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_input_port())->set_timer (timer_func);
setup_midi_machine_control ();
send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
- MIDI::Name::MidiPatchManager::instance().set_session (this);
+ MIDI::Name::MidiPatchManager::instance().add_search_path (session_directory().midi_patch_path() );
ltc_tx_initialize();
/* initial program change will be delivered later; see ::config_changed() */
SessionSaveUnderway (); /* EMIT SIGNAL */
+ bool mark_as_clean = true;
+
+ if (!snapshot_name.empty() && !switch_to_snapshot) {
+ mark_as_clean = false;
+ }
+
if (template_only) {
+ mark_as_clean = false;
tree.set_root (&get_template());
} else {
tree.set_root (&get_state());
if (snapshot_name.empty()) {
snapshot_name = _current_snapshot_name;
} else if (switch_to_snapshot) {
- _current_snapshot_name = snapshot_name;
- }
+ set_snapshot_name (snapshot_name);
+ }
+
+ assert (!snapshot_name.empty());
if (!pending) {
save_history (snapshot_name);
- bool was_dirty = dirty();
+ if (mark_as_clean) {
+ bool was_dirty = dirty();
- _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
+ _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
- if (was_dirty) {
- DirtyChanged (); /* EMIT SIGNAL */
+ if (was_dirty) {
+ DirtyChanged (); /* EMIT SIGNAL */
+ }
}
StateSaved (snapshot_name); /* EMIT SIGNAL */
}
}
+ save_snapshot_name (snapshot_name);
+
return 0;
}
update_route_record_state ();
/* here beginneth the second phase ... */
+ set_snapshot_name (_current_snapshot_name);
StateReady (); /* EMIT SIGNAL */
}
int
-Session::save_template (string template_name)
+Session::save_template (string template_name, bool replace_existing)
{
if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
return -1;
}
if (!ARDOUR::Profile->get_trx()) {
- if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
+ if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
warning << string_compose(_("Template \"%1\" already exists - new version not created"),
template_dir_path) << endmsg;
- return -1;
+ return -2;
}
if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
_state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
+ /* this is mostly for windows which doesn't allow file
+ * renaming if the file is in use. But we don't special
+ * case it because we need to know if this causes
+ * problems, and the easiest way to notice that is to
+ * keep it in place for all platforms.
+ */
+
+ request_stop (false);
+ _butler->summon ();
+ _butler->wait_until_finished ();
+
/* consider deleting all unused playlists */
if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
+ /* this is mostly for windows which doesn't allow file
+ * renaming if the file is in use. But we don't special
+ * case it because we need to know if this causes
+ * problems, and the easiest way to notice that is to
+ * keep it in place for all platforms.
+ */
+
+ fs->close ();
+
if (!fs->is_stub()) {
if (playlists->source_use_count (fs) != 0) {
Session::setup_midi_machine_control ()
{
_mmc = new MIDI::MachineControl;
- _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
+
+ boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
+ boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
+
+ if (!async_out || !async_out) {
+ return;
+ }
+
+ /* XXXX argh, passing raw pointers back into libmidi++ */
+
+ MIDI::Port* mmc_in = async_in.get();
+ MIDI::Port* mmc_out = async_out.get();
+
+ _mmc->set_ports (mmc_in, mmc_out);
_mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
_mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
return _solo_cut_control;
}
+void
+Session::save_snapshot_name (const std::string & n)
+{
+ /* assure Stateful::_instant_xml is loaded
+ * add_instant_xml() only adds to existing data and defaults
+ * to use an empty Tree otherwise
+ */
+ instant_xml ("LastUsedSnapshot");
+
+ XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
+ last_used_snapshot->add_property ("name", string(n));
+ add_instant_xml (*last_used_snapshot, false);
+}
+
+void
+Session::set_snapshot_name (const std::string & n)
+{
+ _current_snapshot_name = n;
+ save_snapshot_name (n);
+}
+
int
Session::rename (const std::string& new_name)
{
}
}
- _current_snapshot_name = new_name;
+ set_snapshot_name (new_name);
_name = new_name;
set_dirty ();
return !(found_sr && found_data_format); // zero if they are both found
}
+std::string
+Session::get_snapshot_from_instant (const std::string& session_dir)
+{
+ std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
+
+ if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
+ return "";
+ }
+
+ XMLTree tree;
+ if (!tree.read (instant_xml_path)) {
+ return "";
+ }
+
+ const XMLProperty* prop;
+ XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
+ if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
+ return prop->value();
+ }
+
+ return "";
+}
+
typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
typedef std::map<std::string,SeveralFileSources> SourcePathMap;
_path = to_dir;
- _current_snapshot_name = saveas.new_name;
+ set_snapshot_name (saveas.new_name);
_name = saveas.new_name;
if (saveas.include_media && !saveas.copy_media) {
_path = old_path;
_name = old_name;
- _current_snapshot_name = old_snapshot;
+ set_snapshot_name (old_snapshot);
(*_session_dir) = old_sd;