writable session patch, forward ported from 2.X
authorPaul Davis <paul@linuxaudiosystems.com>
Tue, 13 Oct 2009 20:43:28 +0000 (20:43 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 13 Oct 2009 20:43:28 +0000 (20:43 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@5770 d708f5d6-7413-0410-9779-e7cbd77b26cf

17 files changed:
gtk2_ardour/actions.cc
gtk2_ardour/actions.h
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui_dialogs.cc
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/editor_actions.cc
gtk2_ardour/mixer_strip.cc
gtk2_ardour/route_time_axis.cc
gtk2_ardour/route_ui.cc
libs/ardour/ardour/file_source.h
libs/ardour/ardour/session.h
libs/ardour/ardour/source.h
libs/ardour/audio_diskstream.cc
libs/ardour/file_source.cc
libs/ardour/session_state.cc
libs/ardour/source.cc
libs/ardour/track.cc

index 5e9c06747639c4fbebd36cb7531f6c819ca5c0ef..19a33ef177d43fa30c1c6bda470944fbaf6fd45b 100644 (file)
@@ -47,6 +47,7 @@ using namespace PBD;
 using namespace ARDOUR;
 
 vector<RefPtr<Gtk::Action> > ActionManager::session_sensitive_actions;
+vector<RefPtr<Gtk::Action> > ActionManager::write_sensitive_actions;
 vector<RefPtr<Gtk::Action> > ActionManager::region_list_selection_sensitive_actions;
 vector<RefPtr<Gtk::Action> > ActionManager::plugin_selection_sensitive_actions;
 vector<RefPtr<Gtk::Action> > ActionManager::region_selection_sensitive_actions;
index 3a20f4d5423d636c3617a4a1c76a7e942629fb33..35331fdac2ad1e36cd3def81d1b8d1b013c21610 100644 (file)
@@ -42,6 +42,7 @@ class ActionManager
        static void init ();
 
        static std::vector<Glib::RefPtr<Gtk::Action> > session_sensitive_actions;
+       static std::vector<Glib::RefPtr<Gtk::Action> > write_sensitive_actions;
        static std::vector<Glib::RefPtr<Gtk::Action> > region_list_selection_sensitive_actions;
        static std::vector<Glib::RefPtr<Gtk::Action> > plugin_selection_sensitive_actions;
 
index ea89b062c8632c582d8a7581fdac8d1b14be16dc..45f6191dd3ebb7e43e18b01b1d47ef6642d24194 100644 (file)
@@ -577,7 +577,7 @@ ARDOUR_UI::update_autosave ()
 {
        ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
 
-       if (session->dirty()) {
+       if (session && session->dirty()) {
                if (_autosave_connection.connected()) {
                        _autosave_connection.disconnect();
                }
@@ -2397,16 +2397,6 @@ ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_na
                goto out;
        }
 
-       /* if it already exists, we must have write access */
-
-       if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
-               MessageDialog msg (*editor, _("You do not have write access to this session.\n"
-                                             "This prevents the session from being loaded."));
-               pop_back_splash ();
-               msg.run ();
-               goto out;
-       }
-
        loading_message (_("Please wait while Ardour loads your session"));
 
        try {
index 91ff10d4730aa6c76c2ab0a69f56d3ffc88a5e5c..e816c3ce916f4fa3575010c96c1fe24ef6506220 100644 (file)
@@ -57,6 +57,7 @@ ARDOUR_UI::connect_to_session (Session *s)
        /* sensitize menu bar options that are now valid */
 
        ActionManager::set_sensitive (ActionManager::session_sensitive_actions, true);
+       ActionManager::set_sensitive (ActionManager::write_sensitive_actions, session->writable());
        
        if (session->locations()->num_range_markers()) {
                ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
index b827625db29a71ef92006ae90366e78cebb58239..d76ff437919f36212bb1e9edc021e09453ffb298 100644 (file)
@@ -89,8 +89,8 @@ ARDOUR_UI::install_actions ()
        /* menus + submenus that need action items */
 
        ActionManager::register_action (main_actions, X_("Session"), _("Session"));
-       ActionManager::register_action (main_actions, X_("Files"), _("Import/Export"));
-       ActionManager::register_action (main_actions, X_("Cleanup"), _("Cleanup"));
+       act = ActionManager::register_action (main_actions, X_("Cleanup"), _("Cleanup"));
+       ActionManager::write_sensitive_actions.push_back (act);
        ActionManager::register_action (main_actions, X_("Sync"), _("Sync"));
        ActionManager::register_action (main_actions, X_("TransportOptions"), _("Options"));
        ActionManager::register_action (main_actions, X_("Help"), _("Help"));
@@ -117,7 +117,7 @@ ARDOUR_UI::install_actions ()
        act = ActionManager::register_action (main_actions, X_("AddTrackBus"), _("Add Track/Bus..."),
                                              bind (mem_fun(*this, &ARDOUR_UI::add_route), (Gtk::Window*) 0));
        ActionManager::session_sensitive_actions.push_back (act);
-
+       ActionManager::write_sensitive_actions.push_back (act);
 
 #ifdef WITH_CMT
 
@@ -132,6 +132,7 @@ ARDOUR_UI::install_actions ()
 
        act = ActionManager::register_action (main_actions, X_("Snapshot"), _("Snapshot..."),  mem_fun(*this, &ARDOUR_UI::snapshot_session));
        ActionManager::session_sensitive_actions.push_back (act);
+       ActionManager::write_sensitive_actions.push_back (act);
 
        act = ActionManager::register_action (main_actions, X_("SaveTemplate"), _("Save Template..."),  mem_fun(*this, &ARDOUR_UI::save_template));
        ActionManager::session_sensitive_actions.push_back (act);
@@ -153,7 +154,10 @@ ARDOUR_UI::install_actions ()
 
        act = ActionManager::register_action (main_actions, X_("CleanupUnused"), _("Cleanup Unused Sources"),  mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::cleanup));
        ActionManager::session_sensitive_actions.push_back (act);
+       ActionManager::write_sensitive_actions.push_back (act);
+
        act = ActionManager::register_action (main_actions, X_("FlushWastebasket"), _("Flush Wastebasket"),  mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::flush_trash));
+       ActionManager::write_sensitive_actions.push_back (act);
        ActionManager::session_sensitive_actions.push_back (act);
 
        /* JACK actions for controlling ... JACK */
@@ -226,6 +230,7 @@ ARDOUR_UI::install_actions ()
        //ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (common_actions, X_("Save"), _("Save"),  bind (mem_fun(*this, &ARDOUR_UI::save_state), string("")));
        ActionManager::session_sensitive_actions.push_back (act);
+       ActionManager::write_sensitive_actions.push_back (act);
        act = ActionManager::register_action (common_actions, X_("RemoveLastCapture"), _("Remove Last Capture"), mem_fun(*this, &ARDOUR_UI::remove_last_capture));
        ActionManager::session_sensitive_actions.push_back (act);
 
@@ -277,8 +282,10 @@ ARDOUR_UI::install_actions ()
 
        act = ActionManager::register_action (transport_actions, X_("Record"), _("Enable Record"), bind (mem_fun(*this, &ARDOUR_UI::transport_record), false));
        ActionManager::session_sensitive_actions.push_back (act);
+       ActionManager::write_sensitive_actions.push_back (act);
        act = ActionManager::register_action (transport_actions, X_("record-roll"), _("Start Recording"), bind (mem_fun(*this, &ARDOUR_UI::transport_record), true));
        ActionManager::session_sensitive_actions.push_back (act);
+       ActionManager::write_sensitive_actions.push_back (act);
        ActionManager::transport_sensitive_actions.push_back (act);
        act = ActionManager::register_action (transport_actions, X_("Rewind"), _("Rewind"), bind (mem_fun(*this, &ARDOUR_UI::transport_rewind), 0));
        ActionManager::session_sensitive_actions.push_back (act);
index db99e3529edb8a2f51ed26f06fe77fcebecaca5b..04189421642175ce46573ba1e704a192855a108b 100644 (file)
@@ -847,10 +847,14 @@ Editor::register_actions ()
 
        act = ActionManager::register_action (editor_actions, X_("addExistingAudioFiles"), _("Import"), mem_fun (*this, &Editor::external_audio_dialog));
        ActionManager::session_sensitive_actions.push_back (act);
+       ActionManager::write_sensitive_actions.push_back (act);
+
        act = ActionManager::register_action (editor_actions, X_("addExternalAudioToRegionList"), _("Import to Region List"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsRegion));
        ActionManager::session_sensitive_actions.push_back (act);
-       
-       ActionManager::register_action (editor_actions, X_("importFromSession"), _("Import From Session"), mem_fun(*this, &Editor::session_import_dialog));
+       ActionManager::write_sensitive_actions.push_back (act);
+
+       act = ActionManager::register_action (editor_actions, X_("importFromSession"), _("Import From Session"), mem_fun(*this, &Editor::session_import_dialog));
+       ActionManager::write_sensitive_actions.push_back (act);
 
        ActionManager::register_toggle_action (editor_actions, X_("ToggleWaveformsWhileRecording"), _("Show Waveforms While Recording"), mem_fun (*this, &Editor::toggle_waveforms_while_recording));
 
index 5f7a89d90ace4b3c670ee8b377efbb790038fb97..4b3cb3649fa8fa5e0584863f4b1fe3562c6579d7 100644 (file)
@@ -369,6 +369,7 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
                connections.push_back (at->FreezeChange.connect (mem_fun(*this, &MixerStrip::map_frozen)));
 
                button_table.attach (*rec_enable_button, 0, 2, 2, 3);
+               rec_enable_button->set_sensitive (_session.writable());
                rec_enable_button->show();
 
        } else if (!is_track()) {
index 68ca7008c7091ef8e78cf050d7e8bf9aed908808..9a3a6a3124944ed0f8232a3fc82e18458b984336 100644 (file)
@@ -188,6 +188,7 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
                controls_table.attach (*rec_enable_button, 5, 6, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
                ARDOUR_UI::instance()->tooltips().set_tip(*rec_enable_button, _("Record"));
 
+               rec_enable_button->set_sensitive (_session.writable());
        }
 
        controls_hbox.pack_start(gm.get_level_meter(), false, false);
index 9a64ca8aa3ba3a2ceec9fcc4b80eb5583322a156..703857bc6b41131263d339b3f35ae49733e58e0a 100644 (file)
@@ -190,7 +190,7 @@ RouteUI::set_route (boost::shared_ptr<Route> rp)
        connections.push_back (_route->listen_changed.connect (mem_fun(*this, &RouteUI::listen_changed)));
        connections.push_back (_route->solo_isolated_changed.connect (mem_fun(*this, &RouteUI::solo_changed)));
   
-       if (is_track()) {
+       if (_session.writable() && is_track()) {
                boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
 
                connections.push_back (t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed)));
index fdf7473c63fb4c847d28e71709c3c1a2407a17f5..82a54094eff727e9c0eb2c7f38d4043fff22cc56 100644 (file)
@@ -68,7 +68,7 @@ protected:
        virtual int move_dependents_to_trash() { return 0; }
        
        bool removable () const;
-       
+
        Glib::ustring _path;
        Glib::ustring _take_id;
        bool          _file_is_new;
index 7da21274e1f0dab2e008ed7aa5366d838a545cd2..cdf65476740017a2298b2d98e8e017fb39d6392d 100644 (file)
@@ -248,7 +248,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
        std::string raid_path () const;
 
        void set_snap_name ();
-
+       
+       bool writable() const { return _writable; }
        void set_dirty ();
        void set_clean ();
        bool dirty() const { return _state_of_the_state & Dirty; }
@@ -1041,6 +1042,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
        float                   _meter_falloff;
        bool                    _non_soloed_outs_muted;
        uint32_t                _listen_cnt;
+       bool                    _writable;
 
        void set_worst_io_latencies ();
        void set_worst_io_latencies_x (IOChange, void *) {
index d6c68edf9036a19746ec8ddf1b4466ebb63fca36..a61af84ac84e92a080ea89839e4b8563299ad346 100644 (file)
@@ -79,7 +79,7 @@ class Source : public SessionObject, public boost::noncopyable
        int set_state (const XMLNode&);
        
        bool         destructive() const       { return (_flags & Destructive); }
-       bool         writable () const         { return _flags & Writable; }
+       bool         writable () const         { return (_flags & Writable); }
        virtual bool set_destructive (bool /*yn*/) { return false; }
        virtual bool length_mutable() const    { return false; }
        
@@ -128,6 +128,7 @@ class Source : public SessionObject, public boost::noncopyable
 
   private:
        uint32_t _in_use;
+       void fix_writable_flags ();
 };
 
 }
index 5c00f10f48fd4aee8c769c7fca071d5c8c712119..04f4173e4df244e29d3052e3ab9fbfea48228bb6 100644 (file)
@@ -2065,7 +2065,7 @@ AudioDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/)
        boost::shared_ptr<ChannelList> c = channels.reader();
        uint32_t n;
 
-       if (!recordable()) {
+       if (!_session.writable() || !recordable()) {
                return;
        }
        
index dc582a36ee0c2ba20b0de6ae7606b5b8b3a7a482..a8119170ded3fc6cebc4876134fbf91dcce69ac1 100644 (file)
@@ -67,7 +67,7 @@ FileSource::FileSource (Session& session, DataType type,
 
 FileSource::FileSource (Session& session, const XMLNode& node, bool /*must_exist*/)
        : Source(session, node)
-       , _file_is_new(false)
+       , _file_is_new (false)
 {
        _path = _name;
        _is_embedded = (_path.find(PATH_SEP) != string::npos);
index 32a4a50cb44f75279d6a9fc1eea64675e1c46abf..771e3b2bc61c297b1192e95961c9f502a25e49b7 100644 (file)
 #include "pbd/search_path.h"
 #include "pbd/stacktrace.h"
 
+#include "ardour/audio_diskstream.h"
+#include "ardour/audio_track.h"
 #include "ardour/audioengine.h"
-#include "ardour/configuration.h"
-#include "ardour/session.h"
-#include "ardour/session_directory.h"
-#include "ardour/session_utils.h"
-#include "ardour/session_state_utils.h"
-#include "ardour/session_metadata.h"
+#include "ardour/audiofilesource.h"
+#include "ardour/audioplaylist.h"
+#include "ardour/audioregion.h"
+#include "ardour/auditioner.h"
 #include "ardour/buffer.h"
-#include "ardour/audio_diskstream.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/utils.h"
-#include "ardour/audioplaylist.h"
+#include "ardour/midi_patch_manager.h"
 #include "ardour/midi_playlist.h"
-#include "ardour/smf_source.h"
-#include "ardour/audiofilesource.h"
-#include "ardour/silentfilesource.h"
-#include "ardour/sndfilesource.h"
+#include "ardour/midi_region.h"
 #include "ardour/midi_source.h"
-#include "ardour/sndfile_helpers.h"
-#include "ardour/auditioner.h"
-#include "ardour/io_processor.h"
-#include "ardour/send.h"
-#include "ardour/processor.h"
-#include "ardour/user_bundle.h"
-#include "ardour/slave.h"
-#include "ardour/tempo.h"
-#include "ardour/audio_track.h"
 #include "ardour/midi_track.h"
-#include "ardour/midi_patch_manager.h"
-#include "ardour/cycle_timer.h"
-#include "ardour/utils.h"
 #include "ardour/named_selection.h"
-#include "ardour/version.h"
-#include "ardour/location.h"
-#include "ardour/audioregion.h"
-#include "ardour/midi_region.h"
-#include "ardour/crossfade.h"
-#include "ardour/control_protocol_manager.h"
+#include "ardour/playlist_factory.h"
+#include "ardour/processor.h"
 #include "ardour/region_factory.h"
+#include "ardour/route_group.h"
+#include "ardour/send.h"
+#include "ardour/session.h"
+#include "ardour/session_directory.h"
+#include "ardour/session_metadata.h"
+#include "ardour/session_state_utils.h"
+#include "ardour/session_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/playlist_factory.h"
-#include "ardour/filename_extensions.h"
-#include "ardour/directory_names.h"
 #include "ardour/template_utils.h"
+#include "ardour/tempo.h"
 #include "ardour/ticker.h"
-#include "ardour/route_group.h"
+#include "ardour/user_bundle.h"
+#include "ardour/utils.h"
+#include "ardour/utils.h"
+#include "ardour/version.h"
 
 #include "control_protocol/control_protocol.h"
 
@@ -140,6 +140,14 @@ Session::first_stage_init (string fullpath, string snapshot_name)
                _path += '/';
        }
 
+       if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS) && ::access (_path.c_str(), W_OK)) {
+               cerr << "Session non-writable based on " << _path << endl;
+               _writable = false;
+       } else {
+               cerr << "Session writable based on " << _path << endl;
+               _writable = true;       
+       }
+
        /* these two are just provisional settings. set_state()
           will likely override them.
        */
@@ -665,7 +673,7 @@ Session::save_state (string snapshot_name, bool pending)
        XMLTree tree;
        sys::path xml_path(_session_dir->root_path());
 
-       if (_state_of_the_state & CannotSave) {
+       if (!_writable || (_state_of_the_state & CannotSave)) {
                return 1;
        }
 
@@ -790,6 +798,15 @@ Session::load_state (string snapshot_name)
 
        set_dirty();
 
+       /* writable() really reflects the whole folder, but if for any
+          reason the session state file can't be written to, still
+          make us unwritable.
+       */
+
+       if (::access (xmlpath.to_string().c_str(), W_OK) != 0) {
+               _writable = false;
+       }
+
        if (!state_tree->read (xmlpath.to_string())) {
                error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
                delete state_tree;
@@ -2795,7 +2812,10 @@ Session::controllable_by_id (const PBD::ID& id)
 void 
 Session::add_instant_xml (XMLNode& node, bool write_to_config)
 {
-       Stateful::add_instant_xml (node, _path);
+       if (_writable) {
+               Stateful::add_instant_xml (node, _path);
+       }
+
        if (write_to_config) {
                Config->add_instant_xml (node);
        }
@@ -2812,6 +2832,10 @@ Session::save_history (string snapshot_name)
 {
        XMLTree tree;
        
+       if (!_writable) {
+               return 0;
+       }                      
+
        if (snapshot_name.empty()) {
                snapshot_name = _current_snapshot_name;
        }
@@ -2833,7 +2857,6 @@ Session::save_history (string snapshot_name)
                }
        }
 
-
        if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
                return 0;
        }
index b052a5b1fa7a60a804de7d6de26986d442e1a175..d7002f2fe1ac1b269c95d9c4664f446e3d7b7e6c 100644 (file)
@@ -55,6 +55,7 @@ Source::Source (Session& s, DataType type, const string& name, Flag flags)
        _analysed = false;
        _timestamp = 0;
        _in_use = 0;
+       fix_writable_flags ();
 }
 
 Source::Source (Session& s, const XMLNode& node) 
@@ -70,6 +71,8 @@ Source::Source (Session& s, const XMLNode& node)
        if (set_state (node) || _type == DataType::NIL) {
                throw failed_constructor();
        }
+
+       fix_writable_flags ();
 }
 
 Source::~Source ()
@@ -77,6 +80,15 @@ Source::~Source ()
        notify_callbacks ();
 }
 
+
+void
+Source::fix_writable_flags ()
+{
+       if (!_session.writable()) {
+               _flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename));
+       }
+}
+
 XMLNode&
 Source::get_state ()
 {
index 23da42f86e156e88e525c68c93c2a457e85a9634..62639c8d3e8bbc155208ee4c453e031d0ee3b5bd 100644 (file)
@@ -170,6 +170,10 @@ Track::can_record()
 void
 Track::set_record_enable (bool yn, void *src)
 {
+       if (!_session.writable()) {
+               return;
+       }
+
        if (_freeze_record.state == Frozen) {
                return;
        }